Difference between revisions of "Sandpit"

From DikuMUD Wiki
Jump to navigation Jump to search
Line 1: Line 1:
==== VME basic zone writing manual ====
 
  
== Introduction ==
+
<HR WIDTH=90%>
=== Giving credit where credit is due! ===
 
  
The, basic zone writing manual, you are reading now, didn't just come flying out of this authors head.  In fact it is a conglomeration of several old texts which are no longer used.  I had first thought about quoting and giving credit to each person who had ever modified or created portions of the first documentation but because of the nature of the way they were built it was impossible to know who did what.  I therefore have decided to create a list here of everyone who has ever worked on or had a hand in the development of the basic zone writing documentation and references.  I will also give a short summary for each.
+
<CENTER>
 +
  <H1>DIL DOCUMENTATION</H1>
 +
  <H3>Version 4.0</H3>
 +
</CENTER>
  
I would also like to thank those listed below for their contribution to the development of one of the best mud servers on the internet today.
+
<HR WIDTH=90%>
  
;Original DIKU coding Team
+
<CENTER>
:
+
  <P><B>Current Version by: <A HREF="mailto:whistler@valhalla.com">Whistler@valhalla.com</A></B></P>
* Hans Henrik Staerfeldt
+
</CENTER>
* Sebastian Hammer
 
* Michael Seifert
 
* Katja Nyboe
 
* Tom Madsen
 
* Lars Balker Rasmussen
 
  
You should all know these people they are not only the original DIKU mud
+
<PRE>
developers but a few of them designed and developed the new VME
 
server. One or more of the previous mentioned people were the authors of
 
the following texts that have been swallowed up by this book.
 
* ''abilities.txt''
 
* ''guild.txt''
 
* ''monster.txt''
 
* ''objects.txt''
 
* ''rooms.txt''
 
* ''vmc.txt''
 
  
;Andrew Cowan
+
<h3>Index</h3><i>
: One of the original administrators of Valhalla mud and now the administrator of the mud connector. Andrew created the first zone tutorial, which was later included into the ''vmc.txt'' to clear up some things missing in the old ''vmc.txt''. Again my thanks go out to Andrew for his contributions not only to this document but to the growth of the DIL programming language.
+
<a href = "#making">Making a Program</a>
;Ryan Holliday
+
<a href = "#types">Data Types:</a>
: Made major updates to the ''tutorial.txt'' created by Andrew Cowan, which became version two of the tutorial.
+
  <a href = "#str">string</a>
;Peter Ryskin
+
  <a href = "#strl">stringlist</a>
: Wrote the original explanation of how to define exits.
+
  <a href = "#int">integer</a>
;John Clare
+
  <a href = "#intlist">integerlist</a>
: Made major updates to the ''tutorial.txt'' created by Andrew Cowan and updated by Ryan Holliday, which became version three of the tutorial.
+
  <a href = "#eptr">extraptr</a>
;Marc Bellemare
+
  <a href = "#uptr">unitptr</a>
: An editor and an author Marc combined and revised the ''tutorial'' and the ''vmc.txt'' into one document making it less Valhalla specific and more for any mud running the VME server.
+
  <a href = "#cptr">cmdptr</a>
;Jennifer Garuba
+
  <a href = "#zptr">zoneptr</a>
: Created the first document on how to create shop keepers. She also was one of the first builders to have the insite and to make it clear that a manual like this was needed.
+
<a href = "#messies">Messages:</a>
;Brian Spanton
+
  <a href = "#sfbcmd">SFB_CMD</a>
: Converted the original ''vmc.txt'' into HTMl, while at the same time fixing many inconsistencies and typos in it.
+
  <a href = "#sfbdone">SFB_DONE</a>
;Kathy Perry
+
  <a href = "#sfbtick">SFB_TICK</a>
: Wrote the original ''compiler howto'' to make it easier for new builders to compile their zone. She was also the first builder to open my eyes to the fact we needed a true manual on how to build.
+
  <a href = "#sfbcom">SFB_COM</a>
;Mark Pringle
+
  <a href = "#sfbdead">SFB_DEAD</a>
: Main editor, which spell checked and looked over my major grammer mistakes. I am sure he didn't catch them all but at least the ugly ones were caught.
+
  <a href = "#sfbmsg">SFB_MSG</a>
;Morgan Shafer
+
  <a href = "#sfbpre">SFB_PRE</a>
: Wrote the guild definition primer which explained teachers.
+
<a href = "#built_in">Built-In Variables</a>
 +
  <a href = "#cmdstr">cmdstr</a>
 +
  <a href = "#excmdstr">excmdstr</a>
 +
  <a href = "#excmdstr_case">excmdstr_case</a>
 +
  <a href = "#self">self</a>
 +
  <a href = "#activator">activator</a>
 +
  <a href = "#targ">target</a>
 +
  <a href = "#medium">medium</a>
 +
  <a href = "#power">power</a>
 +
  <a href = "#argu">argument</a>
 +
  <a href = "#hb">heartbeat</a>
 +
  <a href = "#null">null</a>
 +
  <a href = "#weather">weather</a>
 +
  <a href = "#mmmm">mud(day,month,..)</a>
 +
  <a href = "#bvrealtime">realtime</a>
 +
<a href = "#const">DIL Constructs:</a>
 +
  <a href = "#dcif">if(...)</a>
 +
  <a href = "#dcgoto">goto</a>
 +
  <a href = "#dcwhile">while(...)</a>
 +
  <a href = "#dcbreak">break</a>
 +
  <a href = "#dccont">continue</a>
 +
  <a href = "#ongoto">on .. goto ..</a>
 +
  <a href = "#forea">foreach(...)</a>
 +
<a href = "#assgn">Assignment</a>
 +
<a href = "#express">Expressions:</a>
 +
<a href = "#ops">Operators</a>
 +
  <a href = "#ein">in</a>
 +
  <a href = "#esins">string in string</a>
 +
  <a href = "#esinsl">string in stringlist</a>
 +
  <a href = "#esine">string in extraptr</a>
 +
<a href = "#funcs">Functions:</a>
 +
  <a href = "#fquit">quit</a>
 +
  <a href = "#fret">return</a>
 +
  <a href = "#fret2">return()</a>
 +
  <a href = "#fields">Fields:</a>
 +
  <a href = "#extra">extraptr</a>
 +
  <a href = "#unit">unitptr</a>
 +
  <a href = "#uobj">UNIT_ST_OBJ</a>
 +
  <a href = "#uroom">UNIT_ST_ROOM</a>
 +
  <a href = "#upcnpc">UNIT_ST_PC and UNIT_ST_NPC</a>
 +
  <a href = "#unpc">UNIT_ST_NPC</a>
 +
  <a href = "#upc">UNIT_ST_PC</a>
 +
<a href = "#built_func">Built-In Functions:</a>
 +
  <a href = "#bfasctime">asctime(...)</a>
 +
  <a href = "#bfatoi">atoi(...)</a>
 +
  <a href = "#bfcancarry">cancarry(...)</a>
 +
  <a href = "#bfcheckpassword">check_password(...)</a>
 +
  <a href = "#bfcomm">command(...)</a>
 +
  <a href = "#bfdelstr">delstr(...)</a>
 +
  <a href = "#bfdelunit">delunit(...)</a>
 +
  <a href = "#bfdd">dildestroy(...)</a>
 +
  <a href = "#bfdf">dilfind(...)</a>
 +
  <a href = "#bfeq">equipment(...)</a>
 +
  <a href = "#bffilesize">filesize(...)</a>
 +
  <a href = "#bffindr">findroom(...)</a>
 +
  <a href = "#bffindru">findrndunit(...)</a>
 +
  <a href = "#bffinds">findsymbolic(...)</a>
 +
  <a href = "#bffindu">findunit(...)</a>
 +
  <a href = "#bffits">fits(...)</a>
 +
  <a href = "#bfgcolor">getcolor(...)</a>
 +
  <a href = "#bfgword">getword(...)</a>
 +
  <a href = "#bfgwords">getwords(...)</a>
 +
  <a href = "#bfgghead">ghead(...)</a>
 +
  <a href = "#bfisaff">isaff(...)</a>
 +
    <a href = "#bfislight">islight(...)</a>
 +
  <a href = "#bfisplayer">isplayer(...)</a>
 +
  <a href = "#bfisset">isset(...)</a>
 +
  <a href = "#bfitoa">itoa(...)</a>
 +
  <a href = "#bfleft">left(...)</a>
 +
  <a href = "#bflen">length(...)</a>
 +
  <a href = "#bfload">load(...)</a>
 +
  <a href = "#bfloadstr">loadstr(...)</a>
 +
  <a href = "#bfmelee">meleeattack(...)</a>
 +
  <a href = "#bfmeleedamage">meleedamage(...)</a>
 +
  <a href = "#bfmid">mid(...)</a>
 +
  <a href = "#bfmonstr">moneystring(...)</a>
 +
  <a href = "#bfop">opponent(...)</a>
 +
  <a href = "#bforoll">openroll(...)</a>
 +
  <a href = "#bfpathto">pathto(...)</a>
 +
  <a href = "#bfpaychk">paycheck(...)</a>
 +
  <a href = "#bfpurse">purse(...)</a>
 +
  <a href = "#bfreplace">replace(...)</a>
 +
  <a href = "#bfrestore">restore(...)</a>
 +
  <a href = "#bfright">right(...)</a>
 +
  <a href = "#bfrnd">rnd(...)</a>
 +
  <a href = "#bfsavestr">savestr(...)</a>
 +
  <a href = "#bfsend_pre">send_pre(...)</a>
 +
  <a href = "#bfskill_name">skill_name(...)</a>
 +
  <a href = "#bfsplind">spellindex(...)</a>
 +
  <a href = "#bfsplinf">spellinfo(...)</a>
 +
  <a href = "#bfsplit">split(...)</a>
 +
  <a href = "#bfstrdir">strdir(...)</a>
 +
  <a href = "#bfstrcmp">strcmp(...)</a>
 +
  <a href = "#bfstrcmp">strncmp(...)</a>
 +
  <a href = "#bftextformat">textformat(...)</a>
 +
  <a href = "#bftolower">tolower(...)</a>
 +
  <a href = "#bftoupper">toupper(...)</a>
 +
  <a href = "#bftranmon">transfermoney(...)</a>
 +
  <a href = "#bfvis">visible(...)</a>
 +
  <a href = "#bfweapon_name">weapon_name(...)</a>
 +
    <a href = "#bfweapon_info">weapon_info(...)</a>
 +
<a href = "#biproc">Built-In Procedures:</a>
 +
  <a href = "#bpacc_mod">acc_modify(...)</a>
 +
  <a href = "#bpact">act(...)</a>
 +
  <a href = "#bpaddaff">addaff(...)</a>
 +
  <a href = "#bpaddcolor">addcolor(...)</a>
 +
  <a href = "#bpaddeq">addequip(...)</a>
 +
  <a href = "#bpaddex">addextra(...)</a>
 +
  <a href = "#bpadds">addstring(...)</a>
 +
  <a href = "#bpatt_s">attack_spell(...)</a>
 +
  <a href = "#bpbeginedit">beginedit(...)</a>
 +
  <a href = "#bpblock">block</a>
 +
  <a href = "#bpcast_s">cast_spell(...)</a>
 +
  <a href = "#bpchangecolor">changecolor(...)</a>
 +
  <a href = "#bpchngs">change_speed(...)</a>
 +
  <a href = "#bpclear">clear(...)</a>
 +
  <a href = "#bpdc">dilcopy(...)</a>
 +
  <a href = "#bpdelcolor">delcolor(...)</a>
 +
  <a href = "#bpdp">delete_player(...)</a>
 +
  <a href = "#bpdest">destroy(...)</a>
 +
  <a href = "#bpexec">exec(...)</a>
 +
  <a href = "#bpexp">experience(...)</a>
 +
  <a href = "#bpflog">flog(...)</a>
 +
  <a href = "#bpfol">follow(...)</a>
 +
  <a href = "#bpgamestate">gamestate(...)</a>
 +
  <a href = "#bpinsert">insert(...)</a>
 +
  <a href = "#bpinterr">interrupt(...)</a>
 +
    <a href = "#bpkilledit">killedit</a>
 +
  <a href = "#bplink">link(...)</a>
 +
  <a href = "#bplog">log(...)</a>
 +
  <a href = "#bplogcrime">logcrime(...)</a>
 +
  <a href = "#bpnopri">nopriority</a>
 +
  <a href = "#bpona">on_activation(...)</a>
 +
  <a href = "#bppagestring">pagestring(...)</a>
 +
  <a href = "#bpp_u">position_update(...)</a>
 +
  <a href = "#bppri">priority</a>
 +
  <a href = "#bpreboot">reboot</a>
 +
  <a href = "#bpremove">remove(...)</a>
 +
  <a href = "#bpresetlevel">reset_level(...)</a>
 +
  <a href = "#bpresetvlevel">reset_vlevel(...)</a>
 +
  <a href = "#bpresetrace">reset_race(...)</a>
 +
  <a href = "#bpsec">secure(...)</a>
 +
  <a href = "#bpsend">send(...)</a>
 +
  <a href = "#bpsendall">sendtoall(...)</a>
 +
  <a href = "#bpsendalld">sendtoalldil(...)</a>
 +
  <a href = "#bpsendt">sendtext(...)</a>
 +
  <a href = "#bpsendto">sendto(...)</a>
 +
  <a href = "#bpsend_done">send_done(...)</a>
 +
  <a href = "#bpset">set(...)</a>
 +
  <a href = "#bpsetbright">setbright(...)</a>
 +
  <a href = "#bpsetfight">set_fighting(...)</a>
 +
  <a href = "#bpsetweight">setweight(...)</a>
 +
  <a href = "#bpsetpassword">set_password(...)</a>
 +
  <a href = "#bpstore">store(...)</a>
 +
  <a href = "#bpstopfighting">stop_fighting(...)</a>
 +
  <a href = "#bpsubaff">subaff(...)</a>
 +
  <a href = "#bpsubex">subextra(...)</a>
 +
  <a href = "#bpsubs">substring(...)</a>
 +
  <a href = "#bpuneq">unequip(...)</a>
 +
  <a href = "#bfunitdir">unitdir(...)</a>
 +
  <a href = "#bpunsec">unsecure(...)</a>
 +
  <a href = "#bpunset">unset(...)</a>
 +
  <a href = "#bpwait">wait(...)</a>
 +
  <a href = "#bpwalkto">walkto(...)</a>
 +
<a href = "#note">Ending Notes</a>
 +
</i>
 +
<hr><center>
 +
  This documentation is designed for people with some experience in programming.
 +
Experience in C is recommended, but PASCAL or BASIC in some form or other
 +
will do just fine too.
  
=== Who should read this book? ===
+
  DIL is a simple programming language with fixed types reflecting the types
 +
used in Valhalla Mud. The language gives you almost endless possibilities in
 +
designing your adventures and quests. It gives you the control you need for
 +
making the game interesting and intelligent.
 +
</center>
 +
<IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%"><br><a name="making">
  
This book was designed to be read by anyone who is thinking of writing
+
<h3><b>Making a program:</b></h3>
areas for a VME server. If you have wrote for other mud servers you will still
+
<P>
need to at least skim every chapter because the VME is like no other mud engine
+
  You define your DIL programs within your zone file. Each program you make is a
and has some very interesting differences.
+
*template*. Such a template must be equipped with a unique name (for that zone).
 +
Templates can either be defined in a new %dil section, just below the %zone
 +
section in the zone file, or directly attached to units defined in your zonefile.</P><P>
  
=== What does this book cover? ===
+
  If you define your DIL templates inside a unit definition, that unit is
 +
automatically assigned a program using that template. If you want to use an
 +
already designed template, either in your own, or another zone, you use a
 +
special function named "dilcopy", that takes the name of a template, and any
 +
optional parameters in parenthesis. The parameters of a template called with
 +
'dilcopy' may only be of types integer, strings and stringlists.
 +
</P><P>
 +
<b>Example:</b>
  
The topics covered in this book are everything to do with writing an
+
dilcopy myfunc@myzone("say Hello, my friend!", 1, CMD_SAY, {"name1", "name2"});
area for the VME server.  While we do cover using DIL functions to make your
 
monsters, Rooms, and objects better and smarter we do not cover how to write the
 
DIL functions covered in the DIL manual.  The following
 
are topics covered by this book.
 
* compiling and debugging
 
* Macros using the CPP
 
* Overall Zone structure
 
* Writing rooms
 
* Writing Objects
 
* Writing Monsters
 
* Doing the resets
 
== General compiler information ==
 
  
In order to get your zone onto a valhalla Mud Engine (VME) server you must convert your zone from readable
+
  DIL templates can always be reused. In fact, with version 2.0 of DIL, programs
english text to binary form the server can understand. The way
+
are no longer saved with equipment, but only a symbolic reference is used. That
you do this is with a compiler. No don't freak out you don't have
+
way, if you make a change in your zone, ALL units using that program are changed.
to be a skilled programmer to use a compiler.  The only thing you
+
This however requires you keep the name. Upon loading, if a template is not
have to do is format your rooms, objects, and Non-player characters
+
found, the program is halted and rendered useless until such a reference can be
(NPC) in a form which the compiler can understand. The great thing
+
found during loading.
about the VME is you can do all your zone writing in your favorite
+
</P><P>
editor with out having to log on to code.  For those of you who have
 
coded for other mud servers and are used to coding online this may
 
be a new experience to you but you will find you can plan out
 
better and more well designed areas offline than you can on
 
line.
 
  
<blockquote style="background-color: #E8E8E8; font-style: italic; ">
+
<i>Technical note:</i>
In the future the VME coding team is thinking of adding
+
</P><P>
an online coding module for those mud administrators that can not
+
  When you use several 'dilcopy' in your zonefile, only one instance is present
live with out it.  If you are one of these make sure you write
+
game-time, thus saving tremendous amounts of memory. It is similar to a shared
whistler@valhalla.com and express your desires so
+
library, in which code is shared  but variables are not.
you can be counted.
 
</blockquote>
 
  
This chapter will mainly cover the Valhalla Mud Compiler (VMC), how it works, and
+
You may use your templates to define both procedure and functions for your other
the Valhalla Mud pre processor (VMC -p) works. We will also throw in some debugging
+
templates to call.
hints but debugging will be covered more as you begin creating parts of
 
your areas in the following chapters.
 
=== The compiler ===
 
  
''VMC'' is the Valhalla Mud Engine Compiler.
+
A template is defined by beginning with 'dilbegin' and ending with 'dilend'.
for VME servers.  A compiler takes a source file or better described
+
Inside the template your program section is defined, marked by the keyword 'code',
as your areas input file and converts it to a binary file the
+
followed by the program itself;
server can then load and use online.  In the VME we call areas
 
you build 'zones', therefore the source file for a zone has the
 
extension 'zon'.  In order to make this more clear we will start
 
with our first example.
 
  
Lets say you were making a Zone of dragons.  You may want to
+
<i>dilbegin myprogram();
call the file something resembling its contents like,
+
var
''dragon.zon''.  Notice we have appended the
+
  i : integer;
'.zon' extension.  The compiler requires all zones to end in '.zon'
+
  j : integer;
in order for it to know this is a zone source file.
 
  
Now lets say we have completed writing our first zone and want
+
code
to compile it.  The command is simply:
+
{
'''VMC> dragon.zon'''
+
  heartbeat:=PULSE_SEC*5;
If the zone compiles correctly it will indicate success by printing
+
  :start:
a message to the screen and outputting two files both with the same
+
  exec("say Hello world", self);
root name as the original zone source file but with different
+
  pause;
extensions.  In this case there would be the following:
+
  goto start;
 +
}
 +
dilend</i>
  
;''dragon.data''
+
  This simple template does nothing but making its owner say 'Hello world' once
: The file holding the binary version of the zone
+
every 5 seconds. The template is called 'myprogram' and takes no arguments. The
;''dragon.reset''
+
'pause' command waits for the program to receive a timer message, whose interval
: The file containing the reset information for the zone.
+
is set by the 'inline' variable 'heartbeat'. The 'self' variable is a unitptr
 +
referring to the unit owning the DIL program. Other inline variables will be
 +
explained later.
  
If the zone doesn't compile correctly and you have errors it
+
  For a DIL program to work, it must be part of a *unit*: a room, player, non-player
will print a list of the errors and the location where they can be
+
or object. The program uses *messages* to operateYour program gets activated
found so you can fix themThe debugging process will be explained
+
when it receives a message that some command is being executed, or a certain amount
more as you learn how to create rooms, monsters, and objects.
+
of time has passed. You decide yourself in the program, what to wait for, before
 +
the program continues executing.
  
=== The VMC pre-processor ===
+
  Supposing you want your program to contain variables, you have to put them in a
 +
section before the 'code' section marked 'var'. The variables are declared by
 +
their type and their name, separated by a ':' and ended by a ';'
  
The VMC Pre-Processor (VMC -p) can be thought of as a powerful
+
  For an example, see the program above. Variables of type 'string', 'stringlist'
search and replace tool used by the compiler before it
+
and 'integer' are saved, if the unit the program is attached to is saved with
converts the zone to its binary form.  This tool gives you the
+
player inventory. Variables of type 'unitpr' and 'extraptr' are 'volatile'. This
builder the ability to add comments, create short hand expressions
+
means that they are cleared whenever there is a chance that their contents may
for repeated items, include other files in your zone, and even to do
+
have been rendered non usable.  This ensures that you do not have any 'loose'
some minor calculations when necessary.
+
pointers. However it is possible to 'secure' the contents of a 'unitptr' type
 +
variable of a unit located in your local environment (the units directly 'visible'
 +
to the unit who owns the DIL program) (see the secure / unsecure functions).
  
<blockquote style="background-color: #E8E8E8; font-style: italic; "> If you have coded in C or c++ before the Pre Processor the VMC uses is no different and you can skip this section. </blockquote>
+
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name="types">
==== Commenting your zone ====
+
<h3><b>Data Types:</b></h3>
  
The practice of adding comments to your zone is a good thing
+
DIL supports a fixed set of types you can use and manipulate. Through these, you
to get into so the administrators and other builders can help
+
can get and manipulate information about almost anything in the game. The types
you with your zone and know what you were trying to do if there are
+
are listed below:
problems. Comments aren't as important when writing the zone as
 
they will be when you start writing your own special DIL functions
 
but it is important to know how comments work and that you can use
 
them if you need to.  A comment is a block of text the compiler
 
will never see and is there only for you and who ever reads the
 
file. In order to make it so the compiler will not see the block of
 
text you must surround it by a set of symbols that tell the CPP to
 
strip it out before passing the zone on to the compiler.  These
 
symbols are the '/*' and the '*/' symbols or the '//' symbols together in front of a single line.
 
  
In order to best explain how comments work we will give you a some
+
<hr><a name="str">
what strange example.  First we will start by showing you a very basic
+
<b>String:</b>
line you will see time and time again in rooms.
 
<nowiki>
 
title "this is a title"</nowiki>
 
This is a title it will show up in everything from rooms, to objects
 
and even NPCs.  Now lets see what a commented line would look like.
 
<nowiki>
 
//I am going to make a title now
 
title /* I put the keyword
 
first*/ "this is a title/*then the title*/</nowiki>
 
This of course is very ugly but the point is not to be pretty it is
 
to show you both the first way and the second way will look
 
exactly the same to the compiler because all comments are removed
 
before the compiler ever gets it.  A better use of a comment in a
 
zone however would be something like this:
 
<nowiki>
 
/*
 
The following ten rooms are the vineyards,
 
there are 97 rooms in the zone.
 
*/
 
  
//Zone first created 1994</nowiki>
+
  A string is some text. They are used for a lot of things such as command
You will find comments will make coding large zones much easier
+
arguments, room descriptions etc. String variables are automatically resized and
because you can add text meant just for the builders
+
allocated when you assign them, so you do not have to worry about the string
eyes.
+
length nor allocation in your DIL programs. Strings may be compared either with
 +
'==' (equal to),
 +
'!=' (not equal),
 +
'<=' (less than or equal to),
 +
'>=' (greater than or equal to) 
 +
'<' (less than),
 +
'>' (greater than.
  
<blockquote style="background-color: #E8E8E8; font-style: italic; ">You will have to decide if you want a multi-line comment or a single line comment and use the '//' or the '/**/' respectivelyThe rule of thumb is if the comment is longer than 1 line it is easier to put the '/**/' around the comment than to comment each individual line.</blockquote>
+
  Static strings are defined just as in the rest of the zone, within double
==== Macros and what they can do for you ====
+
quotations.  Strings may be searched easily with the 'in' operatorVariables
 +
of type string are saved with DIL programs, if attached to a saved unit.
  
When making a zone you will find there are things you use more
+
<b>Example:</b>
than once.  In fact you may find things you want others to use or
 
things you want to use in multiple zones.  Its true you could block
 
and copy and stick them everywhere. in fact that is what I did when
 
I first started building.  I soon found my zone file was
 
extremely large and hard to upkeep.  With a few minor changes and a
 
lot of deleting I used short hand or better known in the world of coding
 
as macros to make my zone readable.
 
  
Lets say you had some flags you were going to set in
+
  "This is a static string"
fifty rooms and you knew they would all be the same.  You could type
 
the following line 50 times.
 
<nowiki>
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_CAN_BURY}</nowiki>
 
With the macros however you could make this much easier by just doing
 
the following at the beginning of your zone.
 
<nowiki>
 
#define DIRTFLOOR flags {UNIT_FL_NO_WEATHER, UNIT_FL_CAN_BURY}</nowiki>
 
Then where ever you want the flags you just type DIRTFLOOR.  You are
 
probably thinking, yeah big deal I can do that with block and copy.
 
True but there is another benefit to this.  Lets say later you
 
wanted to also make these 50 rooms no teleport.  All you would have
 
to change is the define like this:
 
<nowiki>
 
#define DIRTFLOOR flags {UNIT_FL_NO_WEATHER,UNIT_FL_CAN_BURY,UNIT_FL_NO_TELEPORT}</nowiki>
 
Now when you recompile all 50 rooms are changed and you didn't even
 
have to do a search and replace.
 
  
You can also make macros that take arguments.  The ability to
+
Strings may also be added to each other, in an expression.
take arguments is where macros take a leap and a bound out in front
 
of your favorite editor to allow you to do things you can not do easily
 
with search and replace.  Lets say you have an exit descr you
 
want to use in 50 swamp rooms because heck everything looks the same
 
in a swamp when you look one direction to the next.
 
<nowiki>
 
east to swamp1 descr
 
"You see the swamp stretch out for miles";</nowiki>
 
This could be made into a macro like:
 
<nowiki>
 
#define sexit(direction, place) direction to place descr \
 
"You see the swamp stretch out for miles.";</nowiki>
 
Then all you need to use it is:
 
<nowiki>
 
SEXIT(east,swamp1)
 
SEXIT(north,swamp2)
 
SEXIT(south,swamp3)</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">There is no space between 'SEXIT' and '(' that is important because the CPP sees 'SEXIT(' and 'SEXIT (' as two different things.  It is also important to notice all defines must start at the beginning of the line and be either one line long or have a '\' telling the Pre Processor that it should continue with the next line as if it was this line.</blockquote>
 
  
You can also combine macros together so you have a set
+
<b>Example:</b>
of macros like:
 
<nowiki>
 
#define DIRTFLOOR flags {UNIT_FL_NO_WEATHER,UNIT_FL_CAN_BURY,UNIT_FL_NO_TELEPORT}
 
#define DIRTSECT  movement SECT_INSIDE \
 
DIRTFLOOR</nowiki>
 
You may have noticed I capitalize all macros.  This is not a must but it is
 
suggested so you can easily tell what is a macro and what is not.
 
==== Including other files in your zone ====
 
  
Another function of the VMC Pre Processor,
+
  "say "+itoa(42)+" is the answer!"
'#include', allows you to include other files  in
 
your zone file.  The VME comes with some basic include files
 
you can use the macros out of and use as examples on how to make
 
your own include files.  These files are the
 
''composed.h'',, ''vme.h'',
 
''values.h'', ''base.h'',
 
''liquid.h'', and ''wmacros.h''.
 
Including ''composed.h'' will include all the rest
 
of
 
the include files into your zone because it has include statements
 
that use all the others.
 
  
<blockquote style="background-color: #E8E8E8; font-style: italic; ">You will want to include the files at the beginning of your zone file because all defines you use must be defined before you use them.</blockquote>
+
<b>Example:</b>
==== Doing minor calculations ====
 
  
You can also do minor calculations in a macro.  Lets say you
+
  if (self.name == self.names.[1]) ...
wanted to make it so the higher level an NPC was the heavier he
+
 
was and the taller he was.  This would be simple with a macro.
+
  Elements of the string can also be accessed by referencing them by their position.
<nowiki>
+
 
#define MLEVEL(lvl) \
+
  <b>Example</b>
level lvl \
+
  if (str.[3]==f])
height lvl+72 \
+
  {
weight lvl*9</nowiki>
+
  exec ("say The 4th element is a F.",self);
This macro would increase the height and weight depending on what
+
  }
level you made the NPC pretty simple.  There is much more a macro
+
 
can do for you but the Pre Processor and all its uses go far beyond the scope
+
  <B>Note</b>
of this manual.  If you are really interested in all the neat things
+
  Currently you can only access the single elements of a string you can not set
it can do type the following command at the '$' prompt on your
+
them.  In the future this will be possible.  You can still accomplish this by
Linux box.
+
copying one string to the other one element at a time and changing any that you
'''man cpp'''
+
want something like this.
The C-Pre Processor is what the VMC Pre Processor is based on and most
+
 
if not all functions of the CPP work in the VMC.
+
<b>Example</b>
== Zone source file ==
+
i:=0;
 
+
ln:=length (str);
In this chapter we will define all the sections of a zone file
+
while (str.[i]<ln)
and go in-depth on the zone info section.  Once complete with this
 
chapter you should be able to create an empty yet compilable zone.
 
 
 
A zone source file is split up into 6 sections.  A
 
zone-declaration section, a mobile (NPC) section, an object
 
section, a room section, a reset section, and the DIL
 
section. The zone section is the only section that  has to be in the file, and
 
they may appear in any order.
 
 
 
Each section is preceded by a section header. These are the  six
 
possible headers:
 
* %zone
 
* %rooms
 
* %mobiles
 
* %objects
 
* %reset
 
* %DIL
 
The  first  four sections may be considered lists of definitions.
 
The reset section can be considered a program in a simple  programming
 
language. And the DIL section is a bit special - it
 
includes the zone templates (DIL functions that can be used from any
 
zone, on anything, as opposed to "specialized" DIL functions placed
 
inside a unit's
 
definitions).  After all sections you are using are defined you
 
must tell the compiler you are done the special symbol '%end'
 
must be placed at the end of the zone for this reason.
 
=== Definition types ===
 
 
 
When creating your zone there are six main building blocks.
 
We call these definition types.  Each type represents some kind of
 
data you want the compiler to be able to recognize. These data
 
definitions take the basic form:
 
<nowiki>
 
field value</nowiki>
 
Where field is the name of a data field, and value is some value.
 
Values are of one of 6 types:
 
 
 
;integer
 
: A whole number or if you are in practice of using Hex you can use the C style hex numbers in either upper or lower case (i.e 0X0f3 0x0f3)
 
;string
 
: Text enclosed in Double Quotes.  The string can span more than one line as it would in a description.
 
<nowiki>
 
title "The dark dragon altar"
 
descr
 
"There are many things you can see and there are many things that
 
can't be seen but this is still a description none the less."</nowiki>
 
;stringlist
 
: A set of strings, it can be a single string or multiple depending on your needs.
 
These are used in names, extras, creators, and special keywords all to be
 
defined later in their respective places. These are defined in the following
 
manor.
 
<nowiki>
 
&lt;fieldname&gt;    {"string1","string2","string3", ...}</nowiki>
 
;intlist
 
: A list of numbers which can be used with an extra.  This type works like the stringlist but doesn't need the quotes.
 
<nowiki>
 
extra {"mynumberlist"} {1,2,3,4,5,6,7,...}
 
"This is a number list attached to an extra"</nowiki>
 
;flags
 
: Like the Intlist the flag is defined with a list of numbers.  The list of numbers is not taken literally however it is combined to create one number by binary ORing the number list together.  If that confuses you don't worry, it takes some getting used to.  These types are used for Manipulation, flags, and positions.
 
<nowiki>
 
flags {2,8}
 
manipulate {8}</nowiki>
 
In the previous example the 'flags' value after this zone compiles
 
would be 10 because binary oring the two flags together is a lot
 
like adding.  The two numbers probably make no sense so most flags
 
you use will have defines if I used the defines found in
 
''vme.h'' the previous example would look like this:
 
<nowiki>
 
flags {UNIT_FL_INVISIBILE,UNIT_FL_BURIED}
 
manipulate {WEAR_BODY}</nowiki>
 
We will cover this more in-depth later but it was necessary to give
 
a good overview so you understand this field type enough to recognize
 
what it is when you see it.
 
;symbol
 
: A label you reference from other parts in your zones.  Every unit (room,object,room) and even the zone itself has a unique label that can be referenced. It is important to make symbol names that are clear so the Administrators of the mud know what each item is when using the online administration commands.
 
<nowiki>
 
dark_sword /*good symbol*/
 
rm_5892 /*Bad symbol*/</nowiki>
 
When loading items online the zone symbol and the item symbol are
 
combined to create a reference to the item.  For example if our zone
 
name was 'dragon' and our item was 'dark_sword' the symbolic name for
 
this item would be 'dark_sword@dragon'.  Using symbols will be
 
covered more in the DIL manual and in the administration manuals for
 
loading objects online.  For now it is enough to understand
 
symbols must follow the following rules when being defined.
 
* The first letter of the
 
symbol must be a letter of the alphabet or a '_' character
 
* Characters following the first can be numbers, alphabet
 
letters, and '_' characters
 
* The name can be no longer than
 
15 characters
 
* No reserved keywords can be used as a name
 
(Link to app-b)
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">the end tag that ends all unit definitions is also considered a symbol it is just a symbol that must be included</blockquote>
 
 
 
There are two other field types that can not be defined as a
 
regular field type.  These are the function reference and the
 
Structure.  The function reference can be either a reference to a
 
DIL function or a special function called from the
 
base code.
 
 
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">Special functions are being replaced with DIL for better performance and should only be used when no DIL functions exist to replace them</blockquote>
 
 
 
The Structure field types are  a combination of other field types
 
to make a special field type for the unit being defined.  A good example
 
of this is a 'exit' for a room.  The exit has everything from flag,
 
string, stringlist, and even description fields.  The exit field will be
 
defined much more in-depth in the chapter on rooms but it is important
 
to know some fields are considered Structure fields because they can have
 
many values.  The only two Structure fields are the exit and extra
 
fields which will both be defined more later because they can be used
 
differently depending on what you are using them for.
 
=== Zone information section ===
 
 
 
The zone information section is the only section that must
 
exist in the source file of your area.  With out this section the
 
compiler is unable to create the zone because frankly it doesn't
 
know what to call it.  It is also the easiest of the sections to
 
learn because there is only a few possible fields. The  Zone-section  defines  the global parameters for the current
 
zone. It is usually wise to place this section in the top of  the
 
source file to make it easy to find the zone information when editing the file.
 
{| class="wikitable"
 
|+Zone section field descriptions
 
|-
 
!Field
 
!Type
 
!Description
 
|-
 
|creators
 
|Stringlist
 
|This field is where you place the creators of the zone.  With
 
this field filled out the Administrators and builders can easily find out who
 
the zone was written by and be able to contact them if there are problems.
 
|-
 
|lifespan
 
|Number
 
|This  defines  the interval between resets for this zone, in minutes.
 
Default is 60 if this field is left out of the information section.
 
|-
 
|notes
 
|String
 
|This is a plain text description of the zone for administrators and builders.
 
It is often a good idea to
 
include your e-mail address in the  notes so you can be
 
reached easily by the administrators.
 
|-
 
|reset
 
|Number
 
|This combined with 'lifespan' defines if the zone will be reset.  This
 
field gives the condition that must be met to reset the zones you
 
should use the defines in the ''vme.h'', RESET_NOT,
 
RESET_IFEMPTY, and RESET_ANYHOW.  Default is RESET_ANYHOW, which
 
means, the zone will be reset even if players are present within it.
 
|-
 
|title
 
|String
 
|This is the title of the zone, for example Dragons Nest, Dark
 
station, and
 
creators hide out.  It is used mainly for the areas command so
 
players can get a list of all the areas in the game.  It can
 
however be accessed by the 'zoneptr' variable type in DIL.  If you
 
have
 
a zone that spans across multiple source files you only need to
 
define the title once.  If you put the title in all source files it
 
will show up multiple times in the area listing.  You would also
 
leave this blank if the zone should not be on the areas list like an
 
administration zone.
 
|-
 
|weather
 
|Integer
 
|This field sets the humidity level of the zone.  If for example you want
 
a hot desert like zone you would want to set this to its highest value.
 
The range of this field is 1000 to -1000.  This is an optional field and
 
will not be covered else where because it is simple to use.
 
|-
 
|%zone
 
|Symbol
 
|This entry defines the name of the
 
zone. Default is the preceding  component of the current filename,
 
minus the trailing ".zon". Note, the symbol should be added
 
after the %zone tag, which should always be put, even if you
 
do not add a symbol after it.
 
|}
 
The only field that must exist when you go to create the zone
 
information section is the '%zone'.  Leaving the '%zone' field out
 
will cause an error when you try to compile it.  We suggest you
 
not only put the '%zone' field but you also add a symbol or as I
 
call it a zone name.  The following are three legal examples of a Zone information header.  You be the judge of
 
which is more informative.
 
<nowiki>
 
/*very bad*/
 
%zone
 
 
 
/*bad but better than nothing*/
 
%zone bug_planet
 
 
 
/*The way it should be done!*/
 
%zone dragonst
 
lifespan 20
 
reset RESET_ANYHOW
 
creators {"whistler"}
 
 
 
notes
 
"This is the dragon station I shortened it to dragonst for ease in
 
loading.  If you have  any questions email me at whistler@valhalla.com"
 
 
 
help
 
"Not sure what could help you now.  You are stuck on one of the
 
weirdest space stations you have ever seen and you smell burning
 
sulfur."</nowiki>
 
If you felt like it you could add a '%end' to the proceeding
 
examples and compile them.  They would create an empty zone so
 
wouldn't be very exciting but at least its possible.  We will not go into any compiling until we have at least one unit
 
type to compile because it is pretty useless to do.
 
  the next chapters will
 
define the basic unit building blocks you will use for rooms,
 
objects, and NPCs and start you off on compiling.
 
== Unit building blocks ==
 
 
 
When creating your zone you will find some basic
 
structures are used in all three unit types rooms, objects, and
 
NPCs. In this chapter we will define the main building blocks of
 
all units along with some helpful hints
 
 
 
No matter which unit type you are dealing with there is a
 
simple basic structure that lets the compiler know not only what
 
unit type it is dealing with but where one unit begins and where it
 
ends.  The way the compiler tells what unit type it is dealing with
 
is by the section header '%rooms', '%objects', and '%mobiles'.  All
 
rooms must be defined under the '%rooms' header and likewise objects
 
and NPCS under their respective headers.  Each unit starts with a
 
symbolic name called the unit symbol and ends with the keyword
 
end. The following would be a legal definition of any
 
unit type:
 
<nowiki>
 
symbol_name
 
end</nowiki>
 
If you define a unit like this when it loads it will be blank, while
 
this is not extremely useful it is good to know you can leave
 
out any field you don't feel you need.
 
==== Unit building blocks ====
 
;symbol field
 
: In the last chapter we defined the different field types and the rules you must follow when defining a symbol.  It is important enough to relist these rules here so you do not run into problems when creating your units.
 
* The first letter of the
 
symbol must be a letter of the alphabet or a '_' character
 
* Characters following the first can be numbers, alphabet
 
letters, and '_' characters
 
* The symbol can be no longer than
 
15 characters
 
* No reserved keywords can be used as a symbol(Link to app-b)
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">It is also important to know currently it is hard to deal with units having capital letters in them, this may be fixed in the future but it is good practice to use all lower case characters in the symbols.</blockquote>
 
 
 
Another thing you should think about when defining your symbol
 
names is to be clear about what the unit is.  When you list units on
 
the VME server with '''wstat''' the symbolic names are
 
shown
 
if you were to see the list:
 
<nowiki>
 
i6853 b2419 l1854</nowiki>
 
You would have no idea what those three items were unless you
 
personally built them recently, therefore it is a much better coding
 
practice to name things what they are like:
 
<nowiki>
 
long_sword healer_hut dog</nowiki>
 
;title field
 
: The title field is probably the easiest field on all units it is what is shown on the first line of a room when you enter and it is the name shown when you get an object or attack a NPC.
 
There is only two important things to look at when defining titles
 
one is punctuation and the other is capitalization.  Room titles
 
need to be capitalized and so do proper names but the first letter of an object
 
title or a NPC title do not normally need to be capitalized. this is
 
best explained by some examples.
 
<nowiki>
 
title "The dragons in."/*good*/
 
title "a big bull dog."/*bad has a period at the end*/
 
title "Bill the destroyer"/*good*/
 
title "A long dagger"/*bad capital 'a'*/</nowiki>
 
Now to show why some of those are good we will demonstrate by some
 
sample output in the game.
 
<nowiki>
 
prompt:  l
 
The Dragons Inn
 
You are standing in a moldy inn.
 
 
 
prompt: get A long dagger
 
You get A long dagger.
 
 
 
prompt kick dog
 
You kick a bull dog. in the head.</nowiki>
 
Notice the 'A' and the extra period do not really look right where
 
they end up appearing in the game.  These may be minor nit picky
 
details but if you do it right the first time you won't have to deal
 
with the english major that just happens to be playing on your
 
mud.
 
;names field
 
: The 'names' field defines the names everything in the game can use to interact with your unit.  For rooms the names are used as teleport or goto points for characters and NPCs or they are sometimes used for special DIL functions on objects to trigger in certain rooms.  On NPCs and objects names can be used for anything from poking a player to giving a player an object.  The names field is very flexible it has even been used to store what a container is holding in order to have quick access to the names in the container.
 
 
 
When making rooms it is not necessary to put room names.  In
 
fact it is a good way of making sure players can't teleport to
 
certain rooms because if the room doesn't have a name the person
 
can't teleport to it.  Objects and NPCs must have names because if
 
you leave names off of them you can not pick them up or kill them
 
depending on which you are dealing with.  It is also good practice
 
to use all combinations of the object or NPCs title so a
 
player will know exactly what to type to use the item for example:
 
<nowiki>
 
bad_obj
 
title a small dog"
 
names{"small dog","small","dog"}
 
end</nowiki>
 
It is up to you as a builder if you want to use names like 'small'
 
in your names list since you would not 'get small' in real life it
 
may not have to be added to the names list.  It is important however
 
to define your extras from big to small because of how the VME
 
command interpreter handles names of things.  For example if you had
 
the following names:
 
<nowiki>
 
small_item
 
title "a small item"
 
names {"small","item","small item"}</nowiki>
 
When you try to '''give small item Bill'''.  The interpreter
 
would try to give
 
small to item and that would not be what you wanted to do.  Don't
 
worry the compiler will catch this and give you an error something
 
like:
 
<nowiki>
 
Fatal name ordering on line ###.</nowiki>
 
;descr field
 
: The description building block is used in many places.  You will find description fields on extras, exits, rooms, NPCs, objects, and as you have already seen the help and the notes field of the zone information section are also description fields.
 
 
 
  Depending on what
 
you are working on description fields can mean totally different
 
things to the person looking in the room.  A description field on a
 
room can be the inside or outside of the rooms description.  A
 
description on extras can be an NPCs descr or an extra description
 
on the room like if you looked at a 'rug' or a 'chair'.  On an exit
 
the descr field describes what you see when you look in that
 
direction from the room you are in.  The important thing right now
 
is no matter where you use them they all work the same.
 
 
 
description fields like the title field have a tag or unlike
 
the title field can have a set of tags before them like in extras or
 
exits but like titles they are just a string surrounded by quotes.
 
You can make multiple line descriptions if the description is on a
 
NPC you may not want to since it is the description shown when you
 
walk into the room.  The following would be some examples of room descriptions.
 
<nowiki>
 
descr
 
"this is how you would define a room descr and as you can see it can
 
be much longer than a line if you like."
 
 
 
extra {"basic extra"}
 
"This is a description field on an extra."
 
 
 
extra{"more advanced","extra"}{1,2,3,4,5,6}
 
"This is still the description field.  Like the room description or
 
any description field for that matter this can be longer than a
 
line."
 
 
 
east to bathroom descr
 
"You see one big toilet!";</nowiki>
 
;extra fields
 
: The extra field is the work horse for the builder.  It is the building block that most brings your zone to life.  You can use it to describe body parts or items in a room.  When you use DIL you will use extras to store information like quest information or special information you need later.  Extras also store the main description on NPCs since the descr field on NPCs is really the long title shown in the room which will be explained later in (Link to ch-05).
 
 
 
The extra Is the first structure definition you have run into
 
so it may take some playing with to figure it out.  The extra has
 
actually 4 fields three of them must be there in some form.  The
 
first is the identifier that tells the compiler that this is an
 
extra, the second is a stringlist, the third is an Optional
 
Intlist, and the final one is the extra description field.  If the extra
 
had all the fields it would look like this:
 
<nowiki>
 
extra {"small chair","chair"} {1,2,3,4,5} "Its a chair."</nowiki>
 
If the previous wasn't an example we
 
would have left out the Intlist because it is not necessary to put
 
the Intlist on a chair unless you want it there for some special DIL
 
you are creating. the Intlist is the only field that can be totally
 
left out but you can leave the string list blank when you want
 
to make the extra the default description when the object, room, or
 
NPC is being looked at, like this:
 
<nowiki>
 
extra {}
 
"This would be what you see when you look at any of the names in the
 
names list."</nowiki>
 
We will go more in-depth into why you want to do this in the
 
following chapters.
 
 
 
You are now ready to put these building blocks to work.  You have only
 
to learn how to put these fields to work for each of the three unit
 
types and you will be off and running.
 
== The room section ==
 
 
 
The previous chapter gave you the basic building blocks that
 
will be used all through creating rooms, NPCs, and objects.  If you
 
jumped straight to this chapter without reading about the general
 
building blocks you might want to return to (Link to ch-03)
 
first.  This chapter will deal with all the fields
 
of rooms what they are and how to use them but with out the previous
 
chapter you may get lost.
 
 
 
In order to get started building rooms you should first be aware
 
of the room fields you can use.  The (Link to rmfields) shows a full listing
 
of all the room fields and their types as defined in (Link to ch-03).
 
{| class="wikitable"
 
|+Room fields and types listing
 
|-
 
!Field
 
!Type
 
!Field
 
!Type
 
|-
 
|symbolic name
 
|Symbol
 
|manipulate
 
|Integer
 
|-
 
|names
 
|Stringlist
 
|alignment
 
|Integer
 
|-
 
|title
 
|String
 
|flags
 
|Integer
 
|-
 
|descr
 
|String
 
|weight
 
|Integer
 
|-
 
|outside_descr
 
|String
 
|capacity
 
|Integer
 
|-
 
|extra
 
|Structure
 
|light
 
|Integer
 
|-
 
|minv
 
|Integer
 
|exit
 
|Structure
 
|-
 
|key
 
|string
 
|movement
 
|Integer
 
|-
 
|spell
 
|Integer
 
|end
 
|Symbol
 
|-
 
|dilbegin or dilcopy
 
|Function pointer
 
|
 
|
 
|}
 
As you can see there is not a whole lot of fields you have to
 
learn in order to make a room.  In fact as you will see shortly some of
 
these fields are not even used on rooms.  In (Link to rmfielddescr) we will expand your knowledge from just knowing what the
 
field types are to how to set them as well.
 
=== Description of room fields ===
 
 
 
 
 
;symbolic name
 
: The rules of the symbols has been explained in (Link to ch-03), if you didn't read them yet you may want to review.
 
The important thing to realize with the room symbol is it is always
 
good practice to give the room a symbol resembling the title so
 
administrators and builders can use the
 
'''goto''' and the '''wstat''' to easily
 
goto the room in question.
 
;title
 
: The room title field should start with a capital and depending on your preference the compiler will not complain if you add punctuation at the end.  The following are good examples of a room title.
 
<nowiki>
 
title "The Post Office"
 
title "The deep dark jungle floor:"
 
title "The Dragon Station control room"</nowiki>
 
It is really up to you weather you want to use punctuation or not, it
 
is more administrator personal opinion than anything.
 
;names
 
: The names field on the rooms are not that important and only should be used if the builder wishes the room to be accessed by the players by a teleport command.  If the room has no names no one will be able to teleport to it.  On some muds there will be no teleport spell so the only use for this field will be for DIL functions the administrator creates.  If a builder wants the room to be accessible by teleport then the names should match the title since that is what the player will try to teleport to.  A few good examples of names on a room would look as follows.
 
<nowiki>
 
title "The Post Office"
 
Names {"post office","office"}
 
 
 
title "the thrown room"
 
names {"thrown room","thrown"}</nowiki>
 
;descr
 
: The description field is what the player sees when walking into the room or when looking with no arguments.
 
;outside_descr
 
: This field is what is shown to a char if the room is loaded inside another room.  For example if you had a room linked inside another room and called a barrel this would be the description that lets the character know it is a barrel.  An example would be like:
 
<nowiki>
 
outside_descr "a big old barrel is laying here on its side."</nowiki>
 
This allows a builder to make a room that looks like an object
 
inside another room.
 
;movement
 
: The movement field defines the endurance cost to a character when moving through this room.  In the future these fields will be adjustable by the use of a define file.  Currently all movement fields are constants and are defined in the
 
''vme.h''  The following is the movement sector types and their values.
 
{| class="wikitable"
 
|+Sector movement values
 
|-
 
!Symbol
 
!Name
 
!Endurance Cost
 
|-
 
|SECT_INSIDE
 
|inside
 
|1
 
|-
 
|SECT_CITY
 
|city
 
|1
 
|-
 
|SECT_FIELD
 
|field
 
|2
 
|-
 
|SECT_FOREST
 
|forest
 
|3
 
|-
 
|SECT_HILLS
 
|hills
 
|4
 
|-
 
|SECT_MOUNTAIN
 
|mountain
 
|6
 
|-
 
|SECT_DESERT
 
|desert
 
|8
 
|-
 
|SECT_SWAMP
 
|swamp
 
|8
 
|-
 
|SECT_WATER_SWIM
 
|water-swim
 
|4
 
|-
 
|SECT_WATER_SAIL
 
|water-sail
 
|50
 
|-
 
|SECT_UNDER_WATER
 
|under-water
 
|8
 
|-
 
|SECT_SNOW
 
|snow
 
|8
 
|-
 
|SECT_SLUSH
 
|slush
 
|6
 
|-
 
|SECT_ICE
 
|ice
 
|10
 
|}
 
The movement is simply defined by placing the 'movement' keyword first
 
followed by the type of sector you desire.  For example a few
 
movement fields would look as follows:
 
<nowiki>
 
movement SECT_FOREST
 
movement SECT_HILLS</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">Only one movement is needed for a room if you put more than one the last one added will be the one used.</blockquote>
 
;flags
 
: This field on a room is used to set special attributes in order to make the room private or no-teleportable and many others.  The following is the list of possible already defined flagsExtras can also be used to create special room flags.
 
{| class="wikitable"
 
|+Room unit flag affects
 
|-
 
!Flag
 
!Description
 
|-
 
|UNIT_FL_PRIVATE
 
|When this flag is set on a room it marks it as a private room.  Commands
 
that honor the private flag will not let more than 2 players into this room.
 
Commands like '''goto''' and direction commands are a few
 
commands that do honor this flag.
 
|-
 
|UNIT_FL_INVISIBLE
 
|Makes unit invisible
 
|-
 
|UNIT_FL_NO_BURY
 
|Makes a hard floor so items can't be buried.
 
|-
 
|UNIT_FL_BURIED
 
|Makes unit buried when loaded
 
|-
 
|UNIT_FL_NO_TELEPORT
 
|makes unit so no one can teleport to it
 
|-
 
|UNIT_FL_NO_MOB
 
|Makes it so no mobile will enter the unit
 
|-
 
|UNIT_FL_NO_WEATHER
 
|keeps weather and natural light out of unit
 
|-
 
|UNIT_FL_INDOORS
 
|Makes unit inside and doesn't affect weather
 
|-
 
|UNIT_FL_TRANS
 
|Makes unit transparent
 
|-
 
|UNIT_FL_NO_SAVE
 
|Makes it so you can't save with unit
 
|-
 
|UNIT_FL_SACRED
 
|Makes unit a double gain unit
 
|-
 
|UNIT_FL_MAGIC
 
|Marks a unit to be magic
 
|}
 
;extra
 
: Extras are the work horse of the VME.  Extras are used in everything from DIL to just normal extra descriptions on rooms.  The first job for an extra was to hold extra description information on a room.  For example if you had a computer room and you described it might look something like this:
 
<nowiki>
 
descr
 
"This small room houses the computer power of the VME development team.
 
All four walls are lined with various pieces of computer equipment old pizza
 
boxes and plenty of empty soda cans."</nowiki>
 
The problem is as a player if you saw this description you might want to know what kind
 
of pizza we eat or maybe you would want to see what kind of soda we drink.  Or heaven forbid you might want to know
 
what kinds of computer equipment is scattered about the room.  In the VME servers we
 
do this by adding extra descriptions to the room.  In this case the builder of the zone
 
may do something like this:
 
<nowiki>
 
descr
 
"This small room houses the computer power of the VME development team.
 
All four walls are lined with various pieces of computer equipment old pizza
 
boxes and plenty of empty soda cans."
 
 
 
extra {"soda cans", "cans", "soda", "can"}
 
"These cans are all Canadian blue.  Maybe the Valhalla team hates American
 
beer.  Strange all of them look to have strange indentations."
 
 
 
extra {"strange indentations", "strange indentation","indentation"}
 
"They are human bite marks.  Is this what happens when code doesn't work right?"
 
 
 
extra {"pizza boxes","pizza","boxes","box"}
 
"Dominos could make a fortune from all these boxes and probably already have
 
from the VME team.  you notice all the boxes are empty at least they finish what
 
they start."
 
 
 
extra {"computer pieces","computer parts", "equipment","hardware", "pieces", "parts"}
 
"I bet you thought you would see what we have running.  Yeah right you might come
 
over and rob us if we told you that.  All you see is an old XT."
 
 
 
extra {"xt"}
 
"Its a hunk of junk really!"</nowiki>
 
There is a lot to notice in the previous examples.  First we will start with
 
extras when defined on rooms, NPC, and objects must be in length
 
order for the names.  There are a few reasons for this but lets just
 
say the most important reason is we wanted it this way.  If you
 
don't put them in order the VMC will give you a fatal error and
 
will not compile your zone.
 
 
 
The next thing you should notice is we have used an extra to
 
describe something in another extra.  We actually did this twice
 
once for the beer cans and once for the computer parts.  That way
 
you can actually give quest information but make the person really
 
have to explore your rooms descriptions to find it.
 
 
 
The previous example is what we consider normal extras in a
 
room.  There are also extras that hold information for DIL functions.  These
 
special extras can have extra fields and they can be hidden to the
 
players eyes.  Here are some
 
examples of special extras.
 
<nowiki>
 
extra {"$rockcount"}
 
"5"
 
 
 
extra {"$playerkill"}
 
"0"
 
 
 
extra {"$coke","$milk","$water"}{1,5,10}
 
"Drinks and amounts"</nowiki>
 
These extras all have the '$' sign appended to the front of
 
the names in order to tell the look command the player
 
shouldn't be able to look at the extra.  If you have not already seen
 
DIL coding you may not understand why you would want extras
 
players can't see.  The DIL language can manipulate these extras by
 
reading and writing them in order to change the way a command or
 
another function works.  For example the last DIL could be used for
 
a shopkeeper to tell how many of each type of drink he has.  Notice
 
the drink extra also has something you haven't seen yet, an added integer list after the namelist. all extras can have these but
 
only extras being used with DIL functions really need
 
them.
 
 
 
Some of these special functions are supported already in the code
 
and the ones that affect the rooms are as follows.  In the
 
following $1n is the activator and $2n is the unit in question.
 
 
 
There is only one special extra already supported for rooms and
 
that would be the '$get'.  As we have previously
 
mentioned the extras that start with a dollar sign are not seen by the
 
players.  This one however is shown to the player when the person
 
types get on the other names in the extras list.  This easier to
 
describe in an example than in words so the following would be a good
 
example.:
 
<nowiki>
 
extra {"$get", "statues", "statue"}
 
"You attempt to pick up a statue but quickly discover your feeble
 
attempts will never work."
 
 
 
{"$get", "red roses", "roses"}
 
"You bend down to pick a rose, but then decide to leave the beautiful
 
flower to itself."</nowiki>
 
With this one special extra we have made it so you don't need to
 
make millions of items so the person can act upon them. You can
 
just make the acts as if the items were in the room.
 
;Exits
 
: Every room has ten possible exits; North, East, South, West, Northeast,
 
Southeast, Southwest, Northwest, Up and Down. To
 
enable mobile use of these commands, you must specify these exits as outlined
 
below:
 
<nowiki>
 
exit &lt;direction&gt; [to &lt;destination&gt;] [open {&lt;infoflags&gt;}]
 
[key &lt;keyname&gt;] [keyword {&lt;keywords&gt;}] descr &lt;description&gt; ;</nowiki>
 
;exit &lt;directions&gt;
 
: Is the direction the exit leads, ie. one of north, south ..
 
  up, down.
 
; to &lt;destinations&gt;
 
*
 
The symbolic reference to the room, you want this exit
 
  to lead to. If you reference a room within another zone, post pend the name
 
  with @&lt;zone name&gt;
 
<nowiki>
 
  to myotherroom
 
 
 
  to hisotherroom@hiszone</nowiki>
 
; open &lt;info flags&gt;
 
*
 
 
 
These flags describe the state of the door.  The following is the
 
list of possible door flags.
 
 
 
;EX_OPEN_CLOSE
 
: Set this if you can open and close this exit, be it a door, gate or otherwise.
 
;EX_CLOSED
 
: Set this if you want the exit to be closed at boot time.
 
;EX_LOCKED
 
: Set this if you want the exit to be clocked at boot time.
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">
 
An interesting aspect is, if you do not specify a key, you can
 
    only unlock this door with the 'pick' skill, 'unlock' spell or from
 
    DIL with UnSet();
 
</blockquote>
 
;EX_PICK_PROOF
 
: Using this flag renders the 'pick' skill and 'unlock' spell un useable on the lock of this exit.
 
;EX_HIDDEN
 
: If this bit is set, the exit is hidden until the mobile has successfully searched for it, using the 'search'-command.
 
 
 
;key &lt;keyname&gt;
 
: The symbolic name of a key object used for unlocking this exit.
 
<nowiki>
 
key mykey@myzone</nowiki>
 
;keyword { &lt;stringlist&gt; }
 
: This stringlist holds all the names of the exit,
 
you specify to manipulate the exit. If the exit is
 
  hidden exit, these are the keywords the mobile can search for.
 
<nowiki>
 
keyword {"wooden door","door"}
 
 
 
keyword {"hidden door","door","hatch","floor"}</nowiki>
 
;descr &lt;description&gt;
 
: This string is the description of what you see if you look in the direction of the exit.
 
;;
 
: Every exit statement needs to be terminated with a semi-colon.
 
 
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">
 
==== General notes ====
 
Even though you do not need an exit in all directions, you can use it to place
 
descriptions of the direction.
 
</blockquote>
 
<nowiki>
 
      exit north descr "An unsurmountable mountain blocks your way.";</nowiki>
 
;minv
 
: This field is rarely used on rooms.  It could however be used to make a room invisible inside another room.  Or it could be used to store numbered values on a room.  The reason this field is on a room is it is part of the base object which all objects are derived from.  If the room is going to be inside another room and you don't want it visible the following would make it invisible to all players below the level of 20.
 
<nowiki>
 
minv 20</nowiki>
 
;key
 
: This field is not used normally on a room.  It is a string that can be used for anything you desire.  The reason it exists on rooms is it is a part of the base object all unitptrs (unit pointers like,
 
rooms, objects, and NPCs) are derived from.
 
;manipulate
 
: This field is not used normally on a room.  It is an integer that can be used for anything you desire.  The reason it exists on rooms is it is a part of the base object all unitptrs are derived from.
 
;alignment
 
: This field is not used normally on a room.  It is an integer that can be used for anything you desire.  The reason it exists on rooms is it is a part of the base object all unitptrs are derived from.
 
;weight
 
: This field is not used normally on a room.  It is an integer that can be used for anything you desire.  The reason it exists on rooms is it is a part of the base object all unitptrs are derived from.
 
;capacity
 
: This field is not used normally on a room.  It is an integer that can be used for anything you desire.  The reason it exists on rooms is it is a part of the base object all unitptrs are derived from.
 
;light
 
: This field sets the light on a room.  Normally this is not done directly, instead it is set using macros defined in
 
''wmacros.h''.
 
{| class="wikitable"
 
|+Light defines
 
|-
 
!Define
 
!Light Value
 
!Affect
 
|-
 
|ALWAYS_LIGHT
 
|1
 
|Room is always light no matter time of day
 
|-
 
|IN_ALWAYS_DARK
 
|-1
 
|When an inside room is always dark - both inside and outside
 
|-
 
|OUT_DARK_NON_NOON
 
|-1
 
|Always a dark room, except when it is high noon
 
|-
 
|OUT_ALWAYS_DARK
 
|-2
 
|Always a Dark room, no matter the time of day
 
|}
 
To set natural light that changes depending on the type of day
 
nothing is needed to be put in the light field the compiler will default
 
to '0'.  If you for some reason want to set the light to default
 
lighting you can do so but you don't need to.  You will also notice
 
there are two macros that set the light to the exact same value.  This is
 
for compatibility with older code base and if you wish to combine these
 
two macros or only use one it would not change the way the mud
 
works.
 
 
 
This is probably one of the simplest fields you will have to deal
 
with in the rooms.  In order to set it all that is needed is to place
 
the macro or the light and value on a line in the room and your all
 
done.
 
<nowiki>
 
//To Set always light with macro
 
ALWAYS_LIGHT
 
 
 
//To set Always light with out macro
 
light 1</nowiki>
 
You can decide which is easiest for you.
 
;link
 
:
 
;spell
 
:
 
;dilbegin or dilcopy
 
: The DIL functions are what give VME servers the edge over all other muds.
 
We will only give some examples here and leave it up to the DIL manual to teach
 
you how to create your own functions that will make your rooms, NPC, and
 
objects more than special.
 
 
 
There are only currently three room functions that come
 
standard with a VME in the ''function.zon''.  There
 
are much more in the zones released with the VME but you
 
will have to hunt for those.  The three that come standard are Safe
 
room, Death room, and forced move.  The safe room makes it
 
impossible for players to kill each other, the death room is a
 
function that lets you make things like rock slides and quick sand,
 
and the forced move lets you make an easy river.
 
 
 
Since these are just DIL's written by builders for the
 
Valhalla mud all you have to do is use the dilcopy keyword in the
 
room with the function name you want to use and the arguments the
 
function requires.  The following is what you would find in the
 
''function.zon'' for death room.
 
<nowiki>
 
/* Death room DIL
 
*tick is in 4th's of seconds
 
* Damage is damage done per tick
 
*act_s is string shown to damaged player.
 
*/
 
dilbegin death_room(tick: integer, damage: integer, act_s: string);
 
 
 
var ext: extraptr;
 
    u  : unitptr;
 
    i  : integer;
 
 
 
code
 
 
{
 
{
 
+
if (str.[i]=="f")
if (tick < 12) tick := 12;
+
newstr.[i]:="b";
 
 
heartbeat := tick;
 
 
 
if (damage < 0)
 
    damage := -damage;
 
 
 
if ("$death room for mobs" in self.extra)
 
    i := UNIT_ST_PC|UNIT_ST_NPC;
 
 
else
 
else
    i := UNIT_ST_PC;
+
newstr:=str.[i];
 
+
i:=i+1;
while (TRUE)
 
{
 
wait (SFB_TICK, TRUE);
 
 
 
foreach (i, u)
 
    {
 
    if (u.level >= IMMORTAL_LEVEL)
 
        continue;
 
 
 
    if (("$no death room" in u.extra) and (u.type == UNIT_ST_NPC))
 
        continue; // Don't allow pcs to get this flag
 
 
 
    if (act_s != "")
 
        act ("&[hit_me]"+act_s, A_ALWAYS, u, null, null, TO_CHAR);
 
    else
 
        act ("&[hit_me]You bleed from your wounds.",
 
            A_ALWAYS, u, null, null, TO_CHAR);
 
 
 
    u.hp := u.hp - damage;
 
    position_update (u);
 
    }
 
 
 
 
}
 
}
 +
str:=newstr;
 +
 +
  This snip of Dil would replace any 'f' in a string with a 'b' remember dil is
 +
not case sensitive so it will also replace an 'F'.
  
}
+
<hr><a name="strl">
 +
<b>Stringlist:</b>
  
dilend</nowiki>
+
  A stringlist is a list of separate strings. This is used for things such as
If this DIL function scares you don't worry you don't have to
+
(multiple) names or keywords. You may request a specified word in a stringlist
understand or adjust it you just have to use it. In this function it requires a time,
+
by its number.
damage, and act.  So you could use this in a room definition like
+
<b>Example:</b>
this:
 
<nowiki>
 
dilcopy death@function (60,25,"Flames shoot from the floor burning
 
your rear.");</nowiki>
 
This says to copy the DIL from zone function with the arguments 60
 
seconds, damage 25% and act as shown.  Pretty simple eh?
 
  
All released DIL room functions are described in
+
  mystring := self.names.[2];
(Link to rmdilfunc).
 
Then we put some to work so you can see how
 
to use them in (Link to rmcomplex)
 
  
=== Building your first room ===
+
  Returning null if out of bounds of the stringlist (see 'length()'). Static
 +
stringlists are defined just as in the rest of the zonefile, as a comma separated
 +
list of static strings within curly brackets.
  
Now you are ready!  With all you have learned about room
+
<b>Example:</b>
fields you are now ready to build your first room.  I personally
 
like dragons and I like space so I have chosen to make a dragon
 
station.  We will first do a simple room and build on to it in the
 
next sections.  In this section we will walk you through creating a
 
basic room and why we choose what we do where we do.
 
  
When making rooms you create the zone source file first as shown
+
  mysrtringlist := {"Some string","another string","the last string"}
in (Link to ch-02).  If you only have rooms you do not need the
 
%reset, %objects, and %mobiles.  For the examples in this chapter we
 
will use the zone we created in (Link to ch-02) and add the %room
 
tag where we will put all the rooms.  At the end of the chapter we will
 
have the entire zone so you can see it all together.
 
  
The first part of all rooms is the symbolic name it is good to
+
  Stringlists are modified through the 'addstring()' and 'substring()' procedures.
always pick a name that will match the title so you can use the
+
Stringlists are searched easily by the 'in' operator. See documentation below.
administrator command '''goto''' to easily get to the
+
They can also be set directly (see example above)Variables of type string are
roomThe reason is when you use the command
+
saved with DIL programs, if attached to a saved unit.
'''wstat''' it will only show you a list of the rooms
 
by symbolic name for example if you type
 
'''wstat zone dragon room'''
 
You will get  the following:
 
  
<nowiki>
+
  Elements of each separate string in a stringlist can be accessed by appending
List of rooms in zone Dragon:
+
a separate position at the end of the request for a string as follows:
chamber portal office</nowiki>
 
If you didn't make it clear what the rooms were by the symbolic name
 
it might look like this:
 
<nowiki>
 
List of rooms in zone Dragon:
 
st_rm1 st_rm2 st_rm3</nowiki>
 
While this might be great when you first start imagine trying to
 
remember what all one hundred rooms are.
 
  
The first room we will create will be a simple chamber with nothing special.  We can build on to it later if we need to.
+
<b>Example</b>
<nowiki>
+
if (strlist.[5].[3]=="b"){
chamber
+
do something
end</nowiki>
+
}
Pretty easy so far.  Now lets add some life to it.  The room
 
will need a title and a description.  The title should be a one line
 
description of a room sort of like if you were walking someone
 
around your house and telling them what each room was like this is
 
'My houses big bathroom' or maybe this is 'The computer room'.  The
 
description should be something you would tell an interior
 
decorator you were talking to on the phone and asking for
 
advice. He would want to know everything about the room you
 
can see so he could give you good advice.
 
<nowiki>
 
chamber
 
title "The middle chamber of the station"
 
descr
 
"This chamber seems to have the entire station rotating around it.
 
Small human size ornate chairs with dragon designs scrawled on the
 
arms and back are arranged in a triangle like setting with one large
 
chair at the front.  This must be where all station meetings are held.
 
large pictures cover the walls depicting dragons in all kinds of
 
situations.  Small passages lead of to the west and the east.
 
."
 
end</nowiki>
 
It is a matter of taste if you want the descriptions of the
 
exits in your description or not but I like them so I put them.  Now
 
if you were reading this description to someone the person might ask
 
you what is on the pictures or maybe even what exactly do the chairs
 
look like so we better take care of that by adding some extras to
 
our little room.
 
<nowiki>
 
extra {"chairs","chair"}
 
"The chairs are made of some metal you don't recognize and every inch is covered
 
with some kind of dragon."
 
  
extra  {"dragon picture","picture"}
+
<b>Note</b>
"Thousands of dragons dot the skies of this rather life like picture.  In the
+
  See the strings for more information on accessing a single element.
center you see something move.  It looks to be a little green dragon."
 
  
extra{"green dragon","dragon","green"}
+
<hr><a name="int">
"An intelligent looking dragon is sitting perched on a large chair watching you."</nowiki>
+
<b>Integer:</b>
Normally we could put a movement type for the amount of
 
endurance lost when a person is moving through the area but we will
 
leave it blank and go with the default which is SECT_CITY since
 
with the fake gravity that is the closest we could come with the
 
sector types availible.  The last thing we need to finish our room
 
is the two exits leading to the other rooms.
 
<nowiki>
 
west to portal descr "You see a small room.";
 
  
east to office descr "You see what looks to be an office.";</nowiki>
+
  Non-fraction numbers can be used throughout your DIL programsThey are given
Thats it that is all there is to making a roomIn the next
+
normally, or in normal C style hexadecimal, preceded with '0x'. Integers are
couple of sections we are going to add some more rooms with more
+
signed 32-bit integersVariables of type string are saved with DIL programs,
advanced features and give some debugging hints for compiling your
+
if attached to a saved unit.
rooms but if you understand everything so far your going to have no
 
problem.  Lets take a look at our entire finished first room
 
<nowiki>
 
chamber
 
title "The middle chamber of the station"
 
descr
 
"This chamber seems to have the entire station rotating around it.
 
Small human size ornate chairs with dragon designs scrawled on the
 
arms and back are arranged in a triangle like setting with one large
 
chair at the front. This must be where all station meetings are held.
 
large pictures cover the walls depicting dragons in all kinds of
 
situationsSmall passages lead of to the west and the east.
 
."
 
  
extra {"chairs","chair"}
+
<b>Example:</b>
"The chairs are made of some metal you don't recognize and every inch is covered
 
with some kind of dragon."
 
  
extra  {"dragon picture","picture"}
+
  0x10
"Thousands of dragons dot the skies of this rather life like picture.  In the
 
center you see something move.  It looks to be a little green dragon."
 
  
extra{"green dragon","dragon","green"}
+
<b>Example:</b>
"An intelligent looking dragon is sitting perched on a large chair watching you."
 
west to portal descr "You see a small room.";
 
  
east to office descr "You see what looks to be an office.";
+
  2
end</nowiki>
 
=== Compiling and debugging your first room ===
 
  
It is time we put the zone header information together with
+
  Integers are used within expressions as both number value and boolean(true/false)
your first zone and compile it into a format the VME server can
+
values. You may use comparison between integers through the comparison operators:
use.  This is done by using the VMC compiler. Depending on if you
+
'==' (equality),
are doing this on your own Linux server or if you are building for a
+
'<' (less than),
VME already set up you will have to use the compiler access
+
'>' (greater than),
method they have defined.  No matter if you are compiling by email,
+
'<=' (less or equal),
ftp, or at the command line with VMC the error messages will all be
+
'>=' (greater or equal)
the same.  Since I have no idea how your particular set up is
+
'!=' (not equal).
designed I will explain the errors that the compiler will return and
 
you will have to ask your system administrator how to access the
 
compiler.  The rest of this section is written as if you have your
 
own VME running on your own Linux box using the VMC at the command
 
line.
 
  
When you are working on your first zone it is always a good
 
idea to start with one or two rooms and compile them instead of
 
writing all the rooms and then trying to compile.  The reason is the
 
more rooms you have the more confused you can make the compiler if
 
you have a lot of errors and you may not be able to figure out where
 
your first mistake was easily.  In our case we only have our first
 
room and the header information for the zone so lets put it together
 
now and try and compile it.
 
<nowiki>
 
#include composed.h>
 
%zone dragonst
 
lifespan 20
 
reset RESET_ANYHOw
 
creators {"whistler"}
 
  
notes
+
<b>Example:</b>
"This is the dragon station I shortened it to dragonst for ease in
 
loading.  If you have  any questions email me at whistler@valhalla.com"
 
  
help
+
  if (42<12) ...
"Not sure what could help you now. You are stuck on one of the
 
weirdest space stations you have ever seen and you smell burning
 
sulfur."
 
  
%rooms
+
  Returning the boolean value (true/false) depending on the comparison between
 +
integers. The result may be stored in an integer variable, and tested later, or
 +
used directly in an 'if' or 'while', etc.  You may also operate on boolean
 +
expression themselves, using LOGICAL operators 'and','not','or', which allows
 +
you to combine the expressions.
  
chamber
+
<b>Example:</b>
title "The middle chamber of the station
 
descr
 
"This chamber seems to have the entire station rotating around it.
 
Small human size ornate chairs with dragon designs scrawled on the
 
arms and back are arranged in a triangle like setting with one large
 
chair at the front.  This must be where all station meetings are held.
 
large pictures cover the walls depicting dragons in all kinds of
 
situations.  Small passages lead of to the west and the east.
 
."
 
  
extra {"chair","chairs"}
+
  if ( not ( (self.hp<42) or (self.level>10) ) ) ..
"The chairs are made of some metal you don't recognize and every inch is
 
covered with some kind of dragon."
 
  
extra  {"dragon picture","picture"}
+
Integer expressions may also use a number of other operators:
"Thousands of dragons dot the skies of this rather life like picture.  In the
+
'+' (addition)
center you see something move.  It looks to be a little green dragon."
+
'-' (subtraction/negation),
 +
'*' (multiplication),
 +
'/' (division),
 +
'|' (bitwise or, for flags),
 +
'&' (bitwise and, for flags)
  
extra{"green dragon","dragon","green"}
+
Precedence rules for using these operators are still somewhat messed up. You'd
"An intelligent looking dragon is sitting perched on a large chair watching you."
+
better use parenthesis where ever possible.
west to portal descr "You see a small room.";
 
  
east to office descr "You see what looks to be an office.";
+
<hr><a name="intlist">
end
+
<b>Intlist:</b>
  
%end</nowiki>
+
  Intlists are an array of integer typesThey can be set directly as follows:
We added the %room tag to our zone header stuck our room in
 
and now its ready to be compiled and put into the VME server for
 
you to be able to look at it in the gameIf you downloaded our
 
example zones for this document you can compile this zone along with
 
us and fix the errors as we do for practice.  The filename is
 
''debug_rm.zon''.  Just so you know the errors in this
 
zone are intentional so please don't write me an email telling me
 
there are errors in it.
 
  
The command to compile the zone is
+
<b>Example</b>
'''VMC debug_rm.zon'''.
 
Here is what we get when we first try and
 
compile the zone.
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [Apr 28 2001]
 
Compiling 'debug_rm.zon'
 
&lt;debug_rm.zon&gt; @ 2: Bad include argument
 
&lt;debug_rm.zon&gt; @ 48: Token too long
 
Fatal error compiling in preprocessor stage in file 'debug_rm.zon'.</nowiki>
 
Don't worry if this looks scary, it really is much easier to read than it looks like.
 
The first thing you need to realize about compiling is always fix one error
 
and compile again because it might fix two or three errors after
 
with one fix.  The reason is once a compiler hits something it
 
doesn't understand it gets confused with the rest of the file.  It
 
is sort of like if you thought the word 'water' meant 'fire' and you
 
tried to read a book it would get confusing really fast.  So you have
 
to correct the definition of 'water' to understand the rest of the
 
book.
 
  
Lets take the first error with this in mind.  The first error
+
wpn:={5,3,6,9,3,9};
shows up on line three of the error file it says:
 
<nowiki>
 
&lt;debug_rm.zon&gt; @ 2: Bad include argument</nowiki>
 
This line is not really cryptic reading it in a more english form
 
would sound like:  In file 'debug_rm.zon' you have an error at line 2, the
 
argument to the include statement is not correct.  Not all errors will
 
be this clear but the compiler does its best to get you close to the
 
error.  Now if you look at line two in ''debug_rm.zon'',
 
you will find, we forgot to put in the '&lt;' symbol.  If you fix
 
the line to look like:
 
<nowiki>
 
#include &lt;composed.h&gt;</nowiki>
 
Then recompile you will have fixed your first error and get a whole new
 
set to play with.  The following is the errors we got after fixing line
 
two:
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_rm.zon'
 
&lt;debug_rm.zon&gt; @ 47: EOF in string
 
debug_rm.zon: 4: parse error
 
  Token: 'RESET_ANYHOw'
 
debug_rm.zon: 21: parse error
 
  Token: 'This'
 
debug_rm.zon: 26: parse error
 
  Token: 'and'
 
debug_rm.zon: 26: parse error
 
  Token: '.'
 
Grave errors in file 'debug_rm.zon'.</nowiki>
 
Now this looks to be a much more interesting error file than the
 
previous one.  Remember we mentioned you should always fix the
 
first error first so the compiler doesn't get confused.  In this error
 
file the first line is not the first error we need to fix.  We have
 
to do some logical reasoning here.  The first error the compiler
 
came across was the one on line 4 that shows up around line 4 of the
 
error file.  The lines before it are letting you know somewhere
 
else in the file there is a missing quote.  If we clean up the first
 
error however we might be able to find this missing quote much easier.
 
So lets do that lets start by looking at line 4 which is saying the
 
compiler doesn't understand what the token 'RESET_ANYHOw' is.  This
 
makes sense the token should be 'RESET_ANYHOW' and the compiler is
 
case sensitive.  So all we need to do to fix this one is capitalize the
 
'w' and the error should be cleared up lets try that and recompile and
 
see what the errors look like.  With that line fixed the following is
 
the errors we get.
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_rm.zon'
 
&lt;debug_rm.zon&gt; @ 47: EOF in string
 
debug_rm.zon: 21: parse error
 
  Token: 'This'
 
debug_rm.zon: 26: parse error
 
  Token: 'and'
 
debug_rm.zon: 26: pars
 
e error
 
  Token: '.'
 
Grave errors in file 'debug_rm.zon'.</nowiki>
 
Again we must figure out which error message we should deal with
 
first.  As before we need to deal with the lowest number error.  The
 
error we need to fix first then is the one on line '21'.  If you go
 
to line '21' you will notice the line looks fine.  When you run
 
into an error like this where the error is not exactly on the line
 
scroll up to the field before the one in question and you should find the
 
problem.  In this case we forgot a '"' on the 'title' line and
 
confused the compiler because it thought the ending quote was the one
 
after the 'descr' field.  Therefore the compiler didn't understand the
 
'This' as a field.  This is one of the harder errors to find but once
 
you get used to it will come naturally and the compiler does try to
 
get you close.  Now if we add the '"' we are missing and recompile
 
the following is the output we get.
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_rm.zon'
 
VMC Done.</nowiki>
 
Notice there are no errors and it says 'VMC done', this means
 
you have now successfully compiled the zone.  I want you to look at the
 
last error file and the fact that we only changed a quote to go from it
 
to no errors.  This is why you always deal with one error at a time.
 
Sometimes fixing one error can fix a lot of the weird errors that make
 
no sense.  In fact I have seen one quote cause as much as 50 errors so
 
if you jump around trying to fix errors that look like they make sense
 
you may end up making more work for yourself.
 
  
Now that you have a compiled zone you should check and make sure
+
The intlists can be accessed in the same way stringlist are accessed as follows.
all the files are there.  When you compile a zone you will end up
 
with  three extra files. the files will have the same filename as your zone
 
with a new extension in this case you should have the following.
 
<nowiki>
 
debug_rm.data
 
debug_rm.err
 
debug_rm.reset
 
debug_rm.zon</nowiki>
 
If you have all of these you are all set to go.  If not then there
 
is something seriously wrong and you may want to write the VME staff for
 
help.  To get your new zone in the mud all that is needed is to make
 
sure your zone is in the zonelist in the VME etc directory and copy
 
these files into your zone directory.  Then reboot the mud.  You should
 
be able to log on your builder character and goto your zone by typing,
 
'''goto chamber@dragonst'''.
 
  
There you go you have now compiled your first zone.  Its not much
+
<b>Example</b>
to look at but with what you already know you could make a full zone of
 
very basic rooms.  The next few sections will teach you some of the more
 
interesting things you can do when making your rooms.
 
=== DIL functions for rooms ===
 
  
The DIL language is the language a builder can use to make his own
+
if (wpn.[5]==5)
special functions on rooms, NPCs, objects, PCs, and much more. This
+
{
manual is for basic zone writing and therefore will not go into how to
+
do something
write your own DIL functions.  The VME however is released with many
+
}
functions for you as an Administrator and your builders to use to make
 
special rooms, NPCs, and objects.  The following is a list of all room
 
functions released with the VME 2.0 server.
 
  
 +
The intlists are saved on savable units.
  
;Death room
 
: This function is a simple function that allows you to create a room to do damage to a player. The death_room can kill them slowly like a fire cave would or it can kill them quickly as if you stuck them in a microwave it is all up to how you set the arguments.  It also lets you see the acts the players see so this function can be used on any number of death style rooms.  There is no need to understand how the function works just how to use it so with that in mind the following is the functions header.
 
<nowiki>
 
//In function.zon
 
dilbegin death_room(tick: integer, damage: integer, act_s: string);</nowiki>
 
As with any function all you have to do is 'dilcopy' the function
 
onto your room with the correct zone name and arguments and it will do
 
the rest.  In this DIL you have three arguments to pass The first is the
 
'tick' or time which in this DIL is broken down into 'ticks' which are 4
 
ticks per second.  Thus if you wanted to get something to do damage
 
every minute you would put '60*4' in that spot.  The next is the amount
 
of damage you want done per your time.  If for example you want '60' hit
 
+points damage done each round you just put '60' as that argument.
 
Finally is the act shown to the character as a string in quotes.  So a
 
finished death room on your room would look like this.
 
<nowiki>
 
dilcopy death_room@function(4*60,60,
 
"Flames shoot up from the floor burning your butt.");</nowiki>
 
;Climb
 
: This special DIL is used for the climb skill and should be set on stationary objects (stationary mast, robe, tree, wall, etc). The
 
    'difficulty' is the skill-amount required to climb. A skill of 100
 
    would be a 50% chance for the expert thief / climber. The 'damage'
 
    is how much damage is given if you fail to climb the object. When
 
    you fail, you "fall" to the 'destination', so you can make gravity
 
    work correctly. The destination can be the same room in which you
 
    started but it doesn't have to be. The 'direction' is the direction
 
    in which you want the person to have to climb enclosed in quotes.
 
  
With all this in mind the following is the DIL definition and
+
<P>
an example use of it.
+
<H2><A NAME="intlist"></A> <A NAME="ss5.3">5.3 The Integer List</A>
<nowiki>
+
</H2>
//DIL definition
 
dilbegin climb(destination:string, difficulty:integer,
 
                damage:integer,direction:integer);
 
  
//Example use of Climb
+
<P><B>Type:  </B><CODE>intlist</CODE>
dilcopy climb@function("deck@ship", 17, 20, "up");</nowiki>
+
<P>
We should note here, if you wanted the person to have to climb
+
  This variable type allows you to keep an ordered list of integers with out
back down you will need to put a climb DIL on the room you are climbing
+
having to create a variable for each integer.
too that has the "down" directory as an argument.  This DIL also allows
+
<P><B>Example:</B>  <CODE>Setting an intlist</CODE>
you to link two rooms not linked by normal directions but we
+
<BLOCKQUOTE><CODE>
suggest you should think before doing this because it may not make sense to not
+
<HR>
have a link between the two places.
+
<PRE>
;Force move
 
: This function allows you to move a player or NPC from a room to another room with out having the player or NPC type or do anything.
 
  
The following is the definition of the force move DIL
+
myintlist:={1,5,9,2,8,5};
<nowiki>
+
myintlist.[10]:=50;
dilbegin force_move (tick: integer, strings: string, random: integer);</nowiki>
+
</PRE>
The 'tick' parameter is how fast you want the force move to be
+
<HR>
triggered.  The 'tick' is in 1/4 second increments so to get a one
+
</CODE></BLOCKQUOTE>
second wait you would place a four.  The second parameter is two strings
+
<P>
the first being the symbolic name of the room you are forcing the
+
  If you set a index that is higher then the highest index, every index in
character to.  The second string is the act you want shown to the player
+
between will be set to zeroFor example if you only have two values in the
or NPC when it is movedThe final parameter is either a one or a zero.
+
intlist and you set index value 10 to 50 all indexes between 2 and 10 will be
The one stands for true and it would make the timer trigger randomly
+
set to 0.
fifty percent of the time, while a zero would make it not random.
+
<P><B>Example:</B> <CODE>Using intlists</CODE>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
 +
if (myintlist.[5]==5){
 +
stuff
 +
}
  
The following is what the force move would look like if you wanted it to trigger every 30 seconds and give acts of a river.
+
if (myintlist&lt;myint){
<nowiki>
+
stuff
dilcopy force_move@function(4*30,{"river2@riverzon","You float down the river."},0);</nowiki>
+
}
;Safe room
 
: This function creates a safe room where combat is not allowed.
 
The following is the definition and an example of how to use it.
 
<nowiki>
 
//Safe room DIL definition
 
dilbegin safe_room ();
 
  
//Example use of Safe room
+
i:=0;
dilcopy safe_room@function ();</nowiki>
+
ln:=length(myintlist);
=== A more complex set of rooms ===
+
while (i&lt;ln){
 +
myintlist.[i]:=i;
 +
i:=i+1;
 +
}
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><b>See Also:</b>
 +
          <LI><A HREF="#bpinsert">Insert</A></LI>
 +
          <LI><A HREF="#bpremove">Remove</A></LI>
 +
          <LI><A HREF="eptr">Extraptr</A></LI></p>
  
In the last section you learned to make basic rooms.  In this
+
<b>Extraptr:</b><br>
section we will build on what you already know to allow you to make much
 
more fancy rooms.  IN this section we will give a much better view of
 
the exits and what can be done with them including doors, hidden doors and
 
rooms inside other rooms.  We will also show some examples of the room
 
DIL functions being used that were described in the previous section.
 
Finally we will pull it all together in a completed zone for you to
 
compile and play with.
 
==== Exits with doors ====
 
  
When we first defined exits we included the 'keyword' and 'open'
+
  Extra descriptions, quests structures, etc can be searched and manipulated
fields on a door.  In this section we will give an example of two rooms
+
using variables of this type. There is no way to declare static structures of
linked together with a door. There is no new information you have
+
this type in DIL programs. Lists of extra descriptions are easily searched with
not already encountered so we will start with an example.
+
the 'in' operator (See below)Extraptr variables are 'volatile', and thus
  <nowiki>
+
cleared whenever there is a possibility that they are rendered unusable.
hallway
 
title "Module tunnel"
 
descr "The hallway is about 50 meters long and around 100 meters from
 
side to side and top to bottom...."
 
  
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
  
west to chamber descr
+
<H2><A NAME="cptr"></H2>
"The hallway opens up into a chamber.";
+
<P><B>Type:  </B><CODE>cmdptr</CODE>
 +
<B>cmdptr fields</B>
 +
<PRE>
  
east to office descr
+
<B>name</B>
"You see what looks to be an office."
+
            string - command name
keyword {"air lock door","air lock","door"}
+
<DT><B>type</B>
open {EX_OPEN_CLOSE, EX_CLOSED};
+
            integer - command type like social or skill or just command
 +
<DT><B>level</B>
 +
            integer - minimum level to use command
 +
<DT><B>loglevel</B>
 +
            integer - level of character that can see the log 0 for no logs
 +
<DT><B>position</B>
 +
            integer - minimum position to use command
 +
<DT><B>next</B>
 +
            cmdptr - pointer to the next cmdptr
 +
<DT><B>previous</B>
 +
            cmdptr - pointer to the previous cmdptr
 +
</DL></PRE>
 +
<P>
 +
  The cmdptr can be used to search the command list or display all the commands.
 +
I0t is also now possible to sort the commands by type by defining your own command
 +
types and using the type field to sort on.
 +
<P>
 +
  In order to get the first command in the list you use the following function:
 +
<P><B>Function:  </B><CODE>chead();</CODE>
 +
<P>If you want to get a specific command then you use the following function:
 +
<P><B>Function:  </B><CODE>cmdptr := getcommand (s : string );</CODE>
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
end
+
dilbegin cmdtst(arg : string);
 +
var
 +
  cmd : cmdptr;
 +
  st : string;
  
office
+
code
title "The station office"
+
{
descr
+
  cmd := chead();
"Large paintings fill the walls of this part of the station...."
 
  
movement SECT_INSIDE
+
  while (cmd)
ALWAYS_LIGHT
+
        {
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
        st := cmd.name + " " + itoa(cmd.level) + " " + itoa(cmd.type) + " " +
 +
        itoa(cmd.loglevel) + " " + itoa(cmd.position);
 +
        act("CMD: $2t", A_ALWAYS, self, st, null, TO_CHAR);
 +
        cmd := cmd.next;
 +
        }
 +
       
 +
        cmd:=getcommand("kick");
 +
        sendtext ("You must be "+itoa(cmd.level+" to use kick&amp;n",self);
 +
       
 +
          quit;
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
west to hallway descr
 
"You see what looks to be a hallway."
 
keyword {"air lock door","air lock","door"}
 
open {EX_OPEN_CLOSE, EX_CLOSED};
 
end</nowiki>
 
One important thing you should notice is, whatever you put as a
 
keyword, along with the direction, is what a person must use to open
 
the door.  To make sure the door closes at reset time you will have to
 
add the doors reset to the '%reset' section.  The door resets will be
 
explained in (Link to ch-07).  Notice also in this example
 
we have a direction both in the room you are going to and the room you
 
came from.  This means you need a 'west' direction for every 'east'
 
direction leading to it.  If you do not put both you will end up with a
 
one way direction.
 
==== Locked exits ====
 
  
Now that you have making a door down, you may find that it is not
+
<hr><a name="uptr">
safe to leave your doors unlocked. Well the VME is ready for you.  You
+
<b>Unitptr:</b>
have already seen the 'keyword' and 'open' sections and what you can set
+
<P>
in them. Now lets use the 'EX_LOCKED field with them and introduce a
+
  Unit pointers are used to keep track of units: rooms, players, non-player or
new macro to allow you to set the difficulty to unlock the lock with out
+
objects. Through a variable of this type you can access most of the information
a key.
+
in a unit. Unitptr variables are 'volatile', and thus cleared whenever there is
 +
a possibility that they are rendered unusable.
 +
<P>
 +
<H2><A NAME="zptr">
 +
</H2>
  
First lets look at the macro that allows you to set a difficulty
+
<P><B>Type:  </B><CODE>zoneptr</CODE>
on a lock.  If you set the lock with out this macro it will default to
+
<B>Zone Pointer Fields</B>
0 and thus be easy to pick.
+
<DL>
<nowiki>
+
<PRE>
#define DOOR_LOCK_DEF(north_lock, east_lock, south_lock, west_lock,\
+
<DT><B>next</B><DD><P>unitptr - pointer to next zoneptr</p>
up_lock, down_lock, northeast_lock, northwest_lock, southeast_lock,\
+
<DT><B>previous</B><DD><P>unitptr - pointer to previous zone</p>
southwest_lock)</nowiki>
+
<DT><B>creators</B><DD><P>stringlist - list of creators</p>
When using this macro you only set the value of the exit you want
+
<DT><B>name</B><DD><P>string - zone name (%zone)</p>
to add the difficulty to, you can leave the rest of the exits '0'.  Only
+
<DT><B>title</B><DD><P>string - zone title (title "")</p>
one of these macros are needed on a room no matter how many exits
+
<DT><B>rooms</B><DD><P>unitptr - pointer to the base room</p>  
because each of the exits are included..  If you have an exit to the
+
<DT><B>objs</B><DD><P>unitptr - pointer to the base objects of the zone</p>
north that is locked and you want it to have a difficulty of 50% the
+
<DT><B>npcs</B><DD><P>unitptr - pointer to base NPCs of the zone</p>
following would be the line you would add to your room
+
<DT><B>resetmode</B><DD><P>integer- reset mode of zone in 'values.h'</p>
<nowiki>
+
<DT><B>resettime</B><DD><P>integer - the reset time of the zone</p>
DOOR_LOCK_DEF(50, 0, 0, 0, 0, 0, 0, 0, 0, 0)</nowiki>
+
<DT><B>access</B><DD><P>integer - the access level of the zone</p>
Now lets add the macro and the locked flag to the exits and create
+
<DT><B>loadlevel</B><DD><P>integer - the loadlevel of the zone</p>
the room.
+
<DT><B>payonly</B><DD><P>integer - the paystatus of the zone</p>
<nowiki>
+
<DT><B>roomcount</B><DD><P>integer - the number of rooms in a zone</p>
hallway
+
<DT><B>objcount</B><DD><P>integer - the numbner of objects in a zone</p>
title "Module tunnel"
+
<DT><B>npccount</B><DD><P>integer - the number of npcs/mobiles in a zone</p>
descr "The hallway is about 50 meters long and around 100 meters from
+
<DT><B>fname</B><DD><P>string - the filename of a zone</p>
side to side and top to bottom...."
+
<DT><B>notes</B><DD><P>string - the Zone Notes</p>
 +
<DT><B>help</B><DD><P>string - the Zone Help</p>
 +
</DL></PRE>
 +
<P>
 +
  The 'zoneptr' works like a unitptr.  To get the first zoneptr in the global
 +
list of zones you use 'zhead'.
 +
<P><B>Example: </B><CODE>zoneptr := zhead();</CODE>
 +
<P><B>Zone list command</B> 
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
movement SECT_INSIDE
+
dilbegin zonelist (arg:string);
ALWAYS_LIGHT
+
var
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
z:zoneptr;
 +
buf:string;
 +
code
 +
{
 +
          z:=zhead();
 +
          while (z)
 +
          {
 +
          buf:="Name:  "+z.name+"&amp;n";
 +
          buf:=buf+"Filename:  "+z.fname+"&amp;n";
 +
          buf:=buf+"Creator:  "+z.creators.[0]+"&amp;n";
 +
          buf:=buf+"Notes:  &amp;n"+z.notes+"&amp;n&amp;n";
 +
          z:=z.next;
 +
          }
 +
         
 +
          pagestring (buf,self);
 +
          quit;
 +
}
 +
dilend
 +
         
 +
                 
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
west to chamber descr
 
"The hallway opens up into a chamber.";
 
  
DOOR_LOCK_DEF(0, 50, 0, 0, 0, 0, 0, 0, 0, 0)
 
east to office descr
 
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
 
  
end
 
  
office
 
title "The station office"
 
descr
 
"Large paintings fill the walls of this part of the station...."
 
  
movement SECT_INSIDE
+
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name="messies">
ALWAYS_LIGHT
+
<h3><b>Messages:</b></h3>
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
<P>
 +
  In DIL, a program attached to a unit gets activated when the program receives
 +
a message. In order to save CPU usage, there are a number of different message
 +
categories which can cause activation of a program.  The 'wait()' commands first
 +
parameter is an integer, telling what message categories the program should
 +
reactivate on.  The second parameter is an expression, which also must evaluate
 +
to TRUE. 'pause' is just special instances of the 'wait()' command.
 +
<a name="bpwait373"></P>
  
DOOR_LOCK_DEF(0, 0, 0, 50, 0, 0, 0, 0, 0, 0)
+
<strong>Caveat Builder: </strong>
west to hallway descr
+
<p>
"You see what looks to be a hallway."
+
  Whenever you construct the arguments for the wait command, bear in mind that
keyword {"air lock door","air lock","door"}
+
ALL your tests will be executed EVERYTIME a message of the relevant kind comes
key nokey
+
throughThus you should keep the length of the activation expression to a
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
+
reasonable minimum, and you should NEVER use the time-consuming findxxx-functions.
end</nowiki>
+
</P>
The only thing you may be wondering about in this example is the
+
Valid example (That prohibits a player from removing an object):
'key' field.  I have picked 'nokey' as my value of the key.  There is no
+
<PRE>
key in this zone so all this does is create a key holeIf you leave
+
:glue:
the 'key' field out totally the only way you can open the lock is by a
 
magical spell.  It is also important that you read about resets of door locks in
 
(Link to ch-07).
 
==== Hidden exits ====
 
  
Locking the doors may not be enough.  In fact sometimes you may
 
not want to lock the door but you might want to hide it.  You can do
 
both or either with the following macro added to your exit.
 
<nowiki>
 
#define SECRET_DOOR_DIFFICULTY(DIR, SKILL) \
 
extra{SECRET_DOOR} {DIR, SKILL}\
 
""</nowiki>
 
So if you wanted a door or just a passage to the north hidden you
 
would add this before or after your exits.
 
<nowiki>
 
SECRET_DOOR_DIFFICULTY(NORTH, 50)</nowiki>
 
Now lets put it all together and link two rooms together with a
 
hidden door.
 
<nowiki>
 
office
 
title "The station office"
 
descr
 
"Large paintings fill the walls of this part of the station..."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
west to hallway descr
 
"You see what looks to be a hallway."
 
keyword {"air lock door","air lock","door"}
 
open {EX_OPEN_CLOSE, EX_CLOSED};
 
 
SECRET_DOOR_DIFFICULTY(SOUTH, 50)
 
south to portal_room descr
 
"You see what looks to be a portal room."
 
keyword {"air lock door","air lock","staff","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED,EX_HIDDEN};
 
 
end
 
 
portal_room
 
title "Green field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a green field right in the center.
 
there is a door that leads to another room to the north."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
north  to office descr
 
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
 
 
end</nowiki>
 
==== Rooms inside of rooms ====
 
 
Now that you have normal exits down its time to take a look at
 
something a bit different.  Lets say you wanted to put a barrel in a
 
room that is also a room that has exits to other rooms.  Or maybe in my
 
case I want to put a transporter pad in the room that is also a room
 
so you can exit back into the room you came from.  In the case of the
 
teleporter I could use an object but as you will find it is much easier
 
to deal with a room for this than an object.
 
 
To put a room in a room it is much different than using the normal
 
exit fields.  The only thing needed is the 'in' keyword and the
 
room you are linking the current room into. There is no need for a
 
semi-colon.  The following is what the line would look like.
 
<nowiki>
 
in &lt;room that room is in&gt;</nowiki>
 
Not too hard.  The following are two rooms one in the other.
 
<nowiki>
 
portal_room
 
title "Green field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a green field right in the center.
 
there is a door that leads to another room to the north."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
extra {"green field","field"}
 
"The field looks to be a green fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
 
north  to office descr
 
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
 
 
//A link to the portal is also here
 
end
 
 
room_port
 
names{"green field", "field"}
 
title "Green field"
 
descr
 
"Green Mist swirls about you."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
in portal_room
 
end</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">
 
After adding a room in a room you should note the room in the
 
description or put an 'outside_descr' on the room inside it.  In
 
our example we have chosen to add the description into the room instead
 
of using the 'outside_descr'.  Also doors and locks work the same way as before you can even hide this exit.</blockquote>
 
==== A room using force move. ====
 
 
  Sometimes you will want to help players along
 
their path.  This could be for a river that flows strongly enough to
 
force a players raft down stream or maybe for a room of quick sand that
 
sucks the player into another room.  In these situations we need to use
 
the force move DIL, explained in the previous section.  Here we
 
have built two rooms linked only by a forced move.
 
<nowiki>
 
portal_room
 
title "Green field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a green field right in the center.
 
there is a door that leads to another room to the north."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
extra {"green field","field"}
 
"The field looks to be a green fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
 
north  to office descr
 
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
 
 
//A link to the portal is also here
 
 
end
 
ship_port
 
names{"green field", "field"}
 
title "Green field"
 
descr
 
"Green Mist swirls about you."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
in ship
 
 
dilcopy force_move@function(
 
//Time to activation
 
4,
 
//room and act
 
"portal_room@dragonst!You feel your body dissolving for lack of a better
 
description.&amp;nYou appear on the deck of a ship.",
 
//True or False for randomizing or not
 
FALSE);
 
 
end</nowiki>
 
==== A death room ====
 
 
As a final touch to my little example zone I want to create a
 
room that will kill a player instantly.  I will use the DIL function
 
Death room and the room would simply look as follows.
 
<nowiki>
 
deathspace
 
title"Open space"
 
descr
 
"You see the ship and the station far off in the distance and you are in Space!"
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
dilcopy death_room@function (
 
//how often is damage done 4 would be 1 second
 
4,
 
//damage
 
400,
 
//act for the damage.
 
"You realize to late that was the trash disposal transporter and you feel your lungs explode.");
 
 
end</nowiki>
 
=== Putting the rooms together ===
 
 
Using all you have learned so far and putting it all together into
 
one zone.  You end up with a very interesting space station with some
 
secret rooms and traps..  The full zone all together looks like
 
this.
 
<nowiki>
 
#include &lt;composed.h&gt;
 
%zone dragonst
 
lifespan 20
 
reset RESET_ANYHOW
 
creators {"whistler"}
 
 
notes
 
"This is the dragon station I shortened it to dragonst for ease in
 
loading.  If you have  any questions email me at whistler@valhalla.com"
 
 
help
 
"Not sure what could help you now.  You are stuck on one of the
 
weirdest space stations you have ever seen and you smell burning
 
sulfur."
 
 
%rooms
 
 
chamber
 
title "The middle chamber of the station"
 
descr
 
"This chamber seems to have the entire station rotating around it.  It is
 
unbelievably large the ceiling seems to be a good 200 meeters high and
 
the room is perfectly cubic. Small human size ornate chairs with dragon
 
designs scrawled on the arms and back are arranged in a triangle like
 
setting with one large chair at the front.  This must be where all
 
station meetings are held. large pictures cover the walls depicting
 
dragons in all kinds of situations.  large passages lead of to the west
 
and the east.."
 
 
extra {"chair","chairs"}
 
"The chairs are made of some metal you don't recognize and every inch is covered
 
with some kind of dragon."
 
 
extra  {"dragon picture","picture"}
 
"Thousands of dragons dot the skies of this rather life like picture.  In the
 
center you see something move.  It looks to be a little green dragon."
 
 
extra{"green dragon","dragon","green"}
 
"An intellegence looking dragon is sitting perched on a large chair watching you."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
west to disposal_room descr
 
"You see a small room.";
 
 
east to hallway descr
 
"You see what looks to be a hallway.";
 
 
end
 
 
hallway
 
title "Module tunnel"
 
descr "The hallway is about 50 meters long and around 100 meters from
 
side to side and top to bottom.  The hallway seems to be dust free.  The
 
walls and the floors seem to be made out of the same sterile
 
metal-plastic that all space agencies uses.  There are large plate glass
 
windows that open up into space.  The hallway is filled with a dim light
 
that seems to come from everywhere yet no where all at once.  You notice
 
a glimmer of bright light coming from the windows.  To the east you see
 
an air lock and to the west the hallway opens up into a larger room."
 
 
extra {"windows","window"}
 
"Your eyes are drawn to a large ship lit up with running lights sitting
 
about 1 kilometer from the station."
 
 
extra{"floor","walls","wall"}
 
"Well what can be said it looks to be in perfect condition.  what else would you want to know?"
 
 
extra {"large ship" ,"ship"}
 
"The ship looks really big and is shaped like a dragon.  The scales
 
sparkle and seem to be multiple colors."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
west to chamber descr
 
"The hallway opens up into a chamber.";
 
 
east to office descr
 
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
open {EX_OPEN_CLOSE, EX_CLOSED};
 
 
end
 
 
office
 
title "The station office"
 
descr
 
"Large paintings fill the walls of this part of the station.  The room
 
is as large as the other rooms big enough for Dragons to lounge while
 
still having a desk in one corner small enough for a humanoid.  The
 
floor along the north wall is lined with some kind of fabric and seems very soft to
 
walk on, it may be some kind of dragon lounge judging by how large an
 
area it covers.  There is a passage to the west."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
extra {"paintings","painting"}
 
"The paintings are of many dragons and riders in all kinds of tasks from
 
combat to look out.  All the figures seem to be staring at a staff
 
being held by a depiction of a wizard on the south wall."
 
 
extra {"wizard","staff"}
 
"The wizard has his hand stretched out and it seems there is a place
 
you can almost grab the staff. Maybe if you searched the staff you would
 
find it."
 
 
extra {"desk"}
 
"Its a desk alright but there doesn't seem to be any drawers and it
 
seems totally empty."
 
 
extra{"fabric"}
 
"Wussshhhhh you bound across the comfortable floor wasn't that fun."
 
 
west to hallway descr
 
"You see what looks to be a hallway."
 
keyword {"air lock door","air lock","door"}
 
open {EX_OPEN_CLOSE, EX_CLOSED};
 
 
SECRET_DOOR_DIFFICULTY(SOUTH, 50)
 
south to portal_room descr
 
"You see what looks to be a portal room."
 
keyword {"air lock door","air lock","staff","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED,EX_HIDDEN};
 
 
end
 
 
portal_room
 
title "Green field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a green field right in the center.
 
there is a door that leads to another room to the north."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
extra {"green field","field"}
 
"The field looks to be a green fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
 
north  to office descr
 
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
 
 
//A link to the portal is also here from room_port
 
end
 
 
ship_port
 
names{"green field", "field"}
 
title "Green field"
 
descr
 
"Green Mist swirls about you."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
in ship
 
 
dilcopy force_move@function(
 
//Time to activation
 
4,
 
//room and act
 
"portal_room@dragonst!You feel your body dissolving for lack of a better
 
description.&amp;nYou appear on the deck of a ship.",
 
//True or False for randomizing or not
 
FALSE);
 
 
end
 
 
room_port
 
names{"green field", "field"}
 
title "Green field"
 
descr
 
"Green Mist swirls about you."
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
in portal_room
 
 
dilcopy force_move@function(
 
//Time to activation
 
4,
 
//room and act
 
"ship@dragonst!You feel your body dissolving for lack of a better
 
description.&amp;nYou appear on the deck of a ship.",
 
//True or False for randomizing or not
 
FALSE);
 
 
end
 
 
disposal_room
 
title "Red field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a red field right in the center.
 
there is a door that leads to another room to the east."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
extra {"red field","field"}
 
"The field looks to be a red fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
 
east to chamber descr
 
"You see the main chamber.";
 
 
//A link to the portal is also here from dis_port
 
end
 
 
dis_port
 
names {"red field","field"}
 
title "Red field"
 
descr
 
"Red Mist swirls about you."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
dilcopy force_move@function(
 
//how fast to force move in seconds
 
4,
 
//room to force move to and act
 
"deathspace@dragonst!You feel your body dissolving for lack of a better description.",
 
//true or false random move or not
 
0);
 
in disposal_room
 
 
end
 
 
ship
 
title "War dragon"
 
descr
 
"Blue light softly glows from con duets that line the walls of this ship.
 
The floors beside the east and west wall have what looks to be soft
 
fabric covering.  The south wall has small controls that seem to be made
 
for humanoids with two small chairs that look to be pilot seats.  view
 
portals are about 50 meters up the side of the ship on the west and east
 
wall and some kind of electronic screen covers the south wall.  The ship
 
seems to be a one room ship but there is a green field by the north
 
wall."
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
extra {"view port"}
 
"Sorry your not 50 meters tall maybe it is made for a dragon?"
 
 
extra {"view screen","screen"}
 
"It seems to be the pilots view screen but you can't seem to see a way
 
to turn it on."
 
 
extra {"controls","control"}
 
"The controls are in some weird language and your afraid if you start
 
pushing buttons you might rocket in to the station or worse slam into
 
a planet."
 
 
extra {"soft fabric","fabric"}
 
"It looks to be a dragon lounge area."
 
 
//A link to the portal is also here from ship_port
 
end
 
 
deathspace
 
title"Open space"
 
descr
 
"You see the ship and the station far off in the distance and you are in Space!"
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
dilcopy death_room@function (
 
//how often is damage done 4 would be 1 second
 
4,
 
//damage
 
400,
 
//act for the damage.
 
"You realize to late that was the trash disposal transporter and you feel your lungs explode.");
 
 
end
 
 
%end</nowiki>
 
=== Suggested room exercises ===
 
 
1. Create a door between the Disposal room and the main chamber
 
of the station.  Make the new door pick-proof and magic-proof.
 
 
2. Create another hallway to the south of the main chamber that leads
 
to a ship attached by an airlock.  You will need a door before the
 
hallway and before the ship so no one gets sucked out in space.  You
 
will need two more rooms for this one for the hallway and one for the
 
ship.
 
 
3. Using the Dragon station zone as a guide create your own zone with
 
eight  rooms.  Don't worry to much about descriptions and extras.  Link all
 
eight of the rooms to each of the other rooms.  This means each room
 
should have seven exits.  If you were to map this it would look like a
 
cube marked with 'X' on the sides.
 
 
4.Make a 3 room cliff that uses the climb DIL function to climb from the bottom to top.
 
== The NPC section ==
 
 
Now that you have rooms down it is time to start filling your area
 
with some life.  The NPC is the Non-player Character or mobile.  These
 
are the things players will hunt and interact with
 
 
In order to get started building NPCs you should first be aware
 
of the NPC fields you can use.  The (Link to npcfields) shows a full listing
 
of all the NPC fields and their types as defined in (Link to ch-03).
 
{| class="wikitable"
 
|+NPC fields and types
 
|-
 
!Field
 
!Type
 
!Field
 
!Type
 
|-
 
|Symbolic name
 
|Symbol
 
|
 
|level
 
|Integer
 
|-
 
|names
 
|Stringlist
 
|height
 
|Integer
 
|-
 
|title
 
|String
 
|race
 
|Integer
 
|-
 
|descr
 
|String
 
|attack
 
|Integer
 
|-
 
|inside_descr
 
|String
 
|armour
 
|Integer
 
|-
 
|extra
 
|Structure
 
|speed
 
|Integer
 
|-
 
|manipulate
 
|Integer
 
|position
 
|Integer
 
|-
 
|flags
 
|Integer
 
|default
 
|Integer
 
|-
 
|weight
 
|Integer
 
|ability
 
|two Integers
 
|-
 
|capacity
 
|Integer
 
|weapon
 
|two Integers
 
|-
 
|dilbegin or dilcopy
 
|Function pointer
 
|spell
 
|two Integers
 
|-
 
|defensive
 
|Integer
 
|romflags
 
|Integer
 
|-
 
|offensive
 
|Integer
 
|light
 
|Integer
 
|-
 
|mana
 
|Integer
 
|alignment
 
|Integer
 
|-
 
|hit
 
|Integer
 
|minv
 
|Integer
 
|-
 
|money
 
|Integer
 
|key
 
|String
 
|-
 
|exp
 
|Integer
 
|open
 
|Integer
 
|-
 
|sex
 
|Integer
 
|end tag
 
|Symbol
 
|}
 
Many of the same fields you found in rooms, as you can see from
 
(Link to npcfields), can also be found in NPCs.  The fields do
 
not always have exactly the same use when coding rooms, NPCs, and
 
objects but they are normally set in the same manor.  It is very
 
important that you read and understand the differences of each field as
 
they pertains to rooms and or NPCs.
 
=== Description of NPC fields ===
 
 
 
;symbolic name
 
: The rules of the symbols has been explained in (Link to ch-03), if you didn't read them yet you may want to review.
 
The important thing to realize with the NPC symbol is it is always
 
good practice to give the NPC a symbol that resembles the title so
 
that administrators and builders can use the
 
'''load''' and the '''wstat''' to easily
 
locate, examine, and load the NPC in question.
 
;title
 
: The NPC title is what is shown if the NPC is being attacked or talking.
 
It is also what is shown if the NPC can be picked up.  there should be
 
no punctuation in the NPC title because of how it is used in the VME
 
server.  If you add punctuation or forget to capitalize something
 
that the VMC thinks you should it will give you a warning when you
 
compile.
 
<nowiki>
 
title "a small dog"
 
title "Hansen"
 
title "a black dragon"
 
title "Drako"
 
title "an elephant"</nowiki>
 
; descr
 
*
 
 
The description field is what the player sees when walking into the room
 
or when looking with no arguments. The description on a NPC will only
 
show up when the NPC is in the standing position.  All other positions
 
will show the title and the position they are in.
 
<nowiki>
 
descr
 
"a small fluffy dog is chasing its tail here."
 
descr
 
"Hansen is standing here sorting the mail."</nowiki>
 
;names
 
: The NPC name field is much more important then the room name field.  It is what is used when players are hunting and killing and even for administrators who are trying to use their administrator commands on a NPC.  The names should match the title and the descr fields and have all normal combinations of each.
 
<nowiki>
 
title "a baby black dragon"
 
descr "a tiny baby black dragon is here playing."
 
names {"tiny baby black dragon", "tiny black dragon",
 
"baby black dragon", "black dragon", "tiny dragon",
 
"baby dragon","dragon"}
 
 
title "Hansen"
 
descr "Hansen the post man is standing here sorting mail."
 
names{"postman","hansen"}</nowiki>
 
The idea of course is to make any combination that a player may
 
type to try and act upon your NPC.  You would not want to describe and
 
title your NPC with an entirely different theme than you created its
 
names with because a player would not know what it is called.
 
;inside_descr
 
: The inside description is what a player sees if it is inside the NPC.  This could be used to show the player its stomach or if on a mount it could be used to show the back of the horse.
 
<nowiki>
 
inside_descr
 
"The lining of this stomach looks indestructible.  Looks like you are in
 
for a long digestion cycle."</nowiki>
 
;extra
 
: The extra's on the NPC can be used to do many things.  It can be used to store information for DIL programs or it can be used to show a part of the NPC like the room extras show a part of the room.  There is also a special extra, the NPCs description when you look at it with the look &lt;NPC&gt; command.
 
 
Lets show the NPC description extra first.  If you use an extra
 
with no names list it will become the NPCs description when you look at
 
any of the names on the NPC.
 
<nowiki>
 
extra {}
 
"The green furry hamster seems to be glowing and it doesn't seem very
 
happy."</nowiki>
 
You can also use extras to show parts of the NPC.
 
<nowiki>
 
extra {"hamster head","head"}
 
"This human like head is covered with a lot of green fur and it looks
 
really  upset."</nowiki>
 
You can also use the extras to give more detailed and vivid
 
descriptions when the NPC is acted upon.
 
{| class="wikitable"
 
|+NPC special action extras
 
|-
 
!Extra
 
!Description
 
|-
 
|$get_s
 
|A message shown to activator when getting a NPC.
 
|-
 
|$get_o
 
|A message shown to others when getting a NPC.
 
|-
 
|$drop_s
 
|a message shown to activator when dropping a NPC.
 
|-
 
|$drop_o
 
|A message shown to others when dropping an NPC.
 
|-
 
|$enter_s
 
|A message shown to activator When mounting
 
|-
 
|$enter_o
 
|A message shown to others when mounting.
 
|-
 
|$exit_s
 
|A message shown to others when dismounting
 
|-
 
|$exit_o
 
|a message shown to others when dismounting
 
|}
 
In the following example, $1n is the activator and $2n is the
 
unit in question.  Assume you are defining a familiar.
 
<nowiki>
 
extra {"$get_s"}
 
"You pick up the $2n it is very warm and cuddles right up to you."
 
 
extra {"$get_o"}
 
"$1n picks up the $2n and you see them cuddle together."</nowiki>
 
Finally you can use extras to store information for DIL programs.
 
We will not cover this because it is a topic covered in-depth in
 
the DIL documentation.
 
;manipulate
 
: The manipulate filed only has two values for NPCs The two values are 'MANIPULATE_TAKE' and 'MANIPULATE_ENTER'.  The 'MANIPULATE_TAKE'
 
makes it possible for a NPC to be picked up this would be good for
 
something like a familiar.  The 'MANIPULATE_ENTER' is used for things
 
like mounts when making a mount you will also have to set the capacity
 
so a fat player can jump on.  The following is how you set the
 
manipulate flag.
 
<nowiki>
 
//Make a  NPC takable.
 
manipulate {MANIPULATE_TAKE}
 
 
//Make a NPC takable and able to be entered
 
manipulate {MANIPULATE_TAKE|MANIPULATE_ENTER}</nowiki>
 
;flags
 
: This field on a NPC is used to set special attributes in order to make the NPC able to be buried or not or no-teleportable and many others.  The NPC flag list uses the UNIT_FL_* variables that both the objects and the rooms also use, therefore while you can set some flags on an NPC it may not have any affect unless you as a builder or administrator adds the functionality.  You can also add extras on an NPC that can be used as a special flag which you will learn as you learn to use DIL.  The following is a full list of all unit flags and how they affect NPC, if they do.
 
{| class="wikitable"
 
|+NPC unit flag affects
 
|-
 
!Flag
 
!Description
 
|-
 
|UNIT_FL_PRIVATE
 
|Currently has no affect on a NPC.
 
|-
 
|UNIT_FL_INVISIBLE
 
|Makes unit invisible
 
|-
 
|UNIT_FL_NO_BURY
 
|Makes it so you can create NPC that can be taken like familiars or
 
pets that can not be buried.  This flag is not needed on every NPC
 
because the bury command will not allow you to bury an NPC outside of
 
your inventory.
 
|-
 
|UNIT_FL_BURIED
 
|Makes unit buried when loaded
 
|-
 
|UNIT_FL_NO_TELEPORT
 
|Makes it so you can not summon the NPC with this flag and the NPC with
 
this flag can not teleport.  You can still teleport to NPC with this
 
flag the current way teleport is written.  Remember all spells are in
 
DIL and you can modify them in ''spells.zon''
 
|-
 
|UNIT_FL_NO_MOB
 
|Currently has no affect on a NPC.
 
|-
 
|UNIT_FL_NO_WEATHER
 
|Currently has no affect on a NPC.
 
|-
 
|UNIT_FL_INDOORS
 
|Currently has no affect on NPC.
 
|-
 
|UNIT_FL_TRANS
 
|Makes unit transparent If the Unit is transparent you will be able
 
to see any other NPCs that it is carrying.  For example if a NPC was
 
carrying a familiar you would see that as you walked into the room.  It
 
also is used in mounts so the PC can see outside its mount.  If the
 
flag is not set on its mount the player will not see what is in the
 
room.
 
|-
 
|UNIT_FL_NO_SAVE
 
|Makes it so a PC can't save with unit
 
|-
 
|UNIT_FL_SACRED
 
|Currently has no affect on a NPC.
 
|-
 
|UNIT_FL_MAGIC
 
|Currently has no affect on a NPC.
 
|}
 
If you wanted to make a NPC that a player can carry around but can
 
not save you would set the manipulate and flags as follows.
 
<nowiki>
 
manipulate {MANIPULATE_TAKE}
 
flags {UNIT_FL_NO_SAVE}</nowiki>
 
;romflags
 
: Like flags these are just integer values that are used to change how the NPC interacts with its environment.
 
{| class="wikitable"
 
|+Room flags for NPCs
 
|-
 
!Flag
 
!Description
 
|-
 
|CHAR_PROTECTED
 
|Set this flag if the character is protected by the law-system.
 
|-
 
|CHAR_LEGAL_TARGET
 
|This flag is used by the law system and should not be set unless you are re-writing your law system.
 
|-
 
|CHAR_OUTLAW
 
|This flag is used by the law system and should not be set unless you are re-writing your law system.
 
|-
 
|CHAR_GROUP
 
|This is used by the follow and group commands and should not be set unless you are re-writing your, movement, status, and combat systems.
 
|-
 
|CHAR_BLIND
 
|Set this if the character is blinded.
 
|-
 
|CHAR_HIDE
 
|Set flag if character is hidden.
 
|-
 
|CHAR_MUTE
 
|Set flag if character is mute.
 
|-
 
|CHAR_SNEAK
 
|Set flag if character is in sneaking mode.
 
|-
 
|CHAR_DETECT_ALIGN
 
|No actual effect on NPCs.
 
|-
 
|CHAR_DETECT_INVISIBLE
 
|Set flag if character can see invisible units.
 
|-
 
|CHAR_DETECT_MAGIC
 
|No actual effect on NPCs.
 
|-
 
|CHAR_DETECT_POISON
 
|No actual effect on NPCs.
 
|-
 
|CHAR_DETECT_UNDEAD
 
|No actual effect on NPCs.
 
|-
 
|CHAR_DETECT_CURSE
 
|No actual effect on NPCs.
 
|-
 
|CHAR_DETECT_LIFE
 
|No actual effect on NPCs.
 
|-
 
|CHAR_WIMPY
 
|Set flag if character if wimpy. Wimpy characters flee when they are
 
low on hit points, and they gain less experience when killing others.
 
If a character is both wimpy and aggressive (NPC_AGGRESSIVE) it will
 
only attack sleeping players.
 
|-
 
|CHAR_SELF_DEFENCE
 
|This is an internal combat flag set this only if you create your own combat system.
 
|}
 
These flags are set in the same way as other flags in rooms NPCs
 
and objects.  The following are a few examples.
 
<nowiki>
 
//wimpy and hidden
 
romflags {CHAR_HIDDEN, CHAR_WIMPY}
 
 
//NPC can see invisible
 
romflags {CHAR_DETECT_INVISIBLE}</nowiki>
 
;weight
 
: The weight is the weight of the NPC in pounds.  In the future we may adjust this to allow you to make things lighter for example you could set it in ounces or grams.  Right now however all we have is pounds so we have some pretty heavy feathers out there.
 
 
To use this you just enter the 'weight' keyword and then the
 
value.
 
<nowiki>
 
/80 lbs.
 
weight 80</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">The weight affects the NPCs natural attack damage.</blockquote>
 
;capacity
 
: This field along with the NPCs strength and dexterity decides how much a NPC can carry.  If you set the capacity to 300 lbs.  the NPC will only be able to carry that much depending if it has the strength and dexterity to carry that much.  This of course doesn't affect DIL programs that link the objects directly into the NPC.  To set the capacity you just put the keyword and the amount in your NPC.
 
<nowiki>
 
capacity  300</nowiki>
 
;height
 
: The height field is the size of the NPC in centimeters.  This determines the size of the equipment the NPC is wearing.  You will learn more about size and height in the object section but for now just understand this makes your NPC the right or wrong size.  To set the 'height' you just put the 'height' keyword followed by the number of centimeters.
 
<nowiki>
 
//6 feet tall since 1 inch equals 2.54
 
height 183</nowiki>
 
;dilbegin or dilcopy
 
: The DIL functions are what give VME servers the edge over all other muds.
 
We will only give some examples here and leave it up to the DIL manual to teach
 
you how to create your own functions that will make your rooms, NPC, and
 
objects more than special.
 
 
There are several NPC functions that come standard with the VME
 
2.0.  The following is a list of the functions.
 
* Mercenary
 
* obey
 
* evaluate
 
* guard direction
 
* shop keeper
 
* combat magic
 
* fido
 
* zone wander
 
* global wander
 
* team work
 
* rescue
 
* agressive
 
These are the only NPC functions currently documented in the VME
 
2.0 release but if you go through the zones that are released with the
 
VME you are sure to find many more.  Hopefully with the descriptions in
 
(Link to npcdilfunc).  You will be able to use the functions
 
listed here and figure out ones that are not.
 
 
Since these are just DIL's written by builders for the
 
Valhalla mud all you have to do is use the dilcopy keyword in the
 
NPC with the function name you want to use and the arguments that
 
function require.  The following is what you would find in the
 
''function.zon'' for evaluate.
 
<nowiki>
 
/* Evaluate DIL. amt is the cost of evaluation in iron pieces.
 
  Note: not to be confused with '''evaluate@commands''', which
 
  is a command.
 
*/
 
dilbegin aware evaluate (amt: integer);
 
 
var u1 : unitptr;
 
    arg: string;
 
    buf: string;
 
    cur: integer;
 
    craft: integer;
 
    category: integer;
 
 
    pc : unitptr;
 
    pcn: string;
 
 
    arm_text  : stringlist;
 
    shi_text  : stringlist;
 
    craft_text: stringlist;
 
code
 
{
 
 
craft_text:=  {"horrible","very bad","bad","worse than average","average",
 
  "a little better than average","better than average","good","very good",
 
  "supreme"};
 
arm_text:= {"clothes", "leather", "hard leather", "chain", "plate"};
 
shi_text:= {"small", "medium", "large"};
 
 
heartbeat:= PULSE_SEC*3;
 
 
:start:
 
arg:= "";
 
u1:= null;
 
 
wait (SFB_CMD, command("evaluate"));
 
 
if (visible(pc, self) == FALSE)
 
    goto start; // Pc is just trying to evaluate using the command
 
  
 +
wait(SFB_CMD,command(CMD_REMOVE));
 +
u := findunit(activator,argument,FIND_UNIT_IN_ME,null );
 +
if (u != self)
 +
{
 +
goto glue;
 +
}
 +
act("You can't remove $2n, it's sticky.",
 +
  A_SOMEONE,activator,self,null,TO_CHAR););
 
block;
 
block;
 +
goto glue;
 +
</PRE>
 +
<h4>See Also:</h4>
 +
<a href="findunit.html">Dil and Findunit()</a>
 +
<P>
 +
The message categories are as follows:</P>
 +
<hr><a name="sfbcmd">
 +
<PRE>
 +
SFB_CMD            Command message
  
pc:= activator;
+
  When this flag is set, the program gets activated by all commands (legal
if (pc.type == UNIT_ST_PC) pcn := pc.name;
+
  or illegal) issued by PC's or NPC's. Moving around is also considered a
else pcn := pc.title;
+
  command.
  
arg:= argument;
+
  Assume a janitor executes the command '
 +
  Ge all from corpse',
 +
  And Ge interprets to 'get'
 +
 
 +
  then this will occur in the DIL program:
  
if (visible(self, pc) == FALSE)
+
    'activator'... is a unitptr to the janitor.
    {
+
    'cmdstr'...... is a string which contains 'get'
    exec ("say I don't do business with people I can't see.", self);
+
    'excmdstr'...... is a string which contains 'ge'
    goto start;
+
    'excmdstr_case'...... is a string which contains 'Ge'
    }
+
    'argument'.... will contain 'all from corpse'
  
if (arg == "")
+
    command(CMD_GET) will evaluate to TRUE.
    {
+
</PRE>
    exec ("say Which item do you wish to evaluate, "+pcn+"?", self);
+
    goto start;
+
<hr><a name="sfbdone">
    }
+
<PRE>
 +
SFB_DONE          'Command has now been executed' message
  
u1:= findunit (pc, arg, FIND_UNIT_IN_ME, null);
+
  When this flag is set, the program gets activated by all successful commands
 +
  issued by PC's or NPC's. The 'activator', 'medium' and 'target' special
 +
  values are used as follows:
  
if (not u1)
+
    'activator'... The PC / NPC which executed the command
    {
+
    'medium'...... The unit which is operated upon.
    exec ("say You do not have such an item, "+pcn+".", self);
+
    'target'...... The target of the operation.
    goto start;
 
    }
 
  
if ((u1.type != UNIT_ST_OBJ) or ( (u1.objecttype != ITEM_WEAPON) and
+
  For example, assume the player John gives a garlic to Mary the Lumberjack
    (u1.objecttype != ITEM_ARMOR) and (u1.objecttype != ITEM_SHIELD) ))
+
  wife. The following values are set:
    {
 
    exec ("say The "+u1.name+" is neither a sword, shield nor armor!", self);
 
    goto start;
 
    }
 
  
// Currency, skip for now
+
    activator == John (unitptr)
 +
    medium    == Mushroom (unitptr)
 +
    target    == Mary (unitptr)
  
if (not transfermoney (pc, null, amt * IRON_MULT))
+
  command(CMD_GIVE) will evaluate to true.
    {
 
    exec ("say The cost is merely "+moneystring(amt*IRON_MULT, TRUE)+
 
        ", get them first.", self);
 
    goto start;
 
    }
 
  
category:= u1.value[0];
+
  You thus know that Mary has in fact received the mushroom. It is NOT possible
craft:= u1.value[1] / 5 + 4; // / 5 + 4 is to get corresponding craft_text val
+
  to block (using the 'block' command) these commands since they have already
 +
  been executed at the time of notification. In a 'get' command, medium would
 +
  be a unitptr to where the unit was taken from, and target would be the object
 +
  which was taken.
  
if (craft < 0) craft := 0;  if (craft > 9) craft := 9;
+
  See the file commands.txt for a description of how the arguments are set for
 +
  each command. If you can not find a command in there, just ask to get it
 +
  implemented. Especially you should pay attention to the non-obvious SFB_DONE
 +
  command(CMD_AUTO_ENTER).
 +
</PRE>
 +
<hr><a name="sfbtick">
 +
<PRE>
 +
SFB_TICK          Timer message
  
// Change the following to use skill_text(craft) instead of itoa(craft)
+
  When this flag is set, the routine gets activated by a "clock". The clock
if (u1.objecttype == ITEM_WEAPON)
+
  ticks (in 1/4th of a second) are determined by the 'heartbeat' variable.
    buf := "say The "+u1.name+" is a "+weapon_name(category)+" of "+
 
        craft_text.[craft]+" craftmanship and material.";
 
  
if (u1.objecttype == ITEM_ARMOR)
+
    'activator'... is null.
    buf := "say The "+u1.name+" is made of "+arm_text.[category]+" and is of "+
+
    'argument'.... will be empty.
        craft_text.[craft]+" craftmanship and material.";
 
  
if (u1.objecttype == ITEM_SHIELD)
+
      command(CMD_AUTO_TICK) will evaluate to TRUE.
    buf := "say The "+u1.name+" is a "+shi_text.[category]+" shield of "+
+
<hr><a name="sfbcom">
        craft_text.[craft]+" craftmanship and material.";
+
SFB_COM            Combat message
  
exec (buf, self);
+
  When this flag is set, the routine gets activated whenever a combat is in
 +
  progress. The unit containing the DIL program needs not be involved in the
 +
  combat itself:
  
goto start;
+
    'activator'... is a unitptr to the PC/NPC about to hit someone else.
 +
    'argument'.... is empty.
  
}
+
      command(CMD_AUTO_COMBAT) will evaluate to TRUE.
 +
<hr><a name="sfbdead">
 +
SFB_DEAD          Death message
  
dilend</nowiki>
+
  When this flag is set, the routine gets activated when a PC or NPC dies:
If this DIL function scares you don't worry you don't have to
 
understand it or adjust it you only have to use it.  In fact this is a
 
really easy DIL to use.  It only has one argument which is 'amt', the integer value of money you want the evaluator to charge when a
 
person evaluates their stuff.  So to use this function it would look
 
like this on an NPC.
 
<nowiki>
 
dilcopy evaluate@function (5*GOLD_PIECE);</nowiki>
 
this tells the evaluate DIL to charge 5 gold pieces each time a player
 
evaluates something.  For more information on the money see the money
 
field.
 
  
All released DIL NPC functions are described in
+
    'activator'... will point to the PC/NPC that is about to die.
(Link to npcdilfunc).
+
    'argument'.... is empty.
Then we put some to work so you can see how
 
to use them in (Link to npccomplex)
 
;defensive
 
: This field sets the NPC natural defense. The defense is a natural bonus the NPC gets when being attacked. If this value is set high enough the NPC becomes almost indestructible. You should use the macro to set the NPC natural attack and defense in (Link to npcmacroattdef).
 
;offensive
 
: This field sets the NPC natural offense. The offense is a natural bonus the NPC gets when being attacked. If this value is set high enough the NPC can do some serious damage when attacking.  You should use the macro to set the NPC natural attack and defense in (Link to npcmacroattdef).
 
;mana
 
: This sets the NPC max mana points. Using this field you can create special NPCs that have more or less mana points than the VME server would normally give when a NPC is loaded.
 
  
this field is simple all you have to do to set it is put the 'mana'
+
      command(CMD_AUTO_DEATH) will evaluate to TRUE
keyword followed by the amount of mana points you want the NPC to have as
 
its max.  The following definition would make an NPC with only 100 mana
 
points no matter what level.
 
<nowiki>
 
mana 100</nowiki>
 
;hit
 
: This sets the NPC max hit points.  Using this field you can create special NPCs that have more or less hit points than the VME server would normally give when a NPC is loaded.
 
  
this field is simple all you have to do to set it is put the 'hit'
+
  The SFB_DEAD message is sent, just as the character dies, while his items are
keyword followed by the amount of hit points you want the NPC to have as
+
  still equipped, just before the corpse is created.  The character's '.fighting'
its max.  The following definition would make an NPC with only 100 hit
+
  field points to his primary opponent, although this person does not necessarily
points no matter what level.
+
  have to be the one that killed him.
<nowiki>
 
hit 100</nowiki>
 
;money
 
: The money field is how you give your NPC money to have while going along its marry way through your world.  The money field is an integer that tells the VME how much money the NPC is carrying.  It would however be hard to calculate the amount you want on an NPC with out the macros we have provided.  For example to put 5 gold on an NPC you would have to use the following on your NPC.
 
<nowiki>
 
money 25600</nowiki>
 
I of course am not sure this will make 5 gold pieces since I did
 
the math in my head and with all this righting I am doing my math mind
 
doesn't seem to be working right.  So to make life easier for you and me
 
we have added some macros to help that are rather self
 
explanatory.
 
<nowiki>
 
IRON_PIECE
 
COPPER_PIECE
 
SILVER_PIECE
 
GOLD_PIECE
 
PLATINUM_PIECE</nowiki>
 
Now if we wanted to make a NPC carrying five gold it would be as
 
simple as this:
 
<nowiki>
 
money 5*GOLD_PIECE</nowiki>
 
the macro method also gains you the ability to tell the VME what
 
amount of each coin you want on the NPC.  If you set it using a single
 
integer the compiler would pick how many of each coin.  This of course
 
is not what is desired in fact you want to be able to set your money
 
however you like.  So setting more than one coin is as simple as adding
 
a comma between the first and second coin.
 
<nowiki>
 
money 5*GOLD_PIECE, 20*IRON_PIECE</nowiki>
 
;exp
 
: By default a monster gives 100% of the experience it is worth.
 
This amount is calculated according to the level of the NPC verses the
 
level of the person fighting it.  Sometimes the amount of experience is
 
not right since the NPC is really hard to kill for example a dragon with
 
breath weapon and heal at the same level as a merchant with a dagger.
 
These should of course give different experience.  The 'exp' field is
 
designed to do just that.  The possible range for the 'exp' field is
 
-500% to 500%.  If you put the NPC at a negative experience value it
 
will take experience away when it is killed. If you want the default of
 
100% you do not even need to place this field in your NPC.
 
<nowiki>
 
//add 50% to the experience gained
 
exp 150
 
  
/subtract 150% from the experience gained
+
  This can be exploited by making items wiz invisible (the .minv field) just as
exp -50</nowiki>
+
  the message is received, causing them to stay inside the player rather than
;sex
+
  being transferred to the corpse. This does both give the ultimate crash
: Gender, one of these:
+
  protection, as well as a means of letting items, such as bribe items, forever
<nowiki>
+
  be a part of the player (remember to make it un-wizinvis when the player
SEX_NEUTRAL
+
  returns from heaven - players should not have access to items while in heaven).
SEX_MALE
+
</PRE>
SEX_FEMALE</nowiki>
+
<hr><a name="sfbmsg">
the values are pretty obvious which is which gender so all we will
+
<PRE>
show here is how to set it.
+
SFB_MSG            User message
<nowiki>
 
//Setting a male NPC
 
sex SEX_MALE</nowiki>
 
;level
 
: When  creating a NPC it must be between level 0 and  199.  The level  of the NPC decides how many skill points  and  ability points the NPC has.  It, along with the 'exp' percentage, determines the amount of experience gained when the NPC is killed. To set the level of the NPC you use the 'level' keyword and then follow it by the level you are setting.
 
<nowiki>
 
//set a NPC to level 50
 
level 50</nowiki>
 
;race
 
: The 'race' keyword is what you use to set the characters race.
 
Races in VME are defined by using an integer that lets the spells and
 
skills act differently for each specific type.  The VME comes standard
 
with many races defined in the ''values.h''.  For
 
ease in access we have provided them in (Link to app-c). For now
 
you can look at the short list below taken from the over all
 
race list.
 
<nowiki>
 
#define RACE_RAT            1102
 
#define RACE_HORSE          1103
 
#define RACE_BADGER        1104
 
#define RACE_SKUNK          1105
 
#define RACE_BOAR          1106
 
#define RACE_MOUSE          1107
 
#define RACE_MONKEY        1108
 
#define RACE_PORCUPINE      1110
 
#define RACE_ELEPHANT      1112
 
#define RACE_CAMEL          1113
 
#define RACE_FERRET        1114</nowiki>
 
If for example you wanted to make a monkey you could simply put
 
the 'race' keyword and follow it by the monkey define like this:
 
<nowiki>
 
race RACE_MONKEY</nowiki>
 
If the race your looking for doesn't exist in the
 
''values.h'' list, you can either add one buy picking a
 
number not already used and creating your own define in the
 
''values.h'' or by adding the define to your zone.
 
Defines added to a single zone will not be accessible if another builder
 
wants to use it.  You could also just set it using a number.  The
 
following two methods would act the same.
 
<nowiki>
 
//add define to values.h and use in your zone
 
#define RACE_SPACE_TROLL  5059
 
race RACE_SPACE_TROLL
 
  
//Just plug in a number
+
  When this flag is set, the routine gets activated when a message is passed
race 5059</nowiki>
+
  to it. Messages can be passed with the DIL commands 'sendto' and 'send':
If you don't use the macros things can get confusing really fast with
 
the amount of races there are.
 
;attack
 
: This field sets the NPCs natural attack type.  Do not use this field directly instead use the macro described in (Link to npcmacroattarm)
 
;armour
 
: This field sets the NPCs natural armour type.  Do not use this field directly instead use the macro described in (Link to npcmacroattarm)
 
;speed
 
: Speed determines the NPCs speed.  The range is one to twelve.  You should not set this when compiling an NPC since the result is really undefined.  If you have a special NPC that you want to try to make move faster and hit faster then you could try setting this. This field is mainly added so DIL can adjust speed.  The lower the number the faster the NPC speed.
 
<nowiki>
 
//fastest speed.
 
speed 0
 
  
//slowest speed
+
    'activator'... is a unitptr to the unit sending the message.
speed 12</nowiki>
+
    'argument'.... is a string containing possible data from the sender.
;position
 
: This field sets the position that the NPC will be in when it is first loaded. The following positions are recognized by the compiler.
 
<nowiki>
 
POSITION_DEAD
 
POSITION_MORTALLYW
 
POSITION_INCAP
 
POSITION_STUNNED
 
POSITION_SLEEPING
 
POSITION_RESTING
 
POSITION_SITTING
 
POSITION_FIGHTING
 
POSITION_STANDING</nowiki>
 
Some of these positions make no sense you would not load a
 
  NPC into a fight or you would not load an NPC that is already dead.
 
  The positions are availible for DIL and you will need to read the DIL
 
  manuals to find out what you would want those for. For now the
 
  following are enough.
 
<nowiki>
 
  POSITION_SLEEPING
 
POSITION_RESTING
 
POSITION_SITTING
 
POSITION_STANDING</nowiki>
 
The position combined with the default position determines what
 
will be shown when a player looks in the room. If the position of the
 
NPC matches its default position the NPC description will be shown. If
 
it doesn't match the NPCs title and position will be shown. The
 
default value for both 'position' and 'default' is 'POSITION_STANDING'
 
  
To set the position like with other fields you type the 'position'
+
      command(CMD_AUTO_MSG) will evaluate to true.
keyword first and follow it by the position you are setting.
 
<nowiki>
 
position POSITION_SITTING</nowiki>
 
;default
 
: The default position along with the position determines what is shown when a NPC is in each position.  If the position and default positions match the 'descr' field is shown.  If they do not match the NPC title is shown along with the current position information.  If
 
'default' is not set it defaults to 'POSITION_STANDING'.  The following
 
are possible default positions.
 
<nowiki>
 
    POSITION_DEAD
 
POSITION_MORTALLYW
 
POSITION_INCAP
 
POSITION_STUNNED
 
POSITION_SLEEPING
 
POSITION_RESTING
 
POSITION_SITTING
 
POSITION_FIGHTING
 
POSITION_STANDING</nowiki>
 
Setting the default field is exactly like setting the 'position'
 
field you place the 'default' keyword first and then the position you
 
want to be default like this:
 
<nowiki>
 
default POSITION_RESTING</nowiki>
 
;ability
 
: this field is used to set each of the NPCs abilities.
 
It should not be used directly but instead set through the macro described
 
in (Link to npcmacroability)
 
;weapon
 
: this field is used to set each of the NPCs weapon proficiencies.
 
It should not be used directly but instead set through the macro described
 
in (Link to npcmacroweapspl)
 
;spell
 
: this field is used to set each of the NPCs spells.
 
It should not be used directly but instead set through the macro described
 
in (Link to npcmacroweapspl)
 
;light
 
: The light field on NPC is not normally set.  If however you have a strange creature like a 'light bug' you can set a light value on a NPC.
 
The default light is set to 0 which means it neither adds or subtracts
 
from the rooms light.  To set the light value on a NPC you just put the
 
'light' keyword first and then the value you want to add to the current
 
light.
 
<nowiki>
 
//add one to light in room
 
light 1
 
  
//default
 
light 0
 
  
//take one away
+
  Messages are normally not generated by actions performed by the owner of the
light -1</nowiki>
+
   program. For a program to be able to be aware of messages from the owner, a
;alignment
+
  keyword 'aware' should be listed just after 'dilbegin'.
: This field   is  a value between -1000 and +1000,  where  -1000  is ultimate  evil, 0 is neutral and +1000 is ultimate good.  Good  is per  definition any value from +1000..+350, neutral is  any  value from  +349..-349 and evil is any value from -350..-1000. Any value in between can also be used.
 
<nowiki>
 
// Quite evil, maybe a Ghoul
 
alignment -750
 
  
// Barely evil.
+
  When a unit is saved, normally, the DIL programs in it would restart when the
alignment -350
+
  program is loaded. However it is possible to let DIL programs recall their
 +
  execution from where they left off when they where saved.  This is done by
 +
  listing the keyword 'recall' after the 'dilbegin'. This is however a bit
 +
  limited.  Only the status of the original template are saved. Not the state
 +
  inside a template called as a function or procedure from inside the original
 +
  template. 'secure' and interrupts are not recalled upon loading the template.
  
//barely good
 
alignment 350</nowiki>
 
;minv
 
: This field is the administrator invisible level of the NPC it is set on.  This means that if you set the 'minv' to two hundred it will make it so the NPC can not be seen by anyone below the administrator level of two hundred.  This is good for hiding ghosts that only come visible when they attack.  In order for the 'minv' to be removed an administrator or a DIL function must change it.
 
<nowiki>
 
minv 239</nowiki>
 
;key
 
: Currently this field is not used in the VME 2.0 release.  It was added so in the future you wanted to add keys to a NPC for some weird reason like a living trunk then you can.  In order to set the key you first place the 'key' keyword and then add the symbolic name of the key.
 
<nowiki>
 
//if the key is in your zone
 
key mynpckey
 
  
//if the key is in some other zone
+
<b>Example:</b>
key someoneelses@keyzone</nowiki>
 
;open
 
: this field is not used yet in the VME 2.0 release.  The field was added so you could make a NPC that can be opened, closed, locked,
 
and everything else that a room or an object can have set on it.  For
 
now we will not document this but if you are interested in how you could
 
use it study the open fields on objects or rooms.
 
  
=== NPC macros ===
+
<i>dilbegin recall aware mute();
==== The attack and armour macro ====
+
var
 +
  i : integer;
  
The natural attack and armour fields allow you to set the NPC to
+
code
do damage like a certain type of weapons and to defend like a certain
+
{
type of armour respectively.  Lets say you had a metal cougar it would
+
  i:=10;
have an attack type of claw and an armour type of plate while a normal
+
  while (i>0)
dog would have an armour type of leather and an attack type of bite.
+
  {
The 'NATURAL_DEF' macro is what allows you to set these fields.  This
+
      wait(SFB_CMD,command(CMD_SAY) or command(CMD_SHOUT));
macro is defined in ''wmacros.h'' and looks like
+
      exec("emote tries to make a sound, but only blood spurts through"+
this.
+
          "the lips",self);
<nowiki>
+
      block;
#define NATURAL_DEF(weapon_category, armour_category) \
+
      i := i - 1;
  armour armour_category \
+
   }
  attack weapon_category</nowiki>
 
The word natural can sometimes be a little confusing since you can
 
set any of the weapons types you like on the NPC.  It doesn't exactly
 
make sense to have a dog that attacks as if it uses a long sword but if
 
you wish it you can do it.  The following is a short list of just the
 
natural weapon types but you can find a full list in
 
(Link to app-d) or in the ''values.h'' of your mud
 
just in case you have added some weapon types.
 
<nowiki>
 
#define WPN_FIST        34
 
#define WPN_KICK        35
 
#define WPN_BITE        36
 
#define WPN_STING        37
 
#define WPN_CLAW        38
 
#define WPN_CRUSH        39</nowiki>
 
Again you don't have to use leather for dogs as we have already
 
mentioned with our metal cat idea you could make a cloth dragon if you
 
really want but its up to you to keep some sanity on your VME.  The
 
following is the list of armour types that can be set.  You will see
 
that the list is exactly the same as the list you will find later when
 
making armour.
 
<nowiki>
 
#define ARM_CLOTHES  0  /*Same as a Human in jeans and a T-shirt*/
 
#define ARM_LEATHER  1 /* A soft flexible leather base armour  */
 
#define ARM_HLEATHER 2  /* A hard un flexible leather base armour */
 
#define ARM_CHAIN    3  /* A flexible armour composed of interlocking rings */
 
#define ARM_PLATE   4  /* An un flexible plate armour. */</nowiki>
 
Now that you have the defines to work with we will return to our
 
metal cat and normal dog.  The definitions for them would look something
 
like this.
 
<nowiki>
 
//Metal Cat
 
NATURAL_DEF(WPN_CLAW, ARM_PLATE)
 
  
//normal dog
+
  i:=10;
NATURAL_DEF(WPN_BITE, ARM_LEATHER)</nowiki>
+
  while (i>0)
You  should  know  that the weight of the monster  determines  the
+
  {
maximum  amount of damage it can give when using a natural attack.
+
      wait(SFB_CMD,command(CMD_SAY) or command(CMD_SHOUT));
The weight is categorized as follows:
+
      exec("emote tries to make a sound, but can't",self);
{| class="wikitable"
+
      block;
|+Weight size chart
+
      i := i - 1;
|-
+
  }
!LBS
 
!Size
 
|-
 
|0 - 5
 
|Tiny
 
|-
 
|6 - 40
 
|Small
 
|-
 
|41 - 160
 
|Medium
 
|-
 
|161 - 500
 
|Large
 
|-
 
|500 and up
 
|Huge
 
|}
 
By default monsters are medium.  So make sure you take this into
 
account when you are creating your NPC.
 
==== The defense and offense bonus macro ====
 
  
There comes a time when you may want to make your NPC super
+
  i:=10;
naturally powerful.  It is for those times that the offense and defense
+
  while (i>0)
fields are available for you to set.  Normally they default to 0 but you
+
  {
can set them from 0 to 5000.  The higher you set the offense number the
+
      wait(SFB_CMD,command(CMD_SAY) or command(CMD_SHOUT));
harder you will hit people you a re in combat with.  The higher you set
+
      exec("emote tries to make a loud sound, but can't",self);
the defense the harder it will be for people to hit your NPC.  The
+
      block;
following macro allows you to set both the offense and defense.
+
      i := i - 1;
<nowiki>
+
  }
#define ATTACK_DEFENSE(attack, defense) \
+
  quit;
offensive attack \
+
}
defensive defense</nowiki>
+
dilend</i>
Using this macro is rather easy you just put the value you want
 
for each and your all done
 
<nowiki>
 
//a really hard hitting hard to kill NPC
 
ATTACK_DEFENSE( 1000, 1000)</nowiki>
 
==== The NPc abilities macro ====
 
  
All  abilities are in the range [1..200]. Players usually  have  a
+
/* When attached to a PC, the pc will be unable to utter a sound the first 10
maximum of 150, modified by magic... 200 is considered divine.
+
  sound command, and blood will spurt out.
When  creating a monster you can not directly specify the size  of
+
  The next 10 sound commands, the victim just can't shout.
the abilities,  instead you specify a percentage distribution  of
+
  The last 10 sound commands only say will work.
points.  The amount of points are then distributed by the computer
+
  In the end, 'quit' removes the program all together.
according  to  the specified level. The  'MSET_ABILITY' macro  is
+
  The smart thing is that the 'aware' keyword lets the program receive messages
available for this purpose, and is defined as:
+
  from the owner (player) commands. Secondly, the keyword 'recall' makes sure
<nowiki>
+
  that the program does not start over, if the victim quits in the middle, but
#define MSET_ABILITY(str,dex,con,hpp,bra,cha,mag,div)  \
+
  restart at the position it had attained.
ability[ABIL_STR]  str  \
+
  Do not put in the 'aware' if it is not needed. It saves some interpretation
  ability[ABIL_DEX]  dex  \
+
  time not having to pass the extra messages.
  ability[ABIL_CON]  con  \
+
*/
  ability[ABIL_HP]  hpp  \
+
</PRE>
  ability[ABIL_BRA]  bra  \
+
<hr><a name="sfbpre">
  ability[ABIL_MAG]  mag  \
+
<PRE>
  ability[ABIL_DIV]  div  \
+
SFB_PRE            Command preprocessing
  ability[ABIL_CHA]  cha</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">
 
Note the sum of the ability values must be 100%. This is thus
 
an example of an ability distribution:
 
<nowiki>
 
    MSET_ABILITY(25,15,10,15,10,5,10,0)  /* Sum is 100% */</nowiki>
 
</blockquote>
 
  
The  amount of points distributed depends directly upon the  level
+
  When this flag is set, the program is activated by a few special events
of the monster and the percentage.  If the percentage is too high and the
+
  which can then be blocked or changed. Currently, this event is triggered
level is also set High some ability points may be lost since a NPC gets
+
  just prior to a spell being cast, and just prior to any sort of damage
all abilities over 255 cut off. For example a level 199 monster with an  ability
+
  being given to a target.
percentage  a  bit above 20% will make an ability  above  the  255
 
points maximum.  In the current combat system in the VME 2.0 it is not
 
necessary to spend points on both 'mag' and 'div' on the NPC since only
 
one or the other is ever used depending on which is higher.
 
==== The NPc weapon and spell macros ====
 
  
NPCs know about weapons and spells but not at the same detailed
+
   PRE "command(CMD_CAST)"
level as the player.  For NPCs the spell and weapon group are used.
 
Thus the Axe hammer category defines all defence and all attack for all
 
kinds of axes and hammers, whereas the player would have to train
 
individually in each axe and hammer type. The same is true for spells.
 
Thus if a monster has 25 points in the weapon sword category it will
 
fight (and defend) with all sword-like weapons at skill 25. When you
 
define weapon and spell skills (monsters have no skill skills) you also
 
define these as percentages, and the program automatically distributes
 
the points. Use the pre-defined macros:
 
<nowiki>
 
#define MSET_WEAPON(axe_ham, sword, club_mace, pole, unarmed, special)  \
 
weapon[WPN_AXE_HAM]    axe_ham   \
 
weapon[WPN_SWORD]      sword      \
 
weapon[WPN_CLUB_MACE]  club_mace  \
 
weapon[WPN_POLEARM]    pole \
 
weapon[WPN_UNARMED]    unarmed    \
 
weapon[WPN_SPECIAL]    special</nowiki>
 
{| class="wikitable"
 
|+MSET_WEAPON arguments
 
|-
 
!Argument
 
!Description
 
|-
 
|axe_ham
 
|any hammer or axe
 
|-
 
|sword
 
|any sword like weapon, including dagger and rapier, etc.
 
|-
 
|club_mace
 
|any club or mace like weapon, flails,  morning star, etc.
 
|-
 
|polearm
 
|any spear or pole like weapon:  spear, trident, sickle, scythe etc.
 
|-
 
|unarmed
 
|Is any bite, claw, sting or other natural attack.
 
|-
 
|special
 
|any very peculiar weapon, currently only whip.
 
|}
 
<nowiki>
 
#define MSET_SPELL(div, pro, det, sum, cre, min, hea, col, cel, int, ext)  \
 
spell[SPL_DIVINE]      div  \
 
spell[SPL_PROTECTION]  pro  \
 
spell[SPL_DETECTION]  det  \
 
spell[SPL_SUMMONING]  sum  \
 
spell[SPL_CREATION]    cre  \
 
spell[SPL_MIND]        min  \
 
spell[SPL_HEAT]        hea  \
 
spell[SPL_COLD]        col  \
 
spell[SPL_CELL]        cel  \
 
spell[SPL_INTERNAL]    int  \
 
spell[SPL_EXTERNAL]    ext</nowiki>
 
{| class="wikitable"
 
|+MSET_SPELL arguments
 
|-
 
!Argument
 
!Description
 
|-
 
|div
 
|Covers all divine sphere spell.
 
|-
 
|pro
 
|Covers all protection sphere spells.
 
|-
 
|det
 
|Covers all detection sphere spells.
 
|-
 
|sum
 
|Covers all summoning spells.
 
|-
 
|Cre
 
|Covers all creation spells.
 
|-
 
|min
 
|Covers all mind spells.
 
|-
 
|hea
 
|Covers all heat spells (fireball, etc.)
 
|-
 
|col
 
|Covers all cold spells (frostball, etc.)
 
|-
 
|cel
 
|Covers all cell (electricity) spells (lightning bolt, etc.)
 
|-
 
|int
 
|Covers all internal (poison) spells (toxicate, etc.)
 
|-
 
|ext
 
|Covers all external (acid) spells (acid ball etc).
 
|}
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">If your not sure what your weapon or spell is categorized as you can look in the ''weapons.def'' or the ''spells.def'' for that you are using for your VME server.</blockquote>
 
The sum of all spell and weapon
 
skills must be 100%. For example, the following would be a legal
 
setting of weapons and spells.
 
<nowiki>
 
//  75%  Total,  Club/Mace  is primary
 
      MSET_WEAPON(10,10,20,5,15,5)
 
  
//  25%  Total,  Fire  is primary
+
  Assume a a spell is cast from player A on player B with a scroll C.
      MSET_SPELL(8,0,0,3,0,3,2,3,3,3,3)</nowiki>
 
Remember that the groups define both attack and defence.  Thus  if
 
you  make  an Orc which has 0% in the flail group it can only  use
 
its  dexterity to defend itself. Likewise with spell  groups.  For
 
this  reason  the groups are both "resistance" as well  as  attack
 
groups.
 
==== Using the composed.h ====
 
  
The  file composed.h contains many standard monsters. It is a good
+
    'activator'... is a unitptr to A.
idea  to study these definitions, as they form the basis of  many
+
    'medium'  ... is a unitptr to C.
different  monsters. Note that the definitions  by  no  means  are
+
    'target'  ... is a unitptr to B.
perfect,  but  we  are hoping to make a more  or  less  complete
 
monster  compendium. If  you create certain  (general)  monsters,
 
please design it as a macro so it can be incorporated in  the
 
file. The more monsters created by using these macros the easier it will
 
be for your builders to create NPCs. If you think you have a really
 
all inclusive Composed.h and want to share it with the rest of the VME
 
servers running out there on the internet. Feel free to submit it to
 
the VME staff and we will put it in the contribution directories on our
 
release site.
 
  
<blockquote style="background-color: #E8E8E8; font-style: italic; ">For more information on how to use the composed.h when building your NPC see (Link to npcbasic).</blockquote>
+
    command(CMD_CAST) will evaluate to TRUE.
=== Building your first NPC ===
 
  
Now that you have built your first zone with rooms its time to
+
    'argument'.... will contain a number followed by any
populate it with Non playing characters for your players to hunt, kill,
+
                    argument to the spell itself. You should
and or interact with. In the last couple of sections you have looked
+
                    parse this number, it equals the spell number SPL_XXX.
through the fields. In this section we are going to make a nice easy
+
    'power' ....  is set to 'HM', i.e. how powerful the spell cast
NPC and then show how to use the ''composed.h'' to make
+
                    is going to be. YOu can change this number at will.
your NPC building easier. As I have previously stated in the section on
+
                    If you decide to block the spell, you ought to set it
room building I like dragons so the first NPC your going to learn to
+
                    to -1.
build is a big bad ugly dragon.  Don't worry if you hate dragons or you
 
just want to build a normal world you will learn plenty from my dragon
 
example to be able to adjust it to whatever you want.
 
  
When making NPCs you create the zone source file first as shown
+
Example:
in (Link to ch-02).  If you only have NPCS you do not need the
+
  wait(SFB_PRE, command(CMD_CAST));
%reset, %objects, and %rooms fields.  For the examples in this chapter we
 
will use the zone we created in (Link to ch-04) and add the
 
%mobiles section where we will put all the NPC definitions.  At the end
 
of this chapter, in (Link to roomnpczone), we will bring it all together with the rooms we have
 
already defined and our NPCs.
 
  
The first part of all NPC definitions is the symbolic name it is good
+
  s := getword(argument);
to always pick a name that will match the name of the NPC so it
+
  splno := atoi(s);
will be easy to load the NPC.
 
The reason the symbolic and name should match is when you use the
 
command '''wstat''' it will only show you a
 
list of the NPCs by symbolic name for example if you type '''
 
wstat zone dragon mobiles ''' You will get the following:
 
<nowiki>
 
List of mobiles in zone Dragon:
 
dragon clerk trashman</nowiki>
 
If you didn't make it clear what the NPC was by the symbolic name
 
it might look like this:
 
<nowiki>
 
List of mobiles in zone Dragon:
 
npc1 npc2 npc3</nowiki>
 
While this might be great when you first start imagine trying to
 
remember each NPC if you have over 30 of them.
 
  
Now lets get started with our dragon.  As with the rooms all that is required to make a NPC is the symbolic and end fields.  That of course will make a NPC with all defaults.
+
  if (splno == SPL_FIREBALL_3)
<nowiki>
+
    power := 0; /* No damage */
bldragon
+
  ...
end</nowiki>
 
Thats it for that dragon right?  Nope not quite that makes a NPC
 
with all defaults. That means this will probably be a very wimpy human
 
with a symbolic name of dragon and no description, in short it will be a
 
blank when you load it. Now lets start putting the Dragon
 
together.
 
  
The first three things we need are the dragons title, description
 
and names.  The description should be what you see when you do a 'look'
 
in the room.  The title should be what you see when the NPC is talking
 
or fighting.  Finally the names should cover everything in the title and
 
description fields so if you wanted to kill them you can easily
 
know what to type.
 
<nowiki>
 
bldragon
 
  
title "a black dragon"
+
  PRE "command(CMD_AUTO_DAMAGE)"
descr "A big ugly black dragon is clawing the ground here."
 
names {"big ugly black dragon","ugly black dragon","big black dragon",
 
"black dragon","dragon"}
 
...
 
end</nowiki>
 
The names, title and description shouldn't be to hard so I don't
 
think its necessary to go into any more description on the subject.
 
Lets move on.  Now we have to take care of what a player sees when he or
 
she looks at a NPC.  to make the main description of an NPC you place an
 
extra on the NPC with no names in the list.  The blank extra is a
 
special extra that will be shown every time you look at anything in the
 
names list of the NPC.  So a description of a NPC would look something
 
like this.
 
<nowiki>
 
extra {}
 
"The black dragons scales glitter like black granite that has been
 
polished for years by water.  He has a large neck and huge bat like
 
wings.  his eyes watch you as you stand before him.  One claw seems to be
 
tapping slightly on the ground as if the dragon is waiting for
 
something."</nowiki>
 
Now that you have a main description for the NPC you need to make
 
any smaller descriptions that you want the player to be able to look at.
 
In this case the dragon eyes and claw would be good things to describe
 
and maybe a few other things just for humor.
 
<nowiki>
 
extra {"eyes","eye"}
 
"The dragons eyes seem to follow you no matter where you go in the room
 
nothing seems to escape the dragons attention."
 
  
extra {"claws","claw"}
+
  Assume that damage is given from player A to player B with a sword C.
"The claw is big black and it looks very deadly.  It seems like the
 
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
 
to say means the claws are about the size of short swords and long
 
swords."
 
  
extra {"scales","scale"}
+
    'activator'... is a unitptr to A.
"Its a scale!  Haven't you ever seen a dragon before!"
+
    'medium'  ... is a unitptr to C.
 +
    'target'   ... is a unitptr to B.
  
extra {"bat wings","wings"}
+
    command(CMD_AUTO_DAMAGE) will evaluate to TRUE.
"The dragon sees you looking and flaps his wings creating one heck of a
 
wind blast."</nowiki>
 
Now that we have the NPC all described we should start setting
 
    things like race, gender, level, height, weight, defense, offense,
 
    alignment, abilities, and finally skills and spells.  First we will pick a race.  Normally the
 
    list of races are in your ''values.h''.  We have
 
    the list in (Link to app-c) and I have searched for dragon
 
    and found the race I want it is as follows.
 
<nowiki>
 
race RACE_DRAGON_BLACK</nowiki>
 
If you don't think there is any difference in dragons you can
 
set them all to one race like you could define a race called
 
'RACE_DRAGON' or something like that.
 
  
Now we should chose the gender of our dragon. Make sure your
+
    'power' ....   is set to how much damage will be given. You can change
descriptions match what you pick. It would be pretty weird to have a
+
                    this number at will, but you should not set it to less
female dragon and have the descriptions say 'he, him, or his'
+
                    than zero.
<nowiki>
 
    sex SEX_MALE</nowiki>
 
Now lets set the height and weight.  Remember you set the height
 
in centimeters and the weight in pounds.  In the future the VME will
 
standardize to one or the other but for now we have to play the
 
conversion game.
 
<nowiki>
 
//20 feet  (1 inch = 2.54 cm
 
height 625
 
  
//566 KG (1 lb. = .45359 kg)
+
    'argument'.... will contain three numbers that you must parse to
weight 1250</nowiki>
+
                    determine what kind of damage we're talking about.
Now that we have the size of the dragon we can pick a level.
 
My dragon is only 20 feet tall and 1250 pounds so I think maybe he
 
is a bit young and will make his level around 70.
 
<nowiki>
 
level 70</nowiki>
 
The dragon may not wear armour but by default a dragon should
 
have an armour equal to someone wearing plate mail.  Not only that
 
but my dragon doesn't like to use his mouth as his natural attack
 
and he sure can't punch with those big claws so we need to set his
 
attack type to claw.
 
<nowiki>
 
NATURAL_DEF(WPN_CLAW, ARM_PLATE)</nowiki>
 
Not many black dragons are good so I will pick almost totally
 
evil, since totally evil is -1000 I will set it as follows.
 
<nowiki>
 
alignment -900</nowiki>
 
Finally we get to the hard part. Many people have trouble
 
setting the NPC abilities, weapons, and spells. There really is nothing
 
to it if you have read (Link to npcmacroability) and (Link to npcmacroweapspl).  The only thing you have to remember is the
 
numbers you are putting are not the actual amount but a percentage of
 
the skill points you want the game to use on your NPC when having your
 
NPC practice as it loads and all amounts of abilities must add up to
 
100% as well as all weapons and spells must add up to 100%.  For the
 
dragon the following would be what the abilities, weapons, and spells
 
would look like.
 
<nowiki>
 
//big strong and magical most ability points on str and mag
 
MSET_ABILITY(20,12,12,12,12,12,20,0)
 
  
//Set natural attack highest of weapons because he fights with claws
+
                    First number is the attack group, this can be one of
MSET_WEAPON(10,10,10,5,30,5)
+
                    MSG_TYPE_XXX from values.h and/or vme.h.
  
//black dragons have natural defense from acid set it highest
+
                    Second number is dependant on the attack group and
MSET_SPELL(0,0,0,0,0,0,0,0,0,0,30)</nowiki>
+
                    identifies what damage compared to the group. For
That is all you need to make a basic dragon.  True this dragon
+
                    example WPN_XXX for weapon group.
will not do anything but claw you to death if you attack it but in (Link to npccomplex) we will give the dragon some more abilities with
 
some special DIL functions. For now lets take a look at our finished
 
product.
 
<nowiki>
 
bldragon
 
  
title "a black dragon"
+
                    Third number is the body hit location, one of WEAR_XXX,
descr "A big ugly black dragon is clawing the ground here."
+
                    (but not all of them, just hands, feet, legs, body, head,
names {"big ugly black dragon","ugly black dragon","big black dragon",
+
                    arms, i.e. the armour positions, not positions like finger
"black dragon","dragon"}
+
                    or ear).
  
extra {}
 
"The black dragons scales glitter like black granite that has been
 
polished for years by water.  He has a large neck and huge bat like
 
wings.  his eyes watch you as you stand before him.  One claw seems to be
 
tapping slightly on the ground as if the dragon is waiting for
 
something."
 
  
extra {"eyes","eye"}
+
Example:
"The dragons eyes seem to follow you no matter where you go in the room
+
  wait(SFB_PRE, command(CMD_AUTO_DAMAGE));
nothing seems to escape the dragons attention."
 
  
extra {"claws","claw"}
+
  s1 := getword(argument);
"The claw is big black and it looks very deadly.  It seems like the
+
  grpno := atoi(s1);
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
 
to say means the claws are about the size of short swords and long
 
swords."
 
  
extra {"scales","scale"}
+
  s2 := getword(argument);
"Its a scale!  Haven't you ever seen a dragon before!"
+
  atkno := atoi(s2);
  
extra {"bat wings","wings"}
+
  s3 := getword(argument);
"The dragon sees you looking and flaps his wings creating one heck of a
+
  hitloc := atoi(s3);
wind blast."
 
  
race RACE_DRAGON_BLACK
+
  if (grpno == MSG_TYPE_SPELL)
sex SEX_MALE
+
  {
height 625
+
      if ((s2 == SPL_FINGER_DEATH))
weight 1250
+
      {
level 70
+
          act("Your scarabaeus lights up as it protects your life force.");
NATURAL_DEF(WPN_CLAW, ARM_PLATE)
+
          power := -1;
alignment -900
+
          block;
MSET_ABILITY(20,12,12,12,12,12,20,0)
+
      }
MSET_WEAPON(10,10,10,5,30,5)
+
  }
MSET_SPELL(0,0,0,0,0,0,0,0,0,0,30)
+
  ...
  
end</nowiki>
 
As you can see there is a bit more to building an NPC than a room
 
but its really not that much harder.  Try changing some stuff and make
 
sure to practice debugging your errors the more compiling you do the
 
better you will get.
 
=== Compiling and debugging your first NPC ===
 
  
As we have previously mentioned in (Link to rmdebug) it is
+
<hr>
always a good idea to build one or two things and then compile to make
+
<b><i>A note upon activating a DIL program</i></b>
finding errors easy.  In this case we have one NPC to compile and rather
 
than having all the rooms get in my way while compiling it I have
 
removed them and only have the '%mobiles' section.  The following is
 
what the zone looks like when it has only one NPC in it.
 
<nowiki>
 
#include &lt;composed.h&gt;
 
%zone dragonst
 
lifespan 20
 
reset RESET_ANYHOW
 
creators {"whistler"}
 
  
notes
+
This is what you can't do:
"This is the dragon station I shortened it to dragonst for ease in
 
loading.  If you have  any questions email me at whistler@valhalla.com"
 
  
help
+
  If a DIL program is already active, e.g. it is sending a message or
"Not sure what could help you now. You are stuck on one of the
+
  perhaps using "exec" to perform an action, then it can not be activated.
weirdest space stations you have ever seen and you smell burning
+
  Thus, any active DIL program is unable to catch further messages.
sulfur."
+
  Imagine this setting:
  
%mobiles
+
  You have five program P1..P5. P1 sends a message, which is intercepted
 +
  by P2. P2 now sends a message, but since P1 is busy it can not process
 +
  the message. P3..P5 are however possible candidates.
 +
  Assume P3 sends a message, and P4 acts upon it. P4 now sends a message
 +
  and the ONLY program which can catch it is P5, since all the other programs
 +
  are "busy". If P5 sends a message no-one can act upon it. When P5
 +
  returns, so does P4, P3, P2 and finally P1.
 +
</PRE>
 +
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name="built_in">
 +
<h3><b>Built-in Variables:</b></h3>
 +
<PRE>
 +
'cmdstr'<a name="cmdstr">
 +
  This variable is a string which contains the "command" which was entered
 +
  by a player. The result of adding:
  
bldragon
+
      cmdstr + " " + argument
  
title "a black dragon"
+
  is the entire string as entered by the player.
descr "A big ugly black dragon is clawing the ground here."
+
  The 'cmdstr' is EXPANDED by the interpreter, so assume a player
names {"big ugly black dragon","ugly black dragon","big black dragon",
+
  types 's' then the string is expanded to 'south'.
"black dragon","dragon"}
+
</PRE>
 +
<PRE>
  
extra
+
'excmdstr'<a name="excmdstr">
"The black dragons scales glitter like black granite that has been
+
  This variable is a string which contains the "first string" which was entered
polished for years by water.  He has a large neck and huge bat like
+
  by a player. The result of adding:
wings. his eyes watch you as you stand before him.  One claw seems to be
 
tapping slightly on the ground as if the dragon is waiting for
 
something."
 
  
extra {"eye","eyes"}
+
      excmdstr + " " + argument
"The dragons eyes seem to follow you no matter where you go in the room
 
nothing seems to escape the dragons attention."
 
  
extra {"claws","claw"}
+
  is the entire string as entered by the player. The 'excmdstr' is not
"The claw is big black and it looks very deadly. It seems like the
+
  EXPANDED by the interpreter, but it is converted to lower case. So
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
+
  assume a player types 'S' then the string is returned as 's'.  The
to say means the claws are about the size of short swords and long
+
  'excmdstr' is however changed to all lower case if you don't want
swords."
+
  this see 'excmdstr_case'.
 +
  </PRE>
 +
  <PRE>
 +
'excmdstr_case'<a name="excmdstr_case">
 +
  This variable is a string which contains the "first string" which was entered
 +
  by a player. The result of adding:
  
extra {"scales","scale"}
+
      excmdstr_case + " " + argument
"Its a scale!  Haven't you ever seen a dragon before!"
 
  
extra {"bat wings","wings"}
+
  is the entire string as entered by the player.
"The dragon sees you looking and flaps his wings creating one heck of a
+
  The 'excmdstr' is not changed in anyway from how a player types it.
wind blast."
+
  If a player types 'S' then the 'excmdstr_case' will have 'S' in it.
 +
  </PRE>
 +
  <PRE>
 +
      <hr><a name="self">
 +
'self'
 +
  This variable is a unitptr to the unit owning the DIL program.
 +
  For C++ people, this is like the 'this' pointer.
 +
  For example, if Mary has a program, then self.title equals
 +
  "Mary the Lumberjack wife"
 +
</PRE><PRE>
 +
<hr><a name="activator">
 +
'activator'
 +
  This variable is a unit pointer to the unit which activated the DIL
 +
  program. It is set if 'activator' issued a command or unknown command
 +
  and the program was setup to catch it, with : wait (SFB_CMD...).
 +
  See description of messages for more information.
 +
</PRE><PRE>
 +
<hr><a name="targ">
 +
'target'
 +
  This variable is a unit pointer to the unit which is the target of the
 +
  current operation. For 'done' messages this could for example be the
 +
  destination in a give command.
 +
  See description of messages for more information.
 +
</PRE><PRE>
 +
<hr><a name="medium">
 +
'medium'
 +
  This variable is a unit pointer to the unit which was used during an
 +
  operation. For 'done' messages this could for example be a bag which
 +
  was the medium in a get operation.
 +
  See description of messages for more information.
 +
</PRE><PRE>
 +
<hr><a name="power">
 +
'power'
 +
  This variable is an integer which can be reassigned. It is used in
 +
  permission messages and in a few done messages. For example a permission
 +
  request to damage a person with 100 damage would have power equal 100.
 +
  This could then be reduced to 50 by assigning a new number.
 +
  See description of messages for more information.
 +
</PRE><PRE>
 +
<hr><a name="argu">
 +
'argument'
 +
  This variable is a string, showing the argument of a command resulting
 +
  in the activation of the DIL program. See SFB_CMD for example.
 +
</PRE><PRE>
 +
<hr><a name="hb">
 +
'heartbeat'
 +
  This is the DIL programs heartbeat. It can be assigned runtime to
 +
  change the rate with which SFB_TICK is activated. Do not set it
 +
  too low, and remember that it is specified in 1/4th of a second.
 +
  use the constant PULSE_SEC to multiply your wanted delay, for
 +
  Example:
 +
      heartbeat := PULSE_SEC*25; /* Tick every 25 seconds */
 +
</PRE><PRE>
 +
<hr><a name="null">
 +
'null'
 +
  This is a null pointer.
 +
</PRE><PRE>
 +
<hr><a name="weather">
 +
'weather'
 +
  This is the state of the mud-weather. It will equal one of the
 +
  SKY_XXX values in values.h and/or vme.h.
 +
</PRE><PRE>
 +
<hr><a name="bvrealtime">
 +
'realtime'
 +
  This variable returns the number of seconds passed since 1970 something.
 +
  For C buffs this is equivalent to time(NULL).
 +
</PRE><PRE>
 +
<hr><a name="mmmm">
 +
'mudday'
 +
'mudhour'
 +
'mudmonth'
 +
'mudyear'
 +
  These variables lets your program keep track of the time in the mud.
 +
  They all have integer types.
 +
</PRE><PRE>
 +
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name="const">
 +
<h3><b>DIL constructs:</b></h3>
  
race RACE_DRAGON_BLACK
+
DIL offers a set of construct for you to program with.
sex SEX_MALE
+
</PRE><PRE>
height 625
+
<hr><a name ="dcif">
weight 1250
+
<b>if:</b>
level 70
+
    The if statement is much like C. It takes any type as
NATURAL_DEF (WPN_CLAW, ARM_PLATE)
+
    argument. Non integers are considered 'TRUE' if they are
alignment -900
+
    not null.
MSET_ABILITY(21,12,12,12,12,12,20,0)
 
MSET_WEAPON(10,10,10,5,30,5)
 
MSET_SPELL(0,0,0,0,0,0,1,0,0,0,30)
 
  
end
+
<b>Example:</b>
  
%end</nowiki>
+
<i> dilbegin foo();
I removed the '%rooms' section added a '%mobiles' section and
+
  code
stuck the dragon in and now its ready to be compiled and put into the VME
+
  {
server for you to be able to look at it in the game. If you downloaded
+
    if (self.hp>10)
our example zones for this document you can compile this zone along with
+
    {
us and fix the errors as we do for practice.  The filename is
+
      exec("say Hehe!",self);
''debug_npc.zon''.  Just so you know the errors in this
+
    }
zone are intentional so please don't write me an email telling me that
+
    else
there are errors in it.
+
    {
 +
      exec("say ouch!", self);
 +
    }
 +
  }
 +
  dilend</i>
  
The command to compile the zone is
+
<b>Example:</b>
'''VMC debug_npc.zon'''.
 
Here is what we get when we first try and
 
compile the zone.
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_npc.zon'
 
debug_npc.zon: 32: parse error
 
  Token: 'extra'
 
debug_npc.zon: 55: parse error
 
  Token: 'alignment'
 
Compilation aborted.</nowiki>
 
This error file doesn't look any harder than the last one we dealt
 
with when compiling our first room.  The problem is when we go to line
 
'32' and look for an error we don't find one.  This normally means that
 
the error was hard for the compiler to figure out.  The best way to deal
 
with an error like this is to start at the line it gives you and go up
 
and look for an error.  When we do this we notice that the extra right
 
above the line that the error is on is missing '{}' so we will add them
 
back in.  Most of the time you want to do one error and recompile but
 
sometimes you can shorten the process for example in this error file
 
the word 'alignment has been spelled wrong so we can fix that before we
 
recompile so go to line '56' and fix that.  Now with those two errors
 
fixed we can recompile and this is what we get:
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_npc.zon'
 
FATAL: Abilities in 'bldragon' sums up to 101,and not 100.
 
FATAL: Spells&amp;weapons in 'bldragon' sums up to 101, and not 100.
 
WARNING: Fatal errors in zone.</nowiki>
 
As we have said before you have to make sure that abilities add up
 
to 100 percent this error is telling us that my math sucks and that I
 
have added 1 extra percent to the abilities.  Not only that but again if
 
we look at both errors I have also put 1 extra on weapons and spells.
 
So we can fix both of these at once.  Notice it doesn't give a line
 
number but that is not a problem because you can search for 'MSET_ABIL'
 
and it will take you right to the problems.  After I subtract one from the
 
abilities and one from either the spells or weapons the following is the
 
error file I get.
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_npc.zon'
 
VMC Done.</nowiki>
 
Notice there are no errors and it says 'VMC done', this means that
 
you have now successfully compiled the zone. The main thing I want to
 
point out is that you can sometimes fix more than one error at a time
 
but be carefull when doing this if you try to fix some errors before
 
fixing the first you will be trying to fix things that are not broken.
 
The safest way to compile stuff is still fix one error at a
 
time.
 
  
Now that you have a compiled zone you should check and make sure
+
  <i>dilbegin foo();
that all the files are there.  When you compile a zone you will end up
+
  code
with  three extra files. the files will have the same filename as your zone
+
  {
with a new extension in this case you should have the following.
+
    if (self.loaded>10)
<nowiki>
+
    {
debug_npc.data
+
      exec("say its getting crowded!",self);
debug_npc.err
+
    }
debug_npc.reset
+
  }
debug_rm.zon</nowiki>
+
  dilend</i>
If you have all of these you are all set to go.  If not then there
 
is something seriously wrong and you may want to write the VME staff for
 
help.
 
  
  To get your new zone in the mud all that is needed is to make
+
<b>Example:</b>
sure your zone is in the zonelist in the VME etc directory and copy
 
these files into your zone directory.  Then reboot the mud.  You should
 
be able to log on your builder character and load your NPC by typing
 
'''load bldragon@dragonst''' and
 
you can list your zones NPCs by typing '''wstat zone dragonst
 
mobiles'''.
 
  
There you go you have now compiled your first NPC.  As you can see
+
  <i>dilbegin foo();
with as little as you have learned so far you can already make a variety
+
  code
of monsters and NPCs of any kind. The next section will cover the DIL
+
  {
functions you can use with a NPC and then we will get right into some
+
    if (self.loaded<10)
more complex examples.
+
      exec("say plenty of room!",self);
=== DIL functions for NPCs ===
+
  }
 +
  dilend</i>
  
The DIL language is the language a builder can use to make his own
+
<hr>
special functions on rooms, NPCs, objects, PCs, and much more.  This
+
</PRE><PRE>
manual is for basic zone writing and therefore will not go into how to
+
<b>goto:</b><a name ="dcgoto">
write your own DIL functions. The VME however is released with many
+
    The goto statement lets you jump about in the code.
functions for you as an Administrator and your builders to use to make
+
    Labels in your DIL programs, for 'goto' or interrupts
special rooms, NPCs, and objects.  The following is a list of all NPC
+
    are defined within ':'. For an example, see the program below.
functions released with the VME 2.0 server.
 
  
 +
<b>Example:</b>
  
;Mercenary
+
  <i>dilbegin foo();
: This function allows you to make an NPC hireable by players in the game.  You simply dilcopy this unto a mob and the player can then type 'contract &lt;character name&gt;
+
  code
and the mob will hunt that char for a fee. This function takes no special
+
  {
arguments.  the following is the function definition found in
+
    :mylabel:
''function.zon'':
+
    exec("say Hello world",self);
<nowiki>
+
    pause;
dilbegin mercenary_hire();</nowiki>
+
    goto mylabel;
To use it you simply dilcopy it to your NPC as follows:
+
  }
<nowiki>
+
  dilend</i>
dilcopy mercenary_hire@function();</nowiki>
 
;Obey
 
: This function when dilcopied on the NPC will make it obey there master.  And example mobile of this is the familiar. Upon completing a small quest a Mage receives a familiar that will obey that player and that player only. The player can simply type '''Tell &lt;familiar name&gt; cast heal
 
&lt;player name&gt;''' and it will carry out the command.  This function takes
 
no arguments.  The following is the definition found in
 
''function.zon'':
 
<nowiki>
 
dilbegin obey();</nowiki>
 
To use this function simply dilcopy it to the NPC you want to be a
 
mercenary like so:
 
<nowiki>
 
dilcopy obey@function();</nowiki>
 
;Evaluate
 
: This function when placed on an NPC allows it to evaluate items for a fee.  The function definition looks as follows:
 
<nowiki>
 
dilbegin evaluate (amt:integer);</nowiki>
 
The function has one argument 'amt' that lets you set the cost of
 
the evaluation of items.  If you wanted to set the value to four gold it
 
would work just like when setting the money field and look as
 
follows:
 
<nowiki>
 
dilcopy evaluate@function(4*GOLD_PIECE);</nowiki>
 
;Guard Direction
 
: This is an enhanced version of the Guard Way Function. It will allow both certain players to enter as well as certain mobs. An optional stop DIL can be supplied if you wish to do something special. It takes two arguments, the activator and the direction.  The following is the function definition:
 
<nowiki>
 
dilbegin guard_dir(direction : string, excludepc : stringlist,
 
                  excludenpc : stringlist, stopdil : string);</nowiki>
 
This function is dilcopied onto the mob in the room that the mob is initially
 
loaded. Thus is the mob is summoned or commanded away it will not block the
 
directions until it is back to where it was first created. This DIL takes four
 
arguments. The first is the direction to block. The second arguments is for those
 
PC's you wish to allow to pass in that direction without being stopped.  The next
 
for the NPCs you wish to allow to pass. The last is the 'act you wish the blocking
 
mob to display to the PC's that are blocked from proceeding in the selected direction.
 
The third and forth arguments may be 'null', this will pass the defaults to the
 
dilcopy.  The third argument is a stringlist that tells which players
 
or NPCs are excluded from the guard.  The forth is a DIL you can pass in
 
to do something special to people who are stopped.  We will not show how
 
to use the forth argument because it takes more DIL knowledge than this
 
manual covers.  The following would be a valid dilcopy for this
 
function:
 
<nowiki>
 
dilcopy guard_dir@function("south", {"papi",
 
{"rejji"}, null, null);</nowiki>
 
;Combat magic
 
: This function when placed on a mobile allows it to use any of the combat spells.  The function definition is as follows: It also allows the NPC to cast heal during combat on itself.
 
<nowiki>
 
dilbegin combat_mag(atk_spl : string, def_spl : string,
 
                    def_pct:integer, spd: integer);</nowiki>
 
{| class="wikitable"
 
|+Combat magic arguments
 
|-
 
!argument
 
!Type
 
!description
 
|-
 
|atk_spl
 
|string
 
|Attack spell ie "fireball" or "" for none
 
|-
 
|def_spl
 
|string
 
|Defense Spell ie "heal" or "" for none
 
|-
 
|def_pct
 
|integer
 
|At what % of hitpoints defense spell will be cast
 
|-
 
|spd
 
|integer
 
|speed at which mob will uses its attack magic, 1 for all
 
at once (every round) to 5 for every 5 rounds. I suggest 2.
 
|}
 
Defense spells take priority when the hit points fall below the % specified,
 
after (if) the hits have been restored above that number attack magic will
 
resume.  If def_spl is used, function automatically makes sure that it retains
 
enough mana for at least one healing, ie it will attack 4 times if it don't
 
need a healing.  The following would be an example of what you would put
 
on your NPC:
 
<nowiki>
 
dilcopy combat_mag@function ("harm", "heal", 25, 2);</nowiki>
 
;Fido
 
: This function turns the NPC into a corpse eating mobile.  The following is the functions definition:
 
<nowiki>
 
dilbegin fido(txt1:string,txt2:string);</nowiki>
 
{| class="wikitable"
 
|+Fido arguments
 
|-
 
!Argument
 
!Type
 
!description
 
|-
 
|txt1
 
|string
 
|The text shown when mob finds and eats corpses, default:
 
                        'XXX savagely devours a corpse.'
 
                  will be shown if txt1 is set to "".
 
                  If txt1 is set to "stop", the mob will NOT devour corpses
 
                  (convenient if you want your dogs to only eat food leftovers
 
                  but not corpses).
 
|-
 
|txt2
 
|string
 
|The text shown when mob finds and eats ITEM_FOOD, default:
 
                        'XXX hungrily devours YYY.'
 
                  will be shown if txt2 is set to "".
 
                  If txt2 is set to "stop", the mob will NOT devour
 
                  ITEM_FOOD (convenient if you want to make a corpse-eating
 
                  ghoul, who'd choke on normal food, etc).
 
|}
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">In both cases $1n is the mob itself, $2n is the title of the item devoured.</blockquote>
 
  
An example of the 'fido' function on an NPC would look as
+
<hr>
follows:
+
<b>while:</b><a name ="dcwhile">
<nowiki>
+
    The while statement lets you execute a series of
dilcopy fido@function("$1n slowly devours $2n, crunching the bones.",
+
    statements while an expression evaluates to TRUE.
                      "$1n grabs $2n and hungrily munches it.");</nowiki>
 
;Wander zone
 
: This function allows a mob to wander around more than one zone, but not all zones.
 
You specify what zones the mob can wander.  Has optional intelligence which allows
 
the opening and closing of doors.  The following is the function
 
definition:
 
<nowiki>
 
dilbegin wander_zones(zones : string, spd : integer, doors : integer,
 
                      lckd_doors : integer);</nowiki>
 
{| class="wikitable"
 
|+Zone wander arguments
 
|-
 
!argument
 
!Type
 
!description
 
|-
 
|zones
 
|string
 
|A string of zone names separated by spaces.
 
|-
 
|spd
 
|integer
 
|The speed (in seconds) at which the mob wanders.
 
                              Minimum = 5 secs (for process time).
 
|-
 
|doors
 
|integer
 
|Can open/close doors (0 = false, 1 = true)
 
|-
 
|lckd_doors
 
|integer
 
|Can open/closed locked doors (0=false, 1=true)
 
|}
 
The options are not too hard so we will show how to use it and
 
leave it at that
 
<nowiki>
 
dilcopy wander_zones@function ("halfzon haon_dor", 5, 1);</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">@loadzone option which is used by inputting @loadzone somewhere in the zones string will replace it by the zone the mob is loaded in like this:
 
<nowiki>
 
dilcopy wander_zones@function ("halfzon haon_dor @loadzone", 5, 1);</nowiki>
 
</blockquote>
 
;Global wander
 
: This is similar to wander_zones because it's just a modified version of it,
 
which requires no zones argument since it moves in all zones.  The
 
following is the function definition:
 
<nowiki>
 
dilbegin global_wander(spd : integer, doors : integer,
 
                      lckd_doors :integer);</nowiki>
 
{| class="wikitable"
 
|+Global wander arguments
 
! Argument
 
! Type
 
! Description
 
|-
 
|spd
 
|integer
 
|The speed (in seconds) at which the mob wanders. Minimum = 5 seconds (for process time).
 
|-
 
|doors
 
|integer
 
|Can open/close doors (0 = false, 1 = true)
 
|-
 
|lckd_doors
 
|integer
 
|Can open/closed locked doors (0=false, 1=true)
 
|}
 
  
The options are not to hard so we will show how to use it and
+
<b>Example:</b>
leave it at that
 
<nowiki>
 
dilcopy global_wander@function (60, 1, 1);</nowiki>
 
;Team work
 
: This function when placed on a mob, located in the same room as another mob,
 
will allow the mobile to assist the other in combat.  The following is
 
the function definition:
 
<nowiki>
 
dilbegin aware teamwork(lst: string);</nowiki>
 
This function takes one argument which is a string of the mobiles it is
 
to protect. So if we wanted a NPC to protect both Jesper and Enver the
 
dilcopy would look as follows:
 
<nowiki>
 
dilcopy teamwork@function("jesper/enver");</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">For this to work both mobs must be in the same room or following each other.</blockquote>
 
;Rescue
 
: This function when placed on a mob, located in the same room as another mob,
 
will allow the mobile to rescue the other mob if it is attacked.  The
 
function is as follows:
 
<nowiki>
 
dilbegin aware rescue(lst: string);</nowiki>
 
This function takes one argument, a string of those mobiles
 
you wish this NPC to assist should they be attacked.
 
  
<blockquote style="background-color: #E8E8E8; font-style: italic; "> For this to work both NPCs must be in the same room or following each other.</blockquote>
+
  <i>dilbegin foo();
 +
  code
 +
  {
 +
    while (not self.inside) {
 +
      exec("say I own nothing", self);
 +
      pause;
 +
    }
 +
    exec("say ahh.. now i own something", self);
 +
  }
 +
  dilend</i>
  
  Again we will use our test subjects Jesper and Enver and if
+
<hr>
we wanted an NPC to protect them and come to their aid the following
+
</PRE><PRE>
would be the dilcopy:
+
<b>break:</b> <a name ="dcbreak">
<nowiki>
+
    The break statement makes you break out of any
dilcopy teamwork@function("jesper/enver");</nowiki>
+
     loop you're currently in.
;Agressive
 
: This function makes a Mob hostile to person(s) in the room with it, under certain conditions which are provided as arguments.
 
In short, the all-singing, all-dancing aggression DIL.  The following is
 
this functions definition:
 
<nowiki>
 
dilbegin aggressive (sx : integer, rce : integer, opp : integer,
 
                    levl : integer, sanc : integer, tme : integer,
 
                    tar : integer, align : string, attack :
 
                    stringlist);</nowiki>
 
{| class="wikitable"
 
|+Agressive arguments
 
|-
 
!argument
 
!Type
 
!description
 
|-
 
|sx
 
|integer
 
|NOTE: not the sex values in values.h.
 
                                This decides the sex of your mob's
 
                                victim.
 
                                0 - Sex doesn't matter,
 
                                1 - Attack opposite sex to self (if not
 
                                    neutral!),
 
                                2 - Attack SEX_MALE,
 
                                3 - Attack SEX_FEMALE,
 
                                4 - Attack SEX_NEUTRAL.
 
|-
 
|rce
 
|integer
 
|Any of the PC races from 0 to 14. A value
 
                                of -1 means we don't care about the
 
                                victim's race.
 
|-
 
|opp
 
|integer
 
|0 - Non race specific (same as rce := -1)
 
                                1 - Attack the specified rce,
 
2 - Attack any pc race _but_ the specified rce.
 
|-
 
|levl
 
|integer
 
|Allow level specific aggression.
 
                                A value of 30 would make the mob hostile
 
                                to all pcs level 30 and above.
 
                                A value of -30 (note the -) would make the
 
                                mob hostile to all pcs level 30 or below.
 
                                A value of 0 means level doesn't matter.
 
|-
 
|sanc
 
|integer
 
|Does this mob obey the sanc/soothe rules?
 
                                (ie, if someone has cast sanctuary on
 
                                themselves, will this mob recognize it, and
 
                                not attack, or attack anyway).
 
                                0 - Doesn't obey sanc or soothe
 
                                1 - Obeys only sanc
 
                                2 - Obeys only soothe
 
                                3 - Obeys both sanc and soothe
 
                                (SOOTHE is a new spell for ranger's guild)
 
|-
 
|tme
 
|integer
 
|Time in ticks to wait before attacking (is
 
                                automatically put to RANTIME, ie, time
 
                                variance of time-time/2 to time+time/2).
 
                                Values accepted are from 0 to 400 (that's
 
                                0 - 100 seconds. Can be specified using
 
                                PULSE_SEC).
 
|-
 
|tar
 
|integer
 
|This is a special value which determines
 
                                which of the eligible victims we pick.
 
                                -2 - Last eligible victim to into the room.
 
                                -1 - Weakest eligible victim in room.
 
                                0  - Random eligible victim.
 
                                +1 - Strongest eligible victim in room.
 
+2 - First eligible victim into the room.
 
|-
 
|align
 
|string
 
|The desired alignment of the victim.
 
                                "ANY"      - We don't care about the alignment.
 
                                "GOOD"     - Attack only good alignment.
 
                                "EVIL"    - Attack only evil alignment.
 
                                "NEUTRAL " - Attack only neutral alignment.
 
                                "OPPOSITE" - Attack opposite alignment to self
 
                                (provided self isn't neutral).
 
"SALIGN" - Attack same alignment as self.
 
                                "DALIGN" - Attack any alignment
 
                                different to self.
 
|-
 
|attack
 
|stringlist
 
|This is a 2 string stringlist. These are
 
                                    the messages sent to the people in the room
 
                                    except the victim, and the victim itself,
 
                                    in that order.
 
                                    If the second (victim) string is "", the
 
                                    first string will be shown to the victim,
 
                                    as if they were anyone else in the room.
 
                                    You can leave both blank if you wish.
 
                                    $1n is the mob name (self), $3n is the
 
                                    victim's name.
 
                                    NOTE: the $ values only apply if you supply
 
                                    BOTH string 1 and 2.
 
|}
 
The argument descriptions pretty much explain everything there is
 
to know about the agressive function and what it was so we will finish
 
off by giving an example of a dilcopy that will create a NPC that fits
 
the following description
 
  
Let's say our mob is a level 40 Goblin who doesn't like
+
<b>Example:</b>
dwarves. He's very particular in that he doesn't like evil female
 
dwarves who are level 20 and above. He does recognize the sanctuary
 
spell, but he doesn't recognize soothe, and he'll wait 10 seconds on
 
average before he attacks. The 2 messages sent are: "$1n savagely
 
attacks $3n with his big axe!" and "$1n attacks you!"
 
  
Here's what the function call would look like:
+
  <i>dilbegin foo();
<nowiki>
+
  code
dilcopy aggressive (3, 2, 1, 20, 2, PULSE_SEC*10, 0, "EVIL",
+
  {
                    {"$1n savagely attacks $3n with his big axe!",
+
    while (self.inside) {
                    "$1n attacks you!"});</nowiki>
+
      if (self.position &lt POSITION_SLEEPING)
In this example, 3 (attack females), 2 (attack dwarves), 1 (just dwarves),
+
        break;
  20 (Level 20+ victims), 2 (obey only soothe), PULSE_SEC*10
+
      exec("say I own something", self);
(wait around 10 seconds before attacking), EVIL (attack only
+
      pause;
evil), and the strings in the stringlist are displayed to
+
    }
the victim and the room, in that order.
+
  }
;Janitors
+
  dilend</i>
: This function turns the NPC into a janitor that will pick up items left lying around and will also tell new  players. those under level 20,
 
where there corpse is if they come across it in there wanderings.
 
You must also supply the wander_zone DIL for this to work correctly.
 
The definition for the janitor function is as follows:
 
<nowiki>
 
dilbegin janitors(rate: integer);</nowiki>
 
The Janitor function only takes one argument and that determines
 
how fast the janitor will pick up stuff in seconds.
 
  
To make a Janitor that will pick up stuff every thirty seconds the
+
<hr>
following would be the dilcopy:
+
</PRE><PRE>
<nowiki>
+
<b>continue:</b><a name ="dccont">
dilcopy janitor@function(30);</nowiki>
+
    The continue statement makes you jump to the top
;Shop Keeper
+
    of any loop you're currently in.
: This is one of the more complex dilcopies and considered by some to be confusing. Below I will step you through the creation of the mobile,
 
and the application of this DIL using defines to hopefully simplify the
 
use of this function.  The function is defined as:
 
<nowiki>
 
dilbegin aware shopkeeper(prod: stringlist, custom_acts : stringlist,
 
                            opentimes : stringlist, itemtype: string,
 
sellprofit : integer,buyprofit: integer,
 
maxcash : integer,closedil : string,
 
dilparams : string );</nowiki>
 
;Step 1
 
: First, figure out what you want your shopkeeper to sell.  He can sell pretty much any item from any zone, as long as you know its symbolic name.
 
For Hogan (our example shopkeeper), he is a bartender, so he sells things
 
you would commonly find in a pub, tavern, or bar.
 
His list of items (their symbolic names at which zone) are:
 
<nowiki>
 
grain_alcohol@gobtown1
 
pretzels@gobtown1
 
beer_nuts@gobtown1
 
rum_coke@gobtown1
 
tuborg@udgaard</nowiki>
 
Now, since I use defines, I make a define for Hogan's products.  I called
 
it TAVERN_PROD (for tavern's products).  And use the following setup
 
and just stick the names of your items in where his items are.
 
Each item will have a setup like this:
 
<nowiki>
 
"tuborg@udgaard 15 20"</nowiki>
 
A symbolic name followed by two numbers, with the entire thing in
 
quotes.  Where :
 
* The "tuborg@udgaard" is your item's symbolic name
 
* The 15 (our first number in the string) is the number of that item that
 
  will load into your shop daily
 
* The 20 (our second number in the string) is the limit available of that
 
  item in the shop ever
 
So this shop would sell tuborgs.. and every mudday, 15 tuborgs will load
 
into our shop to replenish our stock.. and the maximum tuborgs we can have
 
at any given time is 20.
 
  
Next we place all this info into the define we created above, which would look
+
<b>Example:</b>
like this:
 
<nowiki>
 
#define TAVERN_PROD \
 
{"grain_alcohol@gobtown1 15 20", \
 
"pretzels@gobtown1 10 15", \
 
"beer_nuts@gobtown1 15 20", \
 
"rum_coke@gobtown1 10 15", \
 
"tuborg@udgaard 15 20"}</nowiki>
 
The above is my define for Hogan's products that he sells.  Each one is in
 
quotes and they have commas separating them.  If you put each item on its
 
own separate line, you need to put a space and then a back slash after the
 
comma which separates the items, like it shows above.  The entire define
 
is enclosed in curly brackets, {}.
 
Now we are finished with the items he sells.
 
;Step 2
 
: Now you must decide what kind of dialogue you would like your shopkeeper to say.  There are ten separate responses you can make for your shopkeeper.  They do go in a specific order and I will list what each do.
 
  
;Response 1
+
  <i>dilbegin foo();
: The first response will be used if the shopkeeper doesn't have the particular item you're trying to buy in stock, or if he doesn't sell that item at all.
+
  code
;Response 2
+
  {
: The second response is used when the player is trying to sell the shopkeeper something which the player does not have in his inventory. Items worn by the player can not be sold until removed from there worn position.
+
    while (self.inside) {
;Response 3
+
      if (self.position &lt POSITION_SLEEPING)
: The third response is used when the player is trying to sell the shopkeeper something that is not one of those of his trade types. (This will be more clear when we get to the trade type part below. Such as a player trying to sell our bartender a canoe. =)
+
        break;
;Response 4
+
      pause;
: The fourth response is used when the player tries to buy something from the shopkeeper, but doesn't have enough money to buy it.
+
      if (self.hp<0) continue;
;Response 5
+
      exec("say I own something", self);
: The fifth response is used when the sale was successful and the player buys something from the shopkeeper.
+
      pause;
;Response 6
+
    }
: The sixth response is again used when the sale was successful, but this time it's for when the player successfully sells something to the shopkeeper.
+
  }
;Response 7
+
  dilend</i>
: The seventh response is used when the shopkeeper doesn't have enough of the item to sell as the player requests. Such as someone trying to buy 10 tuborgs, but our bartender only has 9.
 
;Response 8
 
: The eighth response is Used when the shop is closed and a player tries to buy something from or sell something to the shopkeeper.
 
;Response 9
 
: The ninth response is used when the player tries to sell an item to the shopkeeper that the shopkeeper doesn't trade that item.
 
;Response 10
 
: The tenth (and last!) response is for when the shopkeeper has run out of money and can't afford to buy what the player is trying to sell him.
 
  
Now. again, I made a define called TAVERN_MSG (for tavern messages) and I
+
<hr>
placed all my responses in it.  Don't forget, they do go in that specific
+
</PRE><PRE>
order!  And below is our setup with responses in it.
+
<b>on <i>n</i> goto <i>la</i>, <i>lb</i>, ..., <i>ln</i>:</b><a name="ongoto">
  
<blockquote style="background-color: #E8E8E8; font-style: italic; ">In the responses below, $1n refers to the shopkeeper, $2n refers to the item being sold, bought, etc.. and $3n refers to the person dealing with the shopkeeper.</blockquote>
+
    This construct is an easy way of performing a goto operation
<nowiki>
+
    based on the result of an integer. The integer value 'n' must
#define TAVERN_MSG \
+
    be zero or positive and less than the number of labels specified
{"$1n says, 'This is a tavern, I don't sell such an item as that!'", \
+
    in the label-list. If n is outside this range, the on-goto operation
"$1n says, '$3n, you don't even have that!'", \
+
    is skipped and execution continues at the next instruction.
"$1n says, 'I don't trade with things such as $2n! Just buy a beer!'", \
 
"$1n says, '$3n, you can't afford $2n.'", \
 
"$1n says, 'Thank you, $3n, here are %s for $2n.'", \
 
"$1n says, 'Thank you, $3n.'", \
 
"$1n says, 'I don't have that many $2ns in stock.'", \
 
"$1n says, 'I'm on break, come back later.'", \
 
"$1n says, 'I haven't got a use for $2n.'", \
 
"$1n says, 'I'd like to buy it, but I can't afford it, sorry.'"} \</nowiki>
 
Just like with the items, the responses are in quotes, and are separated
 
with commas.  Since I put each on their own separate lines (for neatness
 
sake), I put a space and a back slash, \, after each. The entire define is
 
enclosed in curly braces,{}.
 
And then you're done with your shopkeeper's messages!
 
Don't worry, it gets simpler from here.
 
;Step 3
 
: Now we get to decide when we want our shop to be open.  We get to use military time, so 1 refers to 1am, 6 refers to 6am, 12 refers to 12pm
 
(noon), 18 refers to 6pm, and both 0 and 24 refer to 12am (midnight)..
 
etc.. =)
 
And my define for this I named TAVERN_OPEN_TIMES (for when the tavern is
 
open) and I used the following setup:
 
<nowiki>
 
#define TAVERN_OPEN_TIMES {"12","18"}</nowiki>
 
You just have to make your define and stick your times in quotes and
 
enclose them in curly braces.  So Hogan will be opened from 1am ("1")
 
until 11pm ("23").  He will close after 11pm and reopen again at 1am.
 
You may also add multiple open and close times as per the following
 
example:
 
<nowiki>
 
#define TAVERN_OPEN_TIMES {"1","12","16","20"}</nowiki>
 
;Step 4
 
: For this step you get to choose your shopkeeper's trade types.  And what you pick all depends on what kinds of things you want your shopkeeper to sell and buy.  You can find the item types in ''values.h'', but I'll also list them below.
 
{| class="wikitable"
 
|+Sale types
 
|-
 
!Value
 
!Type
 
!Value
 
!Type
 
|-
 
|1
 
|ITEM_LIGHT
 
|14
 
|ITEM_TRAP
 
|-
 
|2
 
|ITEM_SCROLL
 
|15
 
|ITEM_CONTAINER
 
|-
 
|3
 
|ITEM_WAND
 
|16
 
|ITEM_NOTE
 
|-
 
|4
 
|ITEM_STAFF
 
|17
 
|ITEM_DRINKCON
 
|-
 
|5
 
|ITEM_WEAPON
 
|18
 
|ITEM_KEY
 
|-
 
|6
 
|ITEM_FIREWEAPON
 
|19
 
|ITEM_FOOD
 
|-
 
|7
 
|ITEM_MISSILE
 
|20
 
|ITEM_MONEY
 
|-
 
|8
 
|ITEM_TREASURE
 
|21
 
|ITEM_PEN
 
|-
 
|9
 
|ITEM_ARMOR
 
|22
 
|ITEM_BOAT
 
|-
 
|10
 
|ITEM_POTION
 
|23
 
|ITEM_SPELL
 
|-
 
|11
 
|ITEM_WORN
 
|24
 
|ITEM_BOOK
 
|-
 
|12
 
|ITEM_OTHER
 
|25
 
|ITEM_SHIELD
 
|-
 
|13
 
|ITEM_TRASH
 
|
 
|
 
|}
 
We are making a bartender, so he should sell food and drinks. So I
 
selected ITEM_FOOD, and it's corresponding number is 19.  So I made my
 
define TAVERN_ITEM_TYPE (for our tavern's type of items) using the
 
following setup:
 
<nowiki>
 
#define TAVERN_ITEM_TYPE "19"</nowiki>
 
Now, if we had a magic shop, and wanted to sell potions and scrolls, I
 
would make a define called for example MAGIC_ITEM_TYPE and make it like
 
this:
 
<nowiki>
 
#define MAGIC_ITEM_TYPE "2 10"</nowiki>
 
The 2 was our number corresponding to the scrolls, and the 10
 
corresponded to the potions.  That is how you make your shopkeeper
 
sell more than one item type, just stick the corresponding numbers inside
 
quotes with a space separating them.
 
;Step 5
 
: Now you get to decide how much money your shopkeeper gets to have to buy things with.  One platinum piece is equal to 40960.  So if I wanted him to have two platinum pieces to spend on buying things from players, I would make a define called TAVERN_MAX_CASH (for the maximum amount of money our shopkeeper gets) and use the following setup:
 
<nowiki>
 
#define TAVERN_MAX_CASH 81920</nowiki>
 
I got 81920 by multiplying the 40960 (one platinum) by 2
 
;Step 6
 
: The sixth thing we get to do is to decide how much profit does our shopkeeper get when he sells his items.  Items should have a cost to them already tagged on them, so their whatever their cost is, that is equal to 100%. Now, if your shopkeeper wants to take an extra 10% on the items he's selling so he can support his family, then you would make his selling profit 110.  So I made a define called TAVERN_SELL_PROFIT (for his profit when he sells things) and gave him 110% selling profit, and used the following setup:
 
<nowiki>
 
#define TAVERN_SELL_PROFIT 110</nowiki>
 
;Step 7
 
: This last define is almost exactly like our selling profit, but now, we're doing our buying profit... when a player sells an item to the shopkeeper,
 
he doesn't want to pay full price because it must be used since a player
 
has it.  Now the item's cost is 100%, and maybe the shopkeeper only wants
 
to buy items for half its cost.  So I would make his buying profit 50,
 
and use the following setup.
 
<nowiki>
 
#define TAVERN_BUY_PROFIT 50</nowiki>
 
All of the previous  defines you can place anywhere in the zone.  I like
 
to place mine before the %DIL section just to keep them somewhere where
 
I know they all are.  You can place each one on the mob itself, but I
 
think that looks cluttered so's why I put them where I put
 
them.  And you're going to have a dilcopy placed on your mob also, which
 
I'll explain in step 8.
 
;Step 8
 
: Okay one last step.  Now you get to place the DIL on your shopkeeper mob using all of those cute little defines you just made.  The syntax for the DIL is:
 
<nowiki>
 
  dilcopy shopkeeper@function(products, responses, opentimes,
 
                            tradetypes, sellprofit, buyprofit,
 
                            maxcash, closedil, dilparams);</nowiki>
 
Take your defines from above the defines that you made are
 
called:
 
<nowiki>
 
TAVERN_PROD, TAVERN_MSG, TAVERN_OPEN_TIMES, TAVERN_ITEM_TYPE,
 
TAVERN_SELL_PROFIT, TAVERN_BUY_PROFIT, and TAVERN_MAX_CASH.</nowiki>
 
Now all you have to do is place them in the syntax where they belong like
 
in the below example.
 
<nowiki>
 
dilcopy shopkeeper@function(TAVERN_PROD, TAVERN_MSG, TAVERN_OPEN_TIMES,
 
                            TAVERN_ITEM_TYPE, TAVERN_SELL_PROFIT,
 
                            TAVERN_BUY_PROFIT, TAVERN_MAX_CASH, "", "");</nowiki>
 
For the last two fields, I just put "", "" because I don't make my own
 
unique DIL for those.  By just putting and empty set of quotes for each,
 
it makes it go to the default.
 
And make sure you don't forget that semicolon at the end either.
 
  
You are pretty much done now. All you have to do is place your
+
    Based on the value of 'n' execution continues at the label
defines either up before %DIL or somewhere in %mob if you'd like, and
+
    corresponding to number 'n' in the list. I.e. if n is 0, then
place the dilcopy onto your mob.
+
    execution continues at the first specified label, if n is 1
 +
    then at the second, etc. etc.
  
Just to make sure I've completely beaten a very dead horse, this is
 
what it would look like in the end.
 
<nowiki>
 
%zone sample_zon
 
  
#define TAVERN_PROD \
+
<b>Example:</b>
{"grain_alcohol@gobtown1 15 20", \
 
"pretzels@gobtown1 10 15", \
 
"beer_nuts@gobtown1 15 20", \
 
"rum_coke@gobtown1 10 15", \
 
"tuborg@udgaard 15 20"}
 
  
#define TAVERN_MSG \
+
  Assume you have an integer 'i' larger than zero, which takes
{"$1n says, 'This is a tavern, I don't sell such an item as that!'", \
+
  on 0, 1, 2, 3, 4 or 5. Based on each value you need to take a
"$1n says, '$3n, you don't even have that!'", \
+
  different action, this is how you can do it:
"$1n says, 'I don't trade with things such as $2n! Just buy a beer!'", \
+
<i>
"$1n says, '$3n, you can't afford $2n.'", \
+
    on i goto grin, laugh, grin, nada, poke, laugh;
"$1n says, 'Thank you, $3n, here are %s for $2n.'", \
+
    log("Value was not in the range 0..5");
"$1n says, 'Thank you, $3n.'", \
+
    quit;
"$1n says, 'I don't have that many $2ns in stock.'", \
 
"$1n says, 'I'm on break, come back later.'", \
 
"$1n says, 'I haven't got a use for $2n.'", \
 
"$1n says, 'I'd like to buy it, but I can't afford it, sorry.'"} \
 
  
#define TAVERN_OPEN_TIMES {"1","23"}
+
      :laugh:
#define TAVERN_ITEM_TYPE "19"
+
      exec("grin", self);
#define TAVERN_MAX_CASH 81920
+
      goto ...;
#define TAVERN_SELL_PROFIT 110
 
#define TAVERN_BUY_PROFIT 50
 
  
%mobiles
+
      :grin:
 +
      exec("cackle", self);
 +
      goto ...;
  
bartender
+
      :blank:
names {"hogan","goblin","bartender"}
+
      exec("cry", self);
title "Hogan"
+
      goto ...;
descr "Hogan stands behind the bar waiting to take your order."
 
extra {}
 
"He looks back at you, patiently waiting for your order."
 
M_AVG_GOBLIN(76,SEX_MALE)
 
alignment -1000
 
exp 100
 
money 2 SILVER_PIECE, 2 COPPER_PIECE
 
  
dilcopy shopkeeper@function(TAVERN_PROD, TAVERN_MSG, TAVERN_OPEN_TIMES,
+
      :poke:
                            TAVERN_ITEM_TYPE,TAVERN_SELL_PROFIT,
+
      exec("smirk", self);
                            TAVERN_BUY_PROFIT, TAVERN_MAX_CASH, "", "");
+
      goto ...;
end</nowiki>
+
</i>
=== A more complex set of NPCs ===
+
It is often used in this context
 +
<i>
 +
    on rnd(0,4) goto l1, l2, l3, l4, l5;
  
In the last sections you learned all the fields and how to make a basic NPC.
+
    :l1:
In this section we will use the information from the last sections to
+
    bla;
create some more unique NPCs for our dragon station zone There is not a
 
lot of new information here we will be using the DIL functions from the previous
 
section and adding some flags to the NPCs to make them act
 
different.
 
==== Magic casting NPC ====
 
  
The basic Dragon we made in the (Link to npcbasic) looks
+
    :l2:
like a real dragon but it is a bit boring when you fight a dragon and
+
    bla;
don't get toasted by an acid or fire spell or two.  in (Link to npcdilfunc) the 'combat_magic' function was described.  This
 
is the function you use to make all NPCs cast magic while in combat.
 
With that in mind lets take a look at how we can make our dragon a bit
 
more interesting g.
 
  
Well lets see a black dragon is supposed to have the ability to
+
    ....
either cast fire breath or acid breath depending on who you talk to.
 
Once you learn DIL you could even make fire breath be a skill not a
 
spell but for now we will stick with what we know. I like the acts of
 
the acid breath spell so we will use that as the spell of choice. The
 
NPC as we defined it before hasn't changed so the following would be the
 
entire dragon with the combat magic function.
 
<nowiki>
 
bldragon
 
  
title "a black dragon"
+
</i>
descr "A big ugly black dragon is clawing the ground here."
+
</PRE><PRE>
names {"big ugly black dragon","ugly black dragon","big black dragon",
+
<hr><b>foreach:</b><a name="forea">
"black dragon","dragon"}
+
  Foreach is an easy way to process all the units in the
 +
  local environment relative to the 'self' executing the
 +
  foreach. Foreach takes care of creating a list of local
 +
  units, and of securing them. You can use both break and
 +
  continue in a foreach statement. The unit executing the
 +
  foreach ('self') is always a part of the foreach.
  
extra {}
+
      It is important to understand that the units in the local
"The black dragons scales glitter like black granite that has been
+
      environment are relative to the 'self' executing the foreach.
polished for years by water.  He has a large neck and huge bat like
 
wings.  his eyes watch you as you stand before him.  One claw seems to be
 
tapping slightly on the ground as if the dragon is waiting for
 
something."
 
  
extra {"eye","eyes"}
+
<b>Example:</b>
"The dragons eyes seem to follow you no matter where you go in the room
+
    This foreach is copied onto the spell caster, and hence all units
nothing seems to escape the dragons attention."
+
    relative to the spell caster (i.e. self) are processed in the foreach.
 +
    Assume that it was executed on the spell caster's staff, then all units
 +
    found would be relative to the staff, i.e. the spell caster's inventory.
 +
<i>
 +
...
 +
  foreach (UNIT_ST_PC|UNIT_ST_NPC, u)
 +
  {
 +
      if (u.hp < u.max_hp)
 +
      {
 +
        act("Warm raindrops fall upon you, cleaning your wounds.",
 +
            A_ALWAYS, u, null, null, TO_CHAR);
 +
        u.hp := u.hp + 6;
 +
        if (u.hp > u.max_hp)
 +
          u.hp := u.max_hp;
 +
      }
 +
      else
 +
        act("Warm raindrops fall upon you.",
 +
            A_ALWAYS, u, null, null, TO_CHAR);
 +
      pause;
 +
  }
 +
...</i>
  
extra {"claws","claw"}
+
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name="assgn">
"The claw is big black and it looks very deadlyIt seems like the
+
</PRE><PRE>
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
+
<b>Assignment:</b>
to say means the claws are about the size of short swords and long
+
    You can assign values to the variables you declare
swords."
+
    in your 'var' section, and some of the built-in
 +
    variables. This is done by the ':=' operator.
 +
    Note that you can also assign a variable the result
 +
    of an expression
 +
    (the addition of strings below as an example)
  
extra {"scales","scale"}
+
<b>Example:</b>
"Its a scale!  Haven't you ever seen a dragon before!"
 
  
extra {"bat wings","wings"}
+
  <i>dilbegin foo();
"The dragon sees you looking and flaps his wings creating one heck of a
+
  var
wind blast."
+
    myvarsl : stringlist;
 +
    myvars : string;
 +
  code
 +
  {
 +
    :start:
 +
    myvarsl := {"a string","another","the first"};
 +
    myvars := self.name+" XX ";
 +
    myvarsl.[2] := "the last";
 +
    myvarsl.[3] := "illegal";  /* Will not work since [3] is not defined */
 +
    pause;
 +
    goto start:
 +
  }
 +
  dilend</i>
  
race RACE_DRAGON_BLACK
 
sex SEX_MALE
 
height 625
 
weight 1250
 
level 70
 
NATURAL_DEF (WPN_CLAW, ARM_PLATE)
 
alignment -900
 
MSET_ABILITY(20,12,12,12,12,12,20,0)
 
MSET_WEAPON(10,10,10,5,30,5)
 
MSET_SPELL(0,0,0,0,0,0,0,0,0,0,30)
 
  
//Combat Magic added.
+
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name ="express">
  dilcopy combat_mag@function("acid breath", "", 25, 2);
+
</PRE><PRE>
 +
<b>Expressions:</b>
 +
  The expressions used in assignment can return any
 +
  of the types you can declare variables. Also they might return
 +
  fail or null. An expression returning fail will not result
 +
  in any action being taken. Fail is returned when you
 +
  request a field from a null pointer, or the like.
  
end</nowiki>
+
<b>Example:</b>
That is all there is to it.  If you are wondering where I got the
 
'acid breath' part of the DIL copy all the spells names are in the
 
''spells.def'' or you can just pick a spell by what you
 
would type if you wanted to cast it yourself in the game.  Now if this
 
still looks like a lot to do to make a dragon the dragon above could
 
have been created with exactly the same information by using the
 
''composed.h'' and the 'M_DRAGON_BLACK_OLD' macro.  If
 
we use the macro the dragon would look like this
 
<nowiki>
 
bldragon
 
  
title "a black dragon"
+
  <i>dilbegin foo();
descr "A big ugly black dragon is clawing the ground here."
+
  var
names {"big ugly black dragon","ugly black dragon","big black dragon",
+
    myvarsl : stringlist;
"black dragon","dragon"}
+
    myvars : string;
 +
    myvarint : integer;
 +
    myvaredp : extraptr;
 +
    myvarunit : unitptr;
 +
  code
 +
  {
 +
    :start:
 +
    myvarunit := self.inside.next;
 +
    myvarsl := {"a string","another","the last"};
 +
    myvars := self.name+" XX "+itoa(self.hp);
 +
    myvarint := activator.hp;
 +
    myvaredp := "Rabbit Stew Complete" in activator.quests;
 +
    pause;
 +
    goto start:
 +
  }
 +
  dilend</i>
 +
</PRE><PRE>
 +
<hr><a name ="ops">
 +
<b>Operators:</b>
  
extra {}
+
  DIL features many other operators. For integers,
"The black dragons scales glitter like black granite that has been
+
  '<', '>', '<=', '>=', '!=' '==' signify less than,
polished for years by water. He has a large neck and huge bat like
+
  greater than, less or equal, greater or equal, not equal,
wings. his eyes watch you as you stand before him.  One claw seems to be
+
  and equality operators. Furthermore, you can compare
tapping slightly on the ground as if the dragon is waiting for
+
  strings with '==' or '$=' for equality test, and '!='
something."
+
  for non equality. Pointers may also use '==' and '!='
 +
  and you may force DIL to compare pointers, even for
 +
  strings with the '#=' pointer-equality operator.
 +
  The '$=' and '#=' is considered obsolete, and only
 +
  used for backward compatibility.
 +
</PRE><PRE>
 +
<hr><a name ="ein">
 +
<b>in:</b>
 +
The special operator 'in' is a multipurpose operator for
 +
a lot of things. It allows you to search through
 +
quests and extra descriptions, stringlists and search
 +
for words in strings.
 +
</PRE><PRE>
 +
<hr><a name ="esins">
 +
string 'in' string
 +
  Argument 1: A string to find.
 +
  Argument 2: A string to search.
 +
  Return: TRUE, if first string is found in second string.
  
extra {"eye","eyes"}
+
<b>Example:</b>
"The dragons eyes seem to follow you no matter where you go in the room
 
nothing seems to escape the dragons attention."
 
  
extra {"claws","claw"}
+
  <i>dilbegin foo();
"The claw is big black and it looks very deadly. It seems like the
+
  code
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
+
  {
to say means the claws are about the size of short swords and long
+
    if ("guard" in activator.title)
swords."
+
      exec("say hello guard",self);
 +
    pause;
 +
  }
 +
  dilend</i>
 +
</PRE><PRE>
 +
<hr><a name ="esinsl">
 +
string 'in' stringlist
 +
  Argument 1: A string to find.
 +
  Argument 2: A stringlist to search.
 +
  Returns: 1.. if first string is found in stringlist, or 0 if it is
 +
            non existent. If found the number equals the index of the
 +
            string found plus one.
  
extra {"scales","scale"}
+
Example 1:
"Its a scale!  Haven't you ever seen a dragon before!"
+
  s := "c";
 +
  sl := {"a","b","c","d"};
 +
  i := s in sl;
  
extra {"bat wings","wings"}
+
  The result of 'i' is 3, and sl.[i-1] equals "c" (s).
"The dragon sees you looking and flaps his wings creating one heck of a
 
wind blast."
 
  
M_DRAGON_BLACK_OLD(SEX_MALE)
+
Example 2:
  
end</nowiki>
+
  <i>dilbegin foo();
As you can see with the second way the dragon was a lot easier to
+
  code
make because we let the macro set all the other values we just described
+
  {
the NPC and set the macro.
+
    if ("james" in activator.names)
==== A wandering janitor ====
+
      exec("say hello james.",self);
 +
    pause;
 +
  }
 +
  dilend</i>
 +
</PRE><PRE>
 +
<hr><a name ="esine">
 +
string in extraptr
 +
  Argument 1: A string to find.
 +
  Argument 2: An extra description list to search.
 +
  Return: Extraptr to first entry with string matching .names or
 +
          null if none. (names must be exact letter by letter
 +
          match, although case is ignored).
  
Our space station is nice but we wouldn't want a lot of people
+
<b>Example:</b>
coming to visit if we didn't have a janitor to walk around cleaning up.
 
Dragons most likely wouldn't be low life enough to be Janitors so I
 
think we will leave that up to a hobgoblin.  the following would be the
 
definition of a hobgoblin wandering Janitor.
 
<nowiki>
 
janitor
 
names {"ugly janitor", "janitor", "hobgoblin"}
 
title "an ugly janitor"
 
descr "an ugly janitor is walking around, cleaning up."
 
  
extra{}
+
  <i>dilbegin foo();
"This ugly green thing looks more goblin than hobgoblin but he seems
+
  code
intent on cleaning everything around him."
+
  {
 +
    if ("Rabbit Stew Complete" in activator.quests) {
 +
      exec("say wow!, you helped Mary get her stew!", self);
 +
      exec("app ", self);
 +
    }
 +
    pause;
 +
  }
 +
  dilend</i>
  
race RACE_HOBGOBLIN
+
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name ="funcs">
level 6
+
<h3>Functions:</h3>
sex SEX_MALE
+
  DIL features an extended set of built-in functions
height  130      /* cm            */
+
  for extended program control. Built-in functions can be part of
weight  120      /* Pounds        */
+
  any expression in DIL. The built-in functions are
// he is sort of good for cleaning so much
+
  listed later.
alignment 900
 
  
NATURAL_DEF(WPN_FIST, ARM_LEATHER)
+
<b>Example:</b>
MSET_ABILITY(10,10,10,23,15,22,10,0)  \
 
MSET_WEAPON(10,10,10,10,10,10)    /*  Average in everything, any wpn */
 
MSET_SPELL(4,2,2,2,2,2,2,6,6,6,6)  /* Resistances      */
 
  
//give him some money
+
  <i>dilbegin foo();
money 5 IRON_PIECE
+
  code
 +
  {
 +
    exec("say I exist in "+itoa(self.loaded)+"copies", self);
 +
    pause;
 +
  }
 +
  dilend</i>
  
dilcopy janitors@function(15);
+
  DIL also lets you use templates as functions, but in a
 +
  limited way. Using templates as functions, you may only
 +
  use the return value to assign it to one of the variables
 +
  declared in the 'var' section. No fields.
  
// only want him cleaning the station
+
<b>Example:</b>
dilcopy wander_zones@function("dragonst", 20, 1, 1);
 
  
end</nowiki>
+
  <i>dilbegin integer bar(s:string);
Like with the dragon if we wanted to create this NPC easier we
+
  code
would use the Hobgoblin defines in ''composed.h'' so we
+
  {
don't have to fill out all the information.  If we did this it would
+
    exec("say "+s,self);
simply look as follows:
+
    return rnd(1,10);
<nowiki>
+
  }
janitor
+
  dilend</i>
names {"ugly janitor", "janitor", "hobgoblin"}
 
title "an ugly janitor"
 
descr "an ugly janitor is walking around, cleaning up."
 
  
extra{}
+
  <i>dilbegin foo();
"This ugly green thing looks more goblin than hobgoblin but he seems intent
+
  external
on cleaning everything around him."
+
    integer bar(s:string);
 +
  var
 +
    myint:integer;
 +
  code
 +
  {
 +
    myint := bar("rolling the dice.");
 +
    exec("say I rolled a "+itoa(myint));
 +
    pause;
 +
  }
 +
  dilend</i>
  
M_AVG_HOBGOBLIN(6, SEX_MALE)
+
<hr><a name="fquit">
 +
quit:
 +
  This simple command quits the entire DIL program, even if
 +
  called while inside a procedure or function.
  
// he is sort of good for cleaning so much
+
<hr><a name="fret">
alignment 900
+
return:
 +
  Return from a call to a procedure template (no return type
 +
  declared). The execution continues from where the procedure
 +
  was called.
  
//give him some money
+
<hr>
money 5 IRON_PIECE
+
return():<a name="fret2">
 +
  Return from a call to a function (return type declared).
 +
  The expression inside the parenthesis evaluates to the value
 +
  returned.
  
dilcopy janitors@function(15);
+
<hr>
 +
  DIL also allows for game-time *symbolic* resolving of
 +
  function/procedure names. This allows you to pass template names
 +
  as string arguments and call them in your program. This kind of
 +
  function call requires taxing look ups and type check runtime, so
 +
  use the normal kind of procedures if possible.
  
// only want him cleaning the station
+
  In effect, the syntax of a symbolic call is similar to that of
dilcopy wander_zones@function("dragonst", 20, 1, 1);
+
  a normal, except you use a string variable as function name
 +
  instead of the real function name. If the string variable contains
 +
  a valid reference to a procedure/function, and all the argument
 +
  types matches the found templates argument types, the call
 +
  is made. Otherwise, the call is skipped. Note that you will get no
 +
  type check by the compiler when using symbolic references.
  
end</nowiki>
+
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name ="fields">
As you can see you can combine the DIL functions you learned in
+
<h3><b>Fields:</b></h3>
(Link to npcdilfunc) to make your NPC do more than one thing.
+
</PRE><PRE>
==== Creating a teacher ====
+
The 'extraptr' and 'unitptr' types contain information which is available to
 +
you by using fields. For example (self is a unitptr), self.inside is a
 +
unitptr to what is inside the 'self' unit. (Hence '.inside' is the field).
 +
And self.inside.outside is a unitptr to self (assuming that something is
 +
actually inside self, otherwise self.inside would evaluate to null).
 +
Some fields may not be changed by DIL programs directly but must be modified
 +
indirectly using certain procedure calls in DIL. Others may not be changed
 +
at all. All are readable for DIL programs.
  
Setting up teachers on valhalla is harder and more strict formed
+
The extraptr structure is used for several things. The primary is
than most things in the game. The reason is the way you set them up is
+
extra descriptions for units, and quest data. Keywords in the 'names'
to use an old form of functions called special. In the future guilds
+
field and the actual description/data in the 'descr' field.
will be in DIL like everything else but for now the teachers that are
 
released with the VME are base code.  Even though the teachers are base
 
code they still allow for you to adjust many things.  The truth is you
 
don't have to use our teachers you could code your own in DIL but many
 
find this easier.
 
  
Guild teacher definitions are actually less complex than people think
+
In the following (RW) means the value may be assigned new values by DIL,
they are. There really are no big, mysterious secrets. The key is simply
+
while (RO) means the the value only can be read. A (RO) value might be
to understand the numbers and how the balance is achieved.
+
possible to change through built-in functions/procedures
(From here on in, GTD will refer to "guild teacher definition", and
+
<hr>
"entity" will be used to refer to the ability/spell/skill/weapon being
+
<b>The extraptr has the following fields:</b><a name ="extra">
offered by the GTD.)
 
  
<blockquote style="background-color: #E8E8E8; font-style: italic; "> Using TAB characters in GTDs is a very bad idea! It will have extremely adverse effects, including causing the mud to crash.</blockquote>
+
  extraptr:
 +
      'names'        :stringlist (RW)
 +
        names is a list of strings of names, that the extra description matches on.
 +
      'descr'        :string (RW)
 +
        descr is the contents of the extra description.
 +
      'next'        :extraptr (RO)
 +
        next is the next extra description in a list.
 +
      'vals'        :intlist (RW)
 +
        vals is a list of integer values attached to this extra.
 +
</PRE><PRE>
 +
<hr>
 +
The unitptr is the key structure in the MUD, containing any kind of the
 +
following subtypes:
  
We need to tart first and explain that to use the teacher special
+
  object      : a normal object, a sword, a vail, etc.
functions you need to use a field not described anywhere else in the NPC
+
  room        : a room, location or the like.
descriptions.  The field is called a 'special'. The reason the
+
  pc          : a playing character.
'special' field was not included in the field descriptions is because it
+
  npc        : a non playing character (mobile, monster, etc)
is being removed from the VME as soon as banks and teachers have been
+
</PRE><PRE>
replaced by DIL there will be no more special functions. For now
+
<hr>
however we need to use them for the for mentioned purposes. The format
+
<b>The unitptr has the following fields:</b><a name ="unit">
for a special function is as follows:
 
<nowiki>
 
special &lt;Function define&gt; &lt;function arguments&gt;</nowiki>
 
For teachers the function definition is 'SFUN_TEACH_INIT' and the
 
arguments range from who can join, what the acts of the teacher are,
 
and what the teacher teaches.
 
  
In the first part of a SFUN_TEACH_INIT definition, there are several
+
  unitptr:
pieces of important information which allow the mud to know what you are
+
      'names'        :stringlist (RW)
trying to provide to players.  The entire set of arguments are enclosed
+
        A list of names that matches the unit.
in double quotes. So a teacher with nothing at all in it would look
+
      'name'        :string (RW)
like this:
+
        The first name in the namelist in 'names'
<nowiki>
+
      'outside_descr' :string (RW)
special SFUN_TEACH_INIT "&lt;arguments go here&gt;"</nowiki>
+
        The description of the unit from the 'outside'. f.inst.
After the opening double quote ("), the first thing necessary
+
        the description of a boat, seen from the outside.
is the text formatting code '&amp;l', which tells the compiler to ignore the
+
      'inside_descr' :string (RW)
standard text formatting protocols for the rest of the string or until the
+
        The description of the unit from the 'inside'. f.inst.
'&amp;f' code is given.
+
        the description of a boat, seen from the inside.
 +
      'next'        :unitptr (RO)
 +
        The next unit in the local list of units. For instance, the
 +
        units in the inventory of a PC, is linked with this field.
 +
      'title'        :string (RW)
 +
        The title of the unit.
 +
      'extra'        :extraptr (RW)
 +
        Extra descriptions of the unit (identify, look at, read etc.).
 +
      'outside'      :unitptr (RO)
 +
        The outside of the unit hierarchy (carried by, contained by).
 +
        For instance, the contents of a bag have their 'outside'
 +
        field pointing to the bag.
 +
      'inside'      :unitptr (RO)
 +
        The inside of the unit hierarchy (carry, contains).
 +
        For instance the first unit in a PC's inventory is referenced
 +
        by the 'inside' field.
 +
      'key'      :string (RO)
 +
        The key that will open this unitptr
 +
        For instance "big_key@blackzon"
 +
          by the 'inside' field.
 +
      'gnext'        :unitptr (RO)
 +
        Next unit in the global list of units.
 +
      'gprevious'    :unitptr (RO)
 +
        Previous unit in the global list of units.
 +
      'hasfunc'      :integer (RO)
 +
        Returns TRUE if unit has special functions attached to it.
 +
      'max_hp'      :integer (RO/RW)
 +
        The maximum hitpoints of unit, RO for players, RW for mobiles.
 +
      'max_mana'      :integer (RO)
 +
        The maximum mana of the character (player or mobile).
 +
      'max_endurance' :integer (RO)
 +
        The maximum endurance of the character (player or mobile).
 +
      'lifespan'      :integer (RW)
 +
        The lifespan of a character, write permission only on root access.
 +
      'hp'          :integer (RW)
 +
        The current hitpoints of unit. For objects, this can render
 +
        it 'broken' by being set low. If an unit has -1 hitpoints
 +
        its considered unbreakable.
 +
      'manipulate'  :integer (RW)
 +
        Bits that specify how unit can be handled, see MANIPULATE_*
 +
        flags in values.h and/or vme.h
 +
      'flags'        :integer (RW)
 +
        Bits that specify different properties of a unit, see
 +
        UNIT_FL_* in values.h and/or vme.h
 +
      'baseweight'  :integer (RO)
 +
        The empty weight of the unit. This can be set with the
 +
        procedure 'setweight()'
 +
      'weight'      :integer (RO)
 +
        The current weight of the unit (and its contents).
 +
      'capacity'    :integer (RW)
 +
        The amount of weight the unit can contain.
 +
      'height'      :integer (RW)
 +
        The height of a PC/NPC, the length of a rope, the size of weapons,
 +
        armours, and shields.
 +
      'alignment'    :integer (RW)
 +
        The alignment of the unit. [1000..-1000],
 +
        1000 is good, 0 is neutral, -1000 is evil.
 +
      'openflags'    :integer (RW)
 +
        Bits thats specify how a unit may be opened, locked, etc,
 +
        see EX_* in values.
 +
      'light'        :integer (RO)
 +
        How much light is inside the unit.
 +
      'bright'       :integer (RO)
 +
        How much the unit lights up. This can be set with the
 +
        procedure 'setbright()'
 +
      'illum'        :integer (RO)
 +
        How much light units inside a transparent unit create
 +
      'minv'        :integer (RW)
 +
        The 'wizard invisibility' level.
 +
      'spells'[]    :integer (RO)
 +
        The defence/skill of the different spell spheres/spells
 +
        The index should be one of the SPL_* in values.h and/or vme.h
 +
      'zoneidx'      :string (RO)
 +
        The unique database name (in the zone) for this unit.
 +
      'nameidx'      :string (RO)
 +
        The unique database zone name for this unit.
 +
      'idx'      :integer (RO)
 +
        The unique database index (in the zone) for this unit.
 +
        This provides a smart alternative to check for zoneidx
 +
        and nameidx. Thus if (u1.idx == u2.idx) then
 +
        (u1.nameidx == u2.nameidx) and (u1.zoneidx == u2.zoneidx).
 +
        Be warned, this value change between each reboot, so do not
 +
        count on it for purposes of saving.
 +
      'zone'         :string (RO)
 +
        The name of the zone the unit is in.
 +
      'type'        :integer (RO)
 +
        The type of the unit, see UNIT_ST_* in values.h and/or vme.h
 +
      'loadcount'    :integer (RO)
 +
        Returns the number of units loaded in the game
 +
        of this definition (zoneidx,nameidx / idx)
 +
</PRE><PRE>
 +
<b>if the type is UNIT_ST_OBJ</b><a name ="uobj">
  
Immediately following the '&amp;l' code, with no spaces at all, the type of
+
      'objecttype'   :integer (RW)
entity the function will teach is defined. It is one of the following
+
        The type of an object, see ITEM_* in values.h and/or vme.h for types.
types:
+
      'value'[]      :integer (RW)
* abilities
+
        Values for an object. The meaning of the values differ
* spells
+
        from object type to object type. Index should be [0..4].
* skills
+
        These values are used differently for each object type.
* weapons
+
      'objectflags'  :integer (RW)
The first two lines of the SFUN_TEACH_INIT looks like this:
+
        Bits specifying special properties for an object. Some
<nowiki>
+
        combinations may not be logical, see OBJ_* in values.h and/or vme.h
special SFUN_TEACH_INIT
+
      'cost'        :integer (RW)
"&amp;labilities;0;</nowiki>
+
        The basic cost of an object. (old gold value)
<blockquote style="background-color: #E8E8E8; font-style: italic; ">The '0;' is the end of field marker that will be used through out the teacher fields</blockquote>
+
      'rent'        :integer (RW)
 +
        The basic cost of renting an object. Mostly used on very
 +
        special objects. (old gold value)
 +
      'equip'        :integer (RO)
 +
        The position in equipment. This is used by units in a PC/NPC's
 +
        inventory to tell if they are equipped by that PC/NPC.
 +
        use the 'addequip()' and 'unequip()' procedures.
  
The next set of arguments to the teacher function is the acts the
+
<b>if the type is UNIT_ST_ROOM</b><a name ="uroom">
teacher will use when a person is trying to train.  There are seven acts
 
total and they are as follows:
 
==== Teacher acts ====
 
;Line 1
 
: This line is displayed when the player makes a mistake in typing the name of an entity, whether or not it is actually offered at the teacher.
 
;Line 2
 
: This line is similar to the first, but is usually evident of attempting to practice an entity not offered at this particular teacher.
 
;Line 3
 
: This is the act displayed when the player has insufficient funds to practice the desired entity.
 
;Line 4
 
: This is displayed when the player has not got enough ability or skill practice points to learn the desired entity.
 
;Line 5
 
: Simply put, the player has exceeded the teacher's expertise in the offered entity and must go elsewhere to learn more, if at all possible.
 
;Line 6
 
: This line is displayed when the player is either wearing magical,
 
        stat-modifying equipment or is affected by spells/skills which
 
        modify stats.
 
;Line 7
 
: This line is what is shown when your armour affects you using special functions in base code.  This is rare and may never be seen.  In the future when the teachers are made in DIL this act may not be necessary.
 
  
Now we can add the acts to our example it would look as
+
      Note: the descr fields of exits are available as standard extra
follows:
+
        keywords, ie. 'north' ,'east',...,'down'.
<nowiki>
+
        Example:
special SFUN_TEACH_INIT
+
          ex := 'north' in self.extra;
"&amp;labilities;0;
 
$1n tells you, 'I have never heard of such an ability.'; $1n
 
tells you, 'I do not know how to teach this ability.'; $1n tells you,
 
'You haven't got %s for me.'; $1n tells you, 'You haven't got %d ability
 
points.'; $1n tells you, 'I can not teach you any more.'; $1n tells you,
 
'You must be unaffected by magic, else I can't teach you.'; $1n tells
 
you, 'Remove all equipment, please.';</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">
 
  $1n is the substitution variable for the teacher's title (see the DIL
 
document for more details).
 
  
%s is the amount of money the teacher requires to teach the entity in
+
      'exit_names'[]  :stringlist (RW)
      question.
+
        The names matching the exit name 'open grate' The index should
 +
        be one of NORTH EAST SOUTH WEST UP DOWN in values.h and/or vme.h
 +
        Example:
 +
          sl := self.exit_names[SOUTH];
 +
          act("The $2t slides open as you press the button.",
 +
                A_ALWAYS, activator, sl.[0], null, TO_CHAR);
 +
      'exit_info'[] :integer (RW)
 +
        Bits specifying the conditions of the exits, see EX_* in
 +
        values.h and/or vme.h The index should be one of NORTH EAST SOUTH WEST
 +
        UP DOWN in values.h and/or vme.h
 +
      'exit_to'[]    :unitptr (RO)
 +
        The unit, the direction exits to. The index should
 +
        be one of NORTH EAST SOUTH WEST UP DOWN in values.h and/or vme.h
 +
        You may not change the directions through DIL programs.
 +
      'roomflags'    :integer (RW)
 +
        Bits specifying properties of the room, see ROOM_FL_* in
 +
        values.h and/or vme.h
 +
      'movement'    :integer (RW)
 +
        The type of movement in the room, see SECT_* in values.h and/or vme.h
 +
</PRE><PRE>
 +
<b>if the type is UNIT_ST_PC or UNIT_ST_NPC </b><a name ="upcnpc">
  
%d is the amount of ability or skill practice points required to
+
      'speed'        :integer (RO)
      practice the given entity.
+
        The current default combat-speed (as seen by wstat)
 +
      'fighting'    :unitptr (RO)
 +
        The unit the PC/NPC is fighting.
 +
      'master'      :unitptr (RO)
 +
        The unit the PC/NPC is following.
 +
      'follower'    :unitptr (RO)
 +
        The first follower of a PC/NPC. There is currently no way
 +
        of finding other followers, except using a foreach loop in
 +
        the local environment.
 +
      'exp'          :integer (RO)
 +
        The number of experience points for PC, or experience
 +
        quality of monster. The exp can be set by the function
 +
        'experience()'
 +
      'charflags'    :integer (RW)
 +
        Bits specifying by spells affects and other PC/NPC affects,
 +
        and many other things, see CHAR_* in values.h and/or vme.h
 +
      'lastroom'    :unitptr (RO)
 +
        The room the player just left.
 +
      'mana'        :integer (RW)
 +
        The amount of mana a PC/CHAR has left.
 +
      'dex_red'      :integer (RO)
 +
        The amount of DEX reduction the PC/NPC suffers due to
 +
        encumbrance or otherwise.
 +
      'endurance'    :integer (RW)
 +
        The amount of endurance a PC/NPC has left.
 +
      'attack_type'  :integer (RW)
 +
        The non-weapon attack type of a PC/NPC.
 +
      'race'        :integer (RW)
 +
        The race of a PC/NPC, see RACE_* in values.h and/or vme.h
 +
      'sex'          :integer (RW)
 +
        The sex of a PC/NPC, see SEX_* in values.h and/or vme.h
 +
      'level'        :integer (RO)
 +
        The level of a PC/NPC.
 +
      'position'    :integer (RW)
 +
        The position of a PC/NPC, see POSITION_* in values.h and/or vme.h
 +
        affected by the 'position_update()' procedure
 +
      'abilities'[]  :integer (RO)
 +
        The abilities of a PC/NPC. Index should be ABIL_* in values.h and/or vme.h
 +
      'weapons'[]    :integer (RO)
 +
        The weapon skills of a PC/NPC. Index should be WPN_* in values.h and/or vme.h
 +
</PRE><PRE>
 +
<b>if the type is UNIT_ST_NPC </b><a name ="unpc">
  
The standard GTD termination character, a semicolon (;) ends each
+
      'defaultpos'  :integer (RW)
act
+
        The default position of an NPC, see POSITION_* in values.h and/or vme.h
</blockquote>
+
  'natural_armour'  :integer (RW)
 +
    The natural armour of the NPC when naked.
 +
      'npcflags'    :integer (RW)
 +
        Some small options for NPC's see NPC_* in values.h and/or vme.h
 +
      'switched'  :unitptr (RW)
 +
      Character that is switched into this NPC.
 +
</PRE><PRE>  
 +
<b>if the type is UNIT_ST_PC</b><a name ="upc">
  
about the actual GTDs, or the lines that actually define what the
+
      'birth'        :integer (RO)
teachers teach and everything to do about how expensive and how high
+
        The time a PC was created.
they teach itA GTD is a single line, composed of several fields. The data contained
+
  'editing'        :integer (RO)
in these fields determines how a particular entity is practiced.
+
    Is the PC editing?  TRUE for yes FALSE for no.
 +
      'hometown'      :integer (RO)
 +
        The hometown of a PC.
 +
      'pcflags'      :integer (RW)
 +
        The setup of player options. See PC_* in values.h and/or vme.h
 +
      'playtime'      :integer (RO)
 +
        The time a PC has played.
 +
      'skill_points'  :integer (RW)
 +
        The amount of unused skill points the PC has.
 +
      'ability_points' :integer (RW)
 +
        The amount of unused ability points the PC has.
 +
        'exptol' :integer (RW)
 +
        The amount of experience player needs to level
 +
      'skills'[]    :integer (RO)
 +
        The skills of a PC. Index should be SKI_* in values.h and/or vme.h
 +
      'guild'        :string (RW)
 +
        The guild the PC belongs to.
 +
      'prompt'        :string (RW)
 +
        The players prompt string..
 +
      'crimes'      :integer (RW)
 +
        The number of crimes the PC has.
 +
      'full'        :integer (RW)
 +
        How hungry the PC is.
 +
      'thirst'      :integer (RW)
 +
        How thirsty the PC is.
 +
      'drunk'        :integer (RW)
 +
        How drunk the PC is.
 +
      'quests'      :extraptr (RW)
 +
        The quests a PC is finishing/has finished.
 +
      'info'        :extraptr (RW)
 +
        The info structure of a PC.
 +
      'acc_balance' : integer (RO)
 +
        If the game is in accounting mode, then this returns the balance
 +
        of the player, what would be shown on balance in wstat <player> acc.
 +
      'acc_total'  : integer (RO)
 +
        If the game is in accounting mode, then this returns the total
 +
        credit of the player, what would be shown on total in wstat
 +
        &ltplayer&gt acc.
 +
</PRE>
 +
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name="built_func">
 +
<PRE>
 +
<h3>Built-In Functions:</h3>
  
Here is an example of a GTD:
+
    The following are definitions and documentation for the
<nowiki>
+
   built-in functions in DIL. The definitions are not
  0;  100; scan                          ;   9;  9000;  7;          0;</nowiki>
+
  definitions 'as such', but serve to distinguish arguments
Note that it has a lot of white space in it. It is really not necessary,
+
   in the documentation below.
as the field terminators are the semicolons. This means that you could just
 
as easily write:
 
<nowiki>
 
0;100;scan;9;9000;7;0;</nowiki>
 
When making teachers most people prefer to put the white space in
 
  to make it easier to read and find errors.  A larger example would
 
  look as follows:
 
<nowiki>
 
  0;  100; scan                          ;   9;  9000;  7;          0;
 
  0;  90; consider                      ;  4;  4000;  5; 10;      0;
 
  0;  100; appraisal                    ;  9;  4000;  5;          0;
 
  0;  100; fleeing                      ;  9;  9000;  6; 12;      0;</nowiki>
 
Each part of the GTD separated by a semicolon is called a
 
field.  The following is the fields and their definitions.
 
  
;Field 1
+
</PRE><PRE>
: Field 1 is the guild level. It is simply the level at which one is allowed to practice the particular entity in the guild. A level of 0 indicates that one can practice it from the beginning.
+
<hr><a name="bfasctime">
;Field 2
+
string asctime(i : integer)
: This is the maximum percentage one is allowed to practice the particular entity. It can be anywhere from 1 to 200. For abilities, it should be in increments of 2 (or divisible by 2), and for spells, skills,
+
  i : the time to convert in seconds (<a href = "#bvrealtime">realtime</a> variable)
or weapons, in increments of 5 (or divisible by 5). This means that the
 
effective minimum depends on whether the entity is an ability or a spell,
 
skill or weapon.
 
  
Therefore, the minimums for abilities is 2, and the minimum for spells,
+
  Returns: The seconds converted into an ascii format date of the following
skills or weapons is 5. Anything less will be automatically practiced to
+
            form  "Mon Nov 18 18:49:08 1996"
the effective minimum. This also means that putting an odd number for
 
abilities will result in the player practicing an additional point, and
 
for spells, skills or weapons, practicing up to the nearest 5.
 
  
For example:   Percentage maximum for an ability is set for 95%. Player practices the
+
   Example:
ability, which then becomes 96%.
+
      log(asctime(realtime));
  Player then decides to practice a weapon skill. It is set to 77% maximum.
 
After practicing, the player has 80% in the weapon.
 
  It is better to simply make the ability 96% and the weapon 80% maximum
 
instead.
 
;Field 3
 
: Name of Entity
 
;Field 4
 
: This is the practice cost minimum in Old gold pieces. Anything less than 10 here will simply be translated as 1 iron piece. Anything other than a number divisible by 10 is rounded up to the nearest iron piece.
 
;Field 5
 
: This is the practice cost maximum in old gold pieces. It is generally defined as being 1000 times what Field 4 is defined as:
 
  
The reason for this is because there is a scale related to the current
+
</PRE
practice percentage of the entity. The practice minimum is what the entity
 
costs when it is at 0%, and the practice maximum is what it costs to
 
practice it to maximum percentage.
 
  
It is not necessary to multiply the minimum by 1000 to define the
+
<H2><A NAME="bfstrcmp">
maximum. It can be any number, as long as the maximum exceeds the minimum.
+
</H2>
Failure to do so will result in the mud crashing. It is unknown what will
 
happen if the fields have 0 entered in them. I warn that it could be rather
 
unpredictable.
 
  
Setting the maximum too high will only serve to dissuade players from
+
<P><B>Function:</B>  <CODE>integer strcmp( s1:string, s2:string) ;</CODE>
practicing and indeed even playing. This is not to say you cannot make a
+
<DL>
truly powerful entity very expensive. Just make sure that the entity is
+
<DT><B>s1</B><DD><P>first string
worth the cost.
+
<DT><B>s2</B><DD><P>second string
;Field 6
+
<DT><B>returns</B><DD><P>
: This is the only necessary practice points field. It allows one to use their skill or ability practice points to increase their character's powers.
+
<DL>
This number is generally determined by the desire of the builder to make
+
<DT><B>-1</B><DD><P>if s1 &lt; s2
the entity easier or harder to practice, based upon the logical
+
<DT><B>0</B><DD><P>if s1 = s2
consideration of how this class would learn/use the entity.
+
<DT><B>1</B><DD><P>if s1 &gt; s2
 +
</DL>
 +
</DL>
 +
<P>This allows you to compare strings with case sensitivity in place. If
 +
you don't care about the case of the string use the normal '==' '&gt;',
 +
'&lt;', '&lt;=', '&gt;=', symbols.
 +
<P><B>example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
 +
  
For instance, a Fighter class would find practicing "fist" to be
+
if (strcmp("I Care about Capitals",s2)==0))
exceedingly easy, so they may only need 4 points to practice this skill,
+
        {
but on the other hand, a Mage class would not have such an experience so
+
        sendtext ("You care I can see.&amp;n",self);
it may cost them 15 points to practice.
+
        quit;
 +
        }
 +
       
 +
       
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P>
 +
<H2><A NAME="bfstrncmp">
 +
</H2>
  
Don't go overboard, making this field an outrageous number will mean
+
<P><B>Function:</B>  <CODE>integer strcmp( s1:string, s2:string l :integer) ;</CODE>
that no one is likely to practice the entity, mainly because of lack of
+
<DL>
points. However, like in the cost fields, it can be made expensive to
+
<DT><B>s1</B><DD><P>first string
reflect the power of the entity.
+
<DT><B>s2</B><DD><P>second string
;Field 7 - X
+
<DT><B>l</B><DD><P>amount of significant digits to compare
: You can repeat field 6 as many times as you want the player to be able to practice in one level so you can set a point cost each timeThis is so each time they practice at a level you can make it more expensive.
+
<DT><B>returns</B><DD><P>
 +
<DL>
 +
<DT><B>-1</B><DD><P>if s1 &lt; s2
 +
<DT><B>0</B><DD><P>if s1 = s2
 +
<DT><B>1</B><DD><P>if s1 &gt; s2
 +
</DL>
 +
</DL>
 +
<P>This allows you to compare strings with case sensitivity in place and it
 +
allows you to choose how much of the strings are compared.
 +
<P><B>example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
 +
   
  
An example of this would look as follows:
+
if (strcmp("Mark Carper",s2,4)==0))
<nowiki>
+
        {
  0;   90; consider                      ;  4;  4000;  5; 10;      0;</nowiki>
+
        sendtext ("Hi Mark how is it going?&amp;n",self);
This example has consider being practiced at guild level 0 up to 90%,
+
                quit;
costing 4 old gold pieces minimum, 4000 old gold pieces maximum,
+
        }
5 practice points for the first practice per level and 10 for the
+
       
second.
+
       
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
  For 15 points a level, the player can practice consider twice. It is
 
actually quite nice to be able to do this, and generally easier entities
 
take advantage of this more often.
 
  
Each additional field is followed by a semicolon
+
<PRE>
;Field X
+
<hr><a name="bftextformat">
: This is the termination field for the GTD. It tells the compiler that the GTD is finished. In fact, if you set a practice point field to 0, it would consider that Field X, and end the GTD.
+
string textformat(s : string)
 +
  s : The text string to format. The string is formatted according to
 +
      the escape format codes as defined in one of the other documents.
  
Every GTD line must have an end of field marker!
+
  Returns: The formatted string which will automatically adapt to each
 +
            individual player's settings.
  
When we refer to old gold pieces they represent the VME money system as
+
  Example:
follows:
+
      ts := note.extra.descr;
{| class="wikitable"
+
      rs := textformat(ts);
|+Old to new money conversions.
 
|-
 
!Old gold piece
 
!New money
 
|-
 
|10
 
|1 Iron Piece (IP)
 
|-
 
|80
 
|1 copper piece (CP)
 
|-
 
|640
 
|1 silver piece (SP)
 
|-
 
|5120
 
|1 gold piece (GP)
 
|-
 
|40960
 
|1 platinum piece (PP)
 
|}
 
Of course, to finish up the entire SFUN_TEACH_INIT, you must include a
 
closing double quotation mark ("). Failure to do so will cause no end of
 
problems for you.
 
  
A finished teacher of ability function would look like
+
</PRE><PRE>
this:
+
<hr><a name="bfsplind">
<nowiki>
+
integer spellindex(s : string)
special SFUN_TEACH_INIT
+
  s : The abbreviated or full spell name
"&amp;labilities;0;
 
$1n tells you, 'I have never heard of such an ability.';
 
$1n tells you, 'I do not know how to teach this ability.';
 
$1n tells you, 'You haven't got %s for me.';
 
$1n tells you, 'You haven't got %d ability points.';
 
$1n tells you, 'I can not teach you any more';
 
$1n tells you, 'You must be unaffected by magic, otherwise I can't teach
 
you.';
 
$1n tells you, 'Remove all equipment, please.';
 
  
  0;  100; Strength                      ;  4;  4000;  8;      0;
+
  Returns: -1 if no such spell, otherwise it returns the spell index
  0;  90; Dexterity                    ;  14; 14000;  12;      0;
+
            for that spell.
  0;  90; Constitution                  ;  14; 14000;  9;      0;
 
  0;  100; Hitpoints                    ;  4;  4000;  11;      0;
 
  2;  60; Brain                        ;  23; 23000;  14;      0;
 
  4;  80; Charisma                      ;  18; 18000;  14;      0;
 
"</nowiki>
 
There are two other easy to use specials that you will want to use
 
with your teacher.  they are 'SFUN_GUILD_BASIS' and
 
'SFUN_MEMBERS_ONLY'.
 
  
;SFUN_GUILD_BASIS
+
  Example:
: This initializes the teacher and the only argument is the guild name
+
      s := "cu li wo"; /* cure light wounds */
<nowiki>
+
      i := spellindex(s);
special SFUN_GUILD_BASIS "Udgaard Fighter"</nowiki>
+
</PRE><PRE>
;SFUN_MEMBERS_ONLY
+
<hr><a name="bfsplinf">
: This simply blocks anyone who is not in the guild from practicing This means the argument is the guild name. and the act separated by a '#', an example would look as follows:
+
string spellinfo(idx : integer, i1 : integer, i2 : integer, i3 : integer,
<nowiki>
+
                i4 : integer, i5 : integer, i6 : integer, i7 : integer, )
special SFUN_MEMBERS_ONLY "Udgaard fighter#$1n says, 'Buggar ye off, $3n.'"</nowiki>
 
Finally we will show you what a full teacher would look like with
 
the entire specials and the NPC definition.
 
<nowiki>
 
jones
 
  
names {"blacksmith", "smith", "Jones"}
+
    idx : The spell index (SPL_XXX). You might want to use spellindex
title "Jones the blacksmith"
+
          to find this value.
descr "The venerable Jones Blacksmith is here."
 
extra {}
 
"The smith is old but his arms still retain the strength of his youth.
 
He looks as if he has retired, but he can still put you through the
 
drills of physical training."
 
flags {UNIT_FL_NO_TELEPORT}
 
romflags {CHAR_PROTECTED}
 
//Define from composed.h
 
M_HUMAN_WARRIOR_AXE(80, SEX_MALE)
 
  
//negative exp to discourage killing teacher
+
    Returns:
exp -100
+
      The full name of the spell, or the empty string if no such spell.
  
special SFUN_GUILD_BASIS GUILD_UDG_FIGHTER
+
    All the integer parameters are set to the following values:
special SFUN_MEMBERS_ONLY GUILD_UDG_FIGHTER+"#$1n says, 'Buggar ye off, $3n.'"
+
      i1  : Spell realm (MAG / DIC)
 +
      i2  : Spell sphere (SPL_XXX)
 +
      i3  : Mana usage
 +
      i4  : 0 if a non-offensive spell, non-zero otherwise
 +
      i5  : Resistance required (SPLCST_XXX)
 +
      i6  : Mediums (MEDIA_XXX)
 +
      i7  : Targets (FIND_UNIT_XXX & TAR_XXX)
  
special SFUN_TEACH_INIT
+
  Example:
"&amp;labilities;0;
+
    s := "cu li wo"; /* cure light wounds */
$1n tells you, 'I have never heard of such an ability.';
+
    i := spellindex(s);
$1n tells you, 'I do not know how to teach this ability.';
+
    s := spellinfo(i, i1, i2, i3, i4, i5, i6, i7);
$1n tells you, 'You haven't got %s for me.';
+
    /* s & i1 - i7 now set */
$1n tells you, 'You haven't got %d ability points.';
+
</PRE>
$1n tells you, 'I can not teach you any more';
+
$1n tells you, 'You must be unaffected by magic, otherwise I can't teach
+
<P>
you.';
+
<H2><A NAME="bpbeginedit"></a>
$1n tells you, 'Remove all equipment, please.';
 
  
  0;  100; Strength                      ;  4;  4000;  8;      0;
+
</H2>
  0;  90; Dexterity                    ;  14; 14000;  12;      0;
 
  0;  90; Constitution                  ;  14; 14000;  9;      0;
 
  0;  100; Hitpoints                    ;  4;  4000;  11;      0;
 
  2;  60; Brain                        ;  23; 23000;  14;      0;
 
  4;  80; Charisma                      ;  18; 18000;  14;      0;
 
"</nowiki>
 
==== Guild master functions ====
 
  
When you make a guild you have to make a guild master for it. This
+
<P><B>Function:</B> <CODE>beginedit ( u : unitptr);</CODE>
NPC will let people join and leave the guild and it also gives titles.
+
<DL>
To create a guild master you need to use three 'special' functionsThe
+
<DT><B>u</B><DD><P>the PC unit doing the editing
functions you need are 'SFUN_GUILD_BASIS', 'SFUN_GUILD_MASTER', and
+
<DT><B>return</B><DD><P>When done  editing it returns SFB_EDIT and activator
'SFUN_GUILD_TITLES'.
+
is set to PC
 +
</DL>
 +
<P>The 'BEGINEDIT' function sets a PC into editing modewhile in edit mode
 +
the PC field 'editing is set to true.  Once the PC is done editing a 'SFB_EDIT'
 +
message is sent to the unit editing to continue on with the DIL.
 +
If for some reason the PC needs to break
 +
out of the editor before it is done editing then the Dil needs to call
 +
the 'killedit' function
 +
<A HREF="#sect-beginedit">interrupt editing before done</A>
  
;SFUN_GUILD_BASIS
+
<P><B>example:</B>
: This initializes the master and the only argument is the guild name
+
<BLOCKQUOTE><CODE>
<nowiki>
+
<HR>
special SFUN_GUILD_BASIS "Udgaard Fighter"</nowiki>
+
<PRE>
;SFUN_GUILD_MASTER
 
: The guild master function takes 6 arguments.  Like the teacher function the arguments must be surrounded by double quotes.  The strings in the arguments must be surrounded by tilde marks (~).  The following is a description of the arguments and what they do.
 
  
;Line1:
+
dilbegin edextra ();
: The first argument on is what the guild name is.  As in the teacher you need to pre-pend the '&amp;l' symbol so the VME doesn't mess with the formatting of the string when the guild master is compiled.
+
var
<nowiki>
+
        temp:string;
&amp;lGuild = ~Udgaard fighter~</nowiki>
+
code
; Line 2
+
{
*
+
        beginedit (self);
This argument is what quest needs to be done before the character
+
        wait(SFB_EDIT,self==activator) ;
can enter the guild.
+
        temp:=textformat(argument);
<nowiki>
+
        addextra (self.extra,"general",temp);
Guild Enter Quest = ~Fighter Proven~</nowiki>
+
        quit;
; Line 3
+
}
*
+
dilend
  This argument is the amount it costs to enter the guild in old
+
</PRE>
  gold pieces.
+
<HR>
<nowiki>
+
</CODE></BLOCKQUOTE>
Guild Enter Cost = 640</nowiki>
+
<P>The previous DIL is an example of how you could make a command to set the
; Line 4
+
general extra which is the characters description when you do 'look player'
*
 
  this argument is the quest the player must do before leaving the
 
  guild.  If the player has not completed this quest the guild master
 
  will not let the player leave.
 
<nowiki>
 
Guild Leave Quest = ~Wimp proven~</nowiki>
 
; Line 5
 
*
 
This argument is how much old gold pieces it will cost to quit
 
the guild.  If the player doesn't have enough money the guild master
 
will not let the player join.
 
<nowiki>
 
Guild Leave Cost = 3200</nowiki>
 
; Line 6
 
*
 
This argument is what guild the guild master will not accept
 
players from.  For example the following will make it so no Thief can
 
be in the fighter guild.
 
<nowiki>
 
Guild Exclude Quest = ~Udgaard Thief Quitter~</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">When we refer to old gold pieces they represent the VME money system as shown in (Link to oldgold)</blockquote>
 
  
The following is what a full 'SFUN_GUILD_MASTER'
 
function would look like
 
<nowiki>
 
special SFUN_GUILD_MASTER
 
"&amp;lGuild              = ~Udgaard fighter~
 
Guild Enter Quest    = ~Fighter Proven~
 
Guild Enter Cost    = 640
 
Guild Leave Quest    = ~Wimp proven~
 
Guild Leave Cost    = 3200
 
Guild Exclude Quest  = ~Udgaard Fighter Quitter~"</nowiki>
 
;SFUN_GUILD_TITLES
 
: This function allows the player to request a title at the guild master.  A title will be given every 5 levels up to level 100 so you have 20 titles you can set.  The title function takes one title for male chars and one title for female chars so you have to set 40 titles.
 
  
The arguments of this function are easy.  The first thing you do is
+
<hr><a name="bfcancarry">
the normal '&amp;l' to let the VME know not to mess with this string.
+
</PRE><PRE>
Then you put the guild name.  Finally you follow it by the list of 40
+
integer can_carry(ch : unitptr, u : unitptr, n : integer)
titles.  The following is the fighter guilds title list
+
  ch : The character to check
<nowiki>
+
  u  : The unit to check if he can carry.
special SFUN_GUILD_TITLES
+
  n  : How many copies of that unit.
"&amp;lUdgaard fighter
 
the %s Swordpupil
 
the %s Swordpupil
 
the %s Recruit
 
the %s Recruit
 
the %s Sentry
 
the %s Sentress
 
the %s Fighter
 
the %s Fighter
 
the %s Soldier
 
the %s Soldier
 
the %s Warrior
 
the %s Warrior
 
the %s Veteran
 
the %s Veteran
 
the %s Swordsman
 
the %s Swordswoman
 
the %s Fencer
 
the %s Fenceress
 
the %s Combatant
 
the %s Combatess
 
the %s Hero
 
the %s Heroine
 
the %s Myrmidon
 
the %s Myrmidon
 
the %s Swashbuckler
 
the %s Swashbuckleress
 
the %s Mercenary
 
the %s Mercenaress
 
the %s Swordmaster
 
the %s Swordmistress
 
the %s Lieutenant
 
the %s Lieutenant
 
the %s Champion
 
the %s Lady Champion
 
the %s Dragoon
 
the %s Lady Dragoon
 
the %s Cavalier
 
the %s Cavalier
 
the %s Knight
 
the %s Lady Knight"</nowiki>
 
Put all three of these functions on your NPC and your all set you
 
have a guild master.
 
==== NPC banker ====
 
  
The banker function is the easiest 'special' function there is to
+
  Returns: 0 if 'ch' can carry 'n' times 'u'.
use. The following placed on an NPC will make a banker:
+
            1 if 'n' items are too many (his hands are full)
<nowiki>
+
            2 if 'n' times 'u' are too heavy
special SFUN_BANK</nowiki>
 
As you see its very simple, so we will just show you a completed banker
 
and leave it at that.
 
<nowiki>
 
bob
 
  
names {"Bob"}
+
  Example:
title "Bob"
 
descr "Bob the Banker is here, sitting behind the counter."
 
extra {}
 
"He has a very serious look on his face."
 
  
// define from composed.h
+
      i := can_carry(activator, item, 1);
M_SHOP_KEEPER(4, SEX_MALE, RACE_HUMAN)
 
  
//discourage people from killing banker
+
      if (i == 1)
exp -500
+
        exec("say Your hands are full!", self);
 +
      else if (i == 2)
 +
        exec("say You cant carry that much weight.", self);
 +
      else
 +
        exec("give "+item.name+" to "+activator.name, self);
 +
</PRE><PRE>
 +
<hr><a name="bffits">
 +
string fits( char : unitptr, obj : unitptr, pos : integer );
 +
  char: Character which we want to test if obj can be fitted upon
 +
  obj:  The object we want to see if fits char.
 +
  pos:  -1 or WEAR_XXX
 +
  Returns: Empty string if ok, or a textual description of the size problem.
  
flags {UNIT_FL_NO_TELEPORT}
+
  Fits tests if "obj" can be worn by "char" in position "pos". If
 +
  pos is -1, then fits automatically figures out the default worn
 +
  position for "obj".
  
special SFUN_BANK
+
  Example:
end</nowiki>
 
=== Dragon station with rooms and NPCs ===
 
  
Now we will add the NPCs we have built to the zone from the
+
      s := fits(self, obj, -1);
previous chapter.  This is still not complete while it does compile and
+
      if (s != "")
you can log into your zone, you still have to load your NPCs and there
+
        exec("say Don't buy it, its "+s, self);
are no objects.  These will be added as you progress through this
+
manual.  The following is the source file so far.
+
</PRE><PRE>
<nowiki>
+
<H2><A NAME="bfreplace">
#include &lt;composed.h&gt;
+
</H2>
%zone dragonst
 
lifespan 20
 
reset RESET_ANYHOW
 
creators {"whistler"}
 
  
notes
+
<P><B>Function:</B>  <CODE>string replace( t :string, n : string, o : string);</CODE>
"This is the dragon station I shortened it to dragonst for ease in
+
<DL>
loadingIf you have  any questions email me at whistler@valhalla.com"
+
<DT><B>t</B><DD><P>the target string you want to replace
 +
<DT><B>n</B><DD><P>what you want to replace the target with
 +
<DT><B>o</B><DD><P>the original string
 +
<DT><B>return</B><DD><P>the string with the old string replaced by the new string
 +
</DL>
 +
<P>This function replaces all occurences of a string in another string with a
 +
new string.   
 +
<P><B>Example:</B>
 +
<P><CODE>"Jafar %t% %l%" := replace(%n%,pc.name,"%n% %t% %l%");</CODE>
 +
<CODE>"Jafar the human %l%" := replace(%t%,pc.title,"Jafar %t% %l%");</CODE>
 +
<CODE>"Jafar the human 1" := replace(%l%,itoa(pc.vlevel),"Jafar the human %l%");</CODE>
  
help
+
</PRE><PRE>
"Not sure what could help you now.  You are stuck on one of the
+
<H2><A NAME="bfrestore"></A>
weirdest space stations you have ever seen and you smell burning
+
</H2>
sulfur."
 
  
%rooms
+
<P><B>Function:</B>  <CODE>unitptr restore( filename : string , u : unitptr );</CODE>
 +
<DL>
 +
<DT><B>filename</B><DD><P>The name of the Unit file
 +
<DT><B>u</B><DD><P>The Unit you want to restore into or null if none
 +
<DT><B>Return</B><DD><P>if 'u' null returns a pointer to the Unit loaded,
 +
if 'u' not null returns null and loads Units from the specified file into the
 +
unit 'u'
 +
</DL>
 +
<P>restore loads a copy of a unit or units which were previously saved with the
 +
'store' command. Just as with "load", the unit is put inside the unit which
 +
executes the restore command unless the 'u' argument is not null.  If the 'u'
 +
argument is an unitptr like room, object, npc, or pc the items restored will be
 +
placed inside the 'u' Unit..
 +
<P><B>Note</B>, It is only possible to restore items as long as the main-database
 +
contains a reference for the unit 'name@zone'.  Use 'Store' and 'Restore'
 +
sparingly, remember that items saved in player's inventories are automatically
 +
saved in this instance.
 +
<P>The 'store' and 'restore' are perfect for operations such as mud mailing
 +
objects from player to player, storage devices for players that will keep
 +
inventory through a reboot.  Even the ability to save a players inventory while
 +
they fight in an arena and restore it to them undamaged when finished.  Finally
 +
it could be used to save a donation room through reboots since it can be used on
 +
a room to store the contents of a room any NPC or objects in the room would be
 +
saved through reboot.
 +
<P><B>Disk access is always slow</B>.
 +
If you use 'Restore' on a continuous basis always attempt to keep file sizes to
 +
a minimum for quick loading.  Otherwise you might cause serious delays on the
 +
server.  If the Dil that uses Restore saves at certain times try to make it so
 +
the saves are spread out over as large amounts of time as possible.
  
chamber
+
<P><B>Example 1:</B>
title "The middle chamber of the station"
+
<BLOCKQUOTE><CODE>
descr
+
<HR>
"This chamber seems to have the entire station rotating around it.  It is
+
<PRE>
unbelievably large the ceiling seems to be a good 200 meeters high and
 
the room is perfectly cubic. Small human size ornate chairs with dragon
 
designs scrawled on the arms and back are arranged in a triangle like
 
setting with one large chair at the front.  This must be where all
 
station meetings are held. large pictures cover the walls depicting
 
dragons in all kinds of situations.  large passages lead of to the west
 
and the east.."
 
  
extra {"chair","chairs"}
+
dilbegin chest_load ();
"The chairs are made of some metal you don't recognize and every inch is covered
+
var
with some kind of dragon."
+
        waist:unitptr;/*to hold the null returned in this example*/
 +
        chest:unitptr;/*pointer to the storage chest*/
 +
code
 +
{
 +
chest:=load ("chest@myzone");/*get the container*/
 +
if (chest==null)
 +
        {
 +
        log ("Error");/*log an error*/
 +
        quit;
 +
        }
  
extra  {"dragon picture","picture"}
+
waist:=restore("chest."+self.zoneidx,chest);
"Thousands of dragons dot the skies of this rather life like picture. In the
+
/*
center you see something move. It looks to be a little green dragon."
+
restore given filename into chest
 +
waist can be ignored in this dil since it is not used.
 +
*/
 +
link (chest, self);/*link chest into room*/
 +
quit;/*dil load routine done destroy self.*/
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>Example 2:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
extra{"green dragon","dragon","green"}
+
dilbegin chest_load ();
"An intellegence looking dragon is sitting perched on a large chair watching you."
+
var
 +
        chest:unitptr;/*item to be loaded*/
 +
code
 +
{
 +
chest:=restore("chest."+self.zoneidx,null);/*restore into chest*/
 +
if (chest== null)/*see if something was restored*/
 +
        chest:=load("donate_chest@"+self.zoneidx);
 +
        /*load a new one if there is nothing restored*/
  
movement SECT_INSIDE
+
link (chest, self);/*link item into room*/
ALWAYS_LIGHT
+
quit;/*destroy the load dil.*/
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>Note:</B>  Example 1 is to be used if 'storall' was used not storing a container.
 +
Example 2 is for items stored with 'store' with the container saved as
 +
well.
 +
<P><B>See Also</B>
 +
<A HREF="#bpstore">Store a Unit to a Unit file</A> and
 +
<A HREF="#bfdelunit">Delete a Unit file</A>.
  
west to disposal_room descr
+
<PRE>
"You see a small room.";
+
<hr><a name="bfmelee">
 +
integer meleeattack ( ch : unitptr, vict : unitptr,
 +
                    bonus : integer, wtype : integer )
 +
  ch    : The character which should make an additional attack.
 +
  vict  : The victim of the attack.
 +
  bonus : Any penalty or bonus added to the attack.
 +
  wtype : The weapon type of the attack, if a valid type then that is
 +
          used for the attack purpose, otherwise the default weapon/hand
 +
          attack is used.
  
east to hallway descr
+
  result: 'ch' performs a melee attack (using whatever weapon is wielded
"You see what looks to be a hallway.";
+
          or his bare hands) against 'vict'. Returns the amount of damage
 +
          given (-1 is failed).
  
end
+
  If wtype is within a valid weapon range (WPN_XXX) any weapon will
 +
  be bypassed, and the value will be used as the attacktype. Good
 +
  for things like "meleeattack(ch, vict, bonus, WPN_CIRCLE_KICK)"
 +
  if you want person to be able to perform an extra attack even
 +
  though wielding a weapon or something. Note that this will require
 +
  BOTH a weapon type WPN_CIRCLE_KICK and a skill "kick" in order for
 +
  it to work.
  
hallway
+
</PRE><PRE>
title "Module tunnel"
+
<P>
descr "The hallway is about 50 meters long and around 100 meters from
+
<H2><A NAME="bpmeleedamage">
side to side and top to bottom.  The hallway seems to be dust free.  The
+
</H2>
walls and the floors seem to be made out of the same sterile
 
metal-plastic that all space agencies uses.  There are large plate glass
 
windows that open up into space.  The hallway is filled with a dim light
 
that seems to come from everywhere yet no where all at once.  You notice
 
a glimmer of bright light coming from the windows.  To the east you see
 
an air lock and to the west the hallway opens up into a larger room."
 
  
extra {"windows","window"}
+
<P><B>Function:  </B>
"Your eyes are drawn to a large ship lit up with running lights sitting
+
<CODE>meleedamage ( c : unitptr, v : unitptr, b : integer, wt : integer );</CODE>
about 1 kilometer from the station."
+
<DL>
 +
<DT><B>c</B><DD><P>the character that should make an additional attack
 +
<DT><B>v</B><DD><P>the character being attacked
 +
<DT><B>b</B><DD><P>any penalty or bonus added to the attack.
 +
<DT><B>wt</B><DD><P>the weapon type of the attack, if a valid type then that
 +
                    is used for the attack purpose, otherwise the default
 +
weapon/hand attack is used.
 +
<DT><B>returns</B><DD><P>The amount of damage done or -1 for failed
 +
</DL>
 +
<P>ch' performs an attack (using whatever weapon is wielded or his bare hands) against 'vict'.
 +
<P>If wtype is within a valid weapon range (WPN_XXX) any weapon will be bypassed,
 +
and the value will be used as the attacktype.  Good for things like "meleeattack
 +
(ch, vict, bonus, WPN_CIRCLE_KICK)"  If you want person to be able to perform an
 +
extra attack even though wielding a weapon or something. Note that this will
 +
require BOTH a weapon type WPN_CIRCLE_KICK and a skill "kick" in order for it to
 +
work.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
 +
dilbegin kick(arg : string);
 +
external
 +
  provoked_attack (victim : unitptr, ch : unitptr);
  
extra{"floor","walls","wall"}
+
var
"Well what can be said it looks to be in perfect condition. What else would
+
  bonus : integer;
you want to know?"
+
  targ : unitptr;
  
extra {"large ship" ,"ship"}
+
code
"The ship looks really big and is shaped like a dragon. The scales
+
{
sparkle and seem to be multiple colors."
+
  if ((self.type == UNIT_ST_PC) and (self.weapons[WPN_KICK] &lt;= 0))
 +
  {
 +
      act("You must practice first.", A_ALWAYS, self, null, null, TO_CHAR);
 +
      quit;
 +
  }
  
movement SECT_INSIDE
+
  if (arg == "")
ALWAYS_LIGHT
+
  {
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
      if (self.fighting)
 +
      {
 +
        targ := self.fighting;
 +
        goto kick;
 +
      }
  
west to chamber descr
+
      act("Kick who?", A_SOMEONE, self, null, null, TO_CHAR);
"The hallway opens up into a chamber.";
+
      quit;
 +
  }
  
east to office descr
+
  targ := findunit(self, arg, FIND_UNIT_SURRO, null);
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
open {EX_OPEN_CLOSE, EX_CLOSED};
 
  
end
+
  if ((targ == null) or not visible(self, targ))
 +
  {
 +
      act("That person is not here!", A_SOMEONE, self, null, null, TO_CHAR);
 +
      quit;
 +
  }
  
office
+
  if (not (targ.type &amp; (UNIT_ST_PC | UNIT_ST_NPC)))
title "The station office"
+
  {
descr
+
      act("You can't kick that, silly!", A_SOMEONE, self, null, null,
"Large paintings fill the walls of this part of the station.  The room
+
          TO_CHAR);
is as large as the other rooms big enough for Dragons to lounge while
+
      quit;
still having a desk in one corner small enough for a humanoid.  The
+
  }
floor along the north wall is lined with some kind of fabric and seems
 
very soft to walk on, it may be some kind of dragon lounge judging by
 
how large an area it covers.  There is a passage to the west."
 
  
movement SECT_INSIDE
+
  if (targ == self)
ALWAYS_LIGHT
+
  {
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
      act("You kick yourself.", A_HIDEINV, self, null, null,
 +
          TO_CHAR);
 +
      act("$1n kicks $1mself.", A_HIDEINV, self, null, null,
 +
          TO_ROOM);
 +
      quit;
 +
  }
  
extra {"paintings","painting"}
+
  if ((targ.type==UNIT_ST_PC) and
"The paintings are of many dragons and riders in all kinds of tasks from
+
  (self.type==UNIT_ST_PC))
combat to look out.  All the figures seem to be staring at a staff
+
  {
being held by a depiction of a wizard on the south wall."
+
if (not(isset (self.pcflags, PC_PK_RELAXED)))
 +
  {
 +
  act ("You are not allowed to do this unless you sign the book of blood.",
 +
  A_ALWAYS,self,null,null,TO_CHAR);
 +
  quit;
 +
  }
  
extra {"wizard","staff"}
+
if (not(isset (targ.pcflags, PC_PK_RELAXED)))
"The wizard has his hand stretched out and it seems there is a place
+
  {
you can almost grab the staff. Maybe if you searched the staff you would
+
  act ("You are not allowed to do this unless $2e signs the book of blood.",
find it."
+
  A_ALWAYS,self,targ,null,TO_CHAR);
 +
  quit;
 +
  }
 +
  }
  
extra {"desk"}
 
"Its a desk alright but there doesn't seem to be any drawers and it
 
seems totally empty."
 
  
extra{"fabric"}
+
  :kick:
"Wussshhhhh you bound across the comfortable floor wasn't that fun."
+
  /* Penalty for wielding a weapon while kicking! */
 +
  if (equipment(self, WEAR_WIELD))
 +
    bonus := -25;
 +
  else
 +
    bonus := +25;
 +
  if (self.endurance &lt; 2)
 +
    act("You are too exhausted to attempt that.", A_ALWAYS, self, null,
 +
        null, TO_CHAR);
 +
  else self.endurance := self.endurance - 2;
 +
  provoked_attack (targ, self);
 +
  bonus := meleeattack(self, targ, (bonus+self.level), WPN_KICK);
 +
  quit;
 +
}
 +
dilend
 +
</PRE><PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
west to hallway descr
 
"You see what looks to be a hallway."
 
keyword {"air lock door","air lock","door"}
 
open {EX_OPEN_CLOSE, EX_CLOSED};
 
  
SECRET_DOOR_DIFFICULTY(SOUTH, 50)
+
<P>
south to portal_room descr
+
<H2><A NAME="bfmid">
"You see what looks to be a portal room."
+
</H2>
keyword {"air lock door","air lock","staff","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED,EX_HIDDEN};
 
  
end
+
<P><B>Function:</B>  <CODE>string mid ( o : string, s : integer, e : integer );</CODE>
 +
<DL>
 +
<DT><B>o</B><DD><P>the original string to be parsed
 +
<DT><B>s</B><DD><P>The starting point of the string to be parsed out
 +
<DT><B>e</B><DD><P>the ending point of the string to be parsed out
 +
<DT><B>return</B><DD><P>the portion of the string defined by the 's' and 'e' values
 +
</DL>
 +
<P>This function parses the string passed to it and returns the portion of the string
 +
defined by the start value and the end value that is also passed to the function.
 +
<P><B>Example:</B>  <CODE>"rock" := mid ("sprocket",3,6);</CODE>
 +
</PRE><PRE>
 +
<hr><a name="bfmonstr">
 +
string moneystring(amt : integer, verbose : integer)
 +
  amt    : The amount of money
 +
  verbose: True if an expanded string (copper pieces) or false
 +
            if abbreviated money types (cp).
 +
  result : The moneystring for the given currency.
 +
</PRE><PRE>
 +
<hr><a name="bfeq">
 +
unitptr equipment ( u : unitptr , i : integer )
 +
  u : The character to search.
 +
  i : What equipment to find, any of the WEAR_XXX macros.
 +
  result: Returns the unit on 'u' which is equipped on position 'i'.
 +
          See WEAR_* in values.h and/or vme.h
 +
 
 +
  <H2><A NAME="bftolower">
 +
  </h2>
  
portal_room
 
title "Green field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a green field right in the center.
 
there is a door that leads to another room to the north."
 
  
movement SECT_INSIDE
+
<P><B>Function:</B> <CODE>string tolower ( s : string );</CODE> <P>
ALWAYS_LIGHT
+
<DL> <DT><B>s</B><DD><P>String to lower case
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
<DT><B>return</B><DD><P>the string passed in lower cased </DL>
 +
<P>This function returns a copy of the string passed in but with out capitals.
 +
<P><B>Example:</B> <CODE>"hello!" :=  tolower("HELLO!");</CODE>
 +
<P> <H2><A NAME="bftoupper">
 +
</h2>
  
extra {"green field","field"}
+
<P><B>Function:</B>  <CODE>string toupper ( s : string );</CODE>
"The field looks to be a green fog shifting and churning as you watch.
+
<DL>
if you are nuts you could probably enter it."
+
<DT><B>s</B><DD><P>String to lower case
 +
<DT><B>return</B><DD><P>the string passed in lower cased
 +
</DL>
 +
<P>This function returns a copy of the string passed in with all characters changed
 +
to be capitalized.
 +
<P><B>Example:</B>  <CODE>"HELLO!" := toupper ("hello!");</CODE>
  
north  to office descr
+
</PRE><PRE>
"You see what looks to be an office."
+
<hr><a name="bfvis">
keyword {"air lock door","air lock","door"}
+
integer visible(u1 : unitptr, u2 : unitptr)
key nokey
+
  u1: The character who is looking at u2
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
+
  u2: The unit which the character u1 is trying to see.
 +
  return: TRUE if u1 can see u2, FALSE otherwise.
 +
  Example: if (visible(self, victim)) ...
 +
</PRE><PRE>
 +
<hr><a name="bfop">
 +
integer opponent(u1 : unitptr, u2 : unitptr)
 +
  u1, u2: Two characters
 +
  return: TRUE if u1 is in combat with u2, FALSE otherwise.
 +
  Example: if (opponent(self, victim)) ...
  
//A link to the portal is also here from room_port
+
  When in a combat, you are usually only melee-attacking one opponent,
end
+
  although you may have many other opponents. This function lets you
 +
  check if you are directly / indirectly an opponent to another unit.
 +
</PRE><PRE>
 +
<hr><a name="bfpurse">
 +
integer purse(u : unitptr, coinage : integer)
 +
  u : The unit to check
 +
  coinage: The money type (e.g. gold, silver), one of IRON_PIECE, etc.
 +
  Returns: The number of such units found.
 +
  Example: if (purse(self, PLATINUM_PIECE) > 10)
 +
              exec("say I am loaded with platinum!", self);
 +
</PRE><PRE>
 +
<hr><a name="bfatoi">
 +
integer atoi ( s : string )
 +
  s : A string with a number.
 +
  return: The number in the string.
 +
  Example: i := atoi("42");
 +
 
 +
 
 +
</PRE><PRE>
 +
<H2><A NAME="bfcheckpassword">
 +
</H2>
  
ship_port
+
<P><B>Function:</B>  <CODE>integer check_password( u : unitptr, s : string ) ;</CODE>
names{"green field", "field"}
+
<DL>
title "Green field"
+
<DT><B>u</B><DD><P>the unit that you want to check the password of
descr
+
<DT><B>s</B><DD><P>the password you are using to check
"Green Mist swirls about you."
+
<DT><B>Return</B><DD><P>Returns an integer TRUE if pcname is the units password
 +
FALSE if not
 +
</DL>
 +
<P>This function checks the string against the units password and returns TRUE
 +
if they match.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
  
movement SECT_INSIDE
+
if (not check_password(pc,arg))
ALWAYS_LIGHT
+
        {
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
        sendtext (arg+" is not "+pc.name"'s password.",self);
 +
                quit;
 +
        }
 +
       
 +
       
  
in ship
+
<HR>
 +
</CODE></BLOCKQUOTE>
  
dilcopy force_move@function(
+
</PRE><PRE>
//Time to activation
+
<hr><a name="bfcomm">
4,
+
integer command ( cmd : string or integer )
//room and act
+
  cmd : A string of the full typed command, e.g. "push" or "say".
"portal_room@dragonst!You feel your body dissolving for lack of a better
+
        Alternatively you can specify one of the macros defined in
description.&amp;nYou appear on the deck of a ship.",
+
        values.h and/or vme.h, e.g. CMD_SAY
//True or False for randomizing or not
+
return: Whether the command specified by the activator is the one of
FALSE);
+
        the argument.
  
end
+
It is noteworthy, that unlike simple compares like this;
  
room_port
+
if ("spook" in cmdstr) {
names{"green field", "field"}
+
...
title "Green field"
+
...
descr
+
}
"Green Mist swirls about you."
+
or
movement SECT_INSIDE
+
if (cmdstr == "spook") {
ALWAYS_LIGHT
+
...
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
...
 
 
in portal_room
 
 
 
dilcopy force_move@function(
 
//Time to activation
 
4,
 
//room and act
 
"ship@dragonst!You feel your body dissolving for lack of a better
 
description.&amp;nYou appear on the deck of a ship.",
 
//True or False for randomizing or not
 
FALSE);
 
 
 
end
 
 
 
disposal_room
 
title "Red field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a red field right in the center.
 
there is a door that leads to another room to the east."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
extra {"red field","field"}
 
"The field looks to be a red fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
 
 
east to chamber descr
 
"You see the main chamber.";
 
 
 
//A link to the portal is also here from dis_port
 
end
 
 
 
dis_port
 
names {"red field","field"}
 
title "Red field"
 
descr
 
"Red Mist swirls about you."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
dilcopy force_move@function(
 
//how fast to force move in seconds
 
4,
 
//room to force move to and act
 
"deathspace@dragonst!You feel your body dissolving for lack of a better description.",
 
//true or false random move or not
 
0);
 
in disposal_room
 
 
 
end
 
 
 
ship
 
title "War dragon"
 
descr
 
"Blue light softly glows from con duets that line the walls of this ship.
 
The floors beside the east and west wall have what looks to be soft
 
fabric covering.  The south wall has small controls that seem to be made
 
for humanoids with two small chairs that look to be pilot seats.  view
 
portals are about 50 meters up the side of the ship on the west and east
 
wall and some kind of electronic screen covers the south wall.  The ship
 
seems to be a one room ship but there is a green field by the north
 
wall."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
extra {"view port"}
 
"Sorry your not 50 meters tall maybe it is made for a dragon?"
 
 
 
extra {"view screen","screen"}
 
"It seems to be the pilots view screen but you can't seem to see a way
 
to turn it on."
 
 
 
extra {"controls","control"}
 
"The controls are in some weird language and your afraid if you start
 
pushing buttons you might rocket in to the station or worse slam into
 
a planet."
 
 
 
extra {"soft fabric","fabric"}
 
"It looks to be a dragon lounge area."
 
 
 
//A link to the portal is also here from ship_port
 
end
 
 
 
deathspace
 
title"Open space"
 
descr
 
"You see the ship and the station far off in the distance and you are in Space!"
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
dilcopy death_room@function (
 
//how often is damage done 4 would be 1 second
 
4,
 
//damage
 
400,
 
//act for the damage.
 
"You realize to late that was the trash disposal transporter and you feel your
 
lungs explode.");
 
 
 
end
 
 
 
%mobiles
 
 
 
bldragon
 
 
 
title "a black dragon"
 
descr "A big ugly black dragon is clawing the ground here."
 
names {"big ugly black dragon","ugly black dragon","big black dragon",
 
"black dragon","dragon"}
 
 
 
extra {}
 
"The black dragons scales glitter like black granite that has been
 
polished for years by water.  He has a large neck and huge bat like
 
wings.  his eyes watch you as you stand before him.  One claw seems to be
 
tapping slightly on the ground as if the dragon is waiting for
 
something."
 
 
 
extra {"eye","eyes"}
 
"The dragons eyes seem to follow you no matter where you go in the room
 
nothing seems to escape the dragons attention."
 
 
 
extra {"claws","claw"}
 
"The claw is big black and it looks very deadly.  It seems like the
 
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
 
to say means the claws are about the size of short swords and long
 
swords."
 
 
 
extra {"scales","scale"}
 
"Its a scale!  Haven't you ever seen a dragon before!"
 
 
 
extra {"bat wings","wings"}
 
"The dragon sees you looking and flaps his wings creating one heck of a
 
wind blast."
 
 
 
M_DRAGON_BLACK_OLD(SEX_MALE)
 
 
 
end
 
 
 
janitor
 
names {"ugly janitor", "janitor", "hobgoblin"}
 
title "an ugly janitor"
 
descr "an ugly janitor is walking around, cleaning up."
 
 
 
extra{}
 
"This ugly green thing looks more goblin than hobgoblin but he seems intent
 
on cleaning everything around him."
 
 
 
M_AVG_HOBGOBLIN(6, SEX_MALE)
 
 
 
// he is sort of good for cleaning so much
 
alignment 900
 
 
 
//give him some money
 
money 5 IRON_PIECE
 
 
 
dilcopy janitors@function(15);
 
 
 
// only want him cleaning the station
 
dilcopy wander_zones@function("dragonst", 20, 1, 1);
 
 
 
end
 
 
 
bob
 
 
 
names {"Bob"}
 
title "Bob"
 
descr "Bob the Banker is here, sitting behind the counter."
 
extra {}
 
"He has a very serious look on his face."
 
 
 
// define from composed.h
 
M_SHOP_KEEPER(4, SEX_MALE, RACE_HUMAN)
 
 
 
//discourage people from killing banker
 
exp -500
 
 
 
flags {UNIT_FL_NO_TELEPORT}
 
 
 
special SFUN_BANK
 
end
 
 
 
%end</nowiki>
 
=== Suggested NPC exercises ===
 
 
 
1. Using the DIL function for team work found in (Link to npcdilfunc) create a guard that will help all other guards.
 
 
 
2. Using the DIL function for rescue found in
 
(Link to npcdilfunc) add to your guard from exercise one and make it so
 
will now rescue as well as help.
 
 
 
3. Using the shop keeper function from (Link to npcdilfunc);
 
make a shop keeper that sells two types of food.  The shop keeper should
 
make 5 of them a day and it should only buy items of the food type.  For all other arguments be creative.
 
 
 
4. Using the shop keeper you created from exercise three, turn your shop keeper into a global wondering sales person.
 
 
 
5. Using the DIL function for agressive found in
 
(Link to npcdilfunc) create a Dwarf agressive to any Orc that
 
walks into the room.
 
== The objects section ==
 
 
 
The previous chapters would be enough for you to create an entire
 
game of nudists with no technology and no items of any kind.  This of
 
corse would be a very boring game of naked people fighting with no
 
weapons.  don't worry the VME has a solution to this you can build
 
objects to dress up the NPCs and to fill the rooms with cluttered
 
junk.
 
 
 
In order to get started building objects you should first be aware
 
of the object fields you can use.  The (Link to objfields) shows a full listing
 
of all the object fields and their types as defined in (Link to ch-03).
 
{| class="wikitable"
 
|+Object fields and types
 
|-
 
!Field
 
!Type
 
!Field
 
!Type
 
|-
 
|symbolic name
 
|Symbol
 
|
 
|affect
 
|affect function
 
|-
 
|names
 
|Stringlist
 
|dilbegin or dilcopy
 
|function pointer
 
|-
 
|title
 
|String
 
|key
 
|String
 
|-
 
|descr
 
|String
 
|open
 
|Integer
 
|-
 
|inside_descr
 
|String
 
|manipulate
 
|Integer
 
|-
 
|extra
 
|Structure
 
|spell
 
|Integer
 
|-
 
|minv
 
|Integer
 
|value
 
|Integer
 
|-
 
|alignment
 
|Integer
 
|cost
 
|Integer
 
|-
 
|flags
 
|Integer
 
|rent
 
|Integer
 
|-
 
|weight
 
|Integer
 
|type
 
|Integer
 
|-
 
|capacity
 
|Integer
 
|end tag
 
|Symbol
 
|-
 
|light
 
|Integer
 
|
 
|
 
|}
 
Many of the same fields you found in rooms and NPCs, as you can see from
 
(Link to objfields), can also be found in objects.  The fields do
 
not always have exactly the same use when coding rooms, NPCs, and
 
objects but they are normally set in the same manor.  It is very
 
important that you read and understand the differences of each field as
 
they pertains to rooms, objects, and or NPCs.
 
=== Description of object fields ===
 
 
 
 
 
;symbolic name
 
: The rules of the symbols has been explained in
 
(Link to ch-03), if you didn't read them yet you may want to review.
 
The important thing to realize with the object symbol is it is always
 
good practice to give the object a symbol that resembles the title and
 
description so administrators and builders can use the
 
'''load''' and the '''wstat''' to easily
 
locate, examine, and load the object in question.
 
;title
 
: The object title is what is shown if the object is being picked up, dropped, given to someone, when you do the inventory command, , or being used in combat.
 
there should be no punctuation in the object title
 
because of how it is used in the VME server.  If you add punctuation or
 
forget to capitalize something that the VMC thinks you should it will
 
give you a warning when you compile. The following are good examples of
 
an object title.
 
<nowiki>
 
title "a big rock"
 
title "the flame tongue"
 
title "a lap top"
 
title "a garbage bag"
 
title "an oval hover car"</nowiki>
 
; descr
 
*
 
The description field is what the player sees when walking into the room
 
or when looking with no arguments.  It is good practice to make this no
 
longer than one line not counting the 'descr' tag.
 
 
 
Some examples of the object description field would be as
 
follows:
 
<nowiki>
 
descr
 
"a green bloody sword is laying here."
 
 
 
descr
 
"A massive wooden round table sits here."
 
 
 
descr
 
"a funny looking hammer is laying here."</nowiki>
 
;names
 
: The object names are as important as the NPC names.  They are what you act on when picking the object up, dropping it, throwing it, just about anything you do to objects use these name fields.  On drink containers you add the liquid name at the end, so people can drink the liquid.  You always need to make sure you put every possible name that the player may use to examine or take your item.  The rule of thumb is if it is in the title or description it should be in the names list.  conversely if it is not in the title or description it shouldn't be in the names list because the players will not use it if they don't know about it.
 
 
 
The following is some examples of good 'names' fields with respect to
 
        their 'title' and 'descr'.
 
<nowiki>
 
title "a big rock"
 
descr "a big rock is here blocking the road."
 
names {"big rock","rock"}
 
 
 
title "an old twisted staff"
 
descr "An old twisted staff has been discarded here."
 
names{"old twisted staff","twisted staff","old staff","staff"}</nowiki>
 
The idea of course is to make any combination that a player may
 
type to try and act upon your object.  You would not want to describe and
 
title your object with an entirely different theme than you created its
 
names with because a player would not know what it is called.
 
;inside_descr
 
: The inside description is what a player sees if it is inside the object.  This is used for things like Coffins or boxes or boats that a player can climb inside.  The inside description is defined the same way the normal description is but you can make it as many lines as you want like you would with a room description.
 
<nowiki>
 
                                      inside_descr
 
"You are inside a black coffin with a red velvet padding - scary!"
 
 
 
                                      inside_descr
 
"You are inside the pink time machine.  a small control panel is on the
 
floor and seems to be operated by stepping on it."</nowiki>
 
;extra
 
: The extra's on the object like the NPC, can be used to do many things.  It can be used to store information for DIL programs or it can be used to show a part of the object like the room extras show a part of the room.  They can even be used to create new acts when a person picks the item up,
 
drops, or enters it.There is also a special extra that is the object's description when
 
you look at it with the look &lt;object&gt; command.
 
 
 
Lets go over the object description extra first.  If you use an extra
 
with no names list it will become the object's description when you look at
 
any of the names on it.
 
<nowiki>
 
extra {}
 
"Its just a rock nothing special about it."
 
 
 
extra {}
 
"The ice cube is about 40 meters perfectly cubed.  It seems to be
 
melting slightly but waiting for it to finish would be sort of like
 
waiting for the ice age to end."</nowiki>
 
You can also use extras to show parts of the object.
 
<nowiki>
 
extra {"crack"}
 
"There is a big crack in the side of the ice cube.  Maybe if you mess
 
with the crack you will be able to open it or something."
 
 
 
extra {"bed post","post"}
 
"Its a big gold bed post don't you wish you could get this sucker off it
 
would make you a rich adventurer indeed."</nowiki>
 
You can also use the extras to give more detailed and vivid
 
descriptions when the object is acted upon.
 
{| class="wikitable"
 
|+Object special action extras
 
|-
 
!Extra
 
!Description
 
|-
 
|$wear_s
 
|A message shown to activator when wearing (+wield/grab/hold) an
 
item.
 
|-
 
|$wear_o
 
|A message shown to others when wearing an item.
 
|-
 
|$rem_s
 
|A message shown to activator when removing worn stuff.
 
|-
 
|$rem_o
 
|A message shown to others when removing an item.
 
|-
 
|$get_s
 
|A message shown to activator when getting an item.
 
|-
 
|$get_o
 
|A message shown to others when getting an item.
 
|-
 
|$drop_s
 
|A message shown to activator when dropping an item.
 
|-
 
|$drop_o
 
|A message shown to other when dropping an object.
 
|-
 
|$enter_s
 
|A message shown to activator when entering an item.
 
|-
 
|$enter_o
 
|A message shown to other when entering an item.
 
|-
 
|$exit_s
 
|A message shown to activator when leaving an item.
 
|-
 
|$exit_o
 
|A message shown to other when leaving an item.
 
|}
 
In the following example of an ice cube, 1n is the activator and
 
$2n is the unit in question.
 
<nowiki>
 
extra {"$get_s"}
 
"You pick up the $2N, it is very cold and begins to melt in your hands."
 
 
 
extra {"$get_o"}
 
"$1n picks up the $2N, you notice that a drop of water hits the ground as
 
it begins to melt in $1s hand."</nowiki>
 
Finally you can use extras to store information for DIL programs.
 
We will not cover this because it is a topic covered in-depth in
 
the DIL documentation.
 
;manipulate
 
: This field is what defines the things that can be done to the object.  For example a piece of armour should be able to be taken and worn, while a fountain should be able to be entered but not taken unless its some magical portable fountain.  There are two sets of manipulate flags even though you can use them together.  We separate them because the first two are flags that tell you if you can take or enter something while the rest of the manipulate flags are for worn positions.
 
 
 
First the two flags for taking and entering are:
 
{| class="wikitable"
 
|+Take and enter flags
 
|-
 
!Manipulate
 
!Description
 
|-
 
|MANIPULATE_TAKE
 
|Set this flag if the unit can be taken
 
(picked up/moved about).
 
|-
 
|MANIPULATE_ENTER
 
|Set this flag if it is possible to
 
enter a unit, ie set it in a coffin if you want players to be able to
 
enter the coffin.
 
|}
 
These flags are
 
set to indicate on what body positions a particular object can be
 
worn:
 
* MANIPULATE_WEAR_FINGER
 
* MANIPULATE_WEAR_NECK
 
* MANIPULATE_WEAR_BODY
 
* MANIPULATE_WEAR_HEAD
 
* MANIPULATE_WEAR_LEGS
 
* MANIPULATE_WEAR_FEET
 
* MANIPULATE_WEAR_HANDS
 
* MANIPULATE_WEAR_ARMS
 
* MANIPULATE_WEAR_SHIELD
 
* MANIPULATE_WEAR_ABOUT
 
* MANIPULATE_WEAR_WAIST
 
* MANIPULATE_WEAR_WRIST
 
* MANIPULATE_WIELD
 
* MANIPULATE_HOLD
 
* MANIPULATE_WEAR_EAR
 
* MANIPULATE_WEAR_BACK
 
* MANIPULATE_WEAR_CHEST
 
*  MANIPULATE_WEAR_ANKLE
 
Currently you can only set one of the worn positions flags on an
 
item at a time.  You can set both enter and take on an item with a
 
position or just one or the other.  Some legal examples of combinations
 
are as follows:
 
<nowiki>
 
//An earring
 
manipulate {MANIPULATE_TAKE, MANIPULATE_WEAR_EAR}
 
 
 
//A backpack
 
manipulate {MANIPULATE_TAKE, MANIPULATE_ENTER, MANIPULATE_WEAR_BACK}
 
 
 
//strange true but its legal an earring pack
 
manipulate {MANIPULATE_TAKE, MANIPULATE_ENTER, MANIPULATE_WEAR_EAR}</nowiki>
 
;flags
 
: This field on an object is used to set special attributes in order to make the object able to be buried or not or no-teleportable and many others.  The object flag list uses the UNIT_FL_* variables that both the NPCs and the rooms also use, therefore while you can set some flags on an object it may not have any affect unless you as a builder or administrator adds the functionality.  You can also add extras on an object that can be used as a special flag which you will learn as you learn to use DIL.  The following is a full list of all unit flags and how they affect objects, if they do.
 
{| class="wikitable"
 
|+Object unit flag affects
 
|-
 
!Flag
 
!Description
 
|-
 
|UNIT_FL_PRIVATE
 
|Currently has no affect on a NPC.
 
|-
 
|UNIT_FL_INVISIBLE
 
|Makes unit invisible
 
|-
 
|UNIT_FL_NO_BURY
 
|Makes it so you can create objects that
 
can not be buried for example a weapon that for some reason shouldn't be
 
buried.
 
|-
 
|UNIT_FL_BURIED
 
|Makes
 
unit buried when loaded
 
|-
 
|UNIT_FL_NO_TELEPORT
 
|Makes it so you can not teleport into this object.  This flag only
 
works on containers.
 
|-
 
|UNIT_FL_NO_MOB
 
|Currently has no affect on an object.
 
|-
 
|UNIT_FL_NO_WEATHER
 
|Currently has no affect on a NPC.
 
|-
 
|UNIT_FL_INDOORS
 
|Currently has no affect on an object.
 
|-
 
|UNIT_FL_TRANS
 
|Makes unit transparent If the Unit is
 
transparent you will be able to see any NPCs that it is carrying.
 
For example if a canoe was carrying a familiar you would see that as you
 
walked into the room.  If this flag is not set and you are in a canoe you
 
will not see outside the canoe and no one will see in.
 
|-
 
|UNIT_FL_NO_SAVE
 
|Makes it so a PC can't save with
 
unit
 
|-
 
|UNIT_FL_SACRED
 
|Currently has no affect on an object.
 
|-
 
|UNIT_FL_MAGIC
 
|This flag is used by spells to tell if the object is magic.
 
|}
 
If you wanted to make an object that a player can carry around but can
 
not save you would set the manipulate and flags as follows.
 
<nowiki>
 
manipulate {MANIPULATE_TAKE}
 
flags {UNIT_FL_NO_SAVE}</nowiki>
 
;type
 
: This field is what you use to set the objects type.  The type field is used when spells are cast or commands are executed on the object.  You can add your own item types but they will not change the actions of base code commands.  The following is the list of item types and what they mean when you set them.  Some are not supported with the current code but you can add support for them if you like by making DIL commands, which is covered in another manual.
 
{| class="wikitable"
 
|+Item types
 
|-
 
!Type
 
!Description
 
|-
 
|ITEM_LIGHT
 
|Items of this type can be lighted and extinguished.
 
|-
 
|ITEM_SCROLL
 
|Items of this type can be read as a magical scroll.
 
|-
 
|ITEM_WAND
 
|Items of this type can be used with the '''use'''
 
command.
 
|-
 
|ITEM_STAFF
 
|Items of this type can be used with the '''tap'''
 
command as a magical staff
 
|-
 
|ITEM_WEAPON
 
|Items of this type are used as weapons.
 
|-
 
|ITEM_FIREWEAPON
 
|Currently not supported but could be used to classify a special type
 
of weapon.
 
|-
 
|ITEM_MISSILE
 
|Currently not supported but could be used to classify a special type
 
of weapon.
 
|-
 
|ITEM_TREASURE
 
|Items of this type are of some great value to sell but nothing else
 
like a Gem or a block of gold.
 
|-
 
|ITEM_ARMOR
 
|Items of this type can be worn or used as armour.
 
|-
 
|ITEM_POTION
 
|Items of this type can be used with the '''quaff''' as
 
a position.
 
|-
 
|ITEM_WORN
 
|Items of this type can be worn but not normally used for armour it
 
is more for clothing.
 
|-
 
|ITEM_OTHER
 
|This item type is for items that don't fit any other type.  Now
 
that you can make your own commands with the VME 2.0 you should just make
 
your own item type instead of using this value.
 
|-
 
|ITEM_TRASH
 
|Items of this type are usually junk or broken equipment.
 
|-
 
|ITEM_TRAP
 
|Not currently supported but could be used to make a trap command by
 
creating a trap item
 
|-
 
|ITEM_CONTAINER
 
|Items that can be used as containers.
 
|-
 
|ITEM_NOTE
 
|Items of this type can be used to write on like paper or
 
slates.
 
|-
 
|ITEM_DRINKCON
 
|Items of this type can carry liquids.
 
|-
 
|ITEM_KEY
 
|Items of this type can be used as a key.
 
|-
 
|ITEM_FOOD
 
|Items of this type can be eaten
 
|-
 
|ITEM_MONEY
 
|Items of this type can be spent as currency
 
|-
 
|ITEM_PEN
 
|No longer supported but could be used to force people to have a
 
writing instrument before writing a message.
 
|-
 
|ITEM_BOAT
 
|Items of this type can be used as a water craft
 
|-
 
|ITEM_SPELL
 
|Not currently supported but it could be used to make a page in a spell book
 
|-
 
|ITEM_BOOK
 
|Not currently supported but could be used to make
 
regular and spell books.
 
|-
 
|ITEM_SHIELD
 
|Items of this type can be used as a shield.
 
|-
 
|ITEM_SKIN
 
|Not currently supported in the release but could be used to make the
 
skin command and create skins of animals
 
|-
 
|ITEM_BOARD
 
|Items of this type are used for public communications in the form
 
of boards that can be read from and written to.
 
|}
 
Unlike flags and manipulate fields only one item type can be set
 
on an object at a time.  The format for the 'type' field is simply the
 
keyword followed by the value as follows:
 
<nowiki>
 
type ITEM_BOARD</nowiki>
 
;weight
 
: The weight is the weight of the object in pounds.  In the future we may adjust this to allow you to make things lighter for example you could set it in ounces or grams.  Right now however all we have is pounds so we have some pretty heavy feathers out there.
 
 
 
To use this you just enter the 'weight' keyword and then the
 
value.
 
<nowiki>
 
/80 lbs.
 
weight 80</nowiki>
 
;capacity
 
: This field sets the size of a container object.  If the object does not have the manipulate enter flag set then this field doesn't have to be set.  The capacity is currently by pounds since the weight of objects is set in pounds.  In the future we may take into account size and weight but right now it goes only by weight.  The following line of code would set an item to carry 600 pounds of stuff.
 
<nowiki>
 
capacity 600</nowiki>
 
;key
 
: The key field sets the key name of the key that will open the item.  This field should be set to the symbolic name of the key that opens the item it is on.  If the item is in the same zone as the key then you do not need to put the zone extension on the key name.  The following are the three possible examples of using the key field.
 
<nowiki>
 
//if object and key are in same zone.
 
key brasskey
 
 
 
//if key and object are in same zone
 
key brasskey@zonename
 
 
 
//if key and object are not in same zone
 
key brasskey@otherzonename</nowiki>
 
Notice you can put the zone name on it if the key is in the same
 
zone but if the key is not in the same zone you must put the zone name
 
on it.
 
;cost
 
: This is the field you set to add a cost to your object.  If you leave this field out it will default to no cost and will not be able to be sold at stores.  The system for setting cost on an item is the same as setting money on a NPC.  As with a NPC we could set it using a single number but it would not be easy to understand.  For example 5 gold pieces would be something like:
 
<nowiki>
 
money 25600</nowiki>
 
I am no more sure this will make five gold pieces than I was when
 
I used this same example with the money field in NPC.  The problem is I
 
just did the math in my head so its not very accurate.  It is much
 
easier to use the defined money types to set exactly what you want as
 
follows:
 
<nowiki>
 
IRON_PIECE
 
COPPER_PIECE
 
SILVER_PIECE
 
GOLD_PIECE
 
PLATINUM_PIECE</nowiki>
 
Now if we wanted to make an object costing five gold it would be as
 
simple as this:
 
<nowiki>
 
money 5*GOLD_PIECE</nowiki>
 
the define method also gains you the ability to tell the VME what
 
amount of each coin you want on the NPC.  If you set it using a single
 
integer the compiler would pick how many of each coin.  This of course
 
is not what is desired in fact you want to be able to set your cost
 
however you like.  So setting more than one coin is as simple as adding
 
a comma between the first and second coin.
 
<nowiki>
 
money 5*GOLD_PIECE, 20*IRON_PIECE</nowiki>
 
;rent
 
: This field tells how much it costs you to keep an item while your offline.  The rent is not always taken if the VME server is set up to not take any rent then it will not matter if you set this or not.  Also the VME can be set up to take a percentage of this field so it may not take the exact amount you et.  If the VME server is set up to take 100%
 
of the rent then what you set will be taken.  To set this field you do
 
the same as you do with the cost field.
 
<nowiki>
 
money 5*GOLD_PIECE, 20*IRON_PIECE</nowiki>
 
;minv
 
: This field is the administrator invisible level of the object it is set on.  This means that if you set the 'minv' to two hundred it will make it so the object can not be seen by anyone below the administrator level of two hundred.  This is good for hiding objects that you need for administrators but you don't want players to see.
 
In order for the 'minv' to be removed an
 
administrator or a DIL function must change it.
 
<nowiki>
 
minv 239</nowiki>
 
;alignment
 
: The object alignment is not currently used.  It is an integer value that can be set on an object to be used with any DIL functions.
 
In the future it will be what determines if a good or evil person can
 
wield an item.  The value is set by placing the 'alignment' keyword
 
first followed by the alignment desired from -1000 to +1000.
 
<nowiki>
 
alignment -250</nowiki>
 
;open
 
: The open field is used if you want to give your object the ability to be opened, closed, and or locked.  If you add the open flags you need to also add a key field which has already been explained.
 
The following are all
 
the possible open flags and what they are used for.
 
 
 
;EX_OPEN_CLOSE
 
: Set this if you can open and close this object.
 
;EX_CLOSED
 
: Set this if you want the object to be closed when loaded.
 
;EX_LOCKED
 
: Set this if you want the object to be locked when loaded.
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">
 
An interesting aspect is that if you do not specify a key, you can
 
    only unlock this door with the 'pick' skill, 'unlock' spell or from
 
    DIL with UnSet();
 
</blockquote>
 
;EX_PICK_PROOF
 
: Using this flag renders the 'pick' skill and 'unlock' spell un useable on the lock of this object.
 
;EX_INSIDE_OPEN
 
: Usable on container objects only, this enables the mobile to 'open' and
 
    'lock' from the inside.
 
 
 
The simplest use of this field is to make an object that opens
 
and closes.  A coffin for example would have its flags set as
 
follows:
 
<nowiki>
 
open {EX_OPEN_CLOSE}</nowiki>
 
If you wanted to set an object that is locked and closed and
 
having a brass key that can open it, when it is loaded. It would look as follows.
 
<nowiki>
 
open {EX_OPEN_CLOSE, EX_CLOSED, EX_LOCKED}
 
key brass_key</nowiki>
 
You would have to define the key in the object section as well and
 
the symbolic name for that key would be 'brass_key'
 
;spell
 
: The spell field is the power of the objects defense against spells.  You can set it from zero which is just not setting the field all the way to 200% which means a person who has 100% in a spell will fail almost all the time. To set this field it would look as follows:
 
<nowiki>
 
//Spell resistance at 150%
 
spell 150</nowiki>
 
;value
 
: The object values are used for just about any special item from armour to drink containers. They should not be set directly unless you have a reason to do so, like a special DIL command that checks a value on an item. You also have to be carefull not to over write what a value is already used for example value one is already used on weapons and armours for craftsman ship that will be explained later in
 
(Link to objmacros).
 
 
 
If you find you need to set the values there are a total of five
 
of them and they can be set to any integer value as follows:
 
<nowiki>
 
  value[0]  5
 
  value[1] 16
 
  value[2] -2
 
  value[3] -10
 
  value[4] 12</nowiki>
 
;affect
 
: The affect field should not be set directly, instead you should use the macros defined in (Link to objmacros).
 
;dilbegin or dilcopy
 
: As has been mentioned in previous sections the DIL functions are what give VME servers the edge over all other muds.
 
We will only give some examples here and leave it up to the DIL manual to teach
 
you how to create your own functions that will make your rooms, NPC, and
 
objects more than special.
 
 
 
There are several object functions that come standard with the VME
 
2.0.  The following is a list of those functions.
 
* Guild restrict
 
* Anti-guild restrict
 
* Quest restrict
 
* Quests restrict
 
* Alignment restrict
 
* Level restrict
 
* Virtual level restrict
 
* Race restrict
 
* Ability restrict
 
* Skill restrict
 
* Spell restrict
 
* Weapon restrict
 
* Gender restrict
 
* Player restrict
 
* boards
 
* tuborg/dilbegin
 
These are the only object functions currently documented in the VME
 
2.0 release but if you go through the zones that are released with the
 
VME you are sure to find many more.  Hopefully with the descriptions in
 
(Link to objdilfunc).  You will be able to use the functions
 
listed here and figure out ones that are not.
 
 
 
Since these are just DIL's written by builders for the
 
Valhalla mud all you have to do is use the dilcopy keyword in the
 
NPC with the function name you want to use and the arguments that
 
function requires.  The following is what you would find in the
 
''function.zon'' for tuborgs.
 
<nowiki>
 
dilbegin tuborg(s:string);
 
external
 
sub_drink_info@commands(d:unitptr);
 
var
 
  u : unitptr;
 
code
 
{
 
  :start:
 
  wait(SFB_CMD, ( (command("drink")) or
 
                (command("sip")) or
 
  (command("taste")) ) );
 
u := activator;
 
secure (u,start);
 
if (findunit (activator,argument,FIND_UNIT_INVEN|FIND_UNIT_SURRO,null)!=self)
 
goto start;
 
if ( command("sip") or command("taste") )
 
{
 
  block;
 
  act("$1n tastes $2n enjoying every drop.", A_HIDEINV, u, self, null,
 
        TO_ROOM);
 
    act("The taste of the $2N is nothing less than divine.", A_HIDEINV, u, self,
 
    null, TO_CHAR);
 
  goto start;
 
  }
 
 
 
if ( u.thirst >20 )
 
{
 
  block;
 
act("Your not thirsty.", A_HIDEINV, u, null, null, TO_CHAR);
 
    goto start;
 
}
 
block;
 
  act ("You drink $2n and it makes you feel more energetic!", A_HIDEINV, u, self,
 
      null, TO_CHAR);
 
  act ("$1n drinks $2n and looks more energetic!", A_HIDEINV, u, self,
 
      null, TO_ROOM);
 
 
 
u.thirst := u.thirst + 10;
 
u.full := u.full + 10;
 
if (u.thirst > 24)
 
{
 
  u.thirst := 24;
 
}
 
 
 
if (u.full > 24)
 
{
 
  u.full := 24;
 
}
 
u.endurance := u.endurance+50;
 
if (u.endurance > u.max_endurance)
 
{
 
  u.endurance := u.max_endurance;
 
}
 
sub_drink_info@commands(self);
 
quit;
 
 
}
 
}
dilend</nowiki>
 
If this DIL function scares you don't worry you don't have to
 
understand it or adjust it you only have to use it.  In fact this is a
 
really easy DIL to use.  The argument on the tuborg function is not used
 
yet so all you have to do is pass in a blank string or any string for
 
that matter.  So if you wanted to make a tuborg in the game you would
 
just add this to your drink container.
 
<nowiki>
 
dilcopy tuborg@function ("");</nowiki>
 
All of the above listed DIL object functions are described in
 
(Link to objdilfunc).
 
Then we put some to work so you can see how
 
to use them in (Link to objcomplex)
 
  
=== Object macros ===
+
where the first will activate even if the cmdstr is "nospook", and the
 +
second only if cmdstr equals the word "spook" to the letter, the
 +
following construct will activate as long as the contents
 +
of cmdstr doesn't conflict with cmd;
  
  To make the creation of some objects easier we have provided a
+
if (command("spook")) {
set of Macros.  The macros range from general armour and weapons macros
+
...
to macros that help you create special affects on all items.  We will
 
first cover what craftsmanship and magical modifiers are in (Link to objcraft) and (Link to objmag) respectively.  After
 
which we will show the use of craftsmanship and magical modifiers in
 
(Link to objmacroweapon) and (Link to objmacroarmour).
 
==== Weapon and armour craftsmanship ====
 
 
 
The craftsmanship is a way of expressing the overall quality of  a
 
piece of armour or weapon.  The quality on the VME servers currently
 
means the amount of hit points given to an item.  The craftsmanship
 
ranges from 25 to -25 and the hit points range from 125 to 6000.  The craftsmanship can be looked at as how tough or good the armour
 
or weapon is.  The following table should help you in deciding how tough
 
your armour or weapon should be.
 
{| class="wikitable"
 
|+Approximate hit points verses craftsmanship
 
|-
 
!Craftsmanship
 
!Hit points
 
|-
 
|25
 
|6000
 
|-
 
|20
 
|5000
 
|-
 
|15
 
|4000
 
|-
 
|10
 
|3000
 
|-
 
|5
 
|2000
 
|-
 
|0
 
|1000
 
|-
 
|-5
 
|875
 
|-
 
|-10
 
|650
 
|-
 
|-15
 
|425
 
|-
 
|-20
 
|300
 
|-
 
|-25
 
|125
 
|}
 
It is suggested the higher the craftsmanship the higher the cost
 
of the weapon should be.  This is not a must but it goes with out saying
 
the quality of an item should be represented in the cost of it.  Of
 
corse there is the time you would want to sell your players poor quality
 
items at a high cost just to make them think they are getting something
 
cool.
 
==== Magical modifier ====
 
 
 
The magical modifier can be said to modify damage done to an
 
opponent.  In a combat the damage is calculated and then the magical
 
bonuses on armour or weapons is added in.  This is best explained by an
 
example.
 
 
 
Lets say that you were about to give 25 hit points of damage to a
 
person.  Your sword has a plus 25% in magical bonus.  The bonus is added to
 
your damage to make it a total of 50 hit points of damage.  The player
 
you are hitting however has a +25% magical bonus on his armour that you
 
are about to hit him on.  That will reduce the damage back to its 25%
 
hit points originally done.  This is just a nice way to add a bit of
 
damage for a special weapon.
 
 
 
The magical modifier ranges from 25 to -25.  It affects both the
 
damage being given to a player and the damage being given to a weapon or
 
a piece of armour.
 
 
 
It is suggested that you modify the costs of your objects to fit
 
the amount of magical bonus along with adding the magical flag tot he
 
objects flag list so an identify spell can pick up that there is
 
magic about the object.  This is not a must but your players will love
 
you for it.
 
==== Setting weapon fields ====
 
 
 
  To create a weapon you only need three pieces of information.
 
The weapons craftsmanship and magical modifiers defined in (Link to objcraft) and (Link to objmag) and the weapon type.
 
You have seen the weapon types before when defining a NPCs natural
 
attack type in (Link to npcmacroattarm).  The full list of weapon
 
types that are released with the VME 2.0 can be found in (Link to app-d).  With craftsmanship, magical modifier and the weapon
 
type all you need to do is pick from one of the following macros and
 
insert your numbers.
 
<nowiki>
 
#define WEAPONSZ_DEF(weapon_category, craftsmanship, magic_bonus, hgt)  \
 
  WEAPON_DEF(weapon_category, craftsmanship, magic_bonus)\
 
  height hgt
 
 
 
#define SHIELD_DEF(shield_type, craftsmanship, magic_bonus)  \
 
  manipulate {MANIPULATE_TAKE, MANIPULATE_WEAR_SHIELD} \
 
  type ITEM_SHIELD            \
 
  value[0] shield_type        \
 
  value[1] craftsmanship      \
 
  value[2] magic_bonus</nowiki>
 
As you can see the first macro uses the second macro so the only
 
difference between them is the first one sets the height field.  Using
 
the first macro will force your weapon to be a certain size when loaded.
 
While not setting the height field by using the second macro would let
 
the VME server set the size of the weapon by what NPC it is loaded
 
on.
 
 
 
A  flail (two handed) of non-pure iron (-3%), a little better than
 
average craftsmanship (5%) and no magic bonuses would have:
 
<nowiki>
 
    WEAPON_DEF(WPN_FLAIL, +2, 0)</nowiki>
 
A  rusty  (-5%) mean sacrificial dagger by a skilled smithy  (+5%)
 
and magically enchanted might be:
 
<nowiki>
 
    flags {UNIT_FL_MAGIC}
 
    WEAPON_DEF(WPN_DAGGER, 0, +5)</nowiki>
 
An old shaky wooden stick made for a 400 cm tall person could
 
    be:
 
<nowiki>
 
WEAPONSZ_DEF(WPN_CLUB, -5, 0,400)</nowiki>
 
A wooden bastard sword would have considerable less craftsmanship
 
than listed since wood prevents the slashing effect, also it would be
 
non-sense to apply better than average craftsmanship in this
 
case.
 
<nowiki>
 
    WEAPON_DEF(WPN_BROAD_SWORD, -15, 0)</nowiki>
 
==== Setting armour fields ====
 
 
 
When designing armour it is no more difficult then when designing
 
weapons.  There is five main armour types.  The types don't define the
 
material type for example if you wanted to create a wooden pair of
 
armour that protected like plate armour you could do this by defining
 
the armour type as plate and then adding the material as defined in
 
(Link to objmacromattype).  The five armour types are as
 
follows:
 
* Clothes
 
* Leather
 
* Hard leather
 
* Chain
 
* Plate
 
The armours macros are almost the same as the weapons macro it looks
 
as follows.
 
<nowiki>
 
#define ARMOUR_DEF(atype, craftsmanship, magic_bonus) \
 
  manipulate {MANIPULATE_TAKE} \
 
  type ITEM_ARMOR              \
 
  value[0] atype
 
      value[1] craftsmanship      \
 
  value[2] magic_bonus
 
 
 
#define ARMOURSZ_DEF(atype, craftsmanship, magic_bonus, hgt)\
 
  ARMOUR_DEF(atype,craftsmanship, magic_bonus) \
 
  height hgt</nowiki>
 
The craftsmanship and magical modifier fields have already been
 
explained so the only thing new that you need to pass into these macros
 
is the 'atype' which stands for armour type.  As we have mentioned there
 
are five different armour types.  The following are the defines for
 
each:
 
* ARMOUR_CLOTHES
 
* ARMOUR_LEATHER
 
* ARMOUR_HLEATHER
 
* ARMOUR_CHAIN
 
* ARMOUR_PLATE
 
The armour type defines how different weapons and spells are
 
defended against for example plate would be better against acid maybe
 
and worse against electricity.  You as a VME
 
administrator will have to decide which armours are better at what by
 
changing your ''weapons.def'' and
 
''spells.def''
 
 
 
This explains the entire armour define but there is some more to
 
it.  The rest will be covered in (Link to objarmour) For now an
 
example use of the armour define would be as follows:
 
<nowiki>
 
flags {UNIT_FL_MAGIC}
 
ARMOR_DEF(ARM_PLATE,+15,+5)</nowiki>
 
==== Setting shield fields ====
 
 
 
We have tried to keep the interface of making armours, weapons, and shields the same.  If you have already looked through the defines for weapons and armours you will find that there is very little difference here.  The following is the define for the macro that sets the shield values.
 
<nowiki>
 
#define SHIELD_DEF(shield_type, craftsmanship, magic_bonus)  \
 
  manipulate {MANIPULATE_TAKE, MANIPULATE_WEAR_SHIELD} \
 
  type ITEM_SHIELD            \
 
  value[0] shield_type        \
 
  value[1] craftsmanship      \
 
  value[2] magic_bonus
 
 
 
#define SHIELDSZ_DEF(shield_type, craftsmanship, magic_bonus, hgt)  \
 
  SHIELD_DEF(shield_type, craftsmanship, magic_bonus)\
 
  height hgt</nowiki>
 
You have already seen the craftsmanship and magical modifiers
 
in (Link to objcraft) and (Link to objmag), so the only
 
thing different here is the shield type.  There are three shield
 
types available in the current combat system and they are categorized by
 
size.  the three sizes are small, medium, and large.  to set the type
 
you use the defines from ''vme.h'' which define the
 
following:
 
* SHIELD_SMALL
 
* SHIELD_MEDIUM
 
* SHIELD_LARGE
 
the larger the shield the better chance of blocking an attack.
 
You may want to remember to add weight as you add size to your shield so
 
players are weighted down and can not carry the best of everything
 
but that is up to the administrator of the VME server.
 
 
 
A small magical wooden shield could be assigned:
 
<nowiki>
 
    flags {UNIT_FL_MAGIC}
 
    SHIELD_DEF(SHIELD_SMALL, 0, +5)</nowiki>
 
==== Setting material types ====
 
 
 
Currently Material types are not used greatly in spells or skills
 
but in the future we hope to add more functionality for materials.  For
 
example in the future if you are hit by an acid spell we want your
 
armour to be damaged depending on the material it is.  The material
 
doesn't have any affect on damage given or taken it is just a way you can
 
check in DIL what the weapon is made out of.  The following is the list
 
you would find in ''wmacros.h'' of in the VME 2.0
 
release.
 
<nowiki>
 
#define MATERIAL_WOOD(DESCR)    extra {"$material", "$mat_wood"} DESCR
 
#define MATERIAL_METAL(DESCR)   extra {"$material", "$mat_metal"} DESCR
 
#define MATERIAL_STONE(DESCR)  extra {"$material", "$mat_stone"} DESCR
 
#define MATERIAL_CLOTH(DESCR)  extra {"$material", "$mat_cloth"} DESCR
 
#define MATERIAL_LEATHER(DESCR) extra {"$material", "$mat_leather"} DESCR
 
#define MATERIAL_SKIN(DESCR) extra {"$material", "$mat_skin"} DESCR
 
#define MATERIAL_ORGANIC(DESCR) extra {"$material", "$mat_organic"} DESCR
 
#define MATERIAL_GLASS(DESCR)  extra {"$material", "$mat_glass"} DESCR
 
#define MATERIAL_FIRE(DESCR)    extra {"$material", "$mat_fire"} DESCR
 
#define MATERIAL_WATER(DESCR)   extra {"$material", "$mat_water"} DESCR
 
#define MATERIAL_EARTH(DESCR)  extra {"$material", "$mat_earth"} DESCR
 
#define MATERIAL_MAGIC(DESCR)  extra {"$material", "$mat_magic"} DESCR</nowiki>
 
Therefore if you had a wooden staff you could add the following to
 
your weapon so spells would know what it was made out of.
 
<nowiki>
 
MATERIAL_WOOD("a hard oak")</nowiki>
 
==== Drink container macros ====
 
 
 
There are two different kinds of macros for drink containers.  The
 
one you use depends on the need at the time.  The harder macro is made
 
so you can create a drink of any kind.  If however you want normal
 
drinks like water, beer, or even lemonade there are more simple macros
 
already defined for you to use in ''liquid.h''.  The
 
following is a couple of the macros from the
 
''liquid.h'' for a full listing see
 
(Link to app-e).
 
<nowiki>
 
#define LIQ_WATER(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("clear", WEIGHT,CAPACITY,INSIDE,10,1,0,POISON)
 
#define LIQ_BEER(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("brown", WEIGHT,CAPACITY,INSIDE,5,2,3,POISON)
 
#define LIQ_WINE(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("red", WEIGHT,CAPACITY,INSIDE,5,2,5,POISON)
 
#define LIQ_COFFEE(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("black", WEIGHT, CAPACITY, INSIDE, 6, 1, 0,POISON)</nowiki>
 
To use these macros the arguments are pretty simple.
 
 
 
;weight
 
: The first argument just says how heavy your drink container is when empty.  Like a barrel might be 15 pounds and a glass might be 1 pound.
 
You may be thinking there is no way the glasses in your kitchen are one
 
pound.  The truth is if we had less than a pound then we would set the
 
glass to less but currently all units are measured in pounds so the
 
least we can make it is a pound.  In the future of the
 
VME we will be converting to smaller measurements
 
like grams or ounces.
 
; capacity
 
*
 
The second argument is what your container can carry weight wise.
 
So if your barrel is 15 pounds and your barrel can carry 35 pounds of a
 
liquid then the total weight when full would be 50 pounds, if my math
 
is working today.  To make a container with infinity liquid like a
 
fountain you just set capacity to '-1'.
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">Making capacities ridiculously large can cause weight bugs. If your going to allow ridiculous amounts you might just want to give them the infinite amount or really work on your drink and pour functions</blockquote>
 
; inside
 
*
 
  The third argument is how much liquid by weight your container
 
  has inside.  This value should not be greater than the capacity but if
 
  you mess up it will be fixed when the player tries to drink from it.
 
  The total weight of the drink container and the liquid it contains
 
  will be the weight added to this value.
 
; poison
 
*
 
the forth argument is the amount of poison in your drink.  There
 
is no limit on the amount of poison but understand that a value of ten
 
would be a very high poison value.
 
 
 
So if you wanted to make a simple small glass of water you would
 
use the water macro and it would look like this:
 
<nowiki>
 
LIQ_WATER(1,2,2,0)</nowiki>
 
You are probably wondering what it takes to fill a player from
 
empty.  The players thirst ranges from -24 which is dieing of
 
thirst all the way to positive 24 which is full.  So if you have a
 
barrel that can hold 24 capacity one full barrel can take a person from
 
zero thirst to full.
 
 
 
Now lets say you want to make something more exotic.  All the
 
                          normal drinks are made or at least a great
 
                          number of them are in the
 
                          ''liquid.h'' but what if
 
                          you had a race from outer space that drank
 
                          nothing but silicone oil. This obviously is
 
                          not covered in our liquid file so you would
 
                          have to make one yourself or use the more
 
                          complex macro.
 
<nowiki>
 
#define LIQ_DEF(color, wgt, max_cap, inside,thirst,full,drunk,poison) \
 
  type ITEM_DRINKCON          \
 
  weight (wgt)+(inside) \
 
  capacity max_cap \
 
  value[0] inside        \
 
  value[3] poison \
 
  extra {"$drink_color"}color \
 
  extra {"$drink_thirst"} #thirst \
 
  extra {"$drink_full"} #full \
 
  extra {"$drink_drunk"} #drunk</nowiki>
 
As you can see this define has much more information you need to
 
pass it but it really is not that hard.  The following are the arguments
 
and what they do.
 
 
 
;color
 
: the first argument is the color of the liquid.  this color will be shown when you look at the liquid in the container.
 
;wgt
 
: The second argument is the weight of the container as in the last macros.  It is what the container would weigh empty.
 
;max_cap
 
: The third argument is the maximum capacity of the container.  If the value is set to 15 and the container is fulled it will contain 15 pounds of liquid which adds to the base weight to get the total weight of the container.  If you want a container to have unlimited contents then you set the capacity to '-1' and the weight will be that of the
 
'wgt' field.
 
;inside
 
: The forth argument is the amount of liquid the container starts with.  This amount should not be greater than the 'max_cap' field, but if it is it will be corrected when the player takes a drink or acts on the container.
 
;thirst
 
: The fifth field is how much thirst this gives per pound of liquid consumed.  For example if you have a glass of water and it only has a capacity of 1 with 1 inside.  this value will be added once to the players thirst field.
 
 
 
this can be a bit confusing so lets first explain that the thirst
 
field can be anything from 0 to 10 or even greater but we suggest only 10
 
max.  With that in mind know that we set water at 10 because it is one
 
of the best thirst quenchers known to man.  Therefore a glass with 1
 
capacity and 1 quantity inside will give a player +10 to his thirst so if
 
the player was down to zero thirst value one drink will give them 10.
 
remember that a players thirst ranges from -24 to +24 so with three
 
drinks of water a person could fill his thirst need entirely.
 
 
 
With that in mind when setting this field you have to think what
 
kind of thirst quencher is my drink.  If for example it is vodka it would
 
have little to know thirst quenching power so you would set this field
 
to 0 or 1.
 
;full
 
: The sixth field like the thirst field sets how the drink will affect the chars fullness.  The chars fullness field is normally set when a player is eating but as you know drinking some drinks will also give you the feeling of being full.  One drink like this would be milk.
 
The chars fullness field ranges from -24 to 24 like the thirst field and
 
the argument you are setting on this field should range from 0 to 10
 
unless you have a pro teen drink that fills them like food.  Milk might
 
have a fullness of something like 5.
 
;drunk
 
: the seventh field like thirst and full deals with the Drunkenness of a character.  A character can range from 0 (not drunk) all the way up to 24 (smashed).  The drunk field on this macro sets how much drunk is added for each quantity of the liquid is consumed.  Therefore something like vodka should have a value of 10 while something like water should be down at 0 unless you have some weird race that gets drunk from water.
 
;poison
 
: The eighth and final field is again like the last macro we looked at it sets the poison factor of a liquid.  The value ranges from 0 (no poison) to whatever you want but understand that 10 is an extreme poison factor and a player drinking this will most likely die quickly.
 
 
 
So with the definitions of each arguments in mind lets return to
 
the example of making a silicone oil based liquid.  We will first
 
show what it would look like using the hard macro then what the new
 
easy macro that you could create would look like.
 
<nowiki>
 
LIQ_DEF("blue",5,10,10,5,1,0,0)</nowiki>
 
Now if you want to make this a liquid your going to use a lot
 
you would define your own easier macro like this.
 
<nowiki>
 
#define LIQ_SILICONE(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("blue", WEIGHT,CAPACITY,INSIDE,5,1,0,POISON)</nowiki>
 
That covers the use of the macros but for more information on the
 
drink containers see (Link to objdrink).
 
==== The food macros ====
 
 
 
The food macro is much easier than that of the drink macro so if
 
you have drink containers down you will have no problem making food to
 
go with your beverage.  The players fullness value ranges from -24 to 24
 
as we have already learned when making drink containers and in the
 
current food system on the VME server we do not allow thirst to be
 
modified by food.  Therefore the only thing you have to set is the
 
amount of fullness and the poison factor if there is any.  The following
 
is what the define for food looks like.
 
<nowiki>
 
#define FOOD_DEF(food_amount, poison_factor)  \
 
  type ITEM_FOOD        \
 
  value[0] food_amount  \
 
  value[3] poison_factor</nowiki>
 
Therefore if you wanted to make sure that only one of your
 
foods that you were creating would fill a player entirely in one bite
 
you would set it like this:
 
<nowiki>
 
FOOD_DEF(50,0)</nowiki>
 
It is recommended that you only set the value between 1 and 10 so
 
that players have to eat a bit as if they were eating in the real
 
world.
 
==== Light object macro ====
 
 
 
The light macro is very simply to use it only has two values
 
duration and brightness of light.  The macro is defined as
 
follows:
 
<nowiki>
 
#define LIGHT_DEF(hours, how_bright)  \
 
  type ITEM_LIGHT    \
 
  value[0] hours      \
 
  value[1] how_bright</nowiki>
 
The first argument is the duration in mud hours which is about 5
 
  minutes per mud hour.  The second argument is how bright the object
 
  is 0 would be stupid cause it would give off no light but you never
 
  know maybe you want to do something like that.  One, two, and three
 
  would be small torch, large torch, and lantern respectively.  You
 
  could set a brightness greater than 3 but you should be carefull not
 
  to over light your characters or you may cause light bugs.
 
==== Container macro ====
 
 
 
The container macro is a simple macro that just sets two fields.
 
The only information you have to give it is the capacity of the
 
container.  Remember that capacity of an item is in weight not size.
 
Therefore if some ones corpse weighs 230 pounds you will need a container
 
that has a capacity of 230 to fit the corpse in it.  The following is
 
the macros definition as found in ''wmacros.h'':
 
<nowiki>
 
#define CONTAINER_DEF(max_capacity)  \
 
  type ITEM_CONTAINER              \
 
  capacity max_capacity</nowiki>
 
If you wanted to create a coffin that could carry any normal human
 
  corpse you could set it something like this:
 
<nowiki>
 
container_def(300)</nowiki>
 
==== Money macro ====
 
 
 
Money is one of the simplest objects you can make on the VME
 
server.  With this macro all you need is the symbolic before the macro
 
and the end keyword after the macro and you have 1 piece of money or a whole pile.  The macro is defined in the ''wmacros.h'' and looks exactly as follows:
 
<nowiki>
 
#define MONEY(coin_type, coins) \
 
  type ITEM_MONEY \
 
  manipulate MANIPULATE_TAKE \
 
  title coin_type \
 
  value[0] coins</nowiki>
 
The arguments are simple the first argument is the type of money the five possible values are:
 
* IRON_PIECE
 
* COPPER_PIECE
 
* SILVER_PIECE
 
* GOLD_PIECE
 
* PLATINUM_PIECE
 
The second argument is the amount of coins.  If you set it to
 
zero then it will still make exactly 1 of the coins.  The following
 
would be what one platinum piece would be like in a zone file.
 
<nowiki>
 
platinum_piece
 
 
 
MONEY(PLATINUM_PIECE, 0)
 
/* Rest of values are inserted at runtime */
 
 
 
end</nowiki>
 
Now if you want to make a whole pile of money it would look like this:
 
<nowiki>
 
platinum_pile
 
 
 
MONEY(PLATINUM_PIECE, 80)
 
/* Rest of values are inserted at runtime */
 
extra {}
 
"Holy cow thats a stash."
 
 
 
end</nowiki>
 
==== Cursed objects macro ====
 
 
 
Sometimes when making special objects you want to make an item
 
that a person can wear but can't remove.  With the cursed object macro
 
this is a simple thing.  The cursed object macro is defined in
 
''wmacros.h'' and looks as follows:
 
<nowiki>
 
#define CURSED_OBJECT \
 
affect \
 
  id ID_CURSE \
 
  duration -1 \
 
  firstf TIF_NONE \
 
  tickf  TIF_NONE \
 
  lastf  TIF_NONE \
 
  applyf APF_MOD_OBJ_FLAGS \
 
  data[0] OBJ_NO_UNEQUIP;</nowiki>
 
to use this macro it is simply a matter of putting the define
 
in your object like this:
 
<nowiki>
 
CURSED_OBJECT</nowiki>
 
When you set this macro on an object it adds an affect that can
 
only be removed by the 'set' command or by the 'remove curse
 
spell'.
 
==== Potion, wand, and staff macros ====
 
 
 
The macros for potions, scrolls, wands, and staffs are almost the
 
same.  In fact there is only two differences. The first  is the potions and scrolls can cast three
 
spells while wands can only cast two, The second is wands and staffs
 
have multiple charges possible while scrolls and potions only can be
 
used once.  The following are the macros
 
for all four as found in ''wmacros.h''.
 
<nowiki>
 
#define POTION_DEF(power,spell1,spell2,spell3)  \
 
  manipulate {MANIPULATE_TAKE, MANIPULATE_HOLD} \
 
  flags {UNIT_FL_MAGIC} \
 
  spell power      \
 
  type ITEM_POTION \
 
  value[0] power  \
 
  value[1] spell1  \
 
  value[2] spell2  \
 
  value[3] spell3
 
 
 
#define SCROLL_DEF(power,spell1,spell2,spell3)  \
 
  manipulate {MANIPULATE_TAKE, MANIPULATE_HOLD} \
 
  flags {UNIT_FL_MAGIC} \
 
  spell power      \
 
  type ITEM_SCROLL \
 
  value[0] power  \
 
  value[1] spell1  \
 
  value[2] spell2  \
 
  value[3] spell3
 
 
 
#define WAND_DEF(power,charge,spell1,spell2)  \
 
  manipulate {MANIPULATE_TAKE, MANIPULATE_HOLD} \
 
  flags {UNIT_FL_MAGIC} \
 
  spell power      \
 
  type ITEM_WAND \
 
  value[0] power  \
 
  value[1] charge  \
 
  value[2] spell1  \
 
  value[3] spell2  \
 
  value[4] charge  /* The max charge */
 
 
 
#define STAFF_DEF(power,charge,spell1,spell2)  \
 
  manipulate {MANIPULATE_TAKE, MANIPULATE_HOLD} \
 
  flags {UNIT_FL_MAGIC} \
 
  spell power      \
 
  type ITEM_STAFF  \
 
  value[0] power  \
 
  value[1] charge  \
 
  value[2] spell1  \
 
  value[3] spell2  \
 
  value[4] charge  /* The max charge */</nowiki>
 
The arguments are as follows for the macros.
 
 
 
;power
 
: The first argument on potions, scrolls, wands, and staff is the power the spell will be cast at.  You can have the power set in the range 1-200.  The spell power works the same as a player training in the spell.  The higher the number the more powerfull the cast.
 
;charge
 
: The second argument on the staffs and wands is how many charges it has.
 
;spell#
 
: On potions and scrolls you can set up to 2 spells you do not have to set them both the one you don't want set to 0.  On staffs and wands you can set three spells.  Again if you want only one or two you can leave the one you do not want set to 0.
 
 
 
==== Magical transfer macros ====
 
 
 
There are times when you want to give a player a bonus in a
 
ability, weapon, skill, and or weapon.  There is even times when you
 
want to adjust a characters speed or add a flag to a player when they
 
wear an item.  The following macros are what you would use to do any of
 
those when a person uses an item.
 
* CHAR_FLAG_TRANSFER(_MFLAGS)
 
* SKILL_TRANSFER(skill, amount)
 
* WEAPON_TRANSFER(weapon, amount)
 
* SPELL_TRANSFER(spell, amount)
 
* STR_TRANSFER(amount)
 
* DEX_TRANSFER(amount)
 
* CON_TRANSFER(amount)
 
* CHA_TRANSFER(amount)
 
* BRA_TRANSFER(amount)
 
* MAG_TRANSFER(amount)
 
* DIV_TRANSFER(amount)
 
* HIT_TRANSFER(amount)
 
* SPEED_TRANSFER(newspeed)
 
* SLOW_TRANSFER(amount)
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">For the full definitions of the transfer macros see (Link to app-f) or the header file ''wmacros.h''.</blockquote>
 
 
 
The transfer macros can be broken down into three groups those
 
which transfer percentage, flags, and speed.  The skill, weapons,
 
spells, and ability macros transfer the amount of percentage you put.
 
If you give a negative percentage it will take that much away from the
 
player or NPC in that catagory.  The character flag transfer actually
 
adds the flag to the player while the player is using the item.  The
 
speed transfer macros add or subtract the amount of speed you give them.
 
The range for speed is from zero to twelve with twelve being the
 
slowest.
 
=== Building your first object ===
 
 
 
Now that you have learned how to make rooms and NPCs its time to
 
make the objects for your little world.
 
In the last couple of sections you have looked
 
through the fields.  In this section we are going to make a nice easy
 
object.  There is really not that much new from what you have learned
 
with rooms and NPCs so this should be a real quick section.  As always
 
we will start with something I like which as you remember is dragons.
 
So the first object we will make is a dragon head.  I didn't say I liked
 
them alive now did I?  Anyway this will be a nice simple object that
 
your player can pick up and carry around.
 
 
 
When making objects you create the zone source file first as shown
 
in (Link to ch-02).  If you only have objects you do not need the
 
%reset, %mobiles, and %rooms fields.  For the examples in this chapter we
 
will use the zone we created in (Link to ch-04) and add the
 
%objects section where we will put all the object definitions.  At the end
 
of this chapter, in (Link to roomnpcobjzone), we will bring it
 
all together with the rooms and NPCs we have defined already.
 
 
 
The first part of all object definitions is the symbolic name it is good
 
to always pick a name that will match the name of the object so it
 
will be easy to load the object.
 
The reason the symbolic and name should match is when you use the
 
command '''wstat''' it will only show you a
 
list of the objects by symbolic name for example if you type '''
 
wstat zone dragon objects''' You will get the following:
 
<nowiki>
 
List of objects in zone Dragon:
 
claw info_board dragon_head</nowiki>
 
If you didn't make it clear what the object was by the symbolic name
 
it might look like this:
 
<nowiki>
 
List of objects in zone Dragon:
 
obj1 a_obj2 o3</nowiki>
 
While this might be great when you first start imagine trying to
 
remember each object if you have over 30 of them.
 
 
 
Now lets get started with our dragon head.  As with the rooms and
 
npcs all that is required to make an object is the symbolic and end fields.
 
That of course will make a NPC with all defaults.
 
<nowiki>
 
dragon_head
 
end</nowiki>
 
Thats it for that dragon head right?  Nope not quite, like before
 
with NPCs, that makes an object with all defaults.  That means this will probably be
 
a very blank spot on the screen with no names and no way your players
 
can interact with it.
 
Now lets start putting the
 
Dragon heads other more interesting fields on.
 
 
 
Like with rooms and NPCs, the first three things we need are the
 
dragon heads title, description and names.  The description should be what you
 
see when you do a 'look' in the room.  The title should be what you see
 
when the object is in your inventory or you are whacking someone over the
 
head with it.  Since we are not making a weapon though the title is what
 
will be shown when you are picking up or dropping the object.
 
Finally the names should cover everything
 
in the title and description fields so if your player wants to pick
 
the object up or wear it will be easy to figure out what the names
 
are.
 
<nowiki>
 
dragon_head
 
 
 
title "a gold dragon head"
 
 
 
descr "A large golden dragon head is laying here looking sad."
 
 
 
names {"large golden dragon head","large gold dragon head",
 
      "golden dragon head","large dragon head","gold dragon head",
 
      "dragon head","large head", "sad head","head"}
 
 
...
 
...
end</nowiki>
+
}
The names, title and description shouldn't be to hard so I don't
 
think its necessary to go into any more description on the subject.
 
Lets move on.  Now we have to take care of what a player sees when he or
 
she looks at an object.  to make the main description of an NPC you place an
 
extra on the NPC with no names in the list.  The blank extra is a
 
special extra that will be shown every time you look at anything in the
 
names list of the object.  So a description of an object would look something
 
like this.
 
<nowiki>
 
extra {}
 
"The head is large and beautiful, at least as beautiful as a dead
 
dragon head can be.  There is an extreme look of sorrow on the dragons
 
face and it seems to be for much more than its own death."</nowiki>
 
Now that you have a main description for the object you need to make
 
any smaller descriptions that you want the player to be able to look at.
 
In this case it may be good to give some secret information if the
 
player looks at the face of the head directly.
 
<nowiki>
 
extra {"gold dragon head face","dragon head face","head face","face"}
 
"Looking into the dragons face your eyes are drawn to the eyes of the
 
dead dragon.  Could there be something there?"
 
  
extra {"eyes","eye"}
+
ie, it will receive the same kind of treatment as a 'regular' command.
"A world of blue skies and no storms is visible through the eyes and it
+
That means that you provide ease of use to the user (allowing shorthand
seems to be moving as if you were watching the world from space."</nowiki>
+
notation), while securing that you're doing what the user wants.
Now that we have the object all described we only need to give the
+
<a name="bfcommand373"><STRONG>CAVEAT</STRONG> Builder:
    object the manipulate flags it needs, weight, height, and maybe
+
If you use a string argument as cmd, be sure that
    some extras that will make some cool acts when a player picks it up
+
there are no white-space in it, ie, that the argument does only
    or drops it.
+
consist of letters.
  
First thing to do though is pick the manipulate flags you
+
Example:
want on the object.  This is not a weapon or armour so all the
+
    command("spook");
player really needs to be able to do with it is pick it up and maybe
 
hold it if you want and I do.  The flags would then be as follows:
 
<nowiki>
 
manipulate {MANIPULATE_TAKE,MANIPULATE_HOLD}</nowiki>
 
If you were feeling a little weird you could even make the
 
person be able to wear the dragon head on his head but that would
 
just be strange.  of course its always good to know you have
 
options.
 
  
Now lets set the height and weight.  Remember you set the height
+
    is a valid string, while this construct;
in centimeters and the weight in pounds.  In the future the VME will
 
standardize to one or the other but for now we have to play the
 
conversion game.
 
<nowiki>
 
//20 feet  (1 inch = 2.54 cm
 
height 33
 
  
//566 KG (1 lb. = .45359 kg)
+
    command("spook him");
weight 50</nowiki>
 
The final touch to our little dragon head is some cute acts
 
when the player picks it up or drops it.  If you remember from the extra
 
fields in (Link to objfielddescr), there are some special extras
 
that are made just for this purpose.
 
<nowiki>
 
extra {"$get_s"}
 
"You suddenly feel very sad for a world that you don't even know."
 
  
extra {"$get_o"}
+
    is NOT valid. The reason of that is that cmdstr only contains the
"A strange look of sadness crosses $1ns face."
+
    FIRST word of the input from the player, and thus the latter
 +
    construct could never evaluate to true. This should be evident
 +
    taking the above information into account, as "spook him" could
 +
    never equal "spook" (which would indeed be the text in cmdstr
 +
    if the player entered the string "spook him".)
 +
  <p>
 +
</PRE><PRE>
 +
<H2><A NAME="bfdelstr">
  
extra {"$drop_s"}
+
</H2>
"You feel much happier but you remember a feeling of great sorrow."
 
  
extra {"drop_o"}
+
<P><B>Function:</B>  <CODE>integer delstr( filename : string ) ;</CODE>
"$1n seems to cheer up a bit."</nowiki>
+
<DL>
There are other things we could add to this item but I want to
+
<DT><B>filename</B><DD><P>The name of the String file to be deleted
keep this first object simple.  The finished head would then look like
+
<DT><B>Return</B><DD><P>Returns an integer TRUE if deleted FALSE if not
this:
+
</DL>
<nowiki>
+
<P>The delstr is used to delete files that are used with the 'loadstr' and
dragon_head
+
'savestr'      functions.  The delstr function will only delete files that
 +
each individual Zone has access to which is set up in the Zonelist file in the
 +
VME etc directory.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE><PRE>
  
title "a gold dragon head"
+
dilbegin news|del ("arg : string /*filename to be deleted);
 +
var
 +
        ret:integer;/*to hold the return value if deleted or not*/
 +
code
 +
{
 +
ret:= delstr("news.txt");
 +
if (!ret)
 +
        {
 +
        log ("File not deleted.");
 +
        quit;
 +
        }
  
descr "A large golden dragon head is laying here looking sad."
+
sendtext ("News file deleted[&amp;]n",self);
 +
quit;/*dil delete routine done
 +
}
 +
dilend
 +
</PRE>
  
names {"large golden dragon head","large gold dragon head",
+
<HR>
      "golden dragon head","large dragon head","gold dragon head",
+
</CODE></BLOCKQUOTE>
      "dragon head","large head", "sad head","head"}
+
<P><B>See Also</B> <CODE>
 +
<A HREF="#bfloadstr">Load String file</A> and
 +
<A HREF="#bfsavestr">Save String file</A></CODE>
 +
<p>
 +
<PRE>
 +
<H2><A NAME="bfdelunit">
 +
</H2>
  
  extra {}
+
<P><B>Function:</B>  <CODE>integer delunit( filename : string ) ;</CODE>
"The head is large and beautiful, at least as beautiful as a dead
+
<DL>
dragon head can be. There is an extreme look of sorrow on the dragons
+
<DT><B>filename</B><DD><P>The name of the Unit file to be deleted.
face and it seems to be for much more than its own death."
+
<DT><B>Return</B><DD><P>Returns an integer TRUE if deleted FALSE if not delunit
 +
is used to delete files that are used with the 'Restore' and 'store' functions.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
extra {"gold dragon head face","dragon head face","head face","face"}
+
dilbegin chest_del ("arg : string /*filename to be deleted*/);
"Looking into the dragons face your eyes are drawn to the eyes of the
+
var
dead dragon.  Could there be something there?"
+
        ret:integer;/*to hold the return value if deleted or not*/
 +
code
 +
{
 +
ret:= delstr("chest.file");
 +
if (!ret)
 +
        {
 +
        log ("File not deleted.");
 +
        quit;
 +
        }
  
extra {"eyes","eye"}
+
sendtext("Chest file deleted[&amp;]n",self);
"A world of blue skies and no storms is visible through the eyes and it
+
quit;/*dil delete routine done
seems to be moving as if you were watching the world from space."
+
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>See Also</B>
 +
<A HREF="#bfrestore">Restore a Unit from a Unit file</A> and
 +
<A HREF="#bpstore">Store Units to a Unit file</A>.
  
manipulate {MANIPULATE_TAKE,MANIPULATE_HOLD}
 
  
height 33
+
<PRE>
weight 50
+
<hr><a name="bfdd">
 +
integer dildestroy( s : string, u : unitptr )
 +
  s : name of dil template to delete.
 +
  u : unit to remove program from.
 +
  return: Whether a program using a template with same name as in 's'
 +
          attached to unit 'u' was deleted.
 +
</PRE><PRE>
 +
<hr><a name="bfdf">
 +
integer dilfind( s : string, u : unitptr )
 +
  s : name of dil template to find.
 +
  u : unit to find program in.
 +
  return: Whether a program using a template with same name as in 's'
 +
          attached to unit 'u' was found.
 +
</PRE><PRE>
 +
<hr><a name="bfitoa">
 +
string itoa ( i : integer )
 +
  i : A number.
 +
  return: A string with the number.
 +
  Example: s := itoa(42);
 +
</PRE><PRE>
 +
<hr><a name="bfisaff">
 +
integer isaff ( u : unitptr , i : integer )
 +
  u : A unit to be examined.
 +
  i : An id of an affect, see ID_* in values.h and/or vme.h
 +
  return: TRUE, if unit 'u' is affected by affect id 'i'
 +
 
  
extra {"$get_s"}
+
<P>
"You suddenly feel very sad for a world that you don't even know."
+
</PRE>
  
extra {"$get_o"}
+
<P>
"A strange look of sadness crosses $1ns face."
+
<H2><A NAME="bfislight">
 +
</H2>
  
extra {"$drop_s"}
+
<P><B>Function:  </B><CODE>integer islight ( u : unitptr )</CODE>
"You feel much happier but you remember a feeling of great sorrow."
+
<DL>
 +
<DT><B>u</B><DD><P>Unit that you are checking
 +
<DT><B>returns</B><DD><P>''TRUE' if item is a light, 'FALSE' if it is notway to small', 'to small', 'way to large', 'to large', or null if fits
 +
</DL>
 +
<P>Simply checks the item to see if it is a light.
  
extra {"drop_o"}
 
"$1n seems to cheer up a bit."
 
  
end</nowiki>
+
<H2><A NAME="bfisplayer">
Thats all there is to making regular items.  The rest is just
+
</H2>
adding functionality to what you already know.  We will get much deeper
 
into what you can do with items in (Link to objcomplex) but first
 
we will go over a debugging example and then all the special DIL functions made
 
for objects.
 
=== Compiling and Debugging your first object ===
 
  
As we have previously mentioned in (Link to rmdebug) and
+
<P><B>Function:</B>  <CODE>integer isplayer( pcname : string ) ;</CODE>
(Link to npcdebug) it is always a good idea to build one or two
+
<DL>
things and then compile to make finding errors easy.  In this case we
+
<DT><B>pcname</B><DD><P>the name of the player being checked
have one object to compile and rather than having all the rooms and NPCS
+
<DT><B>Return</B><DD><P>Returns an integer TRUE if pcname is a player FALSE if not
get in my way while compiling it I have removed them and only have the
+
</DL>
'%objects' section.  The following is what the zone looks like when it
+
<P>This function is used to find out if a string you pass to it is a player or not.
has only one object in it.
+
This can be used and is used to find out if a player is truly a player that an
<nowiki>
+
Administrator is deleting with out having that player on line.
#include &lt;composed.h&gt;
+
<P><B>Example:</B>
%zone dragonst
+
<BLOCKQUOTE><CODE>
lifespan 20
+
<HR>
reset RESET_ANYHOW
+
<PRE>
creator {"whistler"}
 
  
notes
+
if (not isplayer(arg))
"This is the dragon station I shortened it to dragonst for ease in
+
        {
loading. If you have  any questions email me at whistler@valhalla.com"
+
        sendtext (arg+" is not a character.&amp;n",self);
 +
        quit;
 +
        }
 +
       
 +
       
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
 
 +
 
 +
<PRE>
 +
<hr><a name="bfisset">
 +
integer isset ( i : integer , bit : integer )
 +
  i : An integer to examine.
 +
  bit : A set of bits to match.
 +
  return: TRUE, if bits in 'bit' is set in 'i'.
 +
  Example: if (isset(self.manipulate, MANIPULATE_TAKE)) ...
  
help
+
<hr><a name="bfpaychk">
"Not sure what could help you now. You are stuck on one of the
+
integer paycheck( u1 : unitptr, u2:unitptr)
weirdest space stations you have ever seen and you smell burning
+
  u1 : unit to check against
sulfur."
+
  u2 : player to check access for
 +
  return: TRUE if the player u2 has pay access to the location
 +
in which the unit u1 is located. FALSE if the player does not
 +
have access. Using non-players as u2 will return TRUE. The
 +
function checks if the player has pay-access (if needed) to
 +
the zone in which u1 is located.
  
%objects
+
<hr><a name="bffindu">
 +
unitptr findunit ( u : unitptr , s : string , i : integer , l : unitptr )
 +
    u : The unit the local environment is relative to.
 +
    s : A string with name of the unit to find.
 +
    i : The environment, where to look for it, see FIND_UNIT_*
 +
        in values.h and/or vme.h.
 +
    l : An optional list of units to search.
 +
return: If the unit is found, the function returns that unit.
 +
          Returns null if nothing found.
  
dragon_head
+
  The first argument is typically the char that's looking for something,
 +
  i.e. if Mary needs a spoon to stir the pot, she'll be the first argument.
  
title "a gold dragon head"
+
  The second argument is what you're looking for, represented by a string.
 +
  In the above mentioned example, that'd be "spoon".
  
descr "A large golden dragon head is laying here looking sad."
+
  For the second or third argument, you have a choice, as you'll only need to
 +
  use one of them, and let the other be 0 or null. For instance, if you have
 +
  a pointer to Mary's kitchen utensil pot, you can use the line:
  
names {"large golden dragon head","large gold dragon head,
+
    findunit(mary, "spoon", 0, pot);
      "golden dragon head","large dragon head","gold dragon head",
 
      "dragon head","large head", "sad head","head"}
 
  
  extra {}
+
  Or you can just let her look around for it with:
"The head is large and beautiful, at least as beautiful as a dead
 
dragon head can be.  There is an extreme look of sorrow on the dragons
 
face and it seems to be for much more than its own death."
 
  
extra {"gold dragon head face","dragon head face","head face","face"}
+
    findunit(mary, "spoon", FIND_UNIT_INVEN or FIND_UNIT_SURRO, null);
"Looking into the dragons face your eyes are drawn to the eyes of the
 
dead dragon.  Could there be something there?"
 
  
extra {"eyes","eye"}
+
  You can use all the FIND_UNIT_ values defined in values.h and/or vme.h, if you
"A world of blue skies and no storms is visible through the eyes and it
+
  want to look for something for example within the zone (FIND_UNIT_ZONE), the
seems to be moving as if you were watching the world from space."
+
  entire world (FIND_UNIT_WORLD) (you rarely need to do that, it's mainly for
 +
  tell etc.), or just the inventory or equipment of the char in question
 +
  (FIND_UNIT_INVEN and FIND_UNIT_EQUIP).  Finally, as in the example above,
 +
  you can look in the room of the char (FIND_UNIT_SURRO).
  
manipulate MANIPULATE_TAKE,MANIPULATE_HOLD
+
  Using FIND_UNIT_PAY or FIND_UNIT_NOPAY in this function will be ignored.
 +
  <P>
 +
The flags for findunit, intuitively:
 +
</P>
 +
<P>
 +
FIND_UNIT_EQUIP:<BR>
 +
  The objects you will see with `equipment'
 +
  Assumes first argument to findunit is a char.
 +
</P>
 +
<P>
 +
FIND_UNIT_INVEN:<BR>
 +
  The objects you will see with `inventory' or `look in bag'
 +
</P>
 +
<P>
 +
FIND_UNIT_SURRO:<BR>
 +
  The objects you can see, and get with `get',
 +
  or the characters you can `poke' :-)
 +
</P>
 +
<P>
 +
FIND_UNIT_ZONE:
 +
  As FIND_UNIT_WORLD, only more local.
 +
</P>
 +
<P>
 +
FIND_UNIT_WORLD:
 +
  Any object in the entire world.  Does NOT start looking close to the
 +
  object of findunit's first argument, but rather somewhat randomly.
 +
</P>
 +
<P>
 +
On top of these, the following (new) values are defined:
 +
</P>
 +
<P>
 +
FIND_UNIT_IN_ME:<BR>
 +
  Anything inside of the object of the first argument.
 +
</P>
 +
<P>
 +
FIND_UNIT_HERE:<BR>
 +
  Anything `here', i.e. in object or around it (same as IN_ME + SURRO)
 +
</P>
 +
<P>
 +
FIND_UNIT_GLOBAL:
 +
  ANYTHING, starting close to object and working out.
 +
</P>
  
height 33
 
weight 50
 
  
extra {"$get_s"}
 
"You suddenly feel very sad for a world that you don't even know."
 
  
extra {"$get_o"}
+
<PRE>
"A strange look of sadness crosses $1ns face."
+
<hr><a name="bffindru">
 +
unitptr findrndunit( u : unitptr, sv : integer, uf : integer)
 +
  Returns: A pointer to a random unit, or null
 +
  u  : The unit pointer which the search is relative to.
 +
  sv : The search-location, a value (not bit vector) of FIND_UNIT_XXX
 +
  uf : Bit vector. The unit flags which can match of UNIT_ST_XXX
  
extra {"$drop_s"}
+
  Example: u := findrndunit(self, FIND_UNIT_ZONE, UNIT_ST_PC|UNIT_ST_NPC);
"You feel much happier but you remember a feeling of great sorrow."
 
  
extra {"drop_o"}
+
  This routine returns a random unit. Notice how the 'uf' lets you
"$1n seems to cheer up a bit."
+
  specify exactly what unit types to look for. The 'sv' is not a
 +
  bit vector, although FIND_UNIT_XXX is usually used as such. If
 +
  you need to search multiple environments, then call the routine
 +
  once for each.
  
end
+
  Using FIND_UNIT_PAY or FIND_UNIT_NOPAY in this function will
 +
  pick a random player which in addition to being in the search
 +
  environment also is registered as valid payer (or not). Asking
 +
  for a room would yield a random room registered to be accessible
 +
  for paying players only (or not). Asking for objects would
 +
  return no unit (null).
 +
</PRE>
 +
  <P>
 +
<H2><A NAME="bffilesize"></A>
 +
</H2>
  
%end</nowiki>
+
<P><B>Function:</B>  <CODE>integer filesize ( filename :string);</CODE>
I removed the '%rooms' and '%mobiles' sections added a '%objects' section and
+
<DL>
stuck the dragon head in and now its ready to be compiled and put into the VME
+
<DT><B>file</B><DD><P>The file name you want to check
server for you to be able to look at it in the game.  If you downloaded
+
<DT><B>return</B><DD><P>a file size in bites 0 if no file
our example zones for this document you can compile this zone along with
+
</DL>
us and fix the errors as we do for practice.  The filename is
 
''debug_obj.zon''.  Just so you know the errors in this
 
zone are intentional so please don't write me an email telling me that
 
there are errors in it.
 
  
The command to compile the zone is
+
</PRE>
'''VMC debug_obj.zon'''.
+
<P>
Here is what we get when we first try and
+
This function does exactly what it says it does it checks a files size.
compile the zone.
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_obj.zon'
 
&lt;debug_obj.zon&gt; @ 65: EOF in string
 
debug_obj.zon: 5: parse error
 
  Token: '{'
 
debug_obj.zon: 25: parse error
 
  Token: 'golden'
 
Grave errors in file 'debug_obj.zon'.</nowiki>
 
This error file doesn't look any harder than the last one we dealt
 
with when compiling our first room or NPC.  We can not stress enough
 
always fix the smallest numbered error first.  In this case the lowest
 
numbered error shows up in line five of the zone.  The error says
 
something is wrong with the '{' but looking at the line it is obvious
 
the compiler got confused because I forgot 's' at the end of 'creators'.
 
If we fix line five and recompile this is what we get:
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_obj.zon'
 
&lt;debug_obj.zon&gt; @ 65: EOF in string
 
debug_obj.zon: 25: parse error
 
  Token: 'golden'
 
Grave errors in file 'debug_obj.zon'.</nowiki>
 
Now we have come to another one of those weird errors.  If you
 
look at line 25 you will find that the line looks like it is correct.
 
As we have said before when you find an error like this it most likely
 
means that you are missing a quote or a '{}'.  The only way to find the
 
problem is start at the quote or '{}' before the word in the error and
 
go backwards through the file till you find a missing one.  Lucky for us
 
the missing one is in the very next string.  If you add a double quote
 
just before the ending comma on line 24 and recompile you will get the
 
following:
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_obj.zon'
 
debug_obj.zon: 42: parse error
 
  Token: ','
 
Compilation aborted.</nowiki>
 
This error is a little tricky.  It seems to be pointing at the ','
 
as the problem.  If you look at the line though and remember what you
 
need for a manipulate field you will notice that the surrounding '{}' are
 
missing.  The reason the compiler is pointing at the comma is because it
 
doesn't understand what to do with the comma with out the '{}' grouping
 
symbols.  Fixing these and recompiling results in the following message
 
from the compiler.
 
<nowiki>
 
VMC v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_obj.zon'
 
VMC Done.</nowiki>
 
Notice there are no errors and it says 'VMC done', this means that
 
you have now successfully compiled the zone.  This is the last debugging
 
walk through in the manual.  If you still have a lot of trouble figuring
 
out errors don't stress compiling is an art the more you do it the
 
easier it will get.  We suggest you take the zones we have provided in
 
our release and create errors so you can get used to the messages
 
you will see when you are making your own zones.  Never be afraid to
 
ask for help from someone else sometimes a bug is so simple you will
 
over look it and sometimes it just takes a second person a single glance
 
to find it.  Another trick to finding errors if you have been looking
 
for more than 5 minutes take a break and come back in 10 minutes
 
sometimes that short relaxing time will help you find the
 
problem.
 
  
You have now compiled your first object.  The steps are the same
+
<P><B>Example DIL:</B>
to get it into the game as it was for the rooms and NPCs.  We will not
+
<BLOCKQUOTE><CODE>
go over them again except to say copy your files that the compiler made
+
<HR>
over into the zone directory of your mud and reboot.  From there log on
+
<PRE>
and you should be able to '''wstat''' and
 
'''load''' your object by using its full symbolic
 
name.  It would be a good idea to try and get this zone into your server
 
and lay with the object a bit so when you get to (Link to objcomplex) you will be ready for anything.
 
=== DIL functions for objects ===
 
  
The DIL language is the language a builder can use to make his own
+
dilbegin notebook ();
special functions on rooms, NPCs, objects, PCs, and much more. This
+
code
manual is for basic zone writing and therefore will not go into how to
+
{
write your own DIL functions. The VME however is released with many
+
        ns := filesize (self.name+"notebook");
functions for you as an Administrator and your builders to use to make
+
        if ( ns >500000)
special rooms, NPCs, and objects.  The following sections contain a full list of all object
+
        {
functions released with the VME 2.0 server.
+
                sendtext ("Your notebook is full.&amp;n",self);
==== Restriction functions ====
+
                quit;
 +
        }
 +
        else if ( ns > 250000)
 +
        {
 +
                sendtext ("Your notebook is more than half full.&amp;n",self);
 +
                quit;
 +
        }
 +
        else if (ns >125000)
 +
        {
 +
                sendtext ("Your Notebook is only 1/4 full.&amp;n",self);
 +
                quit;
 +
        }
 +
        else if (ns >0)
 +
        {
 +
                sendtext ("Your notebook is less than 1/4 full.&amp;n",self);
 +
                quit;
 +
        }
 +
        else
 +
        {
 +
                sendtext ("You don't have anything in your Notebook.&amp;n",self);
 +
                quit;
 +
        }
  
The desire to have different equipment comes from every players
+
}
desire to be different.  The restrict functions were designed to help
+
dilend
make this a reality by only allowing certain groups of players to wear
+
</PRE>
some items.  The restrict functions can be used alone or together to
+
<HR>
make a greater restricted item.  for example you could make an item,
+
</CODE></BLOCKQUOTE>
restricted to only females or you could make an item, restricted to females that had a strength greater than 20 and who have
+
<P>The previous DIL example shows how you could use the 'filesize' instruction to
done a certain quest.
+
check the size of a player stored notebook.
 +
<PRE>
  
All restrict functions have a name that describes what the
+
<hr><a name="bffindr">
restriction function is for and four other arguments.  the 2nd, 3rd, and
+
unitptr findroom ( s : string )
4th argument is the exact same for all restrict functions only the name
+
  s : Symbolic name of room.
of the restrict and the first argument changes. The format for the
+
  return: A pointer to the room, or null
restrict functions is as follows.
+
  Example: findroom("inn@udgaard")
<nowiki>
 
dilcopy &lt;function name&gt; (arg 1, &lt;max damage&gt;,
 
    &lt;percentage&gt;,&lt;Optional DIL&gt;);</nowiki>
 
We will skip the function name and the first argument and get back
 
to them later.
 
  
;max damage and percentage
+
<hr><a name="bffinds">
: The second and third arguments set the damage done when the wrong player wears an object. The reason we are explaining them together is they can work together or separately depending on how you set them.
+
unitptr findsymbolic ( s : string )
The second argument is the max damage the third argument is the
+
  s : Symbolic name of the NPC or Object to find.
percentage damage.
+
  return: A pointer to an instance of the unit, or null.
 +
  Example: findsymbolic("bread@midgaard")
  
When both arguments are set to 0 no damage will be
+
  This routine supplements findroom and findunit. It comes in handy,if it is
done when the item is illegally wornWhen the second argument is set
+
  important to get a correct reference to a NPC in the worldIf for example,
to a number like 100 and the third argument is set to 0, exactly 100
+
  Mary needs to send a message to John the Lumberjack, then she should NOT
damage will be done to the player no matter how many hit points he/she
+
  use the findunit() since it may locate a different John - even a player!
hasSo by setting the second argument to a number and setting the
+
  If she instead locates him using findsymbolic("john@haon_dor") she will be
third to 0 you could possibly kill your victim since it will remove the
+
  certain that it is in fact her husband, and not the player John Dow from
amount specified no matter how much the player has.
+
  NorwayIt will NOT locate rooms, for the only reason that findroom is a
 +
  lot more efficient.
  
If you do not want
 
to possibly kill your victim the Third argument should be used.  If you
 
set the second argument to 0 and the third argument to a number it will
 
do a percent of damage to the player. for example if The third argument
 
was set to 25 it would do 25 % damage to a player.
 
  
  You can also use the second and third argument together if you want to set a max amount of
+
unitptr findsymbolic ( u : unitptr, s : string, i : integer )
damage without possibly killing them. for example if you set the second
+
  u : Search is relative to this unit.
argument to 100 and third to 25. The item will do 25% damage up to 100
+
  s : Symbolic name of the NPC or Object to find.
hit points of damage. This all might be a bit confusing so let me show
+
  i : FIND_UNIT_XXX bit vector of places to search.
you a few examples and tell you what they would do.
+
  return: A pointer to an instance of the unit, or null.
 +
  Example: findsymbolic(self, "bread@midgaard", FIND_UNIT_INVEN)
  
;second= 0 third = 25
+
  This routine supplements findroom, findunit and findsymbolic(#).  It comes in
: This would do 25% damage to a player. second =100 third = 0 this would do 100 damage to a player no matter his amount of hit points.
+
  handy, if it is important to get a correct reference to a unit somewhere
;second = 25 third = 25
+
  relative to 'u'. If for example, Mary needs to check if she has her own
: This would do 25 % damage to a player up to 25 hit points.
+
  cooking pot, then she should NOT use the findunit since it may locate a
So if a player had 150 hit points the max that could be removed is 25
+
  different pot, not belonging to Haon-Dor but to some other zone. If she
hit points.
+
  instead locates it using findsymbolic(self, "pot@haon_dor", FIND_UNIT_IN_ME)
 +
  she would be certain that it is in fact her own cooking pot that she is
 +
  carrying around, and not some other pot from a Joe Blow's zone.
 +
 
 +
</PRE><PRE> 
 +
<P>
 +
<H2><A NAME="bpflog">
  
;optional DIL
+
</H2>
: All restrict DIL functions have a default set of acts.  If you want to make your own set of acts you have to create your own DIL that does nothing more than act.  If you don't understand how this works.  You may want to look in the DIL manual about passing DIL functions as arguments.
 
  
Now we should get back to the first argument and function name
+
<P><B>Function:</B>  <CODE>flog (filename : string,  s : string, wa : string );</CODE>
since they are what control the restricts. The function name has been
+
<DL>
chosen so you can easily tell what the restrict was created for
+
<DT><B>filename</B><DD><P>The Filename of the file to appear in the log directory.
while the first argument changes depending on which restrict you use.
+
<DT><B>s</B><DD><P>The string to be logged.
The following are what each function restricts name is and what the function
+
<DT><B>wa</B><DD><P>Write or Append
name and first argument are.
+
</DL>
 +
<P>The 'flog' function allows you to split up your logs in the log directory
 +
so that you don't end up with everything in the main vme.log.
 +
<P><B>Note:</B>
 +
  The append/write argument must be in lower case and can only be a 'w' or a 'a'
 +
  surrounded by '"'.  If the argument is a 'w' it will over write any log file
 +
  by that name.  If the argument is 'a' it will append to the file by that name.
 +
</PRE>
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
; Guild Restrict
+
dilbegin zonelog (s:string);
*
+
code
This function restricts an object to players in a certain
+
{
guild or guilds.  Anyone not in the guild or guilds, will have the damage done as set in the
+
flog (self.zonidx+".log",s,"a");
2nd and 3rd arguments unless none is set.  Even if no damage is set the
+
return;
object will be removed off of the players equipment and placed in their
+
}
inventory.  The following is the definition of the DIL as found in
+
dilend
''function.zon''.
+
</PRE>
<nowiki>
+
<HR>
dilbegin guild_restrict
+
</CODE></BLOCKQUOTE>
(guilds:stringlist,damage:integer,percent:integer,action:string);</nowiki>
+
<P>The previous DIL function will work in any zone to log to a file with that zones
As the definition indicates the first argument is a stringlist.  This
+
name each zone could use it to keep zone logs separate.
means you can restrict this item to more than one guild.  All guilds in
 
the string list will be able to wear this object. If we wanted to make
 
an item that only Paladins and sorcerers could wear it would look like
 
this.
 
<nowiki>
 
dilcopy guild_restrict@function ({"Midgaard Paladin",
 
                        "Midgaard Sorcerer"},0,25,"");</nowiki>
 
;Anti-guild Restrict
 
: This function restricts an object to players not in a certain guild or guilds.  Anyone not in the guild or guilds listed, will have the damage done as set in the 2nd and 3rd arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.  The following is the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin anti_guild_restrict
 
(guilds:stringlist,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first argument is a stringlist.  This
 
means you can restrict this item from more than one guild.  All guilds in
 
the string list will not be able to wear this object.  If we wanted to make
 
an item that only Paladins and sorcerers could not wear it would look like
 
this.
 
<nowiki>
 
dilcopy anti_guild_restrict@function ({"Midgaard Paladin",
 
                              "Midgaard Sorcerer"},0,25,"");</nowiki>
 
;Quest Restrict
 
: This function restricts an object to players who have done a certain quest.  Any  player who has not done the quest,
 
will have the damage done as set in the 2nd and 3rd arguments unless
 
none is set.  Even if no damage is set the object will be removed off of
 
the players equipment and placed in their inventory.  The following is
 
the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin quest_restrict
 
(qst:string,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first argument is a string.  The
 
quest restrict is only made to restrict the by one quest at a time.  If
 
you want the item to have multiple quests restrictions you just add
 
another dilcopy to it.  The following Would be an object
 
restricted to one quest.
 
<nowiki>
 
dilcopy quest_restrict@function ("Eagles quest complete",0,25,"");</nowiki>
 
;Quests Restrict
 
: This function restricts an object to players who have a certain quest or quests.  Anyone not having all quests in the list of quests, will have the damage done as set in the 2nd and 3rd arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.  The following is the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin quests_restrict
 
(qsts:stringlist,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first argument is a stringlist.  This
 
means you can restrict this item to more than one quest.  Players that
 
have not done every quest will not be able to use the object.
 
If we wanted to make an item that only players that have finished both
 
the 'Eagles quest complete' and the 'Feather fall quest complete' could
 
wear.  It would look like this.
 
<nowiki>
 
dilcopy quests_restrict@function ({"Eagles quest complete",
 
                          "Feather fall quest complete"},0,25,"");</nowiki>
 
;Alignment Restrict
 
: This function restricts an object to players with a certain alignment range.
 
Anyone not in the alignment range,
 
will have the damage done as set in the 3nd and 4th arguments unless
 
none is set.  Even if no damage is set the object will be removed off of
 
the players equipment and placed in their inventory.
 
  
We said at the beginning of this section that all restricts have
+
<PRE>
only 4 arguments.  This was a bit of a lie since this restrict has five
+
<hr><a name="bfgword">
arguments.  The reason we didn't count this one is because the first and
+
string getword ( var s : string )
second argument in the alignment restrict function are used together and
+
  s : A string with zero or more words separated by space.
thus are only really one argument. The following is the definition of the DIL as found in
+
  return: The first word of the string.
''function.zon''.
 
<nowiki>
 
dilbegin ali_restrict
 
(max:integer,min:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first and second arguments are two
 
integers.  the first is the max alignment that can wear or use this
 
object and the second is the minimum alignment.  So if we wanted to
 
restrict an item to only good players it would look like this.
 
<nowiki>
 
dilcopy ali_restrict@function (1000,350,0,25,"");</nowiki>
 
;Level restrict
 
: This function restricts an object to players above or equal to a certain level.  Any player not at least the level or higher, will have the damage done as set in the 2nd and 3rd arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.  This restrict works in the old level system from one to fifty which means if the level restrict is set higher than fifty no player will be able to wear or use this object.  This is good if you have objects that only your administrators should be able to use.  If you want to restrict an object to greater than level fifty for players you need to use the 'vlevel' restrict.  The following is the definition of the DIL as found in ''function.zon''.
 
<nowiki>
 
dilbegin level_restrict
 
(lvl:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first argument is an integer.  The
 
integer for the level restrict can range from 1 to 255.  Thus if we
 
wanted to make an object that only administrator could wear or use it would
 
look like this
 
<nowiki>
 
dilcopy level_restrict@function (51, 0,25,"");</nowiki>
 
;Virtual Level Restrict
 
: This function restricts an object to players above or equal to a certain level.  Any player not at least the level or higher, will have the damage done as set in the 2nd and 3rd arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.  This restrict works in the new level system from one to infinity.
 
The following is the definition of the DIL as found in ''function.zon''.
 
<nowiki>
 
dilbegin vlevel_restrict
 
(lvl:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first argument is an integer.  The
 
integer for the level restrict can range from 1 to infinite.  Thus if we
 
wanted to make an object that only players that have reached the level
 
of 5000 could wear or use, it would look like this.
 
<nowiki>
 
dilcopy vlevel_restrict@function (5000, 0,25,"");</nowiki>
 
;Race restrict
 
: This function restricts an object from players of a certain race. Any player not of the selected race, will have the damage done as set in the 2nd and 3rd arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.  The following is the definition of the DIL as found in ''function.zon''.
 
<nowiki>
 
dilbegin race_restrict
 
(rc:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first argument is an integer.  The
 
integer being passed in should be the race you want to restrict the
 
object from.  You can pass in the defines as listed in (Link to app-c) or if you have added races you will find the list of
 
races in ''values.h''. If we wanted to restrict an
 
object from humans the following is what it would look like.
 
<nowiki>
 
dilcopy race_restrict@function (RACE_HUMAN,0,25,"");</nowiki>
 
;Gender restrict
 
: This function restricts an object to players of a certain gender.  Anyone not of the gender, will have the damage done as set in the 2nd and 3rd arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.  The following is the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin sex_restrict
 
(sx:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first argument is an integer.  The
 
integer you should pass in is one of the defines from
 
''vme.h''.  The gender defines are as follows.
 
<nowiki>
 
#define SEX_NEUTRAL  0
 
#define SEX_MALE      1
 
#define SEX_FEMALE    2</nowiki>
 
If we wanted to make an item that could only be worn by a female
 
player, it would look like this.
 
<nowiki>
 
dilcopy sex_restrict (SEX_FEMALE,0,25,"");</nowiki>
 
;Player restrict
 
: This function restricts an object to players who have a specific name. Any player of the wrong name, will have the damage done as set in the 2nd and 3rd arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.  The following is the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin ply_restrict
 
(pname:string,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first argument is a string.  The
 
quest restrict is only made to restrict the quest to one person at a
 
time.  While this DIL was designed to be put on when a player receives a
 
quest item and thus was made to be dilcopied in a DIL you can still put
 
it on when you first create the object if you are making special items
 
for administrators or players that you know in advance.  If you want more
 
information about copying a DIL from with in another DIL you will have
 
to read the DIL manual If however you want to restrict this to a single
 
player at compile time of your zone it would look something like
 
this.
 
<nowiki>
 
dilcopy ply_restrict@function ("Whistler",0,25,"");</nowiki>
 
;Ability restrict
 
: This function restricts an object from a player with less than a certain amount of a certain ability. Any player not having the correct amount of a certain ability, will have the damage done as set in the 3nd and 4th arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.
 
  
We said at the beginning of this section that all restricts have
+
  NB: The argument string has the returned word removed.
only 4 arguments.  This was a bit of a lie since this restrict has five
 
arguments.  The reason we didn't count this one is because the first and
 
second argument in the ability restrict function are used together and
 
thus are only really one argument. The following is the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin abi_restrict
 
(abi:integer,min_abi:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first and second arguments are two
 
integers.  the first is the ability type and the second is the amount of
 
that ability the player needs to have or greater to wear or use the
 
item.  the ability types can be found in ''vme.h'' and
 
are listed here for convenience.
 
<nowiki>
 
#define ABIL_MAG              0
 
#define ABIL_DIV              1
 
#define ABIL_STR              2
 
#define ABIL_DEX              3
 
#define ABIL_CON              4
 
#define ABIL_CHA              5
 
#define ABIL_BRA              6
 
#define ABIL_HP                7</nowiki>
 
If you wanted to restrict an object to people having more than 50%
 
strength it would look like this:
 
<nowiki>
 
dilcopy abi_restrict@function (ABIL_STR,50,0,25,"");</nowiki>
 
If you want to restrict an object to more than one ability you
 
only need to add another restrict to the item.  For example if you
 
wanted to restrict it to people having greater than or equal to 50%
 
divine and 30% brain.  The item would have these two lines.
 
<nowiki>
 
dilcopy abi_restrict@function (ABIL_DIV,50,0,25,"");
 
dilcopy abi_restrict@function (ABIL_BRA,30,0,25,"");</nowiki>
 
;Skill restrict
 
: This function restricts an object from a player with less than a certain amount of a certain skill. Any player not having the correct amount of a certain skill, will have the damage done as set in the 3nd and 4th arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.
 
  
We said at the beginning of this section that all restricts have
+
<hr><a name="bfgwords">
only 4 arguments.  This was a bit of a lie since this restrict has five
+
stringlist getwords ( var s : string )
arguments.  The reason we didn't count this one is because the first and
+
       s : A string with zero or more words separated by space.
second argument in the skill restrict function are used together and
+
  return: A stringlist where each string was a word in 's'.
thus are only really one argument. The following is the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin ski_restrict
 
(ski:integer,min_ski:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first and second arguments are two
 
integers.  the first is the skill and the second is the amount of
 
that skill the player needs to have or greater to wear or use the
 
item.  the skills can be found in (Link to app-g) and
 
''values.h''. We have also included the first five skills
 
here for convenience in explaining how the function works.
 
<nowiki>
 
#define SKI_TURN_UNDEAD        0
 
#define SKI_SCROLL_USE        1
 
#define SKI_WAND_USE          2
 
#define SKI_CONSIDER          3
 
#define SKI_DIAGNOSTICS       4</nowiki>
 
If you wanted to restrict an object to people having more than 50%
 
'turn undead' it would look like this:
 
<nowiki>
 
dilcopy ski_restrict@function (ASKI_TURN_UNDEAD,50,0,25,"");</nowiki>
 
If you want to restrict an object to more than one skill you
 
only need to add another restrict to the item. For example if you
 
wanted to restrict it to people having greater than or equal to 50%
 
in 'turn undead' and 30% in 'scroll use'.  The item would have these two lines.
 
<nowiki>
 
dilcopy ski_restrict@function (SKI_TURN_UNDEAD,50,0,25,"");
 
dilcopy ski_restrict@function (SKI_SCROLL_USE,30,0,25,"");</nowiki>
 
;Spell restrict
 
: This function restricts an object from a player with less than a certain amount of a certain spell. Any player not having the correct amount of a certain spell, will have the damage done as set in the 3nd and 4th arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.
 
  
We said at the beginning of this section that all restricts have
+
<hr><a name="bfghead">
only 4 arguments.  This was a bit of a lie since this restrict has five
+
unitptr ghead ( )
arguments.  The reason we didn't count this one is because the first and
 
second argument in the spell restrict function are used together and
 
thus are only really one argument. The following is the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin sp_restrict
 
(spl:integer,min_sp:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first and second arguments are two
 
integers.  the first is the spell and the second is the amount of
 
that spell the player needs to have or greater to wear or use the
 
item.  the spells can be found in (Link to app-h) and
 
''values.h''. We have also included the first five
 
spells here for convenience in explaining how the function works.
 
<nowiki>
 
#define SPL_LOCK              52
 
#define SPL_UNLOCK            53
 
#define SPL_DROWSE            54
 
#define SPL_SLOW              55
 
#define SPL_DUST_DEVIL        56</nowiki>
 
If you wanted to restrict an object to people having more than 50%
 
'lock' spell, it would look like this:
 
<nowiki>
 
dilcopy sp_restrict@function (ASPL_LOCK,50,0,25,"");</nowiki>
 
If you want to restrict an object to more than one spell you
 
only need to add another restrict to the item.  For example if you
 
wanted to restrict it to people having greater than or equal to 50%
 
in 'lock' and 30% in 'unlock' spells.  The item would have these two lines.
 
<nowiki>
 
dilcopy sp_restrict@function (SPL_LOCK,50,0,25,"");
 
dilcopy SPL_restrict@function (SPL_LOCK,30,0,25,"");</nowiki>
 
;Weapon restrict
 
: This function restricts an object from a player with less than a certain amount of a certain weapon. Any player not having the correct amount of a certain weapon, will have the damage done as set in the 3nd and 4th arguments unless none is set.  Even if no damage is set the object will be removed off of the players equipment and placed in their inventory.
 
  
We said at the beginning of this section that all restricts have
+
return the first unit in the global list which will be the last
only 4 arguments.  This was a bit of a lie since this restrict has five
+
char to have logged on.
arguments.  The reason we didn't count this one is because the first and
 
second argument in the weapon restrict function are used together and
 
thus are only really one argument. The following is the definition of the DIL as found in
 
''function.zon''.
 
<nowiki>
 
dilbegin weap_restrict
 
(wpn:integer,min_wpn:integer,damage:integer,percent:integer,action:string);</nowiki>
 
As the definition indicates the first and second arguments are two
 
integers.  the first is the weapon and the second is the amount of
 
that weapon the player needs to have or greater to wear or use the
 
item.  the weapons can be found in (Link to app-d) and
 
''values.h''. We have also included the first five
 
weapons here for convenience in explaining how the function works.
 
<nowiki>
 
#define WPN_BATTLE_AXE    7  /* Two Handed */
 
#define WPN_HAND_AXE      8
 
#define WPN_WAR_MATTOCK  9  /* Two Handed */
 
#define WPN_WAR_HAMMER  10
 
#define WPN_GREAT_SWORD  11  /* Two Handed */</nowiki>
 
If you wanted to restrict an object to people having more than 50%
 
'battle axe', it would look like this:
 
<nowiki>
 
dilcopy weap_restrict@function (WPN_BATTLE_AXE,50,0,25,"");</nowiki>
 
If you want to restrict an object to more than one weapon you
 
only need to add another restrict to the item.  For example if you
 
wanted to restrict it to people having greater than or equal to 50%
 
in 'hand axe' and 30% in 'battle axe' spells.  The item would have these two lines.
 
<nowiki>
 
dilcopy weap_restrict@function (WPN_HAND_AXE,50,0,25,"");
 
dilcopy weap_restrict@function (WPN_BATTLE_AXE,30,0,25,"");</nowiki>
 
==== Tuborg function ====
 
  
What game would be complete with out the Denmark water!  With that
+
<hr><a name="bfsplit">
in mind the VME 2.0 has a tuborg function that makes a drink give
+
stringlist split ( var s : string, var t : string)
endurance and health when drankThe function is defined in
+
      s : A string with zero or more words separated by var t.
''function.zon'' as follows:
+
  return: A stringlist where each string was a word in 's'
<nowiki>
+
          separated by string 't'.
dilbegin tuborg (s:string);</nowiki>
+
 
As the definition indicates the tuborg function only has one
+
  You can use '&amp;x' to split a string by lineThis is very usefull when reading in files with 'loadstr'.
argument.  The real surprise is that the argument is not used yet in the
+
<P>
DIL so no matter what you set it to it doesn't matter.  In the future
+
<H2><A NAME="bfleft"></A>
this argument is going to allow different kinds of tuborgs to be made
+
</H2>
but for now its just a place holder and all that is needed is a set of
 
double quotes.
 
  
To create a tuborg you just add the following line to your drink
+
<P><B>Function:</B>  <CODE>string left ( o : string, l : integer );</CODE>
container.
+
<DL>
<nowiki>
+
<DT><B>o</B><DD><P>the original string to be parsed
dilcopy tuborg@function ("");</nowiki>
+
<DT><B>l</B><DD><P>The amount of characters to parse out
==== Message board ====
+
<DT><B>return</B><DD><P>the left portion of the string with length l
 +
</DL>
 +
<P>This function parses the string passed to it and returns the number
 +
of characters defined in its second argument.
  
Every game needs a way for Administrators and players to exchange
+
<P><B>Example:</B> <CODE>"short" := left ("shorten me",5);</CODE>
ideas.  The message boards have been designed for this purpose.  The
+
<P><B>Example:</B>
boards function can be easy to use or more difficult depending on what
+
<BLOCKQUOTE><CODE>
all you want them to do.  The board function is defined in
+
<HR>
''boards.zon'' as follows.
+
<PRE>
  <nowiki>
 
dilbegin board
 
(idxfile:string,l_res:string,r_res:string,p_res:string,bmax:integer);</nowiki>
 
This looks pretty hard I know but to make a normal board we have
 
made it as simple as possible while allowing for the boards to be used
 
in almost any situation.  After you make your first board it is pretty
 
much block and copy and change the first argument.  The arguments are as
 
follows:
 
  
;idxfile
+
dilbegin aware describe (arg:string);
: The first argument is the board index filename.  It tells the board DIL what name to store the board under so if you create more boards with the same name they will all be pointing to the same messages.  You can put any legal symbolic name in this string and it will work with no problems.
+
var
;l_res
+
        side:string;
: the second argument is a DIL you pass in that does any checks to see if the player looking at the board is allowed to. This requires some knowledge in DIL but we have given some example DIL functions in the
+
        oneword:stringlist;
''boards.zon''.
+
        location:string;
<nowiki>
+
        ln:integer;
//used to restrict players access to a board
+
        args:stringlist;
dilbegin string admin_res (u:unitptr,v:unitptr);
+
        temp:string;
 +
        i:integer;
 +
        x:extraptr;
 +
code
 +
{
 +
        if (self.type!=UNIT_ST_PC)
 +
                quit;
 +
        if (self.position &lt;POSITION_SLEEPING)
 +
        {
 +
        act ("Recover first and then you can describe your body parts.",
 +
        A_ALWAYS,self,null,null,TO_CHAR);
 +
                quit;
 +
        }
  
//used to restrict non-admin from removing posts
+
        args:=getwords(arg);
dilbegin string rem_res (u:unitptr, v:unitptr);</nowiki>
+
        ln:=length(args);
So with the 'admin_res' you could do something like
+
        if ((ln&lt;1) or (ln>2))
this:
+
        {
<nowiki>
+
        sendtext ("No such location to describe.",self);
dilcopy board@boards ("wizbrd","admin_res@boards"...);</nowiki>
+
        quit;
Putting the 'admin_res' function in the second argument would make
+
        }
it so only administrators could look at the board.  If you put an empty
+
        else if (ln>1)
string or two double quotes as the argument it will let anyone look at
+
        goto two_word;
the board.
 
;r_res
 
: the third argument is a DIL you pass in that does any checks to see if the player trying to remove a post at the board is allowed to.  This requires some knowledge in DIL but we have given some example DIL functions in the
 
''boards.zon''
 
<nowiki>
 
//used to restrict players access to a board
 
dilbegin string admin_res (u:unitptr,v:unitptr);
 
  
//used to restrict non-admin from removing posts
+
        :one_word:
dilbegin string rem_res (u:unitptr, v:unitptr);</nowiki>
 
So with the 'rem_res' you could do something like
 
this:
 
<nowiki>
 
dilcopy board@boards ("citizen","","rem_res@boards",...);</nowiki>
 
With the 'rem_res' in the third argument only administrators can
 
now remove from this board but anyone can look at it because of the empty
 
string in the second argument.  Putting an empty string in the third
 
argument will make it so anyone can remove from this board.
 
;p_res
 
: the forth argument is a DIL you pass in that does any checks to see if the player trying to post at the board is allowed to.  This requires some knowledge in DIL but we have given some example DIL functions in the
 
''boards.zon''.
 
<nowiki>
 
//used to restrict players access to a board
 
dilbegin string admin_res (u:unitptr,v:unitptr);
 
  
//used to restrict non-admin from removing posts
+
        if ((arg==left("help",length(arg))) or
dilbegin string rem_res (u:unitptr, v:unitptr);</nowiki>
+
                (arg==""))
As you can see we haven't made a post restriction DIL because as of
+
                goto hlp_dscr;
yet we haven't found a need for one.  If you have a need for one just
 
look over the two restrict DIL functions we have already mentioned and you will
 
find it is really easy to make.  We want to allow anyone to post so our
 
dilcopy looks like this:
 
<nowiki>
 
dilcopy board@boards ("citizen","","rem_res@boards","",...);</nowiki>
 
With the 'rem_res' in the third argument only administrators can
 
now remove from this board but anyone can post to it because of the empty
 
string in the forth argument.  The empty string again in the second
 
argument also allows everyone to look at the board.
 
;max
 
: The fifth argument is simply the amount of posts that you want to allow to be posted before the board is full.
 
  
To make a free for all board where everyone can post, remove
+
        oneword := {"arms","butt","ears","eyes","face","feet",
posts, look at what posts are on the board, and have a max of 50 posts it would simply be as
+
            "general","hair","hands","head","legs",
follows:
+
"mouth","neck","nose","nostrils","teeth",
<nowiki>
+
"toes","tongue"};
dilcopy board@boards("citizen","","","",50);</nowiki>
 
When making a board for players to post concerns to the
 
administrators and only have the administrators be able to remove them,
 
wile still allowing everyone to read them it would look like
 
this.
 
<nowiki>
 
dilcopy board@boards("citizen","","rem_res@boards","",100);</nowiki>
 
=== More complex objects ===
 
  
In the last sections you learned all the fields and how to make a
+
        i := 0;
basic object. In this section we will use the information from the last
+
        ln := length(args.[0]);
sections to create some more unique objects for our dragon station zone
+
        temp:="ERROR";
There is not a lot of new information here we will be using the DIL functions,
+
        while (i&lt;18)
fields, and flags to make objects we have only mentioned before.
+
        {
==== Making a communication board ====
+
                if (args.[0]==left(oneword.[i],ln))
 +
                {
 +
                        temp := oneword.[i];
 +
                        break;
 +
                }
 +
                i := i+1;
 +
        }
  
In (Link to objdilboard) you learned all there you need to
+
        if (temp=="ERROR")
know about the boards DIL to create a board. In this small section we
+
        {
are going to show you the rest of a board and what a finished one looks
+
                sendtext ("No such location to describe.",self);
like.
+
                quit;
 +
        }
  
As with all objects the first step is to fully describe and name
+
        goto describe;
your board.  We will stick with the space station theme since our goal
 
is to have a complete example zone for you.  The boards symbolic, names, title,
 
description and extra turned out like this.
 
<nowiki>
 
info_board
 
  
title "a merchant information board"
+
        :two_word:
descr "A merchant information Board is mounted on a wall here."
 
  
names {"merchant information board","information board","merchant
+
        oneword := {"arm","leg","foot","hand","eye","ear"};
board","board"}
+
        temp := "ERROR";
 +
        ln := length(args.[0]);
 +
        if (args.[0] == left("left",ln))
 +
                side:="left";
 +
        else if (args.[0] == left("right",ln))
 +
                side:="right";
 +
        else
 +
        {
 +
                sendtext ("No such location to describe.",self);
 +
                quit;
 +
        }
  
extra {} "A large flashy black steal board."</nowiki>
+
        i := 0;
Just incase the VME server we have has a spell that can damage
+
        while (i&lt;6)
inanimate objects we will give this board a material type.
+
        {
<nowiki>
+
                if (args.[1]==left(oneword.[i],ln))
MATERIAL_METAL("A very fine quality black steel")</nowiki>
+
                {
Now for the special stuff for the board.  We need to give the
+
                        temp := oneword.[i];
board a type and copy the board DIL to it.
+
                        break;
<nowiki>
+
                }
type ITEM_BOARD
+
                i := i+1;
dilcopy board@boards("info","","rem_res@boards","",100);</nowiki>
+
        }
There you go nothing to it you have just created your first board.
 
Now lets bring it all together and tag on an end symbol and we are all
 
finished.
 
<nowiki>
 
info_board
 
title "a merchant information board"
 
descr "A merchant information Board is mounted on a wall here."
 
names {"merchant information board","information board","merchant
 
board","board"}
 
  
extra {}
+
        if (temp=="ERROR")
"A large flashy black steal board."
+
        {
 +
                sendtext ("No such location to describe.",self);
 +
                quit;
 +
        }
  
MATERIAL_METAL("A very fine quality black steel")
+
        temp := side+" "+temp;
type ITEM_BOARD
 
dilcopy board@boards("info","","rem_res@boards","",100);
 
  
end</nowiki>
+
        :describe:
==== Making a container ====
+
        if (temp=="General")
 +
                location := "";
 +
        else
 +
                location := temp;
  
I thought it would be cool to have a small weapons locker on the
+
        x := location in self.extra;
space station not to mention event hough we went over the container
+
        if (x!=null)
macro in (Link to objmacrocontainer), we didn't cover everything
+
          if (location=="")
you need in fact the macro eaves a few things out because you may or may
+
sendtext("your Current description for your body is:  &amp;n"+x.descr+"&amp;n",self);
not want to set them.
+
        else
 +
sendtext("your Current description for your "+location+"is:  &amp;n"+x.descr+"&amp;n",self);
 +
        if (location=="")
 +
sendtext ("Enter a text you would like others to see when they look at your body.&amp;n",self);
 +
        else
 +
sendtext ("Enter a text you would like others to see when they look at your "+location+".&amp;n",self);
  
As with all objects we start right off by describing the item.
+
        beginedit (self);
There is nothing new here so we will just show it to you and go
+
        wait(SFB_EDIT,self==activator) ;
on.
+
        temp := textformat(argument);
<nowiki>
+
        oneword:={""};
wpn_locker
+
        subextra(self.extra,location);
 +
        addstring (oneword, location);
 +
        addextra (self.extra,oneword,temp);
 +
        sendtext ("Description added.&amp;n",self);
 +
        quit;
  
title "a weapons locker"
+
        :hlp_dscr:
names {"weapons locker","weapon locker","locker"}
 
  
descr "a small weapons locker hangs on the wall here."
+
        sendtext ("&amp;nCorrect usage of 'describe':&amp;n&amp;n",self);
 +
        sendtext ("describe &lt;position>&amp;n&amp;n",self);
 +
        sendtext("&lt;position> being one of the following:&amp;n&amp;n",self);
 +
        sendtext( "arms        butt        ears        eyes&amp;n"+
 +
                  "face        feet        General    hair&amp;n"+
 +
                  "hands      head        left arm    left leg&amp;n"+
 +
                  "left foot  left hand  left eye    left ear&amp;n"+
 +
                  "legs        mouth      neck        nose&amp;n"+
 +
                  "nostrils    right arm  right leg  right foot&amp;n"+
 +
                  "right hand  right eye  right ear  teeth&amp;n"+
 +
                  "toes        tongue&amp;n&amp;n",self);
 +
        sendtext ("Example:  &amp;n&amp;n",self);
 +
        sendtext ("describe left leg&amp;n",self);
 +
        quit;
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<PRE>
 +
<hr><a name="bflen">
 +
integer length ( a : string or stringlist )
 +
      a : a string or stringlist to examine.
 +
  return: The length of the string in characters, or the number
 +
          of strings in a list.
  
extra {}
+
<hr><a name="bfload">
"It is an ordinary weapons locker that looks like it holds any illegal
 
weapons that are taken on the station."</nowiki>
 
Now we need to put in all the information that makes this item a
 
container that can't be taken but it can be opened and it is
 
locked.
 
<nowiki>
 
manipulate {MANIPULATE_ENTER}
 
CONTAINER_DEF(500)
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
key black_key</nowiki>
 
Notice we didn't make the item 'MANIPULATE_TAKE' because
 
we don't want people to be able to walk off with our weapons locker.
 
One final touch and we are all finished with the weapons locker.  It is
 
always nice to put a material type on your items so a spell or a skill
 
can tell if you can do anything with them.  So with our material added
 
in the full locker would look like this.
 
<nowiki>
 
wpn_locker
 
  
title "a weapons locker"
+
unitptr load ( s : string )
names {"weapons locker","weapon locker","locker"}
+
  s : Symbolic name of unit.
descr "a small weapons locker hangs on the wall here."
+
  return: A pointer to the unit, or null
 +
  Example: load("garlic@midgaard")
 +
  The loaded unit is automatically placed inside the object
 +
  which loaded it.  Use for example the link command to move
 +
  it into other units.
  
extra {}
+
<H2><A NAME="bfloadstr"></A>
"It is an ordinary weapons locker that looks like it holds any illegal
 
weapons that are taken on the station."
 
  
MATERIAL_METAL("A very fine quality steel")
+
</H2>
 +
</PRE><PRE>
 +
<P><B>Function:</B>
 +
<CODE>integer loadstr( filename : string , buff : string );</CODE>
 +
<DL>
 +
<DT><B>filename</B><DD><P>The name of the string file to be loaded
 +
<DT><B>buff</B><DD><P>The string that you wish to read the file contents into
 +
<DT><B>Return</B><DD><P><CODE>FILE_LOADED, FILE_NOT_FOUND, FILE_OUT_OF_MEMORY,or FILE_TO_LARGE</CODE>
 +
</DL>
 +
<P>Loadstr is used to load strings from disk that were saved either by savestr
 +
or any text editor.
 +
The 'loadstr' is perfect for operations such as
 +
on-line edited newspaper, a lottery where the tickets are sold to players,
 +
creating smarter NPC's that can remember through reboots who they are hunting,
 +
Dil based teachers, message boards, mail system, news command., zone or
 +
room based help,  competition boards, and much much more.
 +
<P><B>Disk access is always slow</B>.
 +
attempt to keep file sizes to a minimum for quick loading.  Otherwise you
 +
might cause serious delays on the server.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE><PRE>
  
manipulate {MANIPULATE_ENTER}
+
dilbegin news_load ();
CONTAINER_DEF(500)
+
var
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
+
        ret:integer;/*to hold the return value if loaded or not*/
key black_key
+
        buff:string;/*to hold the loaded string*/
 +
code
 +
{
 +
ret:= loadstr("news.txt",buff);
 +
if (!ret)
 +
        {
 +
        log ("File not read.");
 +
        quit;
 +
        }
  
end</nowiki>
+
sendtext(buff+"[&amp;]n",self);
==== Creating drinks ====
+
quit;/*dil load routine done destroy self.*/
 +
}
 +
dilend
 +
</PRE><PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>See Also</B> <CODE>
 +
<A HREF="#bfdelstr">Delete a String file</A> and
 +
<A HREF="#bfsavestr">Save String file</A></CODE>
  
In (Link to objmacroliqcont), we covered how to set the size and weight of the container and its content but now we need to talk about some other special things about a drink container verses other objects.
+
<hr><a name="bforoll">
 +
integer openroll( dice : integer , end : integer )
 +
  dice : The size of the dice being rolled.
 +
  end  : The margin for the open-ended roll.
 +
  return: A random integer in approximately +/- 2^31 in worst case.
 +
  Example: i := openroll(100,5); The "100" roll continues on values
 +
            96 - 100 and on values 1 - 5.
  
The drink container is one of the few objects that has rules on
+
<hr><a name="bfpathto">
how you set the title, description and names fields.  The title and
+
integer pathto( from : unitptr, to : unitptr )
description fields should ot have anything to do with the liquid inside
+
  from  : The unit which the path is taken from
the container.  This means if you have a barrel full of water you do not
+
  to    : The unit which the path is taken to
put the word water in the title or the description.  In our case we have
+
  returns: DIR_XXX from values.h and/or vme.h.
a bag full of wine so we do not put wine in either the title or
+
  Example: i := pathto(self, findroom("inn@midgaard"));
description. The reason for this is if the player drinks the bag empty
 
and then fills it with water and we had put wine in the title or
 
description it would still be there but the bag would now be full of
 
water.. Our symbolic, title, and description would then look like
 
this.
 
<nowiki>
 
liq_ration
 
  
title "a red bag"
+
<hr><a name="bppagestring">
descr "A red bag has been gently placed here."</nowiki>
+
pathto(buff : string, u : unitptr )
The names on the other hand MUST have the drink name as the last
+
  buff  : The string that is to be paged to the player.
name in the name list.  The reason it must be the last one is when a
+
u : The unitptr the buff is to be paged for.
player drinks or pours out the liquid the name is removed. If a player
+
  returns: nothing
then refills the container the name of the new liquid is added to the
+
example:
last name. The bag we are making is full of wine so our names list would
+
pagestring (buff,self);
look like this.
+
would format the buff string to the player so the buff text doesn't scroll
<nowiki>
+
off the screen until after the player presses enter.
names {"red bag", "bag", "wine"}</nowiki>
 
Now we add the liquid define for wine
 
<nowiki>
 
LIQ_WINE(1,2,2,0)</nowiki>
 
Finally we add the material type for the bag, the cost to buy the
 
container, an extra players can look at, and finally an identify extra so
 
if a player casts either the identify or improved identify spell on the
 
bag they will se it. with all that added The finished drink container
 
looks like this.
 
<nowiki>
 
liq_ration
 
names {"red bag", "bag", "wine"}
 
title "a red bag"
 
descr "A red bag has been gently placed here."
 
  
extra {}
 
"A small label reads Tassel Grove's finest.  Year 321"
 
  
MATERIAL_ORGANIC("a soft plastic")
+
<P>
manipulate {MANIPULATE_TAKE}
+
<H2><A NAME="bfright">
LIQ_WINE(1,2,2,0)
 
cost 2 IRON_PIECE
 
  
extra {"$identify"}
+
</H2>
"Its the special wine from Tassel grove a small halfling village on the
 
planet Valhalla.  It seems like a great vintage wine."
 
  
end</nowiki>
+
<P><B>Function:</B>  <CODE>string right ( o : string, r : integer );</CODE>
==== Creating food ====
+
<DL>
 +
<DT><B>o</B><DD><P>the original string to be parsed
 +
<DT><B>r</B><DD><P>The amount of characters to parse out
 +
<DT><B>return</B><DD><P>the right portion of the string with length r
 +
</DL>
 +
<P>This function parses the string passed to it and returns the number of characters
 +
from the right defined in its second argument.
 +
<P><B>Example:</B>  <CODE>"Easy" := right ("This is Easy",4);</CODE>
  
The food is very simple to make its just a regular item with the
+
<hr><a name="bfrnd">
macros you learned in (Link to objmacrofood). In fact making
+
integer rnd ( i1 : integer , i2 : integer )
food is so simple we almost left it out. I am only adding this to show
+
  i1 : Start of range.
how simple it is to change a regular item like the dragon head we showed
+
  i2 : End of range.
you in (Link to objbasic) into a food item. Now only a sick
+
  return: A random integer in an interval from 'i1' to 'i2'.
person would make a dragon head into food but if you wanted to you just
+
  Example: i := rnd(1,10);
add the 'FOOD_DEF(...)' and your all set.  here is a basic food that you
 
might find laying around a space station.
 
<nowiki>
 
beef_stick
 
  
title "a tough leathery stick"
+
</PRE><PRE>
descr "A tough leathery looking stick is laying here."
+
<IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%"><br><a name="biproc">
names {"tough leathery stick","tough leather stick","leathery stick",
+
<h3>Built-In Procedures:</h3>
"leather stick","tough stick","stick"}
+
    DIL features some built-in procedures that allows you increased control over
 +
  in-game data structures and event handling. Once such procedure (used above)is
 +
  'exec()'. The inline procedures are used as any other procedure by typing its
 +
  name, followed by a list of argument expression enclosed in parentheses. The
 +
  return types of the expressions used for built-in procedure calls are checked
 +
  by the compiler.
  
extra {}
+
    DIL also lets you call templates defined in the current or other zones.  The
"This has the word BEEF burnt into it."
+
  naming of templates follows the normal naming convention for zone, using the
 +
  'name@zone' as a symbolic name for a procedure.  Before being able to use
 +
  external procedures, you must define their name and type in a separate
 +
  'external' section in the template.  The declaration in the 'external' section
 +
  should match the original declaration of the referenced program. You can define
 +
  the number and type of arguments the template take, by listing them inside the
 +
  declaration parenthesis (as well as in the original declaration of that template)
 +
  (see example below)
 +
</PRE><PRE>
 +
<b>Example:</b>
  
manipulate {MANIPULATE_TAKE}
+
  <i>dilbegin bar(s:string);
FOOD_DEF(5,0)
+
  code
weight 1
+
  {
cost 1 COPPER_PIECE
+
    exec("say "+s,self);
MATERIAL_ORGANIC("tough beef")
+
    return;
 +
  }
 +
  dilend</i>
  
end</nowiki>
+
  <i>dilbegin foo();
==== Making a weapon ====
+
  external
 +
    someproc@hades1();
 +
    bar(s:string);
 +
  code
 +
  {
 +
    someproc@hades1();
 +
    bar("Hello "+activator.name);
 +
    pause;
 +
  }
 +
  dilend</i>
 +
</PRE><PRE>
 +
    When the procedure is called, the argument expressions are calculated, and
 +
  passed to the template.  Built-in procedures, their arguments and function
 +
  are listed later.
  
Whats a game with out some kind of weapon to chop or bash things
+
    The following are definitions and documentation for the built-in procedures
into little pieces.  We examined how to set the weapon fields in (Link to objmacroweapon), the object transfers in (Link to objmacrotransfers), and the restriction DIL functions in (Link to objdilrestrict).  Now we will pull all we have learned together
+
  in DIL. The definitions are not definitions 'as such', but serve to distinguish
and make a pretty nifty little stiletto.
+
  arguments in the documentation below.
  
The first part as with all our example objects is to set up the
+
</PRE><PRE>
symbolic, names, title, description, object extra, and material type.  this is no
+
<hr><a name="bpfol">
different from any other object so here is what we ended up with
+
follow( f : unitptr, m : unitptr )
<nowiki>
+
  f : The character to follow
w_stiletto
+
  m : The character to be followed
title "a stiletto"
 
names {"stiletto", "dagger"}
 
descr
 
"A deadly looking stiletto has been left here."
 
  
extra{}
+
  Unconditionally makes 'f' follow 'm', even if 'f' is mortally
"This looks like a thieves dream come true. "
+
  wounded, sleeping, fighting or whatever.
 +
 
 +
</PRE><PRE>
 +
  <P>
 +
<H2><A NAME="bpflog"></a>
 +
</H2>
  
MATERIAL_METAL("A very fine quality steel")</nowiki>
+
<P><B>Function:</B>  <CODE>flog (filename : string,  s : string, wa : string );</CODE>
Now lets add the defines and DIL functions that make this a special weapon
+
<DL>
along with the manipulate flags that makes it able to be wielded. We will give
+
<DT><B>filename</B><DD><P>The Filename of the file to appear in the log directory.
it a bonus in magic and good craftsmanship along with a plus in
+
<DT><B>s</B><DD><P>The string to be logged.
backstab for all those assassins on the game.
+
<DT><B>wa</B><DD><P>Write or Append
<nowiki>
+
</DL>
manipulate {MANIPULATE_TAKE, MANIPULATE_WIELD}
+
<P>The 'flog' function allows you to split up your logs in the log directory
WEAPON_DEF(WPN_DAGGER, 1, 2)
+
so that you don't end up with everything in the main vme.log.
SKILL_TRANSFER(SKI_BACKSTAB, 2)
+
<P><B>Note:</B>The append/write argument must be in lower case and can only be a
dilcopy abi_restrict@function (ABIL_DEX,10,0,25,"");</nowiki>
+
'w' or a 'a' surrounded by '"'.  If the argument is a 'w' it will over write
to finish it off we will give the weapon a cost, rent, and finally
+
any log file by that nameIf the argument is 'a' it will append to the
two identifies for the two identify spellsNow that we have it all
+
file by that name.
defined we pull it together and it looks like this.
+
<P><B>Example:</B>
<nowiki>
+
<BLOCKQUOTE><CODE>
w_stiletto
+
<HR>
title "a stiletto"
+
<PRE>
names {"deadly looking stiletto","deadly stiletto","stiletto", "dagger"}
 
descr
 
"A deadly looking stiletto has been left here."
 
  
extra{}
+
dilbegin zonelog (s:string);
"This looks like a thieves dream come true. "
+
code
 +
{
 +
flog (self.zonidx+".log",s,"a");
 +
return;
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P>The previous DIL function will work in any zone to log to a file with that
 +
zones name each zone could use it to keep zone logs separate.
  
MATERIAL_METAL("A very fine quality steel")
+
<PRE>
  
manipulate {MANIPULATE_TAKE, MANIPULATE_WIELD}
+
<hr><a name="bplogcrime">
WEAPON_DEF(WPN_DAGGER, 1, 2)
+
logcrime( c : unitptr, v : unitptr, t : integer )
SKILL_TRANSFER(SKI_BACKSTAB, 2)
+
  c : The criminal (main suspect)
dilcopy abi_restrict@function (ABIL_DEX,10,0,25,"");
+
  v : The victim
weight 2
+
  t : The crime type (CRIME_XXX)
cost 2 GOLD_PIECE
 
rent 1 COPPER_PIECE
 
  
extra {"$identify"}
+
      Registers a crime committed against 'v' by 'c'. Use the
"The stiletto looks magical in nature and seems really sharp.  You can
+
    CRIME_XXX values from values.h and/or vme.h as the 't' argument.
tell if you wield it you would be able to backstab someone really easy."
+
    The logcrime routine automatically registers group members
 +
    of the criminal, etc. In stuff like steal, remember to make
 +
    the criminal visible if he fails his attempts.
 +
</PRE><PRE>
 +
<hr><a name="bpacc_mod">
 +
acc_modify( u : unitptr, i : integer )
 +
  u : A player
 +
  i : An amount in 1/100s, for example 100 would equal $1.00, and
 +
      -100 would equal -$1.00.
  
extra{"$improved identify"}
+
      Access only allowed with 'root' access and all transactions are
"The stiletto gives you a magical bonus of +1 and has a quality of +2.
+
    registered in the specially encrypted account log file. Use with
It also raises your back stabbing skill  by 2%.  You have to have at
+
    great caution, and always test thoroughly before using.
least 10% in dex before you can wield this magical weapon."
+
    Use without prior permission may cause deletion of god / zone.
 +
      <P>
 +
</PRE><PRE>
 +
<H2><A NAME="#bfstrdir"></A>
 +
</H2>
  
end</nowiki>
+
<P><B>Function:</B>  <CODE>stringlist strdir( match : string ) ;</CODE>
==== Making armour ====
+
<DL>
 +
<DT><B>match</B><DD><P>The wild card file you want to match or '*' for all.
 +
<DT><B>return</B><DD><P>a Stringlist with all the filenames that match the
 +
'match' argument.
 +
</DL>
 +
<P>The 'match' argument uses the same wild cards as the Linux 'ls' command
 +
so the following will work.
 +
<DL>
 +
<DT><B>&ast;</B><DD><P>Match any character or group of characters
 +
<DT><B>&quest;</B><DD><P>Match one of any character
 +
<DT><B>[...]</B><DD><P>Match one of a set of characters
 +
</DL>
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE><PRE>
  
In (Link to objmacroarmour) we explained how to set the
+
"corpse*" matches:  corpse.10938 corpse.whistler corpseofwhistler ...
          armour fields now we will finish off by adding some more
+
"corpse?" matches corpse1 corpses corpse5 ...
          important information about armour in general.
+
"[abc]*" matches ability about cost back ...
 +
"[a-z]*" about zoo man father ...
 +
"start[nm]end" matches startnend startmend
 +
</PRE><PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>Example DIL:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
  
  The most important thing to realize is that not all wear
+
dilbegin wanted ();
          positions on the VME server are armour positions.  In fact
+
var
          only seven of the wear positions count as armour the rest are
+
        wantedlist:stringlist;
          non-armour positions which we will cover next in (Link to objnon-armour).  The following are the armour
+
        templist:stringlist;
          positions and their defines.
+
        i:integer;
{| class="wikitable"
+
        ln:integer;
|+Armour positions
+
code
|-
+
{
!Position
 
!Define
 
|-
 
|head
 
|MANIPULATE_WEAR_HEAD
 
|-
 
|hands
 
|MANIPULATE_WEAR_HANDS
 
|-
 
|arms
 
|MANIPULATE_WEAR_ARMS
 
|-
 
|body
 
|MANIPULATE_WEAR_BODY
 
|-
 
|legs
 
|MANIPULATE_WEAR_LEGS
 
|-
 
|feet
 
|MANIPULATE_WEAR_FEET
 
|-
 
|cloak
 
|MANIPULATE_WEAR_ABOUT
 
|}
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">There is one more field that works as armour, 'MANIPULATE_WEAR_SHIELD' but since that uses another define it is not shown here.  We will leave that for an exercise for you to do later.</blockquote>
 
  
First we do the same as we have for every other item, pick the
+
        wantedlist := strdir ("dead*");
symbolic, title, description, extra description, and material type for the plate.
 
<nowiki>
 
pol_plate
 
names {"polished breast plate","polished plate","breast plate","plate"}
 
title "a polished breast plate"
 
descr "A polished breast plate has been left here."
 
MATERIAL_METAL("A high luster silver colored metal")</nowiki>
 
Now we pick the armour type in this case I want it to be made like
 
plate mail and I want it to have a magical bonus and a high
 
craftsmanship.  Obviously since this is a plate we will pick the body
 
position.
 
<nowiki>
 
manipulate {MANIPULATE_TAKE, MANIPULATE_WEAR_BODY}
 
ARMOUR_DEF(ARM_PLATE,5,9)</nowiki>
 
All that is left is to add the cost, rent, the identify extras,
 
and I felt like putting a 40% strength restriction on the armour.  With
 
all that added together we finish up with the following piece of
 
armour.
 
<nowiki>
 
pol_plate
 
names {"polished breast plate","polished plate","breast plate","plate"}
 
title "a polished breast plate"
 
descr "A polished breast plate has been left here."
 
  
extra{}
+
                i := 0;
"This is one shiny plate it seems to be made out of one perfect piece of
+
                ln := length (wantedlist);
metal.  There doesn't even seem to be any markings of owner ship."
 
  
MATERIAL_METAL("A high luster silver colored metal")
+
        while (i &lt; ln )
 +
                {
 +
                templist := split (wantedlist.[i],".");
 +
                sendtext (templist.[1]+" wanted dead!&amp;n",self);
 +
                i:=i+1;
 +
                }
  
manipulate {MANIPULATE_TAKE, MANIPULATE_WEAR_BODY}
+
quit;
ARMOUR_DEF(ARM_PLATE,5,9)
+
}
 +
dilend
  
dilcopy abi_restrict@function (ABIL_STR,40,0,25,"");
+
</PRE><PRE>
cost 2 GOLD_PIECE
+
<HR>
rent 3 COPPER_PIECE weight 25
+
</CODE></BLOCKQUOTE>
 +
<P>The previous DIL would be an example of a command to check the wanted dead
 +
players on the VME if you saved the files with the first word being
 +
'dead' and separated it with a '.' and the players name. For example if
 +
'whistler' was wanted dead  the file name would be 'dead.whistler'
  
extra{"$identify"}
+
<P>
"This is a high quality plate with a magical feeling."
+
<H2><A NAME="setpassword">
 +
</H2>
  
extra{"$improved identify"}
+
<P><B>Function:</B>  <CODE>set_password( u : unitptr, s : string ) ;</CODE>
"The plate has a magical bonus to your defence of a +5 and a quality of
+
<DL>
+9.  You need 40% in strength to be able to wear it."
+
<DT><B>u</B><DD><P>the unit that you want to set the password of
end</nowiki>
+
<DT><B>s</B><DD><P>the password you are using to set
==== Making non-armour worn objects ====
+
</DL>
 +
<P>This function sets a unit password it only works on Players characters of corse.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE><PRE>
  
In the previous section we defined armour that actually protects
 
the char in combat.  Here we will learn how to make the clothing and
 
jewelery that may not do anything directly to combat but it can give
 
your characters bonuses that help in combat in the long run.  We will
 
start by listing all the non-armour worn positions and their manipulate
 
defines and then we will give a simple ring object.
 
{| class="wikitable"
 
|+Non-armour positions
 
|-
 
!Position
 
!define
 
|-
 
|ear
 
|MANIPULATE_WEAR_EAR
 
|-
 
|neck
 
|MANIPULATE_WEAR_NECK
 
|-
 
|wrist
 
|MANIPULATE_WEAR_WRIST
 
|-
 
|finger
 
|MANIPULATE_WEAR_FINGER
 
|-
 
|chest
 
|MANIPULATE_WEAR_CHEST
 
|-
 
|back
 
|MANIPULATE_WEAR_BACK
 
|-
 
|waist
 
|MANIPULATE_WEAR_WAIST
 
|-
 
|ankle
 
|MANIPULATE_WEAR_ANKLE
 
|}
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">When giving ability, skill, weapon, or spell bonuses make sure you realize that positions like ear, neck, wrist, and ankle can all have two on a player.  This means any bonuses you give can be doubled if the player gets two of them</blockquote>
 
  
I don't want to beat a dead horse so since I have already
+
dilbegin aware do_password (arg:string);
explained armour in (Link to objarmour) the only difference here
+
var
is there is no 'ARMOUR_DEF' everything else is the same.  The following
+
        prmt:string;
was one of the first items my wife made as a new builder and I have
+
  firstpwd:string;
always liked it.  I know, I am a lush but this way I don't have to write
 
an example.
 
  <nowiki>
 
  maskwa
 
  
names {"maskwa platinum ring", "platinum ring","maskwa ring","maskwa","ring"}
+
  i:integer;
title "a Maskwa ring"
+
  tlist:stringlist;
descr "A Maskwa platinum ring is laying here."
 
MATERIAL_METAL("Platinum, and other precious metals")
 
extra {}
 
"The ring has a large bear head. Could this be the legendary head of
 
Maskwa? Any thing formed with its head on it is said to strengthen the
 
wearer."
 
type ITEM_WORN
 
manipulate {MANIPULATE_TAKE, MANIPULATE_HOLD, MANIPULATE_WEAR_FINGER}
 
cost 100 COPPER_PIECE
 
rent 50 IRON_PIECE
 
weight 1
 
STR_TRANSFER(+1)
 
end</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">One last thing I forgot to mention.  The item type also changes but then that is not hard to understand since this is not armour it should be some other thing.  In the case of non-armour worn items the item type is 'ITEM_WORN'.</blockquote>
 
=== Dragon station with rooms, NPCs, and objects ===
 
  
Now we will add the objects we have built to the zone from the
+
code
previous chapter.  This is still not complete while it does compile and
+
{
you can log into your zone, you still have to load your NPCs and objects
 
but they do not load themselves and they are not dressed with their
 
armour.  This will be taken care of in (Link to ch-07) and you
 
will finally have a finished zone.  The following is the source file so
 
far.
 
<nowiki>
 
#include &lt;composed.h&gt;
 
%zone dragonst
 
lifespan 20
 
reset RESET_ANYHOW
 
creators {"whistler"}
 
  
notes
+
if(self.type != UNIT_ST_PC) quit;
"This is the dragon station I shortened it to dragonst for ease in
+
arg:="";
loadingIf you have any questions email me at whistler@valhalla.com"
+
prmt:=self.prompt;
 +
self.prompt:="Enter new password: ";
 +
wait (SFB_CMD,self==activator);
 +
block;
 +
tlist:=getwords (excmdstr);
 +
if (length(tlist)>1){
 +
sendtext ("Password must be only one word. Try again.&amp;n",self);
 +
self.prompt:=prmt;
 +
quit;
 +
}
 +
if (length(excmdstr)&lt;5){
 +
        sendtext ("Password to short. Password must be 5 characters or longer.\
 +
Try again.&amp;n",self);
 +
        self.prompt:=prmt;
 +
        quit;
 +
        }
  
help
+
if (length(excmdstr)>16){
"Not sure what could help you now. You are stuck on one of the
+
        sendtext ("Password to long. Try again.&amp;n",self);
weirdest space stations you have ever seen and you smell burning
+
        self.prompt:=prmt;
sulfur."
+
        quit;
 +
        }
  
%rooms
+
        firstpwd:=excmdstr;
 +
        self.prompt:="Enter password again:  ";
  
chamber
+
wait (SFB_CMD,self==activator);
title "The middle chamber of the station"
+
block;
descr
+
if (excmdstr!=firstpwd){
"This chamber seems to have the entire station rotating around it. It is
+
sendtext ("Passwords do not match try again.&amp;n",self);
unbelievably large the ceiling seems to be a good 200 meeters high and
+
self.prompt:=prmt;
the room is perfectly cubic. Small human size ornate chairs with dragon
+
quit;
designs scrawled on the arms and back are arranged in a triangle like
+
}
setting with one large chair at the front.  This must be where all
+
set_password(self,excmdstr);
station meetings are held. large pictures cover the walls depicting
+
sendtext("Changed your Password to '"+excmdstr+"' Please write it down!&amp;n",self);
dragons in all kinds of situations.  large passages lead of to the west
+
self.prompt:=prmt;
and the east.."
 
  
extra {"chair","chairs"}
+
quit;
"The chairs are made of some metal you don't recognize and every inch is covered
+
}
with some kind of dragon."
+
dilend
  
extra  {"dragon picture","picture"}
+
       
"Thousands of dragons dot the skies of this rather life like picture.  In the
+
</PRE><PRE>
center you see something move.  It looks to be a little green dragon."
 
  
extra{"green dragon","dragon","green"}
+
<HR>
"An intellegence looking dragon is sitting perched on a large chair watching you."
+
</CODE></BLOCKQUOTE>
  
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
  
west to disposal_room descr
 
"You see a small room.";
 
  
east to hallway descr
+
<p>
"You see what looks to be a hallway.";
+
<H2><A NAME="bpstore"></A>
 +
</H2>
  
end
+
<P><B>Function:</B>  <CODE>store( u : unitptr , filename : string , container : integer );</CODE>
 +
<DL>
 +
<DT><B>u</B><DD><P>The Unit that has the contents to be stored or is to be stored
 +
<DT><B>filename</B><DD><P>The name of the file you want to store the Units to
 +
<DT><B>container</B><DD><P>Do you want to save the container 'TRUE' for yes, 'False' for no
 +
</DL>
 +
</PRE><PRE>
 +
<P>Store saves a copy of a unit or units.  If the container value is 'TRUE'
 +
everything inside  including the container itself will be saved. If the container
 +
argument is 'FALSE' only the contents of the object will be saved.  You will want
 +
to use the 'TRUE' value when saving something like a Clan chest that has items
 +
inside to store and has extras on the chest that you also wish to keep.  The
 +
'FALSE' value for container would be good for temporary storage of PC inventory
 +
or for storing room contents.
 +
</PRE><PRE>
  
hallway
+
<P>The 'store' and 'restore' are perfect for operations such as
title "Module tunnel"
+
mud mailing objects from player to player, storage devices for players that will
descr "The hallway is about 50 meters long and around 100 meters from
+
keep inventory through a rebootEven the ability to save a players inventory
side to side and top to bottomThe hallway seems to be dust free.  The
+
while they fight in an arena and restore it to them undamaged when finished.
walls and the floors seem to be made out of the same sterile
+
Finally it could be used to save a donation room through reboots since it can be
metal-plastic that all space agencies uses. There are large plate glass
+
used on a room to store the contents of a room any NPC or objects in the room
windows that open up into space.  The hallway is filled with a dim light
+
would be saved through reboot.
that seems to come from everywhere yet no where all at once.  You notice
+
</PRE><PRE>
a glimmer of bright light coming from the windows.  To the east you see
 
an air lock and to the west the hallway opens up into a larger room."
 
  
extra {"windows","window"}
+
<P><B>Disk access is always slow</B>.
"Your eyes are drawn to a large ship lit up with running lights sitting
+
If you use store on a continues basis, it is essential that you do so ONLY if it
about 1 kilometer from the station."
+
is needed and even then, only at amply spaced intervals.  Otherwise you might
 +
cause serious delays on the server.  Remember that items saved in player's
 +
inventories are automatically saved in their instance.
 +
<P><B>Example 1:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE><PRE>
  
extra{"floor","walls","wall"}
+
dilbegin save_contents ();
"Well what can be said it looks to be in perfect condition.  what else would
+
code
you want to know?"
+
{
  
extra {"large ship" ,"ship"}
+
:start:
"The ship looks really big and is shaped like a dragon.  The scales
+
wait (SFB_CMD,command ("store")); wait for the store command*/
sparkle and seem to be multiple colors."
+
block;
 +
store("chest."+self.zoneidx,self,FALSE);/*store everything inside self.*/
 +
goto start;
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>Example 2:</B>
 +
<BLOCKQUOTE><CODE>
 +
<PRE>
  
movement SECT_INSIDE
+
dilbegin save_container_n_contents ();
ALWAYS_LIGHT
+
code
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
{
  
west to chamber descr
+
:start:
"The hallway opens up into a chamber.";
+
wait (SFB_CMD,command ("store")); wait for the store command*/
 +
block;
 +
store("chest."+self.zoneidx,self,TRUE);/*store everything inside self and self.*/
 +
goto start;
 +
}
 +
dilend
 +
</PRE><PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>See Also</B>
 +
<A HREF="#bfrestore">Store a Unit to a Unit file</A> and
 +
<A HREF="#bfdelunit">Delete a Unit file</A>.
 +
</PRE><PRE>
 +
<hr><a name="bpp_u">
 +
position_update ( u : unitptr )
 +
  u : A pointer to a player or a monster. The character will be
 +
      updated and perhaps killed, incapacitated, mortally
 +
      wounded, revived, etc. depending on current hitpoints.
 +
      Useful when tampering with the 'hp' field. Example:
  
east to office descr
+
      pc.hp := pc.hp - 100;
"You see what looks to be an office."
+
      position_update(pc);
keyword {"air lock door","air lock","door"}
+
</PRE><PRE>
open {EX_OPEN_CLOSE, EX_CLOSED};
+
<H2><A NAME="bpsend_done">
  
end
+
</H2>
  
office
+
<P><B>Function:</B></CODE>
title "The station office"
+
send_done( c : string, a :unitptr, m : unitptr, t :unitptr, p : integer, arg : string, o : unitptr);</CODE>
descr
+
<DL>
"Large paintings fill the walls of this part of the station.  The room
+
<DT><B>c</B><DD><P>the command string that is sending the message
is as large as the other rooms big enough for Dragons to lounge while
+
<DT><B>a</B><DD><P>the unitptr (activator) that activated the message
still having a desk in one corner small enough for a humanoid.  The
+
<DT><B>m</B><DD><P>the unitptr (medium) that the Dil is acting through
floor along the north wall is lined with some kind of fabric and seems very
+
<DT><B>t</B><DD><P>the unitptr (target) the Dil is acting on
soft to walk on, it may be some kind of dragon lounge judging by how large an
+
<DT><B>p</B><DD><P>the power of the message
area it coversThere is a passage to the west."
+
<DT><B>arg</B><DD><P>the argument sent with the message
 +
<DT><B>o</B><DD><P>the unitptr (other) you also want the message to go to
 +
</DL>
 +
<P>
 +
  This sends the 'SFB_DONE' message to any dils that are waiting for it in the
 +
  surrounding area and to the other pointer if not nullThe following is just
 +
  one example you can find many more in <B>commands.zon</B>
  
movement SECT_INSIDE
+
<P><B>Example:</B>
ALWAYS_LIGHT
+
<BLOCKQUOTE><CODE>
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
<HR>
 +
<PRE>
  
extra {"paintings","painting"}
+
dilbegin do_read (arg:string);
"The paintings are of many dragons and riders in all kinds of tasks from
+
var
combat to look out.  All the figures seem to be staring at a staff
+
brdname:string;
being held by a depiction of a wizard on the south wall."
+
        i:integer;
 +
        u:unitptr;
 +
        x:extraptr;
 +
        ln:integer;
 +
        temp:string;
 +
        templist:stringlist;
 +
        buff:string;
 +
        f_name:string;
 +
        act_str:string;
 +
code
 +
{
 +
i:=atoi (arg);
 +
if (i&lt;0)
 +
        {
 +
        exec ("look "+arg,self);
 +
        goto read_quit;
 +
        }
  
extra {"wizard","staff"}
+
if (itoa (i)!=arg)
"The wizard has his hand stretched out and it seems there is a place
+
        {
you can almost grab the staff. Maybe if you searched the staff you would
+
        exec ("look "+arg,self);
find it."
+
        goto read_quit;
 +
        }
  
extra {"desk"}
+
u:=self.outside.inside;
"Its a desk alright but there doesn't seem to be any drawers and it
+
while (u!=null)
seems totally empty."
+
        {
 +
        if ((u.type==UNIT_ST_OBJ) and (u.objecttype==ITEM_BOARD))
 +
                break;
 +
        u:=u.next;
 +
        }
  
extra{"fabric"}
+
if (u==null)
"Wussshhhhh you bound across the comfortable floor wasn't that fun."
+
        {
 +
        act ("You do not see that here.",A_ALWAYS,self,null,null,TO_CHAR);
 +
        quit;
 +
        }
 +
       
 +
                if (u.extra.["$BOARD_L_RES"].descr!="")
 +
                {
 +
                act_str:=u.extra.["$BOARD_L_RES"].descr(self,u);
 +
                if (act_str!="")
 +
                {
 +
        act(act_str,
 +
                        A_ALWAYS,self,null,null,TO_CHAR);
 +
                quit;
 +
                }
 +
                }
  
west to hallway descr
+
brdname:=u.names.[length (u.names)-1];
"You see what looks to be a hallway."
+
i:=loadstr (brdname+".idx",temp);
keyword {"air lock door","air lock","door"}
+
if (i&lt;=0)
open {EX_OPEN_CLOSE, EX_CLOSED};
+
        {
 +
        act ("But the board is empty!",
 +
                A_ALWAYS,self,null,null,TO_CHAR);
 +
        goto read_quit;
 +
        }
 +
       
 +
templist:=split(temp,"&amp;x");
 +
ln:=length (templist);
 +
x:="$BOARD_MAX" in self.extra;
 +
if ((atoi(arg)>atoi(x.descr)) or
 +
(atoi(arg)>ln))
 +
        {
 +
        act("That message exists only within the boundaries of your mind.",
 +
                A_ALWAYS,self,null,null,TO_CHAR);
 +
        goto read_quit;
 +
        }
  
SECRET_DOOR_DIFFICULTY(SOUTH, 50)
+
i:=atoi(arg);
south to portal_room descr
+
temp:=templist.[i-1];
"You see what looks to be a portal room."
+
f_name:=getword(temp);
keyword {"air lock door","air lock","staff","door"}
+
i:=loadstr (brdname+"."+f_name,buff);
key nokey
+
if (i==0)
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED,EX_HIDDEN};
+
        {
 +
        sendtext("You have to let the poster finish the post before reading it.",self);
 +
        quit;
 +
        }
 +
if (i&lt;1)
 +
        {
 +
        log("05: Error when loading board info.");
 +
        act ("This board is not working report to an Administrator",
 +
                A_ALWAYS,self,null,null,TO_CHAR);
 +
                quit;
 +
                }
  
end
+
templist:=split(f_name,".");
 +
if (length(templist)&lt;2)
 +
        act ("Message "+arg+":  "+temp,
 +
                A_ALWAYS,self,null,null,TO_CHAR);
 +
else
 +
        act ("Message "+arg+":  Re:  "+temp,
 +
                A_ALWAYS,self,null,null,TO_CHAR);
  
portal_room
+
pagestring(buff,self);
title "Green field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a green field right in the center.
 
there is a door that leads to another room to the north."
 
  
movement SECT_INSIDE
+
:read_quit:
ALWAYS_LIGHT
+
send_done("read",self,null,u,0,arg,null);
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
quit;
 +
}
 +
dilend
 +
</PRE><PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE> <P>
 +
<H2><A NAME="bfsend_pre"></H2>
 +
<B>Function:</B></CODE>send_pre( c : string, a :unitptr, m : unitptr, t :unitptr, p : integer, arg : string, o : unitptr);</CODE>
 +
<DL>
 +
<DT><B>c</B><DD><P>the command string that is sending the message
 +
<DT><B>a</B><DD><P>the unitptr (activator) that activated the message
 +
<DT><B>m</B><DD><P>the unitptr (medium) that the Dil is acting through
 +
<DT><B>t</B><DD><P>the unitptr (target) the Dil is acting on
 +
<DT><B>p</B><DD><P>the power of the message
 +
<DT><B>arg</B><DD><P>the argument sent with the message
 +
<DT><B>o</B><DD><P>the unitptr (other) you also want the message to go to
 +
</DL>
 +
</PRE><PRE>
 +
<P>
 +
<P>New Function send_pre(...) takes same arguments as send_done but returns either
 +
SFR_SHARE or SFR_BLOCK.
 +
<P>If the command is blocked by another special or dil, then SFB_BLOCK will be returned,
 +
and you should quit your dil.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE><PRE>
  
extra {"green field","field"}
 
"The field looks to be a green fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
  
north  to office descr
+
dilbegin cmdtst(arg : string);
"You see what looks to be an office."
+
var
keyword {"air lock door","air lock","door"}
+
  i : integer;
key nokey
+
code
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
+
{
 +
  i:=send_pre("cmdtest",self,null,null,0,argument,null);
  
//A link to the portal is also here from room_port
+
if (i == SFR_BLOCK)
end
+
  quit;
 +
 
 +
          sendtext ("No one blocked me!&amp;n",self);
 +
          quit;
 +
          }
 +
          dilend
 +
         
  
ship_port
+
dilbegin pretest();
names{"green field", "field"}
+
code
title "Green field"
+
{
descr
+
  :loop:
"Green Mist swirls about you."
+
  wait(SFB_PRE, command("cmdtest"));
 +
  block;
 +
        act("hahahaha I blocked your cmdtest command",
 +
      A_SOMEONE, activator, medium, null, TO_ALL);
 +
        goto loop;
 +
}
 +
dilend
 +
</PRE><PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
  
in ship
+
<hr><a name="bpset">
 +
set ( var i : integer , bit : integer )
 +
  i : Integer variable to alter.
 +
  bit : Bits to set in integer variable.
 +
  result: Sets bits in 'i'
  
dilcopy force_move@function(
+
<hr><a name="bpunset">
//Time to activation
+
unset ( var i : integer , bit : integer )
4,
+
  i : Integer variable to alter.
//room and act
+
  bit : Bits to unset in integer variable.
"portal_room@dragonst!You feel your body dissolving for lack of a better
+
  result: unset bits in 'i'.
description.&amp;nYou appear on the deck of a ship.",
+
 
//True or False for randomizing or not
+
 
FALSE);
+
<H2><A NAME="bpaddcolor">
 +
</H2>
  
end
+
<P><B>Function:  </B><CODE>addcolor (ch : unitptr, ks : string, cstr : string ) ;</CODE>
 +
<DL>
 +
<DT><B>ch</B><DD><P>character you are adding the color to
 +
<DT><B>ks</B><DD><P>key string for the color
 +
<DT><B>cstr</B><DD><P>color string
 +
</DL>
 +
<P>This function allows your Dils to create and add their own personal colors to a players
 +
color list.  That way you can actually make an act in a color that the player chooses or
 +
you yourself choose.
 +
<P><B>Function:  </B><CODE>addcolor(pc, "clan_who","&amp;c+w&amp;bn");</CODE>
 +
<P>
  
room_port
+
<H2><A NAME="bpdelcolor">
names{"green field", "field"}
+
</H2>
title "Green field"
 
descr
 
"Green Mist swirls about you."
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
  
in portal_room
+
<P><B>Function:  </B><CODE>delcolor (ch : unitptr, ks : string) ;</CODE>
 +
<DL>
 +
<DT><B>ch</B><DD><P>character you are deleting the color from
 +
<DT><B>ks</B><DD><P>key string for the color
 +
</DL>
 +
<P>This function is used to delete any colors from a players personal color list.
 +
<P><B>Function:  </B><CODE>delcolor(pc, "clan_who");</CODE>
 +
<P>
 +
<H2><A NAME="bfgetcolor">
 +
</H2>
  
dilcopy force_move@function(
+
<P><B>Function:  </B><CODE> string getcolor (ch : unitptr, ks : string) ;</CODE>
//Time to activation
+
<DL>
4,
+
<DT><B>ch</B><DD><P>character you are deleting the color from
//room and act
+
<DT><B>ks</B><DD><P>key string for the color
"ship@dragonst!You feel your body dissolving for lack of a better
+
<DT><B>returns</B><DD><P>returns the color in a string
description.&amp;nYou appear on the deck of a ship.",
+
</DL>
//True or False for randomizing or not
+
<P>This function returns what color a player has for a key in the players list.
FALSE);
+
<P><B>Function:  </B><CODE>string := getcolor(pc, "clan_who");</CODE>
 +
<P>
 +
<H2><A NAME="bpchangecolor"></A> <A NAME="ss4.4">4.4 Changing a color</A>
 +
</H2>
  
end
+
<P><B>Function:  </B><CODE>changecolor (ch : unitptr, ks : string, cstr : string ) ;</CODE>
 +
<DL>
 +
<DT><B>ch</B><DD><P>character you are changing the color on
 +
<DT><B>ks</B><DD><P>key string for the color
 +
<DT><B>cstr</B><DD><P>color string
 +
</DL>
 +
<P>This will change a color in a players personal list.
 +
<P><B>Function:  </B><CODE>changecolor(pc, "clan_who","&amp;c+w&amp;bn");</CODE>
 +
<P>
 +
<H2><A NAME="bpgamestate">
 +
</H2>
  
disposal_room
+
<P><B>Function:  </B><CODE>  gamestate( u : unitptr, gs : integer ); </CODE>
title "Red field room"
+
<P>Change the gamestate of a unitptr, uses the GS_ defines from the
descr
+
<B>vme.h</B>. This is used on the log on menu of the VME 2.0 release. Which is
"Like the other rooms on the station this one is large enough for
+
shown here as an example but it can also be used in a commandWhen used it
dragons to comfortably fit in.  The strange thing about this room though
+
removes the char from playing so be aware that players could use this to hide
is it is totally empty except for a red field right in the center.
+
if you run a player killing style mud.
there is a door that leads to another room to the east."
+
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE><PRE>
  
movement SECT_INSIDE
+
dilbegin informer();
ALWAYS_LIGHT
+
var
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
tgt : unitptr;
 +
code
 +
{
 +
heartbeat := PULSE_SEC;
  
extra {"red field","field"}
+
tgt := ghead();
"The field looks to be a red fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
  
east to chamber descr
+
while(tgt.type == UNIT_ST_PC)
"You see the main chamber.";
+
{
  
//A link to the portal is also here from dis_port
+
if((isset(tgt.pcflags,PC_INFORM)) and (tgt != self))
end
+
{
 +
    if(visible(tgt,self))
 +
        {
 +
        if(self.outside == tgt.outside)
 +
        sendtext(self.name+" has arrived.&amp;n", tgt);
 +
    else
 +
        sendtext(self.name+" has entered the world.&amp;n", tgt);
 +
        }
 +
}
  
dis_port
+
tgt := tgt.gnext;
names {"red field","field"}
+
}
title "Red field"
 
descr
 
"Red Mist swirls about you."
 
  
movement SECT_INSIDE
+
return;
ALWAYS_LIGHT
+
}
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
dilend
dilcopy force_move@function(
 
//how fast to force move in seconds
 
4,
 
//room to force move to and act
 
"deathspace@dragonst!You feel your body dissolving for lack of a better description.",
 
//true or false random move or not
 
0);
 
in disposal_room
 
  
end
+
dilbegin aware on_connect();
 +
external
 +
        informer();
 +
        login_modify(tgt : unitptr);
  
ship
+
var
title "War dragon"
+
  wizlvl : integer;
descr
+
        i:integer;
"Blue light softly glows from con duets that line the walls of this ship.
+
    err : integer;
The floors beside the east and west wall have what looks to be soft
+
    motd : string;
fabric covering. The south wall has small controls that seem to be made
+
  welcome : string;
for humanoids with two small chairs that look to be pilot seats. view
+
  goodbye : string;
portals are about 50 meters up the side of the ship on the west and east
+
code
wall and some kind of electronic screen covers the south wall.  The ship
+
{
seems to be a one room ship but there is a green field by the north
+
heartbeat := PULSE_SEC;
wall."
 
  
movement SECT_INSIDE
+
if(dilfind("do_quit@commands",self))
ALWAYS_LIGHT
+
        i := dildestroy("do_quit@commands", self);
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
  
extra {"view port"}
+
err := loadstr("motd",motd);
"Sorry your not 50 meters tall maybe it is made for a dragon?"
 
  
extra {"view screen","screen"}
+
if(err > 0)
"It seems to be the pilots view screen but you can't seem to see a way
+
{
to turn it on."
+
        motd := textformat(motd);
 +
        sendtext(motd+"&amp;n&amp;n", self);
  
extra {"controls","control"}
+
}
"The controls are in some weird language and your afraid if you start
 
pushing buttons you might rocket in to the station or worse slam into
 
a planet."
 
  
extra {"soft fabric","fabric"}
+
err := loadstr("welcome",welcome);
"It looks to be a dragon lounge area."
+
if(welcome)
 +
        welcome := textformat(welcome);
  
//A link to the portal is also here from ship_port
+
if (self.level &lt; 200)
end
+
{
  
deathspace
+
login_modify(self);
title"Open space"
+
dilcopy ("clan_delete@clans",self);
descr
+
dilcopy ("clan_clear@clans",self);
"You see the ship and the station far off in the distance and you are in Space!"
 
  
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
  
dilcopy death_room@function (
+
if(err > 0)
//how often is damage done 4 would be 1 second
+
        sendtext("&amp;n"+welcome+"&amp;n&amp;n", self);
4,
+
  informer();
//damage
+
  exec("look", self);
400,
+
  quit;
//act for the damage.
+
}
"You realize to late that was the trash disposal transporter and you feel
+
gamestate(self, GS_MENU);
your lungs explode.");
 
  
end
+
:wiz_menu:
 +
sendtext("Welcome to Valhalla&amp;n&amp;n", self);
 +
sendtext("1) Enter Valhalla&amp;n", self);
 +
sendtext("W) Change Wizinv level&amp;n [&amp;c+g"+itoa(self.minv)+"&amp;[default]]&amp;n",self);
 +
sendtext("0) Exit Valhalla&amp;n&amp;n", self);
 +
sendtext("Make your choice: ", self);
 +
wait(SFB_CMD, TRUE);
  
%mobiles
+
if (command("1") )
 +
{
 +
  gamestate(self, GS_PLAY);
 +
  if(err > 0)
 +
        sendtext("&amp;n"+welcome+"&amp;n&amp;n", self);
 +
  informer();
 +
  exec("look", self);
 +
  quit;
 +
} else if (command("0") ) {
 +
  err := loadstr("goodbye",goodbye);
 +
  if(err > 0)
 +
  {
 +
  goodbye := textformat(goodbye);
 +
  sendtext(goodbye, self);
 +
  }
 +
  destroy(self);
 +
  quit;
 +
} else if (command("w") ) {
 +
  sendtext("Enter new WizInv Level: ", self);
 +
  wait(SFB_CMD, TRUE);
 +
  wizlvl := atoi(cmdstr);
 +
  if (wizlvl > self.level)
 +
    wizlvl := self.level;
 +
  self.minv := wizlvl;
 +
} else {
 +
  sendtext("Invalid Selection&amp;n&amp;n", self);
 +
  goto wiz_menu;
 +
}
  
bldragon
+
}
 +
dilend
 +
</PRE><PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P>Look in <B>vme.h</B> for the possible values you can send to the menu
 +
function.
  
title "a black dragon"
 
descr "A big ugly black dragon is clawing the ground here."
 
names {"big ugly black dragon","ugly black dragon","big black dragon",
 
"black dragon","dragon"}
 
  
extra {}
+
<hr><a name="bpaddex">
"The black dragons scales glitter like black granite that has been
+
addextra ( var e : extraptr, l : stringlist , s : string )
polished for years by water. He has a large neck and huge bat like
+
  e : Extra description list to add element to.
wings. his eyes watch you as you stand before him. One claw seems to be
+
  l : Stringlist for the .names field.
tapping slightly on the ground as if the dragon is waiting for
+
  s : String for the .descr field.
something."
+
  result: Adds an extra description to a list of extra descriptions.
 +
<A name="bpaddex372">
 +
<strong>CAVEAT</strong> builder: You cannot use an extraptr variable as the e
 +
argument, but you may continue to use the following form:
  
extra {"eye","eyes"}
+
  ...
"The dragons eyes seem to follow you no matter where you go in the room
+
  ...
nothing seems to escape the dragons attention."
+
  addextra (self.quests, "Bozo's Quest");
 +
  ...
 +
  ...
  
extra {"claws","claw"}
+
<hr><a name="bpadds">
"The claw is big black and it looks very deadly. It seems like the
+
addstring ( var l : stringlist, s : string )
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
+
  l : Stringlist to add string to.
to say means the claws are about the size of short swords and long
+
  s : String to add.
swords."
+
  result : Adds a string 's' to a stringlist 'l'.
  
extra {"scales","scale"}
+
<hr><a name="bpsubex">
"Its a scale!  Haven't you ever seen a dragon before!"
+
subextra ( var e : extraptr, s : string )
 +
  e : Extra description list to remove element from.
 +
  s : String matching .names field in element
 +
  result: Removes first extra description from list with matching name.
 +
<a name="bpsubex372">
 +
<emp>CAVEAT</EMP> builder: You cannot use an extraptr variable as the e
 +
argument, but you may continue to use the following form:
  
extra {"bat wings","wings"}
+
  ...
"The dragon sees you looking and flaps his wings creating one heck of a
+
  ...
wind blast."
+
  subextra (self.quests, "Bozo's Quest");
 +
  ...
 +
  ...
  
M_DRAGON_BLACK_OLD(SEX_MALE)
+
<hr><a name="bpsubs">
 +
substring ( var l : stringlist, s : string )
 +
  l : Stringlist to remove string from.
 +
  s : String to remove
 +
  result: Removes string 's' from stringlist 'l'.
 +
 
 +
 
 +
<P>
 +
<H2><A NAME="bpstopfighting">
 +
</H2>
  
end
+
<P><B>Function:</B>  <CODE>stop_fighting( ch: unitptr, vict : unitptr ) ;</CODE>
 +
<DL>
 +
<DT><B>ch</B><DD><P>unitptr - person you are stoping the fighting for
 +
<DT><B>vict</B><DD><P>unitptr - person you are removing from the fighting or null for everyone
 +
</DL>
 +
<P>This function can be used to cancel combat in a room or with two people.
 +
The following example copied to a player will stop any fight the player is in.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE><PRE>
  
janitor
+
dilbegin stop_combat();
names {"ugly janitor", "janitor", "hobgoblin"}
+
code
title "an ugly janitor"
+
{
descr "an ugly janitor is walking around, cleaning up."
+
stop_fighting(self,null);
 +
quit;
 +
}
 +
dilend
 +
</PRE><PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
extra{}
 
"This ugly green thing looks more goblin than hobgoblin but he seems intent on
 
cleaning everything around him."
 
  
M_AVG_HOBGOBLIN(6, SEX_MALE)
+
<hr><a name="bpsubaff">
 +
subaff ( u : unitptr, i : integer )
 +
  u : Unit remove affect from.
 +
  i : Affect id to remove, see ID_* in values.h and/or vme.h
 +
  result: Removes first affect at 'u' with matching id 'i'.
  
// he is sort of good for cleaning so much
+
<hr><a name="bpaddaff">
alignment 900
+
addaff ( u : unitptr, id : integer, tif_first : integer, tif_tick : integer,
 +
        tif_last : integer, apf : integer, )XXX
 +
  u  : Unit to add affect to.
 +
  id : Affect id to add, see ID_* in values.h and/or vme.h
 +
  result: Adds affect 'id' at 'u' with first, tick, and last TIF_XXX's
 +
<P>
 +
<H2><A NAME="bpdest"></A>
 +
</H2>
  
//give him some money
+
<P><B>Function:</B>  <CODE>destroy ( u : unitptr );</CODE>
money 5 IRON_PIECE
+
<DL>
 +
<DT><B>u</B><DD><P>:Unit to remove from game
 +
</DL>
 +
<P>The destroy function works in two ways depending on the Unit being acted on.
 +
If the Unit being acted on is a PC the player is saved and ejected from the game.
 +
If the Unit being acted on is a NPC, or an Object. the purge function destroys
 +
the Unit.  Currently destroy will not destroy rooms.
 +
This is different from the old destroy function in that it removes the player
 +
out of the game instead of leaving the player in the menu.
 +
<P><B>Example</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
dilcopy janitors@function(15);
+
dilbegin purge_all_pc();
 +
var
 +
        u:unitptr/*Unit used to purge each player*/
 +
        n:unitptr;/*used to keep track of next player*/
 +
code
 +
{
 +
u:=ghead();/*get first pc in game list*/
 +
n:=u;
  
// only want him cleaning the station
 
dilcopy wander_zones@function("dragonst", 20, 1, 1);
 
  
end
+
while (n.type==UNIT_ST_PC)/*while unit is a pc*/
 +
        {
 +
        n:=u.gnext;
 +
        destroy(u);
 +
        }
  
bob
+
quit;/*done whiping out the players*/
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
names {"Bob"}
 
title "Bob"
 
descr "Bob the Banker is here, sitting behind the counter."
 
extra {}
 
"He has a very serious look on his face."
 
  
// define from composed.h
+
<hr><a name="bpwalkto">
M_SHOP_KEEPER(4, SEX_MALE, RACE_HUMAN)
+
walkto ( u : unitptr )
 +
  u : Room to walk to.
 +
  result: Makes unit (self) walk to room, taking a 'step' at each 'tick'.
  
//discourage people from killing banker
+
<b>Example:</b>
exp -500
+
  <i>walkto(findroom("inn@udgaard"));</i>
  
flags {UNIT_FL_NO_TELEPORT}
+
<hr><a name="bplink">
 +
link ( u : unitptr, t : unitptr )
 +
  u : Unit to link.
 +
  t : Unit to link into.
 +
  result: Link a unit into another unit hierarchy. (Automatically
 +
          unequipps if equipped).
 +
 
 +
 
 +
<H2><A NAME="bfweapon_name">
 +
  </H2>
  
special SFUN_BANK
+
<P><B>Function:</B>  <CODE>string weapon_name( i : integer ) ;</CODE>
end
+
<DL>
 +
<DT><B>i</B><DD><P>Weapon to get the name of ass defined in 'values.h' and 'weapons.def'
 +
<DT><B>returns</B><DD><P>The name of the weapon that corresponds with the integer value
 +
</DL>
 +
<P><B>example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
%objects
+
myweap:=weapon_name(5);
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
info_board
+
<H2><A NAME="bfweapon_info">
 +
  </H2>
  
title "a merchant information board"
+
<P><B>Function:</B>  <CODE>intlist weapon_info( i : integer ) ;</CODE>
descr "A merchant information Board is mounted on a wall here."
+
<DL>
names {"merchant information board","information board","merchant
+
<DT><B>i</B><DD><P>Weapon to get the info of ass defined in 'values.h' and 'weapons.def'
board","board"} extra {} "A large flashy black steal board."
+
<DT><B>returns</B><DD><P>Intlist containing 4 values:
 +
<DL>
 +
<DT><B>0</B><DD><P>Number of hands
 +
<DT><B>1</B><DD><P>weapon speed
 +
<DT><B>2</B><DD><P>weapon type
 +
<DT><B>3</B><DD><P>shield block value
 +
</DL>
 +
</DL>
 +
<P>This function gives you access to the values in the weapons.def file.
 +
With this things like 'wear' equipment' and 'look' are much easier to
 +
write in Dil.
 +
<P><B>Example</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
MATERIAL_METAL("A very fine quality black steel")
+
dilcopy id_weap (arg:string);
type ITEM_BOARD
+
var
dilcopy board@boards("info","","rem_res@boards","",100);
+
  i:integer;
 +
  il:intlist;
 +
code
 +
{
 +
il:=weapon_info(atoi(arg));
  
end
+
if (il!=null)
 +
{
 +
sendtext ("Number of hands:  "+itoa(il.[0])+"&amp;n";
 +
            sendtext ("Speed:  " +itoa(il.[1])+"&amp;n",self);
 +
                        sendtext ("Type:  "+itoa(il.[0])+"&amp;n",self);   
 +
                        sendtext ("Shield value:  "+itoa(il.[0])+"&amp;n",self);   
 +
                        }
 +
else
 +
{
 +
sendtext ("No such weapon.&amp;n",self); 
 +
}
  
w_stiletto
+
quit;
title "a stiletto"
+
}
names {"deadly looking stiletto","deadly stiletto","stiletto", "dagger"}
+
dilend                 
descr "A deadly looking stiletto has been left here."
+
                       
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
  
MATERIAL_METAL("A very fine quality steel")
+
<P>
manipulate {MANIPULATE_TAKE, MANIPULATE_WIELD}
+
<H2><A NAME="bfskill_name"></A> <A NAME="ss4.8">4.8 Getting a skills name</A>
WEAPON_DEF(WPN_DAGGER, 1, 2)
+
  </H2>
weight 2
 
cost 2 GOLD_PIECE
 
rent 1 COPPER_PIECE
 
  
SKILL_TRANSFER(SKI_BACKSTAB, 2)
+
<P><B>Function:</B>  <CODE>string skill_name( i : integer ) ;</CODE>
dilcopy abi_restrict@function (ABIL_DEX,10,0,25,"");
+
<DL>
 +
<DT><B>i</B><DD><P>Skill to get the name of ass defined in 'values.h' and 'commands.def'
 +
<DT><B>returns</B><DD><P>The name of the skill that corresponds with the integer value
 +
</DL>
 +
<P><B>example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
extra{}
+
myski:=skill_name(5);
"This looks like a thief dream come true. "
+
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P>
 +
<H2><A NAME="bpreboot"></A> <A NAME="ss4.9">4.9 Reboot the mud</A>
 +
</H2>
  
extra {"$identify"}
+
<P><B>Function:  </B><CODE>reboot ;</CODE>
"The stiletto looks magical in nature and seems really sharpYou can
+
<P>This function works like a quit command.  Anything after the reboot function in a Dil will not be
tell if you wield it you would be able to backstab someone really easy."
+
executed the mud will reboot instantlyThe zone must have root privileges in
 +
the zonelist in order to use this function.
 +
<P><B>Simple reboot command</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
extra{"$improved identify"}
+
dilbegin cmd_reboot (arg:string);
"The stiletto gives you a magic bonus of +1 and has a quality of +2.
+
code
It also raises your back stabbing skill  by 2%.  You have to have at
+
{
least 10% in dex before you can wield this magical weapon."
+
sendtext ("Rebooting the mud.&amp;n",self);
 +
reboot;
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
end
+
<P>
 +
<H2><A NAME="bpkilledit">
 +
</H2>
  
wpn_locker
+
<P><B>Function:  </B><CODE>killedit ;</CODE>
 +
<P>This function is used to kill the editor on a PC if it needs to
 +
stop editing before the PC is done editing.  An example of when this is needed
 +
is when a player is killed while editing or is transfered away from a place where he was editing.
 +
You can let them finish but it may be wierd for a person to finish
 +
posting in one room while in another.
 +
<P><B>Example</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
title "a weapons locker"
+
dilbegin editextra (arg:string);
names {"weapons locker","weapon locker","locker"}
+
code
 +
{
 +
interrupt (SFB_DEAD,self==activator,int_quit);
 +
        beginedit (self);
 +
        wait(SFB_EDIT,self==activator) ;
 +
        temp := textformat(argument);
 +
addextra (self.outside.extra ,{"graphitee"},temp);
 +
quit;
 +
:int_quit:
 +
killedit;
 +
quit;
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
descr "a small weapons locker hangs on the wall here."
 
manipulate {MANIPULATE_ENTER}
 
CONTAINER_DEF(500)
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
weight 400
 
MATERIAL_METAL("A very fine quality steel")
 
  
extra {}
+
<PRE>
"It is an ordinary weapons locker that looks like it holds any illegal
+
<hr><a name="bpexp">
weapons that are taken on the station."
+
experience ( i : integer, u : unitptr )
 +
  i : A integer number of experience to gain or loose.
 +
  u : The player to receive the experience.
 +
  result: The integer amount of experience is added to the players
 +
          total amount of experience (thus causing more or less
 +
          experience). USE WITH CARE! SUGGEST THAT YOU ONLY USE
 +
          INTEGER CONSTANTS AS THE EXPRESSION TO AVOID ERRORS.
  
end
+
<hr><a name="bpact">
  
pol_plate
+
<P>The purpose of act is to send a message to a number of players <B>present</b> in
names {"polished breast plate","polished plate","breast plate","plate"}
+
a roomThe room is defined as the room containing the afore mentioned
title "a polished breast plate"
+
character (provided he himself is in the room, i.e. not in a closed
descr "A polished breast plate has been left here."
+
container.)</P>
extra{}
 
"This is one shiny plate it seems to be made out of one perfect piece of
 
metalThere doesn't even seem to be any markings of owner ship."
 
manipulate {MANIPULATE_TAKE, MANIPULATE_WEAR_BODY} ARMOUR_PLATE(5,9)
 
  
MATERIAL_METAL("A high luster silver colored metal")
 
  
manipulate {MANIPULATE_TAKE, MANIPULATE_WEAR_BODY}
+
<hr>
ARMOUR_DEF(ARM_PLATE,5,9)
+
<h3>Syntax:</h3>
dilcopy abi_restrict@function (ABIL_STR,40,0,25,"");
+
<P>
cost 2 GOLD_PIECE
+
act(message, visibility, char, medium, victim, to_whom);
rent 3 COPPER_PIECE
+
<dl>
weight 25
+
<dt>message
 +
<dd> - is a string that will be shown to other mobiles when the act is executed.
 +
To refer to the following arguments use the <A href="#formatters">formatters</a> listed below.
 +
<dt>visibility
 +
<dd> - is an integer that defines what happens if the mobile that is about to receive the
 +
message can't see the activator.
 +
<dl>
 +
<dt><CODE>A_SOMEONE</CODE>
 +
<dd>If the receiver cannot see char, replace any reference to char with
 +
  <samp>someone</samp>.
 +
  <dt><CODE>A_HIDEINV</CODE>
 +
<dd>If the receiver cannot see char, don't send the message at all. Use
 +
    this when missing vision should eliminate the perception of the action
 +
the message represent. One instance where it is used is in smile. You
 +
would need a ridiculously sensitive ear to hear, let alone percept
 +
that someone's smiling if you can't see them. Do not use it if
 +
'sound' is inherent in the message.
  
extra{"$identify"}
+
<dt><CODE>A_ALWAYS</CODE>
"This is a high quality plate with a magical feeling."
+
<dd>Works exactly like <CODE>A_SOMEONE</CODE>, except that the receiver
 +
    will see the message even when sleeping.
 +
</dl>
 +
<dt>char
 +
<dd> - is a unitptr, and the most important argument in the act. If this
 +
      is not valid the act will never show, leaving mobiles without
 +
  the message.
 +
<dt>medium
 +
<dd> - is a unit pointer, an integer or a string. Use this at your
 +
      leasure.
 +
<dt>victim
 +
<dd> - is a unit pointer, an integer or a string. Certain flags in
 +
      the next argument rely on the validity of victim.
 +
<dt>
 +
<dd> - is an integer that defines who gets the message.
 +
<dl>
 +
<dt><CODE>TO_ROOM</CODE>
 +
<dd>Sends the message to the entire room, excluding 'char'.
 +
<dt><CODE>TO_VICT</CODE>
 +
<dd>Sends to 'victim' only. 'victim' must be valid, naturally.
 +
<dt><CODE>TO_NOTVICT</CODE>
 +
<dd>Sends the message to the entire room, excluding 'char'
 +
    and 'victim'.  Perfect for bystanders in a melee.
 +
<dt><CODE>TO_CHAR</CODE>
 +
<dd>Sends the message to 'char' and no one else.
 +
<dt><CODE>TO_ALL</CODE>
 +
<dd>Sends the message to everybody in the room.
 +
<dt><CODE>TO_REST</CODE>
 +
<dd>This is a bit different from the rest.  In sends the
 +
    message to all other units in the local environment,
 +
excluding those inside 'char'.
 +
</dl>
 +
</dl>
 +
</P>
 +
<HR>
 +
<P>
 +
<h3>
 +
<a name="formatters">Act Formatters</h3>
  
extra{"$improved identify"}
+
Just as the description formatters, act has its own set of formatters that
"The plate has a magical bonus to your defence of a +5 and a quality of
+
enable you to create generic messages that will be interpreted at run-time,
+9. You need 40% in strength to be able to wear it."
+
lessening the load on you.
end
 
  
liq_ration
+
The format string is a normal message, containing some special characters:<BR>
names {"red bag", "bag", "wine"}
+
<dl>
title "a red bag"
+
  <dt>'$$'
descr "A red bag has been gently placed here."
+
  <dd>will be sent to the receiver as a single `$'
 +
  <dt>'$', followed by a number and an extra character.
 +
  <dl><h4>The numbers:</h4>
 +
      <dt>'1'
 +
      <dd> means this formatter refers to the 'char' argument.
 +
      <dt>'2'
 +
      <dd>means this formatter refers to the 'medium' argument.
 +
      <dt>'3'
 +
      <dd> means this formatter refers to the 'victim' argument.
 +
  </dl>
 +
  <dl><h4>The characters</h4>
 +
      <dt>'N'
 +
      <dd> the formatter will be replaced with the name of the unit, or
 +
      (depending on the visibility)
 +
  'something' or 'someone'.
 +
      <dt>'a'
 +
      <dd>'a' or 'an' depending on the name of the unit referred by the number.
 +
      <dt>'e'
 +
      <dd>'it', 'he' or 'she' depending on the gender of the unit referred
 +
      by the number.
 +
      <dt>'m'
 +
      <dd>'it', 'him' or 'her' depending on the gender of the unit referred by
 +
      the number.
 +
      <dt>'n'
 +
      <dd> the formatter will be replaced with the title of the unit, or
 +
      (depending on the visibility) 'something' or 'someone'.
 +
      <dt>'p'
 +
      <dd>'fighting', 'standing', 'sleeping', etc., depending on the position
 +
      of the unit referred by the number.
 +
      <dt>'s'
 +
      <dd>'its', 'his' or 'her' depending on the gender of the unit referred
 +
      by the number.
 +
      <dt>'t'
 +
      <dd>the string in the argument referred by the number.
 +
  </dl>
  
MATERIAL_ORGANIC("a soft plastic")
 
manipulate {MANIPULATE_TAKE}
 
  
LIQ_WINE(1,2,2,0)
+
<b>Example:</b>
cost 2 IRON_PIECE
+
<i>
extra {}
+
  act("You step over $2n.", A_SOMEONE, self, litter, null, TO_CHAR);
"A small label reads Tassel Grove's finest. Year 321"
+
  act("$1n steps over $2n.", A_SOMEONE, self, litter, null, TO_REST);</i>
  
extra {"$identify"}
 
"Its the special wine from Tassel grove a small halfling village on the
 
planet Valhalla.  It seems like a great vintage wine."
 
  
end
+
<b>See Also:</b>
 +
  <a href = "act.html">DIL Act() for Dummies</a>
  
beef_stick
+
<hr><a name="bpexec">
 +
exec ( s : string , u : unitptr )
 +
  s : Command and arguments to perform.
 +
  u : Unit to perform command.
 +
  result: Unit (PC/NPC) executes command. The argument is treated just as
 +
          if a normal PC entered a command at the command prompt in the
 +
          game. It is not directly possible to detect whether the command
 +
          was a success or fail. For example, you might force a PC to
 +
          "get key". If there is no 'key' available, the PC will get
 +
          notified the normal way. Plenty of examples are given above.
  
title "a tough leathery stick"
+
<hr><a name="bpwait">
descr "A tough leathery looking stick is laying here."
+
wait ( i : integer , dilexp )
names {"tough leathery stick","tough leather stick","leathery stick",
+
  i : Message class to accept, see SFB_* in values.h and/or vme.h
"leather stick","tough stick","stick"}
+
  dilexp : Expression that has to be TRUE or not null to accept message.
 +
  result: Waits for a command, matching the flagset, and satisfies the
 +
          expression. When using the 'wait()' command, the first argument
 +
          is an integer, that tells what classes of messages to wait for.
 +
          Each message class is represented by a bit named as described in
 +
          the chapter on messages.
 +
<b>Example:</b>
  
extra {}
+
  wait (SFB_TICK|SFB_MSG, TRUE)
"This has the word BEEF burnt into it."
+
  /* Will accept a message, either from another DIL program or a
 +
      timer message. As the second argument is always TRUE, any
 +
      such message will reactivate the DIL program.
 +
    */
  
manipulate {MANIPULATE_TAKE}
+
<b>Example:</b>
FOOD_DEF(5,0)
 
weight 1
 
cost 1 COPPER_PIECE
 
MATERIAL_ORGANIC("tough beef")
 
end
 
  
  maskwa
+
  wait (SFB_CMD, command("transmutate"))
 +
  /* waits for an command entered named 'transmutate'.
 +
    Activates the DIL program, that then can block the command, or
 +
    let it pass (and then let the game produce the normal error
 +
    message for unknown commands).
 +
  */
 +
 
 +
  <P>
 +
<H2><A NAME="bfsavestr"></A>
 +
</H2>
  
names {"maskwa platinum ring", "platinum ring","maskwa ring","maskwa","ring"}
+
<P><B>Function:</B>  <CODE>integer savestr( filename : string , buff : string , wa :string);</CODE>
title "a Maskwa ring"
+
<DL>
descr "A Maskwa platinum ring is laying here."
+
<DT><B>filename</B><DD><P>The name of the String file to save the String to
MATERIAL_METAL("Platinum, and other precious metals")
+
<DT><B>buff</B><DD><P>The String you wish to save into the file
extra {}
+
<DT><B>wa</B><DD><P>Write or append
"The ring has a large bear headCould this be the legendary head of
+
<DT><B>Return</B><DD><P><CODE>FILE_SAVED, FILE_NOT_SAVED, FILE_NOT_CREATED, or FILE_ILEGAL_OPP</CODE>
Maskwa? Any thing formed with its head on it is said to strengthen the
+
</DL>
wearer."
+
<P>Savestr is used to save strings to disk to be loaded later by the 'load' function.
type ITEM_WORN
+
The 'savestr' and 'Loadstr' is perfect for operations such as
manipulate {MANIPULATE_TAKE, MANIPULATE_HOLD, MANIPULATE_WEAR_FINGER}
+
on-line edited newspaper, a lottery where the tickets are sold to players,
cost 100 COPPER_PIECE
+
creating smarter NPC's that can remember through reboots who they are hunting,
rent 50 IRON_PIECE
+
Dil based teachers, message boards, mail system, news command., zone or
weight 1
+
room based help,  competition boards, and much much more.
STR_TRANSFER(+1)
+
<P><B>Note:</B>The append/write argument must be in lower case and can only be a
end
+
'w' or a 'a' surrounded by '"'If the argument is a 'w' it will over write
 +
any string file by that name. If the argument is 'a' it will append to the
 +
file by that name.
 +
<P><B>Disk access is always slow</B>.
 +
If you use loadstr on a continuous basis always
 +
attempt to keep file sizes to a minimum for quick loading.  Otherwise you
 +
might cause serious delays on the server.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
</PRE>
 +
<PRE>
  
%end</nowiki>
+
dilbegin news_save (arg:string  /*for saving*/);
=== Suggested object exercises ===
+
var
 +
        ret:integer;/*to hold the return value if saved or not*/
 +
code
 +
{
 +
ret:= savestr("news.txt",arg,"w");
 +
if (!ret)
 +
        {
 +
        log ("File not wrote");
 +
        quit;
 +
        }
  
1. Using information you learned in (Link to objcraft),
+
sendtext("New news file wrote.[&amp;]n",self);
(Link to objmag), (Link to objmacroshield), and
+
quit;/*dil save routine done destroy self.*/
(Link to objarmour) create a large shield.
+
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>See Also</B> <CODE>
 +
<A HREF="#bfdelstr">Delete a String file</A> and
 +
<A HREF="#bfloadstr">Load a String file</A></CODE>
  
2. Using information you learned in (Link to objnon-armour)
 
and (Link to objmacrotransfers) create a ring that gives a person
 
5% strength bonus and removes 5% magic ability.
 
  
3. Using information you learned from (Link to objmacroliqcont) and (Link to objdrink) create a beer or soda from your local area.
+
<P>
 +
<H2><A NAME="bpremove"></A>
 +
</H2>
  
4. Using information you learned in (Link to objmacrolight);
+
<P><B>Function:</B>  <CODE>remove( sl : stringlist, i : integer ) ;</CODE>
make an object that gives off a bright light and will never run
+
<DL>
out.
+
<DT><B>sl</B><DD><P>the stringlist you are removing from
 +
<DT><B>i</B><DD><P>the index you want to remove
 +
</DL>
 +
<P>This function allows you to remove a string from a stringlist with out
 +
leaving a blank spot in the stringlist.
 +
<P><B>Example:  </B><CODE>remove (sl, i);</CODE>
  
5. Using the macros found in (Link to objmacroliqcont),
+
<P>
(Link to objmacrofood), (Link to objmacromoney), and
+
<H2><A NAME="bpresetlevel">
(Link to objmacrocontainer) along with information found in
+
</H2>
(Link to objfood) and (Link to objdrink); create a chest that
 
can be locked that contains food, drink, a pile of silver pieces, and a
 
pile of iron pieces.
 
== The reset section ==
 
  
Once you have learned to build rooms, objects and NPCs, you will
+
<P><B>Function:</B>  <CODE>reset_level( u : unitptr ) ;</CODE>
find one main missing thing, while you have created NPCs and objects
+
<DL>
they don't exist in the game unless you load themWhen developing the
+
<DT><B>u</B><DD><P>player your resetting
VME we found that logging on and loading everything for the players to
+
</DL>
interact with, became a very difficult thing to do when we got over 30
+
<P>This function simply resets a players levelCan be used in functions
items.  After many seconds of thought we came up with the idea of a
+
like reroll where you set the players back to the way he first logged on.
reset section that would do all of this work for us.  In fact the reset
+
<P><B>Example:  </B><CODE>reset_level (u);</CODE>
takes care of closing doors after players have opened them, loading NPCs
+
<P><B>See Also</B>
and their equipment, loading objects by themselves in rooms or even
+
<CODE>
loaded objects in objects.
+
<A HREF="#bpresetvlevel">reset a players virtual level</A> and
 +
<A HREF="#bpresetrace">reset a players race information</A></CODE>
  
Everything inside the reset section activates once at boot time and
+
<P>
then again when the reset time is up and the reset flag is true.  These
+
<H2><A NAME="bpresetvlevel">
two fields were described in (Link to zoneinfo) and are included
+
</H2>
in the zone header.  The reset section is denoted by the symbol '%reset' and can placed
 
anywhere but we try to keep it at the end of our zone files.  There is
 
no set order you must reset your doors, objects, and NPCs in but I like
 
to do doors first, special reset commands second, objects in rooms third, objects with objects in them
 
forth, NPCs fifth,
 
and finally NPCs.  You may find that you have a better way of sorting
 
them and again it is up to you.
 
=== Door resets ===
 
  
To show how the door resets work we will revisit an old room
+
<P><B>Function:</B>  <CODE>reset_vlevel( u : unitptr ) ;</CODE>
example from (Link to rmdoorexits). The following two rooms are
+
<DL>
linked with a door and at boot time they are reset to closedWhen the
+
<DT><B>u</B><DD><P>player your resetting
mud boots the door flags set on the room are the door flags that are
+
</DL>
used.  After boot up time the reset section is where the VME gets its
+
<P>This function simply resets a players virtual levelCan be used in functions
information about what to do with the door.
+
like reroll where you set the players back to the way he first logged on.
  <nowiki>
+
<P><B>Example: </B><CODE>reset_vlevel (u);</CODE>
hallway
+
<P><B>See Also</B>
title "Module tunnel"
+
<CODE>
descr "The hallway is about 50 meters long and around 100 meters from
+
<A HREF="#bpresetlevel">reset a players level</A> and
side to side and top to bottom...."
+
<A HREF="#bpresetrace">reset a players race information</A></CODE>
 +
<P>
 +
<H2><A NAME="bpresetrace">
 +
  </H2>
  
movement SECT_INSIDE
+
<P><B>Function:</B>  <CODE>reset_race( u : unitptr ) ;</CODE>
ALWAYS_LIGHT
+
<DL>
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
<DT><B>u</B><DD><P>player your resetting
 +
</DL>
 +
<P>Reset a characters race, weight, height, age, lifespan, and costs for training.
 +
As if you first log on the character.  Great for reroll along with 'reset_level' and 'reset_vlevel'. 
 +
<P><B>Example:  </B><CODE>reset_race (u);</CODE>
 +
<P><B>See Also</B>
 +
<CODE>
 +
<A HREF="#bpresetlevel">reset a players level</A> and
 +
<A HREF="#bpresetvlevel">reset a players virtual level</A></CODE>
  
west to chamber descr
 
"The hallway opens up into a chamber.";
 
  
east to office descr
+
<P>
"You see what looks to be an office."
+
<hr><a name="bpsec">
keyword {"air lock door","air lock","door"}
+
secure ( u : unitptr , label )
open {EX_OPEN_CLOSE, EX_CLOSED};
+
  u : Unit to secure.
 +
  label : Label to jump to, on removal.
 +
  result: Secures a unitptr, so that the program will go to 'label'
 +
          if unit leaves local environment. If this happens, during
 +
          a call to another function/procedure, it will continue
 +
          at that label when the function/procedure returns.
 +
          If you perform some kind of call to a template, the removing
 +
          of a unit from the local environment will not have affect.
 +
          until the return from that function, as the program execution
 +
          will continue at the designated label after a call. Should
 +
          several secured units leave local environment, the last such
 +
          event will determine the point of execution upon return.
 +
  <p>
 +
<H2><A NAME=bfunitdir"></A>
 +
</H2>
  
end
+
<P><B>Function:</B>  <CODE>stringlist unitdir( match : string ) ;</CODE>
 +
<DL>
 +
<DT><B>match</B><DD><P>The wild card file you want to match or '*' for all.
 +
<DT><B>return</B><DD><P>a Stringlist with all the filenames that match the 'match' argument.
 +
</DL>
 +
<P>The 'match' argument uses the same wild cards as the Linux 'ls' command
 +
so the following will work.
 +
<DL>
 +
<DT><B>&ast;</B><DD><P>Match any character or group of characters
 +
<DT><B>&quest;</B><DD><P>Match one of any character
 +
<DT><B>[...]</B><DD><P>Match one of a set of characters
 +
</DL>
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
office
+
"corpse*" matches:  corpse.10938 corpse.whistler corpseofwhistler ...
title "The station office"
+
"corpse?" matches corpse1 corpses corpse5 ...
descr
+
"[abc]*" matches ability about cost back ...
"Large paintings fill the walls of this part of the station...."
+
"[a-z]*" about zoo man father ...
 +
"start[nm]end" matches startnend startmend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
 +
<P><B>Example DIL:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
movement SECT_INSIDE
+
dilbegin aware reload_corpse();
ALWAYS_LIGHT
+
var
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
        corpselist:stringlist;
 +
        u:unitptr;
 +
        ln:integer;
 +
        i:integer;
 +
        x:extraptr;
 +
code
 +
{
 +
        corpselist:=unitdir("corpse*");
 +
        ln:=length(corpselist);
 +
        i:=0;
 +
        while (i&lt;ln)
 +
        {
 +
        u:=restore(corpselist.[i],null);
 +
        x:=CORPSE_EXTRA in u.extra;
 +
        if (u!=null)
 +
                if (x!=null)
 +
                        link (u,findroom(x.descr));
 +
                else
 +
                        link (u,findroom("temple@udgaard"));
 +
        i:=i+1;
 +
        }
  
west to hallway descr
+
quit;
"You see what looks to be a hallway."
+
}
keyword {"air lock door","air lock","door"}
+
dilend
open {EX_OPEN_CLOSE, EX_CLOSED};
+
</PRE>
end</nowiki>
+
<HR>
Now that we have two rooms lets define the reset command and how
+
</CODE></BLOCKQUOTE>
it works.  All reset commands have a keyword and then a set of
+
<P>The previous DIL example is the DIL used in restoring corpses to the game in
arguments.  The door reset command is simply 'door' followed by a set of
+
case of a crashFor more information you can see how the death DIL'S work
arguments that tell the VME where the door is, which door in that
+
by reading through the file death.zon in the vme2.0/zone.
location, and what you want to do with the door.  The command looks like
+
directory.
this.
 
<nowiki>
 
door &lt;room symbol&gt; &lt;Direction number&gt; {&lt;door flags&gt;}</nowiki>
 
==== Door argument explanation ====
 
;room symbolic
 
: As the name indicates this is the room that the door is located in.  If you are resetting a door not in the zone the reset command is in you will need to use a full symbolic name with the zone extension. The following would be two valid examples.
 
<nowiki>
 
//room symbolic in  this zone
 
door myroom ...
 
  
//room symbolic in another zone
 
door out_room@frogwart ...</nowiki>
 
;direction number
 
: The direction number can be one of the pre-defined direction numbers in the file ''vme.h''.  shown here so you don't have to go flipping file to file.
 
<nowiki>
 
#define NORTH 0
 
#define EAST  1
 
#define SOUTH 2
 
#define WEST  3
 
#define UP    4
 
#define DOWN  5
 
#define NORTHEAST 6
 
#define NORTHWEST 7
 
#define SOUTHEAST 8
 
#define SOUTHWEST 9</nowiki>
 
;door flags
 
: These flags, surrounded by '{}', describe the state of the door after the reset.  The following is the list of possible door flags.
 
  
;EX_OPEN_CLOSE
+
<hr><a name="bpunsec">
: Set this if you can open and close this exit, be it a door, gate or otherwise.
+
unsecure ( u : unitptr )
;EX_CLOSED
+
  u : Secured unit.
: Set this if you want the exit to be closed at reset time.
+
  result: Drop secure on a given unit.
;EX_LOCKED
 
: Set this if you want the exit to be locked at reset time.
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">
 
An interesting aspect is that if you do not specify a key, you can
 
    only unlock this door with the 'pick' skill, 'unlock' spell or from
 
    DIL with UnSet();
 
</blockquote>
 
;EX_PICK_PROOF
 
: Using this flag renders the 'pick' skill and 'unlock' spell un useable on the lock of this exit.
 
;EX_HIDDEN
 
: If this bit is set, the exit is hidden until the mobile has successfully searched for it, using the 'search'-command.
 
  
Now that we have all the information we need we can close the door
+
<hr><a name="bpblock">
after the reset time expires.  For our two rooms the door reset would
+
block
look like this.
+
  result: Blocks any command issued by a player or mobile. Blocking a
<nowiki>
+
          command prevents the command from being parsed by the
door hallway EAST {EX_OPEN_CLOSE, EX_CLOSED}
+
          interpreter. This is ideal if you need to make a routine
door office WEST {EX_OPEN_CLOSE, EX_CLOSED}</nowiki>
+
          which intercepts a command, reacts on it in a special way,
<blockquote style="background-color: #E8E8E8; font-style: italic; ">As you can see from the example it is very important to close both sides of the door. If you do not close both sides you will get very weird and undefined errors when players are trying to open and close them</blockquote>
+
          and does not need the standard way of reacting.
  
Another thing that you can do with the door reset command is
+
<hr><a name="bppri">
change the doors status. In our previous example we reset the door to
+
priority
its status that it has when it first is loaded into the game.  If
+
  result: Set until nopriority command. When set, no special routines
however we wanted to change the door to a locked door we could do that
+
          "below" the current DIL program will be executed. This is used
by adding the locked flag like this.
+
          to make other special routines idle. See haon-dor.zon for an
<nowiki>
+
          example.
door hallway EAST {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
door office WEST {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}</nowiki>
 
=== Loading objects and NPCs ===
 
  
Time to start loading your zone with its life and all the other
+
<hr><a name="bpnopri">
strange things you have built.  There is two commands that do all the
+
nopriority
loading and equipping of objects.  Oddly enough the commands are called
+
  result: Cancels the priority procedure.
'load' and 'equip'.  The format of the commands are almost the same
 
but equip must be used inside a NPC grouping.  With that in mind lets
 
start with simple loads and work our way up.
 
  
The command to load an object or an NPC into a room is as
+
<hr><a name="bpaddeq">
follows:
+
addequip ( u : unitptr , i : integer )
<nowiki>
+
  u : Unit to equip.
load &lt;object or NPC&gt; [into] [&lt;room&lt;] [&lt;load amount&gt;]
+
  i : Where to equip unit.
  [{Other loads and equip commands}]</nowiki>
+
  result: Equips unit, presumed to be in inventory PC/NPC at
;object or NPC
+
          given position. See WEAR_* in values.h and/or vme.h
: The first argument to the load command is the object or NPC symbolic name that you want to load.  The first argument is the only one that must be included in all load commands.
 
;into
 
: This is just a symbol that tells the reset that we are loading the object or NPC into some other unit.
 
;object, NPC, and room
 
: The third argument is the symbolic name of the place where you are loading the object and the NPC.
 
;load amount
 
: the fourth argument is an optional argument that tells the reset how many of the objects are allowed in the world, zone, or locally. The possible values for this field are as follows:
 
  
;max &lt;num&gt;
+
<hr><a name="bpuneq">
: This  command  is  always  part  of  another reset command (load,
+
unequip ( u : unitptr )
equip, etc.).  At reset time the entire world is scanned for occurences
+
  u : Unit to unequip.
of the loaded unit - only if the currently existing number is less than
+
  result: Unequipes unit presumed to be in equipment of PC/NPC.
&lt;num&gt; will the command be executed.
+
 
;local &lt;num&gt;
+
  <P>
: This command is always  part  of  another  reset  command  (load,
+
<H2><A NAME="bpdp">
equip, etc.).  At reset time the location of which the unit is to
+
</H2>
be loaded into is scanned for occurences of the loaded unit only  if  the currently
 
existing number is less than &lt;num&gt; will the
 
command be executed.
 
;zonemax &lt;num&gt;
 
: This command is always  part  of  another  reset  command  (load,
 
equip,  etc.).  At  reset  time  the  entire zone being reset is
 
scanned for occurences of the loaded unit - only if the currently
 
existing number is less than &lt;num&gt; will the command be
 
executed.
 
  
;Optional grouping
+
<P><B>Function:</B>  <CODE>delete_player( s : string ) ;</CODE>
: Any reset command may be followed by a pair of curly brackets {}
+
<DL>
containing  more reset commands. The commands inside the brackets
+
<DT><B>s</B><DD><P>the player name you want to delete
will only be executed in case the associated command was successful.
+
</DL>
 +
<P>This function deletes a player but it doesn't check to see if it
 +
was deleted or if it even existed you will have to do that with 'isplayer'.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
Don't be alarmed if this sounds a bit hard.  It all gets much
+
dilbegin aware do_delete (arg:string);
more clear as some examples are explained.  Lets take a look at the
+
var
following example and see if we can't make this much more clear.
+
        temp:string;
<nowiki>
+
        err:integer;
load udgaard/fido into midgaard/temple max 1</nowiki>
+
code
This example is pretty simple it says load the fido into the
+
{
temple only if there isn't already 1 in the world.  Now lets get a bit
 
more complicated.
 
<nowiki>
 
load udgaard/fido into midgaard/temple max 1
 
{
 
  load bone
 
  load excrement into midgaard/temple
 
}</nowiki>
 
Now we have said again load the fido into the temple if there is
 
not already one in the world.  Then if fido loads fill his inventory
 
with a bone and load excrement into the temple as well.
 
  
We can get even more complicated but still just using the load
+
if(self.type != UNIT_ST_PC) quit;
commands by doing the following
 
<nowiki>
 
load udgaard/fido into midgaard/temple max 1
 
{
 
  load bone
 
  load excrement into midgaard/temple
 
      load bag
 
  {
 
      load apple max 1
 
  }
 
}</nowiki>
 
now we still have the fido loading if there isn't one already in
 
the world then the bone and the excrement and finally we load a bag.
 
If there isn't an apple already in the world we load the bag with a
 
apple in it other wise the bag will be empty.
 
  
Well that should be enough load examples for now but we will get
+
if (self.level>200)
right back to them in a bit.  Now we should introduce another reset
+
        goto admin_delete;
command called the 'equip' command that we have already mentioned.  The
 
'equip' command works a lot like load but has much simpler arguments.
 
The 'equip' command is as follows.
 
<nowiki>
 
equip &lt;symbol&gt; position [load amount &lt;num&gt;]</nowiki>
 
;symbol
 
: The first argument is just the symbolic name of the item being worn by the NPC.
 
;position
 
: The position is any of the positions available in the
 
''vme.h''.  The following are all the positions along
 
side there defines as found in the ''vme.h''.
 
{| class="wikitable"
 
|+Wear positions
 
|-
 
!Position
 
!Define(s)
 
|-
 
|head
 
|WEAR_HEAD
 
|-
 
|hands
 
|WEAR_HANDS
 
|-
 
|arms
 
|WEAR_ARMS
 
|-
 
|body
 
|WEAR_BODY
 
|-
 
|legs
 
|WEAR_LEGS
 
|-
 
|feet
 
|WEAR_FEET
 
|-
 
|cloak
 
|WEAR_ABOUT
 
|-
 
|shield
 
|WEAR_SHIELD
 
|-
 
|hold
 
|WEAR_HOLD
 
|-
 
|wield
 
|WEAR_WIELD
 
|-
 
|ear
 
|WEAR_EAR_R and WEAR_EAR_L
 
|-
 
|neck
 
|WEAR_NECK_1 and WEAR_NECK_2
 
|-
 
|wrist
 
|WEAR_WRIST_R and WEAR_WRIST_L
 
|-
 
|finger
 
|WEAR_FINGER_R and WEAR_FINGER_L
 
|-
 
|chest
 
|MANIPULATE_WEAR_CHEST
 
|-
 
|back
 
|MANIPULATE_WEAR_BACK
 
|-
 
|waist
 
|MANIPULATE_WEAR_WAIST
 
|-
 
|ankle
 
|WEAR_ANKLE_R and WEAR_ANKLE_L
 
|}
 
;load amount
 
: the fourth argument is an optional argument that tells the reset how many of the objects are allowed in the world, zone, or locally.  The possible values for this field are as follows:
 
  
;max &lt;num&gt;
+
:char_delete:
: This  command  is  always  part  of  another reset command (load,
+
        if (arg!="self forever")
equip, etc.).  At reset time the entire world is scanned for occurences
+
                {
of the loaded unit - only if the currently existing number is less than
+
                sendtext ("To delete your char type'delete self forever'&amp;n",self);
&lt;num&gt; will the command be executed.
+
                quit;
;local &lt;num&gt;
+
                }
: This command is always  part  of  another  reset command  (load,
 
equip, etc.).  At reset time the location of which the unit is to
 
be loaded into is scanned for occurences of the loaded unit - only  if  the currently
 
existing number is less than &lt;num&gt; will the
 
command be executed.
 
;zonemax &lt;num&gt;
 
: This command is always  part  of  another  reset  command  (load,
 
equip,  etc.).  At  reset  time  the  entire zone being reset is
 
scanned for occurences of the loaded unit - only if the currently
 
existing number is less than &lt;num&gt; will the command be
 
executed.
 
  
Now with the equipment command you can now get your NPCs dressed
+
err:=loadstr("delete.txt",temp);
and ready for battle.  The 'load' and 'equip' commands are not the
 
easiest though so lets go through some simple examples.
 
<nowiki>
 
load guard into jail
 
  {
 
  equip helmet WEAR_HEAD
 
  equip plate WEAR_BODY
 
  equip pants WEAR_LEGS
 
  equip specialsword max 1
 
  load brass_key
 
  }</nowiki>
 
This is how you would equip a NPC with all items from the current
 
zone.  As you can see we didn't need full symbolics because the server
 
knows to grab the items from the zone the resets are in.
 
<nowiki>
 
load guard into safe_room max 2
 
{
 
equip plate WEAR_BODY
 
load powersword max1
 
  {
 
  load silver_pile into safe_room
 
  }
 
}</nowiki>
 
In this example we only load the silver pile if the guard loads
 
and if the power sword loads which may or may not happen since there is
 
only a max of one sword allowed while there is a max of 2 guards
 
allowed.  What will happen in this case is at the first reset there will
 
be one guard and one pile of silver.  The next reset there will still
 
only be one pile of silver but now there will be two guards.
 
  
Hopefully you have got the basic resets down.  If not don't worry
+
if (err&lt;1)
there are plenty more examples to come and we still have to make the
+
        goto no_insure;
resets for our dragon station zone.
 
=== Special reset functions ===
 
  
Now that we have gone over the basic load and equip commands we
+
sendtext (temp,self);
have some special commands that you can add to them to make them do more
 
interesting things.  Sometimes when doing resets you don't always want
 
items or NPCs to load or sometimes you want them to load but only if a
 
certain amount of other things correctly load.  There are also times you
 
want to clear the rooms or reload an entire object after removing the
 
old one.  All these things and more can be accomplished with the reset
 
section.
 
==== The complete directive. ====
 
  
The 'load' and 'equip' commands have one more argument that can be
+
sendtext ("If your sure you still want to delete your character, 'say delete me'&amp;n",self);
placed at the end of them to make them act a bit different.the complete
+
sendtext ("Doing anything else will abort the deletion.&amp;n",self);
directive. In the case where this directive is placed at the end
 
of a 'load or 'equip' command, the unit is only loaded in case all immediate commands inside
 
its nesting are executed successfully.  For example:
 
<nowiki>
 
load captain into jail_room complete
 
{
 
  equip magic_sword position WEAR_WIELD max 1
 
  load bag
 
  {
 
      load ruby_ring max 1
 
  }
 
}</nowiki>
 
In this case the captain is only loaded if the objects magic_sword
 
and bag are successfully loaded. if the ruby_ring is not loaded,
 
it will have no effect on the complete directive. To make the ruby_ring
 
affect to captains complete directive, the bag must also have specified a
 
complete directive (because the bag would then not be complete, and thus the
 
captain would not be complete).
 
==== The follow command ====
 
 
 
Once you load a NPC you may want that NPC to follow another NPC.
 
  That is what the 'follow' command is for.  The following is the format
 
  of the 'follow' command
 
<nowiki>
 
  follow &lt;symbol&gt; &lt;load amount #&gt; &lt;complete&gt;</nowiki>
 
;symbol
 
: The first argument to the follow command is the symbolic name of the NPC to follow the NPC of the outer grouping.
 
;load amount
 
: the second argument is an optional argument that tells the reset how many of the NPC followers of this type  are allowed in the world, zone, or locally.  The possible values for this field are as follows:
 
 
 
;max &lt;num&gt;
 
: This  command  is  always  part  of  another reset command (load,
 
equip, etc.).  At reset time the entire world is scanned for occurences
 
of the loaded unit - only if the currently existing number is less than
 
&lt;num&gt; will the command be executed.
 
;local &lt;num&gt;
 
: This command is always  part  of  another  reset  command  (load,
 
equip, etc.).  At reset time the location of which the unit is to
 
be loaded into is scanned for occurences of the loaded unit - only  if  the currently existing number is less than &lt;num&gt; will the
 
command be executed.
 
;zonemax &lt;num&gt;
 
: This command is always  part  of  another  reset  command  (load,
 
equip,  etc.).  At  reset  time  the  entire zone being reset is
 
scanned for occurences of the loaded unit - only if the currently
 
existing number is less than &lt;num&gt; will the command be
 
executed.
 
  
;complete
+
wait (SFB_CMD, self==activator);
: This only makes the NPC follow if all the other things in the grouping finishes completely.  For a better description of how this directive works see (Link to resetcomplete).
+
if (command ("say"))
  
The follow command is always used nested inside a loaded
+
        if (argument=="delete me")
NPC to force the NPC &lt;symbol&gt; to follow the NPC of the outer
+
        if (self.extra.[CLAN_RANK]!=null)
grouping. The following would be a correct use of the follow
+
                exec ("cdefect",self);
command.
+
                delete_player(self.name);
<nowiki>
 
load captain into jail
 
  {
 
  follow guard max 4
 
    {
 
equip guard_helmet WEAR_HEAD
 
equip guard_plate WEAR_BODY
 
equip guard_legs WEAR_LEGS
 
equip guard_boots WEAR_FEET
 
}
 
  follow guard max 4
 
    {
 
equip guard_helmet WEAR_HEAD
 
equip guard_plate WEAR_BODY
 
equip guard_legs WEAR_LEGS
 
equip guard_boots WEAR_FEET
 
}
 
  }</nowiki>
 
This example would load two guards that are fully dressed and
 
they would start following the captain which is also loaded.
 
==== The purge command ====
 
  
There are times when you want to clean up a room.  This can be
+
sendtext("Deletion aborted&amp;n",self);
done very easy by using the '''purge'''.  The following is
 
the format of the purge command.
 
<nowiki>
 
purge &lt;symbol&gt;</nowiki>
 
This command doesn't take much description.  The symbol is the
 
room you want to empty of all objects and NPCs.  If you wanted to get
 
rid of all objects and NPCs from a room with the symbolic name of jail
 
it would look like this.
 
<nowiki>
 
purge jail</nowiki>
 
==== The random command ====
 
  
If you ever want to load something only some of the time.  There
+
quit;
is a built in '''random''' command that allows you to pick
 
the percentage of the time that the item will load.  The random command
 
has the following format.
 
<nowiki>
 
random &lt;num&gt;
 
  {group or single set of resets}</nowiki>
 
It is important to point out this is done by a random percentage
 
chance where as 1% of the time would be almost not at all and 100% of
 
the time would be all the time.  If we wanted to load a group of things
 
only 80% of the time it would look like this.
 
<nowiki>
 
random 80
 
  {
 
  load captain into jail_room complete
 
    {
 
    equip magic_sword position WEAR_WIELD max 1
 
    load bag
 
      {
 
      load ruby_ring max 1
 
      }
 
    }
 
}</nowiki>
 
==== The remove command ====
 
  
Many times players take items out of containers like chests or
+
        :no_insure:
steal items from your NPCs and leave them naked.  If the NPC is not dead
+
                if (self.extra.[CLAN_RANK]!=null)
the resets don't reload them therefore your NPCs will stand there empty
+
                exec ("cdefect",self);
and so will your chests.  This is fine if that is what you want but
+
                        delete_player(self.name);
sometimes you want them to get dressed or refilled again at reset time. that is
 
what the '''remove''' command is for. The following is the
 
format of the remove command.
 
<nowiki>
 
remove &lt;symbol1&gt; in &lt;symbol2&gt;</nowiki>
 
Again the remove command is a simple command and it only has two
 
arguments, the item and where it is to remove it from. If you
 
wanted to have a cabinet that at every reset it would have a knife and a
 
bag of sugar in it would look like this.
 
<nowiki>
 
remove cabinet in kitchen
 
load cabinet into kitchen
 
{
 
load sugarbag
 
load knife
 
}</nowiki>
 
=== Reset walk through ===
 
  
The dragon station is almost finished.  All you have to do now is
+
quit;
create the resets for it.  We don't have a lot of stuff in the zone but
+
        :admin_delete:
we have enough to make a decent example of how the resets work. As I
+
        if (arg=="self forever")
mentioned at the start of the chapter on resets I like to do the doors
+
                goto char_delete;
first, the objects in rooms second, then the NPCs.  again this is
+
if (arg==""){
nothing we force you to do but I find it helps me keep track of my items
+
sendtext("You must supply a characters name to delete one.&amp;n",self);
and NPCs.
+
quit;
 +
}
  
With that in mind we will start by resetting our doors. In the
+
if (arg==self.name){
zone there is two doors.  One is a regular door that is closed when the
+
sendtext ("To delete self you need to type 'delete self forever'&amp;n",self);
mud reboots and the other is a hidden and locked door when the mud
+
quit;
reboots.  We will not block the rooms in and show you them again but
+
}
if you want to you can see the rooms in (Link to finishedzone).
 
the resets for these doors would look like this.
 
<nowiki>
 
//Office door reset
 
door hallway EAST {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
door office WEST {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
  
//secret door reset
+
if (not isplayer(arg))
door office SOUTH {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED,EX_HIDDEN}
+
        {
door portal_room  NORTH {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}</nowiki>
+
        sendtext (arg+" is not a character.&amp;n",self);
<blockquote style="background-color: #E8E8E8; font-style: italic; ">Both sides of the door don't have to have the exact same flags the door in the office is hidden but the one on the ship is not.</blockquote>
+
        quit;
 +
        }
 +
dilcopy ("god_delete@clans("+arg+")",self);
  
The next thing to build resets for is the two items we are loading
+
        sendtext (arg+" has been deleted.&amp;n",self);
directly into rooms and their contents if they have any.  The two items
+
quit;
we are loading into rooms are the board and the weapons locker. I am
+
}
just going to stick the board in the main chamber and the weapons locker
+
dilend
in the office.  The reset for these two items looks like this.
 
<nowiki>
 
load info_board into chamber
 
  
load wpn_locker into office
+
       
  {
+
</PRE>
  load w_stiletto
+
<HR>
  }</nowiki>
+
</CODE></BLOCKQUOTE>
Notice we also loaded a stiletto into the weapons locker and it will
 
only load once a reboot since the cabinet will never be removed and
 
unless the cabinet reloads the stiletto will not reload.
 
  
finally we get to the NPcs and their equipment.  We only have 3
+
<PRE>
NPCs in our zone so it shouldn't be any problem especially since we don't
+
<hr><a name="bpdc">
have that much close.  I am going to load the dragon into the ship on a
+
dilcopy( s : string, u : unitptr )
percentage chance basis and then load the Janitor into the station so he
+
  s : Name template to attach to unit.
can get to cleaning it up. Finally I will load Bob into the office so
+
  u : Unit to attach a dil program to.
he can sit and count his money.
+
  result: Attaches a DIL program to a unit 'u', which uses a template
<nowiki>
+
          named by 's'.
load bob into office
 
  {
 
  equip pol_plate WEAR_BODY
 
  }
 
  
  load janitor into chamber
+
<hr><a name="bpsendt">
    {
+
sendtext( s : string, u : unitptr )
equip pol_plate WEAR_BODY
+
  s : text to send
}
+
  u : Unit to send the text to
 +
  result: Sends the string 's' to 'u'. Useful only for nanny stuff,
 +
          because no new line appended.
  
random 50
+
<hr><a name="bpchngs">
  {
+
change_speed( u : unitptr, i : integer )
  load bldragon
+
  u : the unit on which you wish to alter the current combat speed.
      {
+
  i : the amount to add to the speed.
  load maskwa
 
  }
 
  }</nowiki>
 
Only a couple final things to point out.  It doesn't matter if you
 
load the same type of plate or same type of clothing on every NPC. It
 
would look pretty silly if everyone was wearing the same clothes but I
 
wanted to make sure you understood you didn't have to make one set for
 
everyone.  Also you don't have to equip wearable things you can load
 
them into the inventory like we did with the ring on the dragon.  That
 
about covers it all.  The resets are now done and we can now put them
 
all together with the zone and complete our dragon station.
 
=== The complete dragon station ===
 
<nowiki>
 
#include &lt;composed.h&gt;
 
%zone dragonst
 
lifespan 20
 
reset RESET_ANYHOW
 
creators {"whistler"}
 
  
notes
+
  Beware, this is not the 'speed' as in the speed field, rather this is
"This is the dragon station I shortened it to dragonst for ease in
+
  the speed which is calculated during combat. It is used for spells like
loading.  If you have  any questions email me at whistler@valhalla.com"
+
  'stun' which effectively puts the character out of combat for one
 +
  round. Such a spell would be implemented like:
  
help
+
  change_speed(u, 12)
"Not sure what could help you now.  You are stuck on one of the
 
weirdest space stations you have ever seen and you smell burning
 
sulfur."
 
  
%rooms
+
  and would only cause any effect if 'u' was fighting already (if not,
 +
  use setfighting).
  
chamber
+
<hr><a name="bftranmon">
title "The middle chamber of the station"
+
integer transfermoney( f : unitptr, t : unitptr, amount : integer)
descr
+
  f : The char the money is taken from
"This chamber seems to have the entire station rotating around it.  It is
+
  t : The char the money is given to
unbelievably large the ceiling seems to be a good 200 meeters high and
+
  amount : How much money.
the room is perfectly cubic. Small human size ornate chairs with dragon
+
  Returns: TRUE is money was transferred, FALSE if could not afford.
designs scrawled on the arms and back are arranged in a triangle like
 
setting with one large chair at the front.  This must be where all
 
station meetings are held. large pictures cover the walls depicting
 
dragons in all kinds of situations. large passages lead of to the west
 
and the east.."
 
  
extra {"chair","chairs"}
+
  If 'f' is null and 't' isn't, then money is created and given to 't'.
"The chairs are made of some metal you don't recognize and every inch is covered
+
  If 'f' isn't null but 't' is, then money is removed from 'f'.
with some kind of dragon."
 
  
extra  {"dragon picture","picture"}
+
<hr><a name="bpsetfight">
"Thousands of dragons dot the skies of this rather life like picture. In the
+
set_fighting( u : unitptr, t : unitptr )
center you see something move. It looks to be a little green dragon."
+
  u : the unit on which attacks.
 +
  t : the unit being attacked.
  
extra{"green dragon","dragon","green"}
+
  This is used to set two characters fighting. If the attacker is
"An intellegence looking dragon is sitting perched on a large chair watching you."
+
  fighting already, the target will simply be inserted into the
 +
  opponent list and perhaps killed a little later.
  
movement SECT_INSIDE
+
<hr><a name="bpsetweight">
ALWAYS_LIGHT
+
setweight( u : unitptr, i : integer )
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
+
  u : the unit on which you wish to alter the weight.
 +
  i : the new weight
  
west to disposal_room descr
+
  This is needed on for example drink-containers. I.e. if you wish to
"You see a small room.";
+
  remove or add some liquid, you must also adjust the weight of the
 +
  container, or you will mess up things.
  
east to hallway descr
+
<hr><a name="bpsetbright">
"You see what looks to be a hallway.";
+
setbright( u : unitptr, i : integer )
 +
  u : the unit on which you want to change the brightness.
 +
  i : the new brightness
  
end
+
  When you want to increase / decrease the amount of light shed by a
 +
  unit, use this function. Units with "bright" light up rooms so that
 +
  people can see.
  
hallway
+
<hr><a name="bplog">
title "Module tunnel"
+
log( s : string )
descr "The hallway is about 50 meters long and around 100 meters from
+
  s : Text to put in the log.
side to side and top to bottom.  The hallway seems to be dust free.  The
+
  result: Puts text in the log for debugging purposes.
walls and the floors seem to be made out of the same sterile
 
metal-plastic that all space agencies uses.  There are large plate glass
 
windows that open up into space.  The hallway is filled with a dim light
 
that seems to come from everywhere yet no where all at once.  You notice
 
a glimmer of bright light coming from the windows. To the east you see
 
an air lock and to the west the hallway opens up into a larger room."
 
  
extra {"windows","window"}
+
<hr><a name="bpsend">
"Your eyes are drawn to a large ship lit up with running lights sitting
+
send ( s : string )
about 1 kilometer from the station."
+
  s : Message to send.
 +
  result: Send a message to all DIL programs in current local environment,
 +
          matching the message class SFB_MSG. The message is not received
 +
          by those DIL programs in the local environment that is not set up
 +
          to wait for that message class.
  
extra{"floor","walls","wall"}
+
<hr><a name="bpsendto">
"Well what can be said it looks to be in perfect condition. What else would
+
sendto ( s : string , u : unitptr )
you want to know?"
+
  s : Message to send.
 +
  u : Unit to send it to.
 +
  result: The message is passed to all DIL programs in unit, matching the
 +
          message class SFB_MSG. The message is not
 +
          received by those DIL programs in the local environment that is
 +
          not set up to wait for that message class.
  
extra {"large ship" ,"ship"}
+
<hr><a name="bpsendall">
"The ship looks really big and is shaped like a dragon. The scales
+
sendtoall( m : string, s : string )
sparkle and seem to be multiple colors."
+
  m : Message to send.
 +
  s : Name idx to send message to.
 +
  result: Send a message to all units matching a given database name.
  
movement SECT_INSIDE
+
<b>Example:</b>
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
west to chamber descr
 
"The hallway opens up into a chamber.";
 
 
 
east to office descr
 
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
open {EX_OPEN_CLOSE, EX_CLOSED};
 
 
 
end
 
 
 
office
 
title "The station office"
 
descr
 
"Large paintings fill the walls of this part of the station.  The room
 
is as large as the other rooms big enough for Dragons to lounge while
 
still having a desk in one corner small enough for a humanoid.  The
 
floor along the north wall is lined with some kind of fabric and seems
 
very soft to walk on, it may be some kind of dragon lounge judging by
 
how large an area it covers.  There is a passage to the west."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
extra {"paintings","painting"}
 
"The paintings are of many dragons and riders in all kinds of tasks from
 
combat to look out.  All the figures seem to be staring at a staff
 
being held by a depiction of a wizard on the south wall."
 
 
 
extra {"wizard","staff"}
 
"The wizard has his hand stretched out and it seems there is a place
 
you can almost grab the staff. Maybe if you searched the staff you would
 
find it."
 
 
 
extra {"desk"}
 
"Its a desk alright but there doesn't seem to be any drawers and it
 
seems totally empty."
 
 
 
extra{"fabric"}
 
"Wussshhhhh you bound across the comfortable floor wasn't that fun."
 
 
 
west to hallway descr
 
"You see what looks to be a hallway."
 
keyword {"air lock door","air lock","door"}
 
open {EX_OPEN_CLOSE, EX_CLOSED};
 
 
 
SECRET_DOOR_DIFFICULTY(SOUTH, 50)
 
south to portal_room descr
 
"You see what looks to be a portal room."
 
keyword {"air lock door","air lock","staff","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED,EX_HIDDEN};
 
 
 
end
 
 
 
portal_room
 
title "Green field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a green field right in the center.
 
there is a door that leads to another room to the north."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
extra {"green field","field"}
 
"The field looks to be a green fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
 
 
north  to office descr
 
"You see what looks to be an office."
 
keyword {"air lock door","air lock","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
 
 
 
//A link to the portal is also here from room_port
 
end
 
 
 
ship_port
 
names{"green field", "field"}
 
title "Green field"
 
descr
 
"Green Mist swirls about you."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
in ship
 
 
 
dilcopy force_move@function(
 
//Time to activation
 
4,
 
//room and act
 
"portal_room@dragonst!You feel your body dissolving for lack of a better
 
description.&amp;You appear on the deck of a ship.",
 
//True or False for randomizing or not
 
FALSE);
 
 
 
end
 
 
 
room_port
 
names{"green field", "field"}
 
title "Green field"
 
descr
 
"Green Mist swirls about you."
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
in portal_room
 
 
 
dilcopy force_move@function(
 
//Time to activation
 
4,
 
//room and act
 
"ship@dragonst!You feel your body dissolving for lack of a better
 
description.&amp;You appear on the deck of a ship.",
 
//True or False for randomizing or not
 
FALSE);
 
 
 
end
 
 
 
disposal_room
 
title "Red field room"
 
descr
 
"Like the other rooms on the station this one is large enough for
 
dragons to comfortably fit in.  The strange thing about this room though
 
is it is totally empty except for a red field right in the center.
 
there is a door that leads to another room to the east."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
extra {"red field","field"}
 
"The field looks to be a red fog shifting and churning as you watch.
 
if you are nuts you could probably enter it."
 
 
 
east to chamber descr
 
"You see the main chamber.";
 
 
 
//A link to the portal is also here from dis_port
 
end
 
 
 
dis_port
 
names {"red field","field"}
 
title "Red field"
 
descr
 
"Red Mist swirls about you."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
dilcopy force_move@function(
 
//how fast to force move in seconds
 
4,
 
//room to force move to and act
 
"deathspace@dragonst!You feel your body dissolving for lack of a better description.",
 
//true or false random move or not
 
0);
 
in disposal_room
 
 
 
end
 
 
 
ship
 
title "War dragon"
 
descr
 
"Blue light softly glows from con duets that line the walls of this ship.
 
The floors beside the east and west wall have what looks to be soft
 
fabric covering.  The south wall has small controls that seem to be made
 
for humanoids with two small chairs that look to be pilot seats.  view
 
portals are about 50 meters up the side of the ship on the west and east
 
wall and some kind of electronic screen covers the south wall.  The ship
 
seems to be a one room ship but there is a green field by the north
 
wall."
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
extra {"view port"}
 
"Sorry your not 50 meters tall maybe it is made for a dragon?"
 
 
 
extra {"view screen","screen"}
 
"It seems to be the pilots view screen but you can't seem to see a way
 
to turn it on."
 
 
 
extra {"controls","control"}
 
"The controls are in some weird language and your afraid if you start
 
pushing buttons you might rocket in to the station or worse slam into
 
a planet."
 
 
 
extra {"soft fabric","fabric"}
 
"It looks to be a dragon lounge area."
 
 
 
//A link to the portal is also here from ship_port
 
end
 
 
 
deathspace
 
title"Open space"
 
descr
 
"You see the ship and the station far off in the distance and you are in Space!"
 
 
 
movement SECT_INSIDE
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
dilcopy death_room@function (
 
//how often is damage done 4 would be 1 second
 
4,
 
//damage
 
400,
 
//act for the damage.
 
"You realize to late that was the trash disposal transporter and you feel your lungs explode.");
 
 
 
end
 
 
 
%mobiles
 
 
 
bldragon
 
 
 
title "a black dragon"
 
descr "A big ugly black dragon is clawing the ground here."
 
names {"big ugly black dragon","ugly black dragon","big black dragon",
 
"black dragon","dragon"}
 
 
 
extra {}
 
"The black dragons scales glitter like black granite that has been
 
polished for years by water.  He has a large neck and huge bat like
 
wings.  his eyes watch you as you stand before him.  One claw seems to be
 
tapping slightly on the ground as if the dragon is waiting for
 
something."
 
 
 
extra {"eye","eyes"}
 
"The dragons eyes seem to follow you no matter where you go in the room
 
nothing seems to escape the dragons attention."
 
 
 
extra {"claws","claw"}
 
"The claw is big black and it looks very deadly.  It seems like the
 
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
 
to say means the claws are about the size of short swords and long
 
swords."
 
 
 
extra {"scales","scale"}
 
"Its a scale!  Haven't you ever seen a dragon before!"
 
 
 
extra {"bat wings","wings"}
 
"The dragon sees you looking and flaps his wings creating one heck of a
 
wind blast."
 
 
 
M_DRAGON_BLACK_OLD(SEX_MALE)
 
 
 
end
 
 
 
janitor
 
names {"ugly janitor", "janitor", "hobgoblin"}
 
title "an ugly janitor"
 
descr "an ugly janitor is walking around, cleaning up."
 
 
 
extra{}
 
"This ugly green thing looks more goblin than hobgoblin but he seems intent
 
on cleaning everything around him."
 
 
 
M_AVG_HOBGOBLIN(6, SEX_MALE)
 
 
 
// he is sort of good for cleaning so much
 
alignment 900
 
 
 
//give him some money
 
money 5 IRON_PIECE
 
 
 
dilcopy janitors@function(15);
 
 
 
// only want him cleaning the station
 
dilcopy wander_zones@function("dragonst", 20, 1, 1);
 
 
 
end
 
 
 
bob
 
 
 
names {"Bob"}
 
title "Bob"
 
descr "Bob the Banker is here, sitting behind the counter."
 
extra {}
 
"He has a very serious look on his face."
 
 
 
// define from composed.h
 
M_SHOP_KEEPER(4, SEX_MALE, RACE_HUMAN)
 
 
 
//discourage people from killing banker
 
exp -500
 
 
 
flags {UNIT_FL_NO_TELEPORT}
 
 
 
special SFUN_BANK
 
end
 
 
 
%objects
 
 
 
info_board
 
 
 
title "a merchant information board"
 
descr "A merchant information Board is mounted on a wall here."
 
names {"merchant information board","information board","merchant
 
board","board"} extra {} "A large flashy black steal board."
 
 
 
MATERIAL_METAL("A very fine quality black steel")
 
type ITEM_BOARD
 
dilcopy board@boards("info","","rem_res@boards","",100);
 
 
 
end
 
 
 
w_stiletto
 
title "a stiletto"
 
names {"deadly looking stiletto","deadly stiletto","stiletto", "dagger"}
 
descr "A deadly looking stiletto has been left here."
 
 
 
MATERIAL_METAL("A very fine quality steel")
 
manipulate {MANIPULATE_TAKE, MANIPULATE_WIELD}
 
WEAPON_DEF(WPN_DAGGER, 1, 2)
 
weight 2
 
cost 2 GOLD_PIECE
 
rent 1 COPPER_PIECE
 
 
 
SKILL_TRANSFER(SKI_BACKSTAB, 2)
 
dilcopy abi_restrict@function (ABIL_DEX,10,0,25,"");
 
 
 
extra{}
 
"This looks like a thieves dream come true. "
 
 
 
extra {"$identify"}
 
"The stiletto looks magical in nature and seems really sharp.  You can
 
tell if you wield it you would be able to backstab someone really easy."
 
 
 
extra{"$improved identify"}
 
"The stiletto gives you a magical bonus of +1 and has a quality of +2.
 
It also raises your back stabbing skill  by 2%.  You have to have at
 
least 10% in dex before you can wield this magical weapon."
 
 
 
end
 
 
 
wpn_locker
 
 
 
title "a weapons locker"
 
names {"weapons locker","weapon locker","locker"}
 
 
 
descr "a small weapons locker hangs on the wall here."
 
manipulate {MANIPULATE_ENTER}
 
CONTAINER_DEF(500)
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
weight 400
 
MATERIAL_METAL("A very fine quality steel")
 
 
 
extra {}
 
"It is an ordinary weapons locker that looks like it holds any illegal
 
weapons that are taken on the station."
 
 
 
end
 
 
 
pol_plate
 
names {"polished breast plate","polished plate","breast plate","plate"}
 
title "a polished breast plate"
 
descr "A polished breast plate has been left here."
 
extra{}
 
"This is one shiny plate it seems to be made out of one perfect piece of
 
metal.  There doesn't even seem to be any markings of owner ship." manipulate
 
{MANIPULATE_TAKE, MANIPULATE_WEAR_BODY} ARMOUR_PLATE(5,9)
 
 
 
MATERIAL_METAL("A high luster silver colored metal")
 
 
 
manipulate {MANIPULATE_TAKE, MANIPULATE_WEAR_BODY}
 
ARMOUR_DEF(ARM_PLATE,5,9)
 
dilcopy abi_restrict@function (ABIL_STR,40,0,25,"");
 
cost 2 GOLD_PIECE
 
rent 3 COPPER_PIECE
 
weight 25
 
 
 
extra{"$identify"}
 
"This is a high quality plate with a magical feeling."
 
 
 
extra{"$improved identify"}
 
"The plate has a magical bonus to your defence of a +5 and a quality of
 
+9.  You need 40% in strength to be able to wear it."
 
end
 
 
 
liq_ration
 
names {"red bag", "bag", "wine"}
 
title "a red bag"
 
descr "A red bag has been gently placed here."
 
 
 
MATERIAL_ORGANIC("a soft plastic")
 
manipulate {MANIPULATE_TAKE}
 
 
 
LIQ_WINE(1,2,2,0)
 
cost 2 IRON_PIECE
 
extra {}
 
"A small label reads Tassel Grove's finest.  Year 321"
 
 
 
extra {"$identify"}
 
"Its the special wine from Tassel grove a small halfling village on the
 
planet Valhalla.  It seems like a great vintage wine."
 
 
 
end
 
 
 
beef_stick
 
 
 
title "a tough leathery stick"
 
descr "A tough leathery looking stick is laying here."
 
names {"tough leathery stick","tough leather stick","leathery stick",
 
"leather stick","tough stick","stick"}
 
 
 
extra {}
 
"This has the word BEEF burnt into it."
 
 
 
manipulate {MANIPULATE_TAKE}
 
FOOD_DEF(5,0)
 
weight 1
 
cost 1 COPPER_PIECE
 
MATERIAL_ORGANIC("tough beef")
 
end
 
 
 
  maskwa
 
 
 
names {"maskwa platinum ring", "platinum ring","maskwa ring","maskwa","ring"}
 
title "a Maskwa ring"
 
descr "A Maskwa platinum ring is laying here."
 
MATERIAL_METAL("Platinum, and other precious metals")
 
extra {}
 
"The ring has a large bear head.  Could this be the legendary head of
 
Maskwa?  Any thing formed with its head on it is said to strengthen the
 
wearer."
 
type ITEM_WORN
 
manipulate {MANIPULATE_TAKE, MANIPULATE_HOLD, MANIPULATE_WEAR_FINGER}
 
cost 100 COPPER_PIECE
 
rent 50 IRON_PIECE
 
weight 1
 
STR_TRANSFER(+1)
 
end
 
 
 
%reset
 
 
 
//Office door reset
 
door hallway EAST {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
door office WEST {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
 
 
//secret door reset
 
door office SOUTH {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED,EX_HIDDEN}
 
door portal_room  NORTH {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED}
 
 
 
load info_board into chamber
 
 
 
load wpn_locker into office
 
  {
 
  load w_stiletto
 
  }
 
 
 
  load bob into office
 
  {
 
  equip pol_plate WEAR_BODY
 
  }
 
 
 
  load janitor into chamber
 
    {
 
equip pol_plate WEAR_BODY
 
}
 
 
 
random 50
 
  {
 
  load bldragon
 
      {
 
  load maskwa
 
  }
 
  }
 
 
 
%end</nowiki>
 
== Color and formatting codes ==
 
 
 
Now that you have got a handle on how to build rooms, objects, and
 
NPCs, we will now give you the ability to format text the way you want
 
it formatted and color it as well.  Currently the VME doesn't support
 
all the ASCII characters but if we get enough people wanting this
 
ability it will be added.
 
=== The escape character ===
 
 
 
When working with colors or formatting there are always two parts
 
to a formatting command.  The first part we call the escape character
 
which is the '&amp;' character.  Thus all formatting and color commands
 
would look as follows:
 
<nowiki>
 
&amp;&lt;color or formating command&gt;</nowiki>
 
=== Formatting codes ===
 
 
 
As you may have noticed the string fields on the VME are formatted
 
  in an english paragraph style.  What that means is all text is
 
  formatted with he following rules:
 
*
 
  All leading blanks are stripped away. For room descriptions
 
    3 leading spaces are added. This way we ensure a consistent
 
    formatting of the displayed room descriptions.
 
*
 
 
 
Spaces and blanks (newlines) are contracted to single spaces
 
    yielding a correctly 'wrapped' text for any sentence.
 
*
 
If a '.' is encountered followed by a blank, a total of two
 
    spaces are inserted after the '.'.
 
These formatting rules are great for normal descriptions and
 
extras but what if you want to make a sign or a map.  You don't always
 
want the text to be rapped, if the server rapped your sign it would turn
 
out looking like a jumble of punctuation in the form of a paragraph.
 
(Link to formattable) contains a list of all formatting
 
characters and a short description of them.
 
(Link to formatdescr) contains a more in depth discussion of each
 
format command with examples and (Link to colordescr) deals with
 
the color commands.
 
{| class="wikitable"
 
|+Formatting and color codes
 
|-
 
!Code
 
!Description
 
|-
 
|&amp;
 
|Used to make an &amp; character instead of an escape code.
 
|-
 
|l
 
|Text from this point forward will not be formatted. It will
 
              be interpreted literally with newlines, spaces, etc.
 
              Useful when making a sign or a map.
 
|-
 
|f
 
|Text from this point forward will be formatted. This option
 
              is the reverse of &amp;l and is default on any section of text.
 
|-
 
|s&lt;#&gt;
 
|Force a singe space character (or &lt;#&gt; if specified, may
 
              come in handy, instead of having to toggle formatting).
 
|-
 
|n
 
|Force a new line, very handy instead of toggling the &amp;l
 
              formatting switch.
 
|-
 
|h
 
|Clears the screen if the terminal of the user supports it.
 
|-
 
|x
 
|A file new line used for split so that you can split a file into lines
 
|-
 
|c&lt;color&gt;
 
|Set the foreground color.
 
|-
 
|b&lt;color&gt;
 
|Set the background color.
 
|-
 
|[&lt;color&gt;]
 
|Set a preset foreground and background color.
 
|}
 
=== Formatting code descriptions and examples ===
 
 
 
;&amp;&amp;
 
: If you want a single '&' you must let the VME know that you don't want a formatting or a color code.  You do this by doubling the '&amp;' sign.  The following is a couple examples:
 
 
 
{|
 
|-
 
|text
 
|Result
 
|-
 
|&amp;&amp;
 
|&amp;
 
|-
 
|&amp;&&amp;&amp;
 
|&amp;&amp;
 
|-
 
|&amp;&amp;&amp;&amp;&amp;&amp;
 
|&amp;&amp;&amp;
 
|}
 
 
 
;&amp;l
 
: When you want to turn off the formatting you use this formatting code.  Everything after the '&amp;l' will be shown exactly as you put it in the string.
 
<nowiki>
 
&amp;l
 
*    *
 
*  *
 
  * *
 
  *
 
  * *
 
*  *
 
*    *</nowiki>
 
;&amp;f
 
: The formatted text as we have already said is default.  If you want to turn the formatted text back on after some literal text you will have to use the '&amp;f' code.  The following is an example of some literal text followed by a short bit of formatted text.
 
<nowiki>
 
&amp;l
 
*    *
 
*  *
 
  * *
 
  *
 
  * *
 
*  *
 
*    *
 
 
 
&amp;fThe X marks the spot!</nowiki>
 
;&amp;s&lt;#&gt;
 
: If you want to input extra spaces in a sentence with out using the
 
'&amp;l' you can add them one at a time or multiple by using the
 
'&amp;s' code.
 
<nowiki>
 
This sentence has 10 spaces&amp;s10before the first word before.</nowiki>
 
;&amp;n
 
: If you want to input some blank lines with out using the literal code you can add a '&amp;n'for each line you want.
 
<nowiki>
 
This sentence&amp;n&amp;n&amp;n would look like this:
 
 
 
This sentence
 
 
 
would look like this:</nowiki>
 
;&amp;x
 
: The line break is made for use with the DIL language.  You will not need it to do regular text formatting.  It was added so a DIL could split a string that is loaded from a file.  If you don't understand the following example don't worry it is explained more in the DIL reference.
 
<nowiki>
 
mystrlist:=split(string,"&amp;");</nowiki>
 
;&amp;h
 
: On terminals that can handle it the '&amp;h' will clear the screen.  If you wanted a sign that would clear the screen before displaying when a character looked at it would look like this.
 
<nowiki>
 
&amp;h&amp;l
 
*    *
 
*  *
 
  * *
 
  *
 
  * *
 
*  *
 
*    *
 
 
 
&amp;fThe X marks the spot!</nowiki>
 
=== Color code descriptions and examples ===
 
 
 
;&amp;c and &amp;b
 
: In order to allow you to change the colors there are two codes.  One is for the foreground color (&amp;c) and the other is for the background color (&amp;b).  '&amp;c' is used with one or two arguments depending on brightness, while the '&amp;b' s only used with one because it has only one brightness.  They both have the forms as follows:
 
<nowiki>
 
&amp;c&lt;bright&gt;&lt;color&gt;
 
&amp;b&lt;color&gt;</nowiki>
 
It is important to set both the foreground and background color
 
because if a player has his default background color set to blue and you
 
use blue as a foreground color it will make the letters invisible to the
 
player.  It is also important to set the colors back to the default
 
color when done.  this is done by using the following command:
 
<nowiki>
 
&amp;[default]</nowiki>
 
<blockquote style="background-color: #E8E8E8; font-style: italic; ">The '&amp;[default]' command will be described in the next section.  It is enough to know for now that it will return the players colors to their default colors.</blockquote>
 
 
 
Before we give some color examples we should now define the
 
symbols for brightness and the symbols for each color and what they
 
are.
 
{| class="wikitable"
 
|+Colors
 
|-
 
!Code
 
!Color
 
|-
 
|n
 
|Black
 
|-
 
|r
 
|Red
 
|-
 
|g
 
|Green
 
|-
 
|y
 
|Yellow
 
|-
 
|b
 
|Blue
 
|-
 
|m
 
|Magenta
 
|-
 
|c
 
|Cyan
 
|-
 
|w
 
|White
 
|}
 
{| class="wikitable"
 
|+Sample Color codes
 
|-
 
!Code
 
!Resulting Colors
 
|-
 
|&amp;cb&amp;bw
 
|
 
|-
 
|&amp;+g&amp;bn
 
|
 
|-
 
|&amp;c+w&amp;r
 
|
 
|-
 
|&amp;c+w&amp;bn
 
|
 
|}
 
; &amp;[&lt;color&gt;]
 
*
 
 
 
As we have said in the previous section if you are not careful you
 
can make your text not visible by the player by setting the foreground to
 
the same color as the background.  In order to make it possible for you
 
to easily change how the color looks and to even match it with the way
 
players have their colors set already we have created colors that the
 
players can set.  and you can use.  The VME comes
 
with a default list of colors which can be added to by either the
 
''color.def'' or even by a DIL
 
program on line.  The default colors are as follows:
 
{|
 
|-
 
|death
 
|default
 
|exit
 
|-
 
|group
 
|hit_me
 
|hit_opponent
 
|-
 
|hit_other
 
|immort_descr
 
|immort_title
 
|-
 
|log
 
|miss_me
 
|miss_opponent
 
|-
 
|miss_other
 
|nodam_me
 
|nodam_opponent
 
|-
 
|nodam_other
 
|npc_descr
 
|npc_title
 
|-
 
|obj_descr
 
|obj_title
 
|pc_descr
 
|-
 
|pc_title
 
|prompt
 
|respond
 
|-
 
|room_descr
 
|broom_title
 
|say_other
 
|-
 
|say_self
 
|shield_me
 
|shield_opponent
 
|-
 
|shield_other
 
|shout_other
 
|shout_self
 
|-
 
|social_other
 
|social_self
 
|spells
 
|-
 
|tell_other
 
|tell_self
 
|time
 
|-
 
|weather
 
|whisper
 
|who
 
|-
 
|who_guild
 
|who_inv
 
|who_name
 
|-
 
|who_title
 
|wiz
 
|xpgain
 
|}
 
 
 
To use these colors all you have to do is use the following formatting command:
 
<nowiki>
 
&amp;[color]</nowiki>
 
The color that will be shown is the color that the player has set
 
for the color in question.  If for example the player has his or her
 
'death' color set to bright red with a black background and you have a
 
description as follows:
 
<nowiki>
 
descr
 
"This is a &amp;[death]death&amp;[room_descr]room"</nowiki>
 
The description would be in the players 'room_descr' color while
 
the word death would be in his or hers 'death' color.  You should note
 
we had to set the color back to the room description color so that the
 
rest of the description was not in the 'death' color.
 
 
 
To change the players color to the default out put color which is the color that is
 
used when no color is specified by the server then you use
 
'default'.  You probably won't use this in normal zone building but it
 
is very important to know it exists when you start making spells,
 
skills, and commands with DIL
 
 
 
== The DIL section ==
 
 
 
When I first thought of writing this manual I had planned to leave
 
DIL totally out of it.  The DIL language always confuses new Builders
 
and complicates teaching simple rooms, objects, and NPCs.  It became
 
clear to me though that DIL is such a part of the server that I at least
 
had to mention it hear so builders would know where to look and
 
what DIL could do for them when they got to the point where they were
 
ready to use it.
 
=== What is DIL? ===
 
 
 
DIL is short for, Data-based instructional language.  Not to be
 
confused with Database since DIL is nothing like a database.  Data-based
 
means that the language works on a fixed set of units like objects,
 
NPCS, and rooms and is designed to give them a life of their own.
 
Unlike on many of the mud servers on the internet DIL is not an
 
interpreted language it is a compiled language which gives you the user
 
much more safe guards against crashes and slow code.
 
 
 
DIL also provides a full set of data types to allow you to do
 
calculations or store information from players.  The DIL language can
 
even deal with file access and it can add fields and information to the
 
players if needed.  In short the VME server has its own internal
 
functional language that will allow you to do just about anything you
 
want to.
 
=== What can DIL be used for? ===
 
 
 
...
 
  
It is hard to explain what all DIL can be used for with out just
+
  sendtoall ( "some message", "rabbit@haon-dor");
writing a list of things that have already been done in DIL so here is the
 
list.
 
* All spells
 
* 60% of the commands and skills and growing
 
* Administrator commands
 
* Movement commands
 
* look commands
 
* 200+ quests and growing
 
* Message boards
 
* Mail system
 
* Clan system
 
* Automated Newbie guides
 
* object restrictions
 
* Death Sequence
 
* Magical combat system
 
* NPC agressive functions
 
* personalized Familiars
 
* personalized pets
 
* Deck of cards
 
* Chess board
 
* dice
 
* online AD&amp;D game playing system
 
* Communication channels
 
* automated wedding chapel
 
  
Realize this is only a small list of things that can be done in
+
  The message "some message" is sent to all units in the world matching the
DIL.  In the future we hope to be able to add the ability to easily
+
  data base name "rabbit@haon-dor". Like 'send()' and 'sendto()', the
change combat and all the character update features using DIL.  These
+
  message received matches the SFB_MSG message class.
things can be currently done with DIL but it takes a lot of knowledge
 
and work which we hope to simplify.
 
=== Where do I get more information on DIL ===
 
  
The online DIL reference guide is the most authoritative guide
+
<hr><a name="bpsendalld">
currently for DIL. It can be found at
+
sendtoalldil( m : string, s : string )
http://www.valhalla.com and follow the builders links.
+
  m : Message to send.
 +
  s : Name idx to a DIL program to send message to.
 +
  result: Send a message to all DIL programs matching a given database name.
  
In the near future we hope to have an entire new DIL manual that
+
<b>Example:</b>
will teach, a person who has never coded all the way to people who are
 
already professional coders, to use DIL.  For now if you can not find
 
what you need in the DIL reference manual you can join the DIL email list
 
at dil-request@valhalla.com or you can send a mail to
 
whistler@valhalla.com.  Until and even after the new DIL
 
manual is written we will always try to help you as much as possible
 
while you are getting started.  It is important that you at least try
 
and look through the DIL reference before asking a lot of questions
 
because many of the questions may be answered already.
 
  
==== VMC command line options ====
+
  sendtoalldil ( "some message", "intercomm@cemetery");
The argument string is processed from left to right. Options  may
 
appear  between  filenames, but it should be noted that an option
 
only takes effect when it is encountered. In most cases,  options
 
should be placed to the left of the filename arguments.
 
  
{|
+
  The message "some message" is sent to all DIL program in the world
|-
+
  matching the data base name "intercomm@cemetery".
|Option
+
  Like 'send()' and 'sendto()', the
|Description
+
  message received matches the SFB_MSG message class.
|-
 
|-m
 
|The location of the money file.  Normally etc/money.
 
|-
 
|-v
 
|Verbose compiler output shows much more information about objects and NPC
 
|-
 
|-M
 
|Make option. Only compile source files if they have been modified more recently than the corresponding output files.
 
|-
 
|-p
 
|Pre process the file only
 
|-
 
|-s
 
|Suppress the generation of output files.
 
|}
 
  
These options are not available to the email or FTP compiler, but
+
<hr><a name="bpcast_s">
normally you should not bother with them - they are probably
+
cast_spell( i : integer, caster : unitptr, medium : unitptr, target : unitptr )
set automatically.
 
  
 +
  WILL EVENTUALLY BE OBSOLETE AND REPLACED BY THE CAST_SPELL BELOW.
  
==== Reserved keyword listing ====
+
  i : Spell index to cast. See SPL_* in values.h and/or vme.h.
{|
+
  caster : The caster of the spell.
|-
+
  medium : The medium, with which the spell is cast, might be caster.
|ability
+
  target : The target of the spell.
|affect
 
|alignment
 
|applyf
 
|armour
 
|attack
 
|bits
 
|bright
 
|-
 
|capacity
 
|complete
 
|cost
 
|creators
 
|data
 
|default
 
|defensive
 
|descr
 
|-
 
|dilcopy
 
|door
 
|duration
 
|end
 
|equip
 
|exit
 
|exp
 
|extra
 
|-
 
|firstf
 
|flags
 
|follow
 
|height
 
|help
 
|hit
 
|id
 
|in
 
|-
 
|inside_descr
 
|into
 
|key
 
|keyword
 
|lastf
 
|level
 
|lifespan
 
|light
 
|-
 
|link
 
|load
 
|local
 
|mana
 
|manipulate
 
|max
 
|minv
 
|money
 
|-
 
|movement
 
|names
 
|nop
 
|notes
 
|npcflags
 
|offensive
 
|open
 
|outside_descr
 
|-
 
|position
 
|purge
 
|race
 
|random
 
|remove
 
|rent
 
|reset
 
|romflags
 
|-
 
|sex
 
|special
 
|speed
 
|spell
 
|string
 
|tickf
 
|time
 
|title
 
|-
 
|to
 
|type
 
|value
 
|weapon
 
|weather
 
|weight
 
|zonemax
 
|
 
|}
 
  
 +
  Use this to cast spells without performing all the usual mana stuff, etc.
 +
  Very useful with for example rings / items possessing magical abilities.
  
==== Race Definitions in values.h ====
+
integer cast_spell( i : integer, caster : unitptr, medium : unitptr, target : unitptr, effect : string )
The following list was extracted from the
+
  i : Spell index to cast. See SPL_* in values.h and/or vme.h.
''values.h''
+
  caster : The caster of the spell.
<nowiki>
+
  medium : The medium, with which the spell is cast, might be caster.
#define RACE_HUMAN          0    /* PC race */
+
  target : The target of the spell.
#define RACE_ELF             1    /* PC race */
+
  effect : A symbolic DIL program which takes no arguments. This will
#define RACE_DWARF          2    /* PC race */
+
             cause all effects to be suppressed and leave this to the program
#define RACE_HALFLING        3    /* PC race */
+
            specified. A string of "" will cause the ordinary messages to
#define RACE_GNOME          4    /* PC race */
+
             appear.
#define RACE_HALF_ORC        5
+
  returns: The result of the spell.
#define RACE_HALF_OGRE      6
 
#define RACE_HALF_ELF        7
 
#define RACE_BROWNIE        8
 
#define RACE_GROLL          9
 
#define RACE_DARK_ELF      10
 
#define RACE_SKAVEN        120
 
#define RACE_GNOLL          121
 
#define RACE_GOBLIN        122
 
#define RACE_HOBGOBLIN      123
 
#define RACE_KOBOLD        124
 
#define RACE_NIXIE          125
 
#define RACE_NYMPH          126
 
#define RACE_OGRE          127
 
#define RACE_ORC            128
 
#define RACE_SATYR          129
 
#define RACE_FAUN          130
 
#define RACE_SPRITE        131
 
#define RACE_DRYAD          132
 
#define RACE_LEPRECHAUN    133
 
#define RACE_PIXIE          134
 
#define RACE_SYLPH          135
 
#define RACE_HERMIT        136
 
#define RACE_SHARGUGH      137
 
#define RACE_GIANT          138
 
#define RACE_WARDEN        139  /* Warden???             */
 
#define RACE_TROLL          140
 
#define RACE_NORSE_GOD      142  /* Hmmmm. probably need better categories */
 
#define RACE_MERMAID        145
 
#define RACE_SIREN          146
 
#define RACE_NAIAD          147
 
#define RACE_MERMAN        148
 
#define RACE_MINOTAUR      149
 
#define RACE_YETI          150
 
#define RACE_OTHER_HUMANOID 999
 
  
#define RACE_BEAR          1000
+
  Use this to cast spells without performing all the usual mana stuff, etc.
#define RACE_DOG            1001
+
  Very useful with for example rings / items possessing magical abilities.
#define RACE_WOLF          1002
+
  Please note that in the two programs below the variable 'hm' represents
#define RACE_FOX            1003
+
  the number of hitpoints that will be deducted from the target.
#define RACE_CAT            1004
 
#define RACE_RABBIT        1005
 
#define RACE_DEER          1006
 
#define RACE_COW            1007
 
#define RACE_HARE          1008
 
#define RACE_GOAT          1009
 
#define RACE_EAGLE          1010
 
#define RACE_PIG            1011
 
  
#define RACE_DUCK          1100  /* This will interest the biologists... */
+
  <b>Example:</b>
#define RACE_BIRD          1101  /* This will interest the biologists... */
 
#define RACE_RAT            1102
 
#define RACE_HORSE          1103
 
#define RACE_BADGER        1104
 
#define RACE_SKUNK          1105
 
#define RACE_BOAR          1106
 
#define RACE_MOUSE          1107
 
#define RACE_MONKEY        1108
 
#define RACE_PORCUPINE      1110
 
#define RACE_ELEPHANT      1112
 
#define RACE_CAMEL          1113
 
#define RACE_FERRET        1114
 
#define RACE_VULTURE        1115
 
#define RACE_SQUIRREL      1116
 
#define RACE_OWL            1117
 
#define RACE_LEMURE        1118  /* Half-monkey (Makier) */
 
#define RACE_ELK            1119  /* Larger deer (Whapiti-deer) */
 
#define RACE_LION          1120
 
#define RACE_TIGER          1121
 
#define RACE_LEOPARD        1122
 
#define RACE_OTHER_MAMMAL  1999
 
  
#define RACE_TREE          2000
+
  %dil
#define RACE_VINE          2001
 
#define RACE_FLOWER        2002
 
#define RACE_SEAWEED        2003
 
#define RACE_CACTUS        2004
 
  
#define RACE_OTHER_PLANT   2999
+
   <i>dilbegin myeffect(medi : unitptr, targ : unitptr, hm : integer);
 +
  code
 +
  {
 +
      act("The caster is $1N medium is $2N and target is $3N",
 +
          A_ALWAYS, self, medi, targ, TO_ALL);
 +
      act("The spell result is $2d", A_ALWAYS, self, hm, null, TO_ALL);
 +
      quit;
 +
  }
 +
  dilend</i>
  
#define RACE_MAGGOT        3000
+
  .....
#define RACE_BEETLE        3001
 
#define RACE_SPIDER        3002
 
#define RACE_COCKROACH      3003
 
#define RACE_BUTTERFLY      3004
 
#define RACE_ANT            3005
 
#define RACE_WORM          3006
 
#define RACE_LEECH          3008
 
#define RACE_DRAGONFLY      3009
 
#define RACE_MOSQUITO      3010
 
  
#define RACE_OTHER_INSECT  3999
+
  %...
  
#define RACE_LIZARD        4000
+
  <i>dilbegin test();
#define RACE_SNAKE          4001
+
  var
#define RACE_FROG          4002
+
     n : integer;
#define RACE_ALLIGATOR     4004
+
  code
#define RACE_DINOSAUR      4005
+
  {
#define RACE_CHAMELEON      4006
+
       wait(SFB_DONE, command("beg"));
#define RACE_SCORPION       4007
 
#define RACE_TURTLE        4008
 
#define RACE_BAT            4009
 
#define RACE_TOAD          4010
 
  
#define RACE_OTHER_REPTILE  4999
+
      n := cast_spell(SPL_FIREBALL_1, self, self, activator, "myeffect@wiz");
  
#define RACE_CAVE_WIGHT    5001  /* Some kind a creature... */
+
      exec("say Result of spell was "+itoa(n), self);
#define RACE_UR_VILE        5002  /* Some kind a creature... */
+
  }
#define RACE_STONE_RENDER  5003  /* Some kind a creature... */
+
  dilend</i>
#define RACE_VAMPIRE        5005
 
#define RACE_SLIME          5006
 
#define RACE_WYRM          5007
 
#define RACE_AUTOMATON      5008
 
#define RACE_UNICORN        5009
 
  
#define RACE_DRAGON_MIN    5010  /* For use with special object */
+
<hr><a name="bpatt_s">
#define RACE_DRAGON_BLACK  5010
+
integer attack_spell( n : integer, caster : unitptr, medium : unitptr,
#define RACE_DRAGON_BLUE   5011
+
                      target : unitptr, bonus : integer)
#define RACE_DRAGON_GREEN  5012
+
   Returns : The amount of damage given.
#define RACE_DRAGON_RED    5013
+
  n : The spell index of the offensive spell (SPL_XXX)
#define RACE_DRAGON_WHITE  5014
+
  caster : The caster of the spell.
#define RACE_DRAGON_SILVER  5015
+
  medium : The medium, with which the spell is cast, might be caster.
#define RACE_DRAGON_TURTLE  5016
+
  target : The target of the spell.
#define RACE_DRAGON_LAVA   5017
+
   bonus : Possible (+) advantage or (-) penalty.
#define RACE_DRAGON_SHADOW  5018
 
#define RACE_DRAGON_LIZARD  5019
 
#define RACE_DRAGON_MAX    5020 /* For use with special object */
 
  
#define RACE_LESSER_DEMON  5020  /* Approx. Level < 100          */
+
  This is low-level internal spell stuff used to develop new spells. Do not
#define RACE_GREATER_DEMON  5021  /* Approx. Level > 100          */
+
  use unless you know what you are doing and have been allowed to do so by
#define RACE_SERVANT_DEMON  5022  /* Approx. < level 20          */
+
  your Admin.
#define RACE_PRINCE_DEMON  5023  /* Almost god, max level 149 (no more!) */
+
 
#define RACE_LESSER_DEVIL  5025  /* Approx. Level < 100 */
+
</PRE> 
#define RACE_GREATER_DEVIL  5026  /* Approx. Level > 100 */
+
<p>
#define RACE_SHADOW_DEVIL  5027
+
  <H2><A NAME="bpinsert"></A>
#define RACE_ARCH_DEVIL    5028
+
</H2>
  
#define RACE_MEDUSA        5030
+
<P><B>Function:  </B><CODE>insert( sl : &lt;stringlist or intlist&gt;, i : integer, s : string ) ;</CODE>
#define RACE_WINGED_HORSE  5031
+
<DL>
#define RACE_GARGOYLE      5033
+
<DT><B>sl</B><DD><P>the stringlist or intlist you are inserting to
#define RACE_GOLEM          5034
+
<DT><B>i</B><DD><P>the index where you want to insert the string
#define RACE_YOGOLOTH      5035
+
<DT><B>s</B><DD><P>the string you want to insert
#define RACE_MIST_DWELLER  5036
+
</DL>
 +
<P>This function allows you to insert a string in a stringlist or intlist
 +
with out re-writing the entire stringlist or intlist to do it.  The
 +
following Dil will add a string in order to a stringlist.
 +
<P><B>Example:</B>
 +
<BLOCKQUOTE><CODE>
 +
<HR>
 +
<PRE>
  
#define RACE_WEREWOLF      5037
+
dilbegin stringlist add_in_order (sl:stringlist,s:string);
#define RACE_WERERAT        5038
+
var
 +
i:integer;
 +
ln:integer;
 +
code
 +
{
 +
if (length(sl)==0)
 +
{
 +
addstring (sl,s);
 +
return (sl);
 +
}
  
#define RACE_ELEMENTAL_AIR   5040
+
ln:=length(s);
#define RACE_ELEMENTAL_EARTH 5041
+
i:=0;
#define RACE_ELEMENTAL_FIRE 5042
+
while (i&lt;ln)
#define RACE_ELEMENTAL_FROST 5043
+
{
#define RACE_ELEMENTAL_WATER 5044
+
if (length(sl.[i]) &lt;=ln)
#define RACE_ELEMENTAL_LIGHT 5045
+
   {
 +
  insert (sl,i,s);
 +
  return(sl);
 +
}
 +
i:=i+1;
 +
}
  
#define RACE_DEVOURER      5600
+
addstring (sl,s);
#define RACE_DANALEK        5601
+
return (sl);
 +
}
 +
dilend
 +
</PRE>
 +
<HR>
 +
</CODE></BLOCKQUOTE>
  
#define RACE_FAMILIAR      5900 /* Weirdo race... */
+
 
#define RACE_OTHER_CREATURE 5999
+
<PRE>
 +
<hr><a name="bpinterr">
 +
integer interrupt( flags : integer, dilexp, label )
  
#define RACE_ZOMBIE        6000
+
  Set up interrupt matching message classes matching "flags",
#define RACE_LICH          6001
+
  for example "SFB_COM" or "SFB_COM | SFB_MSG".
#define RACE_GHOUL          6002
 
#define RACE_SKELETON      6003
 
#define RACE_GHOST          6004
 
#define RACE_SPIRIT        6005
 
#define RACE_MUMMIE        6006
 
#define RACE_BANSHEE        6007
 
#define RACE_NAGA_SOUL      6008
 
#define RACE_OTHER_UNDEAD  6999
 
  
#define RACE_CRAB          7000
+
   When the program is activated on either of the specified conditions
#define RACE_SAND_SPIDER   7002
+
   the 'dilexp' is evaluated. If true, then execution continues at 'label',
#define RACE_RIVER_LEECH   7003
+
   otherwise the next interrupt is checked (if any).
#define RACE_SAND_CRAWLER  7004
 
#define RACE_SEA_HORSE      7005
 
#define RACE_SHARK          7006
 
#define RACE_LAMPREY        7007
 
#define RACE_MANTA_RAY      7008
 
#define RACE_CLIFF_HUGGER  7009
 
#define RACE_ALGAE_MAN      7010
 
#define RACE_WHELK          7011
 
#define RACE_OYSTER        7012
 
#define RACE_KRAKEN        7013
 
#define RACE_CAVE_FISHER   7014 /* Tiamat: lobster / spider breed */
 
#define RACE_OCTOPUS        7015
 
#define RACE_WHALE          7016
 
#define RACE_DOLPHIN        7017
 
#define RACE_EEL            7018
 
  
#define RACE_FISH          7998
+
  Interrupts are saved (restored), when 'recall' is set.
#define RACE_OTHER_MARINE  7999</nowiki>
+
   Returns an integer which is used for clear() to clear an interrupt.
==== weapon definitions in values.h ====
 
The following list was extracted from the
 
''values.h''
 
<nowiki>
 
#define WPN_BATTLE_AXE   7  /* Two Handed */
 
#define WPN_HAND_AXE      8
 
#define WPN_WAR_MATTOCK  9  /* Two Handed */
 
#define WPN_WAR_HAMMER  10
 
#define WPN_GREAT_SWORD  11  /* Two Handed */
 
#define WPN_SCIMITAR    12
 
#define WPN_KATANA      13
 
#define WPN_FALCHION    14
 
#define WPN_KOPESH      15
 
#define WPN_BROAD_SWORD  16
 
#define WPN_LONG_SWORD  17
 
#define WPN_RAPIER      18
 
#define WPN_SHORT_SWORD  19
 
#define WPN_DAGGER      20
 
#define WPN_BATTLE_MACE  21  /* Two Handed */
 
#define WPN_MACE        22
 
#define WPN_BATTLE_CLUB  23  /* Two handed */
 
#define WPN_CLUB        24
 
#define WPN_MORNING_STAR 25
 
#define WPN_FLAIL        26
 
#define WPN_QUARTERSTAFF 27
 
#define WPN_SPEAR        28
 
#define WPN_HALBERD      29
 
#define WPN_BARDICHE    30
 
#define WPN_SICKLE      31
 
#define WPN_SCYTHE      32  /* Two handed */
 
#define WPN_TRIDENT      33
 
#define WPN_FIST        34
 
#define WPN_KICK        35
 
#define WPN_BITE        36
 
#define WPN_STING        37
 
#define WPN_CLAW        38
 
#define WPN_CRUSH        39
 
#define WPN_WHIP        40
 
#define WPN_WAKIZASHI    41
 
#define WPN_BOW          42 /* Here down to Staff are Rangers Guild Jan 98 */
 
#define WPN_CROSSBOW    43
 
#define WPN_SLING        44
 
#define WPN_FIGHTING_STAFF 45 /* Two handed */
 
#define WPN_SABER        46
 
#define WPN_CUTLASS      47
 
#define WPN_MACHETE      48
 
#define WPN_LANCE        49
 
#define WPN_SHOCK_LANCE  50
 
#define WPN_PIKE        51
 
#define WPN_GREAT_AXE    52
 
#define WPN_BATTLE_SWORD 53</nowiki>
 
==== Liquid macros file ====
 
<nowiki>
 
#define LIQ_WATER(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("clear", WEIGHT,CAPACITY,INSIDE,10,1,0,POISON)
 
#define LIQ_BEER(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("brown", WEIGHT,CAPACITY,INSIDE,5,2,3,POISON)
 
#define LIQ_WINE(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("clear", WEIGHT,CAPACITY,INSIDE,5,2,5,POISON)
 
#define LIQ_ALE(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("brown", WEIGHT,CAPACITY,INSIDE,5,2,2,POISON)
 
#define LIQ_DARK_ALE(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("dark brown", WEIGHT,CAPACITY,INSIDE,5,2,1,POISON)
 
#define LIQ_WISKEY(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("golden",WEIGHT ,CAPACITY,INSIDE,4,1,6,POISON)
 
#define LIQ_WHISKY(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("golden",WEIGHT ,CAPACITY,INSIDE,4,1,6,POISON)
 
  
#define LIQ_LEMONADE(WEIGHT,CAPACITY,INSIDE,POISON) \
+
<b>Example:</b>
LIQ_DEF("red", WEIGHT, CAPACITY, INSIDE, 8, 1, 0,POISON)
 
#define LIQ_FIREBRT(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("green", WEIGHT,CAPACITY,INSIDE,0,0,10,POISON)
 
#define LIQ_LOCALSPC(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("clear", WEIGHT, CAPACITY, INSIDE, 3, 3, 3,POISON)
 
#define LIQ_SLIME(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("light green", WEIGHT,CAPACITY,INSIDE,8,4,0,POISON)
 
#define LIQ_MILK(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("white", WEIGHT, CAPACITY, INSIDE, 6, 3, 0,POISON)
 
#define LIQ_TEA(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("brown", WEIGHT, CAPACITY, INSIDE, 6, 1, 0,POISON)
 
#define LIQ_COFFEE(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("black", WEIGHT, CAPACITY, INSIDE, 6, 1, 0,POISON)
 
#define LIQ_COFFE(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("black", WEIGHT, CAPACITY, INSIDE, 6, 1, 0,POISON)
 
  
#define LIQ_BLOOD(WEIGHT,CAPACITY,INSIDE,POISON) \
+
The following program shows, that the owner (self) of the program keeps
LIQ_DEF("red", WEIGHT, CAPACITY, INSIDE, -1, 2, 0, POISON)
+
snoring while sleeping. The on_activation ensures that the program
#define LIQ_SALTWAT(WEIGHT,CAPACITY,INSIDE,POISON) \
+
is only activated when the owner is sleeping. However, since the interrupt
LIQ_DEF("clear", WEIGHT, CAPACITY, INSIDE, 2, 1, 0, POISON)
+
precede the on_activation, these may still be intercepted before the
#define LIQ_COKE(WEIGHT,CAPACITY,INSIDE,POISON) \
+
on_activation. The on_activation is just another type of interrupt that
LIQ_DEF("black", WEIGHT, CAPACITY, INSIDE, 5, 1, 0,POISON)
+
reacts on all flags (without actually setting them so that the program
#define LIQ_VODKA(WEIGHT,CAPACITY,INSIDE,POISON) \
+
is activated).
LIQ_DEF("clear", WEIGHT,CAPACITY,INSIDE,0,0,10,POISON)
 
#define LIQ_BRANDY(WEIGHT,CAPACITY,INSIDE,POISON) \
 
LIQ_DEF("golden", WEIGHT,CAPACITY,INSIDE,4,1,6,POISON)</nowiki>
 
==== Complete magical transfers macros listing ====
 
This listing of macros was taken from
 
''wmacros.h''. When building your objects you should
 
check the macros file to make sure you have the most up to date
 
macros.
 
<nowiki>
 
#define CHAR_FLAG_TRANSFER(_MFLAGS) \
 
flags {UNIT_FL_MAGIC}      \
 
affect                            \
 
  id ID_TRANSFER_CHARFLAGS      \
 
  duration -1                    \
 
  data[0] _MFLAGS                \
 
  firstf TIF_EYES_TINGLE        \
 
  tickf TIF_NONE                \
 
  lastf TIF_EYES_TINGLE          \
 
  applyf APF_MOD_CHAR_FLAGS;
 
  
/* skill MUST be one of SKI_XXX, amount in -10 to +10 */
+
When the program receives the message "relief" the snoring stops briefly.
#define SKILL_TRANSFER(skill, amount) \
+
As used, "relief" may only be set once.
flags {UNIT_FL_MAGIC}        \
 
affect                      \
 
  id ID_SKILL_TRANSFER      \
 
  duration -1              \
 
  data[0] skill            \
 
  data[1] amount            \
 
  firstf  TIF_SKI_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_SKI_DEC      \
 
  applyf  APF_SKILL_ADJ;
 
  
/* weapon MUST be one of WPN_XXX, amount in -10 to +10 */
+
When the program receives the message "cured", the snoring stops completely
#define WEAPON_TRANSFER(weapon, amount) \
+
(i.e. the program quits itself).
flags {UNIT_FL_MAGIC}        \
 
affect                      \
 
  id ID_WEAPON_TRANSFER    \
 
  duration -1              \
 
  data[0] weapon            \
 
  data[1] amount            \
 
  firstf  TIF_WPN_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_WPN_DEC      \
 
  applyf  APF_WEAPON_ADJ;
 
  
/* spell MUST be one of SPL_XXX, amount in -10 to +10 */
+
<i>dilbegin
#define SPELL_TRANSFER(spell, amount) \
 
flags {UNIT_FL_MAGIC}        \
 
affect                      \
 
  id ID_SPELL_TRANSFER      \
 
  duration -1              /* Must be permanent in the object */  \
 
  data[0] spell            /* It is a spell SPL_XXX transfer  */  \
 
  data[1] amount            /* Amount of better spell skill    */  \
 
  firstf  TIF_SPL_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_SPL_DEC      \
 
  applyf  APF_SPELL_ADJ;
 
  
#define STR_TRANSFER(amount) \
+
var
flags {UNIT_FL_MAGIC}      \
+
  i : integer;
affect                      \
 
  id ID_TRANSFER_STR        \
 
  duration -1                /* Must be permanent in the object */  \
 
  data[0] ABIL_STR          /* It is a strength function      */  \
 
  data[1] amount            /* Amount of better strength      */  \
 
  firstf  TIF_STR_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_STR_DEC      \
 
  applyf  APF_ABILITY;
 
  
#define DEX_TRANSFER(amount) \
+
code
flags {UNIT_FL_MAGIC}      \
+
{
affect                      \
+
  /* Notice that the sequence in which the interrupts (and the on_activation)
  id ID_TRANSFER_DEX        \
+
    are executed, is quite important: You can be cured at *any* time. The
  duration -1                /* Must be permanent in the object */  \
+
    program will skip if you are not sleeping. If you are sleeping you can
  data[0] ABIL_DEX            /* It is a dex function            */  \
+
    be relieved. */
  data[1] amount              /* Amount of better dex            */ \
 
  firstf  TIF_DEX_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_DEX_DEC      \
 
  applyf  APF_ABILITY;
 
  
#define CON_TRANSFER(amount) \
+
  interrupt(SFB_MSG, argument == "cured", the_end);
flags {UNIT_FL_MAGIC}      \
 
affect                      \
 
  id ID_TRANSFER_CON        \
 
  duration -1                /* Must be permanent in the object */  \
 
  data[0] ABIL_CON            /* It is a con function            */  \
 
  data[1] amount              /* Amount of better con            */  \
 
  firstf  TIF_CON_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_CON_DEC      \
 
  applyf  APF_ABILITY;
 
  
#define CHA_TRANSFER(amount) \
+
  on_activation(self.position != POSITION_SLEEPING, skip);
flags {UNIT_FL_MAGIC}        \
 
affect                      \
 
  id ID_TRANSFER_CHA        \
 
  duration -1                /* Must be permanent in the object */  \
 
  data[0] ABIL_CHA            /* It is a cha function            */  \
 
  data[1] amount              /* Amount of better cha            */  \
 
  firstf  TIF_CHA_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_CHA_DEC      \
 
  applyf  APF_ABILITY;
 
  
#define BRA_TRANSFER(amount) \
+
  i1 := interrupt(SFB_MSG, argument == "relief", relief);
flags {UNIT_FL_MAGIC}      \
 
affect                      \
 
  id ID_TRANSFER_BRA        \
 
  duration -1                /* Must be permanent in the object */  \
 
  data[0] ABIL_BRA            /* It is a bra function            */  \
 
  data[1] amount              /* Amount of better bra            */  \
 
  firstf  TIF_BRA_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_BRA_DEC      \
 
  applyf  APF_ABILITY;
 
  
#define MAG_TRANSFER(amount) \
+
  :loop:
flags {UNIT_FL_MAGIC}      \
+
  exec("snore", self);
affect                      \
+
  pause;
  id ID_TRANSFER_MAG        \
+
  goto loop;
  duration -1                /* Must be permanent in the object */  \
 
  data[0] ABIL_MAG            /* It is a mag function            */  \
 
  data[1] amount              /* Amount of better mag            */  \
 
  firstf  TIF_MAG_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_MAG_DEC      \
 
  applyf  APF_ABILITY;
 
  
#define DIV_TRANSFER(amount) \
+
  :relief:
flags {UNIT_FL_MAGIC}      \
+
  /* Suppose you can only be relieved once, then we must clear interrupt */
affect                      \
+
  clear(i1);
  id ID_TRANSFER_DIV        \
+
  pause;
  duration -1                /* Must be permanent in the object */ \
+
  pause;
  data[0] ABIL_DIV            /* It is a div function            */  \
+
  goto loop;
  data[1] amount              /* Amount of better div            */  \
 
  firstf  TIF_DIV_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_DIV_DEC      \
 
  applyf  APF_ABILITY;
 
  
#define HIT_TRANSFER(amount) \
+
  :the_end:
flags {UNIT_FL_MAGIC}      \
+
  /* Person is cured... */
affect                      \
+
  quit;
  id ID_TRANSFER_HPP        \
+
}
  duration -1                /* Must be permanent in the object */  \
+
dilend</i>
  data[0] ABIL_HP            /* It is a hit point function      */ \
 
  data[1] amount            /* Amount of better strength      */  \
 
  firstf  TIF_HIT_INC      \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_HIT_DEC      \
 
  applyf  APF_ABILITY;
 
  
#define SPEED_TRANSFER(newspeed) \
+
<hr><a name="bpclear">
flags {UNIT_FL_MAGIC}      \
+
clear( i : integer )
affect                      \
 
  id ID_TRANSFER_SPEED      \
 
  duration -1                /* Must be permanent in the object */  \
 
  data[0] newspeed          \
 
  firstf  TIF_SPEED_BETTER  \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_SPEED_WORSE  \
 
  applyf  APF_SPEED;
 
  
#define SLOW_TRANSFER(amount) \
+
   Clears the interrupt number "i". If i is invalid, this will either
flags {UNIT_FL_MAGIC}        \
+
   clear an wrong interrupt or do nothing.
affect                        \
 
  id ID_TRANSFER_SPEED      \
 
  duration -1                \
 
  data[0] newspeed          \
 
  firstf  TIF_SPEED_WORSE   \
 
  tickf  TIF_NONE          \
 
  lastf  TIF_SPEED_BETTER  \
 
  applyf  APF_SPEED;</nowiki>
 
==== Skill definitions in values.h ====
 
The following list was extracted from the
 
''values.h''
 
<nowiki>
 
#define SKI_TURN_UNDEAD        0
 
#define SKI_SCROLL_USE        1
 
#define SKI_WAND_USE          2
 
#define SKI_CONSIDER          3
 
#define SKI_DIAGNOSTICS        4
 
#define SKI_APPRAISAL          5
 
#define SKI_VENTRILOQUATE      6
 
#define SKI_WEATHER_WATCH      7
 
#define SKI_FLEE              8
 
#define SKI_SNEAK              9
 
#define SKI_BACKSTAB          10
 
#define SKI_HIDE              11
 
#define SKI_FIRST_AID        12
 
#define SKI_PICK_LOCK        13
 
#define SKI_STEAL            14
 
#define SKI_RESCUE            15
 
#define SKI_SEARCH            16
 
#define SKI_LEADERSHIP        17
 
#define SKI_KICK              18
 
#define SKI_SWIMMING          19
 
#define SKI_BASH              20
 
#define SKI_CLIMB            21
 
#define SKI_SHIELD            22
 
#define SKI_TRIP              23
 
#define SKI_DUAL_WIELD        24
 
#define SKI_CUFF              25
 
#define SKI_RESIZE_CLOTHES    26
 
#define SKI_RESIZE_LEATHER   27
 
#define SKI_RESIZE_METAL      28
 
#define SKI_EVALUATE          29 /* "Fake skill to simulate combinations */
 
#define SKI_PEEK              30
 
#define SKI_PICK_POCKETS      31
 
#define SKI_FILCH            32
 
#define SKI_DISARM            33
 
#define SKI_SKIN            34
 
#define SKI_SHELTER          35
 
#define SKI_SOOTHE            36
 
#define SKI_AMBUSH            37
 
#define SKI_CURARE            38
 
#define SKI_FASHION          39
 
#define SKI_BUTCHER          40
 
#define SKI_LAY_TRAP          41
 
#define SKI_SHOOT            42
 
#define SKI_HERBS            43
 
#define SKI_FORAGE            44
 
#define SKI_DOWSE            45
 
#define SKI_TRACK            46
 
#define SKI_HUNT              47
 
#define SKI_THROW            48
 
#define SKI_COOK              49
 
#define SKI_SCAN              50
 
#define SKI_SLIP              51
 
#define SKI_PALM              52
 
#define SKI_PLANT            53
 
#define SKI_STALK            54
 
#define SKI_KNEE              55
 
#define SKI_ELBOW            56
 
#define SKI_HIT              57
 
#define SKI_PUNCH            58
 
#define SKI_GLANCE            59</nowiki>
 
==== Spell definitions in values.h ====
 
The following list was extracted from the
 
''values.h''
 
<nowiki>
 
#define SPL_CALL_LIGHTNING    12  /* Cell Group  */
 
#define SPL_BLESS            13  /* D I V I N E */
 
#define SPL_CURSE            14
 
#define SPL_REMOVE_CURSE      15
 
#define SPL_CURE_WOUNDS_1    16
 
#define SPL_CURE_WOUNDS_2    17
 
#define SPL_CURE_WOUNDS_3    18
 
#define SPL_CAUSE_WOUNDS_1    19
 
#define SPL_CAUSE_WOUNDS_2    20
 
#define SPL_CAUSE_WOUNDS_3    21
 
#define SPL_DISPEL_EVIL      22
 
#define SPL_REPEL_UNDEAD_1    23
 
#define SPL_REPEL_UNDEAD_2    24
 
#define SPL_BLIND            25
 
#define SPL_CURE_BLIND        26
 
#define SPL_LOCATE_OBJECT    27
 
#define SPL_LOCATE_CHAR      28
 
  
#define SPL_RAISE_MAG        29  /* P R O T E C T I O N */
+
<hr><a name="bpona">
#define SPL_RAISE_DIV        30
+
integer on_activation ( dilexp , label )
#define SPL_RAISE_STR        31
+
  dilexp  : A boolean DIL expression.
#define SPL_RAISE_DEX        32
+
  label   : Label to jump to - OR the reserved keyword SKIP.
#define SPL_RAISE_CON        33
+
  returns : The index to the interrupt handing the on_activation.
#define SPL_RAISE_CHA        34
 
#define SPL_RAISE_BRA        35
 
#define SPL_SUN_RAY          36
 
#define SPL_DIVINE_RESIST    37
 
#define SPL_QUICKEN          38
 
#define SPL_HASTE            39
 
#define SPL_RAISE_SUMMONING   40
 
#define SPL_AWAKEN            41
 
#define SPL_MIND_SHIELD      42
 
#define SPL_HEAT_RESI        43
 
#define SPL_COLD_RESI        44
 
#define SPL_ELECTRICITY_RESI  45
 
#define SPL_POISON_RESI      46
 
#define SPL_ACID_RESI        47
 
#define SPL_PRO_EVIL          48
 
#define SPL_SANCTUARY        49
 
#define SPL_DISPEL_MAGIC      50
 
#define SPL_SUSTAIN          51
 
#define SPL_LOCK              52
 
#define SPL_UNLOCK            53
 
#define SPL_DROWSE            54
 
#define SPL_SLOW              55
 
#define SPL_DUST_DEVIL        56
 
#define SPL_DET_ALIGN        57  /* D E T E C T I O N */
 
#define SPL_DET_INVISIBLE    58
 
#define SPL_DET_MAGIC        59
 
#define SPL_DET_POISON        60
 
#define SPL_DET_UNDEAD        61
 
#define SPL_DET_CURSE        62
 
#define SPL_SENSE_LIFE        63
 
#define SPL_IDENTIFY_1        64
 
#define SPL_IDENTIFY_2        65
 
  
#define SPL_RANDOM_TELEPORT  66  /* S U M M O N I N G */
+
   result: Sets up an interrupt that is executed before every activation
#define SPL_CLEAR_SKIES      67
+
          of the DIL program. This is for example useful to catch
#define SPL_STORM_CALL        68
+
          situations where your NPC has fallen asleep or is injured.
#define SPL_WORD_OF_RECALL   69
+
          If 'dilexp' evaluates to TRUE then the program jumps to 'label'.
#define SPL_CONTROL_TELEPORT  70
+
          If 'label' is 'skip' then the program is simply not activated.
#define SPL_MINOR_GATE        71
+
          When the on_activation evaluates to true, and jumps to a label
#define SPL_GATE              72
+
          other than skip, the condition is automatically cleared. If the
#define SPL_CREATE_FOOD      73  /* C R E A T I O N */
+
          dilexp evaluates to false, or if the label is skip, the activation
#define SPL_CREATE_WATER      74
+
          remains active. Use the clear() to remove the on_activation.
#define SPL_LIGHT_1          75
 
#define SPL_LIGHT_2          76
 
#define SPL_DARKNESS_1        77
 
#define SPL_DARKNESS_2        78
 
#define SPL_STUN              79
 
#define SPL_HOLD              80
 
#define SPL_ANIMATE_DEAD      81
 
#define SPL_LEATHER_SKIN      82
 
#define SPL_BARK_SKIN        83
 
#define SPL_CONTROL_UNDEAD    84
 
#define SPL_BONE_SKIN        85
 
#define SPL_STONE_SKIN        86
 
#define SPL_AID              87
 
#define SPL_COLOURSPRAY_1    88  /* M I N D */
 
#define SPL_COLOURSPRAY_2    89
 
#define SPL_COLOURSPRAY_3    90
 
#define SPL_INVISIBILITY      91
 
#define SPL_WIZARD_EYE        92
 
#define SPL_FEAR              93
 
#define SPL_CONFUSION        94
 
#define SPL_SLEEP            95
 
#define SPL_XRAY_VISION      96
 
#define SPL_SUMMER_RAIN      97
 
#define SPL_COMMAND          98
 
#define SPL_LEAVING          99
 
#define SPL_FIREBALL_1      100  /* H E A T */
 
#define SPL_FIREBALL_2      101
 
#define SPL_FIREBALL_3      102
 
  
#define SPL_FROSTBALL_1      103  /* C O L D */
+
  <b>Example:</b>
#define SPL_FROSTBALL_2      104
+
          on_activation(self.position <= POSITION_SLEEPING, skip);
#define SPL_FROSTBALL_3      105
+
            or
 +
          on_activation(self.position > POSITION_SLEEPING, let_me_sleep);
  
#define SPL_LIGHTNING_1      106  /* C E L L */
+
<hr><a name="note">
#define SPL_LIGHTNING_2      107
+
How 'Done' messages (SFB_DONE) are treated. Note that not all commands are
#define SPL_LIGHTNING_3      108
+
implemented, if you are missing one, let Papi know and it will be created.
 +
See <a href="docs/command.txt">commands.txt</a> for details.
  
#define SPL_STINKING_CLOUD_1 109  /* I N T E R N A L */
+
<h5>This page last updated 03-27-2001, Ken Perry "Whistler" </h5>
#define SPL_STINKING_CLOUD_2 110
+
</pre>
#define SPL_STINKING_CLOUD_3 111
 
#define SPL_POISON          112
 
#define SPL_REMOVE_POISON    113
 
#define SPL_ENERGY_DRAIN    114
 
#define SPL_DISEASE_1        115
 
#define SPL_DISEASE_2        116
 
#define SPL_REM_DISEASE      117
 
#define SPL_ACIDBALL_1      118  /* E X T E R N A L */
 
#define SPL_ACIDBALL_2      119
 
#define SPL_ACIDBALL_3      120
 
#define SPL_FIND_PATH        121  /* Divine  */
 
#define SPL_DISPEL_GOOD      122
 
#define SPL_PRO_GOOD        123
 
#define SPL_TRANSPORT        124
 
#define SPL_FIRE_BREATH      125
 
#define SPL_FROST_BREATH    126
 
#define SPL_LIGHTNING_BREATH 127
 
#define SPL_ACID_BREATH      128
 
#define SPL_GAS_BREATH      129
 
#define SPL_LIGHT_BREATH    130
 
#define SPL_HOLD_MONSTER    131
 
#define SPL_HOLD_UNDEAD      132
 
#define SPL_RAISE_DEAD      133
 
#define SPL_RESURRECTION    134
 
#define SPL_UNDEAD_DOOR      135
 
#define SPL_LIFE_PROTECTION  136
 
#define SPL_ENERGY_BOLT      137
 
#define SPL_CLENCHED_FIST    138
 
#define SPL_METEOR_SHOWER    139
 
#define SPL_SUN_BEAM        140
 
#define SPL_SOLAR_FLARE      141
 
#define SPL_SUMMON_DEVIL    142
 
#define SPL_SUMMON_DEMON    143
 
#define SPL_SUMMON_FIRE      144
 
#define SPL_SUMMON_WATER    145
 
#define SPL_SUMMON_AIR      146
 
#define SPL_SUMMON_EARTH    147
 
#define SPL_CHARGE_WAND      148
 
#define SPL_CHARGE_STAFF    149
 
#define SPL_MENDING          150
 
#define SPL_REPAIR          151
 
#define SPL_RECONSTRUCT      152
 
#define SPL_SENDING          153
 
#define SPL_REFIT            154
 
#define SPL_FIND_WANTED      155
 
#define SPL_LOCATE_WANTED    156
 
#define SPL_SUN_GLOBE        157
 
#define SPL_MAGIC_CANDLE    158
 
#define SPL_SONIC_BREATH    159
 
#define SPL_SHARD_BREATH    160
 
#define SPL_CONE_SHARD      161
 
#define SPL_RAISE_HPP        162
 
#define SPL_MANA_BOOST      163  /* Creation */
 
#define SPL_TOTAL_RECALL    164
 
#define LAST_SPELL          165</nowiki>
 

Revision as of 12:00, 26 May 2020


DIL DOCUMENTATION

Version 4.0


Current Version by: <A HREF="mailto:whistler@valhalla.com">Whistler@valhalla.com</A>


<h3>Index</h3><i>
<a href = "#making">Making a Program</a>
<a href = "#types">Data Types:</a>
  <a href = "#str">string</a>
  <a href = "#strl">stringlist</a>
  <a href = "#int">integer</a>
  <a href = "#intlist">integerlist</a>
  <a href = "#eptr">extraptr</a>
  <a href = "#uptr">unitptr</a>
  <a href = "#cptr">cmdptr</a>
  <a href = "#zptr">zoneptr</a>
<a href = "#messies">Messages:</a>
  <a href = "#sfbcmd">SFB_CMD</a>
  <a href = "#sfbdone">SFB_DONE</a>
  <a href = "#sfbtick">SFB_TICK</a>
  <a href = "#sfbcom">SFB_COM</a>
  <a href = "#sfbdead">SFB_DEAD</a>
  <a href = "#sfbmsg">SFB_MSG</a>
  <a href = "#sfbpre">SFB_PRE</a>
<a href = "#built_in">Built-In Variables</a>
  <a href = "#cmdstr">cmdstr</a>
  <a href = "#excmdstr">excmdstr</a>
  <a href = "#excmdstr_case">excmdstr_case</a>
  <a href = "#self">self</a>
  <a href = "#activator">activator</a>
  <a href = "#targ">target</a>
  <a href = "#medium">medium</a>
  <a href = "#power">power</a>
  <a href = "#argu">argument</a>
  <a href = "#hb">heartbeat</a>
  <a href = "#null">null</a>
  <a href = "#weather">weather</a>
  <a href = "#mmmm">mud(day,month,..)</a>
  <a href = "#bvrealtime">realtime</a>
<a href = "#const">DIL Constructs:</a>
  <a href = "#dcif">if(...)</a>
  <a href = "#dcgoto">goto</a>
  <a href = "#dcwhile">while(...)</a>
  <a href = "#dcbreak">break</a>
  <a href = "#dccont">continue</a>
  <a href = "#ongoto">on .. goto ..</a>
  <a href = "#forea">foreach(...)</a>
<a href = "#assgn">Assignment</a>
<a href = "#express">Expressions:</a>
<a href = "#ops">Operators</a>
  <a href = "#ein">in</a>
  <a href = "#esins">string in string</a>
  <a href = "#esinsl">string in stringlist</a>
  <a href = "#esine">string in extraptr</a>
<a href = "#funcs">Functions:</a>
  <a href = "#fquit">quit</a>
  <a href = "#fret">return</a>
  <a href = "#fret2">return()</a>
  <a href = "#fields">Fields:</a>
  <a href = "#extra">extraptr</a>
  <a href = "#unit">unitptr</a>
  <a href = "#uobj">UNIT_ST_OBJ</a>
  <a href = "#uroom">UNIT_ST_ROOM</a>
  <a href = "#upcnpc">UNIT_ST_PC and UNIT_ST_NPC</a>
  <a href = "#unpc">UNIT_ST_NPC</a>
  <a href = "#upc">UNIT_ST_PC</a>
<a href = "#built_func">Built-In Functions:</a>
  <a href = "#bfasctime">asctime(...)</a>
  <a href = "#bfatoi">atoi(...)</a>
  <a href = "#bfcancarry">cancarry(...)</a>
  <a href = "#bfcheckpassword">check_password(...)</a>
  <a href = "#bfcomm">command(...)</a>
  <a href = "#bfdelstr">delstr(...)</a>
  <a href = "#bfdelunit">delunit(...)</a>
  <a href = "#bfdd">dildestroy(...)</a>
  <a href = "#bfdf">dilfind(...)</a>
  <a href = "#bfeq">equipment(...)</a>
  <a href = "#bffilesize">filesize(...)</a>
  <a href = "#bffindr">findroom(...)</a>
  <a href = "#bffindru">findrndunit(...)</a>
  <a href = "#bffinds">findsymbolic(...)</a>
  <a href = "#bffindu">findunit(...)</a>
  <a href = "#bffits">fits(...)</a>
  <a href = "#bfgcolor">getcolor(...)</a>
  <a href = "#bfgword">getword(...)</a>
  <a href = "#bfgwords">getwords(...)</a>
  <a href = "#bfgghead">ghead(...)</a>
  <a href = "#bfisaff">isaff(...)</a>
    <a href = "#bfislight">islight(...)</a>
  <a href = "#bfisplayer">isplayer(...)</a>
  <a href = "#bfisset">isset(...)</a>
  <a href = "#bfitoa">itoa(...)</a>
  <a href = "#bfleft">left(...)</a>
  <a href = "#bflen">length(...)</a>
  <a href = "#bfload">load(...)</a>
  <a href = "#bfloadstr">loadstr(...)</a>
  <a href = "#bfmelee">meleeattack(...)</a>
  <a href = "#bfmeleedamage">meleedamage(...)</a>
  <a href = "#bfmid">mid(...)</a>
  <a href = "#bfmonstr">moneystring(...)</a>
  <a href = "#bfop">opponent(...)</a>
  <a href = "#bforoll">openroll(...)</a>
  <a href = "#bfpathto">pathto(...)</a>
  <a href = "#bfpaychk">paycheck(...)</a>
  <a href = "#bfpurse">purse(...)</a>
  <a href = "#bfreplace">replace(...)</a>
  <a href = "#bfrestore">restore(...)</a>
  <a href = "#bfright">right(...)</a>
  <a href = "#bfrnd">rnd(...)</a>
  <a href = "#bfsavestr">savestr(...)</a>
  <a href = "#bfsend_pre">send_pre(...)</a>
  <a href = "#bfskill_name">skill_name(...)</a>
  <a href = "#bfsplind">spellindex(...)</a>
  <a href = "#bfsplinf">spellinfo(...)</a>
  <a href = "#bfsplit">split(...)</a>
  <a href = "#bfstrdir">strdir(...)</a>
  <a href = "#bfstrcmp">strcmp(...)</a>
  <a href = "#bfstrcmp">strncmp(...)</a>	
  <a href = "#bftextformat">textformat(...)</a>
  <a href = "#bftolower">tolower(...)</a>
  <a href = "#bftoupper">toupper(...)</a>
  <a href = "#bftranmon">transfermoney(...)</a>
  <a href = "#bfvis">visible(...)</a>
  <a href = "#bfweapon_name">weapon_name(...)</a>
    <a href = "#bfweapon_info">weapon_info(...)</a>
<a href = "#biproc">Built-In Procedures:</a>
  <a href = "#bpacc_mod">acc_modify(...)</a>
  <a href = "#bpact">act(...)</a>
  <a href = "#bpaddaff">addaff(...)</a>
  <a href = "#bpaddcolor">addcolor(...)</a>
  <a href = "#bpaddeq">addequip(...)</a>
  <a href = "#bpaddex">addextra(...)</a>
  <a href = "#bpadds">addstring(...)</a>
  <a href = "#bpatt_s">attack_spell(...)</a>
  <a href = "#bpbeginedit">beginedit(...)</a>
  <a href = "#bpblock">block</a>
  <a href = "#bpcast_s">cast_spell(...)</a>
  <a href = "#bpchangecolor">changecolor(...)</a>
  <a href = "#bpchngs">change_speed(...)</a>
  <a href = "#bpclear">clear(...)</a>
  <a href = "#bpdc">dilcopy(...)</a>
  <a href = "#bpdelcolor">delcolor(...)</a>
  <a href = "#bpdp">delete_player(...)</a>
  <a href = "#bpdest">destroy(...)</a>
  <a href = "#bpexec">exec(...)</a>
  <a href = "#bpexp">experience(...)</a>
  <a href = "#bpflog">flog(...)</a>
  <a href = "#bpfol">follow(...)</a>
  <a href = "#bpgamestate">gamestate(...)</a>
  <a href = "#bpinsert">insert(...)</a>
  <a href = "#bpinterr">interrupt(...)</a>
    <a href = "#bpkilledit">killedit</a>
  <a href = "#bplink">link(...)</a>
  <a href = "#bplog">log(...)</a>
  <a href = "#bplogcrime">logcrime(...)</a>
  <a href = "#bpnopri">nopriority</a>
  <a href = "#bpona">on_activation(...)</a>
  <a href = "#bppagestring">pagestring(...)</a>
  <a href = "#bpp_u">position_update(...)</a>
  <a href = "#bppri">priority</a>
  <a href = "#bpreboot">reboot</a>
  <a href = "#bpremove">remove(...)</a>
  <a href = "#bpresetlevel">reset_level(...)</a>
  <a href = "#bpresetvlevel">reset_vlevel(...)</a>
  <a href = "#bpresetrace">reset_race(...)</a>
  <a href = "#bpsec">secure(...)</a>
  <a href = "#bpsend">send(...)</a>
  <a href = "#bpsendall">sendtoall(...)</a>
  <a href = "#bpsendalld">sendtoalldil(...)</a>
  <a href = "#bpsendt">sendtext(...)</a>
  <a href = "#bpsendto">sendto(...)</a>
  <a href = "#bpsend_done">send_done(...)</a>
  <a href = "#bpset">set(...)</a>
  <a href = "#bpsetbright">setbright(...)</a>
  <a href = "#bpsetfight">set_fighting(...)</a>
  <a href = "#bpsetweight">setweight(...)</a>
  <a href = "#bpsetpassword">set_password(...)</a>
  <a href = "#bpstore">store(...)</a>
  <a href = "#bpstopfighting">stop_fighting(...)</a>
  <a href = "#bpsubaff">subaff(...)</a>
  <a href = "#bpsubex">subextra(...)</a>
  <a href = "#bpsubs">substring(...)</a>
  <a href = "#bpuneq">unequip(...)</a>
  <a href = "#bfunitdir">unitdir(...)</a>
  <a href = "#bpunsec">unsecure(...)</a>
  <a href = "#bpunset">unset(...)</a>
  <a href = "#bpwait">wait(...)</a>
  <a href = "#bpwalkto">walkto(...)</a>
<a href = "#note">Ending Notes</a>
</i>
<hr><center>
  This documentation is designed for people with some experience in programming.
Experience in C is recommended, but PASCAL or BASIC in some form or other
will do just fine too.

  DIL is a simple programming language with fixed types reflecting the types
used in Valhalla Mud. The language gives you almost endless possibilities in
designing your adventures and quests. It gives you the control you need for
making the game interesting and intelligent.
</center>
<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name="making">

<h3><b>Making a program:</b></h3>
<P>
  You define your DIL programs within your zone file. Each program you make is a
*template*. Such a template must be equipped with a unique name (for that zone).
Templates can either be defined in a new %dil section, just below the %zone
section in the zone file, or directly attached to units defined in your zonefile.</P><P>

  If you define your DIL templates inside a unit definition, that unit is
automatically assigned a program using that template. If you want to use an
already designed template, either in your own, or another zone, you use a
special function named "dilcopy", that takes the name of a template, and any
optional parameters in parenthesis. The parameters of a template called with
'dilcopy' may only be of types integer, strings and stringlists.
</P><P>
<b>Example:</b>

dilcopy myfunc@myzone("say Hello, my friend!", 1, CMD_SAY, {"name1", "name2"});

  DIL templates can always be reused. In fact, with version 2.0 of DIL, programs
are no longer saved with equipment, but only a symbolic reference is used. That
way, if you make a change in your zone, ALL units using that program are changed.
This however requires you keep the name. Upon loading, if a template is not
found, the program is halted and rendered useless until such a reference can be
found during loading.
</P><P>

<i>Technical note:</i>
</P><P>
  When you use several 'dilcopy' in your zonefile, only one instance is present
game-time, thus saving tremendous amounts of memory.  It is similar to a shared
library, in which code is shared  but variables are not.

You may use your templates to define both procedure and functions for your other
templates to call.

A template is defined by beginning with 'dilbegin' and ending with 'dilend'.
Inside the template your program section is defined, marked by the keyword 'code',
followed by the program itself;

<i>dilbegin myprogram();
var
  i : integer;
  j : integer;

code
{
  heartbeat:=PULSE_SEC*5;
  :start:
  exec("say Hello world", self);
  pause;
  goto start;
}
dilend</i>

  This simple template does nothing but making its owner say 'Hello world' once
every 5 seconds. The template is called 'myprogram' and takes no arguments. The
'pause' command waits for the program to receive a timer message, whose interval
is set by the 'inline' variable 'heartbeat'. The 'self' variable is a unitptr
referring to the unit owning the DIL program. Other inline variables will be
explained later.

  For a DIL program to work, it must be part of a *unit*: a room, player, non-player
or object. The program uses *messages* to operate.  Your program gets activated
when it receives a message that some command is being executed, or a certain amount
of time has passed. You decide yourself in the program, what to wait for, before
the program continues executing.

  Supposing you want your program to contain variables, you have to put them in a
section before the 'code' section marked 'var'. The variables are declared by
their type and their name, separated by a ':' and ended by a ';'

  For an example, see the program above. Variables of type 'string', 'stringlist'
and 'integer' are saved, if the unit the program is attached to is saved with
player inventory. Variables of type 'unitpr' and 'extraptr' are 'volatile'. This
means that they are cleared whenever there is a chance that their contents may
have been rendered non usable.  This ensures that you do not have any 'loose'
pointers. However it is possible to 'secure' the contents of a 'unitptr' type
variable of a unit located in your local environment (the units directly 'visible'
to the unit who owns the DIL program) (see the secure / unsecure functions).

<IMG SRC="../images/backgr/waveline.gif" BORDER="0"  HEIGHT="18" WIDTH="100%"><br><a name="types">
<h3><b>Data Types:</b></h3>

DIL supports a fixed set of types you can use and manipulate. Through these, you
can get and manipulate information about almost anything in the game. The types
are listed below:

<hr><a name="str">
<b>String:</b>

   A string is some text. They are used for a lot of things such as command
arguments, room descriptions etc. String variables are automatically resized and
allocated when you assign them, so you do not have to worry about the string
length nor allocation in your DIL programs. Strings may be compared either with
'==' (equal to),
'!=' (not equal),
'<=' (less than or equal to),
'>=' (greater than or equal to)  
'<' (less than),
 '>' (greater than.

  Static strings are defined just as in the rest of the zone, within double
quotations.  Strings may be searched easily with the 'in' operator.  Variables
of type string are saved with DIL programs, if attached to a saved unit.

<b>Example:</b>

  "This is a static string"

Strings may also be added to each other, in an expression.

<b>Example:</b>

  "say "+itoa(42)+" is the answer!"

<b>Example:</b>

  if (self.name == self.names.[1]) ...
  
  Elements of the string can also be accessed by referencing them by their position.
  
  <b>Example</b>
  if (str.[3]==f])
  {
  exec ("say The 4th element is a F.",self);
  }
  
  <B>Note</b>
  Currently you can only access the single elements of a string you can not set
them.  In the future this will be possible.  You can still accomplish this by
copying one string to the other one element at a time and changing any that you
want something like this.
  
<b>Example</b>
i:=0;
ln:=length (str);
while (str.[i]<ln)
	{
	if (str.[i]=="f")
	newstr.[i]:="b";
	else
	newstr:=str.[i];
	i:=i+1;
	}
	str:=newstr;
	
  This snip of Dil would replace any 'f' in a string with a 'b' remember dil is
not case sensitive so it will also replace an 'F'.

<hr><a name="strl">
<b>Stringlist:</b>

  A stringlist is a list of separate strings. This is used for things such as
(multiple) names or keywords. You may request a specified word in a stringlist
by its number.
<b>Example:</b>

  mystring := self.names.[2];

  Returning null if out of bounds of the stringlist (see 'length()'). Static
stringlists are defined just as in the rest of the zonefile, as a comma separated
list of static strings within curly brackets.

<b>Example:</b>

  mysrtringlist := {"Some string","another string","the last string"}

  Stringlists are modified through the 'addstring()' and 'substring()' procedures.
Stringlists are searched easily by the 'in' operator. See documentation below.
They can also be set directly (see example above).  Variables of type string are
saved with DIL programs, if attached to a saved unit.

  Elements of each separate string in a stringlist can be accessed by appending
a separate position at the end of the request for a string as follows:

<b>Example</b>
if (strlist.[5].[3]=="b"){
do something
}

<b>Note</b>
  See the strings for more information on accessing a single element.

<hr><a name="int">
<b>Integer:</b>

  Non-fraction numbers can be used throughout your DIL programs.  They are given
normally, or in normal C style hexadecimal, preceded with '0x'. Integers are
signed 32-bit integers.  Variables of type string are saved with DIL programs,
if attached to a saved unit.

<b>Example:</b>

  0x10

<b>Example:</b>

  2

  Integers are used within expressions as both number value and boolean(true/false)
values. You may use comparison between integers through the comparison operators:
'==' (equality),
'<' (less than),
'>' (greater than),
'<=' (less or equal),
'>=' (greater or equal)
'!=' (not equal).


<b>Example:</b>

  if (42<12) ...

  Returning the boolean value (true/false) depending on the comparison between
integers. The result may be stored in an integer variable, and tested later, or
used directly in an 'if' or 'while', etc.  You may also operate on boolean
expression themselves, using LOGICAL operators 'and','not','or', which allows
you to combine the expressions.

<b>Example:</b>

  if ( not ( (self.hp<42) or (self.level>10) ) ) ..

Integer expressions may also use a number of other operators:
'+' (addition)
'-' (subtraction/negation),
'*' (multiplication),
'/' (division),
'|' (bitwise or, for flags),
'&' (bitwise and, for flags)

Precedence rules for using these operators are still somewhat messed up.  You'd
better use parenthesis where ever possible.

<hr><a name="intlist">
<b>Intlist:</b>

  Intlists are an array of integer types.  They can be set directly as follows:

<b>Example</b>

wpn:={5,3,6,9,3,9};

The intlists can be accessed in the same way stringlist are accessed as follows.

<b>Example</b>

if (wpn.[5]==5)
{
do something
}

The intlists are saved on savable units.


<P>
<H2><A NAME="intlist"></A> <A NAME="ss5.3">5.3 The Integer List</A>
</H2>

<P><B>Type:  </B><CODE>intlist</CODE>
<P>
  This variable type allows you to keep an ordered list of integers with out
having to create a variable for each integer.
<P><B>Example:</B>  <CODE>Setting an intlist</CODE>
<BLOCKQUOTE><CODE>
<HR>
<PRE>

myintlist:={1,5,9,2,8,5};
myintlist.[10]:=50;

If you set a index that is higher then the highest index, every index in between will be set to zero. For example if you only have two values in the intlist and you set index value 10 to 50 all indexes between 2 and 10 will be set to 0.

Example: Using intlists


if (myintlist.[5]==5){
stuff
}

if (myintlist<myint){
stuff
}

i:=0;
ln:=length(myintlist);
while (i<ln){
myintlist.[i]:=i;
i:=i+1;
}

See Also:

  • <A HREF="#bpinsert">Insert</A>
  • <A HREF="#bpremove">Remove</A>
  • <A HREF="eptr">Extraptr</A>
  • Extraptr:

     Extra descriptions, quests structures, etc can be searched and manipulated
    

    using variables of this type. There is no way to declare static structures of this type in DIL programs. Lists of extra descriptions are easily searched with the 'in' operator (See below). Extraptr variables are 'volatile', and thus cleared whenever there is a possibility that they are rendered unusable.


    <A NAME="cptr">

    Type: cmdptr cmdptr fields

    
    <B>name</B>
                string - command name
    <DT><B>type</B>
                integer - command type like social or skill or just command
    <DT><B>level</B>
                integer - minimum level to use command
    <DT><B>loglevel</B>
                integer - level of character that can see the log 0 for no logs
    <DT><B>position</B>
                integer - minimum position to use command
    <DT><B>next</B>
                cmdptr - pointer to the next cmdptr
    <DT><B>previous</B>
                cmdptr - pointer to the previous cmdptr 
    </DL>

    The cmdptr can be used to search the command list or display all the commands. I0t is also now possible to sort the commands by type by defining your own command types and using the type field to sort on.

    In order to get the first command in the list you use the following function:

    Function: chead();

    If you want to get a specific command then you use the following function:

    Function: cmdptr := getcommand (s : string );

    Example:


    
    dilbegin cmdtst(arg : string);
    var
      cmd : cmdptr;
      st : string;
    
    code
    {
       cmd := chead();
    
    	  while (cmd)
            { 
            st := cmd.name + " " + itoa(cmd.level) + " " + itoa(cmd.type) + " " +
            itoa(cmd.loglevel) + " " + itoa(cmd.position);
            act("CMD: $2t", A_ALWAYS, self, st, null, TO_CHAR);
            cmd := cmd.next;
            }
            
            cmd:=getcommand("kick");
            sendtext ("You must be "+itoa(cmd.level+" to use kick&n",self);
            
               quit;
    }
    dilend
    



    <a name="uptr">

    Unitptr:

    Unit pointers are used to keep track of units: rooms, players, non-player or objects. Through a variable of this type you can access most of the information in a unit. Unitptr variables are 'volatile', and thus cleared whenever there is a possibility that they are rendered unusable.

    <A NAME="zptr">

    Type: zoneptr Zone Pointer Fields

    <DT><B>next</B><DD><P>unitptr - pointer to next zoneptr</p>
    <DT><B>previous</B><DD><P>unitptr - pointer to previous zone</p>
    <DT><B>creators</B><DD><P>stringlist - list of creators</p>
    <DT><B>name</B><DD><P>string - zone name (%zone)</p>
    <DT><B>title</B><DD><P>string - zone title (title "")</p>
    <DT><B>rooms</B><DD><P>unitptr - pointer to the base room</p> 
    <DT><B>objs</B><DD><P>unitptr - pointer to the base objects of the zone</p>
    <DT><B>npcs</B><DD><P>unitptr - pointer to base NPCs of the zone</p>
    <DT><B>resetmode</B><DD><P>integer- reset mode of zone in 'values.h'</p>
    <DT><B>resettime</B><DD><P>integer - the reset time of the zone</p>
    <DT><B>access</B><DD><P>integer - the access level of the zone</p>
    <DT><B>loadlevel</B><DD><P>integer - the loadlevel of the zone</p>
    <DT><B>payonly</B><DD><P>integer - the paystatus of the zone</p>
    <DT><B>roomcount</B><DD><P>integer - the number of rooms in a zone</p>
    <DT><B>objcount</B><DD><P>integer - the numbner of objects in a zone</p>
    <DT><B>npccount</B><DD><P>integer - the number of npcs/mobiles in a zone</p>
    <DT><B>fname</B><DD><P>string - the filename of a zone</p>
    <DT><B>notes</B><DD><P>string - the Zone Notes</p>
    <DT><B>help</B><DD><P>string - the Zone Help</p>
    </DL>

    The 'zoneptr' works like a unitptr. To get the first zoneptr in the global list of zones you use 'zhead'.

    Example: zoneptr := zhead();

    Zone list command


    
    dilbegin zonelist (arg:string);
    var
     z:zoneptr;
     buf:string;
    code
    {
              z:=zhead();
              while (z)
              {
              buf:="Name:  "+z.name+"&n";
              buf:=buf+"Filename:  "+z.fname+"&n";
              buf:=buf+"Creator:  "+z.creators.[0]+"&n";
              buf:=buf+"Notes:  &n"+z.notes+"&n&n";
              z:=z.next;
              }
               
              pagestring (buf,self);
              quit;
    }
    dilend
               
                       
    



    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%">
    <a name="messies">

    Messages:

    In DIL, a program attached to a unit gets activated when the program receives a message. In order to save CPU usage, there are a number of different message categories which can cause activation of a program. The 'wait()' commands first parameter is an integer, telling what message categories the program should reactivate on. The second parameter is an expression, which also must evaluate to TRUE. 'pause' is just special instances of the 'wait()' command. <a name="bpwait373">

    Caveat Builder:

    Whenever you construct the arguments for the wait command, bear in mind that ALL your tests will be executed EVERYTIME a message of the relevant kind comes through. Thus you should keep the length of the activation expression to a reasonable minimum, and you should NEVER use the time-consuming findxxx-functions.

    Valid example (That prohibits a player from removing an object):

    :glue:
    
    
    	wait(SFB_CMD,command(CMD_REMOVE));
    	u := findunit(activator,argument,FIND_UNIT_IN_ME,null );
    	if (u != self)
    	 {
    		goto glue;
    	 }
    	act("You can't remove $2n, it's sticky.",
    	   A_SOMEONE,activator,self,null,TO_CHAR););
    	block;
    	goto glue;
    

    See Also:

    <a href="findunit.html">Dil and Findunit()</a>

    The message categories are as follows:


    <a name="sfbcmd">
    SFB_CMD            Command message
    
      When this flag is set, the program gets activated by all commands (legal
      or illegal) issued by PC's or NPC's. Moving around is also considered a
      command.
    
      Assume a janitor executes the command '
      Ge all from corpse',
      And Ge interprets to 'get'
      
      then this will occur in the DIL program:
    
         'activator'... is a unitptr to the janitor.
         'cmdstr'...... is a string which contains 'get'
         'excmdstr'...... is a string which contains 'ge'
         'excmdstr_case'...... is a string which contains 'Ge'
         'argument'.... will contain 'all from corpse'
    
         command(CMD_GET) will evaluate to TRUE.
    

    <a name="sfbdone">
    SFB_DONE           'Command has now been executed' message
    
      When this flag is set, the program gets activated by all successful commands
      issued by PC's or NPC's. The 'activator', 'medium' and 'target' special
      values are used as follows:
    
         'activator'... The PC / NPC which executed the command
         'medium'...... The unit which is operated upon.
         'target'...... The target of the operation.
    
      For example, assume the player John gives a garlic to Mary the Lumberjack
      wife. The following values are set:
    
         activator == John (unitptr)
         medium    == Mushroom (unitptr)
         target    == Mary (unitptr)
    
      command(CMD_GIVE) will evaluate to true.
    
      You thus know that Mary has in fact received the mushroom. It is NOT possible
      to block (using the 'block' command) these commands since they have already
      been executed at the time of notification.  In a 'get' command, medium would
      be a unitptr to where the unit was taken from, and target would be the object
      which was taken.
    
      See the file commands.txt for a description of how the arguments are set for
      each command. If you can not find a command in there, just ask to get it
      implemented. Especially you should pay attention to the non-obvious SFB_DONE
      command(CMD_AUTO_ENTER).
    

    <a name="sfbtick">
    SFB_TICK           Timer message
    
      When this flag is set, the routine gets activated by a "clock". The clock
      ticks (in 1/4th of a second) are determined by the 'heartbeat' variable.
    
         'activator'... is null.
         'argument'.... will be empty.
    
          command(CMD_AUTO_TICK) will evaluate to TRUE.
    <hr><a name="sfbcom">
    SFB_COM            Combat message
    
      When this flag is set, the routine gets activated whenever a combat is in
      progress. The unit containing the DIL program needs not be involved in the
      combat itself:
    
         'activator'... is a unitptr to the PC/NPC about to hit someone else.
         'argument'.... is empty.
    
          command(CMD_AUTO_COMBAT) will evaluate to TRUE.
    <hr><a name="sfbdead">
    SFB_DEAD           Death message
    
      When this flag is set, the routine gets activated when a PC or NPC dies:
    
         'activator'... will point to the PC/NPC that is about to die.
         'argument'.... is empty.
    
          command(CMD_AUTO_DEATH) will evaluate to TRUE
    
      The SFB_DEAD message is sent, just as the character dies, while his items are
      still equipped, just before the corpse is created.  The character's '.fighting'
      field points to his primary opponent, although this person does not necessarily
      have to be the one that killed him.
    
      This can be exploited by making items wiz invisible (the .minv field) just as
      the message is received, causing them to stay inside the player rather than
      being transferred to the corpse. This does both give the ultimate crash
      protection, as well as a means of letting items, such as bribe items, forever
      be a part of the player (remember to make it un-wizinvis when the player
      returns from heaven - players should not have access to items while in heaven).
    

    <a name="sfbmsg">
    SFB_MSG            User message
    
      When this flag is set, the routine gets activated when a message is passed
      to it. Messages can be passed with the DIL commands 'sendto' and 'send':
    
         'activator'... is a unitptr to the unit sending the message.
         'argument'.... is a string containing possible data from the sender.
    
          command(CMD_AUTO_MSG) will evaluate to true.
    
    
      Messages are normally not generated by actions performed by the owner of the
      program. For a program to be able to be aware of messages from the owner, a
      keyword 'aware' should be listed just after 'dilbegin'.
    
      When a unit is saved, normally, the DIL programs in it would restart when the
      program is loaded. However it is possible to let DIL programs recall their
      execution from where they left off when they where saved.  This is done by
      listing the keyword 'recall' after the 'dilbegin'.  This is however a bit
      limited.  Only the status of the original template are saved. Not the state
      inside a template called as a function or procedure from inside the original
      template. 'secure' and interrupts are not recalled upon loading the template.
    
    
    <b>Example:</b>
    
    <i>dilbegin recall aware mute();
    var
       i : integer;
    
    code
    {
       i:=10;
       while (i>0)
       {
          wait(SFB_CMD,command(CMD_SAY) or command(CMD_SHOUT));
          exec("emote tries to make a sound, but only blood spurts through"+
               "the lips",self);
          block;
          i := i - 1;
       }
    
       i:=10;
       while (i>0)
       {
          wait(SFB_CMD,command(CMD_SAY) or command(CMD_SHOUT));
          exec("emote tries to make a sound, but can't",self);
          block;
          i := i - 1;
       }
    
       i:=10;
       while (i>0)
       {
          wait(SFB_CMD,command(CMD_SAY) or command(CMD_SHOUT));
          exec("emote tries to make a loud sound, but can't",self);
          block;
          i := i - 1;
       }
       quit;
    }
    dilend</i>
    
    /* When attached to a PC, the pc will be unable to utter a sound the first 10
       sound command, and blood will spurt out.
       The next 10 sound commands, the victim just can't shout.
       The last 10 sound commands only say will work.
       In the end, 'quit' removes the program all together.
       The smart thing is that the 'aware' keyword lets the program receive messages
       from the owner (player) commands. Secondly, the keyword 'recall' makes sure
       that the program does not start over, if the victim quits in the middle, but
       restart at the position it had attained.
       Do not put in the 'aware' if it is not needed. It saves some interpretation
       time not having to pass the extra messages.
    */
    

    <a name="sfbpre">
    SFB_PRE            Command preprocessing
    
      When this flag is set, the program is activated by a few special events
      which can then be blocked or changed. Currently, this event is triggered
      just prior to a spell being cast, and just prior to any sort of damage
      being given to a target.
    
      PRE "command(CMD_CAST)"
    
      Assume a a spell is cast from player A on player B with a scroll C.
    
         'activator'... is a unitptr to A.
         'medium'   ... is a unitptr to C.
         'target'   ... is a unitptr to B.
    
         command(CMD_CAST) will evaluate to TRUE.
    
         'argument'.... will contain a number followed by any
                        argument to the spell itself. You should
                        parse this number, it equals the spell number SPL_XXX.
         'power' ....   is set to 'HM', i.e. how powerful the spell cast
                        is going to be. YOu can change this number at will.
                        If you decide to block the spell, you ought to set it
                        to -1.
    
    Example:
       wait(SFB_PRE, command(CMD_CAST));
    
       s := getword(argument);
       splno := atoi(s);
    
       if (splno == SPL_FIREBALL_3)
         power := 0; /* No damage */
       ...
    
    
      PRE "command(CMD_AUTO_DAMAGE)"
    
      Assume that damage is given from player A to player B with a sword C.
    
         'activator'... is a unitptr to A.
         'medium'   ... is a unitptr to C.
         'target'   ... is a unitptr to B.
    
         command(CMD_AUTO_DAMAGE) will evaluate to TRUE.
    
         'power' ....   is set to how much damage will be given. You can change
                        this number at will, but you should not set it to less
                        than zero.
    
         'argument'.... will contain three numbers that you must parse to
                        determine what kind of damage we're talking about.
    
                        First number is the attack group, this can be one of
                        MSG_TYPE_XXX from values.h and/or vme.h.
    
                        Second number is dependant on the attack group and
                        identifies what damage compared to the group. For
                        example WPN_XXX for weapon group.
    
                        Third number is the body hit location, one of WEAR_XXX,
                        (but not all of them, just hands, feet, legs, body, head,
                         arms, i.e. the armour positions, not positions like finger
                         or ear).
    
    
    Example:
       wait(SFB_PRE, command(CMD_AUTO_DAMAGE));
    
       s1 := getword(argument);
       grpno := atoi(s1);
    
       s2 := getword(argument);
       atkno := atoi(s2);
    
       s3 := getword(argument);
       hitloc := atoi(s3);
    
       if (grpno == MSG_TYPE_SPELL)
       {
          if ((s2 == SPL_FINGER_DEATH))
          {
              act("Your scarabaeus lights up as it protects your life force.");
              power := -1;
              block;
          }
       }
       ...
    
    
    <hr>
    <b><i>A note upon activating a DIL program</i></b>
    
    This is what you can't do:
    
      If a DIL program is already active, e.g. it is sending a message or
      perhaps using "exec" to perform an action, then it can not be activated.
      Thus, any active DIL program is unable to catch further messages.
      Imagine this setting:
    
      You have five program P1..P5. P1 sends a message, which is intercepted
      by P2. P2 now sends a message, but since P1 is busy it can not process
      the message. P3..P5 are however possible candidates.
      Assume P3 sends a message, and P4 acts upon it. P4 now sends a message
      and the ONLY program which can catch it is P5, since all the other programs
      are "busy". If P5 sends a message no-one can act upon it. When P5
      returns, so does P4, P3, P2 and finally P1.
    

    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%">
    <a name="built_in">

    Built-in Variables:

    'cmdstr'<a name="cmdstr">
       This variable is a string which contains the "command" which was entered
       by a player. The result of adding:
    
          cmdstr + " " + argument
    
       is the entire string as entered by the player.
       The 'cmdstr' is EXPANDED by the interpreter, so assume a player
       types 's' then the string is expanded to 'south'.
    
    
    'excmdstr'<a name="excmdstr">
       This variable is a string which contains the "first string" which was entered
       by a player. The result of adding:
    
          excmdstr + " " + argument
    
       is the entire string as entered by the player. The 'excmdstr' is not
       EXPANDED by the interpreter, but it is converted to lower case. So
       assume a player types 'S' then the string is returned as 's'.  The
       'excmdstr' is however changed to all lower case if you don't want
       this see 'excmdstr_case'.
       
    'excmdstr_case'<a name="excmdstr_case">
       This variable is a string which contains the "first string" which was entered
       by a player. The result of adding:
    
          excmdstr_case + " " + argument
    
       is the entire string as entered by the player.
       The 'excmdstr' is not changed in anyway from how a player types it.
       If a player types 'S' then the 'excmdstr_case' will have 'S' in it.
       
          <hr><a name="self">
    'self'
       This variable is a unitptr to the unit owning the DIL program.
       For C++ people, this is like the 'this' pointer.
       For example, if Mary has a program, then self.title equals
       "Mary the Lumberjack wife"
    

    <hr><a name="activator"> 'activator'

      This variable is a unit pointer to the unit which activated the DIL
      program. It is set if 'activator' issued a command or unknown command
      and the program was setup to catch it, with : wait (SFB_CMD...).
      See description of messages for more information.
    

    <hr><a name="targ"> 'target'

      This variable is a unit pointer to the unit which is the target of the
      current operation. For 'done' messages this could for example be the
      destination in a give command.
      See description of messages for more information.
    

    <hr><a name="medium"> 'medium'

      This variable is a unit pointer to the unit which was used during an
      operation. For 'done' messages this could for example be a bag which
      was the medium in a get operation.
      See description of messages for more information.
    

    <hr><a name="power"> 'power'

      This variable is an integer which can be reassigned. It is used in
      permission messages and in a few done messages. For example a permission
      request to damage a person with 100 damage would have power equal 100.
      This could then be reduced to 50 by assigning a new number.
      See description of messages for more information.
    

    <hr><a name="argu"> 'argument'

      This variable is a string, showing the argument of a command resulting
      in the activation of the DIL program. See SFB_CMD for example.
    

    <hr><a name="hb"> 'heartbeat'

      This is the DIL programs heartbeat. It can be assigned runtime to
      change the rate with which SFB_TICK is activated. Do not set it
      too low, and remember that it is specified in 1/4th of a second.
      use the constant PULSE_SEC to multiply your wanted delay, for
      Example:
         heartbeat := PULSE_SEC*25; /* Tick every 25 seconds */
    

    <hr><a name="null"> 'null'

      This is a null pointer.
    

    <hr><a name="weather"> 'weather'

      This is the state of the mud-weather. It will equal one of the
      SKY_XXX values in values.h and/or vme.h.
    

    <hr><a name="bvrealtime"> 'realtime'

      This variable returns the number of seconds passed since 1970 something.
      For C buffs this is equivalent to time(NULL).
    

    <hr><a name="mmmm"> 'mudday' 'mudhour' 'mudmonth' 'mudyear'

      These variables lets your program keep track of the time in the mud.
      They all have integer types.
    

    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%"><br><a name="const"> <h3><b>DIL constructs:</b></h3>

    DIL offers a set of construct for you to program with.

    <hr><a name ="dcif"> <b>if:</b>

       The if statement is much like C. It takes any type as
       argument. Non integers are considered 'TRUE' if they are
       not null.
    

    <b>Example:</b>

    <i> dilbegin foo();

     code
     {
       if (self.hp>10)
       {
         exec("say Hehe!",self);
       }
       else
       {
         exec("say ouch!", self);
       }
     }
     dilend</i>
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       if (self.loaded>10)
       {
         exec("say its getting crowded!",self);
       }
     }
     dilend</i>
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       if (self.loaded<10)
         exec("say plenty of room!",self);
     }
     dilend</i>
    

    <hr>

    <b>goto:</b><a name ="dcgoto">

       The goto statement lets you jump about in the code.
       Labels in your DIL programs, for 'goto' or interrupts
       are defined within ':'. For an example, see the program below.
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       :mylabel:
       exec("say Hello world",self);
       pause;
       goto mylabel;
     }
     dilend</i>
    

    <hr> <b>while:</b><a name ="dcwhile">

       The while statement lets you execute a series of
       statements while an expression evaluates to TRUE.
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       while (not self.inside) {
         exec("say I own nothing", self);
         pause;
       }
       exec("say ahh.. now i own something", self);
     }
     dilend</i>
    

    <hr>

    <b>break:</b> <a name ="dcbreak">

       The break statement makes you break out of any
       loop you're currently in.
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       while (self.inside) {
         if (self.position &lt POSITION_SLEEPING)
           break;
         exec("say I own something", self);
         pause;
       }
     }
     dilend</i>
    

    <hr>

    <b>continue:</b><a name ="dccont">

       The continue statement makes you jump to the top
       of any loop you're currently in.
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       while (self.inside) {
         if (self.position &lt POSITION_SLEEPING)
           break;
         pause;
         if (self.hp<0) continue;
         exec("say I own something", self);
         pause;
       }
     }
     dilend</i>
    

    <hr>

    <b>on <i>n</i> goto <i>la</i>, <i>lb</i>, ..., <i>ln</i>:</b><a name="ongoto">

       This construct is an easy way of performing a goto operation
       based on the result of an integer. The integer value 'n' must
       be zero or positive and less than the number of labels specified
       in the label-list. If n is outside this range, the on-goto operation
       is skipped and execution continues at the next instruction.
    
       Based on the value of 'n' execution continues at the label
       corresponding to number 'n' in the list. I.e. if n is 0, then
       execution continues at the first specified label, if n is 1
       then at the second, etc. etc.
    


    <b>Example:</b>

     Assume you have an integer 'i' larger than zero, which takes
     on 0, 1, 2, 3, 4 or 5. Based on each value you need to take a
     different action, this is how you can do it:
    

    <i>

       on i goto grin, laugh, grin, nada, poke, laugh;
       log("Value was not in the range 0..5");
       quit;
    
         :laugh:
         exec("grin", self);
         goto ...;
    
         :grin:
         exec("cackle", self);
         goto ...;
    
         :blank:
         exec("cry", self);
         goto ...;
    
         :poke:
         exec("smirk", self);
         goto ...;
    

    </i> It is often used in this context <i>

       on rnd(0,4) goto l1, l2, l3, l4, l5;
    
       :l1:
       bla;
    
       :l2:
       bla;
    
       ....
    

    </i>

    <hr><b>foreach:</b><a name="forea">

     Foreach is an easy way to process all the units in the
     local environment relative to the 'self' executing the
     foreach. Foreach takes care of creating a list of local
     units, and of securing them. You can use both break and
     continue in a foreach statement. The unit executing the
     foreach ('self') is always a part of the foreach.
    
         It is important to understand that the units in the local
         environment are relative to the 'self' executing the foreach.
    

    <b>Example:</b>

       This foreach is copied onto the spell caster, and hence all units
       relative to the spell caster (i.e. self) are processed in the foreach.
       Assume that it was executed on the spell caster's staff, then all units
       found would be relative to the staff, i.e. the spell caster's inventory.
    

    <i> ...

      foreach (UNIT_ST_PC|UNIT_ST_NPC, u)
      {
         if (u.hp < u.max_hp)
         {
            act("Warm raindrops fall upon you, cleaning your wounds.",
                A_ALWAYS, u, null, null, TO_CHAR);
            u.hp := u.hp + 6;
            if (u.hp > u.max_hp)
              u.hp := u.max_hp;
         }
         else
           act("Warm raindrops fall upon you.",
               A_ALWAYS, u, null, null, TO_CHAR);
         pause;
      }
    

    ...</i>

    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%"><br><a name="assgn">

    <b>Assignment:</b>

       You can assign values to the variables you declare
       in your 'var' section, and some of the built-in
       variables. This is  done by the ':=' operator.
       Note that you can also assign a variable the result
       of an expression
       (the addition of strings below as an example)
    

    <b>Example:</b>

     <i>dilbegin foo();
     var
       myvarsl : stringlist;
       myvars : string;
     code
     {
       :start:
       myvarsl := {"a string","another","the first"};
       myvars := self.name+" XX ";
       myvarsl.[2] := "the last";
       myvarsl.[3] := "illegal";  /* Will not work since [3] is not defined */
       pause;
       goto start:
     }
     dilend</i>
    


    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%"><br><a name ="express">

    <b>Expressions:</b>

     The expressions used in assignment can return any
     of the types you can declare variables. Also they might return
     fail or null. An expression returning fail will not result
     in any action being taken. Fail is returned when you
     request a field from a null pointer, or the like.
    

    <b>Example:</b>

     <i>dilbegin foo();
     var
       myvarsl : stringlist;
       myvars : string;
       myvarint : integer;
       myvaredp : extraptr;
       myvarunit : unitptr;
     code
     {
       :start:
       myvarunit := self.inside.next;
       myvarsl := {"a string","another","the last"};
       myvars := self.name+" XX "+itoa(self.hp);
       myvarint := activator.hp;
       myvaredp := "Rabbit Stew Complete" in activator.quests;
       pause;
       goto start:
     }
     dilend</i>
    

    <hr><a name ="ops"> <b>Operators:</b>

     DIL features many other operators. For integers,
     '<', '>', '<=', '>=', '!=' '==' signify less than,
     greater than, less or equal, greater or equal, not equal,
     and equality operators. Furthermore, you can compare
     strings with '==' or '$=' for equality test, and '!='
     for non equality. Pointers may also use '==' and '!='
     and you may force DIL to compare pointers, even for
     strings with the '#=' pointer-equality operator.
     The '$=' and '#=' is considered obsolete, and only
     used for backward compatibility.
    

    <hr><a name ="ein"> <b>in:</b> The special operator 'in' is a multipurpose operator for a lot of things. It allows you to search through quests and extra descriptions, stringlists and search for words in strings.

    <hr><a name ="esins"> string 'in' string

      Argument 1: A string to find.
      Argument 2: A string to search.
      Return: TRUE, if first string is found in second string.
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       if ("guard" in activator.title)
         exec("say hello guard",self);
       pause;
     }
     dilend</i>
    

    <hr><a name ="esinsl"> string 'in' stringlist

      Argument 1: A string to find.
      Argument 2: A stringlist to search.
      Returns: 1.. if first string is found in stringlist, or 0 if it is
               non existent. If found the number equals the index of the
               string found plus one.
    

    Example 1:

     s := "c";
     sl := {"a","b","c","d"};
     i := s in sl;
    
     The result of 'i' is 3, and sl.[i-1] equals "c" (s).
    

    Example 2:

     <i>dilbegin foo();
     code
     {
       if ("james" in activator.names)
         exec("say hello james.",self);
       pause;
     }
     dilend</i>
    

    <hr><a name ="esine"> string in extraptr

      Argument 1: A string to find.
      Argument 2: An extra description list to search.
      Return: Extraptr to first entry with string matching .names or
              null if none. (names must be exact letter by letter
              match, although case is ignored).
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       if ("Rabbit Stew Complete" in activator.quests) {
         exec("say wow!, you helped Mary get her stew!", self);
         exec("app ", self);
       }
       pause;
     }
     dilend</i>
    

    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%"><br><a name ="funcs"> <h3>Functions:</h3>

     DIL features an extended set of built-in functions
     for extended program control. Built-in functions can be part of
     any expression in DIL. The built-in functions are
     listed later.
    

    <b>Example:</b>

     <i>dilbegin foo();
     code
     {
       exec("say I exist in "+itoa(self.loaded)+"copies", self);
       pause;
     }
     dilend</i>
    
     DIL also lets you use templates as functions, but in a
     limited way. Using templates as functions, you may only
     use the return value to assign it to one of the variables
     declared in the 'var' section. No fields.
    

    <b>Example:</b>

     <i>dilbegin integer bar(s:string);
     code
     {
       exec("say "+s,self);
       return rnd(1,10);
     }
     dilend</i>
    
     <i>dilbegin foo();
     external
       integer bar(s:string);
     var
       myint:integer;
     code
     {
       myint := bar("rolling the dice.");
       exec("say I rolled a "+itoa(myint));
       pause;
     }
     dilend</i>
    

    <hr><a name="fquit"> quit:

     This simple command quits the entire DIL program, even if
     called while inside a procedure or function.
    

    <hr><a name="fret"> return:

     Return from a call to a procedure template (no return type
     declared). The execution continues from where the procedure
     was called.
    

    <hr> return():<a name="fret2">

     Return from a call to a function (return type declared).
     The expression inside the parenthesis evaluates to the value
     returned.
    

    <hr>

     DIL also allows for game-time *symbolic* resolving of
     function/procedure names. This allows you to pass template names
     as string arguments and call them in your program. This kind of
     function call requires taxing look ups and type check runtime, so
     use the normal kind of procedures if possible.
    
     In effect, the syntax of a symbolic call is similar to that of
     a normal, except you use a string variable as function name
     instead of the real function name. If the string variable contains
     a valid reference to a procedure/function, and all the argument
     types matches the found templates argument types, the call
     is made. Otherwise, the call is skipped. Note that you will get no
     type check by the compiler when using symbolic references.
    

    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%"><br><a name ="fields"> <h3><b>Fields:</b></h3>

    The 'extraptr' and 'unitptr' types contain information which is available to you by using fields. For example (self is a unitptr), self.inside is a unitptr to what is inside the 'self' unit. (Hence '.inside' is the field). And self.inside.outside is a unitptr to self (assuming that something is actually inside self, otherwise self.inside would evaluate to null). Some fields may not be changed by DIL programs directly but must be modified indirectly using certain procedure calls in DIL. Others may not be changed at all. All are readable for DIL programs.

    The extraptr structure is used for several things. The primary is extra descriptions for units, and quest data. Keywords in the 'names' field and the actual description/data in the 'descr' field.

    In the following (RW) means the value may be assigned new values by DIL, while (RO) means the the value only can be read. A (RO) value might be possible to change through built-in functions/procedures <hr> <b>The extraptr has the following fields:</b><a name ="extra">

      extraptr:
         'names'        :stringlist (RW)
            names is a list of strings of names, that the extra description matches on.
         'descr'        :string (RW)
            descr is the contents of the extra description.
         'next'         :extraptr (RO)
            next is the next extra description in a list.
         'vals'        :intlist (RW)
            vals is a list of integer values attached to this extra.
    
    		 
    

    <hr> The unitptr is the key structure in the MUD, containing any kind of the following subtypes:

      object      : a normal object, a sword, a vail, etc.
      room        : a room, location or the like.
      pc          : a playing character.
      npc         : a non playing character (mobile, monster, etc)
    

    <hr> <b>The unitptr has the following fields:</b><a name ="unit">

      unitptr:
         'names'        :stringlist (RW)
            A list of names that matches the unit.
         'name'         :string (RW)
            The first name in the namelist in 'names'
         'outside_descr' :string (RW)
            The description of the unit from the 'outside'. f.inst.
            the description of a boat, seen from the outside.
         'inside_descr' :string (RW)
            The description of the unit from the 'inside'. f.inst.
            the description of a boat, seen from the inside.
         'next'         :unitptr (RO)
            The next unit in the local list of units. For instance, the
            units in the inventory of a PC, is linked with this field.
         'title'        :string (RW)
            The title of the unit.
         'extra'        :extraptr (RW)
            Extra descriptions of the unit (identify, look at, read etc.).
         'outside'      :unitptr (RO)
            The outside of the unit hierarchy (carried by, contained by).
            For instance, the contents of a bag have their 'outside'
            field pointing to the bag.
         'inside'       :unitptr (RO)
            The inside of the unit hierarchy (carry, contains).
            For instance the first unit in a PC's inventory is referenced
            by the 'inside' field.
         'key'       :string (RO)
            The key that will open this unitptr
            For instance "big_key@blackzon"
    

    by the 'inside' field.

         'gnext'        :unitptr (RO)
            Next unit in the global list of units.
         'gprevious'    :unitptr (RO)
            Previous unit in the global list of units.
         'hasfunc'      :integer (RO)
            Returns TRUE if unit has special functions attached to it.
         'max_hp'       :integer (RO/RW)
            The maximum hitpoints of unit, RO for players, RW for mobiles.
         'max_mana'       :integer (RO)
            The maximum mana of the character (player or mobile).
         'max_endurance'  :integer (RO)
            The maximum endurance of the character (player or mobile).
         'lifespan'       :integer (RW)
            The lifespan of a character, write permission only on root access.
         'hp'           :integer (RW)
            The current hitpoints of unit. For objects, this can render
            it 'broken' by being set low. If an unit has -1 hitpoints
            its considered unbreakable.
         'manipulate'   :integer (RW)
            Bits that specify how unit can be handled, see MANIPULATE_*
            flags in values.h and/or vme.h
         'flags'        :integer (RW)
            Bits that specify different properties of a unit, see
            UNIT_FL_* in values.h and/or vme.h
         'baseweight'   :integer (RO)
            The empty weight of the unit. This can be set with the
            procedure 'setweight()'
         'weight'       :integer (RO)
            The current weight of the unit (and its contents).
         'capacity'     :integer (RW)
            The amount of weight the unit can contain.
         'height'       :integer (RW)
            The height of a PC/NPC, the length of a rope, the size of weapons,
            armours, and shields.
         'alignment'    :integer (RW)
            The alignment of the unit. [1000..-1000],
            1000 is good, 0 is neutral, -1000 is evil.
         'openflags'    :integer (RW)
            Bits thats specify how a unit may be opened, locked, etc,
            see EX_* in values.
         'light'        :integer (RO)
            How much light is inside the unit.
         'bright'       :integer (RO)
            How much the unit lights up. This can be set with the
            procedure 'setbright()'
         'illum'        :integer (RO)
            How much light units inside a transparent unit create
         'minv'         :integer (RW)
            The 'wizard invisibility' level.
         'spells'[]     :integer (RO)
            The defence/skill of the different spell spheres/spells
            The index should be one of the SPL_* in values.h and/or vme.h
         'zoneidx'      :string (RO)
            The unique database name (in the zone) for this unit.
         'nameidx'      :string (RO)
            The unique database zone name for this unit.
         'idx'      :integer (RO)
            The unique database index (in the zone) for this unit.
            This provides a smart alternative to check for zoneidx
            and nameidx. Thus if (u1.idx == u2.idx) then
            (u1.nameidx == u2.nameidx) and (u1.zoneidx == u2.zoneidx).
            Be warned, this value change between each reboot, so do not
            count on it for purposes of saving.
         'zone'         :string (RO)
            The name of the zone the unit is in.
         'type'         :integer (RO)
            The type of the unit, see UNIT_ST_* in values.h and/or vme.h
         'loadcount'    :integer (RO)
            Returns the number of units loaded in the game
            of this definition (zoneidx,nameidx / idx)
    

    <b>if the type is UNIT_ST_OBJ</b><a name ="uobj">

         'objecttype'   :integer (RW)
            The type of an object, see ITEM_* in values.h and/or vme.h for types.
         'value'[]      :integer (RW)
            Values for an object. The meaning of the values differ
            from object type to object type. Index should be [0..4].
            These values are used differently for each object type.
         'objectflags'  :integer (RW)
            Bits specifying special properties for an object. Some
            combinations may not be logical, see OBJ_* in values.h and/or vme.h
         'cost'         :integer (RW)
            The basic cost of an object. (old gold value)
         'rent'         :integer (RW)
            The basic cost of renting an object. Mostly used on very
            special objects. (old gold value)
         'equip'        :integer (RO)
            The position in equipment. This is used by units in a PC/NPC's
            inventory to tell if they are equipped by that PC/NPC.
            use the 'addequip()' and 'unequip()' procedures.
    

    <b>if the type is UNIT_ST_ROOM</b><a name ="uroom">

         Note: the descr fields of exits are available as standard extra
            keywords, ie. 'north' ,'east',...,'down'.
            Example:
              ex := 'north' in self.extra;
    
         'exit_names'[]  :stringlist (RW)
            The names matching the exit name 'open grate' The index should
            be one of NORTH EAST SOUTH WEST UP DOWN in values.h and/or vme.h
            Example:
              sl := self.exit_names[SOUTH];
              act("The $2t slides open as you press the button.",
                   A_ALWAYS, activator, sl.[0], null, TO_CHAR);
         'exit_info'[]  :integer (RW)
            Bits specifying the conditions of the exits, see EX_* in
            values.h and/or vme.h The index should be one of NORTH EAST SOUTH WEST
            UP DOWN in values.h and/or vme.h
         'exit_to'[]    :unitptr (RO)
            The unit, the direction exits to. The index should
            be one of NORTH EAST SOUTH WEST UP DOWN in values.h and/or vme.h
            You may not change the directions through DIL programs.
         'roomflags'    :integer (RW)
            Bits specifying properties of the room, see ROOM_FL_* in
            values.h and/or vme.h
         'movement'     :integer (RW)
            The type of movement in the room, see SECT_* in values.h and/or vme.h
    

    <b>if the type is UNIT_ST_PC or UNIT_ST_NPC </b><a name ="upcnpc">

         'speed'        :integer (RO)
            The current default combat-speed (as seen by wstat)
         'fighting'     :unitptr (RO)
            The unit the PC/NPC is fighting.
         'master'       :unitptr (RO)
            The unit the PC/NPC is following.
         'follower'     :unitptr (RO)
            The first follower of a PC/NPC. There is currently no way
            of finding other followers, except using a foreach loop in
            the local environment.
         'exp'          :integer (RO)
            The number of experience points for PC, or experience
            quality of monster. The exp can be set by the function
            'experience()'
         'charflags'     :integer (RW)
            Bits specifying by spells affects and other PC/NPC affects,
            and many other things, see CHAR_* in values.h and/or vme.h
         'lastroom'     :unitptr (RO)
            The room the player just left.
         'mana'         :integer (RW)
            The amount of mana a PC/CHAR has left.
         'dex_red'      :integer (RO)
            The amount of DEX reduction the PC/NPC suffers due to
            encumbrance or otherwise.
         'endurance'    :integer (RW)
            The amount of endurance a PC/NPC has left.
         'attack_type'  :integer (RW)
            The non-weapon attack type of a PC/NPC.
         'race'         :integer (RW)
            The race of a PC/NPC, see RACE_* in values.h and/or vme.h
         'sex'          :integer (RW)
            The sex of a PC/NPC, see SEX_* in values.h and/or vme.h
         'level'        :integer (RO)
            The level of a PC/NPC.
         'position'     :integer (RW)
            The position of a PC/NPC, see POSITION_* in values.h and/or vme.h
            affected by the 'position_update()' procedure
         'abilities'[]  :integer (RO)
            The abilities of a PC/NPC. Index should be ABIL_* in values.h and/or vme.h
         'weapons'[]    :integer (RO)
            The weapon skills of a PC/NPC. Index should be WPN_* in values.h and/or vme.h
    

    <b>if the type is UNIT_ST_NPC </b><a name ="unpc">

         'defaultpos'   :integer (RW)
            The default position of an NPC, see POSITION_* in values.h and/or vme.h
    

    'natural_armour' :integer (RW) The natural armour of the NPC when naked.

         'npcflags'     :integer (RW)
            Some small options for NPC's see NPC_* in values.h and/or vme.h
    

    'switched' :unitptr (RW) Character that is switched into this NPC.

    			   
    

    <b>if the type is UNIT_ST_PC</b><a name ="upc">

         'birth'         :integer (RO)
            The time a PC was created.
    

    'editing' :integer (RO) Is the PC editing? TRUE for yes FALSE for no.

         'hometown'      :integer (RO)
            The hometown of a PC.
         'pcflags'       :integer (RW)
            The setup of player options. See PC_* in values.h and/or vme.h
         'playtime'      :integer (RO)
            The time a PC has played.
         'skill_points'   :integer (RW)
            The amount of unused skill points the PC has.
         'ability_points' :integer (RW)
            The amount of unused ability points the PC has.
    

    'exptol' :integer (RW)

            The amount of experience player needs to level
         'skills'[]     :integer (RO)
            The skills of a PC. Index should be SKI_* in values.h and/or vme.h
         'guild'        :string (RW)
            The guild the PC belongs to.
         'prompt'        :string (RW)
            The players prompt string..
         'crimes'       :integer (RW)
            The number of crimes the PC has.
         'full'         :integer (RW)
            How hungry the PC is.
         'thirst'       :integer (RW)
            How thirsty the PC is.
         'drunk'        :integer (RW)
            How drunk the PC is.
         'quests'       :extraptr (RW)
            The quests a PC is finishing/has finished.
         'info'         :extraptr (RW)
            The info structure of a PC.
         'acc_balance'  : integer (RO)
            If the game is in accounting mode, then this returns the balance
            of the player, what would be shown on balance in wstat <player> acc.
         'acc_total'  : integer (RO)
            If the game is in accounting mode, then this returns the total
            credit of the player, what would be shown on total in wstat
            &ltplayer&gt acc.
    

    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%">
    <a name="built_func">

    <h3>Built-In Functions:</h3>
    
        The following are definitions and documentation for the
      built-in functions in DIL. The definitions are not
      definitions 'as such', but serve to distinguish arguments
      in the documentation below.
    
    

    <hr><a name="bfasctime"> string asctime(i : integer)

      i : the time to convert in seconds (<a href = "#bvrealtime">realtime</a> variable)
    
      Returns: The seconds converted into an ascii format date of the following
               form  "Mon Nov 18 18:49:08 1996"
    
      Example:
         log(asctime(realtime));
    

    </PRE

    <H2><A NAME="bfstrcmp"> </H2>

    <P><B>Function:</B> <CODE>integer strcmp( s1:string, s2:string) ;</CODE> <DL> <DT><B>s1</B><DD><P>first string <DT><B>s2</B><DD><P>second string <DT><B>returns</B><DD><P> <DL> <DT><B>-1</B><DD><P>if s1 < s2 <DT><B>0</B><DD><P>if s1 = s2 <DT><B>1</B><DD><P>if s1 > s2 </DL> </DL> <P>This allows you to compare strings with case sensitivity in place. If you don't care about the case of the string use the normal '==' '>', '<', '<=', '>=', symbols. <P><B>example:</B> <BLOCKQUOTE><CODE> <HR> <PRE>


    if (strcmp("I Care about Capitals",s2)==0))

           {
           sendtext ("You care I can see.&n",self);
           quit;
           }
           
           
    

    <A NAME="bfstrncmp">

    Function: integer strcmp( s1:string, s2:string l :integer) ;

    s1

    first string

    s2

    second string

    l

    amount of significant digits to compare

    returns

    -1

    if s1 < s2

    0

    if s1 = s2

    1

    if s1 > s2

    This allows you to compare strings with case sensitivity in place and it allows you to choose how much of the strings are compared.

    example:


     
    
    if (strcmp("Mark Carper",s2,4)==0))
            {
            sendtext ("Hi Mark how is it going?&n",self);
                    quit;
            }
            
            
    


    <hr><a name="bftextformat">
    string textformat(s : string)
       s : The text string to format. The string is formatted according to
           the escape format codes as defined in one of the other documents.
    
       Returns: The formatted string which will automatically adapt to each
                individual player's settings.
    
       Example:
          ts := note.extra.descr;
          rs := textformat(ts);
    
    

    <hr><a name="bfsplind"> integer spellindex(s : string)

      s  : The abbreviated or full spell name
    
      Returns: -1 if no such spell, otherwise it returns the spell index
               for that spell.
    
      Example:
         s := "cu li wo"; /* cure light wounds */
         i := spellindex(s);
    

    <hr><a name="bfsplinf"> string spellinfo(idx : integer, i1 : integer, i2 : integer, i3 : integer,

                    i4 : integer, i5 : integer, i6 : integer, i7 : integer, )
    
       idx : The spell index (SPL_XXX). You might want to use spellindex
             to find this value.
    
       Returns:
         The full name of the spell, or the empty string if no such spell.
    
       All the integer parameters are set to the following values:
         i1  : Spell realm (MAG / DIC)
         i2  : Spell sphere (SPL_XXX)
         i3  : Mana usage
         i4  : 0 if a non-offensive spell, non-zero otherwise
         i5  : Resistance required (SPLCST_XXX)
         i6  : Mediums (MEDIA_XXX)
         i7  : Targets (FIND_UNIT_XXX & TAR_XXX)
    
     Example:
       s := "cu li wo"; /* cure light wounds */
       i := spellindex(s);
       s := spellinfo(i, i1, i2, i3, i4, i5, i6, i7);
       /* s & i1 - i7 now set */
    

    <A NAME="bpbeginedit"></a>

    Function: beginedit ( u : unitptr);

    u

    the PC unit doing the editing

    return

    When done editing it returns SFB_EDIT and activator is set to PC

    The 'BEGINEDIT' function sets a PC into editing mode. while in edit mode the PC field 'editing is set to true. Once the PC is done editing a 'SFB_EDIT' message is sent to the unit editing to continue on with the DIL. If for some reason the PC needs to break out of the editor before it is done editing then the Dil needs to call the 'killedit' function <A HREF="#sect-beginedit">interrupt editing before done</A>

    example:


    
    dilbegin edextra ();
    var
            temp:string;
    code
    {
            beginedit (self);
            wait(SFB_EDIT,self==activator) ;
            temp:=textformat(argument);
            addextra (self.extra,"general",temp);
            quit;
    }
    dilend
    

    The previous DIL is an example of how you could make a command to set the general extra which is the characters description when you do 'look player'


    <a name="bfcancarry">

    integer can_carry(ch : unitptr, u : unitptr, n : integer)

      ch : The character to check
      u  : The unit to check if he can carry.
      n  : How many copies of that unit.
    
      Returns: 0 if 'ch' can carry 'n' times 'u'.
               1 if 'n' items are too many (his hands are full)
               2 if 'n' times 'u' are too heavy
    
      Example:
    
         i := can_carry(activator, item, 1);
    
         if (i == 1)
           exec("say Your hands are full!", self);
         else if (i == 2)
           exec("say You cant carry that much weight.", self);
         else
           exec("give "+item.name+" to "+activator.name, self);
    

    <hr><a name="bffits"> string fits( char : unitptr, obj : unitptr, pos : integer );

      char: Character which we want to test if obj can be fitted upon
      obj:  The object we want to see if fits char.
      pos:  -1 or WEAR_XXX
      Returns: Empty string if ok, or a textual description of the size problem.
    
      Fits tests if "obj" can be worn by "char" in position "pos". If
      pos is -1, then fits automatically figures out the default worn
      position for "obj".
    
      Example:
    
         s := fits(self, obj, -1);
         if (s != "")
           exec("say Don't buy it, its "+s, self);
    

    <H2><A NAME="bfreplace"> </H2>

    <P><B>Function:</B> <CODE>string replace( t :string, n : string, o : string);</CODE> <DL> <DT><B>t</B><DD><P>the target string you want to replace <DT><B>n</B><DD><P>what you want to replace the target with <DT><B>o</B><DD><P>the original string <DT><B>return</B><DD><P>the string with the old string replaced by the new string </DL> <P>This function replaces all occurences of a string in another string with a new string. <P><B>Example:</B> <P><CODE>"Jafar %t% %l%" := replace(%n%,pc.name,"%n% %t% %l%");</CODE> <CODE>"Jafar the human %l%" := replace(%t%,pc.title,"Jafar %t% %l%");</CODE> <CODE>"Jafar the human 1" := replace(%l%,itoa(pc.vlevel),"Jafar the human %l%");</CODE>

    <H2><A NAME="bfrestore"></A> </H2>

    <P><B>Function:</B> <CODE>unitptr restore( filename : string , u : unitptr );</CODE> <DL> <DT><B>filename</B><DD><P>The name of the Unit file <DT><B>u</B><DD><P>The Unit you want to restore into or null if none <DT><B>Return</B><DD><P>if 'u' null returns a pointer to the Unit loaded, if 'u' not null returns null and loads Units from the specified file into the unit 'u' </DL> <P>restore loads a copy of a unit or units which were previously saved with the 'store' command. Just as with "load", the unit is put inside the unit which executes the restore command unless the 'u' argument is not null. If the 'u' argument is an unitptr like room, object, npc, or pc the items restored will be placed inside the 'u' Unit.. <P><B>Note</B>, It is only possible to restore items as long as the main-database contains a reference for the unit 'name@zone'. Use 'Store' and 'Restore' sparingly, remember that items saved in player's inventories are automatically saved in this instance. <P>The 'store' and 'restore' are perfect for operations such as mud mailing objects from player to player, storage devices for players that will keep inventory through a reboot. Even the ability to save a players inventory while they fight in an arena and restore it to them undamaged when finished. Finally it could be used to save a donation room through reboots since it can be used on a room to store the contents of a room any NPC or objects in the room would be saved through reboot. <P><B>Disk access is always slow</B>. If you use 'Restore' on a continuous basis always attempt to keep file sizes to a minimum for quick loading. Otherwise you might cause serious delays on the server. If the Dil that uses Restore saves at certain times try to make it so the saves are spread out over as large amounts of time as possible.

    <P><B>Example 1:</B> <BLOCKQUOTE><CODE> <HR> <PRE>

    dilbegin chest_load (); var

           waist:unitptr;/*to hold the null returned in this example*/
           chest:unitptr;/*pointer to the storage chest*/
    

    code { chest:=load ("chest@myzone");/*get the container*/ if (chest==null)

           {
           log ("Error");/*log an error*/
           quit;
           }
    

    waist:=restore("chest."+self.zoneidx,chest); /* restore given filename into chest waist can be ignored in this dil since it is not used.

    • /

    link (chest, self);/*link chest into room*/ quit;/*dil load routine done destroy self.*/ } dilend


    Example 2:


    
    dilbegin chest_load ();
    var
            chest:unitptr;/*item to be loaded*/
    code
    {
    chest:=restore("chest."+self.zoneidx,null);/*restore into chest*/
    if (chest== null)/*see if something was restored*/
            chest:=load("donate_chest@"+self.zoneidx);
            /*load a new one if there is nothing restored*/
    
    link (chest, self);/*link item into room*/
    quit;/*destroy the load dil.*/
    }
    dilend
    

    Note: Example 1 is to be used if 'storall' was used not storing a container. Example 2 is for items stored with 'store' with the container saved as well.

    See Also <A HREF="#bpstore">Store a Unit to a Unit file</A> and <A HREF="#bfdelunit">Delete a Unit file</A>.

    <hr><a name="bfmelee">
    integer meleeattack ( ch : unitptr, vict : unitptr,
                         bonus : integer, wtype : integer )
       ch    : The character which should make an additional attack.
       vict  : The victim of the attack.
       bonus : Any penalty or bonus added to the attack.
       wtype : The weapon type of the attack, if a valid type then that is
               used for the attack purpose, otherwise the default weapon/hand
               attack is used.
    
       result: 'ch' performs a melee attack (using whatever weapon is wielded
               or his bare hands) against 'vict'. Returns the amount of damage
               given (-1 is failed).
    
       If wtype is within a valid weapon range (WPN_XXX) any weapon will
       be bypassed, and the value will be used as the attacktype. Good
       for things like "meleeattack(ch, vict, bonus, WPN_CIRCLE_KICK)"
       if you want person to be able to perform an extra attack even
       though wielding a weapon or something. Note that this will require
       BOTH a weapon type WPN_CIRCLE_KICK and a skill "kick" in order for
       it to work.
    
    

    <P> <H2><A NAME="bpmeleedamage"> </H2>

    <P><B>Function: </B> <CODE>meleedamage ( c : unitptr, v : unitptr, b : integer, wt : integer );</CODE> <DL> <DT><B>c</B><DD><P>the character that should make an additional attack <DT><B>v</B><DD><P>the character being attacked <DT><B>b</B><DD><P>any penalty or bonus added to the attack. <DT><B>wt</B><DD><P>the weapon type of the attack, if a valid type then that

                       is used for the attack purpose, otherwise the default
    

    weapon/hand attack is used. <DT><B>returns</B><DD><P>The amount of damage done or -1 for failed </DL> <P>ch' performs an attack (using whatever weapon is wielded or his bare hands) against 'vict'. <P>If wtype is within a valid weapon range (WPN_XXX) any weapon will be bypassed, and the value will be used as the attacktype. Good for things like "meleeattack (ch, vict, bonus, WPN_CIRCLE_KICK)" If you want person to be able to perform an extra attack even though wielding a weapon or something. Note that this will require BOTH a weapon type WPN_CIRCLE_KICK and a skill "kick" in order for it to work. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR> <PRE> dilbegin kick(arg : string); external

      provoked_attack (victim : unitptr, ch : unitptr);
    

    var

      bonus : integer;
      targ  : unitptr;
    

    code {

      if ((self.type == UNIT_ST_PC) and (self.weapons[WPN_KICK] <= 0))
      {
         act("You must practice first.", A_ALWAYS, self, null, null, TO_CHAR);
         quit;
      }
    
      if (arg == "")
      {
         if (self.fighting)
         {
            targ := self.fighting;
            goto kick;
         }
    
         act("Kick who?", A_SOMEONE, self, null, null, TO_CHAR);
         quit;
      }
    
      targ := findunit(self, arg, FIND_UNIT_SURRO, null);
    
      if ((targ == null) or not visible(self, targ))
      {
         act("That person is not here!", A_SOMEONE, self, null, null, TO_CHAR);
         quit;
      }
    
      if (not (targ.type & (UNIT_ST_PC | UNIT_ST_NPC)))
      {
         act("You can't kick that, silly!", A_SOMEONE, self, null, null,
             TO_CHAR);
         quit;
      }
    
      if (targ == self)
      {
         act("You kick yourself.", A_HIDEINV, self, null, null,
             TO_CHAR);
         act("$1n kicks $1mself.", A_HIDEINV, self, null, null,
             TO_ROOM);
         quit;
      }
    
      if ((targ.type==UNIT_ST_PC) and
      (self.type==UNIT_ST_PC))
     {
    

    if (not(isset (self.pcflags, PC_PK_RELAXED)))

     {
     act ("You are not allowed to do this unless you sign the book of blood.",
     A_ALWAYS,self,null,null,TO_CHAR);
     quit;
     }
    

    if (not(isset (targ.pcflags, PC_PK_RELAXED)))

     {
     act ("You are not allowed to do this unless $2e signs the book of blood.",
     A_ALWAYS,self,targ,null,TO_CHAR);
     quit;
     }
     }
    


      :kick:
      /* Penalty for wielding a weapon while kicking! */
      if (equipment(self, WEAR_WIELD))
        bonus := -25;
      else
        bonus := +25;
      if (self.endurance < 2)
        act("You are too exhausted to attempt that.", A_ALWAYS, self, null,
            null, TO_CHAR);
      else self.endurance := self.endurance - 2;
      provoked_attack (targ, self);
      bonus := meleeattack(self, targ, (bonus+self.level), WPN_KICK);
      quit;
    

    } dilend

    <HR> </CODE></BLOCKQUOTE>


    <P> <H2><A NAME="bfmid"> </H2>

    <P><B>Function:</B> <CODE>string mid ( o : string, s : integer, e : integer );</CODE> <DL> <DT><B>o</B><DD><P>the original string to be parsed <DT><B>s</B><DD><P>The starting point of the string to be parsed out <DT><B>e</B><DD><P>the ending point of the string to be parsed out <DT><B>return</B><DD><P>the portion of the string defined by the 's' and 'e' values </DL> <P>This function parses the string passed to it and returns the portion of the string

    defined by the start value and the end value that is also passed to the function.
    

    <P><B>Example:</B> <CODE>"rock" := mid ("sprocket",3,6);</CODE>

    <hr><a name="bfmonstr"> string moneystring(amt : integer, verbose : integer)

      amt    : The amount of money
      verbose: True if an expanded string (copper pieces) or false
               if abbreviated money types (cp).
      result : The moneystring for the given currency.
    

    <hr><a name="bfeq"> unitptr equipment ( u : unitptr , i : integer )

      u : The character to search.
      i : What equipment to find, any of the WEAR_XXX macros.
      result: Returns the unit on 'u' which is equipped on position 'i'.
              See WEAR_* in values.h and/or vme.h
    

    <H2><A NAME="bftolower"> </h2>


    <P><B>Function:</B> <CODE>string tolower ( s : string );</CODE> <P> <DL> <DT><B>s</B><DD><P>String to lower case <DT><B>return</B><DD><P>the string passed in lower cased </DL> <P>This function returns a copy of the string passed in but with out capitals.

    <P><B>Example:</B> <CODE>"hello!" :=  tolower("HELLO!");</CODE>
    

    <P> <H2><A NAME="bftoupper">

    </h2>
    

    <P><B>Function:</B> <CODE>string toupper ( s : string );</CODE> <DL> <DT><B>s</B><DD><P>String to lower case <DT><B>return</B><DD><P>the string passed in lower cased </DL> <P>This function returns a copy of the string passed in with all characters changed to be capitalized. <P><B>Example:</B> <CODE>"HELLO!" := toupper ("hello!");</CODE>

    <hr><a name="bfvis"> integer visible(u1 : unitptr, u2 : unitptr)

      u1: The character who is looking at u2
      u2: The unit which the character u1 is trying to see.
      return: TRUE if u1 can see u2, FALSE otherwise.
      Example: if (visible(self, victim)) ...
    

    <hr><a name="bfop"> integer opponent(u1 : unitptr, u2 : unitptr)

      u1, u2: Two characters
      return: TRUE if u1 is in combat with u2, FALSE otherwise.
      Example: if (opponent(self, victim)) ...
    
      When in a combat, you are usually only melee-attacking one opponent,
      although you may have many other opponents. This function lets you
      check if you are directly / indirectly an opponent to another unit.
    

    <hr><a name="bfpurse"> integer purse(u : unitptr, coinage : integer)

      u : The unit to check
      coinage: The money type (e.g. gold, silver), one of IRON_PIECE, etc.
      Returns: The number of such units found.
      Example: if (purse(self, PLATINUM_PIECE) > 10)
                 exec("say I am loaded with platinum!", self);
    

    <hr><a name="bfatoi"> integer atoi ( s : string )

      s : A string with a number.
      return: The number in the string.
      Example: i := atoi("42");
      
      
    

    <H2><A NAME="bfcheckpassword"> </H2>

    <P><B>Function:</B> <CODE>integer check_password( u : unitptr, s : string ) ;</CODE> <DL> <DT><B>u</B><DD><P>the unit that you want to check the password of <DT><B>s</B><DD><P>the password you are using to check <DT><B>Return</B><DD><P>Returns an integer TRUE if pcname is the units password FALSE if not </DL> <P>This function checks the string against the units password and returns TRUE if they match. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR>

    if (not check_password(pc,arg))

           {
           sendtext (arg+" is not "+pc.name"'s password.",self);
                   quit;
           }
           
           
    

    <HR> </CODE></BLOCKQUOTE>

    <hr><a name="bfcomm"> integer command ( cmd : string or integer )

      cmd : A string of the full typed command, e.g. "push" or "say".
            Alternatively you can specify one of the macros defined in
            values.h and/or vme.h, e.g. CMD_SAY
    return: Whether the command specified by the activator is the one of
            the argument.
    

    It is noteworthy, that unlike simple compares like this;

    if ("spook" in cmdstr) { ... ... } or if (cmdstr == "spook") { ... ... }

    where the first will activate even if the cmdstr is "nospook", and the second only if cmdstr equals the word "spook" to the letter, the following construct will activate as long as the contents of cmdstr doesn't conflict with cmd;

    if (command("spook")) { ... ... }

    ie, it will receive the same kind of treatment as a 'regular' command. That means that you provide ease of use to the user (allowing shorthand notation), while securing that you're doing what the user wants. <a name="bfcommand373"><STRONG>CAVEAT</STRONG> Builder: If you use a string argument as cmd, be sure that there are no white-space in it, ie, that the argument does only consist of letters.

    Example:

       command("spook");
    
       is a valid string, while this construct;
    
       command("spook him");
    
       is NOT valid. The reason of that is that cmdstr only contains the
       FIRST word of the input from the player, and thus the latter
       construct could never evaluate to true. This should be evident
       taking the above information into account, as "spook him" could
       never equal "spook" (which would indeed be the text in cmdstr
       if the player entered the string "spook him".)
    

    <p>

    <H2><A NAME="bfdelstr">

    </H2>

    <P><B>Function:</B> <CODE>integer delstr( filename : string ) ;</CODE> <DL> <DT><B>filename</B><DD><P>The name of the String file to be deleted <DT><B>Return</B><DD><P>Returns an integer TRUE if deleted FALSE if not </DL> <P>The delstr is used to delete files that are used with the 'loadstr' and 'savestr' functions. The delstr function will only delete files that each individual Zone has access to which is set up in the Zonelist file in the VME etc directory. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR>

    dilbegin news|del ("arg : string /*filename to be deleted); var

           ret:integer;/*to hold the return value if deleted or not*/
    

    code { ret:= delstr("news.txt"); if (!ret)

           {
           log ("File not deleted.");
           quit;
           }
    

    sendtext ("News file deleted[&]n",self); quit;/*dil delete routine done } dilend


    See Also <A HREF="#bfloadstr">Load String file</A> and <A HREF="#bfsavestr">Save String file</A>

    <H2><A NAME="bfdelunit">
    </H2>
    
    <P><B>Function:</B>  <CODE>integer delunit( filename : string ) ;</CODE>
    <DL>
    <DT><B>filename</B><DD><P>The name of the Unit file to be deleted.
    <DT><B>Return</B><DD><P>Returns an integer TRUE if deleted FALSE if not delunit
    is used to delete files that are used with the 'Restore' and 'store' functions.
    <P><B>Example:</B>
    <BLOCKQUOTE><CODE>
    <HR>
    <PRE>
    
    dilbegin chest_del ("arg : string /*filename to be deleted*/);
    var
            ret:integer;/*to hold the return value if deleted or not*/
    code
    {
    ret:= delstr("chest.file");
    if (!ret)
            {
            log ("File not deleted.");
            quit;
            }
    
    sendtext("Chest file deleted[&]n",self);
    quit;/*dil delete routine done
    }
    dilend
    

    See Also <A HREF="#bfrestore">Restore a Unit from a Unit file</A> and <A HREF="#bpstore">Store Units to a Unit file</A>.

    <hr><a name="bfdd">
    integer dildestroy( s : string, u : unitptr )
       s : name of dil template to delete.
       u : unit to remove program from.
       return: Whether a program using a template with same name as in 's'
               attached to unit 'u' was deleted.
    

    <hr><a name="bfdf"> integer dilfind( s : string, u : unitptr )

      s : name of dil template to find.
      u : unit to find program in.
      return: Whether a program using a template with same name as in 's'
              attached to unit 'u' was found.
    

    <hr><a name="bfitoa"> string itoa ( i : integer )

      i : A number.
      return: A string with the number.
      Example: s := itoa(42);
    

    <hr><a name="bfisaff"> integer isaff ( u : unitptr , i : integer )

      u : A unit to be examined.
      i : An id of an affect, see ID_* in values.h and/or vme.h
      return: TRUE, if unit 'u' is affected by affect id 'i'
      
    

    <P>

    <A NAME="bfislight">

    Function: integer islight ( u : unitptr )

    u

    Unit that you are checking

    returns

    TRUE' if item is a light, 'FALSE' if it is notway to small', 'to small', 'way to large', 'to large', or null if fits

    Simply checks the item to see if it is a light.

    <A NAME="bfisplayer">

    Function: integer isplayer( pcname : string ) ;

    pcname

    the name of the player being checked

    Return

    Returns an integer TRUE if pcname is a player FALSE if not

    This function is used to find out if a string you pass to it is a player or not. This can be used and is used to find out if a player is truly a player that an Administrator is deleting with out having that player on line.

    Example:


    
    if (not isplayer(arg))
            {
            sendtext (arg+" is not a character.&n",self);
            quit;
            }
            
            
    


    <hr><a name="bfisset">
    integer isset ( i : integer , bit : integer )
       i : An integer to examine.
       bit : A set of bits to match.
       return: TRUE, if bits in 'bit' is set in 'i'.
       Example: if (isset(self.manipulate, MANIPULATE_TAKE)) ...
    
    <hr><a name="bfpaychk">
    integer paycheck( u1 : unitptr, u2:unitptr)
       u1 : unit to check against
       u2 : player to check access for
       return: TRUE if the player u2 has pay access to the location
    	in which the unit u1 is located. FALSE if the player does not
    	have access. Using non-players as u2 will return TRUE. The
    	function checks if the player has pay-access (if needed) to
    	the zone in which u1 is located.
    
    <hr><a name="bffindu">
    unitptr findunit ( u : unitptr , s : string , i : integer , l : unitptr )
         u : The unit the local environment is relative to.
         s : A string with name of the unit to find.
         i : The environment, where to look for it, see FIND_UNIT_*
             in values.h and/or vme.h.
         l : An optional list of units to search.
     return: If the unit is found, the function returns that unit.
              Returns null if nothing found.
    
      The first argument is typically the char that's looking for something,
      i.e. if Mary needs a spoon to stir the pot, she'll be the first argument.
    
      The second argument is what you're looking for, represented by a string.
      In the above mentioned example, that'd be "spoon".
    
      For the second or third argument, you have a choice, as you'll only need to
      use one of them, and let the other be 0 or null.  For instance, if you have
      a pointer to Mary's kitchen utensil pot, you can use the line:
    
         findunit(mary, "spoon", 0, pot);
    
      Or you can just let her look around for it with:
    
         findunit(mary, "spoon", FIND_UNIT_INVEN or FIND_UNIT_SURRO, null);
    
      You can use all the FIND_UNIT_ values defined in values.h and/or vme.h, if you
      want to look for something for example within the zone (FIND_UNIT_ZONE), the
      entire world (FIND_UNIT_WORLD) (you rarely need to do that, it's mainly for
      tell etc.), or just the inventory or equipment of the char in question
      (FIND_UNIT_INVEN and FIND_UNIT_EQUIP).  Finally, as in the example above,
      you can look in the room of the char (FIND_UNIT_SURRO).
    
      Using FIND_UNIT_PAY or FIND_UNIT_NOPAY in this function will be ignored.
      <P>
    The flags for findunit, intuitively:
    </P>
    <P>
    FIND_UNIT_EQUIP:<BR>
      The objects you will see with `equipment'
      Assumes first argument to findunit is a char.
    </P>
    <P>
    FIND_UNIT_INVEN:<BR>
      The objects you will see with `inventory' or `look in bag'
    </P>
    <P>
    FIND_UNIT_SURRO:<BR>
      The objects you can see, and get with `get',
      or the characters you can `poke' :-)
    </P>
    <P>
    FIND_UNIT_ZONE:
      As FIND_UNIT_WORLD, only more local.
    </P>
    <P>
    FIND_UNIT_WORLD:
      Any object in the entire world.  Does NOT start looking close to the 
      object of findunit's first argument, but rather somewhat randomly.
    </P>
    <P>
    On top of these, the following (new) values are defined:
    </P>
    <P>
    FIND_UNIT_IN_ME:<BR>
      Anything inside of the object of the first argument.
    </P>
    <P>
    FIND_UNIT_HERE:<BR>
      Anything `here', i.e. in object or around it (same as IN_ME + SURRO)
    </P>
    <P>
    FIND_UNIT_GLOBAL:
      ANYTHING, starting close to object and working out.
    </P>
    
    
    
    <PRE>
    <hr><a name="bffindru">
    unitptr findrndunit( u : unitptr, sv : integer, uf : integer)
       Returns: A pointer to a random unit, or null
       u  : The unit pointer which the search is relative to.
       sv : The search-location, a value (not bit vector) of FIND_UNIT_XXX
       uf : Bit vector. The unit flags which can match of UNIT_ST_XXX
    
       Example: u := findrndunit(self, FIND_UNIT_ZONE, UNIT_ST_PC|UNIT_ST_NPC);
    
       This routine returns a random unit. Notice how the 'uf' lets you
       specify exactly what unit types to look for. The 'sv' is not a
       bit vector, although FIND_UNIT_XXX is usually used as such. If
       you need to search multiple environments, then call the routine
       once for each.
    
       Using FIND_UNIT_PAY or FIND_UNIT_NOPAY in this function will
       pick a random player which in addition to being in the search
       environment also is registered as valid payer (or not). Asking
       for a room would yield a random room registered to be accessible
       for paying players only (or not). Asking for objects would
       return no unit (null).
    

    <A NAME="bffilesize"></A>

    Function: integer filesize ( filename :string);

    file

    The file name you want to check

    return

    a file size in bites 0 if no file

    This function does exactly what it says it does it checks a files size.

    Example DIL:


    
    dilbegin notebook ();
    code
    {
            ns := filesize (self.name+"notebook");
            if ( ns >500000)
            {
                    sendtext ("Your notebook is full.&n",self);
                    quit;
            }
            else if ( ns > 250000)
            {
                    sendtext ("Your notebook is more than half full.&n",self);
                    quit;
            }
            else if (ns >125000)
            {
                    sendtext ("Your Notebook is only 1/4 full.&n",self);
                    quit;
            }
            else if (ns >0)
            {
                    sendtext ("Your notebook is less than 1/4 full.&n",self);
                    quit;
            }
            else
            {
                    sendtext ("You don't have anything in your Notebook.&n",self);
                    quit;
            }
    
    }
    dilend
    

    The previous DIL example shows how you could use the 'filesize' instruction to check the size of a player stored notebook.

    
    <hr><a name="bffindr">
    unitptr findroom ( s : string )
       s : Symbolic name of room.
       return: A pointer to the room, or null
       Example: findroom("inn@udgaard")
    
    <hr><a name="bffinds">
    unitptr findsymbolic ( s : string )
       s : Symbolic name of the NPC or Object to find.
       return: A pointer to an instance of the unit, or null.
       Example: findsymbolic("bread@midgaard")
    
       This routine supplements findroom and findunit. It comes in handy,if it is
       important to get a correct reference to a NPC in the world.  If for example,
       Mary needs to send a message to John the Lumberjack,  then she should NOT
       use the findunit() since it may locate a different John - even a player!
       If she instead locates him using findsymbolic("john@haon_dor") she will be
       certain that it is in fact her husband, and not the player John Dow from
       Norway.  It will NOT locate rooms, for the only reason that findroom is a
       lot more efficient.
    
    
    unitptr findsymbolic ( u : unitptr, s : string, i : integer )
       u : Search is relative to this unit.
       s : Symbolic name of the NPC or Object to find.
       i : FIND_UNIT_XXX bit vector of places to search.
       return: A pointer to an instance of the unit, or null.
       Example: findsymbolic(self, "bread@midgaard", FIND_UNIT_INVEN)
    
       This routine supplements findroom, findunit and findsymbolic(#).  It comes in
       handy, if it is important to get a correct reference to a unit somewhere
       relative to 'u'.  If for example, Mary needs to check if she has her own
       cooking pot, then she should NOT use the findunit since it may locate a
       different pot, not belonging to Haon-Dor but to some other zone.  If she
       instead locates it using findsymbolic(self, "pot@haon_dor", FIND_UNIT_IN_ME)
       she would be certain that it is in fact her own cooking pot that she is
       carrying around, and not some other pot from a Joe Blow's zone.
       
    
       
    

    <P> <H2><A NAME="bpflog">

    </H2>

    <P><B>Function:</B> <CODE>flog (filename : string, s : string, wa : string );</CODE> <DL> <DT><B>filename</B><DD><P>The Filename of the file to appear in the log directory. <DT><B>s</B><DD><P>The string to be logged. <DT><B>wa</B><DD><P>Write or Append </DL> <P>The 'flog' function allows you to split up your logs in the log directory so that you don't end up with everything in the main vme.log. <P><B>Note:</B>

     The append/write argument must be in lower case and can only be a 'w' or a 'a'
     surrounded by '"'.  If the argument is a 'w' it will over write any log file
     by that name.  If the argument is 'a' it will append to the file by that name.
    

    Example:


    
    dilbegin zonelog (s:string);
    code
    {
    flog (self.zonidx+".log",s,"a");
    return;
    }
    dilend
    

    The previous DIL function will work in any zone to log to a file with that zones name each zone could use it to keep zone logs separate.

    <hr><a name="bfgword">
    string getword ( var s : string )
       s : A string with zero or more words separated by space.
       return: The first word of the string.
    
       NB: The argument string has the returned word removed.
    
    <hr><a name="bfgwords">
    stringlist getwords ( var s : string )
           s : A string with zero or more words separated by space.
       return: A stringlist where each string was a word in 's'.
    
    <hr><a name="bfghead">
    unitptr ghead ( )
    
    return the first unit in the global list which will be the last
    char to have logged on.
    
    <hr><a name="bfsplit">
    stringlist split ( var s : string, var t : string)
           s : A string with zero or more words separated by var t.
       return: A stringlist where each string was a word in 's'
               separated by string 't'.
    		   
    		   You can use '&x' to split a string by line.  This is very usefull when reading in files with 'loadstr'.
    <P>
    <H2><A NAME="bfleft"></A>
    </H2>
    
    <P><B>Function:</B>  <CODE>string left ( o : string, l : integer );</CODE>
    <DL>
    <DT><B>o</B><DD><P>the original string to be parsed
    <DT><B>l</B><DD><P>The amount of characters to parse out
    <DT><B>return</B><DD><P>the left portion of the string with length l
    </DL>
    <P>This function parses the string passed to it and returns the number
    of characters defined in its second argument.
    
    <P><B>Example:</B>  <CODE>"short" := left ("shorten me",5);</CODE>
    <P><B>Example:</B>
    <BLOCKQUOTE><CODE>
    <HR>
    <PRE>
    
    dilbegin aware describe (arg:string);
    var
            side:string;
            oneword:stringlist;
            location:string;
            ln:integer;
            args:stringlist;
            temp:string;
            i:integer;
            x:extraptr;
    code
    {
            if (self.type!=UNIT_ST_PC)
                    quit;
            if (self.position <POSITION_SLEEPING)
            {
            act ("Recover first and then you can describe your body parts.",
            A_ALWAYS,self,null,null,TO_CHAR);
                    quit;
            }
    
            args:=getwords(arg);
            ln:=length(args);
            if ((ln<1) or (ln>2))
            {
            sendtext ("No such location to describe.",self);
            quit;
            }
            else if (ln>1)
            goto two_word;
    
            :one_word:
    
            if ((arg==left("help",length(arg))) or
                    (arg==""))
                    goto hlp_dscr;
    
            oneword := {"arms","butt","ears","eyes","face","feet",
    		            "general","hair","hands","head","legs",
    					"mouth","neck","nose","nostrils","teeth",
    					"toes","tongue"};
    
            i := 0;
            ln := length(args.[0]);
            temp:="ERROR";
            while (i<18)
            {
                    if (args.[0]==left(oneword.[i],ln))
                    {
                            temp := oneword.[i];
                            break;
                    }
                    i := i+1;
            }
    
            if (temp=="ERROR")
            {
                    sendtext ("No such location to describe.",self);
                    quit;
            }
    
            goto describe;
    
            :two_word:
    
            oneword := {"arm","leg","foot","hand","eye","ear"};
            temp := "ERROR";
            ln := length(args.[0]);
            if (args.[0] == left("left",ln))
                    side:="left";
            else if (args.[0] == left("right",ln))
                    side:="right";
            else
            {
                    sendtext ("No such location to describe.",self);
                    quit;
            }
    
            i := 0;
            while (i<6)
            {
                    if (args.[1]==left(oneword.[i],ln))
                    {
                            temp := oneword.[i];
                            break;
                    }
                    i := i+1;
            }
    
            if (temp=="ERROR")
            {
                    sendtext ("No such location to describe.",self);
                    quit;
            }
    
            temp := side+" "+temp;
    
            :describe:
            if (temp=="General")
                    location := "";
            else
                    location := temp;
    
            x := location in self.extra;
            if (x!=null)
              if (location=="")
    sendtext("your Current description for your body is:  &n"+x.descr+"&n",self);
            else
    sendtext("your Current description for your "+location+"is:  &n"+x.descr+"&n",self);
            if (location=="")
    sendtext ("Enter a text you would like others to see when they look at your body.&n",self);
            else
    sendtext ("Enter a text you would like others to see when they look at your "+location+".&n",self);
    
            beginedit (self);
            wait(SFB_EDIT,self==activator) ;
            temp := textformat(argument);
            oneword:={""};
            subextra(self.extra,location);
            addstring (oneword, location);
            addextra (self.extra,oneword,temp);
            sendtext ("Description added.&n",self);
            quit;
    
            :hlp_dscr:
    
            sendtext ("&nCorrect usage of 'describe':&n&n",self);
            sendtext ("describe <position>&n&n",self);
            sendtext("<position> being one of the following:&n&n",self);
            sendtext( "arms        butt        ears        eyes&n"+
                      "face        feet        General     hair&n"+
                      "hands       head        left arm    left leg&n"+
                      "left foot   left hand   left eye    left ear&n"+
                      "legs        mouth       neck        nose&n"+
                      "nostrils    right arm   right leg   right foot&n"+
                      "right hand  right eye   right ear   teeth&n"+
                      "toes        tongue&n&n",self);
            sendtext ("Example:  &n&n",self);
            sendtext ("describe left leg&n",self);
            quit;
    }
    dilend
    

    <hr><a name="bflen">
    integer length ( a : string or stringlist )
           a : a string or stringlist to examine.
       return: The length of the string in characters, or the number
               of strings in a list.
    
    <hr><a name="bfload">
    
    unitptr load ( s : string )
       s : Symbolic name of unit.
       return: A pointer to the unit, or null
       Example: load("garlic@midgaard")
       The loaded unit is automatically placed inside the object
       which loaded it.  Use for example the link command to move
       it into other units.
    
    <H2><A NAME="bfloadstr"></A>
    
    </H2>
    

    <P><B>Function:</B> <CODE>integer loadstr( filename : string , buff : string );</CODE> <DL> <DT><B>filename</B><DD><P>The name of the string file to be loaded <DT><B>buff</B><DD><P>The string that you wish to read the file contents into <DT><B>Return</B><DD><P><CODE>FILE_LOADED, FILE_NOT_FOUND, FILE_OUT_OF_MEMORY,or FILE_TO_LARGE</CODE> </DL> <P>Loadstr is used to load strings from disk that were saved either by savestr or any text editor. The 'loadstr' is perfect for operations such as on-line edited newspaper, a lottery where the tickets are sold to players, creating smarter NPC's that can remember through reboots who they are hunting, Dil based teachers, message boards, mail system, news command., zone or room based help, competition boards, and much much more. <P><B>Disk access is always slow</B>. attempt to keep file sizes to a minimum for quick loading. Otherwise you might cause serious delays on the server. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR>

    dilbegin news_load (); var

           ret:integer;/*to hold the return value if loaded or not*/
           buff:string;/*to hold the loaded string*/
    

    code { ret:= loadstr("news.txt",buff); if (!ret)

           {
           log ("File not read.");
           quit;
           }
    

    sendtext(buff+"[&]n",self); quit;/*dil load routine done destroy self.*/ } dilend

    <HR> </CODE></BLOCKQUOTE> <P><B>See Also</B> <CODE> <A HREF="#bfdelstr">Delete a String file</A> and <A HREF="#bfsavestr">Save String file</A></CODE>

    <hr><a name="bforoll"> integer openroll( dice : integer , end : integer )

      dice : The size of the dice being rolled.
      end  : The margin for the open-ended roll.
      return: A random integer in approximately +/- 2^31 in worst case.
      Example: i := openroll(100,5); The "100" roll continues on values
               96 - 100 and on values 1 - 5.
    

    <hr><a name="bfpathto"> integer pathto( from : unitptr, to : unitptr )

      from   : The unit which the path is taken from
      to     : The unit which the path is taken to
      returns: DIR_XXX from values.h and/or vme.h.
      Example: i := pathto(self, findroom("inn@midgaard"));
    

    <hr><a name="bppagestring"> pathto(buff : string, u : unitptr )

      buff   : The string that is to be paged to the player.
    

    u : The unitptr the buff is to be paged for.

      returns: nothing
    

    example: pagestring (buff,self); would format the buff string to the player so the buff text doesn't scroll off the screen until after the player presses enter.


    <P> <H2><A NAME="bfright">

    </H2>

    <P><B>Function:</B> <CODE>string right ( o : string, r : integer );</CODE> <DL> <DT><B>o</B><DD><P>the original string to be parsed <DT><B>r</B><DD><P>The amount of characters to parse out <DT><B>return</B><DD><P>the right portion of the string with length r </DL> <P>This function parses the string passed to it and returns the number of characters from the right defined in its second argument. <P><B>Example:</B> <CODE>"Easy" := right ("This is Easy",4);</CODE>

    <hr><a name="bfrnd"> integer rnd ( i1 : integer , i2 : integer )

      i1 : Start of range.
      i2 : End of range.
      return: A random integer in an interval from 'i1' to 'i2'.
      Example: i := rnd(1,10);
    

    <IMG SRC="../images/backgr/waveline.gif" BORDER="0" HEIGHT="18" WIDTH="100%"><br><a name="biproc"> <h3>Built-In Procedures:</h3>

       DIL features some built-in procedures that allows you increased control over
     in-game data structures and event handling. Once such procedure (used above)is
     'exec()'. The inline procedures are used as any other procedure by typing its
     name, followed by a list of argument expression enclosed in parentheses. The
     return types of the expressions used for built-in procedure calls are checked
     by the compiler.
    
       DIL also lets you call templates defined in the current or other zones.  The
     naming of templates follows the normal naming convention for zone, using the
     'name@zone' as a symbolic name for a procedure.  Before being able to use
     external procedures, you must define their name and type in a separate
     'external' section in the template.  The declaration in the 'external' section
     should match the original declaration of the referenced program. You can define
     the number and type of arguments the template take, by listing them inside the
     declaration parenthesis (as well as in the original declaration of that template)
     (see example below)
    

    <b>Example:</b>

     <i>dilbegin bar(s:string);
     code
     {
       exec("say "+s,self);
       return;
     }
     dilend</i>
    
     <i>dilbegin foo();
     external
       someproc@hades1();
       bar(s:string);
     code
     {
       someproc@hades1();
       bar("Hello "+activator.name);
       pause;
     }
     dilend</i>
    
       When the procedure is called, the argument expressions are calculated, and
      passed to the template.  Built-in procedures, their arguments and function
      are listed later.
    
       The following are definitions and documentation for the built-in procedures
      in DIL. The definitions are not definitions 'as such', but serve to distinguish
      arguments in the documentation below.
    

    <hr><a name="bpfol"> follow( f : unitptr, m : unitptr )

      f : The character to follow
      m : The character to be followed
    
      Unconditionally makes 'f' follow 'm', even if 'f' is mortally
      wounded, sleeping, fighting or whatever.
      
    
      <P>
    

    <H2><A NAME="bpflog"></a> </H2>

    <P><B>Function:</B> <CODE>flog (filename : string, s : string, wa : string );</CODE> <DL> <DT><B>filename</B><DD><P>The Filename of the file to appear in the log directory. <DT><B>s</B><DD><P>The string to be logged. <DT><B>wa</B><DD><P>Write or Append </DL> <P>The 'flog' function allows you to split up your logs in the log directory so that you don't end up with everything in the main vme.log. <P><B>Note:</B>The append/write argument must be in lower case and can only be a 'w' or a 'a' surrounded by '"'. If the argument is a 'w' it will over write any log file by that name. If the argument is 'a' it will append to the file by that name. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR> <PRE>

    dilbegin zonelog (s:string); code { flog (self.zonidx+".log",s,"a"); return; } dilend


    The previous DIL function will work in any zone to log to a file with that zones name each zone could use it to keep zone logs separate.

    
    <hr><a name="bplogcrime">
    logcrime( c : unitptr, v : unitptr, t : integer )
       c : The criminal (main suspect)
       v : The victim
       t : The crime type (CRIME_XXX)
    
          Registers a crime committed against 'v' by 'c'. Use the
        CRIME_XXX values from values.h and/or vme.h as the 't' argument.
        The logcrime routine automatically registers group members
        of the criminal, etc. In stuff like steal, remember to make
        the criminal visible if he fails his attempts.
    

    <hr><a name="bpacc_mod"> acc_modify( u : unitptr, i : integer )

      u : A player
      i : An amount in 1/100s, for example 100 would equal $1.00, and
          -100 would equal -$1.00.
    
         Access only allowed with 'root' access and all transactions are
       registered in the specially encrypted account log file. Use with
       great caution, and always test thoroughly before using.
       Use without prior permission may cause deletion of god / zone.
    

    <P>

    <H2><A NAME="#bfstrdir"></A> </H2>

    <P><B>Function:</B> <CODE>stringlist strdir( match : string ) ;</CODE> <DL> <DT><B>match</B><DD><P>The wild card file you want to match or '*' for all. <DT><B>return</B><DD><P>a Stringlist with all the filenames that match the

    'match' argument.
    

    </DL> <P>The 'match' argument uses the same wild cards as the Linux 'ls' command so the following will work. <DL> <DT><B>&ast;</B><DD><P>Match any character or group of characters <DT><B>&quest;</B><DD><P>Match one of any character <DT><B>[...]</B><DD><P>Match one of a set of characters </DL> <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR>

    "corpse*" matches: corpse.10938 corpse.whistler corpseofwhistler ... "corpse?" matches corpse1 corpses corpse5 ... "[abc]*" matches ability about cost back ... "[a-z]*" about zoo man father ... "start[nm]end" matches startnend startmend

    <HR> </CODE></BLOCKQUOTE> <P><B>Example DIL:</B> <BLOCKQUOTE><CODE> <HR>

    dilbegin wanted (); var

           wantedlist:stringlist;
           templist:stringlist;
           i:integer;
           ln:integer;
    

    code {

           wantedlist := strdir ("dead*");
    
                   i := 0;
                   ln := length (wantedlist);
    
           while (i < ln )
                   {
                   templist := split (wantedlist.[i],".");
                   sendtext (templist.[1]+" wanted dead!&n",self);
                   i:=i+1;
                   }
    

    quit; } dilend

    <HR> </CODE></BLOCKQUOTE> <P>The previous DIL would be an example of a command to check the wanted dead players on the VME if you saved the files with the first word being 'dead' and separated it with a '.' and the players name. For example if 'whistler' was wanted dead the file name would be 'dead.whistler'

    <P> <H2><A NAME="setpassword"> </H2>

    <P><B>Function:</B> <CODE>set_password( u : unitptr, s : string ) ;</CODE> <DL> <DT><B>u</B><DD><P>the unit that you want to set the password of <DT><B>s</B><DD><P>the password you are using to set </DL> <P>This function sets a unit password it only works on Players characters of corse. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR>


    dilbegin aware do_password (arg:string); var

           prmt:string;
    firstpwd:string;
    
    i:integer;
    tlist:stringlist;
    

    code {

    if(self.type != UNIT_ST_PC) quit; arg:=""; prmt:=self.prompt; self.prompt:="Enter new password: "; wait (SFB_CMD,self==activator); block; tlist:=getwords (excmdstr); if (length(tlist)>1){ sendtext ("Password must be only one word. Try again.&n",self); self.prompt:=prmt; quit; } if (length(excmdstr)<5){

           sendtext ("Password to short. Password must be 5 characters or longer.\
    

    Try again.&n",self);

           self.prompt:=prmt;
           quit;
           }
    

    if (length(excmdstr)>16){

           sendtext ("Password to long. Try again.&n",self);
           self.prompt:=prmt;
           quit;
           }
    
           firstpwd:=excmdstr;
           self.prompt:="Enter password again:  ";
    

    wait (SFB_CMD,self==activator); block; if (excmdstr!=firstpwd){ sendtext ("Passwords do not match try again.&n",self); self.prompt:=prmt; quit; } set_password(self,excmdstr); sendtext("Changed your Password to '"+excmdstr+"' Please write it down!&n",self); self.prompt:=prmt;

    quit; } dilend


    <HR> </CODE></BLOCKQUOTE>


    <p> <H2><A NAME="bpstore"></A> </H2>

    <P><B>Function:</B> <CODE>store( u : unitptr , filename : string , container : integer );</CODE> <DL> <DT><B>u</B><DD><P>The Unit that has the contents to be stored or is to be stored <DT><B>filename</B><DD><P>The name of the file you want to store the Units to <DT><B>container</B><DD><P>Do you want to save the container 'TRUE' for yes, 'False' for no </DL>

    <P>Store saves a copy of a unit or units. If the container value is 'TRUE' everything inside including the container itself will be saved. If the container argument is 'FALSE' only the contents of the object will be saved. You will want to use the 'TRUE' value when saving something like a Clan chest that has items inside to store and has extras on the chest that you also wish to keep. The 'FALSE' value for container would be good for temporary storage of PC inventory or for storing room contents.

    <P>The 'store' and 'restore' are perfect for operations such as mud mailing objects from player to player, storage devices for players that will keep inventory through a reboot. Even the ability to save a players inventory while they fight in an arena and restore it to them undamaged when finished. Finally it could be used to save a donation room through reboots since it can be used on a room to store the contents of a room any NPC or objects in the room would be saved through reboot.

    <P><B>Disk access is always slow</B>. If you use store on a continues basis, it is essential that you do so ONLY if it is needed and even then, only at amply spaced intervals. Otherwise you might cause serious delays on the server. Remember that items saved in player's inventories are automatically saved in their instance. <P><B>Example 1:</B> <BLOCKQUOTE><CODE> <HR>

    dilbegin save_contents (); code {

    start:

    wait (SFB_CMD,command ("store")); wait for the store command*/ block; store("chest."+self.zoneidx,self,FALSE);/*store everything inside self.*/ goto start; } dilend


    Example 2:

    
    dilbegin save_container_n_contents ();
    code
    {
    
    :start:
    wait (SFB_CMD,command ("store")); wait for the store command*/
    block;
    store("chest."+self.zoneidx,self,TRUE);/*store everything inside self and self.*/
    goto start;
    }
    dilend
    

    <HR> </CODE></BLOCKQUOTE> <P><B>See Also</B> <A HREF="#bfrestore">Store a Unit to a Unit file</A> and <A HREF="#bfdelunit">Delete a Unit file</A>.

    <hr><a name="bpp_u"> position_update ( u : unitptr ) u : A pointer to a player or a monster. The character will be updated and perhaps killed, incapacitated, mortally wounded, revived, etc. depending on current hitpoints. Useful when tampering with the 'hp' field. Example:

    pc.hp := pc.hp - 100; position_update(pc);

    <H2><A NAME="bpsend_done">

    </H2>

    <P><B>Function:</B></CODE> send_done( c : string, a :unitptr, m : unitptr, t :unitptr, p : integer, arg : string, o : unitptr);</CODE> <DL> <DT><B>c</B><DD><P>the command string that is sending the message <DT><B>a</B><DD><P>the unitptr (activator) that activated the message <DT><B>m</B><DD><P>the unitptr (medium) that the Dil is acting through <DT><B>t</B><DD><P>the unitptr (target) the Dil is acting on <DT><B>p</B><DD><P>the power of the message <DT><B>arg</B><DD><P>the argument sent with the message <DT><B>o</B><DD><P>the unitptr (other) you also want the message to go to </DL> <P> This sends the 'SFB_DONE' message to any dils that are waiting for it in the surrounding area and to the other pointer if not null. The following is just one example you can find many more in <B>commands.zon</B>

    <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR> <PRE>

    dilbegin do_read (arg:string); var brdname:string; i:integer; u:unitptr; x:extraptr; ln:integer; temp:string; templist:stringlist; buff:string; f_name:string; act_str:string; code { i:=atoi (arg); if (i<0) { exec ("look "+arg,self); goto read_quit; }

    if (itoa (i)!=arg) { exec ("look "+arg,self); goto read_quit; }

    u:=self.outside.inside; while (u!=null) { if ((u.type==UNIT_ST_OBJ) and (u.objecttype==ITEM_BOARD)) break; u:=u.next; }

    if (u==null) { act ("You do not see that here.",A_ALWAYS,self,null,null,TO_CHAR); quit; }

    if (u.extra.["$BOARD_L_RES"].descr!="") { act_str:=u.extra.["$BOARD_L_RES"].descr(self,u); if (act_str!="") { act(act_str, A_ALWAYS,self,null,null,TO_CHAR); quit; } }

    brdname:=u.names.[length (u.names)-1]; i:=loadstr (brdname+".idx",temp); if (i<=0) { act ("But the board is empty!", A_ALWAYS,self,null,null,TO_CHAR); goto read_quit; }

    templist:=split(temp,"&x"); ln:=length (templist); x:="$BOARD_MAX" in self.extra; if ((atoi(arg)>atoi(x.descr)) or (atoi(arg)>ln)) { act("That message exists only within the boundaries of your mind.", A_ALWAYS,self,null,null,TO_CHAR); goto read_quit; }

    i:=atoi(arg); temp:=templist.[i-1]; f_name:=getword(temp); i:=loadstr (brdname+"."+f_name,buff); if (i==0) { sendtext("You have to let the poster finish the post before reading it.",self); quit; } if (i<1) { log("05: Error when loading board info."); act ("This board is not working report to an Administrator", A_ALWAYS,self,null,null,TO_CHAR); quit; }

    templist:=split(f_name,"."); if (length(templist)<2) act ("Message "+arg+": "+temp, A_ALWAYS,self,null,null,TO_CHAR); else act ("Message "+arg+": Re: "+temp, A_ALWAYS,self,null,null,TO_CHAR);

    pagestring(buff,self);

    read_quit:

    send_done("read",self,null,u,0,arg,null); quit; } dilend

    <HR> </CODE></BLOCKQUOTE> <P> <H2><A NAME="bfsend_pre"></H2> <B>Function:</B></CODE>send_pre( c : string, a :unitptr, m : unitptr, t :unitptr, p : integer, arg : string, o : unitptr);</CODE> <DL> <DT><B>c</B><DD><P>the command string that is sending the message <DT><B>a</B><DD><P>the unitptr (activator) that activated the message <DT><B>m</B><DD><P>the unitptr (medium) that the Dil is acting through <DT><B>t</B><DD><P>the unitptr (target) the Dil is acting on <DT><B>p</B><DD><P>the power of the message <DT><B>arg</B><DD><P>the argument sent with the message <DT><B>o</B><DD><P>the unitptr (other) you also want the message to go to </DL>

    <P> <P>New Function send_pre(...) takes same arguments as send_done but returns either SFR_SHARE or SFR_BLOCK. <P>If the command is blocked by another special or dil, then SFB_BLOCK will be returned, and you should quit your dil. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR>


    dilbegin cmdtst(arg : string); var i : integer; code { i:=send_pre("cmdtest",self,null,null,0,argument,null);

    if (i == SFR_BLOCK) quit;

    sendtext ("No one blocked me!&n",self); quit; } dilend


    dilbegin pretest(); code { :loop: wait(SFB_PRE, command("cmdtest")); block; act("hahahaha I blocked your cmdtest command", A_SOMEONE, activator, medium, null, TO_ALL); goto loop; } dilend

    <HR> </CODE></BLOCKQUOTE>


    <hr><a name="bpset"> set ( var i : integer , bit : integer ) i : Integer variable to alter. bit : Bits to set in integer variable. result: Sets bits in 'i'

    <hr><a name="bpunset"> unset ( var i : integer , bit : integer ) i : Integer variable to alter. bit : Bits to unset in integer variable. result: unset bits in 'i'.


    <H2><A NAME="bpaddcolor"> </H2>

    <P><B>Function: </B><CODE>addcolor (ch : unitptr, ks : string, cstr : string ) ;</CODE> <DL> <DT><B>ch</B><DD><P>character you are adding the color to <DT><B>ks</B><DD><P>key string for the color <DT><B>cstr</B><DD><P>color string </DL> <P>This function allows your Dils to create and add their own personal colors to a players color list. That way you can actually make an act in a color that the player chooses or you yourself choose. <P><B>Function: </B><CODE>addcolor(pc, "clan_who","&c+w&bn");</CODE> <P>

    <H2><A NAME="bpdelcolor"> </H2>

    <P><B>Function: </B><CODE>delcolor (ch : unitptr, ks : string) ;</CODE> <DL> <DT><B>ch</B><DD><P>character you are deleting the color from <DT><B>ks</B><DD><P>key string for the color </DL> <P>This function is used to delete any colors from a players personal color list. <P><B>Function: </B><CODE>delcolor(pc, "clan_who");</CODE> <P> <H2><A NAME="bfgetcolor"> </H2>

    <P><B>Function: </B><CODE> string getcolor (ch : unitptr, ks : string) ;</CODE> <DL> <DT><B>ch</B><DD><P>character you are deleting the color from <DT><B>ks</B><DD><P>key string for the color <DT><B>returns</B><DD><P>returns the color in a string </DL> <P>This function returns what color a player has for a key in the players list. <P><B>Function: </B><CODE>string := getcolor(pc, "clan_who");</CODE> <P> <H2><A NAME="bpchangecolor"></A> <A NAME="ss4.4">4.4 Changing a color</A> </H2>

    <P><B>Function: </B><CODE>changecolor (ch : unitptr, ks : string, cstr : string ) ;</CODE> <DL> <DT><B>ch</B><DD><P>character you are changing the color on <DT><B>ks</B><DD><P>key string for the color <DT><B>cstr</B><DD><P>color string </DL> <P>This will change a color in a players personal list. <P><B>Function: </B><CODE>changecolor(pc, "clan_who","&c+w&bn");</CODE> <P> <H2><A NAME="bpgamestate"> </H2>

    <P><B>Function: </B><CODE> gamestate( u : unitptr, gs : integer ); </CODE> <P>Change the gamestate of a unitptr, uses the GS_ defines from the <B>vme.h</B>. This is used on the log on menu of the VME 2.0 release. Which is shown here as an example but it can also be used in a command. When used it removes the char from playing so be aware that players could use this to hide if you run a player killing style mud. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR>

    dilbegin informer(); var tgt : unitptr; code { heartbeat := PULSE_SEC;

    tgt := ghead();

    while(tgt.type == UNIT_ST_PC) {

    if((isset(tgt.pcflags,PC_INFORM)) and (tgt != self)) { if(visible(tgt,self)) { if(self.outside == tgt.outside) sendtext(self.name+" has arrived.&n", tgt); else sendtext(self.name+" has entered the world.&n", tgt); } }

    tgt := tgt.gnext; }

    return; } dilend

    dilbegin aware on_connect(); external informer(); login_modify(tgt : unitptr);

    var wizlvl : integer; i:integer; err : integer; motd : string; welcome : string; goodbye : string; code { heartbeat := PULSE_SEC;

    if(dilfind("do_quit@commands",self)) i := dildestroy("do_quit@commands", self);

    err := loadstr("motd",motd);

    if(err > 0) { motd := textformat(motd); sendtext(motd+"&n&n", self);

    }

    err := loadstr("welcome",welcome); if(welcome) welcome := textformat(welcome);

    if (self.level < 200) {

    login_modify(self); dilcopy ("clan_delete@clans",self); dilcopy ("clan_clear@clans",self);


    if(err > 0) sendtext("&n"+welcome+"&n&n", self); informer(); exec("look", self); quit; } gamestate(self, GS_MENU);

    wiz_menu:

    sendtext("Welcome to Valhalla&n&n", self); sendtext("1) Enter Valhalla&n", self); sendtext("W) Change Wizinv level&n [&c+g"+itoa(self.minv)+"&[default]]&n",self); sendtext("0) Exit Valhalla&n&n", self); sendtext("Make your choice: ", self); wait(SFB_CMD, TRUE);

    if (command("1") ) { gamestate(self, GS_PLAY); if(err > 0) sendtext("&n"+welcome+"&n&n", self); informer(); exec("look", self); quit; } else if (command("0") ) { err := loadstr("goodbye",goodbye); if(err > 0) { goodbye := textformat(goodbye); sendtext(goodbye, self); } destroy(self); quit; } else if (command("w") ) { sendtext("Enter new WizInv Level: ", self); wait(SFB_CMD, TRUE); wizlvl := atoi(cmdstr); if (wizlvl > self.level) wizlvl := self.level; self.minv := wizlvl; } else { sendtext("Invalid Selection&n&n", self); goto wiz_menu; }

    } dilend

    <HR> </CODE></BLOCKQUOTE> <P>Look in <B>vme.h</B> for the possible values you can send to the menu function.


    <hr><a name="bpaddex"> addextra ( var e : extraptr, l : stringlist , s : string ) e : Extra description list to add element to. l : Stringlist for the .names field. s : String for the .descr field. result: Adds an extra description to a list of extra descriptions. <A name="bpaddex372"> <strong>CAVEAT</strong> builder: You cannot use an extraptr variable as the e argument, but you may continue to use the following form:

    ... ... addextra (self.quests, "Bozo's Quest"); ... ...

    <hr><a name="bpadds"> addstring ( var l : stringlist, s : string ) l : Stringlist to add string to. s : String to add. result : Adds a string 's' to a stringlist 'l'.

    <hr><a name="bpsubex"> subextra ( var e : extraptr, s : string ) e : Extra description list to remove element from. s : String matching .names field in element result: Removes first extra description from list with matching name. <a name="bpsubex372"> <emp>CAVEAT</EMP> builder: You cannot use an extraptr variable as the e argument, but you may continue to use the following form:

    ... ... subextra (self.quests, "Bozo's Quest"); ... ...

    <hr><a name="bpsubs"> substring ( var l : stringlist, s : string ) l : Stringlist to remove string from. s : String to remove result: Removes string 's' from stringlist 'l'.


    <P> <H2><A NAME="bpstopfighting"> </H2>

    <P><B>Function:</B> <CODE>stop_fighting( ch: unitptr, vict : unitptr ) ;</CODE> <DL> <DT><B>ch</B><DD><P>unitptr - person you are stoping the fighting for <DT><B>vict</B><DD><P>unitptr - person you are removing from the fighting or null for everyone </DL> <P>This function can be used to cancel combat in a room or with two people. The following example copied to a player will stop any fight the player is in. <P><B>Example:</B> <BLOCKQUOTE><CODE> <HR>

    dilbegin stop_combat(); code { stop_fighting(self,null); quit; } dilend

    <HR> </CODE></BLOCKQUOTE>


    <hr><a name="bpsubaff"> subaff ( u : unitptr, i : integer ) u : Unit remove affect from. i : Affect id to remove, see ID_* in values.h and/or vme.h result: Removes first affect at 'u' with matching id 'i'.

    <hr><a name="bpaddaff"> addaff ( u : unitptr, id : integer, tif_first : integer, tif_tick : integer, tif_last : integer, apf : integer, )XXX u : Unit to add affect to. id : Affect id to add, see ID_* in values.h and/or vme.h result: Adds affect 'id' at 'u' with first, tick, and last TIF_XXX's <P> <H2><A NAME="bpdest"></A> </H2>

    <P><B>Function:</B> <CODE>destroy ( u : unitptr );</CODE> <DL> <DT><B>u</B><DD><P>:Unit to remove from game </DL> <P>The destroy function works in two ways depending on the Unit being acted on. If the Unit being acted on is a PC the player is saved and ejected from the game. If the Unit being acted on is a NPC, or an Object. the purge function destroys the Unit. Currently destroy will not destroy rooms. This is different from the old destroy function in that it removes the player out of the game instead of leaving the player in the menu. <P><B>Example</B> <BLOCKQUOTE><CODE> <HR> <PRE>

    dilbegin purge_all_pc(); var u:unitptr/*Unit used to purge each player*/ n:unitptr;/*used to keep track of next player*/ code { u:=ghead();/*get first pc in game list*/ n:=u;


    while (n.type==UNIT_ST_PC)/*while unit is a pc*/ { n:=u.gnext; destroy(u); }

    quit;/*done whiping out the players*/ } dilend




    <a name="bpwalkto">

    walkto ( u : unitptr )

      u : Room to walk to.
      result: Makes unit (self) walk to room, taking a 'step' at each 'tick'.
    

    Example:

     walkto(findroom("inn@udgaard"));
    

    <a name="bplink">

    link ( u : unitptr, t : unitptr )

      u : Unit to link.
      t : Unit to link into.
      result: Link a unit into another unit hierarchy. (Automatically
              unequipps if equipped).
    


    <A NAME="bfweapon_name">

    Function: string weapon_name( i : integer ) ;

    i

    Weapon to get the name of ass defined in 'values.h' and 'weapons.def'

    returns

    The name of the weapon that corresponds with the integer value

    example:


    
    myweap:=weapon_name(5);
    

    <A NAME="bfweapon_info">

    Function: intlist weapon_info( i : integer ) ;

    i

    Weapon to get the info of ass defined in 'values.h' and 'weapons.def'

    returns

    Intlist containing 4 values:

    0

    Number of hands

    1

    weapon speed

    2

    weapon type

    3

    shield block value

    This function gives you access to the values in the weapons.def file. With this things like 'wear' equipment' and 'look' are much easier to write in Dil.

    Example


    
    dilcopy id_weap (arg:string);
    var
      i:integer;
      il:intlist;
    code
    {
    il:=weapon_info(atoi(arg));
    
    if (il!=null)
    {
    sendtext ("Number of hands:  "+itoa(il.[0])+"&n";
                 sendtext ("Speed:  " +itoa(il.[1])+"&n",self);
                             sendtext ("Type:  "+itoa(il.[0])+"&n",self);    
                             sendtext ("Shield value:  "+itoa(il.[0])+"&n",self);    
                             }
    else
    {
    sendtext ("No such weapon.&n",self);  
    }
    
    quit;
    }
    dilend                   
                             
    


    <A NAME="bfskill_name"></A> <A NAME="ss4.8">4.8 Getting a skills name</A>

    Function: string skill_name( i : integer ) ;

    i

    Skill to get the name of ass defined in 'values.h' and 'commands.def'

    returns

    The name of the skill that corresponds with the integer value

    example:


    
    myski:=skill_name(5);
    

    <A NAME="bpreboot"></A> <A NAME="ss4.9">4.9 Reboot the mud</A>

    Function: reboot ;

    This function works like a quit command. Anything after the reboot function in a Dil will not be executed the mud will reboot instantly. The zone must have root privileges in the zonelist in order to use this function.

    Simple reboot command


    
    dilbegin cmd_reboot (arg:string);
    code
    {
    sendtext ("Rebooting the mud.&n",self);
    reboot;
    }
    dilend
    

    <A NAME="bpkilledit">

    Function: killedit ;

    This function is used to kill the editor on a PC if it needs to stop editing before the PC is done editing. An example of when this is needed is when a player is killed while editing or is transfered away from a place where he was editing. You can let them finish but it may be wierd for a person to finish posting in one room while in another.

    Example


    
    dilbegin editextra (arg:string);
    code
    {
    interrupt (SFB_DEAD,self==activator,int_quit);
            beginedit (self);
            wait(SFB_EDIT,self==activator) ;
            temp := textformat(argument);
    addextra (self.outside.extra ,{"graphitee"},temp);
    quit;
    :int_quit:
    killedit;
    quit;
    }
    dilend
    


    <hr><a name="bpexp">
    experience ( i : integer, u : unitptr )
       i : A integer number of experience to gain or loose.
       u : The player to receive the experience.
       result: The integer amount of experience is added to the players
               total amount of experience (thus causing more or less
               experience). USE WITH CARE! SUGGEST THAT YOU ONLY USE
               INTEGER CONSTANTS AS THE EXPRESSION TO AVOID ERRORS.
    
    <hr><a name="bpact">
    
    <P>The purpose of act is to send a message to a number of players <B>present</b> in
    a room.  The room is defined as the room containing the afore mentioned
    character (provided he himself is in the room, i.e. not in a closed
    container.)</P>
    
    
    <hr>
    <h3>Syntax:</h3>
    <P>
    act(message, visibility, char, medium, victim, to_whom);
    <dl>
    	<dt>message
    		<dd> - is a string that will be shown to other mobiles when the act is executed.
    		To refer to the following arguments use the <A href="#formatters">formatters</a> listed below.
    	<dt>visibility
    		<dd> - is an integer that defines what happens if the mobile that is about to receive the
    		message can't see the activator.
    		<dl>
    			<dt><CODE>A_SOMEONE</CODE>
    		<dd>If the receiver cannot see char, replace any reference to char with
    	   <samp>someone</samp>.
    	  <dt><CODE>A_HIDEINV</CODE>
    	<dd>If the receiver cannot see char, don't send the message at all.	Use
    	    this when missing vision should eliminate the perception of the action
    		the message represent. One instance where it is used is in smile. You
    		would need a ridiculously sensitive ear to hear, let alone percept
    		that someone's smiling if you can't see them. Do not use it if
    		'sound' is inherent in the message.
    
    	<dt><CODE>A_ALWAYS</CODE>
    	<dd>Works exactly like <CODE>A_SOMEONE</CODE>, except that the receiver
    	    will see the message even when sleeping.
    		</dl>
    	<dt>char
    	<dd> - is a unitptr, and the most important argument in the act. If this
    	       is not valid the act will never show, leaving mobiles without
    		   the message.
    	<dt>medium
    		<dd> - is a unit pointer, an integer or a string. Use this at your
    		       leasure.
    	<dt>victim
    		<dd> - is a unit pointer, an integer or a string. Certain flags in
    		       the next argument rely on the validity of victim.
    	<dt>
    		<dd> - is an integer that defines who gets the message.
    		<dl>
    			<dt><CODE>TO_ROOM</CODE>
    				<dd>Sends the message to the entire room, excluding 'char'.
    			<dt><CODE>TO_VICT</CODE>
    				<dd>Sends to 'victim' only. 'victim' must be valid, naturally.
    			<dt><CODE>TO_NOTVICT</CODE>
    				<dd>Sends the message to the entire room, excluding 'char'
    				    and 'victim'.  Perfect for bystanders in a melee.
    			<dt><CODE>TO_CHAR</CODE>
    				<dd>Sends the message to 'char' and no one else.
    			<dt><CODE>TO_ALL</CODE>
    				<dd>Sends the message to everybody in the room.
    			<dt><CODE>TO_REST</CODE>
    				<dd>This is a bit different from the rest.  In sends the
    				     message to all other units in the local environment,
    					 excluding those inside 'char'.
    		</dl>
    </dl>
    </P>
    <HR>
    <P>
    <h3>
    <a name="formatters">Act Formatters</h3>
    
    Just as the description formatters, act has its own set of formatters that
    enable you to create generic messages that will be interpreted at run-time,
    lessening the load on you.
    
    The format string is a normal message, containing some special characters:<BR>
    <dl>
      <dt>'$$'
      <dd>will be sent to the receiver as a single `$'
      <dt>'$', followed by a number and an extra character.
      <dl><h4>The numbers:</h4>
          <dt>'1'
          <dd> means this formatter refers to the 'char' argument.
          <dt>'2'
          <dd>means this formatter refers to the 'medium' argument.
          <dt>'3'
          <dd> means this formatter refers to the 'victim' argument.
       </dl>
       <dl><h4>The characters</h4>
          <dt>'N'
          <dd> the formatter will be replaced with the name of the unit, or
    	       (depending on the visibility)
    		   'something' or 'someone'.
          <dt>'a' 
          <dd>'a' or 'an' depending on the name of the unit referred by the number.
          <dt>'e'
          <dd>'it', 'he' or 'she' depending on the gender of the unit referred
    	       by the number.
          <dt>'m'
          <dd>'it', 'him' or 'her' depending on the gender of the unit referred by
    	       the number.
          <dt>'n'
          <dd> the formatter will be replaced with the title of the unit, or
    	       (depending on the visibility) 'something' or 'someone'.
          <dt>'p'
          <dd>'fighting', 'standing', 'sleeping', etc., depending on the position
    	       of the unit referred by the number.
          <dt>'s'
          <dd>'its', 'his' or 'her' depending on the gender of the unit referred
    	       by the number.
          <dt>'t'
          <dd>the string in the argument referred by the number.
       </dl>
    
    
    <b>Example:</b>
    <i>
      act("You step over $2n.", A_SOMEONE, self, litter, null, TO_CHAR);
      act("$1n steps over $2n.", A_SOMEONE, self, litter, null, TO_REST);</i>
    
    
    <b>See Also:</b>
      <a href = "act.html">DIL Act() for Dummies</a>
    
    <hr><a name="bpexec">
    exec ( s : string , u : unitptr )
       s : Command and arguments to perform.
       u : Unit to perform command.
       result: Unit (PC/NPC) executes command. The argument is treated just as
               if a normal PC entered a command at the command prompt in the
               game. It is not directly possible to detect whether the command
               was a success or fail. For example, you might force a PC to
               "get key". If there is no 'key' available, the PC will get
               notified the normal way. Plenty of examples are given above.
    
    <hr><a name="bpwait">
    wait ( i : integer , dilexp )
       i : Message class to accept, see SFB_* in values.h and/or vme.h
       dilexp : Expression that has to be TRUE or not null to accept message.
       result: Waits for a command, matching the flagset, and satisfies the
               expression. When using the 'wait()' command, the first argument
               is an integer, that tells what classes of messages to wait for.
               Each message class is represented by a bit named as described in
               the chapter on messages.
    <b>Example:</b>
    
       wait (SFB_TICK|SFB_MSG, TRUE)
       /* Will accept a message, either from another DIL program or a
          timer message. As the second argument is always TRUE, any
          such message will reactivate the DIL program.
        */
    
    <b>Example:</b>
    
      wait (SFB_CMD, command("transmutate"))
      /* waits for an command entered named 'transmutate'.
         Activates the DIL program, that then can block the command, or
         let it pass (and then let the game produce the normal error
         message for unknown commands).
      */
      
      <P>
    <H2><A NAME="bfsavestr"></A>
    </H2>
    
    <P><B>Function:</B>  <CODE>integer savestr( filename : string , buff : string , wa :string);</CODE>
    <DL>
    <DT><B>filename</B><DD><P>The name of the String file to save the String to
    <DT><B>buff</B><DD><P>The String you wish to save into the file
    <DT><B>wa</B><DD><P>Write or append
    <DT><B>Return</B><DD><P><CODE>FILE_SAVED, FILE_NOT_SAVED, FILE_NOT_CREATED, or FILE_ILEGAL_OPP</CODE>
    </DL>
    <P>Savestr is used to save strings to disk to be loaded later by the 'load' function.
    The 'savestr' and 'Loadstr' is perfect for operations such as
    on-line edited newspaper, a lottery where the tickets are sold to players,
    creating smarter NPC's that can remember through reboots who they are hunting,
    Dil based teachers, message boards, mail system, news command., zone or
    room based help,  competition boards, and much much more.
    <P><B>Note:</B>The append/write argument must be in lower case and can only be a
    'w' or a 'a' surrounded by '"'.  If the argument is a 'w' it will over write
    any string file by that name.  If the argument is 'a' it will append to the
    file by that name.
    <P><B>Disk access is always slow</B>.
    If you use loadstr on a continuous basis always
    attempt to keep file sizes to a minimum for quick loading.  Otherwise you
    might cause serious delays on the server.
    <P><B>Example:</B>
    <BLOCKQUOTE><CODE>
    <HR>
    
    
    dilbegin news_save (arg:string  /*for saving*/);
    var
            ret:integer;/*to hold the return value if saved or not*/
    code
    {
    ret:= savestr("news.txt",arg,"w");
    if (!ret)
            {
            log ("File not wrote");
            quit;
            }
    
    sendtext("New news file wrote.[&]n",self);
    quit;/*dil save routine done destroy self.*/
    }
    dilend
    

    See Also <A HREF="#bfdelstr">Delete a String file</A> and <A HREF="#bfloadstr">Load a String file</A>

    <A NAME="bpremove"></A>

    Function: remove( sl : stringlist, i : integer ) ;

    sl

    the stringlist you are removing from

    i

    the index you want to remove

    This function allows you to remove a string from a stringlist with out leaving a blank spot in the stringlist.

    Example: remove (sl, i);

    <A NAME="bpresetlevel">

    Function: reset_level( u : unitptr ) ;

    u

    player your resetting

    This function simply resets a players level. Can be used in functions like reroll where you set the players back to the way he first logged on.

    Example: reset_level (u);

    See Also <A HREF="#bpresetvlevel">reset a players virtual level</A> and <A HREF="#bpresetrace">reset a players race information</A>

    <A NAME="bpresetvlevel">

    Function: reset_vlevel( u : unitptr ) ;

    u

    player your resetting

    This function simply resets a players virtual level. Can be used in functions like reroll where you set the players back to the way he first logged on.

    Example: reset_vlevel (u);

    See Also <A HREF="#bpresetlevel">reset a players level</A> and <A HREF="#bpresetrace">reset a players race information</A>

    <A NAME="bpresetrace">

    Function: reset_race( u : unitptr ) ;

    u

    player your resetting

    Reset a characters race, weight, height, age, lifespan, and costs for training. As if you first log on the character. Great for reroll along with 'reset_level' and 'reset_vlevel'.

    Example: reset_race (u);

    See Also <A HREF="#bpresetlevel">reset a players level</A> and <A HREF="#bpresetvlevel">reset a players virtual level</A>


    <a name="bpsec">

    secure ( u : unitptr , label )

      u : Unit to secure.
      label : Label to jump to, on removal.
      result: Secures a unitptr, so that the program will go to 'label'
              if unit leaves local environment. If this happens, during
              a call to another function/procedure, it will continue
              at that label when the function/procedure returns.
              If you perform some kind of call to a template, the removing
              of a unit from the local environment will not have affect.
              until the return from that function, as the program execution
              will continue at the designated label after a call. Should
              several secured units leave local environment, the last such
              event will determine the point of execution upon return.
    

    <A NAME=bfunitdir"></A>

    Function: stringlist unitdir( match : string ) ;

    match

    The wild card file you want to match or '*' for all.

    return

    a Stringlist with all the filenames that match the 'match' argument.

    The 'match' argument uses the same wild cards as the Linux 'ls' command so the following will work.

    &ast;

    Match any character or group of characters

    &quest;

    Match one of any character

    [...]

    Match one of a set of characters

    Example:


    
    "corpse*" matches:  corpse.10938 corpse.whistler corpseofwhistler ...
    "corpse?" matches corpse1 corpses corpse5 ...
    "[abc]*" matches ability about cost back ...
    "[a-z]*" about zoo man father ...
    "start[nm]end" matches startnend startmend
    

    Example DIL:


    
    dilbegin aware reload_corpse();
    var
            corpselist:stringlist;
            u:unitptr;
            ln:integer;
            i:integer;
            x:extraptr;
    code
    {
            corpselist:=unitdir("corpse*");
            ln:=length(corpselist);
            i:=0;
            while (i<ln)
            {
            u:=restore(corpselist.[i],null);
            x:=CORPSE_EXTRA in u.extra;
            if (u!=null)
                    if (x!=null)
                            link (u,findroom(x.descr));
                    else
                            link (u,findroom("temple@udgaard"));
            i:=i+1;
            }
    
    quit;
    }
    dilend
    

    The previous DIL example is the DIL used in restoring corpses to the game in case of a crash. For more information you can see how the death DIL'S work by reading through the file death.zon in the vme2.0/zone. directory.


    <a name="bpunsec">

    unsecure ( u : unitptr )

      u : Secured unit.
      result: Drop secure on a given unit.
    

    <a name="bpblock">

    block

      result: Blocks any command issued by a player or mobile. Blocking a
              command prevents the command from being parsed by the
              interpreter. This is ideal if you need to make a routine
              which intercepts a command, reacts on it in a special way,
              and does not need the standard way of reacting.
    

    <a name="bppri">

    priority

      result: Set until nopriority command. When set, no special routines
              "below" the current DIL program will be executed. This is used
              to make other special routines idle. See haon-dor.zon for an
              example.
    

    <a name="bpnopri">

    nopriority

      result: Cancels the priority procedure.
    

    <a name="bpaddeq">

    addequip ( u : unitptr , i : integer )

      u : Unit to equip.
      i : Where to equip unit.
      result: Equips unit, presumed to be in inventory PC/NPC at
              given position. See WEAR_* in values.h and/or vme.h
    

    <a name="bpuneq">

    unequip ( u : unitptr )

      u : Unit to unequip.
      result: Unequipes unit presumed to be in equipment of PC/NPC.
      
    

    <A NAME="bpdp">

    Function: delete_player( s : string ) ;

    s

    the player name you want to delete

    This function deletes a player but it doesn't check to see if it was deleted or if it even existed you will have to do that with 'isplayer'.

    Example:


    
    dilbegin aware do_delete (arg:string);
    var
            temp:string;
            err:integer;
    code
    {
    
    if(self.type != UNIT_ST_PC) quit;
    
    if (self.level>200)
            goto admin_delete;
    
    :char_delete:
            if (arg!="self forever")
                    {
                    sendtext ("To delete your char type:  'delete self forever'&n",self);
                    quit;
                    }
    
    err:=loadstr("delete.txt",temp);
    
    if (err<1)
            goto no_insure;
    
    sendtext (temp,self);
    
    sendtext ("If your sure you still want to delete your character, 'say delete me'&n",self);
    sendtext ("Doing anything else will abort the deletion.&n",self);
    
    wait (SFB_CMD, self==activator);
    if (command ("say"))
    
            if (argument=="delete me")
            if (self.extra.[CLAN_RANK]!=null)
                    exec ("cdefect",self);
                    delete_player(self.name);
    
    sendtext("Deletion aborted&n",self);
    
    quit;
    
            :no_insure:
                    if (self.extra.[CLAN_RANK]!=null)
                    exec ("cdefect",self);
                            delete_player(self.name);
    
    quit;
            :admin_delete:
            if (arg=="self forever")
                    goto char_delete;
    if (arg==""){
    sendtext("You must supply a characters name to delete one.&n",self);
    quit;
    }
    
    if (arg==self.name){
    sendtext ("To delete self you need to type 'delete self forever'&n",self);
    quit;
    }
    
    if (not isplayer(arg))
            {
            sendtext (arg+" is not a character.&n",self);
            quit;
            }
    dilcopy ("god_delete@clans("+arg+")",self);
    
            sendtext (arg+" has been deleted.&n",self);
    quit;
    }
    dilend
    
            
    

    <hr><a name="bpdc">
    dilcopy( s : string, u : unitptr )
       s : Name template to attach to unit.
       u : Unit to attach a dil program to.
       result: Attaches a DIL program to a unit 'u', which uses a template
               named by 's'.
    
    <hr><a name="bpsendt">
    sendtext( s : string, u : unitptr )
       s : text to send
       u : Unit to send the text to
       result: Sends the string 's' to 'u'. Useful only for nanny stuff,
               because no new line appended.
    
    <hr><a name="bpchngs">
    change_speed( u : unitptr, i : integer )
      u : the unit on which you wish to alter the current combat speed.
      i : the amount to add to the speed.
    
      Beware, this is not the 'speed' as in the speed field, rather this is
      the speed which is calculated during combat. It is used for spells like
      'stun' which effectively puts the character out of combat for one
      round. Such a spell would be implemented like:
    
       change_speed(u, 12)
    
      and would only cause any effect if 'u' was fighting already (if not,
      use setfighting).
    
    <hr><a name="bftranmon">
    integer transfermoney( f : unitptr, t : unitptr, amount : integer)
       f : The char the money is taken from
       t : The char the money is given to
       amount : How much money.
       Returns: TRUE is money was transferred, FALSE if could not afford.
    
       If 'f' is null and 't' isn't, then money is created and given to 't'.
       If 'f' isn't null but 't' is, then money is removed from 'f'.
    
    <hr><a name="bpsetfight">
    set_fighting( u : unitptr, t : unitptr )
       u : the unit on which attacks.
       t : the unit being attacked.
    
       This is used to set two characters fighting. If the attacker is
       fighting already, the target will simply be inserted into the
       opponent list and perhaps killed a little later.
    
    <hr><a name="bpsetweight">
    setweight( u : unitptr, i : integer )
       u : the unit on which you wish to alter the weight.
       i : the new weight
    
       This is needed on for example drink-containers. I.e. if you wish to
       remove or add some liquid, you must also adjust the weight of the
       container, or you will mess up things.
    
    <hr><a name="bpsetbright">
    setbright( u : unitptr, i : integer )
       u : the unit on which you want to change the brightness.
       i : the new brightness
    
       When you want to increase / decrease the amount of light shed by a
       unit, use this function. Units with "bright" light up rooms so that
       people can see.
    
    <hr><a name="bplog">
    log( s : string )
       s : Text to put in the log.
       result: Puts text in the log for debugging purposes.
    
    <hr><a name="bpsend">
    send ( s : string )
       s : Message to send.
       result: Send a message to all DIL programs in current local environment,
               matching the message class SFB_MSG. The message is not received
               by those DIL programs in the local environment that is not set up
               to wait for that message class.
    
    <hr><a name="bpsendto">
    sendto ( s : string , u : unitptr )
       s : Message to send.
       u : Unit to send it to.
       result: The message is passed to all DIL programs in unit, matching the
               message class SFB_MSG. The message is not
               received by those DIL programs in the local environment that is
               not set up to wait for that message class.
    
    <hr><a name="bpsendall">
    sendtoall( m : string, s : string )
       m : Message to send.
       s : Name idx to send message to.
       result: Send a message to all units matching a given database name.
    
    <b>Example:</b>
    
       sendtoall ( "some message", "rabbit@haon-dor");
    
       The message "some message" is sent to all units in the world matching the
       data base name "rabbit@haon-dor". Like 'send()' and 'sendto()', the
       message received matches the SFB_MSG message class.
    
    <hr><a name="bpsendalld">
    sendtoalldil( m : string, s : string )
       m : Message to send.
       s : Name idx to a DIL program to send message to.
       result: Send a message to all DIL programs matching a given database name.
    
    <b>Example:</b>
    
       sendtoalldil ( "some message", "intercomm@cemetery");
    
       The message "some message" is sent to all DIL program in the world
       matching the data base name "intercomm@cemetery".
       Like 'send()' and 'sendto()', the
       message received matches the SFB_MSG message class.
    
    <hr><a name="bpcast_s">
    cast_spell( i : integer, caster : unitptr, medium : unitptr, target : unitptr )
    
       WILL EVENTUALLY BE OBSOLETE AND REPLACED BY THE CAST_SPELL BELOW.
    
       i : Spell index to cast. See SPL_* in values.h and/or vme.h.
       caster : The caster of the spell.
       medium : The medium, with which the spell is cast, might be caster.
       target : The target of the spell.
    
       Use this to cast spells without performing all the usual mana stuff, etc.
       Very useful with for example rings / items possessing magical abilities.
    
    integer cast_spell( i : integer, caster : unitptr, medium : unitptr, target : unitptr, effect : string )
       i : Spell index to cast. See SPL_* in values.h and/or vme.h.
       caster : The caster of the spell.
       medium : The medium, with which the spell is cast, might be caster.
       target : The target of the spell.
       effect : A symbolic DIL program which takes no arguments. This will
                cause all effects to be suppressed and leave this to the program
                specified. A string of "" will cause the ordinary messages to
                appear.
       returns: The result of the spell.
    
       Use this to cast spells without performing all the usual mana stuff, etc.
       Very useful with for example rings / items possessing magical abilities.
       Please note that in the two programs below the variable 'hm' represents
       the number of hitpoints that will be deducted from the target.
    
       <b>Example:</b>
    
       %dil
    
       <i>dilbegin myeffect(medi : unitptr, targ : unitptr, hm : integer);
       code
       {
          act("The caster is $1N medium is $2N and target is $3N",
              A_ALWAYS, self, medi, targ, TO_ALL);
          act("The spell result is $2d", A_ALWAYS, self, hm, null, TO_ALL);
          quit;
       }
       dilend</i>
    
       .....
    
       %...
    
       <i>dilbegin test();
       var
         n : integer;
       code
       {
          wait(SFB_DONE, command("beg"));
    
          n := cast_spell(SPL_FIREBALL_1, self, self, activator, "myeffect@wiz");
    
          exec("say Result of spell was "+itoa(n), self);
       }
       dilend</i>
    
    <hr><a name="bpatt_s">
    integer attack_spell( n : integer, caster : unitptr, medium : unitptr,
                          target : unitptr, bonus : integer)
       Returns : The amount of damage given.
       n : The spell index of the offensive spell (SPL_XXX)
       caster : The caster of the spell.
       medium : The medium, with which the spell is cast, might be caster.
       target : The target of the spell.
       bonus  : Possible (+) advantage or (-) penalty.
    
       This is low-level internal spell stuff used to develop new spells. Do not
       use unless you know what you are doing and have been allowed to do so by
       your Admin.
       
    

    <A NAME="bpinsert"></A>

    Function: insert( sl : <stringlist or intlist>, i : integer, s : string ) ;

    sl

    the stringlist or intlist you are inserting to

    i

    the index where you want to insert the string

    s

    the string you want to insert

    This function allows you to insert a string in a stringlist or intlist with out re-writing the entire stringlist or intlist to do it. The following Dil will add a string in order to a stringlist.

    Example:


    
    dilbegin stringlist add_in_order (sl:stringlist,s:string);
    var
     i:integer;
     ln:integer;
    code
    {
    if (length(sl)==0)
     {
     addstring (sl,s);
     return (sl);
     }
    
    ln:=length(s);
    i:=0;
    while (i<ln)
     {
     if (length(sl.[i]) <=ln)
      {
      insert (sl,i,s);
     return(sl);
     }
     i:=i+1;
     }
    
    addstring (sl,s);
    return (sl);
    }
    dilend
    


    <hr><a name="bpinterr">
    integer interrupt( flags : integer, dilexp, label )
    
       Set up interrupt matching message classes matching "flags",
       for example "SFB_COM" or "SFB_COM | SFB_MSG".
    
       When the program is activated on either of the specified conditions
       the 'dilexp' is evaluated. If true, then execution continues at 'label',
       otherwise the next interrupt is checked (if any).
    
       Interrupts are saved (restored), when 'recall' is set.
       Returns an integer which is used for clear() to clear an interrupt.
    
    <b>Example:</b>
    
    The following program shows, that the owner (self) of the program keeps
    snoring while sleeping. The on_activation ensures that the program
    is only activated when the owner is sleeping. However, since the interrupt
    precede the on_activation, these may still be intercepted before the
    on_activation. The on_activation is just another type of interrupt that
    reacts on all flags (without actually setting them so that the program
    is activated).
    
    When the program receives the message "relief" the snoring stops briefly.
    As used, "relief" may only be set once.
    
    When the program receives the message "cured", the snoring stops completely
    (i.e. the program quits itself).
    
    <i>dilbegin
    
    var
       i : integer;
    
    code
    {
      /* Notice that the sequence in which the interrupts (and the on_activation)
        are executed, is quite important: You can be cured at *any* time. The
        program will skip if you are not sleeping. If you are sleeping you can
        be relieved. */
    
       interrupt(SFB_MSG, argument == "cured", the_end);
    
       on_activation(self.position != POSITION_SLEEPING, skip);
    
       i1 := interrupt(SFB_MSG, argument == "relief", relief);
    
       :loop:
       exec("snore", self);
       pause;
       goto loop;
    
       :relief:
       /* Suppose you can only be relieved once, then we must clear interrupt */
       clear(i1);
       pause;
       pause;
       goto loop;
    
       :the_end:
       /* Person is cured... */
       quit;
    }
    dilend</i>
    
    <hr><a name="bpclear">
    clear( i : integer )
    
       Clears the interrupt number "i". If i is invalid, this will either
       clear an wrong interrupt or do nothing.
    
    <hr><a name="bpona">
    integer on_activation ( dilexp , label )
       dilexp  : A boolean DIL expression.
       label   : Label to jump to - OR the reserved keyword SKIP.
       returns : The index to the interrupt handing the on_activation.
    
       result: Sets up an interrupt that is executed before every activation
               of the DIL program. This is for example useful to catch
               situations where your NPC has fallen asleep or is injured.
               If 'dilexp' evaluates to TRUE then the program jumps to 'label'.
               If 'label' is 'skip' then the program is simply not activated.
               When the on_activation evaluates to true, and jumps to a label
               other than skip, the condition is automatically cleared. If the
               dilexp evaluates to false, or if the label is skip, the activation
               remains active. Use the clear() to remove the on_activation.
    
       <b>Example:</b>
               on_activation(self.position <= POSITION_SLEEPING, skip);
                 or
               on_activation(self.position > POSITION_SLEEPING, let_me_sleep);
    
    <hr><a name="note">
    How 'Done' messages (SFB_DONE) are treated. Note that not all commands are
    implemented, if you are missing one, let Papi know and it will be created.
    See <a href="docs/command.txt">commands.txt</a> for details.
    
    <h5>This page last updated 03-27-2001, Ken Perry "Whistler" </h5>