329 lines
12 KiB
Plaintext
329 lines
12 KiB
Plaintext
chapter 34 "QCS: Modification of NPC's"
|
|
|
|
In the previous chapter we learned how to make a generic object.
|
|
Now that we have it, what to do with it?
|
|
|
|
It's important to keep in mind that the generic thing now in
|
|
front of you isn't just a clone from a template file. If the command
|
|
you used was "create npc cowboy", there is now a file (probably)
|
|
called /realms/you/area/npc/cowboy.c that contains the code for the
|
|
creature in front of you.
|
|
However, this poor beast has the most uninteresting of features.
|
|
It is in fact so boring that it responds only to its generic type.
|
|
Such that "examine cowboy" or "kill tex" won't work. You'll need to
|
|
"look at npc".
|
|
|
|
Accordingly, any modification commands need to be made referring
|
|
to the new thing with an it responds to, until such a time as you
|
|
change the id to suit your tastes. Let's carry on with the example
|
|
of our generic npc. To make a cowboy out of him, we can either
|
|
change his name, or his id, or both. Let's start with his name:
|
|
|
|
%^GREEN%^modify npc name cowboy%^RESET%^
|
|
|
|
This makes the SetKeyName() directive in cowboy.c use "cowboy"
|
|
as its argument, effectively allowing you to address this npc as "cowboy"
|
|
from now on. Now you can "look at cowboy" with some results.
|
|
Obviously our NPC isn't *just* a cowboy. He's also a human, a dude,
|
|
and his name is Tex. How do we make him respond to all of these nouns?
|
|
|
|
%^GREEN%^modify cowboy id%^RESET%^
|
|
|
|
You'll notice there are no arguments following the word "id". Setting
|
|
a thing's id is different from most other settings. If you'll think back
|
|
to the LPC datatypes chapter of this manual (you did read the LPC
|
|
chapters, didn't you?) you'll remember that some information about
|
|
objects is in the form of strings ("cowboy"), some is in the form of
|
|
integers (the cowboy's health points, for example) and some is in the
|
|
form of arrays, which are a group of data points. In this example we
|
|
want the cowboy's id to be an array, because of the many ways we might
|
|
want to address him. Therefore, we want the SetId directive in his
|
|
file to look like this:
|
|
|
|
SetId( ({"human", "dude", "tex" }) );
|
|
|
|
You might think that QCS should be able to accept multiple values
|
|
like this on a line, perhaps with "modify cowboy id human dude tex" as
|
|
the command.
|
|
But what if you want this npc to be a "Boy Named Sue"? How would
|
|
you accommodate id's that contain spaces? In designing QCS, I considered
|
|
having escape characters to allow for such things, but ultimately
|
|
reasoned that this was just way too much mess. Instead, SetId, and
|
|
other directives that take arrays as arguments, are handled by entering
|
|
a query session. Below is an example of what it might look like. The
|
|
example is necessarily messy because I am including both the queries
|
|
and the responses.
|
|
|
|
---------------------------------------------------
|
|
> %^GREEN%^modify npc name cowboy%^RESET%^
|
|
Indenting file...
|
|
"/tmp/indent.1136206130.tmp.dat" 15 lines 420 bytes
|
|
Exit from ed.
|
|
|
|
> %^GREEN%^modify cowboy id%^RESET%^
|
|
This setting takes multiple values. If you have no more values to enter, then
|
|
enter a dot on a blank line. To cancel, enter a single q on a blank line.
|
|
You may now enter the next value. So far, it is blank.
|
|
If you're done entering values, enter a dot on a blank line.
|
|
%^GREEN%^dude%^RESET%^
|
|
You may now enter the next value. So far, we have: ({ "dude" })
|
|
If you're done entering values, enter a dot on a blank line.
|
|
%^GREEN%^human%^RESET%^
|
|
You may now enter the next value. So far, we have: ({ "dude", "human" })
|
|
If you're done entering values, enter a dot on a blank line.
|
|
%^GREEN%^tex%^RESET%^
|
|
You may now enter the next value. So far, we have: ({ "dude", "human", "tex" })
|
|
If you're done entering values, enter a dot on a blank line.
|
|
%^GREEN%^boy named sue%^RESET%^
|
|
You may now enter the next value. So far, we have: ({ "dude", "human", "tex",
|
|
"boy named sue" })
|
|
If you're done entering values, enter a dot on a blank line.
|
|
%^GREEN%^.%^RESET%^
|
|
Entries complete. Final array is: ({ "dude", "human", "tex", "boy named sue" })
|
|
Indenting file...
|
|
"/tmp/indent.1136206156.tmp.dat" 19 lines 459 bytes
|
|
Exit from ed.
|
|
|
|
/open/1136206138: Ok
|
|
/realms/cratylus/area/npc/cowboy: Ok
|
|
SetId modification complete.
|
|
> %^GREEN%^exa tex%^RESET%^
|
|
Other than being human, this npc is entirely unremarkable.
|
|
The male human is in top condition.
|
|
---------------------------------------------------
|
|
|
|
If you were now to examine Tex's code (with the command "about tex")
|
|
you'd see that his SetId directive now looks like this:
|
|
|
|
SetId( ({"dude", "human", "tex", "boy named sue"}) );
|
|
|
|
Other NPC features take arrays also. SetAdjectives is one. You
|
|
might enter this (mud output omitted for clarity):
|
|
|
|
%^GREEN%^modify tex adjectives%^RESET%^
|
|
%^GREEN%^dusty%^RESET%^
|
|
%^GREEN%^hardy%^RESET%^
|
|
%^GREEN%^.%^RESET%^
|
|
%^GREEN%^look at dusty cowboy%^RESET%^
|
|
|
|
There are two other directives that require queries. Things and
|
|
NPC's can be looked at, but they can also be smelled and listened
|
|
to, if you add SetSmell and SetListen. The syntax is:
|
|
|
|
%^GREEN%^modify tex smell%^RESET%^
|
|
|
|
And you will then be asked a question about keys and mappings.
|
|
Understanding mappings is important, but for now you just need to
|
|
understand that you are being asked *two* separate questions:
|
|
1) What on the cowboy is being smelled/listened to?
|
|
2) What is the smell/sound?
|
|
|
|
What this means is that your input will look something like
|
|
this:
|
|
|
|
%^GREEN%^modify tex smell%^RESET%^
|
|
%^GREEN%^default%^RESET%^
|
|
%^GREEN%^.%^RESET%^
|
|
Tex smells of sweat and manure.
|
|
|
|
What happens is this:
|
|
- You enter the modify command.
|
|
- You enter the word "default" to indicate this is Tex's general smell.
|
|
- You enter a dot to indicate that you are done specifying what
|
|
part of Tex is being smelled.
|
|
- You then specify the smell.
|
|
|
|
This may seem odd until you realize you can also add smells/listens to
|
|
parts of things. Not on NPC's, though. We'll look at this more closely in
|
|
later chapters. For now, just use the syntax as shown above. For adding
|
|
a listen to the cowboy, it works the same way:
|
|
|
|
%^GREEN%^modify tex listen%^RESET%^
|
|
%^GREEN%^default%^RESET%^
|
|
%^GREEN%^.%^RESET%^
|
|
Tex seems to be humming a jaunty melody.
|
|
|
|
Other features of an NPC do not take arrays, so one-line commands
|
|
will do. For example:
|
|
|
|
%^GREEN%^modify cowboy long This is a cowboy who calls himself Tex, but is in fact a Boy Named Sue.%^RESET%^
|
|
|
|
%^GREEN%^modify cowboy short a cowboy%^RESET%^
|
|
|
|
%^GREEN%^modify cowboy level 5%^RESET%^
|
|
|
|
%^GREEN%^modify cowboy class fighter%^RESET%^
|
|
|
|
%^GREEN%^modify tex currency gold 1%^RESET%^
|
|
|
|
%^GREEN%^modify tex currency silver 12%^RESET%^
|
|
|
|
%^GREEN%^modify tex skill bargaining 5%^RESET%^
|
|
|
|
%^GREEN%^modify tex skill projectile attack 7%^RESET%^
|
|
|
|
%^GREEN%^modify tex stat strength 33%^RESET%^
|
|
|
|
%^GREEN%^modify tex property nice guy 1%^RESET%^
|
|
|
|
%^GREEN%^modify tex healthpoints 150%^RESET%^
|
|
|
|
%^GREEN%^modify tex maxhealthpoints 170%^RESET%^
|
|
|
|
%^GREEN%^modify tex melee 0%^RESET%^
|
|
|
|
%^GREEN%^modify tex unique 1%^RESET%^
|
|
|
|
If you now issue the "about tex" command you will see that all
|
|
the changes you made have been put into the file.
|
|
|
|
You may have noticed the "melee" keyword. Dead Souls 2 NPC's come
|
|
in various shapes and sizes, and some of them shouldn't wield weapons. A
|
|
wolf with a battle axe would be a strange sight indeed. However, the
|
|
default combat system makes unarmed creatures extremely vulnerable in
|
|
combat.
|
|
To make an NPC combat-capable without weapons, use the new SetMelee
|
|
directive. SetMelee(1) makes the NPC capable of proper unarmed combat.
|
|
SetMelee(0) makes the NPC a weak opponent if unarmed.
|
|
NPC's will generally try to bite during unarmed combat. If this
|
|
is beneath the capability or dignity of your NPC, you can prevent
|
|
this with:
|
|
|
|
%^GREEN%^modify tex canbite 0%^RESET%^
|
|
|
|
If your NPC should try to escape when the battle isn't going
|
|
his way, the wimpy settings should do:
|
|
|
|
%^GREEN%^modify tex wimpy 30%^RESET%^
|
|
|
|
%^GREEN%^modify tex wimpycommand climb ladder%^RESET%^
|
|
|
|
If you don't specify a wimpy command, Tex will leave the
|
|
room through a random exit. In this case, when Tex's health
|
|
is down to 30% and he is in combat, he will try to climb a ladder.
|
|
|
|
Some NPC's are designed to travel about. To enable this
|
|
feature, use the wanderspeed directive:
|
|
|
|
%^GREEN%^modify tex wanderspeed 5%^RESET%^
|
|
|
|
If you want him to travel more quickly, use a
|
|
lower number. By default, wandering NPC's only wander in rooms
|
|
that have already been loaded into memory. They avoid loading
|
|
rooms because loading a bunch of rooms that only the NPC
|
|
will ever see is a waste of your mud's resources.
|
|
However, if you *do* want your NPC to wander in an
|
|
unrestricted manner, regardless of whether a room is loaded,
|
|
use the permitload directive:
|
|
|
|
%^GREEN%^modify tex permitload 1%^RESET%^
|
|
|
|
By default, NPC's stand up when they can. This is
|
|
so that if they collapse during combat, they try to
|
|
get back up once they are able to do so.
|
|
If you prefer that your NPC maintain some other
|
|
posture, you can set that posture, then disable
|
|
autostanding like this:
|
|
|
|
%^GREEN%^modify tex posture lying%^RESET%^
|
|
|
|
%^GREEN%^modify tex autostand 0%^RESET%^
|
|
|
|
If he's especially lazy, you can have him take
|
|
a nap this way:
|
|
|
|
%^GREEN%^modify tex sleeping 10%^RESET%^
|
|
|
|
Which will have him wake up after about a minute.
|
|
However, note that if you've disabled autostanding,
|
|
he will remain lying down after he wakes up.
|
|
|
|
If the NPC should be hostile, that is, he should
|
|
attack any creatures that it sees enter a room,
|
|
SetEncounter should do it:
|
|
|
|
%^GREEN%^modify tex encounter 100%^RESET%^
|
|
|
|
This means that if the creature it sees has a
|
|
charisma score of less than 100 (which should pretty
|
|
much be always true), Tex will try to kill it. You
|
|
can do some fancy stuff with SetEncounter, such
|
|
as only attacking orcs, or actually doing something
|
|
friendly, but to do so you can't use QCS. Read
|
|
the NPC and Sentients chapter in the Creator's
|
|
Manual for details on how to code such stuff.
|
|
|
|
If the NPC is a golem or other such non-biological
|
|
creature, it may be useful to specify what they are
|
|
made of. The SetComposition setting for a clay
|
|
golem might look like this:
|
|
|
|
%^GREEN%^modify golem composition clay%^RESET%^
|
|
|
|
If it happens to be a golem that does not believe
|
|
in violence as a solution to problems, you can
|
|
make refuse to hurt others with the following:
|
|
|
|
%^GREEN%^modify golem pacifist 1%^RESET%^
|
|
|
|
|
|
Vendors:
|
|
-------
|
|
|
|
Vendors are a special kind of NPC that can sell stuff.
|
|
Along with the standard NPC settings, vendors have
|
|
the following:
|
|
|
|
SetStorageRoom specifies where the vendor's stock
|
|
is stored. If a valid room is specified, anything
|
|
in that room can be sold by the vendor.
|
|
|
|
SetLocalCurrency specifies the type of currency,
|
|
such as gold or silver, that the vendor accepts.
|
|
|
|
SetMaxItems is the maximum number of items in
|
|
the storeroom that the vendor is permitted to sell.
|
|
|
|
SetVendorType specifies the kind of stuff the vendor can
|
|
trade in. "all" allows him to buy and sell whatever.
|
|
But if he is a weapon vendor, he can't trade in armor,
|
|
etc. See /include/vendor_types.h for the available
|
|
vendor types. To have a "multi-type" vendor, you'll have to
|
|
code it by hand. The result of that looks something
|
|
like this:
|
|
|
|
SetVendorType( VT_TREASURE | VT_ARMOR | VT_HERBS );
|
|
|
|
|
|
Barkeeps:
|
|
--------
|
|
|
|
Like vendors, barkeeps sell stuff, but they are
|
|
limited to selling food and drink.
|
|
|
|
Unlike vendors, barkeeps have no limitation on
|
|
the amount of stuff they can sell. They also do
|
|
not have a storeroom. The stuff they can sell is
|
|
specified in their SetMenu directive, like this:
|
|
|
|
%^GREEN%^clone woody%^RESET%^
|
|
You clone a generic barkeep (/realms/temujin/area/npc/woody.c).
|
|
%^GREEN%^modify woody menu%^RESET%^
|
|
If you don't understand these questions, type the letter q on a blank line and hit enter.
|
|
|
|
Please enter the first key element for this mapping:
|
|
|
|
%^GREEN%^bourbon%^RESET%^
|
|
Please enter the next key element, or enter a single dot to finish entering key elements.
|
|
%^GREEN%^whiskey%^RESET%^
|
|
Please enter the next key element, or enter a single dot to finish entering key elements.
|
|
%^GREEN%^.%^RESET%^
|
|
Please enter the value for key ({ "bourbon", "whiskey" }):
|
|
|
|
%^GREEN%^/domains/town/meals/bourbon%^RESET%^
|
|
|
|
Barkeeps also have the SetLocalCurrency directive
|
|
to specify the currency they accept.
|
|
|
|
|