=======================================================================
                          USING ANSI ON HAVEN
=======================================================================
  Using ANSIcodes on Haven are fairly easy. Haven supports 9 different
colors. They are black, red, blue, cyan, magenta, orange, yellow, green,
and white. These colors may also be modified to be bold, in the 
background of the text, or to be flashing. First, we'll go over the
basic syntax of how to use ANSI and then we'll move on from there.

=======================================================================
                              ANSI SYNTAX
=======================================================================
  The syntax for ANSI is pretty easy. All you do is specify your 
options, separating each one with %^. Don't include the period. All of
your options are in UPPERCASE letters (such as RED). The basic ANSI
sentence would look like this:

                       %^<COLOR>%^<TEXT>%^RESET%^

  You must ALWAYS use a RESET at the end, otherwise you will make 
everything else that color. For example, you have a red gummy bear. You
forget to put a RESET at the end. Now, instead of just the red gummy
bear appearing red, your whole inventory would appear red. So, don't
forget to put a RESET at the end of all of your ANSI codes. So, if you
wanted to make that red gummy bear, it would look like this:

		     %^RED%^A red gummy bear%^RESET%^
				  - or -
		     A %^RED%^red%^RESET%^ gummy bear

  The first one would have the whole thing red, while the second 
example would have just the word 'red' actually red.

  Now let's say that you want to make the color for this gummy bear 
really bright, or maybe you want it to flash. This is what you would do:

		   %^RED%^BOLD%^A red gummy bear%^RESET%^
				  - and -
		  %^RED%^FLASH%^A red gummy bear%^RESET%^

  Also, you can combine them both to make a red and flashing gummy bear.

	       %^RED%^BOLD%^FLASH%^A red gummy bear%^RESET%^

  You may stack options like this as much as you want. For another 
example, let's say you want it to have a yellow background in order to 
make it really stand out. To make any color the background, just put a 
B_ before the color. So, to make a yellow background with the entire 
sentence, it would end up looking like this:

	    %^RED%^BOLD%^FLASH%^B_YELLOW%^A red gummy bear%^RESET%^

=======================================================================
                             LIST OF OPTIONS
=======================================================================
This is a list of all of the triggers that may be used to make ANSI:

			    Regular Colors:
                       %^BLACK%^	%^RED%^
                       %^BLUE%^	        %^CYAN%^
		       %^MAGENTA%^	%^ORANGE%^
		       %^YELLOW%^	%^GREEN%^
                               %^WHITE%^

			   Background Colors:
                       %^B_BLACK%^	%^B_RED%^
                       %^B_BLUE%^	%^B_CYAN%^
                       %^B_MAGENTA%^	%^B_ORANGE%^
                       %^B_YELLOW%^	%^B_GREEN%^
	                       %^B_WHITE%^

			     Extra Triggers 
                          (RESET must be used):
		       %^FLASH%^	%^BOLD%^
                               %^RESET%^	

Remember that all of these options can be stacked to make a really nice
color scheme.

=======================================================================
                               CONCLUSION
=======================================================================
  So, all of the ANSI options are fairly easy and can be done with just
a little bit of learning and getting used to. All of the options and 
extras can be used with every color and they may be stacked as much as
needed. An area can look really nice with a bit of color, but don't go
too far overboard as it can make it look bad. For example, FLASH is
programmed in, but nobody ever uses it because it is kind of irritating
so watch when you are making ANSI and that it is not irritating.

  If there are any errors in here, or you have suggstions/comments, just
mail Zaxan.

					--Zaxan

   --  How to get an Area or Town into the game --

 1) Mail Duuktsaryth (or duly appointed other) saying that your
    area is ready for approval.  DO NOT CONNECT it to the game yet.
    Doing so is cause for immediate removal.

 2) Duuk will enter your area at his earliest convienance.  Do not
    be upset if this takes a few days.  After all, he's busy.

 3) Duuk will likely find things wrong with your area.  He keeps
    good notes and will mail you with a full listing of all things
    that are wrong with your area.  Fix each and every one.

 4) Remail Duuk with the news of the completetion.

 5) Repeat as neccessary.

 

 Pointers:

  SetItems() for any noun mentioned, even if mentioned in another
  item's description.

  ie:  'exa tree'  The tree has leaves.
       'exa leaf'  The leaves are covered with bugs.
       'exa bug'   Aww, what a cute bug.

  Have both singular and plural of the nouns available.

       'exa tree'  'exa trees'

 Do not use 'you'.

 Use passive, vivid descriptions, not boring or routine ones.

 Have unique, differant NPCs with whom the PCs can interact.

 Make sure all NPCs conform to policy.

 Make sure all treasure is balanced.

			   Building Armours
		     The Nightmare IV LPC Library
		 written by Descartes of Borg 950430

Armour has changed quite a bit from the days of armour class.  The
Nightmare IV LPC Library now uses damage types, which means armour that
is great against one attack may be pathetic against another.  In fact,
in building armour, it is important that you keep in mind weaknesses.
Fortunately, armour is by default absolutely pathetic.  If you go
making it awesome, chances are that it will not make it through the
approval process.  This document is designed to get you started
building armour as well introduce you to the features available to
make unique and interesting armour.

I. Basic Armour
You should be familiar with /doc/build/Items, as armour is just a
special type of item.  It therefore has all of the features of regular
items. 



The basic armour looks like this:

#include <lib.h>              /* see this everywhere */
#include <armour_types.h>     /* a listing of armour types */
#include <damage_types.h>     /* a listing of damage types */

inherit LIB_ARMOUR;           /* the armour inheritable */

static void create() {
    armour::create();         /* call create() in armour.c */
    SetKeyName("rusty helm");
    SetId( ({ "helm", "rusty helm", "a rusty helm" }) );
    SetAdjectives( ({ "rusty" }) );
    SetShort("a rusty helm");
    SetLong("A rusty helmet which will be better than nothing on your head.");
    SetMass(75);
    SetValue(200);
    SetDamagePoints(1000);    
    SetProtection(BLUNT, 4);   /* SetProtection() sets the sort of */
    SetProtection(BLADE, 3);   /* protection for a given damage type */
    SetProtection(KNIFE, 3);
    SetArmourType(A_HELMET);     /* set what kind of armour this is */
}

As you can see, there is very little that you have to do specific to
armour.  The only armour specific call you MUST make is
SetArmourType().  Everything else is fluff.

int SetArmourType(int type)
Armour types are found in /include/armour_types.h.  The armour type
basically determines where the armour is worn.  Each monster,
depending on its race, has for each limb a list of armour types which
may be worn on that limb.  For example, most monsters have heads.
Some have two heads.  You do not have to worry about this.  They know
that they can wear anything that is A_HELMET on their heads.  What if
you have something that may not be wearable on all monsters?  Like,
for example, you have body armour which should only go on two armed
beings?  See SetRestrictLimbs() later.  It allows you to restrict
exactly which kinds of limbs can wear the armour.

int SetProtection(int type, int amount);
Without this call, armour is nothing.  Just something you wear.  This
allows you to make clothes, which may protect against COLD, but do not
do a thing when struck with a sword.  Protection is a number between 0
and 100.  Refer to approval documentation for details on what levels
are appropriate, as well as for information on mass and value levels.

That's it for the basics!

II. Advanced Function Calls
The Nightmare IV LPC Library armour object is fairly flexible for
allowing you to do interesting things with your armours.  In this
section, you will learn about other function calls you can make to
customize your armour.

string *SetRestrictLimbs(string *limbs);
Example:
	SetRestrictLimbs( ({ "right arm", "left arm", "torso" }) );

For armours which can only be on certain body configurations, for
example regular armour (A_ARMOUR) should only be worn on people with
the same number of hands, this function allows you to restrict the
armour to being worn only on the limbs you name.  If the person trying
to wear the armour does not have one of those limbs, any attempt to
wear fails.

int SetFingers(int num);
Example:
	SetFingers(5);

Used for the glove types.  If a person has more fingers on the limb on
which they are trying to wear a glove type than the glove has spaces
for, the wear fails.

mixed SetWear(string | function val);
Examples:
	SetWear("The cloak feels all yucky on you.");
	SetWear( (: CheckArtrell :) );

Allows you to create a special message seen by the person wearing the
item when they wear it if you pass a string.  On the other hand, if
you pass a function, it will call that function to see if the person
can wear the item.  The function should be of the form:
	int WearFunc();

For example:

int CheckArtrell() {
    if( (string)this_player()->GetRace() == "artrell" ) {
        write("The rusty helm makes you feel safe.");
        say((string)this_player()->GetName() + " wears a rusty helm.");
        return 1;
    }
    else {
        write("You cannot wear that you bum!");
        return 1;
    }
}

III. Function Overrides
The only function of interest that you might want to override is a
function called eventReceiveDamage().  This function is called every
time the armour is hit to see how much of the damage it absorbs.  It
looks like this:

int eventReceiveDamage(int type, int strength, int unused, mixed limbs);

This function is called by combat to determine how much damage the
armour absorbs for a given bit of damage being done.  It thus should
return how much damage it takes.  

You should always at some point call item::eventReceiveDamage() so
that it can do its processing.  You do not want to call it, however,
until you determine how much damage you are absorbing unnaturally.
Here is a sample one for an armour that does extra protection for fighters:

int eventReceiveDamage(int type, int strength, int blah, mixed limbs) {
    object who_is_wearing;
    int x;

    if( !(who_is_wearing = environment()) ) /* eek! no one wearing */
	return 0;
    if( (int)who_is_wearing->ClassMember("fighter") ) /* reduce strength */
        x = strength - random(5); 
    if( x < 1 ) return strength; /* protect against all the damage */
    return armour::eventReceiveDamage(type, x, blah, limbs);
}

Keep in mind what eventReceiveDamage() in armour.c is doing.  First,
it is modifying the strength of the blow based on the protections you
set with SetProtection().  Then, it is having the armour take damage
based on how much it absorbed.  So you need to call
eventReceiveDamage() in armour at the point where you have a value you
want the armour to do its normal stuff with.  In the example above, we
wanted to magically protect fighters against a random(5) points of
damage without having the armour take any damage for that.  Then if
there is still strength left in the blow, the armour does its normal
protection. 

What else can you do with this?  Imagine an armour that turns all cold
damage back on the attacker?

int eventReceiveDamage(int type, int strength, int unused, mixed limbs) {
    object who_wearing, enemy;

    enemy = (object)(who_wearing = previous_object())->GetCurrentEnemy();
    if( !enemy || !(type & COLD) ) 
      return armour::eventReceiveDamage(type, strength, unused, limbs);
    limbs = enemy->GetTargetLimb(0);
    message("environment", "Your anti-cold throws the frost in your "
      "enemy's face!", who_wearing);
    message("environment", "Your cold attack is turned back upon you!",
        enemy);
    enemy->eventReceiveDamage(COLD, strength, unused, limbs);
    return strength; /* we absorb all of the strength but take no damage */
}

	Descartes of Borg
	borg@imaginary.com
		   Building Food and Drink Sellers
		     The Nightmare IV LPC Library
		 written by Descartes of Borg 950528

This document details the building of barkeeps, waiters, and other
such people who sell food and drink.  Barkeeps are NPC's, and
therefore everythign which applies to NPC's applies to barkeeps.  

To build a barkeep, you should inherit LIB_BARKEEP.

Beyond the functions specific to NPC's barkeeps also make use of the
following functions:

mapping SetMenuItems(mapping menu);
mapping AddMenuItem(string item, string file);
mapping RemoveMenuItem(string item);
mapping GetMenuItems();
string SetLocalCurrency(string curr);

When building a barkeep, you must add some mechanism in the room in
which the barkeep is placed for people to view a list of things for
sale.

*****
mapping SetMenuItems(mapping menu);
*****

Example: SetMenuItems( ([ "coffee" : "/realms/descartes/coffee" ]) );

Sets which menu items are found in which file.  This is a mapping with
the name of the item as a key and the file in which it is located as
the value.

*****
mapping AddMenuItem(string item, string file);
*****

Example: AddMenuItem("lobster", "/realms/descartes/lobster");

Adds one menu item at a time to the list of menu items.

*****
mapping RemoveMenuItem(string item);
*****

Example: RemoveMenuItem("coffee");

Removes the named item from the menu.

*****
mapping GetMenuItems();
*****

Returns all the menu items for this barkeep.  Useful in building your
menu list.

*****
string SetLocalCurrency(string curr);
*****

Example: SetLocalCurrency("khucha");

Sets the currency in which the barkeep does business.




indoors
temperate
arid
arctic
tropical
sub-tropical
underground


   Consistancy

  Armour instead of Armor
  Mithril, not mithral
  Robes should be A_BODY_ARMOUR.

  
    Terms

  Please use single words when possible, like 
    'longsword' instead of 'long sword'
The following are valid domains as of Dec '98

Southern Coast
Estergrym
Valley
Crystal Reaches
HavenWood
WestWood
FrostMarches
Baria
Yozrath
		   Creating Doors between Two Rooms
		     The Nightmare IV LPC Library
		 created by Descartes of Borg 950419

This document describes how to build door-type objects which link two
rooms.  These door-type objects do not need to be doors, but in fact
can be windows or boulders or any other such object.  The Nightmare IV
LPC Library door object, unlike the old way of doing doors, is an
object separate from the rooms it connects.  In other words, in order
to build a door, you have three objects (just as you would visualize):
two rooms and a door.

The door object is /lib/door.c.  To inherit it, #include <lib.h> and
inherit LIB_DOOR;.  An example door may be found in
/domains/Examples/etc/door.c as well as the rooms
/domains/Examples/room/doorroom1.c and /domains/Examples/room/doorroom2.c.

Setting up the door object
The first thing you must do is create the door object.  You must
visualize this door object just like a door connecting two rooms in
real life.  You have a room on each side with a single door with two
sides.  Technically, a door object may have any number of sides.
Practically speaking, most people using this object will be using it
as a door, which means it will have two sides.

To create a door object, you simply describe each side of the door.
The easiest way to do this is through the SetSide() function.

mapping SetSide(string side, mapping mp);

Example:

	SetSide("east", ([ "id" : "red door", "short" : "a red door",
	                  "long" : "A freshly painted red door.",
                          "lockable" : 0 ]) );

The name of the side is simply the exit used by the room which sees
that side.  For example, if in one room the door is at the east exit,
then the side is identified as east.  The mapping consists of the
following data:

"id"
What a person on that side calls the door.  For example, you can have a
door blue on one side and red on the other.  On one side, you go east
to go through the door, and from that room the door appears red.  The
id for that side might be "red door".  The id for the other side might
be "blue door".

"short" 
The short description for the door as seen from the side in question.
This can be a function or a string.

"long"
The long description for the door as seen from the side in question.
Whether the door is open or not will be added to the long if the long
is a string.  This can be either a string or function.  If it is a
function, you must specify whether the door is open or close on your
own.

"lockable"
0 if the door cannot be locked (and unlocked) from that side, 1 if it
can.

"keys"
An array of id's of objects which can be used to unlock it if it is
lockable.  Lockable doors do not need keys.

II.  Setting up the rooms
After you have called SetItems() and SetExits() in the room
(remembering to set the exit for the exit with the door), call the
function SetDoor().

string SetDoor(string dir, string doorfile);

Example: SetDoor("east", "/realms/descartes/doors/red_door");

Sets the exit named to be blocked by a door object when that door
object is closed.

This is all you need to do in the room.  Note that the exit name
corresponds to the side name mentioned in the door.

III. Advanced Door Stuff
At this point, you should know how to do the minimum stuff to build a
door.  This section goes into detail about door functions and how you
can do advanced things with doors by manipulating door events.  This
section has two parts, door data functions and door events.

a. Door Data Functions

*****
SetSide()
*****
mapping SetSide(string side, mapping mp);

As described above.

*****
SetClosed()
*****
static int SetClosed(int x)

Example: SetClosed(1);

This function can only be called from inside the door object.
Generally you use it to set the initial state of the door.  If you
want to close the door at any other time, or to close it from another
object, use eventClose() or eventOpen().

*****
SetLocked()
*****

static int SetLocked(int x)

Example: SetLocked(1);

Like SetClosed(), this function should only be used from create()
inside the door object to set the initial state of the door.  At other
times, use eventLock() or eventUnlock().

*****
SetLockable()
*****

int SetLockable(string side, int x)

Example: SetLockable("east", 1);

Sets a side as being able to be locked or unlocked.  Since it is done
by sides, this means you can have one side not be lockable with the
other side being lockable.  The first argument is the side being set
lockable or not lockable, the second argument is 1 for lockable and 0
for not lockable.

*****
SetId()
*****

string SetId(string side, string id)

Example: SetId("west", "blue door");

This is not like your traditional SetId() function.  Instead, it sets
a single way of identifying the door from a given side.  It is what
the player might use to open the door or look at it.

*****
SetShort()
*****

mixed SetShort(string side, string | function desc)

Examples:
	SetShort("north", "a red door");
	SetShort("west", (: GetWestShort :) );

Sets the short description for a given side of a door.  If the second
argument is a function, it gets passed as an argument the name of the
side for which the function serves as a description.  That function
should return a string.  For the above:

string GetWestShort(string dir) {
    if( query_night() ) return "a shadowy door";
    else return "a red door";
}

*****
SetLong()
*****

mixed SetLong(string side, string | function desc)

Examples:
	SetLong("south", "An old, dusty door covered in cobwebs.");
	SetLong("east", (: GetEastLong :))

This works much like the SetShort() function, except it handles the
long description.  It is important to note that if the second argument
is a string, that the state of the door will be added onto the long
description automatically.  In other words "It is open." will appear
as the second line.  This will *not* be done if you use a function for
your long description.

*****
SetKeys()
*****

string *SetKeys(string side, string *keys)

Example: SetKeys("east", ({ "skeleton key", "special key" }));

Builds an array of id's which can be used to unlock the door if it is
lockable from this side. In other words, a person can only unlock the
door if that person has an object which has one of the id's you
specify for its id.

b. Events

*****
eventOpen()
*****

varargs int eventOpen(object by, object agent)

Examples:

"/realms/descartes/etc/red_door"->eventOpen(this_object());

int eventOpen(object by, object agent) {
    if( query_night() ) return 0; /* Can't open it at night */
    else return door::eventOpen(by, agent);
}

The function that actually allows the door to be opened externally.
It returns 1 if the door is successfully opened.  It returns 0 if it
fails.  The first argument is the room object from which the door is
being opened.  The second argument, which is optional, is the living
thing responsible for opening the door.

The first example above is an example of what you might do from
reset() inside a room in order to have the door start open at every
reset.

The second example above is an example of how you might conditionally
prevent the door from opening by overriding the Open event.  In this
case, if it is night, you cannot open this door.  If it is day, you
can. 

*****
eventClose()
*****

varargs int eventClose(object by, object agent)

Example: See eventOpen()

This function works just like eventOpen(), except it does the closing
of the door.

*****
eventLock()
*****

varargs int eventLock(object by, object agent)

Example: see eventOpen()

This function works just like eventOpen(), except that it gets called
for locking the door.

*****
eventUnlock()
*****

varargs int eventUnlock(object by, object agent)

Example: See eventOpen()

This function works just like eventOpen(), except that it gets called
for unlocking the door.

FTP 
******

It is an option for all creators to upload your code files to the mud 
via FTP. All you have to do is use an FTP client to connect to 
entropymedia.com 3999. Login with your normal username and password and 
the files will be automatically moved to your /realms/ directory. 
If you login anonymously, the files will be put in /ftp. Remember 
that if you log in anonymously, you can ONLY access /ftp.


-- Syra
.h files
--------

.h files are pretty easy to use.  There are examples everywhere (looking 
in the /domains/ directories is a good place to look if you want more 
examples).  They are important for various reasons, like cleaner code 
and the ability to move whole areas around the mud without having to 
change more than just one file.  Here is an example of what one looks 
like (you can find it in /domains/soleil/soleil.h):

#define SOLEIL_DIR   "/domains/soleil"
#define S_ROOM       SOLEIL_DIR + "/room"
#define S_NPC        SOLEIL_DIR + "/npc"
#define S_OBJ        SOLEIL_DIR + "/obj"

The first line (#define SOLEIL_DIR "/domains/soleil") tells the mud that 
whenever the string SOLEIL_DIR shows up, replace it with "/domains/soleil".
The second line (#define S_ROOM SOLEIL_DIR + "/room") tells the mud that
whenever S_ROOM comes up, it should replace it with SOLEIL_DIR + "/room",
which amounts to "/domains/soleil/room" when it's all done.  The third 
and fourth lines do just about the same thing, except that they reference 
where the NPC's and OBJ's are.

To make your own, you just need to replace the info in there with 
whatever your directories are and whatever you want your key phrases 
to be.  Just remember to #include the .h file in all the files you use 
those key phrases in.  Here are some examples of using it:

SetExits( ([
             "east" : S_ROOM + "/temple",
        ]) );

SetInventory( ([
                 S_NPC + "/banker_aegri" : 1,
            ]) );

SetInventory( ([
                 S_OBJ + "/pole_short" : "wield pole in right hand",
            ]) );

SetDoor("out",S_ROOM + "/cemet");

It's just like using any normal SetExits() or SetInventory() or 
SetDoor() or anything else that references a path, only you replace
part of that path with a shorter phrase.

Now go look at some of the /domains, like /domains/haven/ or 
/domains/jidoor, to see some more examples.

*******
Healers
*******

Healers are really very easy.  There are only two basic functions
which are differant than a basic Sentient.
 
int SetCharge(int);
Example:  SetCharge(10); 

    Sets the charge rate for healing.
    The rates are:
    Healing, per point == charge / 5
    Restoring Limbs    == Charge * 5
    Ressurection       == Charge * 50
 
string SetLocalCurrency(string);
Example:  SetLocalCurrency("imperials");

    Sets the local currency.
 
 
  PLEASE NOTE:  The charge is given as a normal number.
     This means that if you set a charge of 10, it will cost:
     50 of whatever coin you specify to restore a limb.
     This is NOT modified by the economy daemon.  Please remember
     that when setting prices.
 
  -- Duuk
  Modified by Amelia June 21, 1997
	      Introduction to Building Nightmare Objects
		     Nightmare IV Object Library
		 written by Descartes of Borg 951204

If you are anything like I was when I became a creator for the first
time, then your knowledge of computers consists of how to write a
paper using WordPerfect and how to play the games you like to play.
It probably seems like a long distance between that and actually
writing programs to run on a computer.  And the truth is, many years
ago it was.

Programming a computer is no longer really programming.  It is more
like playing with Legos.  Whereas you used to feed into a computer
step by step instructions on how the program is supposed to work,
today instead you fit objects together like pieces of a puzzle and
define their basic characteristics.  The object library handles the
rest.

Of course, that begs the question, what is an object?

It is easiest to understand the concept if you get out of the computer
mindset.  Just think about things like you do in every day life.
Objects simply are things.  Your house is an object, your car is an
object, your floor is an object, your cat is an object, and you are an
object.  Programming for an LPMud is simply about defining what
objects exist in the world.

What distinguishes you from your cat?  What distinguishes your cat
from your neighbour's cat?  Each object has two defining pieces, its
attributes and its behaviour.  An attribute is simply something that
is true of the object, for example, your cat has green eyes, while
your neighbours has blue.  Things such as name, eye colour, fur
length, tail length, mass, intelligence, etc. are all attributes.  In
building on muds, you will often hear attributes referred to as global
variables.

The other part of an object is its behaviour.  In the real world,
things happen to objects, and objects react.  Your cat sees a bird.
Seeing the bird causes the cat to salivate.  The cat in turn hunts the
bird.  The chain of events really goes on and on with no identifiable
beginning or end, except in the way you describe the event.  For
example, you could take the cat seeing the bird as being caused by the
bird landing, which was caused by its migration south, which was
caused by the change of seasons...

The bottom line is that the world is full of objects which behave in
response to events according to their attributes and built-in nature.
Building objects on a mud therefore is about setting the attributes
for specific objects and defining they way they react to certain
events.  Fortunately, the LPC language has built-in mechanism to make
this easy.  It is called inheritance.

Going back to the cat example, let's say you were going to build a
cat.  You could go and rewrite every piece of behaviour common to your
first cat and your neghbour's cat.  If you were going to build ten
cats, that would get tedious.  LPC allows you to build a generic cat,
then customize an instance of that generic class and make it your cat.

The Nightmare Object Library is what its name implies, a library of
objects that object-oriented terminology refers to as "abstract
classes".  An abstract class is a type of object you never see running
around the mud.  Instead, it is a building block used in the objects
you see running around the mud.  In other words, the object library
builds the concept of cat, and you use this to build individual cats.
Another analogy is that of the object library being like a Lego set.
You take the pieces it gives you to build specific objects.

In building an area, you know understand your task is to build the
objects which make up that area.  Building an object simply means
using the abstract classes the object library gives you to create
specific instances of those abstract classes.  You do this by defining
the specific attributes of the new objects, and defining new
behaviours.

You have probably heard me refer to the terms behaviour and event
interchangeably.  In philosophy, they are not interchangeable.  A
behaviour is a type of event which is defined as being caused by
something that meant to cause the event.  In other words, the cat
chasing the bird is behaviour, while the cat seeing the bird is simply
an event.  Both are considered events.  With respect to objects, you
are really defining events, since some events are actually
unintentional responses to other events.  The Nightmare Object Library
therefore refers to what you define in objects as events.

Writing an event in LPC is nothing more that providing step by step
instructions for what happens when a given event occurs.  The LPC term
for an event is a function (sometimes you will hear people refer to
functions as methods).  The Nightmare Object Library uses four types of
events:

#1 MudOS initiated events, sometimes called an "apply"
The names of these events are all lower case.  The most common apply
is the create() event.  It is caused by the creation of the object.

#2 Attribute manipulation events
These are the SetXXX() and GetXXX() events.  They exist basically to
allow other objects to find out about an object's attributes, or to do
initial setup for an object's attributes.

#3 Modal events
These are the CanXXX() events.  They get called often just prior to a
behaviour type of an event.  For example, I am trying to leave a room,
so my leave behaviour asks the room if I can leave.  This would be
CanLeave() in the room.  If CanLeave() says I can leave, then the
leave event is triggered in the room.

#4 True events
A true event is identified by eventXXX().  These type of events are
the meat of what is happening in the game.  Any given true event is
generally in turn triggered by some other true event.  The chain
generally can be traced as starting with a player or NPC command at
some point.

There are also two other types of functions which are not really
events, but instead simple routines that perform complex operations,
like the absolute_value() function.  These functions belong to no
particular object since they are not really events.  Instead any
object in the game may refer to them.  You will hear them referred to
sefuns (simul efuns) and efuns respectively.

So, an object in the Nightmare Object Library consists of all of these
events.  That sounds like you have a lot to do?  Not really.  The
object library itself defines almost all of the events needed for any
particular object.  Most often, you will be defining only one event
for any object, the creation event (create()).  

The event create() is triggered by MudOS for every single object when
it is first created.  This is therefore the ideal place for defining
what the attributes are for an object, so your create() generally ends
up being a series of SetXXX() calls.  In addition, if you add any
attributes, you will want to give them values in create().

Take for example an NPC.  Any NPC you build will have to have a name.
Thus, when it gets created, you want to be sure to set its name.  You
do this through the SetKeyName() event.

The documents in this directory primarily describe for you what
SetXXX() functions exist in objects to allow you to define your own
unique objects.  Once you are feeling comfortable with building simple
objects that only have create() behaviours, you can then start adding
other behaviours to objects.  For example, one type of behaviour you
can add to some rooms is to respond to someone digging in the room.
You thus define CanDig() and eventDig() events in addition to your
create() event.  In the event, whatever events you end up defining,
they end up being nothing more than modifying attributes of the object
in question, or causing events in other objects.
			  Building Any Item
		     The Nightmare IV LPC Library
		 written by Descartes of Borg 950430

Each object you build has a certain common make-up no matter what type
of object it is.  This is because all of your objects actually are
based upon the same object, the object called /lib/object.c.  That
object contains functions such as SetShort() and SetLong() which you
use in almost every single object you will build.  This document
details how to set up any possible object you will use.  The only
exceptions will be for rooms, which do not have key names or id's.

Beyond that, most of the every day objects you will code like armours,
weapons, drinks, foods, etc. all derive from a common object called
/lib/item.c.  This document attempts to detail what is involved in
building any object on the MUD through /lib/item.c and its ancestor
/lib/object.c.

This document is in three sections

I.  	List of Mandatory Function Calls
II.	Basic Functions
III.	Extras
IV.	Events

** ***************  List of Mandatory Function Calls  **************  **

SetKeyName("red bag");
Setid( ({ "bag" }) );
SetAdjectives( ({ "red" }) );
SetShort("a red bag");
SetLong("The small red bag has no distinguishing marks.");
SetMass(90);
SetValue(50);
SetVendorType(VT_TREASURE);

You also need to include vendor_types.h.

      **  ***************  Basic Functions  ***************  **

*****
SetKeyName()
*****

string SetKeyName(string key_name);

Example: SetKeyName("red bag");

Notes: 
	Mandatory for all objects except rooms.  
	Not used for rooms.

The key name is the central name by which the object is referred to in
sentences where no article is required.  For example, the sentence
"You pick up your red bag" makes use of the key name to complete the
sentence.  This is much like the short description, except the short
description will include an article.  For this object, SetShort("a red
bag") would be used.

*****
SetId()
*****

string *SetId(string *id);

Example: SetId( ({ "bag" }) );

Notes: 
	Mandatory for all objects except rooms.  
	Not used in rooms.
	Must be all lower case.

The id is an array of strings by which the object may be referred to by a
player.  For example, if the player wants to get this bag, the player
can type "get bag" or "get red bag".  The id is used purely for
identification purposes, so if you have something you need to sneak in
a unique way of identifying it, you may add an id only you know about.
Note:  We have added in SetAdjectives(), so the SetId() should only 
include nouns.  Read about SetAdjectives() below.

*****
SetAdjectives()
*****

string *SetAdjectives(string *adjs);

Example: SetAdjectives( ({ "red" }) );

Notes:
	This is just like SetId(), only you're putting in the adjectives.
This will allow you to make neat code instead of having to write out 
every way possible to look at your object.  It is expected to have 
all the possible adjectives.
	Not used in rooms.


*****
SetShort()
*****

string SetShort(string description | function desc_func);

Examples: 
	SetShort("a red bag");
	SetShort((: DescribeBag :));

The short description is a brief description of the object.  Only
names and proper nouns should be capitalized, the rest should be lower
case, as if it were appearing in the middle of a sentence.  In rooms,
the player sees the short description when in brief mode and when they
glance at the room.  For objects, the player sees the short when it is
described in the room or in their inventory.

If you pass a function instead of a string, then that function is used
to create the description.  You can use this to do something like make
the object change its short description depending on who is looking at
it.  The function that you build should therefore return a string
that will be used as the short description.  For example...

string DescribeBag() {
    if( query_night() ) return "a bag";
    else return "a red bag";
}

*****
SetLong()
*****

string SetLong(string description | function desc_func);

Examples:
	SetLong("The red bag has no markings on it at all.");
	SetLong((: BagLong :));

Creates a verbose way to present the object to the player.  You should
be much more descriptive than I have been in the example.  Being a
text game, descriptions are 90% of what make the game.  The more
creative you are with your descriptions, the more interesting the game
is to players.  The long description of a room is seen by players in
verbose mode and when the player uses the "look" command.  For
objects, the long description is seen when the player looks at the
object.  Functions work in exactly the same fashion as short
functions.

*****
SetMass()
*****

int SetMass(int mass);

Example: SetMass(100);

Notes:
	Mandatory for all visible objects.
	Not needed for non-tangible objects and rooms.

Sets the mass for the object.  In conjunction with the gravity of the
room it is in, this works to determine the weight of the object.

*****
SetValue()
*****

int SetValue(int value);

Example: SetValue(50);

Notes:
	Mandatory for all sellable objects.
	Not used in rooms.

Sets the base economic value of an object.  This has no meaning in any
currencies, and in fact the actual value in any given currency may
vary.

*****
  SetMaterial(string array);
*****
  example:  SetMaterial( ({ "wood", "natural" }) );

 Notes:

    Used to set materials needed to repair a given object.
    Acceptable materials are given in /doc/build/Materials.
    Feel free to add more if you check with an Arch first.

*****
  SetRepairSkills(mapping skills)

  example:  SetRepairSkills( ([ "wood working" : 1, 
                               "weapon smithing" : 1,
                                 ]) );
  
  Notes:
   
    Sets the skills required to repair a given object, along with the 
    minimum skill levels.

*****
  SetRepairDifficulty(int)

  example:  SetRepairDifficulty(20);

  Notes:
  
    Sets the difficulty a player will encounter when trying to repair
    a given object.  See balance docs.

*****
SetVendorType()
*****

int SetVendorType(int vt);

Example: SetVendorType(VT_BAG);

Note:
	Mandatory for all objects except rooms.
	Preset to VT_ARMOUR for objects which inherit LIB_ARMOUR.
	Preset to VT_TREASURE for objects which inherit LIB_ITEM.
	Preset to VT_LIGHT for objects which inherit LIB_LIGHT.
	Not valid for room objects.
	Values are found in /include/vendor_types.h.

You must do:
#include <vendor_types.h>
to use the VT_* macros (i.e. VT_ARMOUR, VT_TREASURE, VT_WEAPON).

The vendor type determines which shops will buy the item.  For
example, things with VT_BAG as the vendor type can be bought and sold
in bag stores.  For items which cross the line, for example a flaming
sword, you can combine vendor types in the following manner:
	SetVendorType(VT_WEAPON | VT_LIGHT);

*****
SetDamagePoints()
*****

int SetDamagePoints(int pts);

Example: SetDamagePoints(500)

Sets the amount of damage an object can take before descreasing in
value.  With armours and weapons, damage is taken quite often.  Damage
is more rare with other kinds of objects.  With this example object
which has 500 damage points, whenever 500 points has been done to it,
its value is cut in half and eventDeteriorate() is called for the
object.  See the events section on using eventDeteriorate().  The
points are then reset to 500 and damage is done from that.
 
	   **  ***************  Extras  ***************  **

*****
SetProperty()
*****

mixed SetProperty(string property, mixed value);

Example: SetProperty("no pick", 1);

Allows you to store information in an object which may not have been
intended by the designer of the object, or which is fleeting in
nature.  See /doc/build/Properties for a list of common properties.
*****
SetProperties()
*****

mapping SetProperties(mapping props);

Example: SetProperties( ([ "light" : 1, "no attack" : 1 ]) );

Allows you to set any properties you want all in one shot.

*****
SetDestroyOnSell() 
*****

int SetDestroyOnSell(int true_or_false);

Example: SetDestroyOnSell(1);

For mundane objects, or objects which should not be resold, allows you
to set it so that the object gets destroyed when sold instead of
allowing it to be resold.

*****
SetPreventGet()
*****

mixed SetPreventGet(mixed val);

Examples:
	SetPreventGet("You cannot get that!");
	SetPreventGet( (: check_get :) );

Allows you to make an object un-gettable by a player.  If you pass a
string, the player will see that string any time they try to get the
item.  If you pass a function, that function will be called to see if
you want to allow the get. Your function gets the person trying to get
the object as an argument:

int check_get(object who) {
    if( (int)who->GetRave() == "ogre" ) {
	message("my_action", "Ogres cannot get this thing!", who);
	return 0;
    }
    else return 1;
}

*****
SetPreventPut()
*****

mixed SetPreventPut(mixed val);

Examples:
	SetPreventPut("You cannot put that in there!");
	SetPreventPut( (: check_put :) );

The same as SetPreventGet(), except this is used when the object is
being put into another object.

*****
SetPreventDrop()
*****

mixed SetPreventDrop(mixed val);

Examples:
	SetPreventDrop("You cannot drop that!");
	SetPreventDrop( (: check_drop :) );

The same as SetPreventGet(), except this is used when a player tries
to drop the object.


       **  ***************  General Events  **************  **

*****
eventDeteriorate()
*****

void eventDeteriorate(int type);

Example: ob->eventDeteriorate(COLD);

Notes:
	Damage types can be found in /include/damage_types.h

This function gets called periodically in objects whenever they wear
down a bit.  The type passed to the function is the type of damage
which triggered the deterioration.

*****
eventMove()
*****

int eventMove(mixed dest);

Example: 
	ob->eventMove(this_player());
	ob->eventMove("/domains/Praxis/square");

The eventMove event is called in an object when it is being moved from
one place to the next.  You can either pass it the file name of a room
to which it should be moved or an object into which it should be
moved.  It will return true if the object gets moved, false if it
cannot move for some reason.  For objects which are being dropped,
gotten, or put, it is generally a good idea to check CanDrop(),
CanClose(), or CanGet() for the object in question since eventMove()
does not know the context of the move and therefore will allow a drop
since it does not check CanDrop().

*****
eventReceiveDamage()
*****

varargs int eventReceiveDamage(int type, int amount, int unused, mixed limbs);

Example: ob->eventReceiveDamage(BLUNT, 30, 0, "right hand");

This function gets called in an object whenever any damage is done to
it.  Most frequently this gets called in monsters and armour.  In
armour you can use it to modify the amount of damage which gets done.
The return value of this function is the amount of damage done to the
object.  For example, if you have a piece of armour that absorbs 5 of
the 30 points listed above, then you return 5.  

NOTE:
	For monsters there is an extra arg at the front called
	agent.  The agent is the being responsible for doing
	the damage.  It may be zero if something like the weather
	is causing the damage.  It looks like:

varargs int eventReceiveDamage(object agent, int type, int strength, 
	int internal, mixed limbs);

	For more detailed information, see /doc/build/NPC.

metal
textile
wood
leather
stone
natural
mithril
		   Building Food and Drink Objects
		     The Nightmare IV LPC Library
		 written by Descartes of Borg 950603

This document details the creation of food and drinks using the
Nightmare LPC Library.  The creation of barkeeper objects requires you
to be able to build these objects, so make sure you understand what is
going on in here before moving on to barkeepers.

To create food or drink, you inherit from the standard meal object
/lib/meal.c  For example:

#include <lib.h>

inherit LIB_MEAL;

You have access to the same functions you have in generic items when
you build food and drinks.  In particular, you should be sure to call
the following:

SetKeyName()
SetId()
SetShort()
SetLong()
SetMass()

Note that SetValue() does NOTHING for food and drinks.  Value is
automatically determined by the strength of the item.

The following function calls are specific to "meal" objects:

int SetMealType(int types);
int SetStrength(int strength);

mixed *SetMealMessages(function f);
OR
mixed *SetMealmessages(string mymsg, string othermsg);

string SetEmptyName(string str);
string SetEmptyShort(string str);
string SetEmptyLong(string str);
string SetEmptyItem(string str);

You must call SetMealType(), SetStrength(), and SetMealMessages().
If you call SetEmptyItem(), you do not need to call the functions
SetEmptyName(), SetEmptyShort(), SetEmptyLong().  On the other hand,
if you do not call SetEmptyItem(), you do need to set the other three.

*****
int SetMealType(int types)
*****

Example: SetMealType(MEAL_FOOD);

For meal objects, you must do:

#include <meal_types.h>

This includes all od the definitions for the meal types in
/include/meal_types.h into your food or drink.  You need these
definitions when setting what type of meal object this is.  The types
are:

MEAL_FOOD       
MEAL_DRINK      
MEAL_CAFFEINE    
MEAL_ALCOHOL     
MEAL_POISON      

In general, almost anything you create will be at least either
MEAL_FOOD or MEAL_DRINK.  You can add onto it using the | operator.
For example, to make an alcoholic drink:

SetMealType(MEAL_DRINK | MEAL_ALCOHOL);

This makes something a drink and an alcoholic drink.  You want to
stick poison in it?

SetMealType(MEAL_DRINK | MEAL_ALCOHOL | MEAL_POISON);

*****
int SetStrength(int x)
*****

Example: SetStrength(20);

This sets how strong your food or drink is.  It affects things like
which people can drink or eat it and how much the drink or food costs.
Refer to balance documents to see what is good.

*****
varargs mixed *SetMealMessages(function|string, string)
*****

Examples:
	SetMealMessages((: call_other(find_object("/some/object"),"drink") :));
	SetMealmessages("You drink your beer.", "$N drinks $P beer.");

You can pass a single argument, which is a function to be called.
This function will be called after the person has drank or eaten the
meal.  It gives you a chance to do some bizarre messaging and such.

If you pass two strings, the first string is used as a message to send
to the player doing the drinking, and the second is what everyone else
sees.  To make the message versatile, you can put in the following
place holders:

$N the name of the drinker/eater
$P his/her/its

For example:
$N drinks $P beer.
might resolve to:
Descartes drinks his beer.

*****
string SetEmptyName(string str)
*****

Example: SetEmptyName("bottle");

Sets an id from the empty container of drinks.  This need not be set
for food.

*****
string SetEmptyShort(string str)
*****

Example: SetEmptyShort("an empty bottle")

Sets what the short description of the empty container is for anything
that is of type MEAL_DRINK.

*****
string SetEmptyLong(string str)
*****

Example: SetEmptyLong("A brown bottle that used to contain beer.");

Sets the long description for the empty container for drink objects.

*****
string SetEmptyItem(string str)
*****

Example: SetEmptyItem("/domains/Praxis/etc/empty_bottle")

Instead of cloning a generic empty object and setting the other empty
functions, you can create a special empty container which gets given
to the player after they drink a drink object.  Not relevant to food.
		    Building Non-Player Characters
		   The Nightmare IV Object Library
		 written by Descartes of Borg 951201

This document outlines the creation of non-player characters (NPC's).
On other muds, NPC's are sometimes referred to as monsters.  Like the
rooms document, this document is divided up into two sections: basic
NPC building and complex NPC building.  NPC's are living things which
inherit all the behaviours of living things.  Documentation on living
specific functionality may be found in /doc/build/Livings.

           ************************************************
		      Part 1: Basic NPC Building
           ************************************************

*****
I. The simplest NPC
*****

#include <lib.h>

inherit LIB_NPC;

static void create() {
    npc::create();
    SetKeyName("praxis peasant");
    SetId( ({ "peasant", "praxis peasant" }) );
    SetShort("a local peasant");
    SetLong("Dirty and totally disheveled, this poor inhabitant of Praxis "
	    "still somehow maintains an air of dignity that nothing can "
	    "break.");
    SetLevel(1);
    SetRace("elf");
    SetClass("fighter");
    SetGender("male");
}

There are two things you should note.  The first is that an NPC is
also a general object, meaning that you have available to you all the
things you can do with general objects, like setting descriptions and
ID's.  The second is that a basic NPC does not require a heck of a lot
more.  I will cover the NPC specific functions here.

SetLevel(1)
SetRace("elf")
SetClass("fighter")
Level, race, and class are the three most important settings in any
NPC.  Together they determine how powerful the NPC is.  You are
absolutely required to set a level and a race.  For those who
absolutely do not want to give the NPC a class, you do not have to.
But, you must instead manually set the NPC's skill levels, which is
described in the second part of this document.  In general, however,
you always want to set the class.

Together, the class and race and level determine which skills and
stats are considered important for the monster, and how good at those
skills and stats the monster is.  The order in which you call these
functions is irrelevant, as everything is recalculated any time one of
the above changes.

Also, note that SetRace() may only be called with a race listed in the
mraces command with simple NPC's.  If you wish to build an NPC with a
unique race, you need to do some limb manipulation, which is described
in the advanced section.

SetGender("male")
While not required, you will normally want to give an NPC a gender.
The default is neutral.  However, in this world, very little is
neuter.  Your choices for this function are male, female, and neuter.

*****
II. Other NPC Configuration Functions
*****

Function: int SetMorality(int amount);
Example: SetMorality(100);

This is a number between -2000 and 2000 which determines the morality
of an individual with respect to good and evil.  -2000 is absolute
evil, and 2000 is absolute good.  The actions of players determine
their morality, and often those actions are relative to a target.
Thus killing an evil being can be considered good, while killing a bad
one evil.

Function: int SetUnique(int x);
Example: SetUnique(1)

Marks the NPC as a unique monster.  This allows the room which clones
your NPC to use the negative values to SetInventory() (see
/doc/build/Rooms) to make sure the NPC only gets cloned every few
days.

           ************************************************
		    Part 2: Advanced NPC Building
           ************************************************

*****
I. Functions
*****

You may use these functions to make your NPC's a bit more interesting
than the simple variety.

Function: void SetAction(int chance, mixed val);
Examples: SetAction(5, (: DoSomething :));
          SetAction(5, ({ "!smile", "!frown" }));
          SetAction(5, ({ "The peasant looks unhappy." }));

Sets something to randomly happen every few heart beats while the NPC
is not in combat.  In the above examples, the NPC has a 5% chance each
heart beat of performing the action you provided with the second
argument.  The action can be a call to a function, a list of potential
commands, or a list of strings to be echoed to the room.

If you pass a function, that function will be called each time an
action is supposed to occur.  If you pass a list of strings, one of
those strings will be randomly chosen as the target action for this
heart beat.  If the chosen string begins with a !, it is treated as a
command.  Otherwise, it is simply echoed to the room.  Note that you
can mix commands and echo strings.

*****

Function: void SetCombatAction(int chance, mixed val);
Examples: SetCombatAction(5, (: DoSomething :));
          SetCombatAction(5, ({ "!missile", "!fireball" }));
          SetAction(5, ({ "The peasant looks angry." }));

This function works exactly the same as SetAction(), except that these
actions only get triggered while the NPC is in combat.  This is the
best place to have the NPC cast spells.

*****

Function: varargs void SetCurrency(mixed val, int amount); 
Examples: SetCurrency("gold", 100);
          SetCurrency( ([ "gold" : 100, "electrum" : 1000 ]) );

This function allows you to set how much money an NPC is carrying.
The first syntax allows you to set one currency at a time.  The second
allows you to set multiple currencies at once.  Not that if you use
the second syntax, it will blow away any currencies the NPC might
already be carrying.

*****

Function:  SetFriends(string *Friends);
Example:   SetFriends( ({ "dog", "bandit" }) );

This function allows you to set NPCs to react to threats together.
By using SetFriends, the NPC will react when its friends are attacked,
and vice versa.  Note the following to make it work:
  the values in SetFriends() check the KeyName of the friends, not
  simply an ID, so you must be sure to use the correct name.  Also, 
  be sure to use the function in BOTH NPCs if it is to work in both
  directions.

*****

Function: mixed SetDie(mixed val);
Examples: SetDie("The black knight bleeds on you as he drops dead.");
          SetDie((: CheckDie :));

If you pass a string, that string will be echoed as the NPC's death
message when it dies.  If you pass a function, that function gets
called with the agent doing the killing, if any, as an argument.  For
example, with the above example, the function that you write:

int CheckDie(object killer);

gets called.  If you return 1, the NPC goes on to die.  If you return
0, the NPC does not die.  In the event you prevent death, you need to
make some arrangements with the NPC's health points and such to make
sure it really is still alive.

*****

Function: mixed SetEncounter(mixed val);
Examples: SetEncounter(40);
          SetEncounter( (: CheckDwarf :) );
          SetEncounter( ({ str1, str2 }) );

This allows you to set up e behaviour for an NPC upon encountering
another living thing.  Note that this behaviour occurrs for both
players and other NPC's.  Using the first syntax, the NPC will simply
attack any other living thing with a charisma less than 40.  The
second syntax calls the function you specify.  You may have it do any
number of things, however, you must also return a 1 or a 0 from that
function.  A 1 means that after the function is called, the NPC should
initiate combat against the thing it just encountered.  A 0 means
carry on as usual.

Finally, the third syntax is likely to be used in places other than
the create() funciton in the NPC.  This syntax lets you set a list
names which are simply enemies to the NPC.  More likely, you will be
using AddEncounter() and RemoveEncounter() for this.

*****

Function: string *AddEncounter(string name);
Example: AddEncounter((string)this_player()->GetKeyName());

Adds a name to the list of names an NPC will attack on sight.

*****

Function: string *RemoveEncounter(string name);
Example: RemoveEncounter((string)this_player()->GetKeyName());

Removes a name from the list of names an NPC will attack on sight.

*****

Function: SetInventory(mapping inventory);
Examples:
	SetInventory( ([ "/domains/Praxis/weapon/sword" : "wield sword" ]) );
	SetInventory( ([ "/domains/Praxix/etc/ruby" : 1 ]) );
	SetInventory( ([ "/domains/Praxis/etc/emerald" : -10 ]) );

This functions behaves almost identically to SetInventory() for rooms
(see /doc/build/Rooms).  The big difference is that you may pass a
string in addition to a number as the value for any item you want in
the inventory.  In the first example above, that string is the command
the NPC issues when the sword is cloned into its inventory.  In other
words, if you want an NPC to do something special with an item it has
in its inventory, in this case wield the sword, you pass the command
string as the value instead of a number.

Note that this means only one of such item will be cloned, and it
cannot be unique.

*****
II. Events
*****

The following events exist in NPC's.  You should have a good grasp of
function overriding before overriding these functions.

Event: varargs int eventDie(object target);

This event is triggered any time the NPC is killed.  The event returns
1 if the NPC dies, 0 if it fails to die, and -1 on error.  If you
intend to allow the NPC to die, you should call npc::eventDie(target)
and make sure it returns 1.

*****

Event: int eventFollow(object dest, int chance);

This event is triggered whenever an NPC is following another living
thing and that thing leaves the room.  Returnung 1 means that the NPC
successfully followed the other being, and 0 means the NPC did not.

*****
3. Manipulating limbs
*****

The basic set of limbs an NPC gets is generally set when you set its
race.  You can get a list of supported NPC races through the mraces
command.  Occassionally, however, you may want to create NPCs of
unique races, or with unique body structures.  Or perhaps you want a
human whose right hand is already amputated.  This section deals with
doing those things.

Amputating a limb is simple.  Call RemoveLimb("limb").  Note that that
is not useful for removing a limb that should not be there.  Instead,
it is used for amputating a limb that looks amputated.

If, on the other hand, you wish to remove a limb which simply should
not have been there in the first place, call DestLimb("limb").

The most simple case of actual limb manipulation, however, is to
change the basic structure of an individual NPC around for some
reason.  For example, perhaps you wanted to add a tail to a human.
For this, you use the AddLimb() function.

Function: varargs int AddLimb(string limb, string parent, int class, int *armours);
Examples: AddLimb("tail", "torso", 4)
          AddLimb("head", "torso", 1, ({ A_HELMET, A_VISOR, A_AMULET }));
       
This function adds a new limb to the NPC's body.  The first argument
is the name of the limb to be added.  The second argument is the name
of the limb to which it is attached.  The third argument is the limb
class.  Limb class is a number between 1 and 5.  The lower the number,
the harder the limb is to remove.  A limb class of 1 also means that
removal of the limb is fatal.  The fourth, optional argument is a list
of armour types which may be worn on that limb.

In some cases, you may wish to create a new race from scratch.  This
requires adding every single limb manually.  You first call SetRace()
with a special second argument to note that you are creating a new
race:

SetRace("womble", 1);

Then, you add the limbs for that race one by one.  Make sure you call
SetRace() first.
			 Supported Properties
		     The Nightmare IV LPC Library
		 written by Descartes of Borg 950429
                 amended to Haven by Duuktsaryth@Haven 30 July 1998

The Nightmare IV LPC Library allows creators to set dynamic variables in
objects which do not get saved when the object saves.  The variables are
called properties.  A property is an attribute of an object which is
considered fleeting.  This document serves to list the properties
commonly used and their purpose.  It is by no means complete, as the
point of having properties is to allow creators to build their own on the
fly.

Note: All properties are 0 by default unless otherwise stated.

Property: no attack
Values: 1 to prevent attacks, 0 to allow them
Things cannot begin combat from inside a room with this property.

Property: no bump
Values: 1 to prevent bumping, 0 to allow it
If a room, then nothing can be bumped from this room.  If a living
thing, then it cannot be bumped.

Property: no steal
Values: 1 to prevent stealing, 0 to allow it
This prevents stealing inside a room with this property.

Property: no magic
Values: 1 to prevent magic, 0 to allow it
This prevents any magic from being used inside the room if set.
Also: no conjuring, no chaos magic, no natural magic, no faith,
      no enchantment, no evokation, no necromancy, no healing,
     no planar magic, no divination
These prevent spells of the appropriate type being cast.

Property: no paralyze
Values: 1 prevents paralysis from occurring in a room, 0 allows it
Stops any sort of thing which might cause paralysis from occurring in
a room.

Property: no teleport
Values: 1 if teleporting is prohibited, 0 if allowed
Prevents people from teleporting to or from the room.



Property: magic 
Sets the string value that tells a magic item from a normal one.
For example, SetProperty("magic", "This magical staff glows.");

Property: lockpicking tool
Values: any integer marking how well lockpicking is enhanced
When picking a lock, the value of this property is calculated for each
object and added to the overall chance to pick the lock.

Property: blessed
Value: any integer
  Sets an amount of blessing on an object which will
  affect the abilities of weapons or armour.

Property: history
Value: A string
  Sets the 'history' of special items which can be determined
  by diviners or bards.

Property: login
Value: a string representing a file name
Sets which room a player should login to at next login if they quit
from the room that has this property.  For example, if you have a
treasure room that is protected, and therefore you do not want people
logging into it, you can call:
	SetProperty("login", "/file/name/outside/this/room");
to have the players login to the room outside.
			   Building Quests
		  from the Nightmare IV LPC Library
		 written by Descartes of Borg 950716

Unlike previous Nightmare versions, Nightmare IV has no support for
centralized quest administration.  This was done under the belief that
coercive questing was among the least favourite features players have
mentioned about the MUDs I have encountered.  Nevertheless, the
presence of quests is still an extrememly important part of any MUD.
Since the coercive nature (needing to complete quest X to raise to
level Y) has been removed, other ways to make questing worthwhile need
to be found.

The first, and most obvious, is to properly reward the player with
money, items, and skill and stat points.  The other bit of support is
for a title list.  Each quest, or accomplishment, is added to a list
of accomplishments the player has.  The player may display any of
those at any time as part of their title.

The interface to this is simple:

player_object->AddQuest(string title, string description);

Example:

this_player()->AddQuest("the slayer of frogs", 
	"You viciously slayed the evil frogs of Wernmeister that "
	"threatened the peaceful town with warts and unabated fly murder.");

In the player's biography, they will see the description along with
the date they accomplished the task.  From their title list, they will
now be able to choose this title.

Descartes of Borg
950716
// Amelia@Haven

REPAIR SKILLS
-------------
The following are the different repair skills:

- armour smithing
- weapon smithing
- metal working
- textile working
- wood working
- leather working
- stone working
- natural working
- mithril working

You should use all the various ones that apply to your object.  These are
the materials the object is made up with + working (wood working and
stone working, for instance, for a axe w/ a stone head and a wooden 
handle).  As well, weapons should have weapon smithing and armours
should have armour smithing.
                            Building Rooms
                     The Nightmare IV LPC Library
                 written by Descartes of Borg 950420

This document details how to build rooms using the Nightmare IV LPC
Library's inheritable room object.  This document is divided into
simple room building and complex room building.  The first part
teaches you about basic rooms.  The second part tells you what
features are there to allow you to do creative things with the room object.

           ************************************************
                     Part 1: Basic Room Building
           ************************************************

I. The Simple Room
The simple room minimally looks like this:

#include <lib.h>

inherit LIB_ROOM;

static void create() {
    room::create();
    SetClimate("indoors");
    SetAmbientLight(40);
    SetShort("an empty room");
    SetLong("The empty room has no exits leading anywhere.  It is "
            "completely barren with nothing to describe.");
}

#include <lib.h>
This first line is one you need in any object.  It defines the exact
location of objects which you inherit.  In this case, the object is
LIB_ROOM.  It is currently located at /lib/room.c.  If we wanted to
change that location, however, we could do it easily since you only
reference LIB_ROOM.  So lib.h is a file that says that LIB_ROOM is
"/lib/room".

inherit LIB_ROOM;
The third line, the inherit line, says that this object will inherit
/lib/room.c.

static void create() {
The fifth line begins the meat of any object you will write.  This is
the beginning of a function.  This one is called create().  If you are
curious, the static means no one can use the call command to call the
function.  Do not worry about that too much, however, as it is always
something you put there for the create() function.

The "void" part simply says that you are returning no value from the
function.  See the LPC Basics textbook for more information on
functions.

room::create();
Inside the create() function are the calls which define what the
object will do.  The first call calls the function create() in
/lib/room.c, the object you just inherited.  /lib/room.c has its own
create() function which does some things needed in order to set up
your object.  You need to make sure it gets called through this line.

SetClimate("indoors")
Every room has a climate.  An indoors room, among other things, is not
affected by weather or the time of day.  A list of climate types can be
found in /doc/build/Climates

SetAmbientLight(40);
This sets the light of an indoors room to 40.  That is a fairly average
number.  Outdoors rooms use SetDayLight() and SetNightLight().  These
functions take whatever number you give them, and add it on
to the normal day and night light values.  SetAmbientLight() is
required in all indoors rooms.  SetDayLight() and SetNightLight() are only needed
in rooms with special light that are not inside.

SetShort("an empty room")
This is the description that the player sees when in brief mode.  In
addition, in brief mode, obvious exit abbreviations are automatically
added.  This is done through the SetObviousExits() function described
later.  However, the short should be phrased in such a way that it
makes sense from something like a scry command which would say
something like: "You see Descartes in an empty room."

SetLong("The empty room has no exits leading anywhere.  It is "
            "completely barren with nothing to describe.");
This sets the long description seen by the player when in verbose
mode.   Note that items in the room as well as scents and sounds are
added to what the player sees automatically.

That's it! You now have a room which no one can leave!

II.  Adding items
Approval on any decent MUD will eat you for lunch if you do not
describe your items.  This is likely the most tedious part of area
building, however, it is also the part that largely makes the
difference between a dull area and a fun one.  You must be sure to
make it so that anything a player might logically want to see in
detail in a room is described in detail.  For example, say you have
the following long description for a room:

You are in Monument Square, once known as Krasna Square. The two main
roads of Praxis intersect here, where all of Nightmare's people gather
in joy and sorrow.  The road running north and south is called Centre
Path, while Boc La Road is the name of the road running east and west.
A magnificent monument rises above the square.

You should have descriptions for the following items placed in your
room:

square, monument, monument square, krasna square, roads, road,
intersection, people, centre path, boc la road, magnificent monument

How to do this with a minimum of hassle:

SetItems( ([ ({ "square", "monument square", "krasna square" }) :
        "The central square of Praxis where citizens and adventurers "
        "gather to chat and trade.  Formerly known as Krasna Square, "
        "is now known as Monument Square as thanks to those who helped "
        "to build the town",
        ({ "monument", "magnificent monument" }) : "A giant monolith "
        "rising above Monument Square",
        ({ "intersection", "road", "roads" }) : "The two main roads of Praxis "
        "intersect in Monument Square.  The one to the north and south "
        "is called Centre Path, while the other is Boc La Road.",
        ({ "people", "adventurers", "citizens" }) : "A varied group of "
        "people from countless realms hanging about talking and trading.",
        "centre path" : "The main road leading north to the North Forest "
        "from Praxis, and south to the sea.",
        "boc la road" : "The main east-west road through Praxis, going "
        "east towards the jungle, and west towards the Daroq Mountains." ]) );

That may seem like a mouthful, but it is easier to break down into
smaller points and see what is going on.  The SetItems() prototype
looks like this:

mapping SetItems(mapping items);

That means it accepts a data type called a mapping as the argument and
returns a new mapping of items.  A mapping is a special data type in
LPC that allows you to associate two values together, for example, to
associate an item with its description.  For example, above we wanted
to associate the items "monument" and "magnificent monument" with the
description "A giant monolith rising above Monument Square".  To do
that, a mapping looks like this:

([ value1 : assoc_value1 ])

where assoc_value1 is the value associated with value1.  In this case,
we might have something like:

([ "monument" : "A giant monolith rising above Monument Square." ])

But, we also wanted to associate "magnificent monument" with this
description.  One way, which is perfectly legitimate, would be:

([ "monument" : "A giant monolith rising above Monument Square",
   "magnificent monument" : "A giant monolith rising above Monument Square" ])

But that would be damned annoying, especially with long descriptions
or things with a lot of synonyms.  You can therefore group values
which have the same description together using array notation:
({ value1, value2, value3 })

And thus, make that mapping look like:

([ ({ "monument", "magnificent monument" }) : "A giant monolith rising "
  "above Monument Square." ])

To complete setting the items, you simply add other item/description
pairs separated by commas:

([ ({ "monument", "monument square" }) : "A giant monolith rising "
  "above Monument Square.",
   "house" : "A little white house with white picket fences." ])

Mappings are a rather difficult concept to grasp, but once grasped
they are very powerful.  You should take a look at some sample code
from /domains/Examples/room to get a good idea of what proper code
looks like.  In addition, there is a chapter in Intermediate LPC
dedicated to the concept.  Finally, you can always mail
borg@imaginary.com to ask questions.

IIb. Addendum - Setting Adjectives for your SetItems

In an effort to simplify the process of defining items in rooms 
the function SetItemAdjectives was implimented. Like SetItems, the
function take a mapping with the key being one of the items defined
in SetItems.

ie.
  
  SetItems( ([ ({"desk"}) : "A polished writing desk.",
               ({"blue chair","chair"}) : "A broken old blue chair.",
               ({"red chair","chair"}) : "A shiny new red chair.",
          ]) );
  
  SetItemAdjectives( ([ "desk" : ({"polished","writing"}),
                        "blue chair" : ({"blue","broken","old"}),
                        "red chair" : ({"red","shiny","new"}),
                   ]) );

Where the key in the SetItemAdjectives mapping is one of the keys from
the SetItems mapping. (ie 'desk' in SetItemAdjects matches up with 
'desk' in SetItems and 'blue chair' lines up with 'blue chair') The 
values of the SetItemAdjectives mapping are the adjectives being added 
to the Item.  

In SetItems it is important that if you have more than one item of the
same type, (ie 'red chair' and 'blue chair') you will need to add those
permutations of the items in SetItems.  If there is only one item of a
type (ie 'desk') then listing it without any additional descriptor is
fine.

SetItemAdjectives MUST be after SetItems to work.

III. Adding Exits and Enters
If you understand the section above, exits and enters are simple.
They too use mappings, but less complicated ones:

SetExits( ([ "north" : "/domains/Praxis/n_centre1",
             "south" : "/domains/Praxis/s_centre1",
             "east" : "/domains/Praxis/e_boc_la1",
             "west" : "/domains/Praxis/w_boc_la1" ]) );

SetEnters( ([ "hall" : "/domains/Praxis/town_hall",
              "pub" : "/domains/Praxis/pub" ]) );

With an exit mapping, you simply match the direction to the room to
which it leads.  With an enter mapping, you match a thing being
entered with the room to which it leads.

Unlike other LPC Libraries, the Nightmare IV LPC Library distinguishes
between the concept of motion towards and motion into.  Motion towards
is exemplified by the "go" command, which is affected by SetExits().
For example, to go east, you type "go east".  You are simply going
towards the east (Note that "go east" is by default aliased to "e").

Motion into is exemplified by the "enter" command, which is affected
by SetEnters().  Enter marks anything you enter into, for example a
building or bushes or the like.  In the above example, a player would
issue the command "enter pub" to enter the pub.

IV. Adding Objects
If you want to add physical objects into your room, you use the
SetInventory() function.  For example, if you wanted to place a balrog
in the room:

    SetInventory(([ "/domains/Praxis/npc/balrog" : 1 ]);

Every reset, the room will then check to see if any balrogs are in the
room.  If no balrogs are in the room it will clone 1.  Again, this is
another function using a mapping.  In this case it is associating the
file name of an object with how many of that object should be in the
room at every reset.  If you wanted 5 balrogs in the room, you would
have changed the 1 to 5.

V.  Adding Smells, Listens, and Searches

The functions:
SetSmell()
SetSearch()
SetListen()

All work identically to the SetItems() function.  That is they match
things you can smell, listen, search to descriptions which the player
sees when they smell, listen, search the item.

For example:

SetSmell( ([ "monument" : "It smells of obsidian.",
             "road" : "It smells dusty.",
             ({ "pub", "bar" }) : "It smells of alcohol." ]) );

If a player types:
"smell monument"
then they see
"It smells of obsidian."

One unique thing about these three functions, however, is that you can
use the special thing "default" to set a smell, listen, or search that
occurs when no object is specified.  For example,

SetSmell(([ "default" : "It really stinks here." ]) );

Will have the player see "It really stinks here." when they simply
type "smell".  In addition, this is the smell the player sees when
they simply walk into a room.

VI. Miscellaneous stuff

SetDomain("WestWood")
Sets the Domain the room is in.  A list of valid domains
is in /doc/build/Domains.  This function is necessary
in all rooms that are not indoors or underground.

SetObviousExits("north, south, east")
Sets an obvious exits string which gets seen in brief mode and by
newbies in verbose mode.  Generally, this should consist of the
room's obvious exits only.
SetObviousExits() is not necessary except in rooms with hidden exits.
When not set, obvious exits will be done automatically,
consisting of all the exits.  Enters should not be listed
in the obvious exits, either.

SetTown("Praxis")
For rooms which are considered part of a town, you must specify that
they are part of the town through this function.  In this example, the
room is set to be in the town of Praxis.  See the document
/doc/build/Towns for more information on towns.

SetDayLong("The sky lights up the endless fields of wheat which stand "
           "before you.");
SetNightLong("You are standing in a pitch black field of wheat.");
Instead of using SetLong(), you can call both of these functions to
give different long descriptions for day and night.

SetGravity(2.0)
This makes things in the room twice as heavy as normal.

SetDoor("east", "/domains/Praxis/doors/red_door");
Sets a door to the east which is the file
"/domains/Praxis/doors/red_door.c".  You should have an exit to the
east, and you should do this AFTER you have called SetItems().  See
the document /doc/build/Doors for detailed information on door
building.

VII.  Summary

Here is a room that uses everything described above:

#include <lib.h>

inherit LIB_ROOM;

static void create() {
    room::create();
    SetProperty("light", 2);
    SetClimate("temperate");
    SetTown("Praxis");
    SetShort("a peaceful park");
    SetDayLong("The light of the sun shines down upon an open field "
               "in the middle of Praxis known as Kronos Park.  In spite "
               "of the time of day, no one is around.  East Boc La "
               "Road is to the south.");
    SetNightLong("Kronos Park is a poorly lit haven for rogues in the "
                 "cover of night.  It is safest to head back south "
                 "towards the lights of East Boc La Road");
    SetItems( ([ ({ "field", "park" }) : "A wide open park in the "
                 "center of Praxis." ]) );
    SetSearch( ([ "field" : "You get dirt all over your hands." ]) );
    SetSmell( ([ "default" : "You smell grass after a fresh rain.",
                 "dirt" : "It smells like... dirt!" ]) );
    SetExits( ([ "south" : "/domains/Praxis/e_boc_la3" ]) );
    SetInventory( ([ "/domains/Praxis/npc/rogue" : 2 ]) );
}

           ************************************************
                    Part 2: Advanced Room Building
           ************************************************
I. Functionals
MudOS has a data type called a functional.  Most room functions take a
functional as an argument instead of a string.  What this does is
allow you to specify a function to get called in order to determine
the value rather than set it as a string which cannot be changed.  For
example, if you wanted to set a long description that varied depending the
status of a door:

#include <lib.h>

inherit LIB_ROOM;

string CheckDoor(string useless);

static void create() {
    room::create();
    SetProperty("light", 2);
    SetClimate("indoors");
    SetShort("an indoor room with a door");
    SetLong( (: CheckDoor :) );
    SetExits( ([ "east" : "/domains/Praxis/east_room" ]) );
    SetDoor("east", "/domains/Praxis/doors/red_door");
}

string CheckDoor(string useless) {
    string tmp;

    tmp = "You are in a plain indoor room with a door.  ";
    if( (int)"/domains/Praxis/doors/red_door"->GetOpen() )
      tmp += "The door is open.";
    else tmp += "The door is closed.";
    return tmp;
}

In this example, a function called CheckDoor() was written to
determine exactly what the long description should be.  This is done
because in create(), you have no idea what the status of the door will
be from moment to moment.  Using a function, you can therefore
determine what the long description is at the time it is needed.

Functionals can reference any function anywhere on the MUD, including
efuns.  See /doc/lpc/data_types/functionals for details on them.  For
the sake of this document however, you note a functional using smileys
:).

(: CheckDoor :) means the function CheckDoor() in this object.  You
can also specify function in other objects, for example:
(: call_other, this_player(), "GetName" :) would refer to GetName() in
the person who was this_player() AT THE TIME THE FUNCTIONAL WAS
CREATED.

Notice at the top of the file that CheckDoor() was prototyped.  You
must prototype any function you reference inside your objects. The
expression (: CheckDoor :) constitutes as a reference, and thus makes
you need to prototype the function.

The rest of this portion describes individual function calls using
functionals.  The functional prototype part is how your functional
should be declared.:

SetShort(string | function)
Functional prototype: string ShortFunc();
Example: SetShort( (: MyShort :) );
If you pass it a function, then this function gets called to determine
the short description.  The function should return a string which will
be used as the short description.

SetLong(string | function)
Functional prototype: string LongFunc(string unused)
Example: SetLong( (: MyLong :) );
This function should return a string which will be used as the long
description for the room.  The argument "unused" is just that, unused
in this context.  It is something used for other objects.

SetItems(mapping mp);
Functional prototype: string ItemFunc(string item);
Example: SetItems( ([ "house" : (: LookHouse :) ]) );
This function should return a string to be used for the item
description.  The argument is passed the name of the item being looked
at, so you can use the same function for multiple items.

SetSearch(mapping mp)
Alternate: SetSearch(string item, string | function desc)
Functional prototype: string SearchFunc(string item);
Examples: SetSearch( ([ "grass" : (: SearchGrass :) ]) );
          SetSearch("grass", (: SearchGrass :));
Note that there are two forms to SetSearch(), useful depending on how
many searches you are setting at once.  If you have a search function,
then that function should return a string which is what they will see.
The argument passed is the item being searched.

SetSmell()
SetListem()
see SetSearch()

II. Advanced Exits
SetExits() is fairly straight forward.  However, there exists another
function for exits called AddExit().  It allows you to add one exit at
a time (useful if say a player searches and finds a new exit) as well
as give functional power to exits.  The prototype for AddExit() is:

varargs mapping AddExit(string dir, string dest, function pre, function post);

The varargs part of the prototype simply means you can call it using
less than the full number of arguments specified.  In this case, the
minimum call is:

AddExit("east", "/domains/Praxis/square");

The last two arguments are called pre-exit functions and post exit
functions.  The pre-exit function gets called when a player issues a
command to leave the room, but before the player is allowed to leave.
Depending on the return value of the function, the player is allowed
or denied the right to leave.  For example:

AddExit("north", "/domains/Praxis/square", (: PreExit :));

int PreExit(string dir) {
    if( !avatarp(this_player()) ) {
        write("You are too lowly to go that way!");
        return 0;
    }
    else return 1;
}

In other words, if the player is an avatar, they can go north.
Otherwise they cannot.  The prototype is:

int PreExit(string dir);

where the return value is 1 or 0 for can or cannot leave, and the
argument dir is the direction in which the player is exiting.

Post exit functions work a little differently since it makes no sense
to prevent someone from leaving once they have left.  The prototype
looks like:

void PostExit(string dir);

This simply allows you to do processing once the player is gone.  If
you wish a post exit without a pre exit, then:

AddExit("north", "/domains/Praxis/square"", 0, (: PostExit :));

Enters work exactly the same way.

Please read about the events CanReceive() and CanRelease(), as those
may be more appropriate places to do what you want.  Remember, this
only prevents a player from using the "go" command to go in that
direction.  CanReceive() in the other room would be better if your
desire is to keep non-avatars out of the square at any cost.

III.  Other Functions

AddExit()
RemoveExit()
AddEnter()
RemoveEnter()
RemoveSearch()
RemoveSmell()
RemoveListen()
AddItem()
RemoveItem()

All of the above Remove*() functions take a single string argument
specifying what it is that is being removed.  For example:

RemoveExit("east")

removes the exit to the east.

AddItem(string item, mixed val)
Adds a single item.  Val can be a string or function.

        Descartes of Borg
        borg@imaginary.com

	       Building Sentient Non-Player Characters
		   The Nightmare IV Object Library
		 written by Descartes of Borg 951127

One thing most everyone wants to see are monsters that react more
intelligently to user input.  The fact is, however, that most monsters
in the game only need a small, basic behaviour set.  Nevertheless, in
order to make an area interesting, there should be some monsters which
stand out as unique and purposeful.  The problem about building such
monsters is that they use a lot of processing time.

In order to make sure most monsters which do not need such
intelligence do not waste processing time on such activities, the
Nightmare Object Library separates non-player characters into two
classes: dumb monsters, which are basic mindless automata and
sentients, monsters which react more intelligently to their
environment.

This document describes sentients.  Before looking at this document,
it is highly recommended that you be familiar with the document
/doc/build/NPC which details non-player characters.  Sentients are
non-player characters, so everthing which applies to non-player
characters also applies to sentients.

				*****

Currently, a few basic behaviours distinguish sentients from normal
npcs.  Those behaviours are the ability to intelligently move about
the mud and to react to user speech.  Nightmare thus provides the
following functions to allow you to easily have an sentient enact
those behaviours:

	mapping SetTalkResponses(mapping mp);
	mixed AddTalkResponse(string str, mixed val);
	int RemoveTalkResponse(string str);

	mapping SetCommandResponses(mapping mp);
	mixed AddCommandResponse(string str, mixed val);
	int RemoveCommandResponse(string str);

	varargs int SetWander(int speed, string *path, int recurse);
	string *SetWanderPath(string *path);

	int SetWanderRecurse(int x);

	int SetWanderSpeed(int x);

				*****

Making NPCs react to user speech

You may want to have NPCs react to things players say.  To that end,
the following functions exist:

	mapping SetTalkResponses(mapping mp);
	mixed AddTalkResponse(string str, mixed val);
	int RemoveTalkResponse(string str);

Function: mapping SetTalkResponses(mapping mp)
Example: SetTalkResponses( ([ "square" : "The square is east of here.",
            "house" : "Isn't that an ugly house?" ]) );

This function allows you to set a list of responses to given phrases.
For example, if you put this code in a sentient and a player said
"Where is the square?" or "Your frog is certainly square.", your NPC
would have said "The square is east of here.".  Note therefore that
the NPC is only looking for the keys you place in there.  You could
have restricted it to "where is the square" instead of "square", but
then someone asking "Where's the square" would be missed.  

Also note that phrases should be in lower case.  It will match to
upper case words automatically.

Finally, you can either give a string or a function as the match to a
phrase.  If the match is a string, the NPC simply says the string in
the NPC's native tongue.  If, however, the match is a function, that
function will get called.

*****

Function: mixed AddTalkResponse(string str, mixed val);
Example: AddTalkResponse("in the house", (: HouseFunc :));

Matches an individual phrase to a string or function.  As with
SetTalkResponses(), if the match is a string, the NPC simply says the
string in response to the phrase.  If it is a function, that function
gets called.

*****

Function: int RemoveTalkResponse(string str);
Example: RemoveTalkResponse("house");

Removes the previous set or added talk response from the NPC.

				*****

Making NPCs react to user directives

Nightmare supports a special command, the "ask" command.  A player may
use the ask command to ask an NPC to perform a certain task.  For
example, "ask the healer to mend my right leg".  There is a special
event in NPC's which responds to this called eventAsk().  In order to
make responding to this easier, however, Nightmare has the
CommandResponse functions.  The command response functions allow NPC's
to respond based on commands, like "mend".  

*****

Function: mapping SetCommandResponses(mapping mp);
Example: SetCommandResponses( ([ "heal", "I cannot heal people" ]) );

Allows you to match commands to either strings or functions.  Matched
functions get called with the command as the first argument, and
command arguments as the second argument.  For example, if you had:
	SetCommandResponses("give", (: give :));
Your give() function would get called with "give" as the first
argument and "me the sword" as the second argument in response to a
player issuing the command "ask the monster to give me the sword".

*****

Function: mixed AddCommandResponse(string str, mixed val);
Example: AddCommandResponse("give", (: give :));

This allows you to add to the list of commands to which the NPC
responds.  The NPC responds to those commands as outlined for
SetCommandResponses().

*****

Function: int RemoveCommandResponse(string str);
Example: RemoveCommandResponse("give")

Removes a previously set command response.

				*****

Making NPCs move about the game intelligently

A sticky subject on most muds is that of wandering monsters.  When
done poorly, they can waste resources to a great degree.  Nightmare,
however, works to avoid wasting resources while getting the most out
of allowing monsters to move about.

Nightmare supports two types of wandering monsters: those which have
pre-determined paths and others which are true wanderers.  True
wanderers, those who simply randomly choose paths are subject to the
following restrictions:
	They may not move into rooms not yet loaded in memory.
	They will not try to open closed doors.
The first restriction is the most important to note.  This means that
the NPC will not wander into rooms that have not been recently visited
by some player.  This avoids the problem NPCs cause on many muds of
uselessly loading rooms that only the monster will ever see.

Monsters given specific paths to wander are not subject to the above
restrictions.  Of course, they cannot wander through closed doors.
But you can make part of their path to open a closed door.  In
addition, since such monsters have very specific sets of rooms into
which they can travel, they are not in danger of needlessly loading a
zillion rooms.

*****

Function: varargs int SetWander(int speed, string *path, int recurse);
Examples:
	SetWander(5);
	SetWander(5, ({ "go north", "open door", "enter hut", "go west" }));
	SetWander(5, ({ "go north", "open door", "enter hut", "go west",
                       "go south" }), 1);

This is the function you will almost always use in create() to make a
sentient wander.  Only one of the three possible arguments is
mandatory, that being the speed.  The speed is simply the number of
heart beats between attempts to move.  Thus, the higher the number,
the slower the movement of the monster.

The second argument, if given, is a list of commands which will be
executed in order by the monster.  If it is not given, the monster
will be assumed to be a true wanderer.  In other words, the first time
the monster tries to wander, the monster will "go north".  The second
time, he will "open door".  The third, he will "enter hut", etc.  

The third argument is either 1 or 0.  If 1, that means once the
monster has completed the path, it will use the first command in the
list the next time it tries to wander.  If 0, it will cease to issue
commands once it has cycled through the list.

You might note that between the time the above monster opens the door
and enters the hut, somebody could come along and shut the door.  How
can you deal with that?  You could do:
	SetWander(5, ({ "go north", ({ "open door", "enter hut" }) }));
You will notice here that the second member of the command array is
itself an array instead of a string.  In that case, all members of
that array get executed as part of that wander.  In this case it helps
make sure no one closes the door between when the monster tries to
open it and when it tries to pass through the door.

For even more flexibility, you can make elements of the array into
functions.  Instead of executing a command in a wander turn, the
function you provide instead gets called.  For example:
	SetWander(5, ({ "go north", (: kill_anyone :), "go south" }), 1);
Where the function kill_anyone() has the monster kill any players in
that room.  Thus, this monster sits in its room and occasionally pops
its head one room to the north to kill anyone sitting there.

*****

Function: string *SetWanderPath(string *path);
Example: SetWanderPath(({ "go north", "go south" }))

Allows you to set the monster's wander path independent of other
settings.  The wander path will never get executed, however, unless
the monster's wander speed is greater than 0.

*****

Function: int SetWanderRecurse(int x);
Example: SetWanderRecurse(1);

Allows you to make the monster's wander path recurse independent of
other settings.  This is meaningless, however, unless the monster's
wander speed is greater than 0 and a wander path is set for it.

*****

Function: int SetWanderSpeed(int x);
Example: SetWanderSpeed(5);

Allows you to set the monster's wander speed independent of other
settings.  This is NOT the same as SetWander(5).  SetWander() will
clear out any previous wander path and wander recurse settings.  This
function has no effect on the monster's wander path or wander recurse.


** Weapon and Combat Skills **

  pole attack   pole defense  knife attack  knife defense  melee attack
  blunt attack  blunt defense hack attack   hack defense   melee defense
  slash attack  slash defense  pierce attack  pierce defense 
  projectile attack  projectile defense

** Rogue Skills  **

  stealth  stealing

** Repair Skills **

  metal working  textile working   natural working  stone working
  metal working  mithril working  leather working
  armour smithing  weapon smithing

** Combat Related Skills **

  multi-hand  multi-weapon

** Magic Skills **

  conjuring  faith  natural magic
  enchantment  evokation  planar magic  divination  healing  necromancy

** Other Skills **

  bargaining  fishing
                          The Spell Inheritable
                          written by Zaxan@Haven

This document details the different functions in the Nightmare IV LPC
Library's spell inheritable. This document is divided into
many sections. Each section explains a different type of function
in the lib inheritable.

Note that all spells inherit /lib/spell.c and include lib.h, magic.h, and
damage_types.h.

           ************************************************
                         Part 1: Set Functions
           ************************************************

static string SetSpell(string str);
This function defines the actual name of the spell. Players will use
this word to get help (help <spellname>), and to cast it (cast <spellname>).
Normally, it is named similar to the filename of the spell 
(/spells/spellname.c).

varargs static string array SetRules(mixed args...);
This function defines the syntax of how the spell may be cast. A different
rule will give different syntax for casting. Valid tokens for SetRules() 
are:

   OBJ 
     Any object 
   LIV 
     Any object returning 1 for the is_living()
     apply. Note that this has no relation
     whatsoever to the living() or livings() efuns. 
   WRD 
     Any single word in a command. Use this
     instead of STR wherever possible. 
   STR 
     Any serious of words not matching any
     other token. Use this as a last restort, as
     careless use of it can have it capturing
     things you do not want it to capture. 
   OBS 
     Any set of one or more objects 
   LVS 
     Any set of one or more objects returning 1
     for the is_living() apply. 

If you have a verb that supports OBS or LVS for a
token, there is no need to supply a OBJ or LIV
version that corresponds. 

static int SetSpellType(int x);
This function defines what type of spell it is. The valid damage types
are SPELL_COMBAT, SPELL_HEALING, SPELL_DEFENSE, and SPELL_OTHER.

static int SetRequiredMagic(int x);
This function defines the minimum amount of magic points the caster
must currently have in order to get a chance to even get a chance at
casting the spell.

static mapping SetSkills(mapping mp);
This function defines the skills and levels that they must be at in
order to learn the spell from their class leader. If they do not have
the skills, or they are not at the right level, they cannot learn the
spell. These skills are important for deciding what class will be using
the spell.

static varargs int array SetMagicCost(mixed args...);
This function defines how much the spell will cost the caster in terms
of Magic Points. The first number is a base. This means this spell
will ALWAYS cost at least that much. The second number, is a random
number. It will pick a number in the random to add to the base.

static int SetDifficulty(int x);
This function defines a couple things. 1) It helps determine the success
rate of the caster, and 2) the more difficult the spell is, the more it
will train the skills used in SetSkills() and the more It will increase
the % known of the spell by the caster.

static int SetMorality(int x);
This function defines how the successful casting of the spell will change
the caster's aligment. Negative numbers indicate evil and positive numbers
indicate a good alignment.

static int SetAutoDamage(int x); and static int SetAutoHeal(int x);
This function is the damage flag which determines how the target will
be affected by the damage inflicted by the spell. A value of 0 will affect
random limbs using the values in SetDamage(). A value of 1 hurts the
actual internals of the target's body and will show an immediate decrease
in hp. For example, a missile has a value of 0 because it is shot at the
body, therefore hitting limbs. A spell such as chill touch has a value
of 1 because the spell attempts to chill and freeze the innards of the
target's body. This function is ONLY used in a SPELL_COMBAT type. If it
is a healing spell, SetAutoHeal() is used in place of SetAutoDamage(). 
They both use the same values and they both mean the same thing.

varargs static void SetDamage(int type, mixed array rest...); and 
static varargs int array SetHealing(mixed args...);
This function defines the type and amount of damage done to the target on
a successful cast. The first argument is ALWAYS magic, because it's always
a magical type of damage because it came from a spell. The second defines
the type of damage done to the target. Available damage types are 
available in /include/damage_types.h. After the damage type, the first 
value is a base value meaning that it will always do atleast that amount 
of damage. The second value is a random meaning it will pick a random 
number between this numbers to add to the base value.

If you are making a healing spell, you will use SetHealing() instead of
SetDamage(). However, you do not need to put in a damage type. All you
have to put in is a base and random value for the amount of healing
done.

static mixed array SetMessages(mixed array messages);
This function defines the messages printed to the room depending on
what happens during the cast. View /doc/lib/messages to learn about
messages.

static string SetHelp(string str);
The SetHelp() defines what the player will see when they type 
'help <spellname>'. Be sure to insert the syntaxes and a short synopsis
of the spell.

static string SetConjure(string str);
This function is used in a spell that conjures up an item for use by
the player. A filename is the str and it defines the item that is conjured
on a successful cast.

static int SetRequiredStamina(int x);
This function defines the minimum amount of stamina points the caster
must currently have in order to get a chance to even get a chance at
casting the spell.

static varargs int array SetStaminaCost(mixed args...);
This function defines how much the spell will cost the caster in terms
of Stamina Points. The first number is a base. This means this spell
will ALWAYS cost at least that much. The second number, is a random
number. It will pick a number in the random to add to the base.

static int SetAreaSpell(int x);
This function defines that all living things in the room excluding you
and immortals will be affected by the spell when cast.

static int SetGlobalSpell(int x);
This function defines that the target defined can be anywhere on the
MUD when cast. Note the SetRules() MUST be "STR" and not "LIV". This
is due to parser restrictions.

static int SetRemoteTargets(int x); and 
static string SetVerb(string verb);
These functions are inside the /lib/spell.c object but are no longer used
in code. Spells using these functions will automatically not be approved.

           ************************************************
                         Part 2: Get Functions
           ************************************************

int GetAutoDamage(); and int GetAutoHeal();
These functions return the values set in SetAutoDamage() and SetAutoHeal(),
respectively.

string GetConjure();
This function returns the filename value set in SetConjure();.

int GetDamage(); and int GetHealing();
These functions return the values set in SetDamage() and SetHealing(), 
respectively.

varargs string array GetMessage();
This function returns the first argument set in SetMessages().

int GetAreaSpell();
This returns the value set in SetAreaSpell();

int GetGlobalSpell();
This returns the value set in SetGlobalSpell();

int GetDamageType();
This function returns the damage type set in SetDamageType().

int GetDifficulty();
This function will return the value in SetDifficulty();

int GetMagicCost(); and int GetStaminaCost();
These functions return the values set in SetMagicCost() and GetStaminaCost(),
respecively.

int GetMorality();
This function will return the morality value set in SetMorality().

int GetRequiredMagic(); and int GetRequiredStamina();
These functions return the values set in SetRequiredMagic() and 
SetRequiredStamina(), respectively.

string array GetRules();
This function returns the rules for the spell set in SetRules().

string array GetSkills();
This function returns the names of the skills set in SetSkills().

string GetSpell();
This function returns the name of the spell set in SetSpell().

int GetSpellType();
This function returns the type of the spell set in SetSpellType().

varargs object array GetTargets(object who, mixed args...);
This function returns the target of the spell depending on the spell
rules and the syntax input by the caster.

string GetVerb(); and int GetMorality();
These should not be used in any spell because the SetVerb() and 
SetMorality() functions should not be used.

Zaxan Zimtafarous
970523:970625


Also See: 
'help spellbalance' and 'help messaging' ~ Dylanthalus
			    Building Towns
		     The Nightmare IV LPC Library
		 written by Descartes of Borg 950429

The Nightmare IV LPC Library contains support for towns, which is in
fact very minimal from the mudlib level.  If, however, you wish to
structure your MUD to be centered around the concept as Nightmare LPMud
is, then you need to understand how to build a town.  This document
describes the building of towns using the Nightmare IV LPC Library.

I. What Is a Town?
A town is simply a collection of rooms which have the same value set
for Town.  If done poorly, this is all it is.  If done right, however,
a town becomes the center of the games' social structure.  If you
decide to build a town in your area, the first thing you need to do is
isolate it.  All towns should be surrounded by vast, vast areas of
wilderness of some sort.  This may mean desert, forest, jungle, or
whatever.  You may or may not want to have a road which links it to
the rest of civilization.

Rooms are considered "wilderness" by default.  That is, if you never
set the town in them, they are considered wilderness.  To make a room
part of a town, you need to call SetTown() from create() of the room:

	SetTown("Praxis");

Capitalize your town name properly.

Next you need to decide how many estates may be built in the room.
Ideally, towns are expanding and changing things.  Upper level players
have the ability to build estates in their home towns.  Of course, ten
estates in one room is crowded.  Generally you should limit the number
of estates to what would logically fit in a given room.  For example,
if you are on a road at the edge of town with nothing about, then
allowing two estates makes sense.  On the other hand, in the middle of
an intersection of two roads, there is hardly any room for an estate
to be built.  To allow estates to be built in a room:

	SetProperty("estates", 2);

This allows two estates to be built off of this room.

As stated above, towns are expanding.  This is why they should be
situated far apart.  Too close together it is hard for them to expand
without changing the overall map of the game.  Therefore, when your
town has gotten as full as can be handled, then you simply move to
outlying rooms and make them part of the town by setting their town.
In addition, give them the capacity for estates.  Do not forget to
change room descriptions and allow for needed roads!

II. What do I put in towns?
The first section described what is minimally needed for a town from a
code point of view.  This section describes what sorts of things you
should put in your towns.  Most are optional, however, you do need to
add something called an adventurer's hall.  An adventurer's hall is
the default start room for the town for anyone who chooses the town as
their home town.  In order to make it their home town, they go to the
adventurer's hall and pay a fee (generally determined by approval) to
move to this town.  Until that person builds an estate in the town,
the adventurer's hall is their default starting point.

Beyond that, the only other thing required is a real estate office for
selling estates.  This is an inheritable from /lib/sales.c
(LIB_SALES).  Approval determines what your local land value is, and
you fill in the descriptions.  For information on advanced coding of
sales offices, see the document /doc/build/Sales.

Nothing else is required.  Of course, your land value (the amount
people pay to live and build in your town) is determined by the sorts
of services your town offers.  No town should offer all services.  And
certainly, the services your town offers should reflect the nature of
the region in which you are building.  Are you an isolated, small
town?  Then few services will be available.  Are you a central, large
town?  Then a majority of services should be available.

Services include:
	shops of different types
	bars and pubs
	restaurants
	libraries for learning languages
	class halls
	town council rooms

This list will probably expand over time, but it provides a good
starting point for common services.

	Descartes of Borg
	borg@imaginary.com

	
			Building Store Vendors
		     The Nightmare IV LPC Library
		 written by Descartes of Borg 950528

This document details the creation of vendor objects, NPC's which buy
and sell items.  Note that vendors are NPC's, so everything in the
document on building NPC's applies to vendors.  It is recommended that
you be completely familiar with that document before moving on to this
one.

Keep in mind that to make a vendor, you need to inherit LIB_VENDOR;
and vendor::create();, instead of LIB_NPC and npc::create().
Also, to use VT_ anything, you need to #include <vendor_types.h> too.

Building vendors is actually quite simple, with very little required
beyond the NPC requirements.  In fact, only the following function
calls are unique to vendors:

string SetLocalCurrency(string currency);
string SetStorageRoom(string room);
int SetMaxItems(int num);
int SetVendorType(int vt);

One special note, however, is that the skill "bargaining" is extremely
important to vendors.  Namely, the higher the bargaining, the harder
it is for players to get decent prices.

*****
string SetLocalCurrency(string curr);
*****

Example: SetLocalCurrency("electrum");

Sets the currency which the vendor will use for doing business.  The
currencies should be approved by the approval team.

*****
string SetStorageRoom(string room);
*****

Example: SetStorageRoom("/domains/Praxis/horace_storage");

Identifies the file name of the room in which the vendor will be
storing items for sale.  This room should never be accessible to
players.

*****
int SetMaxItems(int num);
*****

Example: SetMaxItems(60);

Sets the maximum number of items a vendor can keep in storage at any
given time.  Refer to approval documentation for proper numbers for
this.

*****
int SetVendorType(int type);
*****

Examples: 
	SetVendorType(VT_WEAPON);
	SetVendorType(VT_ARMOUR | VT_WEAPON);

Sets which types of items a vendor will buy and sell.  A list of all
vendor types is in /include/vendor_types.h.  You may allow a vendor to
sell multiple types using the | operator.

  Building verbs on Haven  (Nightmare-IVr5 lib)


  There are 2 main sections to creating a verb.  The first and primary
  importance is NOT the verb code itself, it is creating an inheritable
  that handles an object's reaction and response to the verb.

  For example, it is more important and more difficult to create the
  functions which allow an item to be repaired than it is to create
  the code for the actual verb repair.


  To begin with, one must remember that all verbs use a set-piece 
  format of action and reaction.  These are defined by the verb 
  parser, which checks how commands are issued.

  To begin with, we will start with the easy stuff, how to create
  a basic verb.


#include <lib.h>
inherit LIB_VERB;

static void create() {
  verb::create();
  SetVerb("chuckle");
  SetRules("","LIV");
  SetHelp("Syntax:  chuckle, chuckle LIV");
  }

  That is the create function for a basic verb called 'chuckle'
  which allows the agent (the person performing the action) to
  either chuckle with no arguments or chuckle at a LIVing object.

  SetVerb()
    This is simply what it sounds like, a one word command that
    is issued to begin this verb.

  SetRules()
    This defines how the parser can accept arguments to the verb.
    Acceptable rules are:
      "", "LIV", "OBJ", "WRD"
    these rules also accept many prepositions, such as:
        "on", "in", "at", "of", "from"

  For example, an acceptable rule would be "at LIV"

  SetHelp()
    This is simply a string returned when 'help <verb>' command is used.

--

  Parser Code:

  mixed can_verb_rule()

  This returns either a string failure message or 1, depending on
  whether or not the agent CAN perform the verb.

  For example, you could return "Aren't you rather busy?"
  after a check to see if the player is in combat.

  remember to return 1 if the action is allowed.

  mixed do_verb_rule()
   This implies that all checks have been made, and the verb will
    happen.  This is the actual code to complete the verb, including
    all effects and reactions.

--

  Response code

  This is code added to an object which allows the target to be affected
  by the verb.

  mixed direct_verb_rule()

  This returns either a string failure or 1 to the AGENT informing 
  (upon failure) of why the target cannot be affected by the verb.
  If no direct is given in target object, it will return :
  "You cannot do that to that."

  -- 

  Advanced Stuff:

  indirect_verb_firstobject_rule/secondobject()

    This is the code for an agent acting on TWO objects, as in
    'give sword to bob'.

    In which, the sword will call direct_give_obj() and bob will
    have to call 'indirect_give_obj_to_liv()'
    This should again return a string or 1.

  Examples in lib.
			   Building Weapons
		     The Nightmare IV LPC Library
		 written by Descartes of Borg 950429

All items in the Nightmare LPC Library (descendants of /lib/item.c)
are weapons.  A player can, for example, use a can of spam as a
weapon.  However, they are set up as extremely pathetic weapons.  This
document describes in detail how to make an object into a real weapon.

I. Basic Stuff
The basic weapon is exactly the same as the basic item.  You can do
anything to it that can be done to other items.  For details on items,
see /doc/build/Items.  The simple weapon should look like this:

#include <lib.h>
#include <damage_types.h>
#include <vendor_types.h>

inherit LIB_ITEM;

static void create() {
    item::create();
    SetKeyName("short sword");
    SetId( ({ "sword", "short sword", "a short sword" }) );
    SetAdjectives( ({ "short" }) );
    SetShort("a short sword");
    SetLong("Specks of blood cover this rusty short sword.");
    SetVendorType(VT_WEAPON);
    SetDamagePoints(1500);
    SetClass(12);
    SetValue(150);
    SetMass(100);
    SetWeaponType("slash");
    SetDamageType(SLASH);
}

The last part is what differs from regular items.  Note the functions:

SetVendorType()
SetClass()
SetWeaponType()
SetDamageType()

The available vendor types can be found by reading the file
/include/vendor_types.h.  Similarly, damage types may be found by
reading /include/damage_types.h.  The vendor type states what sort of
stores can carry this item.  VT_WEAPON should almost ALWAYS be the
vendor type you give for weapons.

pierce
melee
hack
SetClass()
The class is the basic weapon strength.  It is how much damage gets
done without any modification.  This number ranges between 1 and 100,
where 1 is a pathetic weapon (the class for basic items) and 100 is
probably bordering on illegal.

SetWeaponType()
This sets what sort of attack skill the player needs to use this
weapon.  The weapon types are:
slash
knife
blunt
projectile

SetDamageType()
Damage types, again, are found in /include/damage_types.h.  This sets
what type of damage is done by this weapon to its victims.

II. Wield Functions

mixed SetWield(string | function) 
Examples:
	SetWield("The short sword feels dull as you wield it.");
	SetWield( (: WieldMe :) );

If you pass a string to SetWield(), then the player sees that string
whenever they wield the weapon.  If, on the other hand, you pass a
function, then that function will get called just before the weapon is
wielded when the player issues the wield command.  The function you
pass should be written in the form of:

int WieldMe();

If the function returns 1, then the player can wield the weapon.  If
it returns 0, then the player cannot wield the weapon.  Note that if
you have a wield function, you are responsible for all messaging to
the player to let the player know that they can/cannot wield the
weapon.  Example:

int WieldMe() {
    if( (int)this_player()->ClassMember("fighter") ) {
        write("The short sword gives you power as you wield it.");
        say((string)this_player()->GetName() + " wields a short sword.");
        return 1;
    }
    else {
        write("You are not worthy of this short sword.");
        return 0;
    }
}


III. Modifying Stats and Skills
A common thing people like to do with weapons is temporarily modify a
player's skills.  This is done by making use of the function
AddStatBonus() and AddSkillBonus().  Most of the time this is done
through a SetWield() function.

void AddStatBonus(string stat, function f);
void AddSkillBonus(string stat, function f);

Examples:
	this_player()->AddStatBonus("wisdom", (: CheckStat :));
	this_player()->AddSkillBonus("slash attack", (: CheckSkill :));

The functions then have the format:

int CheckWhatever(string stat_or_skill);

NOTE: You should always check whether the bonus is still in effect.
For example, make sure the weapon is still wielded if it results from
wielding the weapon.  For example:

#include <lib.h>

inherit LIB_ITEM;

int DoWield()
int CheckBlade(string skill);

static void create() {
...
    SetWield((: DoWield :));
...
}

int DoWield() { 
    this_player()->AddSkillBonus("slash attack", (: CheckBlade :) );
    write("You wield the short sword.");
    say((string)this_player()->GetName() + " wields a short sword.");
    return 1;
}

int CheckBlade(string skill) {
    if( !GetWorn() ) {
        previous_object()->RemoveSkillBonus("slash", this_object());
        return 0;
    }
    else return 5;
}


In other words, this weapon will give its wielder a slash attack bonus
of 5.  Note that you must use previous_object() in CheckBlade() and
NOT this_player() because there is no way of knowing who this_player()
is at the time.  You do know, however, that the object calling
CheckBlade() is always the player for whom the skill bonus is made.
Always remember to remove bonuses.

IV. Modifying Hits
The Nightmare IV LPC Library uses an event driven combat system.  With
respect to weapons, a round of combat is broken down into the
following events:

1. The person wielding the weapon uses it.
2. If they cannot hit a motionless target, the round ends.
3. If the target dodges the attack, the round ends.
4. eventStrike() is called in the weapon to determine how much damage
the weapon can do.
5. eventReceiveDamage() is called in the target object.  This in turn:
	a. Calls eventReceiveDamage() in all armour objects, which each:
		i. Calls eventReceiveDamage() in the weapon
		ii. The weapon wears down a bit
	b. The armour wears down a bit
	c. The amount of armour damage absorbed is returned
	d. The target objects loses health points.
	f. The amount of damage done is returned.
6. Skill and stat points are added.

Note the two important functions which get called in weapon.c:

	int eventStrike(object ob);
	int eventReceiveDamage(int type, int amount, int unused, mixed limbs);

By default, eventStrike() returns the value of GetClass().  However,
you can modify this value by overriding the eventStrike().  For
example:

int eventStrike(object target) {
    if( (string)target->GetRace() != "orc" ) return item::eventStrike(target);
    message("environment", "The orc slayer makes a nasty sound!",
      environment(target));
    return item::eventStrike(target) + random(10);
}

NOTE: You should always use item::eventStrike() rather than hard coded
values since weapon class deteriorates over time.

In this example, a random(10) points of extra damage gets done to
orcs.  This would be the orc slayer weapon of ancient fame.

For those familiar with hit functions in the old Nightmare Mudlibs,
this would be roughly equivalent to that.

Another place where you can make things happen is in
eventDeteriorate() which gets called by eventReceieveDamage().  This is
where a weapon wears down from the shock which armour has absorbed
from it.  For weapons, there is not much which can be done here, but
this document points it out for the creative who feel they might be able to do
somthing with it.

	Descartes of Borg
	borg@imaginary.com
