chapter 29 "Weapons"
			   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("A rusty short sword with specs of blood on it.");
    SetVendorType(VT_WEAPON);
    SetDamagePoints(1500);
    SetClass(12);
    SetValue(150);
    SetMass(100);
    SetWeaponType("blade");
    SetDamageType(BLADE);
}

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.

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:
blade
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("blade 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("blade 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("blade", this_object());
        return 0;
    }
    else return 5;
}


In other words, this weapon will give its wielder a blade 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
