Difference between revisions of "Sandpit"

From DikuMUD Wiki
Jump to navigation Jump to search
 
(66 intermediate revisions by the same user not shown)
Line 1: Line 1:
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
+
<BOOK ID="basiczone"><?dbhtml filename="index.html">
+
<H2>DIL DOCUMENTATION</H2>
<bookinfo>
+
'''Version 4.0'''
<TITLE>VME basic zone writing manual</TITLE>
+
<author>
+
'''Current Version by: Whistler@valhalla.com'''
<firstname>Ken</firstname>
+
<surname>Perry</surname>
+
<h3>Index</h3>
</author>
+
[[#making|Making a Program]]
<copyright><year>2001</year><holder>Ken Perry</holder></copyright>
+
[[#types|Data Types:]]
</bookinfo>
+
  [[#str|string]]
 
+
  [[#strl|stringlist]]
<CHAPTER ID="ch-intro"><?dbhtml filename="ch00.html">
+
  [[#int|integer]]
<TITLE>Introduction</TITLE>
+
  [[#intlist|integerlist]]
 
+
  [[#eptr|extraptr]]
<SECT1><TITLE>Giving credit where credit is due!</TITLE>
+
  [[#uptr|unitptr]]
 
+
  [[#cptr|cmdptr]]
<PARA>The, basic zone writing manual, you are reading now, didn't
+
  [[#zptr|zoneptr]]
just come flying out of this authors head. In fact it is a
+
  [[#messies|Messages:]]
conglomeration of several old texts which are no longer used.  I had
+
  [[#sfbcmd|SFB_CMD]]
first thought about quoting and giving credit to each person who had
+
  [[#sfbdone|SFB_DONE]]
ever modified or created portions of the first documentation but
+
  [[#sfbtick|SFB_TICK]]
because of the nature of the way they were built it was impossible
+
  [[#sfbcom|SFB_COM]]
to know who did what.  I therefore have decided to create a list
+
  [[#sfbdead|SFB_DEAD]]
here of everyone who has ever worked on or had a hand in the
+
  [[#sfbmsg|SFB_MSG]]
development of the basic zone writing documentation and references. I will also
+
  [[#sfbpre|SFB_PRE]]
give a short summary for each.
+
  [[#built_in|Built-In Variables]]
I would also like to thank those listed below for their contribution
+
  [[#cmdstr|cmdstr]]
to the development of one of the best mud servers on the internet
+
  [[#excmdstr|excmdstr]]
today.
+
  [[#excmdstr_case|excmdstr_case]]
 
+
  [[#self|self]]
<VARIABLELIST id="var-credits">
+
  [[#activator|activator]]
<VARLISTENTRY>
+
  [[#targ|target]]
;Original DIKU coding Team
+
  [[#medium|medium]]
<DICTDEF>
+
  [[#power|power]]
<PARA><itemizedlist>
+
  [[#argu|argument]]
<LISTITEM><PARA>Hans Henrik Staerfeldt</PARA></LISTITEM>
+
  [[#hb|heartbeat]]
<LISTITEM><PARA>Sebastian Hammer</PARA></LISTITEM>
+
  [[#null|null]]
<LISTITEM><PARA>Michael Seifert</PARA></LISTITEM>
+
  [[#weather|weather]]
<LISTITEM><PARA>Katja Nyboe</PARA></LISTITEM>
+
  [[#mmmm|mud(day,month,..)]]
<LISTITEM><PARA>Tom Madsen</PARA></LISTITEM>
+
  [[#bvrealtime|realtime]]
<LISTITEM><PARA>Lars Balker Rasmussen</PARA></LISTITEM>
+
[[#const|DIL Constructs:]]
</itemizedlist>
+
  [[#dcif|if()]]
 
+
  [[#dcgoto|goto]]
You should all know these people they are not only the original DIKU mud
+
  [[#dcwhile|while()]]
developers but a few of them designed and developed the new <ACRONYM>VME</ACRONYM>
+
  [[#dcbreak|break]]
server. One or more of the previous mentioned people were the authors of
+
  [[#dccont|continue]]
the following texts that have been swallowed up by this book.
+
  [[#ongoto|on ... goto ...]]
<itemizedlist>
+
  [[#forea|foreach()]]
<LISTITEM><PARA>''abilities.txt''</PARA></LISTITEM>
+
[[#assgn|Assignment]]
<LISTITEM><PARA>''guild.txt''</PARA></LISTITEM>
+
[[#express|Expressions:]]
<LISTITEM><PARA>''monster.txt''</PARA></LISTITEM>
+
[[#ops|Operators]]
<LISTITEM><PARA>''objects.txt''</PARA></LISTITEM>
+
  [[#ein|in]]
<LISTITEM><PARA>''rooms.txt''</PARA></LISTITEM>
+
  [[#esins|string in string]]
<LISTITEM><PARA>''vmc.txt''</PARA></LISTITEM>
+
  [[#esinsl|string in stringlist]]
</itemizedlist></PARA>
+
  [[#esine|string in extraptr]]
</LISTITEM>
+
[[#funcs|Functions:]]
</VARLISTENTRY>
+
  [[#fquit|quit]]
<VARLISTENTRY>
+
  [[#fret|return]]
;Andrew Cowan
+
  [[#fret2|return()]]
<DICTDEF>
+
  [[#fields|Fields:]]
 
+
  [[#extra|extraptr]]
<PARA>One of the original administrators of Valhalla mud and now the administrator of the
+
  [[#unit|unitptr]]
mud connector.  Andrew created the first zone tutorial, which was later included
+
  [[#uobj|UNIT_ST_OBJ]]
into the ''vmc.txt'' to clear up some things missing
+
  [[#uroom|UNIT_ST_ROOM]]
in the old ''vmc.txt''. Again my thanks go out to Andrew for his
+
  [[#upcnpc|UNIT_ST_PC and UNIT_ST_NPC]]
contributions not only to this document but to the growth of the <ACRONYM>DIL</ACRONYM>
+
  [[#unpc|UNIT_ST_NPC]]
programming language.</PARA>
+
  [[#upc|UNIT_ST_PC]]
</LISTITEM>
+
[[#built_func|Built-In Functions:]]
</VARLISTENTRY>
+
  [[#bfasctime|asctime()]]
<VARLISTENTRY>
+
  [[#bfatoi|atoi()]]
;Ryan Holliday
+
  [[#bfcancarry|cancarry()]]
<DICTDEF>
+
  [[#bfcheckpassword|check_password()]]
 
+
  [[#bfcomm|command()]]
<PARA>Made major updates to the ''tutorial.txt'' created by Andrew
+
  [[#bfdelstr|delstr()]]
Cowan, which became version two of the tutorial.</PARA>
+
  [[#bfdelunit|delunit()]]
</LISTITEM>
+
  [[#bfdd|dildestroy()]]
</VARLISTENTRY>
+
  [[#bfdf|dilfind()]]
<VARLISTENTRY>
+
  [[#bfeq|equipment()]]
;Peter Ryskin
+
  [[#bffilesize|filesize()]]
<DICTDEF>
+
  [[#bffindr|findroom()]]
<PARA>Wrote the original explanation of how to define exits.</PARA>
+
  [[#bffindru|findrndunit()]]
</LISTITEM>
+
  [[#bffinds|findsymbolic()]]
</VARLISTENTRY>
+
  [[#bffindu|findunit()]]
<VARLISTENTRY>
+
  [[#bffits|fits()]]
 
+
  [[#bfgcolor|getcolor()]]
;John Clare
+
  [[#bfgword|getword()]]
<DICTDEF>
+
  [[#bfgwords|getwords()]]
 
+
  [[#bfghead|ghead()]]
<PARA>Made major updates to the ''tutorial.txt'' created by Andrew
+
  [[#bfisaff|isaff()]]
Cowan and updated by Ryan Holliday, which became version three of the
+
  [[#bfislight|islight()]]
tutorial.</PARA>
+
  [[#bfisplayer|isplayer()]]
</LISTITEM>
+
  [[#bfisset|isset()]]
</VARLISTENTRY>
+
  [[#bfitoa|itoa()]]
<VARLISTENTRY>
+
  [[#bfleft|left()]]
;Marc Bellemare
+
  [[#bflen|length()]]
<DICTDEF>
+
  [[#bfload|load()]]
 
+
  [[#bfloadstr|loadstr()]]
<PARA>An editor and an author Marc combined and revised the ''tutorial''
+
  [[#bfmelee|meleeattack()]]
and the ''vmc.txt'' into one document making it less Valhalla specific
+
  [[#bfmeleedamage|meleedamage()]]
and more for any mud running the <ACRONYM>VME</ACRONYM> server.</PARA>
+
  [[#bfmid|mid()]]
</LISTITEM>
+
  [[#bfmonstr|moneystring()]]
</VARLISTENTRY>
+
  [[#bfop|opponent()]]
 
+
  [[#bforoll|openroll()]]
<VARLISTENTRY>
+
  [[#bfpathto|pathto()]]
;Jennifer Garuba
+
  [[#bfpaychk|paycheck()]]
<DICTDEF>
+
  [[#bfpurse|purse()]]
<para>Created the first document on how to create shop keepers.  She also was
+
  [[#bfreplace|replace()]]
one of the first builders to have the insite and to make it clear that a manual like this was
+
  [[#bfrestore|restore()]]
needed.</para>
+
  [[#bfright|right()]]
</LISTITEM>
+
  [[#bfrnd|rnd()]]
</VARLISTENTRY>
+
  [[#bfsavestr|savestr()]]
 
+
  [[#bfsend_pre|send_pre()]]
 
+
  [[#bfskill_name|skill_name()]]
<VARLISTENTRY>
+
  [[#bfsplind|spellindex()]]
;Brian Spanton
+
  [[#bfsplinf|spellinfo()]]
<DICTDEF>
+
  [[#bfsplit|split()]]
 
+
  [[#bfstrdir|strdir()]]
<PARA>Converted the original ''vmc.txt'' into HTMl, while at the same
+
  [[#bfstrcmp|strcmp()]]
time fixing many inconsistencies and typos in it.</PARA>
+
  [[#bfstrncmp|strncmp()]]
</LISTITEM>
+
  [[#bftextformat|textformat()]]
</VARLISTENTRY>
+
  [[#bftolower|tolower()]]
<VARLISTENTRY>
+
  [[#bftoupper|toupper()]]
;Kathy Perry
+
  [[#bftranmon|transfermoney()]]
<DICTDEF>
+
  [[#bfvis|visible()]]
 
+
  [[#bfweapon_name|weapon_name()]]
<PARA>Wrote the original ''compiler howto'' to make it easier for new builders
+
  [[#bfweapon_info|weapon_info()]]
to compile their zone.  She was also the first builder to open my eyes
+
[[#biproc|Built-In Procedures:]]
to the fact we needed a true manual on how to build.</PARA>
+
  [[#bpacc_mod|acc_modify()]]
 
+
  [[#bpact|act()]]
</LISTITEM>
+
  [[#bpaddaff|addaff()]]
</VARLISTENTRY>
+
  [[#bpaddcolor|addcolor()]]
 
+
  [[#bpaddeq|addequip()]]
<VARLISTENTRY>
+
  [[#bpaddex|addextra()]]
;Mark Pringle
+
  [[#bpadds|addstring()]]
<DICTDEF>
+
  [[#bpatt_s|attack_spell()]]
<para>Main editor, which spell checked and looked over my major grammer
+
  [[#bpbeginedit|beginedit()]]
mistakes.  I am sure he didn't catch them all but at least the ugly ones
+
  [[#bpblock|block]]
were caught.</para>
+
  [[#bpcast_s|cast_spell()]]
</LISTITEM>
+
  [[#bpchangecolor|changecolor()]]
</VARLISTENTRY>
+
  [[#bpchngs|change_speed()]]
 
+
  [[#bpclear|clear()]]
 
+
  [[#bpdc|dilcopy()]]
<VARLISTENTRY>
+
  [[#bpdelcolor|delcolor()]]
;Morgan Shafer
+
  [[#bpdp|delete_player()]]
<DICTDEF>
+
  [[#bpdest|destroy()]]
 
+
  [[#bpexec|exec()]]
<PARA>Wrote the guild definition primer which explained teachers.</PARA>
+
  [[#bpexp|experience()]]
</LISTITEM>
+
  [[#bpflog|flog()]]
</VARLISTENTRY>
+
  [[#bpfol|follow()]]
 
+
  [[#bpgamestate|gamestate()]]
 
+
  [[#bpinsert|insert()]]
</VARIABLELIST></PARA>
+
  [[#bpinterr|interrupt()]]
 
+
  [[#bpkilledit|killedit]]
</SECT1>
+
  [[#bplink|link()]]
 
+
  [[#bplog|log()]]
<SECT1> <TITLE> Who should read this book?</TITLE>
+
  [[#bplogcrime|logcrime()]]
 
+
  [[#bpnopri|nopriority]]
<PARA>This book was designed to be read by anyone who is thinking of writing
+
  [[#bpona|on_activation()]]
areas for a <ACRONYM>VME</ACRONYM> server.  If you have wrote for other mud servers you will still
+
  [[#bppagestring|pagestring()]]
need to at least skim every chapter because the <ACRONYM>VME</ACRONYM> is like no other mud engine
+
  [[#bpp_u|position_update()]]
and has some very interesting differences.</PARA>
+
  [[#bppri|priority]]
 
+
  [[#bpreboot|reboot]]
</SECT1>
+
  [[#bpremove|remove()]]
 
+
  [[#bpresetlevel|reset_level()]]
<SECT1> <TITLE>What does this book cover?</TITLE>
+
  [[#bpresetvlevel|reset_vlevel()]]
 
+
  [[#bpresetrace|reset_race()]]
<PARA>The topics covered in this book are everything to do with writing an
+
  [[#bpsec|secure()]]
area for the <ACRONYM>VME</ACRONYM> server.  While we do cover using <ACRONYM>DIL</ACRONYM> functions to make your
+
  [[#bpsend|send()]]
monsters, Rooms, and objects better and smarter we do not cover how to write the
+
  [[#bpsendall|sendtoall()]]
<ACRONYM>DIL</ACRONYM> functions covered in the <ACRONYM>DIL</ACRONYM> manual.  The following
+
  [[#bpsendalld|sendtoalldil()]]
are topics covered by this book.
+
  [[#bpsendt|sendtext()]]
<itemizedlist>
+
  [[#bpsendto|sendto()]]
<LISTITEM><PARA>compiling and debugging</PARA></LISTITEM>
+
  [[#bpsend_done|send_done()]]
<LISTITEM><PARA>Macros using the CPP</PARA></LISTITEM>
+
  [[#bpset|set()]]
<LISTITEM><PARA>Overall Zone structure</PARA></LISTITEM>
+
  [[#bpsetbright|setbright()]]
<LISTITEM><PARA>Writing rooms</PARA></LISTITEM>
+
  [[#bpsetfight|set_fighting()]]
<LISTITEM><PARA>Writing Objects</PARA></LISTITEM>
+
  [[#bpsetweight|setweight()]]
<LISTITEM><PARA>Writing Monsters</PARA></LISTITEM>
+
  [[#bpsetpassword|set_password()]]
<LISTITEM><PARA>Doing the resets</PARA></LISTITEM>
+
  [[#bpstore|store()]]
</itemizedlist></PARA>
+
  [[#bpstopfighting|stop_fighting()]]
 
+
  [[#bpsubaff|subaff()]]
</SECT1>
+
  [[#bpsubex|subextra()]]
</chapter>
+
  [[#bpsubs|substring()]]
 
+
  [[#bpuneq|unequip()]]
<chapter  ID="ch-01"><?dbhtml filename="ch01.html">
+
  [[#bfunitdir|unitdir()]]
<TITLE>General compiler information</TITLE>
+
  [[#bpunsec|unsecure()]]
 
+
  [[#bpunset|unset()]]
<PARA>In order to get your zone onto a valhalla Mud Engine (<ACRONYM>VME</ACRONYM>) server you must convert your zone from readable
+
  [[#bpwait|wait()]]
english text to binary form the server can understand.  The way
+
  [[#bpwalkto|walkto()]]
you do this is with a compiler.  No don't freak out you don't have
+
  [[#note|Ending Notes]]
to be a skilled programmer to use a compiler.  The only thing you
+
have to do is format your rooms, objects, and Non-player characters
+
---~---~---~---~---~---~---~---~---
(NPC) in a form which the compiler can understand.  The great thing
+
<center>
about the <ACRONYM>VME</ACRONYM> is you can do all your zone writing in your favorite
+
  This documentation is designed for people with some experience in programming.
editor with out having to log on to code. For those of you who have
+
  Experience in C is recommended, but PASCAL or BASIC in some form or other
coded for other mud servers and are used to coding online this may
+
will do just fine too.
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
+
  DIL is a simple programming language with fixed types reflecting the types
line.</PARA>
+
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
<NOTE>
+
making the game interesting and intelligent.
<PARA>In the future the <ACRONYM>VME</ACRONYM> coding team is thinking of adding
+
</center>
an online coding module for those mud administrators that can not
+
<!--LINK--><span id="making" />
live with out itIf you are one of these make sure you write
+
<email>whistler@valhalla.com</email> and express your desires so
+
<h3>'''Making a program:'''</h3>
you can be counted.
+
   
</PARA>
+
  You define your DIL programs within your zone file. Each program you make is a
</NOTE>
+
*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
<PARA>This chapter will mainly cover the Valhalla Mud Compiler (<ACRONYM>VMC</ACRONYM>), how it works, and
+
  section in the zone file, or directly attached to units defined in your zonefile.
the Valhalla Mud pre processor (<ACRONYM>VMC</ACRONYM> -p) works. We will also throw in some debugging
+
hints but debugging will be covered more as you begin creating parts of
+
  If you define your DIL templates inside a unit definition, that unit is
your areas in the following chapters.
+
automatically assigned a program using that template. If you want to use an
</PARA>
+
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
<SECT1><TITLE>The compiler</TITLE>
+
  optional parameters in parenthesis. The parameters of a template called with
 
+
  'dilcopy' may only be of types integer, strings and stringlists.
<PARA>''VMC'' is the Valhalla Mud Engine Compiler.
+
for <ACRONYM>VME</ACRONYM> servers. A compiler takes a source file or better described
+
'''Example:'''
as your areas input file and converts it to a binary file the
+
server can then load and use onlineIn the <ACRONYM>VME</ACRONYM> we call areas
+
  dilcopy myfunc@myzone("say Hello, my friend!", 1, CMD_SAY, {"name1", "name2"});
you build 'zones', therefore the source file for a zone has the
+
extension 'zon'. In order to make this more clear we will start
+
  DIL templates can always be reused. In fact, with version 2.0 of DIL, programs
with our first example.</PARA>
+
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.
<PARA>Lets say you were making a Zone of dragons. You may want to
+
This however requires you keep the name. Upon loading, if a template is not
call the file something resembling its contents like,
+
found, the program is halted and rendered useless until such a reference can be
''dragon.zon''. Notice we have appended the
+
found during loading.
'.zon' extension. The compiler requires all zones to end in '.zon'
+
in order for it to know this is a zone source file.</PARA>
+
Technical note:
       
+
<PARA>Now lets say we have completed writing our first zone and want
+
  When you use several 'dilcopy' in your zonefile, only one instance is present
to compile it.  The command is simply:
+
game-time, thus saving tremendous amounts of memoryIt is similar to a shared
<command>
+
library, in which code is shared  but variables are not.
VMC> dragon.zon
+
   
</command>
+
You may use your templates to define both procedure and functions for your other
If the zone compiles correctly it will indicate success by printing
+
templates to call.
a message to the screen and outputting two files both with the same
+
   
root name as the original zone source file but with different
+
A template is defined by beginning with 'dilbegin' and ending with 'dilend'.
extensions. In this case there would be the following:
+
Inside the template your program section is defined, marked by the keyword 'code',
<VARIABLELIST>
+
  followed by the program itself;
<VARLISTENTRY>
+
;''dragon.data''
 
<DICTDEF>
 
 
 
<PARA>The file holding the binary version of the zone</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;''dragon.reset''
 
<DICTDEF>
 
 
 
<PARA>The file containing the reset information for the
 
zone.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
</VARIABLELIST>
 
If the zone doesn't compile correctly and you have errors it
 
will print a list of the errors and the location where they can be
 
found so you can fix them. The debugging process will be explained
 
more as you learn how to create rooms, monsters, and objects.</PARA>
 
 
 
</SECT1>
 
 
 
<SECT1><TITLE>The VMC pre-processor</TITLE>
 
 
 
<PARA>The <ACRONYM>VMC</ACRONYM> Pre-Processor (<ACRONYM>VMC</ACRONYM> -p) can be thought of as a powerful
 
search and replace tool used by the compiler before it
 
converts the zone to its binary form. This tool gives you the
 
builder the ability to add comments, create short hand expressions
 
for repeated items, include other files in your zone, and even to do
 
some minor calculations when necessary.</PARA>
 
 
 
<NOTE> <PARA>If you have coded in C or c++ before the Pre Processor the
 
<ACRONYM>VMC</ACRONYM> uses is no different and you can skip this section.</PARA>
 
</NOTE>
 
 
 
<sect2><TITLE>Commenting your zone</TITLE>
 
 
 
<PARA>The practice of adding comments to your zone is a good thing
 
to get into so the administrators and other builders can help
 
you with your zone and know what you were trying to do if there are
 
problems.  Comments aren't as important when writing the zone as
 
they will be when you start writing your own special <ACRONYM>DIL</ACRONYM> functions
 
but it is important to know how comments work and that you can use
 
them if you need toA 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 compilerThese
 
symbols are the '/*' and the '*/' symbols or the '//' symbols together in front of a single line.</PARA>
 
 
 
<PARA>In order to best explain how comments work we will give you a some
 
what strange example. First we will start by showing you a very basic
 
line you will see time and time again in rooms.</PARA>
 
 
 
  <nowiki>
 
  <nowiki>
 
+
title "this is a title"
+
dilbegin myprogram();
 
+
var
</nowiki>
+
  i : integer;
+
  j : integer;
<PARA>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.</PARA>
+
code
+
{
 +
  heartbeat:=PULSE_SEC*5;
 +
  :start:
 +
  exec("say Hello world", self);
 +
  pause;
 +
  goto start;
 +
}
 +
dilend</nowiki>
 +
 +
  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).
 +
 +
<!--LINK--><span id="types" />
 +
<h3>'''Data Types:'''</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:
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="str" />
 +
'''String:'''
 +
 +
    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.
 +
 +
'''Example:'''
 +
 +
  "This is a static string"
 +
 +
Strings may also be added to each other, in an expression.
 +
 +
'''Example:'''
 +
 +
  "say "+itoa(42)+" is the answer!"
 +
 +
'''Example:'''
 +
 +
  if (self.name == self.names.[1]) ...
 +
 +
  Elements of the string can also be accessed by referencing them by their position.
 +
 +
  '''Example'''
 +
  if (str.[3]==f])
 +
  {
 +
  exec ("say The 4th element is a F.",self);
 +
  }
 +
 +
  '''Note'''
 +
  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.
 +
 +
'''Example'''
 +
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'.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="strl" />
 +
'''Stringlist:'''
 +
 +
  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.
 +
'''Example:'''
 +
 +
  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.
 +
 +
'''Example:'''
 +
 +
  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:
 +
 +
'''Example'''
 +
if (strlist.[5].[3]=="b"){
 +
do something
 +
}
 +
 +
'''Note'''
 +
  See the strings for more information on accessing a single element.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="int" />
 +
'''Integer:'''
 +
 +
  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.
 +
 +
'''Example:'''
 +
 +
  0x10
 +
 +
'''Example:'''
 +
 +
  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).
 +
 +
 +
'''Example:'''
 +
 +
  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.
 +
 +
'''Example:'''
 +
 +
  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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="intlist" />
 +
'''Intlist:'''
 +
 +
  Intlists are an array of integer types.  They can be set directly as follows:
 +
 +
'''Example'''
 +
 +
wpn:={5,3,6,9,3,9};
 +
 +
The intlists can be accessed in the same way stringlist are accessed as follows.
 +
 +
'''Example'''
 +
 +
if (wpn.[5]==5)
 +
{
 +
do something
 +
}
 +
 +
The intlists are saved on savable units.
 +
 +
'''Type:  '''<i><!--CODE-->intlist</i><!--ENDCODE-->
 +
 +
  This variable type allows you to keep an ordered list of integers with out
 +
having to create a variable for each integer.
 +
'''Example:'''  <i><!--CODE-->Setting an intlist</i><!--ENDCODE-->
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
myintlist:={1,5,9,2,8,5};
 +
myintlist.[10]:=50;
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
  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:'''  <i><!--CODE-->Using intlists</i><!--ENDCODE-->
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
if (myintlist.[5]==5){
 +
stuff
 +
}
 +
 +
if (myintlist&lt;myint){
 +
stuff
 +
}
 +
 +
i:=0;
 +
ln:=length(myintlist);
 +
while (i&lt;ln){
 +
myintlist.[i]:=i;
 +
i:=i+1;
 +
}
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''See Also:'''
 +
[[#bpinsert|Insert]]
 +
[[#bpremove|Remove]]
 +
[[#eptr|Extraptr]]
 +
 +
<!--LINK--><span id="eptr" />
 +
'''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.
 +
 +
 +
<!--LINK--><span id="cptr" />
 +
'''Type:  '''<i><!--CODE-->cmdptr</i><!--ENDCODE-->
 +
'''cmdptr fields'''
 +
 +
 +
'''name'''
 +
            string - command name
 +
'''type'''
 +
            integer - command type like social or skill or just command
 +
'''level'''
 +
            integer - minimum level to use command
 +
'''loglevel'''
 +
            integer - level of character that can see the log 0 for no logs
 +
'''position'''
 +
            integer - minimum position to use command
 +
'''next'''
 +
            cmdptr - pointer to the next cmdptr
 +
'''previous'''
 +
            cmdptr - pointer to the previous cmdptr
 +
 +
 +
  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:  '''<i><!--CODE-->chead();</i><!--ENDCODE-->
 +
If you want to get a specific command then you use the following function:
 +
'''Function:  '''<i><!--CODE-->cmdptr := getcommand (s : string );</i><!--ENDCODE-->
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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&amp;n",self);
 +
 +
            quit;
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
<!--LINK--><span id="zptr" />
 +
 +
'''Type:  '''<i><!--CODE-->zoneptr</i><!--ENDCODE-->
 +
'''Zone Pointer Fields'''
 +
 +
 +
<!--TERM-->  '''next'''
 +
<!--DEFINITION-->        unitptr - pointer to next zoneptr
 +
<!--TERM-->  '''previous'''
 +
<!--DEFINITION-->        unitptr - pointer to previous zone
 +
<!--TERM-->  '''creators'''
 +
<!--DEFINITION-->        stringlist - list of creators
 +
<!--TERM-->  '''name'''
 +
<!--DEFINITION-->        string - zone name (%zone)
 +
<!--TERM-->  '''title'''
 +
<!--DEFINITION-->        string - zone title (title "")
 +
<!--TERM-->  '''rooms'''
 +
<!--DEFINITION-->        unitptr - pointer to the base room
 +
<!--TERM-->  '''objs'''
 +
<!--DEFINITION-->        unitptr - pointer to the base objects of the zone
 +
<!--TERM-->  '''npcs'''
 +
<!--DEFINITION-->        unitptr - pointer to base NPCs of the zone
 +
<!--TERM-->  '''resetmode'''
 +
<!--DEFINITION-->        integer- reset mode of zone in 'values.h'
 +
<!--TERM-->  '''resettime'''
 +
<!--DEFINITION-->        integer - the reset time of the zone
 +
<!--TERM-->  '''access'''
 +
<!--DEFINITION-->        integer - the access level of the zone
 +
<!--TERM-->  '''loadlevel'''
 +
<!--DEFINITION-->        integer - the loadlevel of the zone
 +
<!--TERM-->  '''payonly'''
 +
<!--DEFINITION-->        integer - the paystatus of the zone
 +
<!--TERM-->  '''roomcount'''
 +
<!--DEFINITION-->        integer - the number of rooms in a zone
 +
<!--TERM-->  '''objcount'''
 +
<!--DEFINITION-->        integer - the numbner of objects in a zone
 +
<!--TERM-->  '''npccount'''
 +
<!--DEFINITION-->        integer - the number of npcs/mobiles in a zone
 +
<!--TERM-->  '''fname'''
 +
<!--DEFINITION-->        string - the filename of a zone
 +
<!--TERM-->  '''notes'''
 +
<!--DEFINITION-->        string - the Zone Notes
 +
<!--TERM-->  '''help'''
 +
<!--DEFINITION-->        string - the Zone Help
 +
 +
 +
  The 'zoneptr' works like a unitptrTo get the first zoneptr in the global
 +
list of zones you use 'zhead'.
 +
'''Example: '''<i><!--CODE-->zoneptr := zhead();</i><!--ENDCODE-->
 +
'''Zone list command'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
dilbegin zonelist (arg:string);
 +
var
 +
  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
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
 +
 +
 +
<!--LINK--><span id="messies" />
 +
<h3>'''Messages:'''</h3>
 +
 +
  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.
 +
 +
 +
<strong>Caveat Builder: </strong>
 +
 +
  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:'''
 +
[[#findunit.html|Dil and Findunit()]]
 +
 +
The message categories are as follows:
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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).
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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).
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
//I am going to make a title now
+
dilbegin recall aware mute();
title /* I put the keyword
+
var
first*/ "this is a title/*then the title*/
+
    i : integer;
 
+
</nowiki>
+
code
+
{
<PARA>This of course is very ugly but the point is not to be pretty it is
+
    i:=10;
to show you both the first way and the second way will look
+
    while (i>0)
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
+
      wait(SFB_CMD,command(CMD_SAY) or command(CMD_SHOUT));
zone however would be something like this:</PARA>
+
      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</nowiki>
 +
 +
/* 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.
 +
*/
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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;
 +
      }
 +
    }
 +
    ...
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
'''<i>A note upon activating a DIL program</i>'''
 +
 +
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.
 +
 +
<!--LINK--><span id="built_in" />
 +
<h3>'''Built-in Variables:'''</h3>
 +
<!--LINK--><span id="cmdstr" />
 +
'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'.
 +
 +
 +
<!--LINK--><span id="excmdstr" />
 +
'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'.
 +
 +
<!--LINK--><span id="excmdstr_case" />
 +
'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.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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"
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
   
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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 */
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="null" />
 +
'null'
 +
    This is a null pointer.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bvrealtime" />
 +
'realtime'
 +
    This variable returns the number of seconds passed since 1970 something.
 +
    For C buffs this is equivalent to time(NULL).
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="mmmm" />
 +
'mudday'
 +
'mudhour'
 +
'mudmonth'
 +
'mudyear'
 +
    These variables lets your program keep track of the time in the mud.
 +
    They all have integer types.
 +
 +
<!--LINK--><span id="const" />
 +
<h3>'''DIL constructs:'''</h3>
 +
 +
DIL offers a set of construct for you to program with.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="dcif" />
 +
'''if:'''
 +
    The if statement is much like C. It takes any type as
 +
    argument. Non integers are considered 'TRUE' if they are
 +
    not null.
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
/*
+
  dilbegin foo();
The following ten rooms are the vineyards,
+
  code
there are 97 rooms in the zone.
+
  {
*/
+
    if (self.hp>10)
 
+
    {
//Zone first created 1994
+
      exec("say Hehe!",self);
 
+
    }
</nowiki>
+
    else
+
    {
<PARA>You will find comments will make coding large zones much easier
+
      exec("say ouch!", self);
because you can add text meant just for the builders
+
    }
eyes.</PARA>
+
  }
 
+
  dilend</nowiki>
<NOTE><PARA>You will have to decide if you want a multi-line comment or a single
+
line comment and use the '//' or the '/**/' respectively.  The 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.</PARA></NOTE>
+
'''Example:'''
 
+
   
</sect2>
 
<sect2><TITLE>Macros and what they can do for you</TITLE>
 
 
 
 
 
<PARA>When making a zone you will find there are things you use more
 
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.</PARA>
 
 
 
<PARA>Lets say you had some flags you were going to set in
 
fifty rooms and you knew they would all be the same.  You could type
 
the following line 50 times.</PARA>
 
 
 
  <nowiki>
 
  <nowiki>
 
+
flags {UNIT_FL_NO_WEATHER, UNIT_FL_CAN_BURY}
+
  dilbegin foo();
 
+
  code
</nowiki>
+
  {
+
    if (self.loaded>10)
<PARA>With the macros however you could make this much easier by just doing
+
    {
the following at the beginning of your zone.</PARA>
+
      exec("say its getting crowded!",self);
+
    }
 +
  }
 +
  dilend</nowiki>
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
#define DIRTFLOOR flags {UNIT_FL_NO_WEATHER, UNIT_FL_CAN_BURY}
+
  dilbegin foo();
 
+
  code
</nowiki>
+
  {
+
    if (self.loaded<10)
<PARA>Then where ever you want the flags you just type DIRTFLOOR. You are
+
      exec("say plenty of room!",self);
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
+
  dilend</nowiki>
wanted to also make these 50 rooms no teleport. All you would have
+
to change is the define like this:</PARA>
+
---~---~---~---~---~---~---~---~---
+
 +
<!--LINK--><span id="dcgoto" />
 +
'''goto:'''
 +
    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.
 +
   
 +
  '''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
#define DIRTFLOOR flags {UNIT_FL_NO_WEATHER,UNIT_FL_CAN_BURY,UNIT_FL_NO_TELEPORT}
+
dilbegin foo();
 
+
  code
</nowiki>
+
  {
<PARA>Now when you recompile all 50 rooms are changed and you didn't even
+
    :mylabel:
have to do a search and replace.</PARA>
+
    exec("say Hello world",self);
 
+
    pause;
<PARA>You can also make macros that take arguments.  The ability to
+
    goto mylabel;
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
+
  dilend</nowiki>
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.</PARA>
+
<!--LINK--><span id="dcwhile" />
+
'''while:'''
 +
    The while statement lets you execute a series of
 +
    statements while an expression evaluates to TRUE.
 +
   
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
east to swamp1 descr
+
dilbegin foo();
"You see the swamp stretch out for miles";
+
  code
 
+
  {
</nowiki>
+
    while (not self.inside) {
+
      exec("say I own nothing", self);
<PARA>This could be made into a macro like:</PARA>
+
      pause;
+
    }
 +
    exec("say ahh.. now i own something", self);
 +
  }
 +
  dilend</nowiki>
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
'''break:''' <!--LINK--><span id="dcbreak" />
 +
    The break statement makes you break out of any
 +
    loop you're currently in.
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
#define sexit(direction, place) direction to place descr \
+
dilbegin foo();
"You see the swamp stretch out for miles.";
+
  code
 
+
  {
</nowiki>
+
    while (self.inside) {
+
      if (self.position &lt POSITION_SLEEPING)
<PARA>Then all you need to use it is:</PARA>
+
        break;
+
      exec("say I own something", self);
 +
      pause;
 +
    }
 +
  }
 +
  dilend</nowiki>
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="dccont" />
 +
'''continue:'''
 +
    The continue statement makes you jump to the top
 +
    of any loop you're currently in.
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
SEXIT(east,swamp1)
+
  dilbegin foo();
SEXIT(north,swamp2)
+
  code
SEXIT(south,swamp3)
+
  {
 
+
    while (self.inside) {
</nowiki>
+
      if (self.position &lt POSITION_SLEEPING)
+
        break;
<NOTE><PARA>There is no space between 'SEXIT' and '(' that is
+
      pause;
important because the CPP sees 'SEXIT(' and 'SEXIT (' as two
+
      if (self.hp<0) continue;
different things. It is also important to notice all defines must start at the
+
      exec("say I own something", self);
beginning of the line and be either one line long or have a '\'  
+
      pause;
telling the Pre Processor that it should continue with the next line as if it was
+
    }
this line.</PARA></NOTE>
+
  }
 
+
  dilend</nowiki>
<PARA>You can also combine macros together so you have a set
+
of macros like:</PARA>
+
---~---~---~---~---~---~---~---~---
+
<!--LINK--><span id="ongoto" />
 +
'''on <i>n</i> goto <i>la</i>, <i>lb</i>, ..., <i>ln</i>:'''
 +
 +
    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.
 +
 +
 +
'''Example:'''
 +
 +
  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:
 +
 
  <nowiki>
 
  <nowiki>
 
+
#define DIRTFLOOR flags {UNIT_FL_NO_WEATHER,UNIT_FL_CAN_BURY,UNIT_FL_NO_TELEPORT}
+
    on i goto grin, laugh, grin, nada, poke, laugh;
#define DIRTSECT  movement SECT_INSIDE \
+
    log("Value was not in the range 0..5");
DIRTFLOOR
+
    quit;
 
+
</nowiki>
+
      :laugh:
+
      exec("grin", self);
 
+
      goto ...;
<PARA>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.</PARA>
+
      :grin:
 
+
      exec("cackle", self);
</sect2>
+
      goto ...;
<sect2><TITLE>Including other files in your zone</TITLE>
+
   
 
+
      :blank:
<PARA>Another function of the <ACRONYM>VMC</ACRONYM> Pre Processor,
+
      exec("cry", self);
'#include', allows you to include other files  in
+
      goto ...;
your zone file. The <ACRONYM>VME</ACRONYM> comes with some basic include files
+
you can use the macros out of and use as examples on how to make
+
      :poke:
your own include files. These files are the
+
      exec("smirk", self);
''composed.h'',, ''vme.h'',
+
      goto ...;
''values.h'', ''base.h'',
+
</nowiki>
''liquid.h'', and ''wmacros.h''.
+
It is often used in this context
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.</PARA>
 
 
 
<NOTE><PARA>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.</PARA></NOTE>
 
 
 
</sect2>
 
<sect2><TITLE>Doing minor calculations</TITLE>
 
 
 
<PARA> You can also do minor calculations in a macro.  Lets say you
 
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.</PARA>
 
 
 
  <nowiki>
 
  <nowiki>
 
+
#define MLEVEL(lvl) \
+
    on rnd(0,4) goto l1, l2, l3, l4, l5;
level lvl \
+
height lvl+72 \
+
    :l1:
weight lvl*9
+
    bla;
 
+
</nowiki>
+
    :l2:
+
    bla;
<PARA>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
+
of this manual. If you are really interested in all the neat things
+
</nowiki>
it can do type the following command at the '$' prompt on your
+
Linux box.
+
---~---~---~---~---~---~---~---~---
<command>man cpp</command>
+
<!--LINK--><span id="forea" />
The C-Pre Processor is what the <ACRONYM>VMC</ACRONYM> Pre Processor is based on and most
+
'''foreach:'''
if not all functions of the CPP work in the <ACRONYM>VMC</ACRONYM>. </PARA>
+
  Foreach is an easy way to process all the units in the
</sect2>
+
  local environment relative to the 'self' executing the
 
+
  foreach. Foreach takes care of creating a list of local
</SECT1>
+
  units, and of securing them. You can use both break and
</chapter>
+
  continue in a foreach statement. The unit executing the
 
+
  foreach ('self') is always a part of the foreach.
<chapter ID="ch-02"><?dbhtml filename="ch02.html">
+
   
<TITLE>Zone source file</TITLE>
+
      It is important to understand that the units in the local
 
+
      environment are relative to the 'self' executing the foreach.
<PARA>In this chapter we will define all the sections of a zone file
+
   
and go in-depth on the zone info section.  Once complete with this
+
'''Example:'''
chapter you should be able to create an empty yet compilable zone.</PARA>
+
    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.
<PARA>A zone source file is split up into 6 sections. A
+
    Assume that it was executed on the spell caster's staff, then all units
zone-declaration section, a mobile (NPC) section, an object
+
    found would be relative to the staff, i.e. the spell caster's inventory.
section, a room section, a reset section, and the <ACRONYM>DIL</ACRONYM>
+
section. The zone section is the only section that  has to be in the file, and
 
they may appear in any order.</PARA>
 
 
 
<PARA>Each section is preceded by a section header. These are the six
 
possible headers:
 
<itemizedlist>
 
<LISTITEM><PARA>%zone</PARA></LISTITEM>
 
<LISTITEM><PARA>%rooms</PARA></LISTITEM>
 
<LISTITEM><PARA>%mobiles</PARA></LISTITEM>
 
<LISTITEM><PARA>%objects</PARA></LISTITEM>
 
<LISTITEM><PARA>%reset</PARA></LISTITEM>
 
<LISTITEM><PARA>%<ACRONYM>DIL</ACRONYM></PARA></LISTITEM>
 
</itemizedlist>
 
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 <ACRONYM>DIL</ACRONYM> 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.
 
</PARA>
 
 
 
<SECT1><TITLE>Definition types</TITLE>
 
 
 
<PARA>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:</PARA>
 
 
 
  <nowiki>
 
  <nowiki>
 
+
field value
+
...
 
+
    foreach (UNIT_ST_PC|UNIT_ST_NPC, u)
</nowiki>
+
    {
+
      if (u.hp < u.max_hp)
<PARA>Where field is the name of a data field, and value is some value.
+
      {
Values are of one of 6 types:
+
          act("Warm raindrops fall upon you, cleaning your wounds.",
<VARIABLELIST>
+
              A_ALWAYS, u, null, null, TO_CHAR);
<VARLISTENTRY>
+
          u.hp := u.hp + 6;
;integer
+
          if (u.hp > u.max_hp)
<DICTDEF>
+
            u.hp := u.max_hp;
<PARA>
+
      }
 
+
      else
A whole number or if you are in practice of using Hex you can
+
        act("Warm raindrops fall upon you.",
use the C style hex numbers in either upper or lower case (i.e 0X0f3
+
            A_ALWAYS, u, null, null, TO_CHAR);
0x0f3)</PARA>
+
      pause;
</LISTITEM>
+
    }
</VARLISTENTRY>
+
...</nowiki>
<VARLISTENTRY>
+
;string
+
<!--LINK--><span id="assgn" />
<DICTDEF>
+
<PARA>
+
<h3>'''Assignment:'''</h3>
 
+
    You can assign values to the variables you declare
Text enclosed in Double QuotesThe string can span more than
+
    in your 'var' section, and some of the built-in
one line
+
    variables. This is done by the ':=' operator.
as it would in a description.</PARA>
+
    Note that you can also assign a variable the result
+
    of an expression
 +
    (the addition of strings below as an example)
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
title "The dark dragon altar"
+
  dilbegin foo();
descr
+
  var
"There are many things you can see and there are many things that
+
    myvarsl : stringlist;
can't be seen but this is still a description none the less."
+
    myvars : string;
 
+
  code
</nowiki>
+
  {
+
    :start:
</LISTITEM>
+
    myvarsl := {"a string","another","the first"};
</VARLISTENTRY>
+
    myvars := self.name+" XX ";
<VARLISTENTRY>
+
    myvarsl.[2] := "the last";
;stringlist
+
    myvarsl.[3] := "illegal";  /* Will not work since [3] is not defined */
<DICTDEF>
+
    pause;
<PARA>
+
    goto start:
 
+
  }
A set of strings, it can be a single string or multiple depending on your needs.
+
  dilend</nowiki>
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.</PARA>
+
<!--LINK--><span id="express" />
+
 +
<h3>'''Expressions:'''</h3>
 +
  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.
 +
   
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
&lt;fieldname&gt;    {"string1","string2","string3", ...}
+
  dilbegin foo();
 
+
  var
</nowiki>
+
    myvarsl : stringlist;
+
    myvars : string;
</LISTITEM>
+
    myvarint : integer;
</VARLISTENTRY>
+
    myvaredp : extraptr;
<VARLISTENTRY>
+
    myvarunit : unitptr;
;intlist
+
  code
<DICTDEF>
+
   {
<PARA>
+
    :start:
 
+
    myvarunit := self.inside.next;
A list of numbers which can be used with an extra.  This type works like the
+
    myvarsl := {"a string","another","the last"};
stringlist but doesn't need the quotes.</PARA>
+
    myvars := self.name+" XX "+itoa(self.hp);
+
    myvarint := activator.hp;
 +
    myvaredp := "Rabbit Stew Complete" in activator.quests;
 +
    pause;
 +
    goto start:
 +
  }
 +
  dilend</nowiki>
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="ops" />
 +
<h3>'''Operators:'''</h3>
 +
 +
  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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="ein" />
 +
'''in:'''
 +
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.
 +
 +
  ---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
extra {"mynumberlist"} {1,2,3,4,5,6,7,...}
+
  dilbegin foo();
"This is a number list attached to an extra"
+
  code
 
+
  {
</nowiki>
+
    if ("guard" in activator.title)
+
      exec("say hello guard",self);
</LISTITEM>
+
    pause;
</VARLISTENTRY>
+
  }
<VARLISTENTRY>
+
  dilend</nowiki>
;flags
+
<DICTDEF>
+
---~---~---~---~---~---~---~---~---
<PARA>
+
<!--LINK--><span id="esinsl" />
 
+
string 'in' stringlist
Like the Intlist the flag is defined with a list of numbers. The list of numbers
+
    Argument 1: A string to find.
is not taken literally however it is combined to create one number by binary
+
    Argument 2: A stringlist to search.
oring the number list togetherIf that confuses you don't worry, it
+
    Returns: 1.. if first string is found in stringlist, or 0 if it is
takes some getting used to. These types are used for Manipulation, flags,
+
            non existent. If found the number equals the index of the
and positions.</PARA>
+
            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:
 +
 
  <nowiki>
 
  <nowiki>
 
+
flags {2,8}
+
  dilbegin foo();
manipulate {8}
+
  code
 
+
  {
</nowiki>
+
    if ("james" in activator.names)
+
      exec("say hello james.",self);
<PARA>In the previous example the 'flags' value after this zone compiles
+
    pause;
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
+
  dilend</nowiki>
you use will have defines if I used the defines found in
+
''vme.h'' the previous example would look like this:</PARA>
+
---~---~---~---~---~---~---~---~---
+
<!--LINK--><span id="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).
 +
   
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
flags {UNIT_FL_INVISIBILE,UNIT_FL_BURIED}
+
  dilbegin foo();
manipulate {WEAR_BODY}
+
  code
 
+
  {
</nowiki>
+
    if ("Rabbit Stew Complete" in activator.quests) {
+
      exec("say wow!, you helped Mary get her stew!", self);
<PARA>We will cover this more in-depth later but it was necessary to give
+
      exec("app ", self);
a good overview so you understand this field type enough to recognize
+
    }
what it is when you see it.</PARA>
+
    pause;
</LISTITEM> </VARLISTENTRY> <VARLISTENTRY>
+
  }
;symbol
+
  dilend</nowiki>
<DICTDEF> <PARA>
+
 
+
<!--LINK--><span id="funcs" />
A label you reference from other parts in your zones. Every
+
<h3>Functions:</h3>
unit (room,object,room) and even the zone itself has a unique label
+
  DIL features an extended set of built-in functions
that can be referenced. It is important to make symbol names that
+
  for extended program control. Built-in functions can be part of
are clear so the Administrators of the mud know what each item
+
  any expression in DIL. The built-in functions are
is when using the online administration commands.</PARA>
+
  listed later.
+
   
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
dark_sword /*good symbol*/
+
  dilbegin foo();
rm_5892 /*Bad symbol*/
+
  code
 
+
  {
</nowiki>
+
    exec("say I exist in "+itoa(self.loaded)+"copies", self);
+
    pause;
<PARA>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
+
  dilend</nowiki>
name was 'dragon' and our item was 'dark_sword' the symbolic name for
+
   
this item would be 'dark_sword@dragon'.  Using symbols will be
+
  DIL also lets you use templates as functions, but in a
covered more in the <ACRONYM>DIL</ACRONYM> manual and in the administration manuals for
+
  limited way. Using templates as functions, you may only
loading objects online.  For now it is enough to understand
+
  use the return value to assign it to one of the variables
symbols must follow the following rules when being defined.</PARA>
+
  declared in the 'var' section. No fields.
<itemizedlist>
+
   
<LISTITEM><PARA>The first letter of the
+
  '''Example:'''
symbol must be a letter of the alphabet or a '_' character</PARA></LISTITEM>
+
   
<LISTITEM><PARA>Characters following the first can be numbers, alphabet
 
letters, and '_' characters</PARA></LISTITEM>
 
<LISTITEM><PARA>The name can be no longer than
 
15 characters</PARA></LISTITEM>
 
<LISTITEM><PARA>No reserved keywords can be used as a name
 
<XREF LINKEND="app-b"></PARA></LISTITEM>
 
</itemizedlist>
 
 
 
<NOTE><PARA>the end tag that ends all unit definitions is also
 
considered a symbol it is just a symbol that must be included with</PARA></NOTE>
 
</LISTITEM>
 
</VARLISTENTRY>
 
</VARIABLELIST></PARA>
 
 
 
<PARA>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
 
<ACRONYM>DIL</ACRONYM> function or a special function called from the
 
base code.</para>
 
 
 
<NOTE><PARA>Special functions are being replaced with
 
<ACRONYM>DIL</ACRONYM> for better performance and should only be used
 
when no <ACRONYM>DIL</ACRONYM> functions exist to replace
 
them</PARA></NOTE>
 
 
 
<para>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.</PARA>
 
 
 
</SECT1>
 
 
 
<SECT1 id="zoneinfo">
 
<TITLE>Zone information section</TITLE>
 
 
 
<PARA>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.</PARA>
 
 
 
<TABLE frame=all>
 
<TITLE>Zone section field descriptions</TITLE>
 
<TGROUP align=left cols=3 colsep=1>
 
<THEAD>
 
<ROW>
 
<ENTRY>Field</ENTRY>
 
<ENTRY>Type</ENTRY>
 
<ENTRY>Description</ENTRY>
 
</ROW>
 
</THEAD>
 
 
 
<TBODY>
 
 
 
<ROW>
 
<ENTRY>creators</ENTRY>
 
<ENTRY>Stringlist</ENTRY>
 
<ENTRY>
 
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.
 
</ENTRY></ROW>
 
<ROW>
 
<ENTRY>lifespan</ENTRY>
 
<ENTRY>Number</ENTRY>
 
<ENTRY>
 
This  defines  the interval between resets for this zone, in minutes.
 
Default is 60 if this field is left out of the information section.
 
</ENTRY></ROW>
 
<ROW>
 
<ENTRY>notes</ENTRY>
 
<ENTRY>String</ENTRY>
 
<ENTRY>
 
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.
 
</ENTRY></ROW>
 
<ROW>
 
<ENTRY>reset</ENTRY>
 
<ENTRY>Number</ENTRY>
 
<ENTRY>
 
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.
 
</ENTRY></ROW>
 
<ROW>
 
<ENTRY>title</ENTRY>
 
<ENTRY>String</ENTRY>
 
<ENTRY>
 
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 <ACRONYM>DIL</ACRONYM>. 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.
 
</ENTRY></ROW>
 
 
 
<ROW>
 
<ENTRY>weather</ENTRY>
 
<ENTRY>Integer</ENTRY>
 
<ENTRY>
 
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.
 
</ENTRY></ROW>
 
 
 
 
 
<ROW>
 
<ENTRY>%zone</ENTRY>
 
<ENTRY>Symbol</ENTRY>
 
<ENTRY>
 
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.
 
</ENTRY></ROW>
 
</TBODY>
 
</TGROUP>
 
</TABLE>
 
 
 
 
 
<PARA>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.</PARA>
 
 
 
 
 
  <nowiki>
 
  <nowiki>
 
+
/*very bad*/
+
  dilbegin integer bar(s:string);
%zone
+
  code
 
+
  {
/*bad but better than nothing*/
+
    exec("say "+s,self);
%zone bug_planet
+
    return rnd(1,10);
 
+
  }
/*The way it should be done!*/
+
  dilend</nowiki>
%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>
 
 
 
 
<PARA>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.</PARA>
 
</SECT1>
 
 
 
</chapter>
 
 
 
<chapter ID="ch-03"><?dbhtml filename="ch03.html">
 
<TITLE>Unit building blocks</TITLE>
 
 
 
<PARA>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 </PARA>
 
 
 
<PARA>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:</PARA>
 
 
 
  <nowiki>
 
  <nowiki>
 
+
symbol_name
+
  dilbegin foo();
end
+
  external
 
+
    integer bar(s:string);
</nowiki>
+
  var
+
    myint:integer;
<PARA>If you define a unit like this when it loads it will be blank, while
+
  code
this is not extremely useful it is good to know you can leave
+
  {
out any field you don't feel you need.</PARA>
+
    myint := bar("rolling the dice.");
 
+
    exec("say I rolled a "+itoa(myint));
 
+
    pause;
<VARIABLELIST>
+
  }
<TITLE>Unit building blocks</TITLE>
+
  dilend</nowiki>
<VARLISTENTRY>
+
;symbol field
+
  ---~---~---~---~---~---~---~---~---
<DICTDEF>
+
<!--LINK--><span id="fquit" />
<PARA>
+
quit:
 
+
  This simple command quits the entire DIL program, even if
In the last chapter we defined the different field types and
+
  called while inside a procedure or function.
the rules you must follow when defining a symbolIt is
+
   
important enough to relist these rules here so you do not run into
+
---~---~---~---~---~---~---~---~---
problems when creating your units.
+
<!--LINK--><span id="fret" />
<itemizedlist>
+
return:
<LISTITEM><PARA>The first letter of the
+
  Return from a call to a procedure template (no return type
symbol must be a letter of the alphabet or a '_' character</PARA></LISTITEM>
+
  declared). The execution continues from where the procedure
<LISTITEM><PARA>Characters following the first can be numbers, alphabet
+
  was called.
letters, and '_' characters</PARA></LISTITEM>
+
<LISTITEM><PARA>The symbol can be no longer than
+
---~---~---~---~---~---~---~---~---
15 characters</PARA></LISTITEM>
+
<!--LINK--><span id="fret2" />
<LISTITEM><PARA>No reserved keywords can be used as a symbol<XREF LINKEND="app-b"></PARA></LISTITEM>
+
return():
</itemizedlist></PARA>
+
  Return from a call to a function (return type declared).
 
+
  The expression inside the parenthesis evaluates to the value
<NOTE><PARA>It is also important to know currently it is hard to deal with units
+
  returned.
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.</PARA></NOTE>
+
 
+
  DIL also allows for game-time *symbolic* resolving of
<PARA>Another thing you should think about when defining your symbol
+
  function/procedure names. This allows you to pass template names
names is to be clear about what the unit isWhen you list units on
+
  as string arguments and call them in your program. This kind of
the <ACRONYM>VME</ACRONYM> server with <command>wstat</command> the symbolic names are
+
  function call requires taxing look ups and type check runtime, so
shown
+
  use the normal kind of procedures if possible.
if you were to see the list:
+
   
<computeroutput>
+
  In effect, the syntax of a symbolic call is similar to that of
i6853 b2419 l1854
+
  a normal, except you use a string variable as function name
</computeroutput>
+
  instead of the real function name. If the string variable contains
You would have no idea what those three items were unless you
+
  a valid reference to a procedure/function, and all the argument
personally built them recently, therefore it is a much better coding
+
  types matches the found templates argument types, the call
practice to name things what they are like:
+
  is made. Otherwise, the call is skipped. Note that you will get no
<computeroutput>
+
  type check by the compiler when using symbolic references.
long_sword healer_hut dog
+
</computeroutput>
+
<!--LINK--><span id="fields" />
</PARA></LISTITEM>
+
<h3>'''Fields:'''</h3>
</VARLISTENTRY>
+
<VARLISTENTRY>
+
The 'extraptr' and 'unitptr' types contain information which is available to
;title field
+
you by using fields. For example (self is a unitptr), self.inside is a
<DICTDEF>
+
unitptr to what is inside the 'self' unit. (Hence '.inside' is the field).
<PARA>
+
And self.inside.outside is a unitptr to self (assuming that something is
 
+
actually inside self, otherwise self.inside would evaluate to null).
The title field is probably the easiest field on all units it
+
  Some fields may not be changed by DIL programs directly but must be modified
is what is shown on the first line of a room when you enter and it
+
indirectly using certain procedure calls in DIL. Others may not be changed
is the name shown when you get an object or attack a NPC.
+
at all. All are readable for DIL programs.
There is only two important things to look at when defining titles
+
one is punctuation and the other is capitalizationRoom titles
+
The extraptr structure is used for several things. The primary is
need to be capitalized and so do proper names but the first letter of an object
+
extra descriptions for units, and quest data. Keywords in the 'names'
title or a NPC title do not normally need to be capitalized. this is
+
field and the actual description/data in the 'descr' field.
best explained by some examples.</PARA>
+
+
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
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="extra" />
 +
'''The extraptr has the following fields:'''
 +
 +
    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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
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)
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="unit" />
 +
'''The unitptr has the following fields:'''
 +
 +
    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)
 +
<!--LINK--><span id="uobj" />
 +
'''if the type is UNIT_ST_OBJ'''
 +
 +
      '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.
 +
<!--LINK--><span id="uroom" />
 +
'''if the type is UNIT_ST_ROOM'''
 +
 +
      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
 +
<!--LINK--><span id="upcnpc" />
 +
'''if the type is UNIT_ST_PC or UNIT_ST_NPC '''
 +
 +
      '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
 +
<!--LINK--><span id="unpc" />
 +
'''if the type is UNIT_ST_NPC '''
 +
 +
      '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.
 +
<!--LINK--><span id="upc" />
 +
'''if the type is UNIT_ST_PC'''
 +
 +
      '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.
 +
 +
<!--LINK--><span id="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.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bfasctime" />
 +
string asctime(i : integer)
 +
    i : the time to convert in seconds ([[#bvrealtime|realtime]] 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
 +
 +
<!--LINK--><span id="bfstrcmp" />
 +
 +
'''Function:'''  <i><!--CODE-->integer strcmp( s1:string, s2:string) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''s1'''
 +
<!--DEFINITION-->        first string
 +
<!--TERM-->  '''s2'''
 +
<!--DEFINITION-->        second string
 +
 +
  '''returns'''
 +
<!--TERM-->  '''-1'''
 +
<!--DEFINITION-->        if s1 &lt; s2
 +
<!--TERM-->  '''0'''
 +
<!--DEFINITION-->        if s1 = s2
 +
<!--TERM-->  '''1'''
 +
<!--DEFINITION-->        if s1 &gt; s2
 +
 +
 +
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.
 +
'''example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
if (strcmp("I Care about Capitals",s2)==0))
 +
        {
 +
        sendtext ("You care I can see.&amp;n",self);
 +
        quit;
 +
        }
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
<!--LINK--><span id="bfstrncmp" />
 +
 +
'''Function:'''  <i><!--CODE-->integer strcmp( s1:string, s2:string l :integer) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''s1'''
 +
<!--DEFINITION-->        first string
 +
<!--TERM-->  '''s2'''
 +
<!--DEFINITION-->        second string
 +
<!--TERM-->  '''l'''
 +
<!--DEFINITION-->        amount of significant digits to compare
 +
 +
  '''returns'''
 +
<!--TERM-->  '''-1'''
 +
<!--DEFINITION-->        if s1 &lt; s2
 +
<!--TERM-->  '''0'''
 +
<!--DEFINITION-->        if s1 = s2
 +
<!--TERM-->  '''1'''
 +
<!--DEFINITION-->        if s1 &gt; 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:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
if (strcmp("Mark Carper",s2,4)==0))
 +
        {
 +
        sendtext ("Hi Mark how is it going?&amp;n",self);
 +
                quit;
 +
        }
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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);
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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);
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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 */
 +
 +
 +
 +
<!--LINK--><span id="bpbeginedit" />
 +
 +
'''Function:'''  <i><!--CODE-->beginedit ( u : unitptr);</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->        the PC unit doing the editing
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        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
 +
[[#sect-beginedit|interrupt editing before done]]
 +
 +
'''example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
dilbegin edextra ();
 +
var
 +
        temp:string;
 +
code
 +
{
 +
        beginedit (self);
 +
        wait(SFB_EDIT,self==activator) ;
 +
        temp:=textformat(argument);
 +
        addextra (self.extra,"general",temp);
 +
        quit;
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
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'
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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);
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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);
 +
 +
 +
<!--LINK--><span id="bfreplace" />
 +
 +
'''Function:'''  <i><!--CODE-->string replace( t :string, n : string, o : string);</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''t'''
 +
<!--DEFINITION-->        the target string you want to replace
 +
<!--TERM-->  '''n'''
 +
<!--DEFINITION-->        what you want to replace the target with
 +
<!--TERM-->  '''o'''
 +
<!--DEFINITION-->        the original string
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        the string with the old string replaced by the new string
 +
 +
This function replaces all occurences of a string in another string with a
 +
new string.
 +
'''Example:'''
 +
<i><!--CODE-->"Jafar %t% %l%" := replace(%n%,pc.name,"%n% %t% %l%");</i><!--ENDCODE-->
 +
<i><!--CODE-->"Jafar the human %l%" := replace(%t%,pc.title,"Jafar %t% %l%");</i><!--ENDCODE-->
 +
<i><!--CODE-->"Jafar the human 1" := replace(%l%,itoa(pc.vlevel),"Jafar the human %l%");</i><!--ENDCODE-->
 +
 +
 +
<!--LINK--><span id="bfrestore" />
 +
 +
'''Function:'''  <i><!--CODE-->unitptr restore( filename : string , u : unitptr );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''filename'''
 +
<!--DEFINITION-->        The name of the Unit file
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->        The Unit you want to restore into or null if none
 +
<!--TERM-->  '''Return'''
 +
<!--DEFINITION-->        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'
 +
 +
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..
 +
'''Note''', 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.
 +
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.
 +
'''Disk access is always slow'''.
 +
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.
 +
 +
'''Example 1:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''Example 2:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''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'''
 +
[[#bpstore|Store a Unit to a Unit file]] and
 +
[[#bfdelunit|Delete a Unit file]].
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
 +
 +
<!--LINK--><span id="bfmeleedamage" />
 +
 +
'''Function:  '''
 +
<i><!--CODE-->meleedamage ( c : unitptr, v : unitptr, b : integer, wt : integer );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''c'''
 +
<!--DEFINITION-->        the character that should make an additional attack
 +
<!--TERM-->  '''v'''
 +
<!--DEFINITION-->        the character being attacked
 +
<!--TERM-->  '''b'''
 +
<!--DEFINITION-->        any penalty or bonus added to the attack.
 +
<!--TERM-->  '''wt'''
 +
<!--DEFINITION-->        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.
 +
<!--TERM-->  '''returns'''
 +
<!--DEFINITION-->        The amount of damage done or -1 for failed
 +
 +
ch' performs an attack (using whatever weapon is wielded or his bare hands) against 'vict'.
 +
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.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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] &lt;= 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 &amp; (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 &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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
 +
<!--LINK--><span id="bfmid" />
 +
 +
'''Function:'''  <i><!--CODE-->string mid ( o : string, s : integer, e : integer );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''o'''
 +
<!--DEFINITION-->        the original string to be parsed
 +
<!--TERM-->  '''s'''
 +
<!--DEFINITION-->        The starting point of the string to be parsed out
 +
<!--TERM-->  '''e'''
 +
<!--DEFINITION-->        the ending point of the string to be parsed out
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        the portion of the string defined by the 's' and 'e' values
 +
 +
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.
 +
'''Example:'''  <i><!--CODE-->"rock" := mid ("sprocket",3,6);</i><!--ENDCODE-->
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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
 +
 +
  <!--LINK--><span id="bftolower" />
 +
 +
 +
'''Function:''' <i><!--CODE-->string tolower ( s : string );</i><!--ENDCODE-->
 +
<!--TERM-->  '''s'''
 +
<!--DEFINITION-->        String to lower case
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        the string passed in lower cased
 +
 +
This function returns a copy of the string passed in but with out capitals.
 +
  '''Example:''' <i><!--CODE-->"hello!" :=  tolower("HELLO!");</i><!--ENDCODE-->
 +
  <!--LINK--><span id="bftoupper" />
 +
 +
'''Function:'''  <i><!--CODE-->string toupper ( s : string );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''s'''
 +
<!--DEFINITION-->        String to lower case
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        the string passed in lower cased
 +
 +
This function returns a copy of the string passed in with all characters changed
 +
to be capitalized.
 +
'''Example:'''  <i><!--CODE-->"HELLO!" := toupper ("hello!");</i><!--ENDCODE-->
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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)) ...
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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);
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bfatoi" />
 +
integer atoi ( s : string )
 +
    s : A string with a number.
 +
    return: The number in the string.
 +
    Example: i := atoi("42");
 +
 +
 +
 +
<!--LINK--><span id="bfcheckpassword" />
 +
 +
'''Function:'''  <i><!--CODE-->integer check_password( u : unitptr, s : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->        the unit that you want to check the password of
 +
<!--TERM-->  '''s'''
 +
<!--DEFINITION-->        the password you are using to check
 +
<!--TERM-->  '''Return'''
 +
<!--DEFINITION-->        Returns an integer TRUE if pcname is the units password FALSE if not
 +
 +
This function checks the string against the units password and returns TRUE
 +
if they match.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
if (not check_password(pc,arg))
 +
        {
 +
        sendtext (arg+" is not "+pc.name"'s password.",self);
 +
                quit;
 +
        }
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
<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".)
 +
 +
 +
<!--LINK--><span id="bfdelstr" />
 +
 +
'''Function:'''  <i><!--CODE-->integer delstr( filename : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''filename'''
 +
<!--DEFINITION-->        The name of the String file to be deleted
 +
<!--TERM-->  '''Return'''
 +
<!--DEFINITION-->        Returns an integer TRUE if deleted FALSE if not
 +
 +
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.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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[&amp;]n",self);
 +
quit;/*dil delete routine done
 +
}
 +
dilend
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''See Also''' <i><!--CODE-->
 +
[[#bfloadstr|Load String file]] and
 +
[[#bfsavestr|Save String file]]</i><!--ENDCODE-->
 +
 +
 +
<!--LINK--><span id="bfdelunit" />
 +
 +
'''Function:'''  <i><!--CODE-->integer delunit( filename : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''filename'''
 +
<!--DEFINITION-->        The name of the Unit file to be deleted.
 +
<!--TERM-->  '''Return'''
 +
<!--DEFINITION-->        Returns an integer TRUE if deleted FALSE if not delunit is used to delete files that are used with the 'Restore' and 'store' functions.
 +
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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[&amp;]n",self);
 +
quit;/*dil delete routine done
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''See Also'''
 +
[[#bfrestore|Restore a Unit from a Unit file]] and
 +
[[#bpstore|Store Units to a Unit file]].
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bfitoa" />
 +
string itoa ( i : integer )
 +
    i : A number.
 +
    return: A string with the number.
 +
    Example: s := itoa(42);
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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'
 +
 +
 +
 +
 +
 +
 +
<!--LINK--><span id="bfislight" />
 +
 +
'''Function:  '''<i><!--CODE-->integer islight ( u : unitptr )</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->        Unit that you are checking
 +
<!--TERM-->  '''returns'''
 +
<!--DEFINITION-->        ''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.
 +
 +
 +
<!--LINK--><span id="bfisplayer" />
 +
 +
'''Function:'''  <i><!--CODE-->integer isplayer( pcname : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''pcname'''
 +
<!--DEFINITION-->        the name of the player being checked
 +
<!--TERM-->  '''Return'''
 +
<!--DEFINITION-->        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:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
if (not isplayer(arg))
 +
        {
 +
        sendtext (arg+" is not a character.&amp;n",self);
 +
        quit;
 +
        }
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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)) ...
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
The flags for findunit, intuitively:
 +
 +
 +
FIND_UNIT_EQUIP:
 +
  The objects you will see with `equipment'
 +
  Assumes first argument to findunit is a char.
 +
 +
 +
FIND_UNIT_INVEN:
 +
  The objects you will see with `inventory' or `look in bag'
 +
 +
 +
FIND_UNIT_SURRO:
 +
  The objects you can see, and get with `get',
 +
  or the characters you can `poke' :-)
 +
 +
 +
FIND_UNIT_ZONE:
 +
  As FIND_UNIT_WORLD, only more local.
 +
 +
 +
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.
 +
 +
 +
On top of these, the following (new) values are defined:
 +
 +
 +
FIND_UNIT_IN_ME:
 +
  Anything inside of the object of the first argument.
 +
 +
 +
FIND_UNIT_HERE:
 +
  Anything `here', i.e. in object or around it (same as IN_ME + SURRO)
 +
 +
 +
FIND_UNIT_GLOBAL:
 +
  ANYTHING, starting close to object and working out.
 +
 +
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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).
 +
 +
 +
<!--LINK--><span id="bffilesize" />
 +
 +
'''Function:'''  <i><!--CODE-->integer filesize ( filename :string);</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''file'''
 +
<!--DEFINITION-->        The file name you want to check
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        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:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
dilbegin notebook ();
 +
code
 +
{
 +
        ns := filesize (self.name+"notebook");
 +
        if ( ns >500000)
 +
        {
 +
                sendtext ("Your notebook is full.&amp;n",self);
 +
                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;
 +
        }
 +
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
The previous DIL example shows how you could use the 'filesize' instruction to
 +
check the size of a player stored notebook.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bffindr" />
 +
unitptr findroom ( s : string )
 +
    s : Symbolic name of room.
 +
    return: A pointer to the room, or null
 +
    Example: findroom("inn@udgaard")
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
dilbegin zonelog (s:string);
 +
code
 +
{
 +
flog (self.zonidx+".log",s,"a");
 +
return;
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
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.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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'.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bfghead" />
 +
unitptr ghead ( )
 +
 +
return the first unit in the global list which will be the last
 +
char to have logged on.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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 '&amp;x' to split a string by line.  This is very usefull when reading in files with 'loadstr'.
 +
 +
<!--LINK--><span id="bfleft" />
 +
 +
'''Function:'''  <i><!--CODE-->string left ( o : string, l : integer );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''o'''
 +
<!--DEFINITION-->        the original string to be parsed
 +
<!--TERM-->  '''l'''
 +
<!--DEFINITION-->        The amount of characters to parse out
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        the left portion of the string with length l
 +
 +
This function parses the string passed to it and returns the number
 +
of characters defined in its second argument.
 +
 +
'''Example:'''  <i><!--CODE-->"short" := left ("shorten me",5);</i><!--ENDCODE-->
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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 &lt;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&lt;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&lt;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&lt;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:  &amp;n"+x.descr+"&amp;n",self);
 +
        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);
 +
 +
        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.&amp;n",self);
 +
        quit;
 +
 +
        :hlp_dscr:
 +
 +
        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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
<!--LINK--><span id="bfloadstr" />
 +
 +
'''Function:'''
 +
<i><!--CODE-->integer loadstr( filename : string , buff : string );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''filename'''
 +
<!--DEFINITION-->        The name of the string file to be loaded
 +
<!--TERM-->  '''buff'''
 +
<!--DEFINITION-->        The string that you wish to read the file contents into
 +
<!--TERM-->  '''Return'''
 +
<!--DEFINITION-->        <i><!--CODE-->FILE_LOADED, FILE_NOT_FOUND, FILE_OUT_OF_MEMORY,or FILE_TO_LARGE</i><!--ENDCODE-->
 +
 +
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.
 +
'''Disk access is always slow'''.
 +
attempt to keep file sizes to a minimum for quick loading.  Otherwise you
 +
might cause serious delays on the server.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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+"[&amp;]n",self);
 +
quit;/*dil load routine done destroy self.*/
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''See Also''' <i><!--CODE-->
 +
[[#bfdelstr|Delete a String file]] and
 +
[[#bfsavestr|Save String file]]</i><!--ENDCODE-->
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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"));
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
 +
 +
<!--LINK--><span id="bfright" />
 +
 +
'''Function:'''  <i><!--CODE-->string right ( o : string, r : integer );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''o'''
 +
<!--DEFINITION-->        the original string to be parsed
 +
<!--TERM-->  '''r'''
 +
<!--DEFINITION-->        The amount of characters to parse out
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        the right portion of the string with length r
 +
 +
This function parses the string passed to it and returns the number of characters
 +
from the right defined in its second argument.
 +
'''Example:'''  <i><!--CODE-->"Easy" := right ("This is Easy",4);</i><!--ENDCODE-->
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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);
 +
 +
 +
<!--LINK--><span id="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)
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
title "The dragons in."/*good*/
+
  dilbegin bar(s:string);
title "a big bull dog."/*bad has a period at the end*/
+
  code
title "Bill the destroyer"/*good*/
+
  {
title "A long dagger"/*bad capital 'a'*/
+
    exec("say "+s,self);
 
+
    return;
</nowiki>
+
  }
+
  dilend</nowiki>
<PARA>Now to show why some of those are good we will demonstrate by some
+
   
sample output in the game.
 
<computeroutput>
 
 
 
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.
 
</computeroutput>
 
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.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;names field
 
<DICTDEF>
 
<PARA>
 
 
 
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.
 
it</PARA>
 
 
 
<PARA>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:</PARA>
 
 
 
  <nowiki>
 
  <nowiki>
 
+
bad_obj
+
  dilbegin foo();
title a small dog"
+
  external
names{"small dog","small","dog"}
+
    someproc@hades1();
end
+
    bar(s:string);
 
+
  code
</nowiki>
+
  {
+
    someproc@hades1();
<PARA>It is up to you as a builder if you want to use names like 'small'
+
    bar("Hello "+activator.name);
in your names list since you would not 'get small' in real life it
+
    pause;
may not have to be added to the names listIt is important however
+
  }
to define your extras from big to small because of how the <ACRONYM>VME</ACRONYM>
+
  dilend</nowiki>
command interpreter handles names of thingsFor example if you had
+
the following names:</PARA>
+
    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.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
 +
 +
<!--LINK--><span id="bpflog" />
 +
 +
'''Function:'''  <i><!--CODE-->flog (filename : string,  s : string, wa : string );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''filename'''
 +
<!--DEFINITION-->        The Filename of the file to appear in the log directory.
 +
<!--TERM-->  '''s'''
 +
<!--DEFINITION-->        The string to be logged.
 +
<!--TERM-->  '''wa'''
 +
<!--DEFINITION-->        Write or Append
 +
 +
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.
 +
'''Note:'''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:'''
 +
<i><!--CODE-->
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
dilbegin zonelog (s:string);
 +
code
 +
{
 +
flog (self.zonidx+".log",s,"a");
 +
return;
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
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.
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
 +
<!--LINK--><span id="bfstrdir" />
 +
 +
'''Function:'''  <i><!--CODE-->stringlist strdir( match : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''match'''
 +
<!--DEFINITION-->        The wild card file you want to match or '*' for all.
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        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.
 +
 +
<!--TERM-->  '''&ast;'''
 +
<!--DEFINITION-->        Match any character or group of characters
 +
<!--TERM-->  '''&quest;'''
 +
<!--DEFINITION-->        Match one of any character
 +
<!--TERM-->  '''[...]'''
 +
<!--DEFINITION-->        Match one of a set of characters
 +
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
"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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''Example DIL:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
dilbegin wanted ();
 +
var
 +
        wantedlist:stringlist;
 +
        templist:stringlist;
 +
        i:integer;
 +
        ln:integer;
 +
code
 +
{
 +
 +
        wantedlist := strdir ("dead*");
 +
 +
                i := 0;
 +
                ln := length (wantedlist);
 +
 +
        while (i &lt; ln )
 +
                {
 +
                templist := split (wantedlist.[i],".");
 +
                sendtext (templist.[1]+" wanted dead!&amp;n",self);
 +
                i:=i+1;
 +
                }
 +
 +
quit;
 +
}
 +
dilend
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
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'
 +
 +
 +
<!--LINK--><span id="bpsetpassword" />
 +
 +
'''Function:'''  <i><!--CODE-->set_password( u : unitptr, s : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM--> '''u'''
 +
<!--DEFINITION-->        the unit that you want to set the password of
 +
<!--TERM-->  '''s'''
 +
<!--DEFINITION-->        the password you are using to set
 +
 +
This function sets a unit password it only works on Players characters of corse.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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.&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;
 +
        }
 +
 +
if (length(excmdstr)>16){
 +
        sendtext ("Password to long. Try again.&amp;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.&amp;n",self);
 +
self.prompt:=prmt;
 +
quit;
 +
}
 +
set_password(self,excmdstr);
 +
sendtext("Changed your Password to '"+excmdstr+"' Please write it down!&amp;n",self);
 +
self.prompt:=prmt;
 +
 +
quit;
 +
}
 +
dilend
 +
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
 +
 +
<!--LINK--><span id="bpstore" />
 +
 +
'''Function:'''  <i><!--CODE-->store( u : unitptr , filename : string , container : integer );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->        The Unit that has the contents to be stored or is to be stored
 +
<!--TERM-->  '''filename'''
 +
<!--DEFINITION-->        The name of the file you want to store the Units to
 +
<!--TERM-->  '''container'''
 +
<!--DEFINITION-->        Do you want to save the container 'TRUE' for yes, 'False' for no
 +
 +
 +
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.
 +
 +
 +
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.
 +
 +
 +
'''Disk access is always slow'''.
 +
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.
 +
'''Example 1:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''Example 2:'''
 +
<i><!--CODE-->
 +
 +
 +
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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''See Also'''
 +
[[#bfrestore|Store a Unit to a Unit file]] and
 +
[[#bfdelunit|Delete a Unit file]].
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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);
 +
 +
<!--LINK--><span id="bpsend_done" />
 +
 +
'''Function:'''</i><!--ENDCODE-->
 +
send_done( c : string, a :unitptr, m : unitptr, t :unitptr, p : integer, arg : string, o : unitptr);</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''c'''
 +
<!--DEFINITION-->        the command string that is sending the message
 +
<!--TERM-->  '''a'''
 +
<!--DEFINITION-->        the unitptr (activator) that activated the message
 +
<!--TERM-->  '''m'''
 +
<!--DEFINITION-->        the unitptr (medium) that the Dil is acting through
 +
<!--TERM-->  '''t'''
 +
<!--DEFINITION-->        the unitptr (target) the Dil is acting on
 +
<!--TERM-->  '''p'''
 +
<!--DEFINITION-->        the power of the message
 +
<!--TERM-->  '''arg'''
 +
<!--DEFINITION-->        the argument sent with the message
 +
<!--TERM-->  '''o'''
 +
<!--DEFINITION-->        the unitptr (other) you also want the message to go to
 +
 +
 +
  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 '''commands.zon'''
 +
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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&lt;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&lt;=0)
 +
        {
 +
        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;
 +
        }
 +
 +
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&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;
 +
                }
 +
 +
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);
 +
 +
pagestring(buff,self);
 +
 +
:read_quit:
 +
  send_done("read",self,null,u,0,arg,null);
 +
quit;
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
<!--LINK--><span id="bfsend_pre" />
 +
'''Function:'''</i><!--ENDCODE-->send_pre( c : string, a :unitptr, m : unitptr, t :unitptr, p : integer, arg : string, o : unitptr);</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''c'''
 +
<!--DEFINITION-->        the command string that is sending the message
 +
<!--TERM-->  '''a'''
 +
<!--DEFINITION-->        the unitptr (activator) that activated the message
 +
<!--TERM-->  '''m'''
 +
<!--DEFINITION-->        the unitptr (medium) that the Dil is acting through
 +
<!--TERM-->  '''t'''
 +
<!--DEFINITION-->        the unitptr (target) the Dil is acting on
 +
<!--TERM-->  '''p'''
 +
<!--DEFINITION-->        the power of the message
 +
<!--TERM-->  '''arg'''
 +
<!--DEFINITION-->        the argument sent with the message
 +
<!--TERM-->  '''o'''
 +
<!--DEFINITION-->        the unitptr (other) you also want the message to go to
 +
 +
 +
 +
New Function send_pre() takes same arguments as send_done but returns either
 +
  SFR_SHARE or SFR_BLOCK.
 +
  If the command is blocked by another special or dil, then SFB_BLOCK will be returned,
 +
  and you should quit your dil.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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!&amp;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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bpset" />
 +
set ( var i : integer , bit : integer )
 +
    i : Integer variable to alter.
 +
    bit : Bits to set in integer variable.
 +
    result: Sets bits in 'i'
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bpunset" />
 +
unset ( var i : integer , bit : integer )
 +
    i : Integer variable to alter.
 +
    bit : Bits to unset in integer variable.
 +
    result: unset bits in 'i'.
 +
 +
 +
<!--LINK--><span id="bpaddcolor" />
 +
 +
'''Function:  '''<i><!--CODE-->addcolor (ch : unitptr, ks : string, cstr : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''ch'''
 +
<!--DEFINITION-->        character you are adding the color to
 +
<!--TERM-->  '''ks'''
 +
<!--DEFINITION-->        key string for the color
 +
<!--TERM-->  '''cstr'''
 +
<!--DEFINITION-->        color string
 +
 +
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.
 +
'''Function:  '''<i><!--CODE-->addcolor(pc, "clan_who","&amp;c+w&amp;bn");</i><!--ENDCODE-->
 +
 +
 +
<!--LINK--><span id="bpdelcolor" />
 +
 +
'''Function:  '''<i><!--CODE-->delcolor (ch : unitptr, ks : string) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''ch'''
 +
<!--DEFINITION-->        character you are deleting the color from
 +
<!--TERM-->  '''ks'''
 +
<!--DEFINITION-->        key string for the color
 +
 +
This function is used to delete any colors from a players personal color list.
 +
'''Function:  '''<i><!--CODE-->delcolor(pc, "clan_who");</i><!--ENDCODE-->
 +
 +
<!--LINK--><span id="bfgcolor" />
 +
 +
'''Function:  '''<i><!--CODE--> string getcolor (ch : unitptr, ks : string) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''ch'''
 +
<!--DEFINITION-->        character you are deleting the color from
 +
<!--TERM-->  '''ks'''
 +
<!--DEFINITION-->        key string for the color
 +
<!--TERM-->  '''returns'''
 +
<!--DEFINITION-->        returns the color in a string
 +
 +
This function returns what color a player has for a key in the players list.
 +
'''Function:  '''<i><!--CODE-->string := getcolor(pc, "clan_who");</i><!--ENDCODE-->
 +
 +
<!--LINK--><span id="bpchangecolor" />
 +
 +
'''Function:  '''<i><!--CODE-->changecolor (ch : unitptr, ks : string, cstr : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''ch'''
 +
<!--DEFINITION-->        character you are changing the color on
 +
<!--TERM-->  '''ks'''
 +
<!--DEFINITION-->        key string for the color
 +
<!--TERM-->  '''cstr'''
 +
<!--DEFINITION-->        color string
 +
 +
This will change a color in a players personal list.
 +
'''Function:  '''<i><!--CODE-->changecolor(pc, "clan_who","&amp;c+w&amp;bn");</i><!--ENDCODE-->
 +
 +
<!--LINK--><span id="bpgamestate" />
 +
 +
'''Function:  '''<i><!--CODE-->  gamestate( u : unitptr, gs : integer ); </i><!--ENDCODE-->
 +
Change the gamestate of a unitptr, uses the GS_ defines from the
 +
'''vme.h'''. 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.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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.&amp;n", tgt);
 +
      else
 +
        sendtext(self.name+" has entered the world.&amp;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+"&amp;n&amp;n", self);
 +
 +
}
 +
 +
err := loadstr("welcome",welcome);
 +
if(welcome)
 +
        welcome := textformat(welcome);
 +
 +
if (self.level &lt; 200)
 +
{
 +
 +
login_modify(self);
 +
dilcopy ("clan_delete@clans",self);
 +
dilcopy ("clan_clear@clans",self);
 +
 +
 +
if(err > 0)
 +
        sendtext("&amp;n"+welcome+"&amp;n&amp;n", self);
 +
  informer();
 +
  exec("look", self);
 +
  quit;
 +
}
 +
gamestate(self, GS_MENU);
 +
 +
: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);
 +
 +
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;
 +
}
 +
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
Look in '''vme.h''' for the possible values you can send to the menu
 +
function.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
<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");
 +
    ...
 +
    ...
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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'.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
<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");
 +
    ...
 +
    ...
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bpsubs" />
 +
substring ( var l : stringlist, s : string )
 +
    l : Stringlist to remove string from.
 +
    s : String to remove
 +
    result: Removes string 's' from stringlist 'l'.
 +
 +
 +
 +
<!--LINK--><span id="bpstopfighting" />
 +
 +
'''Function:'''  <i><!--CODE-->stop_fighting( ch: unitptr, vict : unitptr ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''ch'''
 +
<!--DEFINITION-->        unitptr - person you are stoping the fighting for
 +
<!--TERM-->  '''vict'''
 +
<!--DEFINITION-->        unitptr - person you are removing from the fighting or null for everyone
 +
 +
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.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
dilbegin stop_combat();
 +
code
 +
{
 +
stop_fighting(self,null);
 +
quit;
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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'.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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
 +
 +
<!--LINK--><span id="bpdest" />
 +
 +
'''Function:'''  <i><!--CODE-->destroy ( u : unitptr );</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->         :Unit to remove from game
 +
 +
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.
 +
'''Example'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bpwalkto" />
 +
walkto ( u : unitptr )
 +
    u : Room to walk to.
 +
    result: Makes unit (self) walk to room, taking a 'step' at each 'tick'.
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
  walkto(findroom("inn@udgaard"));</nowiki>
small_item
+
title "a small item"
+
---~---~---~---~---~---~---~---~---
names {"small","item","small item"}
+
<!--LINK--><span id="bplink" />
 
+
link ( u : unitptr, t : unitptr )
</nowiki>
+
    u : Unit to link.
+
    t : Unit to link into.
<PARA>When you try to <command>give small item Bill</command>. The interpreter
+
    result: Link a unit into another unit hierarchy. (Automatically
would try to give
+
            unequipps if equipped).
small to item and that would not be what you wanted to doDon't
+
worry the compiler will catch this and give you an error something
+
like:
+
<!--LINK--><span id="bfweapon_name" />
<computeroutput>
+
 
+
'''Function:'''  <i><!--CODE-->string weapon_name( i : integer ) ;</i><!--ENDCODE-->
Fatal name ordering on line ###.
+
 
+
<!--TERM-->  '''i'''
</computeroutput></PARA>
+
<!--DEFINITION-->        Weapon to get the name of ass defined in 'values.h' and 'weapons.def'
</LISTITEM>
+
<!--TERM-->  '''returns'''
</VARLISTENTRY>
+
<!--DEFINITION-->        The name of the weapon that corresponds with the integer value
 
+
<VARLISTENTRY>
+
'''example:'''
;descr field
+
<i><!--CODE-->
<DICTDEF>
+
---~---~---~---~---~---~---~---~---
<PARA>
+
 
+
myweap:=weapon_name(5);
The description building block is used in many placesYou 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.</PARA>
+
</i><!--ENDCODE-->
 
+
<PARADepending on what
+
<!--LINK--><span id="bfweapon_info" />
you are working on description fields can mean totally different
+
things to the person looking in the roomA description field on a
+
'''Function:'''  <i><!--CODE-->intlist weapon_info( i : integer ) ;</i><!--ENDCODE-->
room can be the inside or outside of the rooms descriptionA
+
description on extras can be an NPCs descr or an extra description
+
<!--TERM-->  '''i'''
on the room like if you looked at a 'rug' or a 'chair'.  On an exit
+
<!--DEFINITION-->        Weapon to get the info of ass defined in 'values.h' and 'weapons.def'
the descr field describes what you see when you look in that
+
<!--TERM-->  '''returns'''
direction from the room you are in.  The important thing right now
+
<!--DEFINITION-->        Intlist containing 4 values:
is no matter where you use them they all work the same.</PARA>
+
 
+
<!--TERM-->  '''0'''
<PARA>description fields like the title field have a tag or unlike
+
<!--DEFINITION-->        Number of hands
the title field can have a set of tags before them like in extras or
+
<!--TERM-->  '''1'''
exits but like titles they are just a string surrounded by quotes.
+
<!--DEFINITION-->        weapon speed
You can make multiple line descriptions if the description is on a
+
<!--TERM-->  '''2'''
NPC you may not want to since it is the description shown when you
+
<!--DEFINITION-->        weapon type
walk into the roomThe following would be some examples of room descriptions.</PARA>
+
<!--TERM-->  '''3'''
 
+
<!--DEFINITION-->        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'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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])+"&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);
 +
}
 +
 +
quit;
 +
}
 +
dilend
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
 +
<!--LINK--><span id="bfskill_name" />
 +
 +
'''Function:'''  <i><!--CODE-->string skill_name( i : integer ) ;</i><!--ENDCODE-->
 +
   
 +
<!--TERM-->  '''i'''
 +
<!--DEFINITION-->        Skill to get the name of ass defined in 'values.h' and 'commands.def'
 +
<!--TERM-->  '''returns'''
 +
<!--DEFINITION-->        The name of the skill that corresponds with the integer value
 +
 +
'''example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
myski:=skill_name(5);
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
<!--LINK--><span id="bpreboot" />
 +
 +
'''Function:  '''<i><!--CODE-->reboot ;</i><!--ENDCODE-->
 +
This function works like a quit command.  Anything after the reboot function in a Dil will not be
 +
executed the mud will reboot instantlyThe zone must have root privileges in
 +
the zonelist in order to use this function.
 +
'''Simple reboot command'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
dilbegin cmd_reboot (arg:string);
 +
code
 +
{
 +
sendtext ("Rebooting the mud.&amp;n",self);
 +
reboot;
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
<!--LINK--><span id="bpkilledit" />
 +
 +
'''Function:  '''<i><!--CODE-->killedit ;</i><!--ENDCODE-->
 +
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'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bpact" />
 +
 +
The purpose of act is to send a message to a number of players '''present''' 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.)
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
'''Syntax:'''
 +
   
 +
act(message, visibility, char, medium, victim, to_whom);
 +
 +
 +
<!--TERM--> '''message'''
 +
<!--DEFINITION-->          - is a string that will be shown to other mobiles when the act is executed. To refer to the following arguments use the [[#formatters|formatters]] listed below.
 +
<!--TERM--> '''visibility'''
 +
<!--DEFINITION-->          - is an integer that defines what happens if the mobile that is about to receive the message can't see the activator.
 +
<!--TERM-->        <b><!--CODE-->A_SOMEONE</b><!--ENDCODE-->
 +
<!--DEFINITION-->                If the receiver cannot see char, replace any reference to char with <i>someone</i>.
 +
<!--TERM-->        <b><!--CODE-->A_HIDEINV</b><!--ENDCODE-->
 +
  <!--DEFINITION-->                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.
 +
<!--TERM-->        <b><!--CODE-->A_ALWAYS</b><!--ENDCODE-->
 +
<!--DEFINITION-->                Works exactly like <i><!--CODE-->A_SOMEONE</i><!--ENDCODE-->, except that the receiver will see the message even when sleeping.
 +
<!--TERM--> '''char'''
 +
<!--DEFINITION-->          - 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.
 +
<!--TERM--> '''medium'''
 +
  <!--DEFINITION-->          - is a unit pointer, an integer or a string. Use this at your leisure.
 +
<!--TERM--> '''victim'''
 +
<!--DEFINITION-->          - is a unit pointer, an integer or a string. Certain flags in the next argument rely on the validity of victim.
 +
<!--TERM--> '''to_whom'''
 +
<!--DEFINITION-->          - is an integer that defines who gets the message.
 +
<!--TERM-->        <b><!--CODE-->TO_ROOM</b><!--ENDCODE-->
 +
<!--DEFINITION-->                Sends the message to the entire room, excluding 'char'.
 +
  <!--TERM-->        <b><!--CODE-->TO_VICT</b><!--ENDCODE-->
 +
<!--DEFINITION-->                Sends to 'victim' only. 'victim' must be valid, naturally.
 +
<!--TERM-->        <b><!--CODE-->TO_NOTVICT</b><!--ENDCODE-->
 +
<!--DEFINITION-->                Sends the message to the entire room, excluding 'char' and 'victim'.  Perfect for bystanders in a melee.
 +
<!--TERM-->        <b><!--CODE-->TO_CHAR</b><!--ENDCODE-->
 +
<!--DEFINITION-->                Sends the message to 'char' and no one else.
 +
<!--TERM-->        <b><!--CODE-->TO_ALL</b><!--ENDCODE-->
 +
<!--DEFINITION-->                Sends the message to everybody in the room.
 +
<!--TERM-->        <b><!--CODE-->TO_REST</b><!--ENDCODE-->
 +
<!--DEFINITION-->                This is a bit different from the rest.  In sends the message to all other units in the local environment, excluding those inside 'char'.
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
<!--LINK--><span id="formatters" />'''Act Formatters'''
 +
   
 +
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:
 +
 +
<!--TERM--> '$$'
 +
<!--DEFINITION-->        will be sent to the receiver as a single `$'
 +
 +
'$', followed by a number and an extra character.
 +
  '''The numbers:'''
 +
 +
<!--TERM--> '1'
 +
<!--DEFINITION-->          means this formatter refers to the 'char' argument.
 +
<!--TERM--> '2'
 +
<!--DEFINITION-->         means this formatter refers to the 'medium' argument.
 +
<!--TERM--> '3'
 +
<!--DEFINITION-->         means this formatter refers to the 'victim' argument.
 +
 +
    '''The characters'''
 +
 +
<!--TERM--> 'N'
 +
<!--DEFINITION-->          the formatter will be replaced with the name of the unit, or (depending on the visibility) 'something' or 'someone'.
 +
<!--TERM--> 'a'
 +
<!--DEFINITION-->        'a' or 'an' depending on the name of the unit referred by the number.
 +
<!--TERM--> 'e'
 +
<!--DEFINITION-->        'it', 'he' or 'she' depending on the gender of the unit referred by the number.
 +
<!--TERM--> 'm'
 +
<!--DEFINITION-->        'it', 'him' or 'her' depending on the gender of the unit referred by the number.
 +
<!--TERM--> 'n'
 +
<!--DEFINITION-->          the formatter will be replaced with the title of the unit, or (depending on the visibility) 'something' or 'someone'.
 +
<!--TERM--> 'p'
 +
<!--DEFINITION-->        'fighting', 'standing', 'sleeping', etc., depending on the positionof the unit referred by the number.
 +
  <!--TERM--> 's'
 +
<!--DEFINITION-->        'its', 'his' or 'her' depending on the gender of the unit referred by the number.
 +
<!--TERM--> 't'
 +
<!--DEFINITION-->         the string in the argument referred by the number.
 +
 +
 +
 +
'''Example:'''
 +
 
  <nowiki>
 
  <nowiki>
 
+
descr
+
  act("You step over $2n.", A_SOMEONE, self, litter, null, TO_CHAR);
"this is how you would define a room descr and as you can see it can
+
  act("$1n steps over $2n.", A_SOMEONE, self, litter, null, TO_REST);</nowiki>
be much longer than a line if you like."
+
 
+
extra {"basic extra"}
+
'''See Also:'''
"This is a description field on an extra."
+
  [[#act.html|DIL Act() for Dummies]]
 
+
extra{"more advanced","extra"}{1,2,3,4,5,6}
+
---~---~---~---~---~---~---~---~---
"This is still the description field. Like the room description or
+
<!--LINK--><span id="bpexec" />
any description field for that matter this can be longer than a
+
exec ( s : string , u : unitptr )
line."
+
    s : Command and arguments to perform.
 
+
    u : Unit to perform command.
east to bathroom descr
+
    result: Unit (PC/NPC) executes command. The argument is treated just as
"You see one big toilet!";
+
            if a normal PC entered a command at the command prompt in the
 
+
            game. It is not directly possible to detect whether the command
</nowiki>
+
            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
</LISTITEM>
+
            notified the normal way. Plenty of examples are given above.
</VARLISTENTRY>
+
 
+
---~---~---~---~---~---~---~---~---
<VARLISTENTRY>
+
<!--LINK--><span id="bpwait" />
;extra fields
+
wait ( i : integer , dilexp )
<DICTDEF>
+
    i : Message class to accept, see SFB_* in values.h and/or vme.h
<PARA>
+
    dilexp : Expression that has to be TRUE or not null to accept message.
 
+
    result: Waits for a command, matching the flagset, and satisfies the
The extra field is the work horse for the builderIt is the
+
            expression. When using the 'wait()' command, the first argument
building block that most brings your zone to lifeYou can use it
+
            is an integer, that tells what classes of messages to wait for.
to describe body parts or items in a roomWhen you use
+
            Each message class is represented by a bit named as described in
<ACRONYM>DIL</ACRONYM> you will use extras to store information like quest information
+
            the chapter on messages.
or special information you need laterExtras also store the
+
'''Example:'''
main description on NPCs since the descr field on NPCs is really the
+
long title shown in the room which will be explained later
+
    wait (SFB_TICK|SFB_MSG, TRUE)
in <xref linkend="ch-05">.</PARA>
+
    /* Will accept a message, either from another DIL program or a
 
+
      timer message. As the second argument is always TRUE, any
<PARA>The extra Is the first structure definition you have run into
+
      such message will reactivate the DIL program.
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
+
'''Example:'''
extra, the second is a stringlist, the third is an Optional
+
Intlist, and the final one is the extra description fieldIf the extra
+
  wait (SFB_CMD, command("transmutate"))
had all the fields it would look like this:</PARA>
+
  /* 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).
 +
  */
 +
 +
 +
<!--LINK--><span id="bfsavestr" />
 +
 +
'''Function:'''  <i><!--CODE-->integer savestr( filename : string , buff : string , wa :string);</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''filename'''
 +
<!--DEFINITION-->        The name of the String file to save the String to
 +
<!--TERM-->  '''buff'''
 +
<!--DEFINITION-->        The String you wish to save into the file
 +
<!--TERM-->  '''wa'''
 +
<!--DEFINITION-->        Write or append
 +
<!--TERM-->  '''Return'''
 +
<!--DEFINITION-->        <i><!--CODE-->FILE_SAVED, FILE_NOT_SAVED, FILE_NOT_CREATED, or FILE_ILEGAL_OPP</i><!--ENDCODE-->
 +
 +
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.
 +
'''Note:'''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.
 +
'''Disk access is always slow'''.
 +
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.
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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.[&amp;]n",self);
 +
quit;/*dil save routine done destroy self.*/
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''See Also''' <i><!--CODE-->
 +
[[#bfdelstr|Delete a String file]] and
 +
[[#bfloadstr|Load a String file]]</i><!--ENDCODE-->
 +
 +
 +
 +
<!--LINK--><span id="bpremove" />
 +
 +
'''Function:'''  <i><!--CODE-->remove( sl : stringlist, i : integer ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''sl'''
 +
<!--DEFINITION-->        the stringlist you are removing from
 +
<!--TERM-->  '''i'''
 +
<!--DEFINITION-->        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:  '''<i><!--CODE-->remove (sl, i);</i><!--ENDCODE-->
 +
 +
 +
<!--LINK--><span id="bpresetlevel" />
 +
 +
'''Function:'''  <i><!--CODE-->reset_level( u : unitptr ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->        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:  '''<i><!--CODE-->reset_level (u);</i><!--ENDCODE-->
 +
'''See Also'''
 +
<i><!--CODE-->
 +
[[#bpresetvlevel|reset a players virtual level]] and
 +
[[#bpresetrace|reset a players race information]]</i><!--ENDCODE-->
 +
 +
 +
<!--LINK--><span id="bpresetvlevel" />
 +
 +
'''Function:'''  <i><!--CODE-->reset_vlevel( u : unitptr ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->        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:  '''<i><!--CODE-->reset_vlevel (u);</i><!--ENDCODE-->
 +
'''See Also'''
 +
<i><!--CODE-->
 +
[[#bpresetlevel|reset a players level]] and
 +
[[#bpresetrace|reset a players race information]]</i><!--ENDCODE-->
 +
 +
<!--LINK--><span id="bpresetrace" />
 +
 +
'''Function:'''  <i><!--CODE-->reset_race( u : unitptr ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''u'''
 +
<!--DEFINITION-->        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:  '''<i><!--CODE-->reset_race (u);</i><!--ENDCODE-->
 +
'''See Also'''
 +
<i><!--CODE-->
 +
[[#bpresetlevel|reset a players level]] and
 +
[[#bpresetvlevel|reset a players virtual level]]</i><!--ENDCODE-->
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
<!--LINK--><span id="bfunitdir" />
 +
 +
'''Function:'''  <i><!--CODE-->stringlist unitdir( match : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''match'''
 +
<!--DEFINITION-->        The wild card file you want to match or '*' for all.
 +
<!--TERM-->  '''return'''
 +
<!--DEFINITION-->        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.
 +
 +
<!--TERM-->  '''&ast;'''
 +
<!--DEFINITION-->        Match any character or group of characters
 +
<!--TERM-->  '''&quest;'''
 +
<!--DEFINITION-->         Match one of any character
 +
<!--TERM-->  '''[...]'''
 +
<!--DEFINITION-->         Match one of a set of characters
 +
 +
'''Example:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
"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
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
'''Example DIL:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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&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;
 +
        }
 +
 +
quit;
 +
}
 +
dilend
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
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.
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bpunsec" />
 +
unsecure ( u : unitptr )
 +
    u : Secured unit.
 +
    result: Drop secure on a given unit.
 +
 +
---~---~---~---~---~---~---~---~---
 +
  <!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bpnopri" />
 +
nopriority
 +
    result: Cancels the priority procedure.
 +
 +
---~---~---~---~---~---~---~---~---
 +
  <!--LINK--><span id="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
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bpuneq" />
 +
unequip ( u : unitptr )
 +
    u : Unit to unequip.
 +
    result: Unequipes unit presumed to be in equipment of PC/NPC.
 +
 +
 +
<!--LINK--><span id="bpdp" />
 +
 +
'''Function:'''  <i><!--CODE-->delete_player( s : string ) ;</i><!--ENDCODE-->
 +
 +
<!--TERM-->  '''s'''
 +
<!--DEFINITION-->        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:'''
 +
<i><!--CODE-->
 +
---~---~---~---~---~---~---~---~---
 +
 +
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'&amp;n",self);
 +
                quit;
 +
                }
 +
 +
err:=loadstr("delete.txt",temp);
 +
 +
if (err&lt;1)
 +
        goto no_insure;
 +
 +
sendtext (temp,self);
 +
 +
sendtext ("If your sure you still want to delete your character, 'say delete me'&amp;n",self);
 +
sendtext ("Doing anything else will abort the deletion.&amp;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&amp;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.&amp;n",self);
 +
quit;
 +
}
 +
 +
if (arg==self.name){
 +
sendtext ("To delete self you need to type 'delete self forever'&amp;n",self);
 +
quit;
 +
}
 +
 +
if (not isplayer(arg))
 +
        {
 +
        sendtext (arg+" is not a character.&amp;n",self);
 +
        quit;
 +
        }
 +
dilcopy ("god_delete@clans("+arg+")",self);
 +
 +
        sendtext (arg+" has been deleted.&amp;n",self);
 +
quit;
 +
}
 +
dilend
 +
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
 +
</i><!--ENDCODE-->
 +
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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'.
 +
 +
  ---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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).
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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'.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="bplog" />
 +
log( s : string )
 +
    s : Text to put in the log.
 +
    result: Puts text in the log for debugging purposes.
 +
 +
  ---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
  ---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
'''Example:'''
 +
 +
    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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
'''Example:'''
 +
 +
    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.
 +
 +
---~---~---~---~---~---~---~---~---
 +
<!--LINK--><span id="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.
 +
 +
    '''Example:'''
 +
 +
    %dil
 +
 
  <nowiki>
 
  <nowiki>
 
+
extra {"small chair","chair"} {1,2,3,4,5} "Its a chair."
+
    dilbegin myeffect(medi : unitptr, targ : unitptr, hm : integer);
 
+
    code
</nowiki>
+
    {
+
      act("The caster is $1N medium is $2N and target is $3N",
<PARA>If the previous wasn't an example we
+
          A_ALWAYS, self, medi, targ, TO_ALL);
would have left out the Intlist because it is not necessary to put
+
      act("The spell result is $2d", A_ALWAYS, self, hm, null, TO_ALL);
the Intlist on a chair unless you want it there for some special <ACRONYM>DIL</ACRONYM>
+
      quit;
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
+
    dilend</nowiki>
to make the extra the default description when the object, room, or
+
NPC is being looked at, like this:</PARA>
+
    .....
+
 +
    %...
 +
 
  <nowiki>
 
  <nowiki>
 
+
extra {}
+
    dilbegin test();
"This would be what you see when you look at any of the names in the
+
    var
names list."
+
      n : integer;
 
+
    code
</nowiki>
+
    {
+
      wait(SFB_DONE, command("beg"));
<PARA>We will go more in-depth into why you want to do this in the
+
following chapters.
+
      n := cast_spell(SPL_FIREBALL_1, self, self, activator, "myeffect@wiz");
</PARA></LISTITEM>
+
   
</VARLISTENTRY>
+
      exec("say Result of spell was "+itoa(n), self);
</VARIABLELIST>
+
    }
 
+
    dilend</nowiki>
<PARA>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.</PARA>
+
<!--LINK--><span id="bpatt_s" />
 
+
integer attack_spell( n : integer, caster : unitptr, medium : unitptr,
</chapter>
+
                      target : unitptr, bonus : integer)
 
+
    Returns : The amount of damage given.
<chapter ID="ch-04"><?dbhtml filename="ch04.html">
+
    n : The spell index of the offensive spell (SPL_XXX)
<TITLE>The room section</TITLE>
+
    caster : The caster of the spell.
 
+
    medium : The medium, with which the spell is cast, might be caster.
<PARA> The previous chapter gave you the basic building blocks that
+
    target : The target of the spell.
will be used all through creating rooms, NPCs, and objects. If you
+
    bonus  : Possible (+) advantage or (-) penalty.
jumped straight to this chapter without reading about the general
+
   
building blocks you might want to return to <XREF LINKEND="ch-03">
+
    This is low-level internal spell stuff used to develop new spells. Do not
first. This chapter will deal with all the fields
+
    use unless you know what you are doing and have been allowed to do so by
of rooms what they are and how to use them but with out the previous
+
    your Admin.
chapter you may get lost.</PARA>
+
 
+
<PARA>In order to get started building rooms you should first be aware
+
   
of the room fields you can use. The <xref linkend="rmfields"> shows a full listing
+
    <!--LINK--><span id="bpinsert" />
of all the room fields and their types as defined in <xref linkend="ch-03">.</PARA>
+
 
+
'''Function:  '''<i><!--CODE-->insert( sl : &lt;stringlist or intlist&gt;, i : integer, s : string ) ;</i><!--ENDCODE-->
<TABLE frame=all  id="rmfields">
+
<TITLE>Room fields and types listing</TITLE>
+
<!--TERM--> '''sl'''
<TGROUP align=left cols=5 colsep=1>
+
<!--DEFINITION-->         the stringlist or intlist you are inserting to
<COLSPEC COLNAME="c1" COLWIDTH="2in">
+
<!--TERM--> '''i'''
<COLSPEC COLNAME="c2" COLWIDTH="2in">
+
<!--DEFINITION-->         the index where you want to insert the string
<COLSPEC COLNAME="c3" COLWIDTH=".5in">
+
<!--TERM--> '''s'''
<COLSPEC COLNAME="c4" COLWIDTH="2in">
+
<!--DEFINITION-->         the string you want to insert
<COLSPEC COLNAME="c5" COLWIDTH="2in">
+
 
+
This function allows you to insert a string in a stringlist or intlist
<THEAD>
+
with out re-writing the entire stringlist or intlist to do it.  The
<ROW>
+
following Dil will add a string in order to a stringlist.
<ENTRY COLNAME="c1">Field</ENTRY>
+
'''Example:'''
<ENTRY COLNAME="c2">Type</ENTRY>
+
<i><!--CODE-->
<entry></entry>
+
---~---~---~---~---~---~---~---~---
<ENTRY COLNAME="c4">Field</ENTRY>
+
<ENTRY COLNAME="c5">Type</ENTRY>
+
dilbegin stringlist add_in_order (sl:stringlist,s:string);
</ROW>
+
var
</THEAD>
+
  i:integer;
<TBODY>
+
  ln:integer;
               
+
code
<ROW>
+
{
<ENTRY COLNAME="c1">symbolic name</ENTRY>
+
if (length(sl)==0)
<ENTRY COLNAME="c2">Symbol</ENTRY>
+
  {
<ENTRY morerows=9 colname="c3"></ENTRY>
+
  addstring (sl,s);
 
+
  return (sl);
<ENTRY COLNAME="c4">manipulate</ENTRY>
+
  }
<ENTRY COLNAME="c5">Integer</ENTRY>
+
</ROW>
+
ln:=length(s);
 
+
i:=0;
<ROW>
+
while (i&lt;ln)
<ENTRY COLNAME="c1">names</ENTRY>
+
  {
<ENTRY COLNAME="c2">Stringlist</ENTRY>
+
  if (length(sl.[i]) &lt;=ln)
 
+
  {
<ENTRY COLNAME="c4">alignment</ENTRY>
+
  insert (sl,i,s);
<ENTRY COLNAME="c5">Integer</ENTRY>
+
  return(sl);
</ROW>
+
  }
 
+
  i:=i+1;
<ROW>
+
  }
<ENTRY COLNAME="c1">title</ENTRY>
+
<ENTRY COLNAME="c2">String</ENTRY>
+
addstring (sl,s);
 
+
return (sl);
<ENTRY COLNAME="c4">flags</ENTRY>
+
}
<ENTRY COLNAME="c5">Integer</ENTRY>
+
dilend
</ROW>
+
 
+
---~---~---~---~---~---~---~---~---
<ROW>
+
<ENTRY COLNAME="c1">descr</ENTRY>
+
</i><!--ENDCODE-->
<ENTRY COLNAME="c2">String</ENTRY>
+
 
+
<ENTRY COLNAME="c4">weight</ENTRY>
+
<ENTRY COLNAME="c5">Integer</ENTRY>
+
---~---~---~---~---~---~---~---~---
</ROW>
+
<!--LINK--><span id="bpinterr" />
 
+
integer interrupt( flags : integer, dilexp, label )
<ROW>
+
<ENTRY COLNAME="c1">outside_descr</ENTRY>
+
    Set up interrupt matching message classes matching "flags",
<ENTRY COLNAME="c2">String</ENTRY>
+
    for example "SFB_COM" or "SFB_COM | SFB_MSG".
 
+
<ENTRY COLNAME="c4">capacity</ENTRY>
+
    When the program is activated on either of the specified conditions
<ENTRY COLNAME="c5">Integer</ENTRY>
+
    the 'dilexp' is evaluated. If true, then execution continues at 'label',
</ROW>
+
    otherwise the next interrupt is checked (if any).
 
+
   
<ROW>
+
    Interrupts are saved (restored), when 'recall' is set.
<ENTRY COLNAME="c1">extra</ENTRY>
+
    Returns an integer which is used for clear() to clear an interrupt.
<ENTRY COLNAME="c2">Structure</ENTRY>
+
 
+
'''Example:'''
<ENTRY COLNAME="c4">light</ENTRY>
+
<ENTRY COLNAME="c5">Integer</ENTRY>
+
The following program shows, that the owner (self) of the program keeps
</ROW>
+
snoring while sleeping. The on_activation ensures that the program
 
+
is only activated when the owner is sleeping. However, since the interrupt
<ROW>
+
precede the on_activation, these may still be intercepted before the
<ENTRY COLNAME="c1">minv</ENTRY>
+
on_activation. The on_activation is just another type of interrupt that
<ENTRY COLNAME="c2">Integer</ENTRY>
+
reacts on all flags (without actually setting them so that the program
 
+
is activated).
<ENTRY COLNAME="c4">exit</ENTRY>
+
<ENTRY COLNAME="c5">Structure</ENTRY>
+
When the program receives the message "relief" the snoring stops briefly.
</ROW>
+
As used, "relief" may only be set once.
 
+
<ROW>
+
When the program receives the message "cured", the snoring stops completely
<ENTRY COLNAME="c1">key</ENTRY>
+
(i.e. the program quits itself).
<ENTRY COLNAME="c2">string</ENTRY>
+
   
 
 
<ENTRY COLNAME="c4">movement</ENTRY>
 
<ENTRY COLNAME="c5">Integer</ENTRY>
 
</ROW>
 
 
 
<ROW>
 
<ENTRY COLNAME="c1">spell</ENTRY>
 
<ENTRY COLNAME="c2">Integer</ENTRY>
 
 
 
<ENTRY COLNAME="c4">end</ENTRY>
 
<ENTRY COLNAME="c5">Symbol</ENTRY>
 
</ROW>
 
 
 
<ROW>
 
<ENTRY COLNAME="c1">dilbegin or dilcopy</ENTRY>
 
<ENTRY COLNAME="c2">Function pointer</ENTRY>
 
 
 
<ENTRY COLNAME="c4"></ENTRY>
 
<ENTRY COLNAME="c5"></ENTRY>
 
</ROW>
 
</TBODY>
 
</TGROUP>
 
</TABLE>
 
 
 
 
 
<PARA>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 roomsIn <xref linkend="
 
rmfielddescr"> we will expand your knowledge from just knowing what the
 
field types are to how to set them as well.</PARA>
 
 
 
<sect1 id="rmfielddescr">
 
<TITLE>Description of room fields</TITLE>
 
 
 
<variablelist id="var-rmfields">
 
<VARLISTENTRY>
 
;symbolic name
 
<DICTDEF>
 
<PARA>
 
 
 
The rules of the symbols has been explained in <XREF
 
LINKEND="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
 
<command>goto</command> and the <command>wstat</command> to easily
 
goto the room in question.
 
</PARA></LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;title
 
<DICTDEF>
 
<PARA>
 
 
 
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 endThe following are good examples of a room title.</PARA>
 
 
 
  <nowiki>
 
  <nowiki>
 
+
title "The Post Office"
+
dilbegin
title "The deep dark jungle floor:"
+
title "The Dragon Station control room"
+
var
 
+
    i : integer;
</nowiki>
+
+
code
<PARA>It is really up to you weather you want to use punctuation or not, it
+
{
is more administrator personal opinion than anything.
+
  /* Notice that the sequence in which the interrupts (and the on_activation)
</PARA></LISTITEM>
+
    are executed, is quite important: You can be cured at *any* time. The
</VARLISTENTRY>
+
    program will skip if you are not sleeping. If you
<VARLISTENTRY>
 
;names
 
<DICTDEF>
 
<PARA>
 
 
 
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 <ACRONYM>DIL</ACRONYM> 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.</PARA>
 
 
<nowiki>
 
 
 
title "The Post Office"
 
Names {"post office","office"}
 
 
 
title "the thrown room"
 
names {"thrown room","thrown"}
 
 
 
</nowiki>
 
 
</LISTITEM>
 
  </VARLISTENTRY>
 
<VARLISTENTRY>
 
;descr
 
<DICTDEF>
 
<PARA>
 
 
 
The description field is what the player sees when walking into the room or
 
when looking with no arguments.
 
</PARA></LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;outside_descr
 
<DICTDEF>
 
<PARA>
 
 
 
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:</PARA>
 
 
<nowiki>
 
 
 
outside_descr "a big old barrel is laying here on its side."
 
 
 
</nowiki>
 
 
<PARA>This allows a builder to make a room that looks like an object
 
inside another room.
 
</PARA></LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;movement
 
<DICTDEF>
 
<PARA>
 
 
 
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.
 
<TABLE frame=all id="sectors">
 
<TITLE>Sector movement values</TITLE>
 
<TGROUP align=left cols=3 colsep=1>
 
<THEAD>
 
<ROW>
 
<ENTRY>Symbol</ENTRY>
 
<ENTRY>Name</ENTRY>
 
<ENTRY>Endurance Cost</ENTRY>
 
</ROW>
 
</THEAD>
 
<TBODY>
 
 
 
<ROW>
 
<ENTRY>SECT_INSIDE</ENTRY>
 
<ENTRY>inside</ENTRY>
 
<ENTRY>1</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_CITY</ENTRY>
 
<ENTRY>city</ENTRY>
 
<ENTRY>1</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_FIELD</ENTRY>
 
<ENTRY>field</ENTRY>
 
<ENTRY>2</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_FOREST</ENTRY>
 
<ENTRY>forest</ENTRY>
 
<ENTRY>3</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_HILLS</ENTRY>
 
<ENTRY>hills</ENTRY>
 
<ENTRY>4</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_MOUNTAIN</ENTRY>
 
<ENTRY>mountain</ENTRY>
 
<ENTRY>6</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_DESERT</ENTRY>
 
<ENTRY>desert</ENTRY>
 
<ENTRY>8</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_SWAMP</ENTRY>
 
<ENTRY>swamp</ENTRY>
 
<ENTRY>8</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_WATER_SWIM</ENTRY>
 
<ENTRY>water-swim</ENTRY>
 
<ENTRY>4</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_WATER_SAIL</ENTRY>
 
<ENTRY>water-sail</ENTRY>
 
<ENTRY>50</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_UNDER_WATER</ENTRY>
 
<ENTRY>under-water</ENTRY>
 
<ENTRY>8</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_SNOW</ENTRY>
 
<ENTRY>snow</ENTRY>
 
<ENTRY>8</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_SLUSH</ENTRY>
 
<ENTRY>slush</ENTRY>
 
<ENTRY>6</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>SECT_ICE</ENTRY>
 
<ENTRY>ice</ENTRY>
 
<ENTRY>10</ENTRY>
 
</ROW>
 
</TBODY></TGROUP></TABLE>
 
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:</PARA>
 
 
<nowiki>
 
 
 
movement SECT_FOREST
 
movement SECT_HILLS
 
 
 
</nowiki>
 
 
<NOTE><PARA>Only one movement is needed for a room if you put more than one
 
the last one added will be the one used.</PARA></NOTE>
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;flags
 
<DICTDEF>
 
<PARA>
 
 
 
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 flags.  Extras can also be used to create special room flags.
 
<TABLE frame=all id="unitflagsroom">
 
<TITLE>Room unit flag affects</TITLE>
 
<TGROUP align=left cols=2 colsep=1>
 
<THEAD>
 
<ROW>
 
<ENTRY>Flag</ENTRY>
 
<ENTRY>Description</ENTRY>
 
</ROW>
 
</THEAD>
 
<TBODY>
 
 
 
 
 
<ROW>
 
<ENTRY>UNIT_FL_PRIVATE</ENTRY>
 
<ENTRY>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 <command>goto</command> and direction commands are a few
 
commands that do honor this flag.</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_INVISIBLE</ENTRY>
 
<ENTRY>Makes unit invisible</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_NO_BURY</ENTRY>
 
<ENTRY>Makes a hard floor so items can't be buried.</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_BURIED</ENTRY>
 
<ENTRY>Makes unit buried when loaded</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_NO_TELEPORT</ENTRY>
 
<ENTRY>makes unit so no one can teleport to it</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_NO_MOB</ENTRY>
 
<ENTRY>Makes it so no mobile will enter the unit</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_NO_WEATHER</ENTRY>
 
<ENTRY>keeps weather and natural light out of unit</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_INDOORS</ENTRY>
 
<ENTRY>Makes unit inside and doesn't affect weather</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_TRANS</ENTRY>
 
<ENTRY>Makes unit transparent</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_NO_SAVE</ENTRY>
 
<ENTRY>Makes it so you can't save with unit</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_SACRED</ENTRY>
 
<ENTRY>Makes unit a double gain unit</ENTRY>
 
</ROW>
 
<ROW>
 
<ENTRY>UNIT_FL_MAGIC</ENTRY>
 
<ENTRY>Marks a unit to be magic</ENTRY>
 
</ROW>
 
</TBODY></TGROUP></TABLE>
 
 
 
</PARA></LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;extra
 
<DICTDEF>
 
<PARA>
 
</PARA>
 
 
 
<PARA>Extras are the work horse of the <ACRONYM>VME</ACRONYM>.  Extras are used in everything from <ACRONYM>DIL</ACRONYM> 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:</PARA>
 
 
<nowiki>
 
 
 
descr
 
"This small room houses the computer power of the <ACRONYM>VME</ACRONYM> development team.
 
All four walls are lined with various pieces of computer equipment old pizza
 
boxes and plenty of empty soda cans."
 
 
 
</nowiki>
 
 
<PARA>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 <ACRONYM>VME</ACRONYM> servers we
 
do this by adding extra descriptions to the room.  In this case the builder of the zone
 
may do something like this:</PARA>
 
 
<nowiki>
 
 
 
descr
 
"This small room houses the computer power of the <ACRONYM>VME</ACRONYM> 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 <ACRONYM>VME</ACRONYM> 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>
 
 
<PARA>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 <ACRONYM>VMC</ACRONYM> will give you a fatal error and
 
will not compile your zone.</PARA>
 
 
 
<PARA>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.</PARA>
 
 
 
<PARA>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.</PARA>
 
 
<nowiki>
 
 
 
extra {"$rockcount"}
 
"5"
 
 
 
extra {"$playerkill"}
 
"0"
 
 
 
extra {"$coke","$milk","$water"}{1,5,10}
 
"Drinks and amounts"
 
 
 
</nowiki>
 
 
<PARA>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
 
<ACRONYM>DIL</ACRONYM> coding you may not understand why you would want extras
 
players can't see.  The <ACRONYM>DIL</ACRONYM> 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 <ACRONYM>DIL</ACRONYM> 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.</PARA>
 
 
 
<PARA>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.</PARA>
 
 
 
<PARA>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.:</PARA>
 
 
<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>
 
 
<PARA>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.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;Exits
 
<DICTDEF>
 
<PARA>
 
</PARA>
 
 
 
<PARA>
 
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:</PARA>
 
 
<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>
 
 
 
 
<VARIABLELIST>
 
<VARLISTENTRY>
 
;exit &lt;directions&gt;
 
<DICTDEF>
 
<PARA>Is the direction the exit leads, ie. one of north, south ..
 
  up, down.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
                  <VARLISTENTRY>
 
    <TERM>to &lt;destinations&gt;</TERM>
 
<LISTITEM>
 
<PARA>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;</PARA>
 
 
<nowiki>
 
 
 
  to myotherroom
 
 
 
  to hisotherroom@hiszone
 
 
 
</nowiki>
 
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
                  <VARLISTENTRY>
 
    <TERM>open &lt;info flags&gt;</TERM>
 
<LISTITEM>
 
 
 
<PARA>These flags describe the state of the door.  The following is the
 
list of possible door flags.</PARA>
 
 
 
<VARIABLELIST>
 
<VARLISTENTRY>
 
;EX_OPEN_CLOSE
 
<DICTDEF>
 
<PARA> Set this if you can open and close this exit, be it a door, gate or
 
    otherwise.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;EX_CLOSED
 
<DICTDEF>
 
<PARA>Set this if you want the exit to be closed at boot time.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;EX_LOCKED
 
<DICTDEF>
 
<PARA>Set this if you want the exit to be clocked at boot time.</PARA>
 
<NOTE>
 
<PARA>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
 
    <ACRONYM>DIL</ACRONYM> with UnSet();</PARA>
 
</NOTE>
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;EX_PICK_PROOF
 
<DICTDEF>
 
<PARA>Using this flag renders the 'pick' skill and 'unlock' spell un useable on the
 
    lock of this exit.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;EX_HIDDEN
 
<DICTDEF>
 
<PARA>If this bit is set, the exit is hidden until the mobile has successfully
 
    searched for it, using the 'search'-command.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
</VARIABLELIST>
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;key &lt;keyname&gt;
 
<DICTDEF>
 
<PARA>The symbolic name of a key object used for unlocking this exit.</PARA>
 
 
<nowiki>
 
 
key mykey@myzone
 
 
</nowiki>
 
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;keyword { &lt;stringlist&gt; }
 
<DICTDEF>
 
<PARA>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.</PARA>
 
 
 
<nowiki>
 
 
keyword {"wooden door","door"}
 
 
 
keyword {"hidden door","door","hatch","floor"}
 
 
 
</nowiki>
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;descr &lt;description&gt;
 
<DICTDEF>
 
<PARA>This string is the description of what you see if you look in
 
  the direction of the exit.</PARA>
 
  </LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;;
 
<DICTDEF>
 
<PARA>Every exit statement needs to be terminated with a semi-colon.
 
</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
  </VARIABLELIST>
 
 
 
<NOTE>
 
<TITLE>General notes</TITLE>
 
<PARA>Even though you do not need an exit in all directions, you can use it to place
 
descriptions of the direction.</PARA>
 
</NOTE>
 
 
<nowiki>
 
 
 
      exit north descr "An unsurmountable mountain blocks your way.";
 
 
 
</nowiki>
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
<VARLISTENTRY>
 
;minv
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>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.</PARA>
 
 
<nowiki>
 
 
 
minv 20
 
 
 
</nowiki>
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;key
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>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.</PARA>
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;manipulate
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>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.</PARA>
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;alignment
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>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.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;weight
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>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.</PARA>
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;capacity
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>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.</PARA>
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;light
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>This field sets the light on a room.  Normally this is not done
 
directly, instead it is set using macros defined in
 
''wmacros.h''.</PARA>
 
 
 
<TABLE frame=all id="seg-light">
 
<TITLE>Light defines</TITLE>
 
<TGROUP align=left cols=3 colsep=1>
 
<THEAD>
 
<ROW>
 
<ENTRY>Define</ENTRY>
 
<ENTRY>Light Value</ENTRY>
 
<ENTRY>Affect</ENTRY>
 
</ROW>
 
</THEAD>
 
<TBODY>
 
 
 
 
 
 
 
<ROW>
 
<ENTRY>ALWAYS_LIGHT</ENTRY>
 
<ENTRY>1</ENTRY>
 
<ENTRY>Room is always light no matter time of day</ENTRY>
 
</ROW>
 
 
 
<ROW>
 
<ENTRY>IN_ALWAYS_DARK  </ENTRY>
 
<ENTRY>-1</ENTRY>
 
<ENTRY>When an inside room is always dark - both inside and outside </ENTRY>
 
</ROW>
 
 
 
<ROW>
 
<ENTRY>OUT_DARK_NON_NOON </ENTRY>
 
<ENTRY>-1</ENTRY>
 
<ENTRY>Always a dark room, except when it is high noon </ENTRY>
 
</ROW>
 
 
 
<ROW>
 
<ENTRY>OUT_ALWAYS_DARK  </ENTRY>
 
<ENTRY>-2</ENTRY>
 
<ENTRY>Always a Dark room, no matter the time of day</ENTRY>
 
</ROW>
 
 
 
</TBODY></TGROUP></TABLE>
 
 
 
<PARA>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.</PARA>
 
 
 
<PARA>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.</PARA>
 
 
<nowiki>
 
 
 
//To Set always light with macro
 
ALWAYS_LIGHT
 
 
 
//To set Always light with out macro
 
light 1
 
 
 
</nowiki>
 
 
<PARA>You can decide which is easiest for you.</PARA>
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;link
 
<DICTDEF>
 
<PARA></PARA>
 
</LISTITEM>
 
 
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;spell
 
<DICTDEF>
 
<PARA></PARA>
 
</LISTITEM>
 
 
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;dilbegin or dilcopy
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
 
 
<PARA>The <ACRONYM>DIL</ACRONYM> functions are what give <ACRONYM>VME</ACRONYM> servers the edge over all other muds.
 
We will only give some examples here and leave it up to the <ACRONYM>DIL</ACRONYM> manual to teach
 
you how to create your own functions that will make your rooms, NPC, and
 
objects more than special.</PARA>
 
 
 
<PARA>There are only currently three room functions that come
 
standard with a <ACRONYM>VME</ACRONYM> in the ''function.zon''.  There
 
are much more in the zones released with the <ACRONYM>VME</ACRONYM> 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.</PARA>
 
 
 
<PARA>Since these are just <ACRONYM>DIL</ACRONYM>'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.</PARA>
 
 
 
 
<nowiki>
 
 
 
/* Death room <ACRONYM>DIL</ACRONYM>
 
*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 (tick < 12) tick := 12;
 
 
 
heartbeat := tick;
 
 
 
if (damage < 0)
 
    damage := -damage;
 
 
 
if ("$death room for mobs" in self.extra)
 
    i := UNIT_ST_PC|UNIT_ST_NPC;
 
else
 
    i := UNIT_ST_PC;
 
 
 
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);
 
    }
 
 
 
}
 
 
 
}
 
 
 
dilend
 
 
 
</nowiki>
 
 
<PARA>If this <ACRONYM>DIL</ACRONYM> function scares you don't worry you don't have to
 
understand or adjust it you just have to use it.  In this function it requires a time,
 
damage, and act.  So you could use this in a room definition like
 
this:</PARA>
 
 
<nowiki>
 
 
 
dilcopy death@function (60,25,"Flames shoot from the floor burning
 
your rear.");
 
 
 
</nowiki>
 
 
<PARA>This says to copy the <ACRONYM>DIL</ACRONYM> from zone function with the arguments 60
 
seconds, damage 25% and act as shown.  Pretty simple eh?</PARA>
 
 
 
<PARA>All released <ACRONYM>DIL</ACRONYM> room functions are described in
 
<XREF LINKEND="rmdilfunc">.
 
Then we put some to work so you can see how
 
to use them in <XREF LINKEND="rmcomplex"></PARA>
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
</VARIABLELIST>
 
 
 
</SECT1>
 
 
 
<sect1 id="rmbasic">
 
<TITLE>Building your first room</TITLE>
 
 
 
<PARA>Now you are ready!  With all you have learned about room
 
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.</PARA>
 
 
 
<PARA>When making rooms you create the zone source file first as shown
 
in <xref linkend="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 <xref linkend="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.</PARA>
 
 
 
<PARA>The first part of all rooms is the symbolic name it is good to
 
always pick a name that will match the title so you can use the
 
administrator command <command>goto</command> to easily get to the
 
room.  The reason is when you use the command
 
<command>wstat</command> it will only show you a list of the rooms
 
by symbolic name for example if you type
 
<command>
 
wstat zone dragon room
 
</command>
 
You will get  the following:</PARA>
 
 
<nowiki>
 
 
 
List of rooms in zone Dragon:
 
chamber portal office
 
 
 
</nowiki>
 
 
<PARA>If you didn't make it clear what the rooms were by the symbolic name
 
it might look like this:</PARA>
 
 
<nowiki>
 
 
 
List of rooms in zone Dragon:
 
st_rm1 st_rm2 st_rm3
 
 
 
</nowiki>
 
 
 
 
<PARA>While this might be great when you first start imagine trying to
 
remember what all one hundred rooms are.</PARA>
 
 
 
<PARA>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.</PARA>
 
 
<nowiki>
 
 
 
chamber
 
end
 
 
 
</nowiki>
 
 
<PARA>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.</PARA>
 
 
 
 
<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>
 
 
 
<PARA>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.</PARA>
 
 
<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"}
 
"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 intelligent looking dragon is sitting perched on a large chair watching you."
 
 
 
</nowiki>
 
<PARA>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.</PARA>
 
 
<nowiki>
 
 
 
west to portal descr "You see a small room.";
 
 
 
east to office descr "You see what looks to be an office.";
 
 
 
</nowiki>
 
 
 
<PARA>Thats it that is all there is to making a room.  In the next
 
couple of sections we are going to add some more rooms with more
 
advanced features and give some debugging hints for compiling your
 
rooms but if you understand everything so far your going to have no
 
problem.  Lets take a look at our entire finished first room</PARA>
 
 
 
 
<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.
 
."
 
 
 
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"}
 
"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 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.";
 
end
 
 
 
</nowiki>
 
 
 
</SECT1>
 
<sect1 id="rmdebug">
 
<TITLE>Compiling and debugging your first room</TITLE>
 
<PARA>It is time we put the zone header information together with
 
your first zone and compile it into a format the <ACRONYM>VME</ACRONYM> server can
 
use.  This is done by using the <ACRONYM>VMC</ACRONYM> compiler.  Depending on if you
 
are doing this on your own Linux server or if you are building for a
 
<ACRONYM>VME</ACRONYM> already set up you will have to use the compiler access
 
method they have defined.  No matter if you are compiling by email,
 
ftp, or at the command line with <ACRONYM>VMC</ACRONYM> the error messages will all be
 
the same.  Since I have no idea how your particular set up is
 
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 <ACRONYM>VME</ACRONYM> running on your own Linux box using the <ACRONYM>VMC</ACRONYM> at the command
 
line.</PARA>
 
 
 
<PARA>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.</PARA>
 
 
 
 
<nowiki>
 
 
 
#include composed.h>
 
%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.
 
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"}
 
"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 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.";
 
end
 
 
 
%end
 
 
 
</nowiki>
 
<PARA>We added the %room tag to our zone header stuck our room in
 
and now its ready to be compiled and put into the <ACRONYM>VME</ACRONYM> server for
 
you to be able to look at it in the game.  If 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.</PARA>
 
 
 
<PARA>The command to compile the zone is
 
<command>VMC debug_rm.zon</command>.
 
Here is what we get when we first try and
 
compile the zone.</PARA>
 
 
 
 
<nowiki>
 
 
 
<ACRONYM>VMC</ACRONYM> 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>
 
 
 
<PARA>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.</PARA>
 
 
 
<PARA>Lets take the first error with this in mind.  The first error
 
shows up on line three of the error file it says: </PARA>
 
 
<nowiki>
 
 
 
&lt;debug_rm.zon&gt; @ 2: Bad include argument
 
 
 
</nowiki>
 
 
 
<PARA>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:</PARA>
 
 
<nowiki>
 
 
 
<ACRONYM>VMC</ACRONYM> 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>
 
 
 
<PARA>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.
 
</PARA>
 
 
 
 
<nowiki>
 
 
 
<ACRONYM>VMC</ACRONYM> 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>
 
 
 
<PARA>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.</PARA>
 
 
 
 
<nowiki>
 
 
 
<ACRONYM>VMC</ACRONYM> v2.0 Copyright (C) 2001 by Valhalla [May  9 2001]
 
Compiling 'debug_rm.zon'
 
<ACRONYM>VMC</ACRONYM> Done.
 
 
 
</nowiki>
 
 
 
<PARA>Notice there are no errors and it says '<ACRONYM>VMC</ACRONYM> 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.
 
</PARA>
 
 
 
<PARA>Now that you have a compiled zone you should check and make sure
 
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.</PARA>
 
 
<nowiki>
 
 
 
debug_rm.data
 
debug_rm.err
 
debug_rm.reset
 
debug_rm.zon
 
 
 
</nowiki>
 
 
 
<PARA>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 <ACRONYM>VME</ACRONYM> 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 <ACRONYM>VME</ACRONYM> 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,
 
<command>goto chamber@dragonst</command>.</PARA>
 
 
 
<PARA>There you go you have now compiled your first zone.  Its not much
 
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.</PARA>
 
 
 
</SECT1>
 
<sect1 id="rmdilfunc">
 
<TITLE><ACRONYM>DIL</ACRONYM> functions for rooms</TITLE>
 
 
 
<PARA>The <ACRONYM>DIL</ACRONYM> language is the language a builder can use to make his own
 
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
 
write your own <ACRONYM>DIL</ACRONYM> functions.  The <ACRONYM>VME</ACRONYM> 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 <ACRONYM>VME</ACRONYM> 2.0 server.</PARA>
 
 
 
 
 
<variablelist id="var-roomfunc">
 
<VARLISTENTRY>
 
;Death room
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>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.</PARA>
 
 
<nowiki>
 
 
 
//In function.zon
 
dilbegin death_room(tick: integer, damage: integer, act_s: string);
 
 
 
</nowiki>
 
<PARA>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 <ACRONYM>DIL</ACRONYM> you have three arguments to pass The first is the
 
'tick' or time which in this <ACRONYM>DIL</ACRONYM> 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.</PARA>
 
 
<nowiki>
 
 
 
dilcopy death_room@function(4*60,60,
 
"Flames shoot up from the floor burning your butt.");
 
 
 
</nowiki>
 
 
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;Climb
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>
 
    This special <ACRONYM>DIL</ACRONYM> 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.</PARA>
 
 
<PARA>With all this in mind the following is the <ACRONYM>DIL</ACRONYM> definition and
 
an example use of it.</PARA>
 
 
 
 
<nowiki>
 
 
 
//<ACRONYM>DIL</ACRONYM> definition
 
dilbegin climb(destination:string, difficulty:integer,
 
                damage:integer,direction:integer);
 
 
 
//Example use of Climb
 
dilcopy climb@function("deck@ship", 17, 20, "up");
 
 
 
</nowiki>
 
 
 
<PARA>We should note here, if you wanted the person to have to climb
 
back down you will need to put a climb <ACRONYM>DIL</ACRONYM> on the room you are climbing
 
too that has the "down" directory as an argument.  This <ACRONYM>DIL</ACRONYM> also allows
 
you to link two rooms not linked by normal directions but we
 
suggest you should think before doing this because it may not make sense to not
 
have a link between the two places.</PARA>
 
</LISTITEM>
 
 
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;Force move
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>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.</PARA>
 
 
 
<PARA>The following is the definition of the force move <ACRONYM>DIL</ACRONYM></PARA>
 
 
<nowiki>
 
 
 
dilbegin force_move (tick: integer, strings: string, random: integer);
 
 
 
</nowiki>
 
 
 
<PARA>The 'tick' parameter is how fast you want the force move to be
 
triggered.  The 'tick' is in 1/4 second increments so to get a one
 
second wait you would place a four.  The second parameter is two strings
 
the first being the symbolic name of the room you are forcing the
 
character to.  The second string is the act you want shown to the player
 
or NPC when it is moved.  The final parameter is either a one or a zero.
 
The one stands for true and it would make the timer trigger randomly
 
fifty percent of the time, while a zero would make it not random.</PARA>
 
 
 
<PARA>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.</PARA>
 
 
<nowiki>
 
 
 
dilcopy force_move@function(4*30,{"river2@riverzon","You float down the river."},0);
 
 
 
</nowiki>
 
</LISTITEM>
 
</VARLISTENTRY>
 
 
 
<VARLISTENTRY>
 
;Safe room
 
<DICTDEF>
 
<PARA></PARA>
 
 
 
<PARA>This function creates a safe room where combat is not allowed.
 
The following is the definition and an example of how to use it.</PARA>
 
 
<nowiki>
 
 
 
//Safe room <ACRONYM>DIL</ACRONYM> definition
 
dilbegin safe_room ();
 
 
 
//Example use of Safe room
 
dilcopy safe_room@function ();
 
 
 
</nowiki>
 
</LISTITEM>
 
</VARLISTENTRY>
 
</VARIABLELIST>
 
 
 
</sect1>
 
 
 
<sect1 id="rmcomplex">
 
<TITLE>A more complex set of rooms</TITLE>
 
 
 
<PARA>In the last section you learned to make basic rooms.  In this
 
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
 
<ACRONYM>DIL</ACRONYM> 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. </PARA>
 
 
 
<sect2 id="rmdoorexits">
 
<TITLE>Exits with doors</TITLE>
 
 
 
<PARA>When we first defined exits we included the 'keyword' and 'open'
 
fields on a door.  In this section we will give an example of two rooms
 
linked together with a door.  There is no new information you have
 
not already encountered so we will start with an example.</PARA>
 
 
 
 
<nowiki>
 
 
 
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
 
"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...."
 
 
 
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};
 
end
 
 
 
 
 
</nowiki>
 
 
 
<PARA>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 <xref LINKEND="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.</PARA>
 
 
 
</sect2>
 
 
 
<sect2>
 
<TITLE>Locked exits</TITLE>
 
<PARA>Now that you have making a door down, you may find that it is not
 
safe to leave your doors unlocked.  Well the <ACRONYM>VME</ACRONYM> is ready for you.  You
 
have already seen the 'keyword' and 'open' sections and what you can set
 
in them.  Now lets use the 'EX_LOCKED field with them and introduce a
 
new macro to allow you to set the difficulty to unlock the lock with out
 
a key.</PARA>
 
 
 
<PARA>First lets look at the macro that allows you to set a difficulty
 
on a lock.  If you set the lock with out this macro it will default to
 
0 and thus be easy to pick.</PARA>
 
 
<nowiki>
 
 
#define DOOR_LOCK_DEF(north_lock, east_lock, south_lock, west_lock,\
 
up_lock, down_lock, northeast_lock, northwest_lock, southeast_lock,\
 
southwest_lock)
 
 
 
</nowiki>
 
<PARA>When using this macro you only set the value of the exit you want
 
to add the difficulty to, you can leave the rest of the exits '0'.  Only
 
one of these macros are needed on a room no matter how many exits
 
because each of the exits are included..  If you have an exit to the
 
north that is locked and you want it to have a difficulty of 50% the
 
following would be the line you would add to your room</PARA>
 
 
<nowiki>
 
 
 
DOOR_LOCK_DEF(50, 0, 0, 0, 0, 0, 0, 0, 0, 0)
 
 
 
</nowiki>
 
<PARA>Now lets add the macro and the locked flag to the exits and create
 
the room.</PARA>
 
 
<nowiki>
 
 
 
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
 
"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
 
ALWAYS_LIGHT
 
flags {UNIT_FL_NO_WEATHER, UNIT_FL_INDOORS}
 
 
 
DOOR_LOCK_DEF(0, 0, 0, 50, 0, 0, 0, 0, 0, 0)
 
west to hallway descr
 
"You see what looks to be a hallway."
 
keyword {"air lock door","air lock","door"}
 
key nokey
 
open {EX_OPEN_CLOSE, EX_CLOSED,EX_LOCKED};
 
end
 
 
 
</nowiki>
 
 
 
<PARA>The only thing you may be wondering about in this example is the
 
'key' field.  I have picked 'nokey' as my value of the key.  There is no
 
key in this zone so all this does is create a key hole.  If you leave
 
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
 
<xref LINKEND="ch-07">.</PARA>
 
</sect2>
 
 
 
<sect2>
 
<TITLE>Hidden exits</TITLE>
 
 
 
<PARA>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.</PARA>
 
 
<nowiki>
 
 
 
#define SECRET_DOOR_DIFFICULTY(DIR, SKILL) \
 
extra{SECRET_DOOR} {DIR, SKILL}\           
 
""                                       
 
 
 
</nowiki>
 
<PARA
 

Latest revision as of 09:02, 27 May 2020

DIL DOCUMENTATION

Version 4.0

Current Version by: Whistler@valhalla.com

Index

Making a Program
Data Types:
  string
  stringlist
  integer
  integerlist
  extraptr
  unitptr
  cmdptr
  zoneptr
Messages:
  SFB_CMD
  SFB_DONE
  SFB_TICK
  SFB_COM
  SFB_DEAD
  SFB_MSG
  SFB_PRE
Built-In Variables
  cmdstr
  excmdstr
  excmdstr_case
  self
  activator
  target
  medium
  power
  argument
  heartbeat
  null
  weather
  mud(day,month,..)
  realtime
DIL Constructs:
  if()
  goto
  while()
  break
  continue
  on ... goto ...
  foreach()
Assignment
Expressions:
Operators
  in
  string in string
  string in stringlist
  string in extraptr
Functions:
  quit
  return
  return()
Fields:
  extraptr
  unitptr
  UNIT_ST_OBJ
  UNIT_ST_ROOM
  UNIT_ST_PC and UNIT_ST_NPC
  UNIT_ST_NPC
  UNIT_ST_PC
Built-In Functions:
  asctime()
  atoi()
  cancarry()
  check_password()
  command()
  delstr()
  delunit()
  dildestroy()
  dilfind()
  equipment()
  filesize()
  findroom()
  findrndunit()
  findsymbolic()
  findunit()
  fits()
  getcolor()
  getword()
  getwords()
  ghead()
  isaff()
  islight()
  isplayer()
  isset()
  itoa()
  left()
  length()
  load()
  loadstr()
  meleeattack()
  meleedamage()
  mid()
  moneystring()
  opponent()
  openroll()
  pathto()
  paycheck()
  purse()
  replace()
  restore()
  right()
  rnd()
  savestr()
  send_pre()
  skill_name()
  spellindex()
  spellinfo()
  split()
  strdir()
  strcmp()
  strncmp()
  textformat()
  tolower()
  toupper()
  transfermoney()
  visible()
  weapon_name()
  weapon_info()
Built-In Procedures:
  acc_modify()
  act()
  addaff()
  addcolor()
  addequip()
  addextra()
  addstring()
  attack_spell()
  beginedit()
  block
  cast_spell()
  changecolor()
  change_speed()
  clear()
  dilcopy()
  delcolor()
  delete_player()
  destroy()
  exec()
  experience()
  flog()
  follow()
  gamestate()
  insert()
  interrupt()
  killedit
  link()
  log()
  logcrime()
  nopriority
  on_activation()
  pagestring()
  position_update()
  priority
  reboot
  remove()
  reset_level()
  reset_vlevel()
  reset_race()
  secure()
  send()
  sendtoall()
  sendtoalldil()
  sendtext()
  sendto()
  send_done()
  set()
  setbright()
  set_fighting()
  setweight()
  set_password()
  store()
  stop_fighting()
  subaff()
  subextra()
  substring()
  unequip()
  unitdir()
  unsecure()
  unset()
  wait()
  walkto()
Ending Notes

---~---~---~---~---~---~---~---~---
  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.


Making a program:

  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.

  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.

Example:

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.

Technical note:

  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;


 
 dilbegin myprogram();
 var
   i : integer;
   j : integer;
 
 code
 {
   heartbeat:=PULSE_SEC*5;
   :start:
   exec("say Hello world", self);
   pause;
   goto start;
 }
 dilend

  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).


Data Types:

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:

---~---~---~---~---~---~---~---~---

String:

   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.

Example:

  "This is a static string"

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

Example:

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

Example:

  if (self.name == self.names.[1]) ...

  Elements of the string can also be accessed by referencing them by their position.

  Example
  if (str.[3]==f])
  {
  exec ("say The 4th element is a F.",self);
  }

  Note
  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.

Example
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'.

---~---~---~---~---~---~---~---~---

Stringlist:

  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.
Example:

  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.

Example:

  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:

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

Note
  See the strings for more information on accessing a single element.

---~---~---~---~---~---~---~---~---

Integer:

  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.

Example:

  0x10

Example:

  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).


Example:

  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.

Example:

  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.

---~---~---~---~---~---~---~---~---

Intlist:

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

Example

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

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

Example

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

The intlists are saved on savable units.

Type:  intlist

  This variable type allows you to keep an ordered list of integers with out
having to create a variable for each integer.
Example:  Setting an intlist

---~---~---~---~---~---~---~---~---

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:
Insert
Remove
Extraptr


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.



Type:  cmdptr
cmdptr fields


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


  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

---~---~---~---~---~---~---~---~---




---~---~---~---~---~---~---~---~---

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.



Type:  zoneptr
Zone Pointer Fields


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


  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



---~---~---~---~---~---~---~---~---








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.


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:
Dil and Findunit()

The message categories are as follows:
---~---~---~---~---~---~---~---~---


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.


---~---~---~---~---~---~---~---~---


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).

---~---~---~---~---~---~---~---~---


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.
---~---~---~---~---~---~---~---~---

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.
---~---~---~---~---~---~---~---~---

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).

---~---~---~---~---~---~---~---~---


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.


Example:


 
 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

/* 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.
*/

---~---~---~---~---~---~---~---~---


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;
      }
   }
   ...


---~---~---~---~---~---~---~---~---

A note upon activating a DIL program

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.


Built-in Variables:


'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'
   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'
   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.


---~---~---~---~---~---~---~---~---

'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"

---~---~---~---~---~---~---~---~---

'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.

---~---~---~---~---~---~---~---~---

'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.

---~---~---~---~---~---~---~---~---

'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.

---~---~---~---~---~---~---~---~---

'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.

---~---~---~---~---~---~---~---~---

'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.

---~---~---~---~---~---~---~---~---

'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 */

---~---~---~---~---~---~---~---~---

'null'
   This is a null pointer.

---~---~---~---~---~---~---~---~---

'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.

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---

'mudday'
'mudhour'
'mudmonth'
'mudyear'
   These variables lets your program keep track of the time in the mud.
   They all have integer types.


DIL constructs:

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

---~---~---~---~---~---~---~---~---

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

Example:


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

Example:


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

Example:


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

---~---~---~---~---~---~---~---~---


goto:
    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.

Example:


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

---~---~---~---~---~---~---~---~---

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

Example:


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

---~---~---~---~---~---~---~---~---

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

Example:


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

---~---~---~---~---~---~---~---~---

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

Example:


 
   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

---~---~---~---~---~---~---~---~---

on n goto la, lb, ..., ln:

    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.


Example:

  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:


 
     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 ...;
 
It is often used in this context


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

---~---~---~---~---~---~---~---~---

foreach:
  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.

Example:
    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.


 
 ...
    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;
    }
 ...



Assignment:

    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)

Example:


 
   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




Expressions:

  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.

Example:


 
   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

---~---~---~---~---~---~---~---~---

Operators:

  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.

---~---~---~---~---~---~---~---~---

in:
	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.

---~---~---~---~---~---~---~---~---

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.

Example:


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

---~---~---~---~---~---~---~---~---

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:


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

---~---~---~---~---~---~---~---~---

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).

Example:


 
   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


Functions:

  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.

Example:


 
   dilbegin foo();
   code
   {
     exec("say I exist in "+itoa(self.loaded)+"copies", self);
     pause;
   }
   dilend

  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.

Example:


 
   dilbegin integer bar(s:string);
   code
   {
     exec("say "+s,self);
     return rnd(1,10);
   }
   dilend


 
   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

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---

  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.


Fields:

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
---~---~---~---~---~---~---~---~---

The extraptr has the following fields:

   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.

---~---~---~---~---~---~---~---~---

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)

---~---~---~---~---~---~---~---~---

The unitptr has the following fields:

   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)

if the type is UNIT_ST_OBJ

      '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.

if the type is UNIT_ST_ROOM

      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

if the type is UNIT_ST_PC or UNIT_ST_NPC 

      '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

if the type is UNIT_ST_NPC 

      '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.

if the type is UNIT_ST_PC

      '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.



Built-In Functions:

    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.


---~---~---~---~---~---~---~---~---

string asctime(i : integer)
   i : the time to convert in seconds (realtime 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



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

  s1
         first string
  s2
         second string

 returns
  -1
         if s1 < s2
  0
         if s1 = s2
  1
         if s1 > s2


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.
example:

---~---~---~---~---~---~---~---~---

if (strcmp("I Care about Capitals",s2)==0))
        {
        sendtext ("You care I can see.&n",self);
        quit;
        }



---~---~---~---~---~---~---~---~---





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



---~---~---~---~---~---~---~---~---





---~---~---~---~---~---~---~---~---

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);


---~---~---~---~---~---~---~---~---

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);

---~---~---~---~---~---~---~---~---

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 */





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
interrupt editing before done

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'


---~---~---~---~---~---~---~---~---


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);

---~---~---~---~---~---~---~---~---

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);




Function:  string replace( t :string, n : string, o : string);

  t
         the target string you want to replace
  n
         what you want to replace the target with
  o
         the original string
  return
         the string with the old string replaced by the new string

This function replaces all occurences of a string in another string with a
new string.
Example:
"Jafar %t% %l%" := replace(%n%,pc.name,"%n% %t% %l%");
"Jafar the human %l%" := replace(%t%,pc.title,"Jafar %t% %l%");
"Jafar the human 1" := replace(%l%,itoa(pc.vlevel),"Jafar the human %l%");




Function:  unitptr restore( filename : string , u : unitptr );

  filename
         The name of the Unit file
  u
         The Unit you want to restore into or null if none
  Return
         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'

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..
Note, 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.
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.
Disk access is always slow.
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.

Example 1:

---~---~---~---~---~---~---~---~---

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
Store a Unit to a Unit file and
Delete a Unit file.


---~---~---~---~---~---~---~---~---

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.





Function:  
meleedamage ( c : unitptr, v : unitptr, b : integer, wt : integer );

  c
         the character that should make an additional attack
  v
         the character being attacked
  b
         any penalty or bonus added to the attack.
  wt
         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.
  returns
         The amount of damage done or -1 for failed

ch' performs an attack (using whatever weapon is wielded or his bare hands) against 'vict'.
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.
Example:

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---







Function:  string mid ( o : string, s : integer, e : integer );

  o
         the original string to be parsed
  s
         The starting point of the string to be parsed out
  e
         the ending point of the string to be parsed out
  return
         the portion of the string defined by the 's' and 'e' values

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.
Example:  "rock" := mid ("sprocket",3,6);

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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

		   


Function: string tolower ( s : string );
   s
         String to lower case
  return
         the string passed in lower cased

This function returns a copy of the string passed in but with out capitals.
 Example: "hello!" :=  tolower("HELLO!");
 

Function:  string toupper ( s : string );

  s
         String to lower case
  return
         the string passed in lower cased

This function returns a copy of the string passed in with all characters changed
to be capitalized.
Example:  "HELLO!" := toupper ("hello!");


---~---~---~---~---~---~---~---~---

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)) ...

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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);

---~---~---~---~---~---~---~---~---

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





Function:  integer check_password( u : unitptr, s : string ) ;

  u
         the unit that you want to check the password of
  s
         the password you are using to check
  Return
         Returns an integer TRUE if pcname is the units password FALSE if not

This function checks the string against the units password and returns TRUE
if they match.
Example:

---~---~---~---~---~---~---~---~---

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



---~---~---~---~---~---~---~---~---




---~---~---~---~---~---~---~---~---

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.
CAVEAT 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".)




Function:  integer delstr( filename : string ) ;

  filename
         The name of the String file to be deleted
  Return
         Returns an integer TRUE if deleted FALSE if not

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.
Example:

---~---~---~---~---~---~---~---~---

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 
Load String file and
Save String file




Function:  integer delunit( filename : string ) ;

  filename
         The name of the Unit file to be deleted.
  Return
         Returns an integer TRUE if deleted FALSE if not delunit is used to delete files that are used with the 'Restore' and 'store' functions.

Example:

---~---~---~---~---~---~---~---~---

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
Restore a Unit from a Unit file and
Store Units to a Unit file.



---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---

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'








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.




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



---~---~---~---~---~---~---~---~---





---~---~---~---~---~---~---~---~---

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)) ...

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.

The flags for findunit, intuitively:


FIND_UNIT_EQUIP:
  The objects you will see with `equipment'
  Assumes first argument to findunit is a char.


FIND_UNIT_INVEN:
  The objects you will see with `inventory' or `look in bag'


FIND_UNIT_SURRO:
  The objects you can see, and get with `get',
  or the characters you can `poke' :-)


FIND_UNIT_ZONE:
  As FIND_UNIT_WORLD, only more local.


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.


On top of these, the following (new) values are defined:


FIND_UNIT_IN_ME:
  Anything inside of the object of the first argument.


FIND_UNIT_HERE:
  Anything `here', i.e. in object or around it (same as IN_ME + SURRO)


FIND_UNIT_GLOBAL:
  ANYTHING, starting close to object and working out.





---~---~---~---~---~---~---~---~---

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).




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.


---~---~---~---~---~---~---~---~---

unitptr findroom ( s : string )
   s : Symbolic name of room.
   return: A pointer to the room, or null
   Example: findroom("inn@udgaard")

---~---~---~---~---~---~---~---~---

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.


---~---~---~---~---~---~---~---~---

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.


---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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'.

---~---~---~---~---~---~---~---~---

unitptr ghead ( )

return the first unit in the global list which will be the last
char to have logged on.

---~---~---~---~---~---~---~---~---

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'.



Function:  string left ( o : string, l : integer );

  o
         the original string to be parsed
  l
         The amount of characters to parse out
  return
         the left portion of the string with length l

This function parses the string passed to it and returns the number
of characters defined in its second argument.

Example:  "short" := left ("shorten me",5);
Example:

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---



---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---


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.



Function:
integer loadstr( filename : string , buff : string );

  filename
         The name of the string file to be loaded
  buff
         The string that you wish to read the file contents into
  Return
         FILE_LOADED, FILE_NOT_FOUND, FILE_OUT_OF_MEMORY,or FILE_TO_LARGE

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.
Disk access is always slow.
attempt to keep file sizes to a minimum for quick loading.  Otherwise you
might cause serious delays on the server.
Example:

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---


See Also 
Delete a String file and
Save String file

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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"));

---~---~---~---~---~---~---~---~---

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.





Function:  string right ( o : string, r : integer );

  o
         the original string to be parsed
  r
         The amount of characters to parse out
  return
         the right portion of the string with length r

This function parses the string passed to it and returns the number of characters
from the right defined in its second argument.
Example:  "Easy" := right ("This is Easy",4);

---~---~---~---~---~---~---~---~---

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);



Built-In Procedures:

    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)

Example:


 
   dilbegin bar(s:string);
   code
   {
     exec("say "+s,self);
     return;
   }
   dilend


 
   dilbegin foo();
   external
     someproc@hades1();
     bar(s:string);
   code
   {
     someproc@hades1();
     bar("Hello "+activator.name);
     pause;
   }
   dilend

    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.


---~---~---~---~---~---~---~---~---

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.





Function:  flog (filename : string,  s : string, wa : string );

  filename
         The Filename of the file to appear in the log directory.
  s
         The string to be logged.
  wa
         Write or Append

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.
Note: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.



---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.




Function:  stringlist strdir( 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 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


---~---~---~---~---~---~---~---~---


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'




Function:  set_password( u : unitptr, s : string ) ;

  u
         the unit that you want to set the password of
  s
         the password you are using to set

This function sets a unit password it only works on Players characters of corse.
Example:

---~---~---~---~---~---~---~---~---

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




---~---~---~---~---~---~---~---~---








Function:  store( u : unitptr , filename : string , container : integer );

  u
         The Unit that has the contents to be stored or is to be stored
  filename
         The name of the file you want to store the Units to
  container
         Do you want to save the container 'TRUE' for yes, 'False' for no


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.


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.


Disk access is always slow.
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.
Example 1:

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---


See Also
Store a Unit to a Unit file and
Delete a Unit file.

---~---~---~---~---~---~---~---~---

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);



Function:
send_done( c : string, a :unitptr, m : unitptr, t :unitptr, p : integer, arg : string, o : unitptr);

  c
         the command string that is sending the message
  a
         the unitptr (activator) that activated the message
  m
         the unitptr (medium) that the Dil is acting through
  t
         the unitptr (target) the Dil is acting on
  p
         the power of the message
  arg
         the argument sent with the message
  o
         the unitptr (other) you also want the message to go to


  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 commands.zon

Example:

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---



Function:send_pre( c : string, a :unitptr, m : unitptr, t :unitptr, p : integer, arg : string, o : unitptr);

  c
         the command string that is sending the message
  a
         the unitptr (activator) that activated the message
  m
         the unitptr (medium) that the Dil is acting through
  t
         the unitptr (target) the Dil is acting on
  p
         the power of the message
  arg
         the argument sent with the message
  o
         the unitptr (other) you also want the message to go to



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

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---




---~---~---~---~---~---~---~---~---

set ( var i : integer , bit : integer )
   i : Integer variable to alter.
   bit : Bits to set in integer variable.
   result: Sets bits in 'i'

---~---~---~---~---~---~---~---~---

unset ( var i : integer , bit : integer )
   i : Integer variable to alter.
   bit : Bits to unset in integer variable.
   result: unset bits in 'i'.




Function:  addcolor (ch : unitptr, ks : string, cstr : string ) ;

  ch
         character you are adding the color to
  ks
         key string for the color
  cstr
         color string

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.
Function:  addcolor(pc, "clan_who","&c+w&bn");




Function:  delcolor (ch : unitptr, ks : string) ;

  ch
         character you are deleting the color from
  ks
         key string for the color

This function is used to delete any colors from a players personal color list.
Function:  delcolor(pc, "clan_who");



Function:   string getcolor (ch : unitptr, ks : string) ;

  ch
         character you are deleting the color from
  ks
         key string for the color
  returns
         returns the color in a string

This function returns what color a player has for a key in the players list.
Function:  string := getcolor(pc, "clan_who");



Function:  changecolor (ch : unitptr, ks : string, cstr : string ) ;

  ch
         character you are changing the color on
  ks
         key string for the color
  cstr
         color string

This will change a color in a players personal list.
Function:  changecolor(pc, "clan_who","&c+w&bn");



Function:    gamestate( u : unitptr, gs : integer ); 
Change the gamestate of a unitptr, uses the GS_ defines from the
vme.h. 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.
Example:

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---


Look in vme.h for the possible values you can send to the menu
function.


---~---~---~---~---~---~---~---~---

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.

CAVEAT 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");
   ...
   ...

---~---~---~---~---~---~---~---~---

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'.

---~---~---~---~---~---~---~---~---

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.

<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");
   ...
   ...

---~---~---~---~---~---~---~---~---

substring ( var l : stringlist, s : string )
   l : Stringlist to remove string from.
   s : String to remove
   result: Removes string 's' from stringlist 'l'.





Function:  stop_fighting( ch: unitptr, vict : unitptr ) ;

  ch
         unitptr - person you are stoping the fighting for
  vict
         unitptr - person you are removing from the fighting or null for everyone

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.
Example:

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---




---~---~---~---~---~---~---~---~---

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'.

---~---~---~---~---~---~---~---~---

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



Function:  destroy ( u : unitptr );

  u
         :Unit to remove from game

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.
Example

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---




---~---~---~---~---~---~---~---~---

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"));

---~---~---~---~---~---~---~---~---

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).




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);

---~---~---~---~---~---~---~---~---





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


---~---~---~---~---~---~---~---~---







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);

---~---~---~---~---~---~---~---~---





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

---~---~---~---~---~---~---~---~---






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

---~---~---~---~---~---~---~---~---





---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---


The purpose of act is to send a message to a number of players present 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.)


---~---~---~---~---~---~---~---~---

Syntax:

act(message, visibility, char, medium, victim, to_whom);


 message
          - is a string that will be shown to other mobiles when the act is executed. To refer to the following arguments use the formatters listed below.
 visibility
          - is an integer that defines what happens if the mobile that is about to receive the message can't see the activator.
         A_SOMEONE
                If the receiver cannot see char, replace any reference to char with someone.
         A_HIDEINV
                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.
         A_ALWAYS
                Works exactly like A_SOMEONE, except that the receiver will see the message even when sleeping.
 char
          - 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.
 medium
          - is a unit pointer, an integer or a string. Use this at your leisure.
 victim
          - is a unit pointer, an integer or a string. Certain flags in the next argument rely on the validity of victim.
 to_whom
          - is an integer that defines who gets the message.
         TO_ROOM
                Sends the message to the entire room, excluding 'char'.
         TO_VICT
                Sends to 'victim' only. 'victim' must be valid, naturally.
         TO_NOTVICT
                Sends the message to the entire room, excluding 'char' and 'victim'.  Perfect for bystanders in a melee.
         TO_CHAR
                Sends the message to 'char' and no one else.
         TO_ALL
                Sends the message to everybody in the room.
         TO_REST
                This is a bit different from the rest.  In sends the message to all other units in the local environment, excluding those inside 'char'.

---~---~---~---~---~---~---~---~---

Act Formatters

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:

 '$$'
         will be sent to the receiver as a single `$'

'$', followed by a number and an extra character.
  The numbers:

 '1'
          means this formatter refers to the 'char' argument.
 '2'
         means this formatter refers to the 'medium' argument.
 '3'
          means this formatter refers to the 'victim' argument.

   The characters

 'N'
          the formatter will be replaced with the name of the unit, or (depending on the visibility) 'something' or 'someone'.
 'a'
         'a' or 'an' depending on the name of the unit referred by the number.
 'e'
         'it', 'he' or 'she' depending on the gender of the unit referred by the number.
 'm'
         'it', 'him' or 'her' depending on the gender of the unit referred by the number.
 'n'
          the formatter will be replaced with the title of the unit, or (depending on the visibility) 'something' or 'someone'.
 'p'
         'fighting', 'standing', 'sleeping', etc., depending on the positionof the unit referred by the number.
 's'
         'its', 'his' or 'her' depending on the gender of the unit referred by the number.
 't'
         the string in the argument referred by the number.



Example:


 
   act("You step over $2n.", A_SOMEONE, self, litter, null, TO_CHAR);
   act("$1n steps over $2n.", A_SOMEONE, self, litter, null, TO_REST);


See Also:
  DIL Act() for Dummies

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.
Example:

   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.
    */

Example:

  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).
  */




Function:  integer savestr( filename : string , buff : string , wa :string);

  filename
         The name of the String file to save the String to
  buff
         The String you wish to save into the file
  wa
         Write or append
  Return
         FILE_SAVED, FILE_NOT_SAVED, FILE_NOT_CREATED, or FILE_ILEGAL_OPP

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.
Note: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.
Disk access is always slow.
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.
Example:

---~---~---~---~---~---~---~---~---

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 
Delete a String file and
Load a String file





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);




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

reset a players virtual level and
reset a players race information




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

reset a players level and
reset a players race information



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

reset a players level and
reset a players virtual level



---~---~---~---~---~---~---~---~---

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.



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.


---~---~---~---~---~---~---~---~---

unsecure ( u : unitptr )
   u : Secured unit.
   result: Drop secure on a given unit.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

nopriority
   result: Cancels the priority procedure.

---~---~---~---~---~---~---~---~---

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

---~---~---~---~---~---~---~---~---

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




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



---~---~---~---~---~---~---~---~---




---~---~---~---~---~---~---~---~---

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'.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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).

---~---~---~---~---~---~---~---~---

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'.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

log( s : string )
   s : Text to put in the log.
   result: Puts text in the log for debugging purposes.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.

---~---~---~---~---~---~---~---~---

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.

Example:

   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.

---~---~---~---~---~---~---~---~---

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.

Example:

   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.

---~---~---~---~---~---~---~---~---

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.

   Example:

   %dil


 
    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

   .....

   %...


 
    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

---~---~---~---~---~---~---~---~---

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.



   

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

---~---~---~---~---~---~---~---~---





---~---~---~---~---~---~---~---~---

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.

Example:

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).


 
 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

---~---~---~---~---~---~---~---~---

clear( i : integer )

   Clears the interrupt number "i". If i is invalid, this will either
   clear an wrong interrupt or do nothing.

---~---~---~---~---~---~---~---~---

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.

   Example:
           on_activation(self.position <= POSITION_SLEEPING, skip);
             or
           on_activation(self.position > POSITION_SLEEPING, let_me_sleep);

---~---~---~---~---~---~---~---~---

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 commands.txt for details.

This page last updated 03-27-2001, Ken Perry "Whistler"