The NPC Section
In the previous chapters you were given the basic building blocks and they were demonstrated with rooms. This chapter will deal with all the fields of NPCs - what they are and how to use them. You may want to review the Unit Building Blocks chapter if you skipped it.
When looking at NPC fields you will find that some of them are the same as what you learned with rooms. For example: extra, alignment, flags, and more. These fields work the exact same way as they do on rooms so when you run across them they will be briefly reviewed with an emphasis on NPC-specific details.
NPC Fields and Types
| Field | Type |
|---|---|
| symbolic name | Symbol |
| names | Stringlist |
| title | String |
| descr | String |
| extra | Structure |
| minv | Integer |
| key | String |
| spell | Integer |
| romflags | Integer |
| sex | Integer |
| race | Integer |
| attack | Integer |
| defense | Integer |
| position | Integer |
| manipulate | Integer |
| alignment | Integer |
| flags | Integer |
| weight | Integer |
| capacity | Integer |
| light | Integer |
| money | Structure |
| exp | Integer |
| level | Integer |
| height | Integer |
| abilities | Structure |
| weapons | Structure |
| spells | Structure |
| special | Structure |
| dilbegin/dilcopy | Function pointer |
| end | Symbol |
NPC Field Descriptions
Symbolic Name
The rules of the symbols have been explained in the Unit Building Blocks chapter. The important thing to realize with NPC symbols is they are shown in all administration commands when dealing with NPCs. So it is good to make the symbol resemble the title, and as we explained in Unit Building Blocks, the symbol must start with an alphabetic character or underscore and should be no more than 15 characters.
Title
With NPCs the title will be shown when fighting and interacting with your NPC. For example, if the title is ‘the large dog’ and you try to kick it you will get the message:
You kick the large dog in the head.
Putting a period on the end of a title will look funny and putting a capital letter at the beginning of the title will also look strange since the title is used in sentences.
Names
As in all units, the names field is a stringlist including all the names that will be associated with the NPC to be used to interact with it. These names should be everything in the title along with some extras. The names should go from most descriptive to least. For example:
names {"large ugly dog","large dog","ugly dog","dog"}
title "a large ugly dog"
Description (descr)
Unlike descriptions in rooms this description is shown when you walk into the room and see the NPC. It should not be the description of the NPC, that goes in the extras described later. This description should be what the NPC is doing or just a statement that the NPC is there. Some examples are:
descr "A small dog is chasing its tail here."
descr "An ugly child is throwing rocks at the wall."
Extra
The extras on NPCs work like on all unit types but on NPCs they have a much greater role. The default extra on an NPC is shown when the player looks at the NPC. The following is what this would look like:
extra {}
"The small girl looks around as if she were waiting for someone."
You can add an extra description that players see when they look at the NPC. Use either an empty-named extra or one matching the NPC’s first name. If neither exists, players see “You see nothing special.” You can also create body parts and equipment:
extra {}
"A small sickly child watches you wearily. The child is dressed in
torn dirty clothes that don't look like they have been washed in years."
extra {"head"}
"A normal looking human head."
Alignment
Alignment on an NPC is a value between -1000 and +1000. You should choose an alignment on your NPC that matches the overall theme of the NPC. If your NPC is a mean killer then it probably shouldn’t be +1000 alignment, which is the highest possible good alignment. You may think alignment is not a big deal but once you assign quests to your NPCs, which can make a player good or evil, then these values really start to matter.
Flags
The flags field is the same as explained with rooms. On NPCs you may want to flag them as already buried so when they are loaded they are buried. You may also want to set them INVISIBLE or SACRED. All of the other flags are rarely set on an NPC.
Romflags (Character Flags)
The character flags are an addition to the normal flags. These flags are found in vme.h and are prefixed with ‘CHAR_’. There are many of these flags and some of them would be hard to explain without a lot more DIL or base code knowledge. Here are the most common character flags:
| Flag | Description |
|---|---|
| CHAR_PROTECTED | Attacking this char is treated as murder and triggers guard responses |
| CHAR_LEGAL_TARGET | Internal flag after illegal actions. Will not persist in zones |
| CHAR_OUTLAW | Killing this char is not treated as a crime |
| CHAR_GROUP | Char is in a group. Will not persist in zones |
| CHAR_BLIND | Sets the char as blind |
| CHAR_HIDE | Sets the char as hiding |
| CHAR_MUTE | Sets the char as mute, can not speak |
| CHAR_SNEAK | Sets the char as sneaking |
| CHAR_DETECT_ALIGN | Char can detect alignment. Pointless for NPCs |
| CHAR_DETECT_INVISIBLE | Char can see invisible units |
| CHAR_DETECT_MAGIC | Char can detect magic. Pointless for NPCs |
| CHAR_DETECT_POISON | Char can detect poison. Pointless for NPCs |
| CHAR_DETECT_UNDEAD | Char can detect undead. Pointless for NPCs |
| CHAR_DETECT_CURSE | Char can detect curses. Pointless for NPCs |
| CHAR_DETECT_LIFE | Char can detect life. Pointless for NPCs |
| CHAR_WIMPY | Makes the char flee when low on HP |
| CHAR_SELF_DEFENCE | Temporary flag when the char is not the initiator in combat. Pointless for NPC definitions. |
| CHAR_PEACEFUL | Aggressive NPCs will not attack this character |
| CHAR_KILL_SELF | Set when a PC kills themselves (will not stick) |
An example of setting a romflag on an NPC:
romflags {CHAR_PROTECTED}
Sex
In zones you use symbols to define the sex of your NPC. All symbols are prefixed with SEX_ and are found in vme.h:
| Symbol | Value | Description |
|---|---|---|
| SEX_NEUTRAL | 0 | Neither male nor female |
| SEX_MALE | 1 | Male |
| SEX_FEMALE | 2 | Female |
To set the sex on an NPC:
sex SEX_MALE
Race
In zones you also use symbols to define the race of the NPC. All symbols are prefixed with RACE_ and are found in values.h. Some common race defines are:
| Symbol | Description |
|---|---|
| RACE_HUMAN | Human |
| RACE_ELF | Elf |
| RACE_DWARF | Dwarf |
| RACE_HALFLING | Halfling |
| RACE_GNOME | Gnome |
| RACE_HALF_ORC | Half-orc |
| RACE_HALF_OGRE | Half-ogre |
| RACE_HALF_ELF | Half-elf |
| RACE_BROWNIE | Brownie |
| RACE_GROLL | Groll |
| RACE_DARK_ELF | Dark Elf |
Example:
race RACE_HUMAN
Height
The height of your NPC is set in centimeters. For example, a 6-foot NPC would be set as:
height 182
Weight
The weight of your NPC is set in pounds. For example, a 200-pound NPC:
weight 200
Position
The position of an NPC is the way it is positioned when loaded. This can be good if you want the NPC to be asleep or prone. The following defines are from vme.h:
| Symbol | Description |
|---|---|
| POSITION_DEAD | NPC is dead |
| POSITION_MORTALLYW | NPC is mortally wounded |
| POSITION_INCAP | NPC is incapacitated |
| POSITION_STUNNED | NPC is stunned |
| POSITION_SLEEPING | NPC is sleeping |
| POSITION_RESTING | NPC is resting |
| POSITION_SITTING | NPC is sitting |
| POSITION_FIGHTING | NPC is fighting |
| POSITION_STANDING | NPC is standing |
Example:
position POSITION_SLEEPING
Level
The level sets the overall power of the NPC. When you set the level it sets the experience the NPC gives and sets the starting HP. The level sets a lot of default values that can be changed after you set them so always set this field first. The level on NPCs can be anything from 1 to 199.
Example:
level 10
Experience (exp)
Experience is automatically calculated from the level and all other settings. It is, however, possible to adjust experience by setting the exp field. If you set experience as a positive number it adds that to the calculated experience. If set to a negative number it will subtract experience from the NPC.
Example:
exp -500
Attack
The attack type defines the message shown when the NPC attacks during combat. If you set the default with ‘NATURAL_DEF’, discussed later, you won’t need this field. The attack type is one of the defines found in values.h prefixed with WPN_.
Example:
attack WPN_BITE
Defense
The defense type is the amount of protection the NPC has based on an armor type. The define is also from vme.h prefixed with ARM_. Normal armor types include: clothes, leather, hleather, chain, plate.
Example:
defense ARM_PLATE
Money
Money is the amount of currency a NPC is carrying. This is set with the special money syntax. Defines IRON_PIECE, COPPER_PIECE, SILVER_PIECE, GOLD_PIECE, and PLATINUM_PIECE can be used:
money 5 SILVER_PIECE, 2 COPPER_PIECE
Abilities
Abilities are set on NPCs using a macro because they must add up to exactly 100%. The defines are in wmacros.h and the one for abilities is MSET_ABILITY.
The MSET_ABILITY macro takes 8 arguments corresponding to: Strength, Dexterity, Constitution, Hitpoints, Brain, Charisma, Magic Ability, and Divine Power. All must add to 100.
MSET_ABILITY(20, 10, 14, 21, 10, 5, 10, 10)
Weapons
Weapons and Spells are combined into 100% because they’re both used in combat. The values represent the percentages in weapon categories (axes, swords, clubs, etc.) and spell spheres. The weapon macro MSET_WEAPON takes 6 arguments for weapon groups:
MSET_WEAPON(10, 10, 10, 10, 10, 5)
Spells
The spell macro MSET_SPELL takes 11 arguments for spell spheres. When combined with weapons, the total must equal 100:
MSET_SPELL(0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 35)
Special
The special field is a special function handler passed to base code. This is only used for backwards compatibility and will be removed when all specials are replaced by DIL. Example usage for a banker:
special SFUN_BANK
Minv, Key, Light, Manipulate, Capacity
These fields are not normally set on NPCs but can be used for storing information or creating unique behavior.
NPC Macros
The file composed.h provides macros that simplify NPC creation. These define race-specific defaults and help standardize NPC building.
The Attack and Armour Macro
The natural attack and armour fields allow you to set the NPC to do damage like a certain type of weapon and to defend like a certain type of armour respectively. Let’s say you had a metal cougar; it would have an attack type of claw and an armour type of plate while a normal dog would have an armour type of leather and an attack type of bite. The NATURAL_DEF macro is what allows you to set these fields. This macro is defined in wmacros.h and looks like this:
#define NATURAL_DEF(weapon_category, armour_category) \
armour armour_category \
attack weapon_category
The word “natural” can sometimes be a little confusing since you can set any of the weapon types you like on the NPC. It doesn’t exactly make sense to have a dog that attacks as if it uses a long sword but if you wish it you can do it. The following is a short list of just the natural weapon types but you can find a full list in the appendix or in the values.h of your mud:
#define WPN_FIST 34
#define WPN_KICK 35
#define WPN_BITE 36
#define WPN_STING 37
#define WPN_CLAW 38
#define WPN_CRUSH 39
Again you don’t have to use leather for dogs - as we have already mentioned with our metal cat idea you could make a cloth dragon if you really want but it’s up to you to keep some sanity on your VME. The following is the list of armour types that can be set:
#define ARM_CLOTHES 0 /* Same as a Human in jeans and a T-shirt */
#define ARM_LEATHER 1 /* A soft flexible leather base armour */
#define ARM_HLEATHER 2 /* A hard inflexible leather base armour */
#define ARM_CHAIN 3 /* A flexible armour composed of interlocking rings */
#define ARM_PLATE 4 /* An inflexible plate armour */
Now that you have the defines to work with we will return to our metal cat and normal dog. The definitions for them would look something like this:
// Metal Cat
NATURAL_DEF(WPN_CLAW, ARM_PLATE)
// Normal dog
NATURAL_DEF(WPN_BITE, ARM_LEATHER)
You should know that the weight of the monster determines the maximum amount of damage it can give when using a natural attack. The weight is categorized as follows:
| LBS | Size |
|---|---|
| 0 - 5 | Tiny |
| 6 - 40 | Small |
| 41 - 160 | Medium |
| 161 - 500 | Large |
| 501 and up | Huge |
By default monsters are medium. So make sure you take this into account when you are creating your NPC.
The Defense and Offense Bonus Macro
There comes a time when you may want to make your NPC supernaturally powerful. It is for those times that the offense and defense fields are available for you to set. Normally they default to 0 but you can set them from -1000 to +1000. The higher you set the offense number the harder you will hit people you are in combat with. The higher you set the defense the harder it will be for people to hit your NPC. The following macro allows you to set both the offense and defense:
#define ATTACK_DEFENSE(attack, defense) \
offensive attack \
defensive defense
Using this macro is rather easy - you just put the value you want for each and you’re all done:
// A really hard hitting, hard to kill NPC
ATTACK_DEFENSE(1000, 1000)
The NPC Abilities Macro
All abilities are in the range [1..250]. Players usually have a maximum of around 150, modified by magic. When creating a monster you can not directly specify the size of the abilities, instead you specify a percentage distribution of points. The amount of points are then distributed by the computer according to the specified level. The MSET_ABILITY macro is available for this purpose:
#define MSET_ABILITY(str, dex, con, hpp, bra, cha, mag, div) \
ability[ABIL_STR] str \
ability[ABIL_DEX] dex \
ability[ABIL_CON] con \
ability[ABIL_HP] hpp \
ability[ABIL_BRA] bra \
ability[ABIL_MAG] mag \
ability[ABIL_DIV] div \
ability[ABIL_CHA] cha
Note: The sum of the ability values must be 100%. This is therefore an example of an ability distribution:
MSET_ABILITY(25, 15, 10, 15, 10, 5, 10, 10) /* Sum is 100% */
The amount of points distributed depends directly upon the level of the monster and the percentage. If the percentage is too high and the level is also set high some ability points may be lost since an NPC gets all abilities over 250 cut off. For example a level 199 monster with an ability percentage a bit above 20% will make an ability above the 250 points maximum. Each spell has a realm (magic or divine) and uses the corresponding ability - if an NPC casts both divine and magic spells, they need points in both ‘mag’ and ‘div’.
The NPC Weapon and Spell Macros
NPCs know about weapons and spells but not at the same detailed level as the player. For NPCs the spell and weapon groups are used. Thus the axe/hammer category defines all defense and all attack for all kinds of axes and hammers, whereas the player would have to train individually in each axe and hammer type. The same is true for spells.
When you define weapon and spell skills (monsters have no skill skills) you also define these as percentages, and the program automatically distributes the points. Use the pre-defined macros:
#define MSET_WEAPON(axe_ham, sword, club_mace, pole, unarmed, special) \
weapon[WPN_AXE_HAM] axe_ham \
weapon[WPN_SWORD] sword \
weapon[WPN_CLUB_MACE] club_mace \
weapon[WPN_POLEARM] pole \
weapon[WPN_UNARMED] unarmed \
weapon[WPN_SPECIAL] special
| Argument | Description |
|---|---|
| axe_ham | Any hammer or axe |
| sword | Any sword-like weapon, including dagger and rapier, etc. |
| club_mace | Any club or mace-like weapon, flails, morning star, etc. |
| polearm | Any spear or pole-like weapon: spear, trident, sickle, scythe, etc. |
| unarmed | Any bite, claw, sting or other natural attack |
| special | Any very peculiar weapon, currently only whip |
#define MSET_SPELL(div, pro, det, sum, cre, min, hea, col, cel, int, ext) \
spell[SPL_DIVINE] div \
spell[SPL_PROTECTION] pro \
spell[SPL_DETECTION] det \
spell[SPL_SUMMONING] sum \
spell[SPL_CREATION] cre \
spell[SPL_MIND] min \
spell[SPL_HEAT] hea \
spell[SPL_COLD] col \
spell[SPL_CELL] cel \
spell[SPL_INTERNAL] int \
spell[SPL_EXTERNAL] ext
| Argument | Description |
|---|---|
| div | Covers all divine sphere spells |
| pro | Covers all protection sphere spells |
| det | Covers all detection sphere spells |
| sum | Covers all summoning spells |
| cre | Covers all creation spells |
| min | Covers all mind spells |
| hea | Covers all heat spells (fireball, etc.) |
| col | Covers all cold spells (frostball, etc.) |
| cel | Covers all cell (electricity) spells (lightning bolt, etc.) |
| int | Covers all internal (poison) spells (toxicate, etc.) |
| ext | Covers all external (acid) spells (acid ball, etc.) |
Note: If you’re not sure what your weapon or spell is categorized as you can look in the
weapons.defor thespells.deffor your VME server.
The sum of all spell and weapon skills must be 100%. For example, the following would be a legal setting of weapons and spells:
// 75% Total, Club/Mace is primary
MSET_WEAPON(10, 10, 20, 5, 15, 5)
// 25% Total, Fire is primary
MSET_SPELL(8, 0, 0, 3, 0, 3, 2, 3, 3, 3, 3)
Remember that the groups define both attack and defense. So if you make an orc that has 0% in the flail group it can only use its dexterity to defend itself. Likewise with spell groups. For this reason the groups are both “resistance” as well as attack groups.
Using the composed.h
The file composed.h contains many standard monsters. It is a good idea to study these definitions, as they form the basis of many different monsters. Note that the definitions by no means are perfect, but we are hoping to make a more or less complete monster compendium. If you create certain (general) monsters, please design it as a macro so it can be incorporated in the file. The more monsters created by using these macros the easier it will be for your builders to create NPCs. If you think you have a really all-inclusive composed.h and want to share it with the rest of the VME servers running out there on the internet, feel free to submit it to the VME staff and we will put it in the contribution directories on our release site.
Race Macros
There are many race macros available. For example, M_AVG_HUMAN sets all the default values for an average human:
M_AVG_HUMAN(level, sex)
The zone distributed with VME has many race macros including: M_AVG_GOBLIN, M_AVG_HOBGOBLIN, M_DRAGON_BLACK_OLD, and many more.
Building Your First NPC
Now you know all the fields and what they are used for - let’s put all the knowledge together and build an NPC. Since this is a dragon station, we will create a dragon.
We need: a symbol, title, description, names, default extra description, race, sex, height, weight, level, natural defense, and the ability/weapon/spell macros.
bldragon
title "a black dragon"
descr "A big ugly black dragon is clawing the ground here."
names {"big ugly black dragon","ugly black dragon","big black dragon",
"black dragon","dragon"}
extra {}
"The black dragons scales glitter like black granite that has been
polished for years by water. He has a large neck and huge bat like
wings. His eyes watch you as you stand before him. One claw seems to be
tapping slightly on the ground as if the dragon is waiting for
something."
extra {"eye","eyes"}
"The dragons eyes seem to follow you no matter where you go in the room
nothing seems to escape the dragons attention."
extra {"claws","claw"}
"The claw is big black and it looks very deadly. It seems like the
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
means the claws are about the size of short swords and long swords."
extra {"scales","scale"}
"It's a scale! Haven't you ever seen a dragon before!"
extra {"bat wings","wings"}
"The dragon sees you looking and flaps his wings creating one heck of a
wind blast."
race RACE_DRAGON_BLACK
sex SEX_MALE
height 625
weight 1250
level 70
NATURAL_DEF(WPN_CLAW, ARM_PLATE)
alignment -900
MSET_ABILITY(20, 12, 12, 12, 12, 12, 20, 0)
MSET_WEAPON(10, 10, 10, 5, 30, 5)
MSET_SPELL(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30)
end
Compiling and Debugging Your First NPC
As mentioned in the room compilation section, it’s always a good idea to build one or two things and then compile to make finding errors easy. Here’s the zone with just one NPC:
#include <composed.h>
%zone dragonst
lifespan 20
reset RESET_ANYHOW
creators {"whistler"}
notes
"This is the dragon station I shortened it to dragonst for ease in
loading. If you have any questions email me at admin@example.com"
help
"Not sure what could help you now. You are stuck on one of the
weirdest space stations you have ever seen and you smell burning
sulfur."
%mobiles
bldragon
title "a black dragon"
descr "A big ugly black dragon is clawing the ground here."
names {"big ugly black dragon","ugly black dragon","big black dragon",
"black dragon","dragon"}
extra {}
"The black dragons scales glitter like black granite that has been
polished for years by water. He has a large neck and huge bat like
wings. His eyes watch you as you stand before him. One claw seems to be
tapping slightly on the ground as if the dragon is waiting for
something."
extra {"eye","eyes"}
"The dragons eyes seem to follow you no matter where you go in the room
nothing seems to escape the dragons attention."
extra {"claws","claw"}
"The claw is big black and it looks very deadly. It seems like the
dragon has two sets of 4 large claws and 2 sets of 4 smaller claws which
means the claws are about the size of short swords and long swords."
extra {"scales","scale"}
"It's a scale! Haven't you ever seen a dragon before!"
extra {"bat wings","wings"}
"The dragon sees you looking and flaps his wings creating one heck of a
wind blast."
race RACE_DRAGON_BLACK
sex SEX_MALE
height 625
weight 1250
level 70
NATURAL_DEF(WPN_CLAW, ARM_PLATE)
alignment -900
MSET_ABILITY(20, 12, 12, 12, 12, 12, 20, 0)
MSET_WEAPON(10, 10, 10, 5, 30, 5)
MSET_SPELL(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30)
end
%end
Common NPC compilation errors include:
- Missing
{}on extra declarations - MSET_ABILITY not adding to 100
- MSET_WEAPON + MSET_SPELL not adding to 100
When you compile successfully, you’ll get the .data, .err, and .reset files. Load your NPC with load bldragon@dragonst.
DIL Functions for NPCs
The DIL language allows builders to create special functions. The VME is released with many functions for NPCs:
Mercenary
Makes an NPC hirable by players. Players can type contract <character name> and the mob will hunt that character for a fee.
dilcopy mercenary_hire@function();
Obey
Makes an NPC obey its master. Players can tell the NPC to perform commands.
dilcopy obey@function();
Evaluate
Allows an NPC to evaluate items for a fee:
dilcopy evaluate@function(4*GOLD_PIECE);
Guard Direction
Guards a direction, optionally allowing certain players or NPCs to pass:
dilcopy guard_dir@function("south", {"papi"}, {"guard"}, "");
Combat Magic
Allows NPCs to cast spells during combat:
| Argument | Type | Description |
|---|---|---|
| atk_spl | string | Attack spell, e.g., “fireball” or “” for none |
| def_spl | string | Defense spell, e.g., “heal” or “” for none |
| def_pct | integer | HP percentage when defense spell is cast |
| spd | integer | Speed of attack magic (1=every round, 5=every 5 rounds) |
dilcopy combat_mag@function("harm", "heal", 25, 2);
Fido
Turns an NPC into a corpse/food eating mobile:
dilcopy fido@function("$1n slowly devours $2n, crunching the bones.",
"$1n grabs $2n and hungrily munches it.");
Wander Zones
Allows a mob to wander across multiple zones:
| Argument | Type | Description |
|---|---|---|
| zones | string | Zone names separated by spaces |
| spd | integer | Speed in seconds (minimum 5) |
| doors | integer | Can open/close doors (0=false, 1=true) |
| lckd_doors | integer | Can open locked doors (0=false, 1=true) |
dilcopy wander_zones@function("halfzon haon_dor", 5, 1, 1);
Global Wander
Like wander_zones but moves through all zones:
dilcopy global_wander@function(60, 1, 1);
Teamwork
Makes an NPC assist other specified NPCs in combat:
dilcopy teamwork@function("jesper/enver");
Rescue
Makes an NPC rescue other specified NPCs when attacked:
dilcopy rescue@function("jesper/enver");
Aggressive
Makes an NPC hostile under configurable conditions:
| Argument | Type | Description |
|---|---|---|
| sx | integer | 0=any sex, 1=opposite, 2=male, 3=female, 4=neutral |
| rce | integer | Race to attack (-1 for any) |
| opp | integer | 0=non-specific, 1=attack specified race, 2=attack all except |
| levl | integer | Level threshold (positive=above, negative=below, 0=any) |
| sanc | integer | 0=ignore, 1=obey sanc, 2=obey soothe, 3=obey both |
| tme | integer | Time to wait before attacking (ticks) |
| tar | integer | Target selection (-2=last, -1=weakest, 0=random, 1=strongest, 2=first) |
| align | string | “ANY”, “GOOD”, “EVIL”, “NEUTRAL”, “OPPOSITE”, “SALIGN”, “DALIGN” |
| attack | stringlist | Two messages: room message and victim message |
dilcopy aggressive(3, 2, 1, 20, 2, PULSE_SEC*10, 0, "EVIL",
{"$1n savagely attacks $3n with his big axe!",
"$1n attacks you!"});
Janitors
Picks up items from the room and sends them to a designated donation room:
dilcopy janitor@clashut("jandonate@myzone");
Shop Keeper
Creates a shop. This is one of the more complex functions. Here’s the complete setup:
Step 1 - Define Products:
#define TAVERN_PROD \
{"grain_alcohol@gobtown1 15 20", \
"pretzels@gobtown1 10 15", \
"tuborg@udgaard 15 20"}
Each product string contains: symbolic_name daily_restock max_stock
Step 2 - Define Messages (10 responses):
#define TAVERN_MSG \
{"$1n says, 'I don't sell that!'", \
"$1n says, '$3n, you don't have that!'", \
"$1n says, 'I don't trade in $2n!'", \
"$1n says, '$3n, you can't afford $2n.'", \
"$1n says, 'Thank you, here are %s for $2n.'", \
"$1n says, 'Thank you, $3n.'", \
"$1n says, 'I don't have that many.'", \
"$1n says, 'I'm closed, come back later.'", \
"$1n says, 'I have no use for $2n.'", \
"$1n says, 'I can't afford to buy that.'"}
Step 3 - Define Open Times:
#define TAVERN_OPEN_TIMES {"1","23"}
Step 4 - Define Trade Types:
#define TAVERN_ITEM_TYPE "19"
Item types: 1=LIGHT, 5=WEAPON, 9=ARMOR, 10=POTION, 15=CONTAINER, 17=DRINKCON, 19=FOOD, etc.
Step 5-7 - Define Costs:
#define TAVERN_MAX_CASH 81920
#define TAVERN_SELL_PROFIT 110
#define TAVERN_BUY_PROFIT 50
Step 8 - Apply to NPC:
dilcopy shopkeeper@function(TAVERN_PROD, TAVERN_MSG, TAVERN_OPEN_TIMES,
TAVERN_ITEM_TYPE, TAVERN_SELL_PROFIT,
TAVERN_BUY_PROFIT, TAVERN_MAX_CASH, "", "");
A More Complex Set of NPCs
Magic Casting NPC
Add combat magic to make the dragon more interesting:
bldragon
...
M_DRAGON_BLACK_OLD(SEX_MALE)
dilcopy combat_mag@function("acid breath", "", 25, 2);
end
Or using the race macro to simplify:
bldragon
title "a black dragon"
descr "A big ugly black dragon is clawing the ground here."
names {"big ugly black dragon","ugly black dragon","big black dragon",
"black dragon","dragon"}
extra {}
"The black dragons scales glitter like black granite..."
M_DRAGON_BLACK_OLD(SEX_MALE)
end
A Wandering Janitor
janitor
names {"ugly janitor", "janitor", "hobgoblin"}
title "an ugly janitor"
descr "an ugly janitor is walking around, cleaning up."
extra {}
"This ugly green thing looks more goblin than hobgoblin but he seems
intent on cleaning everything around him."
M_AVG_HOBGOBLIN(6, SEX_MALE)
alignment 900
money 5 IRON_PIECE
dilcopy janitor@clashut("disposal_room@dragonst");
dilcopy wander_zones@function("dragonst", 20, 1, 1);
end
Creating a Teacher
Setting up teachers requires stricter formatting. The ‘special’ field is used with SFUN_TEACH_INIT.
Note: Using TAB characters in teacher definitions will cause the mud to crash!
The format begins with the entity type (abilities, spells, skills, or weapons):
special SFUN_TEACH_INIT
"&labilities;0;
Then seven act messages for various situations, followed by the teaching definitions:
$1n tells you, 'I have never heard of such an ability.';
$1n tells you, 'I do not know how to teach this ability.';
$1n tells you, 'You haven't got %s for me.';
$1n tells you, 'You haven't got %d ability points.';
$1n tells you, 'I can not teach you any more.';
$1n tells you, 'You must be unaffected by magic.';
$1n tells you, 'Remove all equipment, please.';
Each teaching line has fields: guild_level; max_percent; name; min_cost; max_cost; points; 0;
0; 100; Strength ; 4; 4000; 8; 0;
0; 90; Dexterity ; 14; 14000; 12; 0;
Complete teacher example:
jones
names {"blacksmith", "smith", "Jones"}
title "Jones the blacksmith"
descr "The venerable Jones Blacksmith is here."
extra {}
"The smith is old but his arms still retain the strength of his youth."
flags {UNIT_FL_NO_TELEPORT}
romflags {CHAR_PROTECTED}
M_HUMAN_WARRIOR_AXE(80, SEX_MALE)
exp -100
dilcopy guild_basis@guilds("Udgaard Fighter");
dilcopy members_only@guilds("Udgaard Fighter", "$1n says, 'Buggar ye off.'");
special SFUN_TEACH_INIT
"&labilities;0;
$1n tells you, 'I have never heard of such an ability.';
$1n tells you, 'I do not know how to teach this ability.';
$1n tells you, 'You haven't got %s for me.';
$1n tells you, 'You haven't got %d ability points.';
$1n tells you, 'I can not teach you any more';
$1n tells you, 'You must be unaffected by magic.';
$1n tells you, 'Remove all equipment, please.';
0; 100; Strength ; 4; 4000; 8; 0;
0; 90; Dexterity ; 14; 14000; 12; 0;
0; 90; Constitution ; 14; 14000; 9; 0;
0; 100; Hitpoints ; 4; 4000; 11; 0;
"
end
Guild Master Functions
Guild masters need three DIL functions from guilds.zon:
guild_basis- Combat detection; banishes guild members who attack the NPCguild_master- Handles join/leave commandsguild_titles- Time-based title system (titles awarded based on time in guild)
dilcopy guild_basis@guilds("Udgaard Fighter");
dilcopy guild_master@guilds(
"Udgaard Fighter", // guild_name
{"Fighter Proven"}, // enter_quests - quests required to join
640, // enter_cost - iron cost to join
{"Wimp proven"}, // leave_quests - quests required to leave
3200, // leave_cost - iron cost to leave
{"Udgaard Fighter Quitter"} // exclude_quests - quests that prevent joining
);
dilcopy guild_titles@guilds(
"Udgaard Fighter",
{"the %s Swordpupil", "the %s Swordpupil", // male/female pair
"the %s Recruit", "the %s Recruit",
...}
);
The %s in titles is replaced with the player’s race name. Titles come in male/female pairs.
NPC Banker
The simplest special function:
bob
names {"Bob"}
title "Bob"
descr "Bob the Banker is here, sitting behind the counter."
extra {}
"He has a very serious look on his face."
M_SHOP_KEEPER(4, SEX_MALE, RACE_HUMAN)
exp -500
flags {UNIT_FL_NO_TELEPORT}
special SFUN_BANK
end
Suggested NPC Exercises
-
Using the teamwork DIL function, create a guard that will help all other guards.
-
Using the rescue DIL function, add to your guard from exercise one and make it so it will now rescue as well as help.
-
Using the shop keeper function, make a shop keeper that sells two types of food. The shop keeper should make 5 of them a day and should only buy items of the food type.
-
Turn your shop keeper from exercise three into a global wandering sales person.
-
Using the aggressive DIL function, create a Dwarf aggressive to any Orc that walks into the room.