182 lines
7.2 KiB
Plaintext
182 lines
7.2 KiB
Plaintext
chapter 16 "Armor"
|
|
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
|