Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - petriomelony

Pages: [1]
1
Hi everyone,

I'm using the DW distribution lib with FluffOS 2.20-ds01, on linux, and was wondering if anyone else ran into a problem with mob spawn causing a seg fault, in pumpkin town (on squash street).

This is the trace I get

Code: [Select]
Object: /d/dist/pumpkin/squash/squash4, Program: /d/dist/pumpkin/inherit/cityroom.c
   in make_citymonster() at /d/dist/pumpkin/inherit/cityroom.c:61
arguments were (0)
Object: /d/dist/pumpkin/hospital, Program: /d/dist/pumpkin/hospital.c
   in ok_to_clone() at /d/dist/pumpkin/hospital.c:490
arguments were ()
Object: /secure/simul_efun, Program: /secure/simul_efun/modified_efuns.c
   in named_livings() at /secure/simul_efun/modified_efuns.c:232
arguments were ()
'     <fake>' in '/            <driver>' ('/   secure/simul_efun')

I checked the hospital.c files first (there's a couple of them), and I think the piece of code in question is trying to count the mobs in Ankh-Morpork, which isn't part of the distributed lib:

Code: [Select]
// This function returns 1 if its ok to clone some more npcs and
// false if not.
int ok_to_clone() {
  if(time() > last_check + 300) {
    last_check = time();
    am_npcs = sizeof( filter( named_livings(),
      (: environment( $1 ) && base_name( environment( $1
       ) )[0..4] == "/d/am" :) ) );
  }
  return ( am_npcs < MAX_AM_LIVING );
}

where "/d/am" doesn't exist, but MAX_AM_LIVING is defined in another file alright.  however, there are also 4 hospital files to do with pumpkin, one in /d/dist/pumpkin, and the others in /d/dist/pumpkin/pumpkin, /d/dist/pumpkin/inherit, and /d/dist/pumpkin/hospital.  pumpkin's path.h only points to the one in the base pumpkin folder, though (i also just found a typo where it was referring to hostpial.h, but i don't think that's the issue since each hospital.c has hospital.h included at the top)

i think there's also something wrong with named_livings(), but i have no idea what the trace is saying.  the e_fun code in the trace is simply:

Code: [Select]
/** @ignore yes */
object *named_livings() {
#if efun_defined(named_livings)
  return filter( efun::named_livings(), (: reference_allowed :) );
#else
  return filter( LIV->named_livings(), (: reference_allowed :) );
#endif
} /* named_livings() */

any input would be appreciated!

edit: this doesn't happen all the time, only if i leave the mud running a while (presumably when the number approaches/hits the max?)

2
Skylib Stuff / automap with skylib?
« on: April 19, 2009, 01:51:43 AM »
after browsing through the code, it looks like the discworld files for maps are still included in the lib... does anyone know how to use them with skylib, by chance?

3
Skylib Stuff / add_item
« on: April 13, 2009, 06:43:24 PM »
I was working my way through the new discworld creator LPC for dummies guide (which is fantastic, if anyone wants to know.  a big props to Drakkos for it), and I got to a part about making items in the room searchable.  Now I know that skylib != dw, but they have quite a few similarities.  I just could not get the searchable items thing working (without defining a search string comparison).

This is what the guide said to try:

Code: [Select]
add_item ("jagged rock",
({
  "long", "This is a jagged rock.",
  "searchable", "#search_rock",
  "position", "on the jagged rock",
  ({"kick", "punch"}), "Ow! That stung!\n",
}));

and this is what I ended up doing:

Code: [Select]
int do_search(string str)
{
  if (str == "rock")
  {
    call_out ("search_rock", 3);
    return 1;
  }
  return -1;
}

I know call_outs are bad, which is why I wanted to avoid this code, but this is what was used in one of the stock rooms (part of the creator school). 

Note: Using the example code from the DW LPC guide, I could literally type "searchable rock" and it would return the string "#search_rock".  I also tried changing "searchable" to just "search", but that would just do a room search if i typed "search rock".

I guess my question is: does anyone know of a better way to make something searchable in skylib?

Thanks!

4
Skylib Stuff / efuns?
« on: April 11, 2009, 09:16:59 PM »
Hello everyone,

I just started looking at Skylib, and so far it looks awesome.  A big thanks to Cratylus for making the bundle that works on windows :)

I ran into a bit of a problem with the 'grep' command internal to the mud, and traced it back to an external_start efun.  The mud says:

Code: [Select]
/secure/cmds/creator/grep.c line 61: Undefined function external_start before ;

where line 61 is where grep.c uses external_start:

Code: [Select]
    if( nfiles || !search )
        fd = external_start( 6, arg, "read_call_back",
            "write_call_back", "close_call_back");
    else
        return notify_fail("Grep needs at least one file.\n");

    if( fd == -1 )
        return notify_fail("Grep failed for some reason.\n");

looking at the help file for external_start, it says the first parameter passed should be an int, for one of five external commands specified in the config file.  could the fact that it's a 6 be messing it up?

i'm running skylib right out of the bundle (with the included fluffos-2.9).

any advice would be greatly appreciated! :)

5
Dead Souls Support / inventory item order
« on: December 06, 2007, 10:05:31 AM »
is there any way to make it not so random?  every time i type "i" i get a different order of items... does anyone know which file should i look at if i want to make it say, chronological in the order they were obtained, or something?

6
Dead Souls Support / mobs giving items
« on: November 08, 2007, 02:46:24 PM »
hey all! i've just begun to dip my toes into programming sentients.  i wanted to make a kind of interactive shop keeper, and i've done ok, but there's two things i would really love to add in... and i would appreciate any help with them.

here's the code for the vendor:

Code: [Select]
#include <lib.h>


inherit LIB_SENTIENT;



int WandSpeech();
int SellWand(object who, string verb, string wand);
static void create() {
    sentient::create();
    SetKeyName("ollivander");
    SetId( ({ "ollivander", "wizard", "wand maker", "wand-maker", "old man", "man" }) );
    SetShort("Mr. Ollivander the Wand-Maker");
    SetLong("Standing before you is Mr. Ollivander, an old man with wispy white "
          "hair.  He looks a little tired, but his bright blue eyes convey a "
          "hidden energy.  He twirls a thin wand in his hands as he looks you "
          "up and down, as if he knew you were coming.");
    SetLevel(25);
    SetRace("humantest");
    SetClass("mage");
    SetGender("male");
    SetAction(25, ({
"Mr. Ollivander says, \"%^BOLD%^%^CYAN%^Tis the wand that chooses the wizard, you know.%^RESET%^\"",
"Mr. Ollivander rummages about the shelves idly.", "Mr. Ollivander twirls his wand between his fingers.",
"Mr. Ollivander looks you up and down.",
"Mr. Ollivander says, \"%^BOLD%^%^CYAN%^Just starting up at Hogwarts then, eh?%^RESET%^\"",
"Mr. Ollivander says, \"%^BOLD%^CYAN%^Your spells will always be better when performed with your own wand.%^RESET%^\"",
"Mr. Ollivander says, \"%^BOLD%^CYAN%^I remember every wand I've ever sold...%^RESET%^\"",
"Mr. Ollivander says, \"%^BOLD%^CYAN%^Don't settle for anything less than Ollivander's!  There ain't no place better.%^RESET%^\"",
"Mr. Ollivander says, \"%^BOLD%^CYAN%^Almost gored me with his horn, that one unicorn...%^RESET%^\"",
"Mr. Ollivander says, \"%^BOLD%^CYAN%^All my wands are hand-made with the finest Phoenix Tailfeathers, Unicorn Hairs, and Dragon Heart-Strings.%^RESET%^\"",
      }));
    SetTalkResponses( ([
        "wand" : "Do you want me to explain wands?",
        "wands" : "Do you want me to explain wands?",
        ]) );
    SetCommandResponses( ([
"explain": (: WandSpeech :),
"sell" : (: SellWand :),
      ]) );
   
}
int WandSpeech(string what){
    eventForce("say The magic wand is the source of a wizard or witch's power. "
               "Without one, incantations would be ineffectual, curses would "
               "be casual chatter, and hexes about as harmful as hedgehogs.  "
               "Indeed, the wand makes or breaks the wizard.  However, it is "
               "worthwhile to note that the wand chooses the wizard, and that "
               "your spells will never be as powerful with another wizard's wand.");
    eventForce("emote pauses for a moment, looking you up and down.");
    eventForce("say Now, if you would like me to sell you a wand, just ask!");
    eventForce("smile");
    return 1;
}
int SellWand(object who, string verb, string wand) {
    int cost, onhand;
    if(wand != "me a wand"){
    eventForce("say You want me to sell you a what?");
    return 1;
    }
    cost = 6;
    onhand = who->GetCurrency("galleons");
    if(onhand < cost) {
    eventForce("say It looks like you don't have enough galleons for a wand.");
    eventForce("say A wand costs 6 galleons.  But mind you, you only get the finest wands here!");
    return 1;
    }
    environment(this_object())->eventPrint("Mr. Ollivander gives "+ who->GetName() +" multiple wands to try, without luck. "
                                 "Finally, after about " + random(100) + " tries, " + who->GetName() + " causes "
                                 "gold sparks to shoot out of the wand with a simple wave.", ({who}));
    who->eventPrint("Mr. Ollivander gives you multiple wands to try, without luck.  After about " + random(100)
                   +" different wands, you grasp the next one wearily, but suddenly feel a surge of warmth and "
                    "energy flow through you from the wand.  Smiling to yourself, you give the wand a simple flick, "
                    "causing gold sparks to shoot impressively out of the end.");
    environment(this_object())->eventPrint("Mr. Ollivander says, \"OH! Well done, " + who->GetName() + "!  Well done indeed. "
                                 "Well, here is your wand, take good care of it!\"");
    this_object()->eventGiveWand(who);
    who->AddCurrency("galleons", -cost);
    who->eventPrint("You hand Mr. Ollivander 6 galleons, and he thanks you.");
    return 1;
}
int eventGiveWand(object player) {
    new("/domains/town/weap/carving_knife")->eventMove(this_object());
    if(player && environment(this_object()) == environment(player)) {
eventForce("give wand to "+player->GetName());
    }
    return 1;
}
void init(){
::init();
}

basically, what i want to do is perhaps have a check of the player's inventory to see if they already have a wand, and then stop the selling function... i'm thinking i can use GetInventory for this, but i'm not sure how.  i'm going to maybe try playing around with it when i get home, with something like

Code: [Select]
object *tmp = GetInventory(player);
for(int i = 0, i < sizeof(tmp), i++) {
    if(tmp[i]->GetweaponType = "wand"){
    ** have the guy say something **;
    return 1;
}

ok, the 2nd thing is... i want the wands to be unique to every player, and for only that player... like, to modify the short desc to be "player's wand", and have the player's name in the long desc, as well as randomize the features of the wand, like...

Code: [Select]
string determine_wood();
switch(random(4)){
case 0 : return "holly";
case 1 : return "oak";
case 2 : return "maple";
case 3 : return "walnut";
}
[code]

and have one of those for each attribute, sort of thing, and include those strings in the long desc of the item.  i know an alternative would be to just have multiple wand#.c files, and then maybe do a random() before cloning the wand into the NPC, but that would take up a lot of space and is inefficient, right?  and then i'd still have the issue of making the wand personalized for the player...

so yea :) any help is appreciated!
[/code]

7
Dead Souls Support / verb help, please?
« on: November 06, 2007, 01:56:02 PM »
hey guys, so i'm trying to write a new verb, and i'm basing it on backstab...

basically, i don't want it to take up a combat round like backstab does (or like spells do), and i've attributed it to stats and skills that aren't yet in the lib, so i've commented those out for now.  also i tried getting it to work with tigwyk's skill delay code, but that wouldn't work either, so i've commented that bit out.

i've also changed the header file around to match, but still nothing.

here's the code... i get

Code: [Select]
/verbs/players/sectumsempra.c line 157: syntax error
when i try to update it, and when i comment out that last eventPrintDamage section, it turns out ok except whenever i try to use it it says "You can't sectumsempra that." even if it is living... it gives the correct messages for no target and a non-living target, though.

here's sectumsempra.c
Code: [Select]
#include <lib.h>
#include <position.h>
#include "damage_types.h"
#include "include/sectumsempra.h"

inherit LIB_VERB;

static void create() {
    verb::create();
    SetVerb("sectumsempra");
    SetRules("LIV");
    SetErrorMessage("Who do you want to cast that on?");
    SetHelp("Syntax: sectumsempra LIVING\n\n"
      "This dark spell inflicts terrible wounds on your opponent.");
}

mixed can_sectumsempra_liv() {
    if( !environment(this_player()) ) return 0;
    else if( this_player()->GetParalyzed() ) {   
    return "You cannot do anything.";
}
    else return this_player()->CanManipulate();
}

mixed do_sectumsempra_liv(object ob) {
    object env;
   
    if(!(env = environment(this_player()))) return 0;
    if( (int)this_player()->GetPosition() != POSITION_STANDING )
    this_player()->eventStand();
    if(!ob || !present(ob, env)) {
    this_player()->eventPrint("Your target is not here.");
    return 1;
    }
    this_player()->eventPrint("You shout: %^RED%^SECTUMSEMPRA!!%^RESET%^");
    this_player()->eventSpell(this_player(), ob);
    return 1;
}

int eventSpell(object caster, object target) {
    object env;
    float tmp;
    int success;
    object *weapons;
    int numberOfWeapons;
    int i;
    weapons = caster->GetWielded();
   
    if(!caster || !(env = environment(caster))) return 0;
    if(!target || !present(target, env)) {
    caster->eventPrint("Your target is not here.");
    return 1;
    }

   
    //tmp = caster->GetSkillLevel("sectumsempra")*1.5;
    //tmp += caster->GetStatLevel("mindpower")/2.0;
    tmp = caster->GetStatLevel("wisdom")*1.5;
    tmp += caster->GetStatLevel("luck")/2.0;
    tmp += caster->GetStatLevel("intelligence")/1.0;
    tmp += caster->GetStatLevel("agility")/2.0;
    tmp -= target->GetStatLevel("luck")/3.0;
    tmp -= target->GetStatLevel("agility")/3.0;
    tmp *= 1.0;
    if(tmp < 1.0) tmp = 1.0;
    success = to_int(tmp);

   
    //caster->AddSkillPoints("sectumsempra", to_int(success * 3.0));
    //caster->SetSkillDelay(6);
   
    moral_act(caster, target, -30);
   
    if(success < random(50) || !present(target, environment(caster))) {
    caster->eventPrint("%^RED%^" + target->GetName()
    + " dodges your spell!%^RESET%^");
    target->eventPrint("%^RED%^ You leap out of the way of " + caster->GetName() + "'s spell!%^RESET%^");
    environment(caster)->eventPrint("%^RED%^" + target->GetName() + " leaps away from " + caster->GetName() + "'s jet of red light!%^RESET%^",
    ({caster, target}));
    return 1;
    }
   
    caster->eventSectumsempra(caster, target, weapons);
   
    caster->eventExecuteAttack(target);
    return 1;
}

int eventSectumsempra(object caster, object target, object weapon) {
    int damage;
    float x;
    int percentDamage;
    float adjustment;
    string weaponType = weapon->GetWeaponType();
    int numberOfWeapons;
   
    x = weapon->GetClass() * 5.0;
    //x += caster->GetSkillLevel("sectumsempra")/1.0;
    //x += caster->GetStatLevel("mindpower")/2.0;
    x += caster->GetStatLevel("wisdom")/2.0;
    x += caster->GetStatLevel("intelligence")/2.0;
    x += caster->GetStatLevel("luck")/3.0;
    x += random(10);
    if(x < 1.0) x = 0.0;
   
    if(!numberOfWeapons || weaponType != "wand") {
    caster->eventPrint("Where's your wand?!");
    return 1;
    }
   
    damage = (int)target->eventReceiveDamage(caster,
     weapon->GetDamageType(), to_int(x), 0, target->GetTorso());
    if(damage > 0) {
    percentDamage = damage * 100 / target->GetMaxHealthPoints();
    if(percentDamage < 1) percentDamage = 0;
    }
    else percentDamage = 0;
    eventPrintDamage(caster, target, weapon, percentDamage);
    //caster->AddSkillPoints("Sectumsempra", 7 + damage/10);
    return 1;
}

int eventPrintDamage(object caster, object target, object weapon, int percentDamage) {
    string wounds;
    string colour;
   
    if(!percentDamage) {
    caster->eventPrint("%^RED%^Your spell fizzles.%^RESET%^");
    environment(caster)->eventPrint("%^RED%^" + caster->GetName()
    + " shouts, 'SECTUMSEMPRA!!' but nothing happens.%^RESET%^",
    ({caster, target}));
    return 1;
    }
   
    if(percentDamage < 15) {
    wounds = "light scratches ";
    colour = "dim red ";
    }
    else if(percentDamage < 30) {
    wounds = "deep cuts ";
    colour = "red ";
    }
    else {
    wounds = "grevious wounds ";
    colour = "blood red ";
    }
   
    caster->eventPrint("%^RED%^Your "+colour+"jet of light inflicts " + wounds
    + "on "+ target->GetName() +".");
    target->eventPrint("%^RED%^You feel "+ caster->GetName() +"'s jet of " + colour + "light inflicting " + wounds
    + "on your chest.%^RESET%^");
    environment(caster)->eventPrint("%^RED%^" + caster->GetName() + "'s jet of " + colour +"light causes " + wounds
    + "on " + target->GetName() + "'s chest!%^RESET%^", ({caster, target}));
   
    return 1
}

thanks for your time :)

8
Dead Souls Support / body.c
« on: November 02, 2007, 01:48:55 PM »
hey everyone

i've been trying to re-write body.c today, and now i only have one error that i can't figure out.

it says there's a syntax error on line 883, which is:

mixed CanWear(object ob, switch *eqslots) {

this is identical to the line in the original body.c except that everywhere in the text i changed limb to eqslot, and i've been using WornItems["slot"] with different slot names in place.  i basically want every mob/player to have the same item slots for wearing and wielding.

please have a look in that section, because it's most likely where i did stuff wrong, trying to recode the entire thing.  i tried to basically make CanWear check to see if there was an item already occupying that slot for each armor type/weapon if applicable.

thanks!

[code]
/*    /lib/body.c
 *    from the Dead Souls LPC Library
 *    handles information regarding bodies as well as events which
 *    affect them
 *    created by Descartes of Borg 950121
 *    Version: @(#) body.c 1.24@(#)
 */

#include <lib.h>
#include <config.h>
#include <rooms.h>
#include <daemons.h>
#include <function.h>
#include <medium.h>
#include <position.h>
#include <armor_types.h>
#include <damage_types.h>
#include <magic_protection.h>
#include "include/body.h"

inherit LIB_POSITION;
inherit LIB_UNDEAD;
inherit LIB_CRAWL;
inherit LIB_FLY;
inherit LIB_MOUNT;
inherit LIB_BODY_MASS;
inherit LIB_PERSIST;

#define COLLAPSE_AT            0.0

private int HealthPoints, SocialPoints, ExperiencePoints, QuestPoints;
private int melee;
private int Alcohol, Caffeine, Food, Drink, Poison, Sleeping, DeathEvents;
private string Torso, Biter;
private mapping Fingers, Limbs, MissingLimbs, eqslots;
private static int Dying, LastHeal, Encumbrance;
private static function Protect;
private static mapping WornItems;
private static class MagicProtection *Protection;
static private int HeartModifier = 0;
private static string PoliticalParty, BodyComposition;
private static int Pacifist, rifleshot_wounds, gunshot_wounds, globalint1;
private static int Size, Respiration, BodyType;
string *ExtraChannels;
mixed Agent;

string GetRace();

static void create() {
    PoliticalParty = "UNDECIDED";
    rifleshot_wounds = 0;
    gunshot_wounds = 0;
    DeathEvents = 0;
    NewBody(0);
    Protect = 0;
    WornItems = ([]);
    Limbs = ([]);
    Food = Drink = 100;
    Alcohol = Caffeine = 0;
    HealthPoints = SocialPoints = 50;
    ExperiencePoints = 1000;
    QuestPoints = 0;
    Dying = 0;
    LastHeal = time();
    Protection = ({});
    ExtraChannels = ({});
    eqslots = ([]);
   
}

varargs mixed eventBuy(mixed arg1, mixed arg2, mixed arg3){
    //This function will hopefully get overridden where appropriate.
    write(capitalize(this_object()->GetShort())+" isn't buying anything from you.");
    return 1;
}
int GetMaxSocialPoints() {return 0;}
int AddSocialPoints(int x) {
    int y;
    if((SocialPoints += x) < 1) SocialPoints = 0;
    else if(SocialPoints > (y = GetMaxSocialPoints())) SocialPoints = y;
    return SocialPoints;
    }
int GetSocialPoints() {return SocialPoints;}


int GetMass(){
    return body_mass::GetBodyMass();
}

int GetSize(){
    int size = RACES_D->GetRaceSize(GetRace());
    if(Size) return Size;
    return size;
}

int GetRespiration(){
    int resp = RACES_D->GetRaceRespirationType(GetRace());
    if(Respiration) return Respiration;
    return resp;
}

int GetBodyType(){
    int body_type = RACES_D->GetRaceBodyType(GetRace());
    if(BodyType) return BodyType;
    return body_type;
}

int SetMass(int i){
    return body_mass::SetBodyMass(i);
}

int SetSize(int i){
    return Size = i;
}

int SetRespiration(int i){
    return Respiration = i;
}

int SetBodyType(int i){
    return BodyType = i;
}


int GetEncumbrance(){
    int encumbrance = 0;
    object *stuff = filter(all_inventory(this_object()), (: !($1->GetWorn()) :) );

    if(!(ENABLE_ENCUMBRANCE) || inherits(LIB_NPC,this_object()) ) return encumbrance;
    if(sizeof(stuff)) foreach(object item in stuff)
   encumbrance += (item->GetMass())/2;
    if(sizeof(stuff)) encumbrance += sizeof(stuff);
    return encumbrance;
}

string SetBodyComposition(string str){
    if(!str) return "";
    else BodyComposition = str;
    return BodyComposition;
}

string GetBodyComposition(){
    return BodyComposition;
}

int GetPacifist(){
    return Pacifist;
}

int SetPacifist(int i){
    if(!i) Pacifist = 0;
    else Pacifist = 1;
    return Pacifist;
}

int SetCanBite(int i){
    if(i) Biter = "yes";
    else Biter = "no";
    return i;
}

int GetCanBite(){
    if(sizeof(Biter)){
   if(Biter == "yes") return 1;
   else return 0;
    }
    else return RACES_D->GetBitingRace(this_object()->GetRace());
}

string *AddExtraChannels(string *chans){
    foreach(string chan in chans){
   if(member_array(chan,this_player()->GetChannels()) == -1){
       ExtraChannels += ({ chan });
   }
    }
    return ExtraChannels;
}

string *RemoveExtraChannels(string *chans){
    foreach(string chan in chans){
   if(member_array(chan,this_player()->GetChannels()) != -1){
       ExtraChannels -= ({ chan });
   }
    }
    return ExtraChannels;
}

string *GetExtraChannels(){
    return ExtraChannels;
}

string *SetExtraChannels(string *chans){
    ExtraChannels = chans;
    return ExtraChannels;
}

mixed direct_turn_liv() {
    if( GetUndead() ) {
   return 1;
    }
    else {
   return "You cannot turn the living!";
    }
}

static void heart_beat() {
    object env = environment();
    int i;

    undead::heart_beat();
    if( i = sizeof(Protection) ) {
   while(i--)
       if( Protection->time && (--Protection->time < 1) )
      RemoveMagicProtection(i);
    }
    if( env && (i = env->GetPoisonGas()) > 0 ) {
   if( GetResistance(GAS) != "immune" ) {
       eventPrint("You choke on the poisonous gases.");
       eventReceiveDamage("Poison gas", GAS, i);
   }
    }
    eventCheckHealing();
    if(!stringp(hobbled(this_player()))) {
        this_object()->eventCollapse();
    }
    if(this_object()->GetPosition() == POSITION_FLYING && !this_object()->CanFly()){
   eventFall();
    }
}

void eventReconnect() {
    LastHeal = time();
}

void ParseHook(string str){
    parse_sentence(str);
}


/************      /lib/body.c Modal Methods Section      ************/

mixed CanRemoveItem(object ob) { return 1; }

/************      /lib/body.c Events Section      ************/

private void checkCollapse() {
    float h = percent(GetHealthPoints(), GetMaxHealthPoints());

    if( h < COLLAPSE_AT ) {
   SetParalyzed(3, (: checkCollapse :));
   return;
    }
    eventPrint("You feel some strength returning.");
}

int eventCollapse() {
    int position = GetPosition();

    if(!this_object() || !environment()) return 0;

    foreach(object ob in all_inventory(environment())){
   if(inherits(LIB_CHAIR,ob) || inherits(LIB_BED,ob) ){
       ob->eventReleaseStand(this_object());
   }
    }

    SetParalyzed(3, (: checkCollapse :));
    if( position == POSITION_LYING ) {
   return 1;
    }
    send_messages("collapse", "$agent_name $agent_verb to the ground.",
      this_object(), 0, environment());
    SetPosition(POSITION_LYING);
    return 1;
}

void eventCheckHealing() {
    int x, y;
    object dude;
    dude = this_object();

    //This resets the parser counter.
    this_object()->DoneTrying();

    if(HealthPoints < 1) {
   this_object()->eventDie(previous_object());
   return;
    }

    x = GetHeartRate() * 10;

    if(dude->GetSleeping() > 0 && dude->GetPosition() != POSITION_LYING
      && dude->GetPosition() != POSITION_SITTING){
   dude->eventCollapse();
    }

    if(dude->GetInCombat()){
   if(dude->GetInvis()) dude->SetInvis(0);
   if(!interactive(dude) && !RACES_D->GetLimblessRace(dude->GetRace())) {
       dude->SetAutoStand(1);
   }
    }

    if( (y = time() - LastHeal)  >= x ) {
   LastHeal = time();
   do {
       eventCompleteHeal(GetHealRate());
   } while( (y = y - x) >= x );
   if( Alcohol > 0 ) {
       Alcohol--;
       if( !Alcohol ) {
      message("my_action", "You are left with a pounding headache.",
        this_object());
       }
       else if( !GetSleeping() && random(100) < 8 ) {
      string verb, adv;

      switch(random(5)) {
      case 0: verb = "burp"; adv = "rudely"; break;
      case 1: verb = "look"; adv = "ill"; break;
      case 2: verb = "hiccup"; adv = "loudly"; break;
      case 3: verb = "stumble"; adv = "clumsily"; break;
      case 4: verb = "appear"; adv = "drunk"; break;
      }
      message("my_action", "You " + verb + " " + adv + ".",
        this_object());
      message("other_action", GetName() + " " + pluralize(verb) + " " +
        adv + ".", environment(), ({ this_object() }));
       }
   }
   if( Sleeping > 0 ) {
       Sleeping--;
       if( !Sleeping || dude->GetInCombat() ) {
      Sleeping = 0;
      message("my_action", "You wake up!", this_object());
      message("other_action", GetName() + " wakes up from " +
        possessive(this_object()) + " deep sleep.",
        environment(this_object()), ({ this_object() }));
       }
       else if( random(100) < 8 ) {
      message("my_action", "You snore.", this_object());
      message("other_action", (string)this_player()->GetName() +
        " snores loudly.", environment(this_object()),
        ({ this_object() }));
       }
   }
   if( Caffeine > 0 ) Caffeine--;
   if( Food > 0 ) Food--;
   if( Drink > 0 ) Drink--;
    }
}

void eventCompleteHeal(int x) {
    eventHealDamage(x, 1);
    AddSocialPoints(x + 1);
}
/*
mixed eventFall() {
    object env = environment();
    string dest;

    if( !env ) {
   return 0;
    }
    if( GetPosition() == POSITION_LYING ) {
   return 0;
    }
    if( env->GetMedium() == MEDIUM_AIR ) {
   return position::eventFall();
    }
    dest = env->GetGround();
#if 0
    if( !dest ) {
   send_messages(({ "fall", "die" }), "$agent_name $agent_verb into a "
     "dark abyss and $agent_verb.", this_object(), 0, env);
   this_object()->eventCollapse();
   eventDie("Deceleration sickness");
    }
#endif
    if(!dest){
   int p = random(100) + 1;
   int was_undead = GetUndead();

   send_messages("fall", "$agent_name $agent_verb through the sky "
     "towards the world below.", this_object(), 0, env);
   eventMove(dest);
   environment()->eventPrint(GetName() + " comes falling in from above.",
     this_object());
   this_object()->eventCollapse();
   foreach(string limb in GetLimbs()) {
       int hp = GetHealthPoints(limb);

       p = (hp * p)/100;
       //eventReceiveDamage("Deceleration sickness", BLUNT, p, 0, ({ limb }));
       //tc("hmm.");
       eventReceiveDamage("Deceleration sickness", BLUNT, p, 0, ({ GetTorso() }));
       if( Dying || (was_undead != GetUndead()) ) {
      break;
       }
   }
    }
}
*/
/* varargs int eventHealDamage(int x, int internal, mixed limbs)
 * int x - amount of damage being healed, negatives illegal (required)
 * int internal - internal damage flag (optional)
 * mixed limbs - limb or limbs affected by the heal event (optional)
 *
 * defaults
 * internal defaults to 0
 * limbs defaults to 0
 *
 * description
 * this event is triggered whenever something performs a healing action
 * on the body
 *
 * if the internal flag is set then overall health is healed.
 * if limbs are specified then the specified limbs are healed. * if the internal flag is NOT set and NO limbs are specified (default)
 *   then both overall health as well as the health of all limbs are healed.
 *
 * returns the actual amount of healing done or -1 if an error occurs
 */
 /*
varargs int eventHealDamage(int x, int internal, mixed limbs) {
    if(!limbs && !internal) {
   limbs = GetLimbs(); internal = 1;
    }
    else if(stringp(limbs)) {
   limbs = ({ limbs });
    }
    if(!limbs) {
   limbs = ({});
    }
    if( !arrayp(limbs)) {
   error("Bad argument 3 to eventHealDamage().\n");
    }
    if(internal) {
   AddHealthPoints(x);
    }
    map(limbs, (: AddHealthPoints($(x), $1) :));
    return x;
}
*/
varargs int eventHealDamage(int x) {
    AddHealthPoints(x);
    return x;
}

/* varargs int eventReceiveDamage(mixed agent, int type, int x,
 *     int internal, mixed limbs)
 * object agent - the thing responsible for this damage (required)
 * int type - the damage type(s) being done (required)
 * int x - the amount of damage being done, negatives illegal (required)
 * int internal - flag for internal or external damage (optional)
 * mixed limbs - limbs to which damage has been done (optional)
 *
 * defaults
 * internal defaults to 0
 * limbs defaults to 0
 *
 * description
 * handles sorting out damage events which happen to the body
 * It assumes some agent is acting as the cause of this event, an
 * agent being some sort of being as the cause of the event
 * the previous_object() is considered to be doing the actual damage
 * what does the damage is different than the agent in the sense
 * that a knife does damage and a living thing is the agent
 * can't get into more detail without getting philosophical, which is
 * beyond the scope of a comment
 * "x" amount of damage gets attempted, modified by varying things like
 * armor and natural resistence to this type of damage
 * the internal flag with no limbs specified means that the damage
 * is taken solely to the overall health
 * if the internal flag is set with limbs, the damage is both internal and
 * done to named limbs
 * if no internal flag is set and no limbs are specified, damage is done to
 * all limbs
 * if no internal flag is set and limbs are specified, then damage is done
 * only to the specified limbs
 * NOTE: internal damage is not modified by armor worn
 *
 * returns the average actual amount of damage done
 */
/*
varargs int eventReceiveDamage(mixed agent, int type, int x, int internal,
  mixed limbs) {
    string tmp = GetResistance(type);
    string agentname;
    int fp;

    //tc("wtf");
    //tc("agent: "+identify(agent),"red");

    if(agent && stringp(agent)){
   agentname = agent;
   agent = 0;
    }

    //tc("stack: "+get_stack(),"red");
    //tc("agent: "+identify(agent),"red");

    if( tmp == "immune") {
   return 0;
    }
    switch(tmp) {
    case "low": x = (3*x)/4; break;
    case "medium": x /= 2; break;
    case "high": x /= 4; break;
    }
    if( fp = functionp(Protect) ) {
   if( !(fp & FP_OWNER_DESTED) ) {
       function f;

       f = Protect;
       Protect = 0;
       x -= evaluate(f, this_object(), agent, type, x, limbs);
   }
    }
    x = eventCheckProtection(agent, type, x);
    if( !limbs ) {
   if( internal ) {
       AddHealthPoints(-x, 0, (agent || agentname));
       return x;
   }
   else {
       limbs = GetLimbs();
   }
    }
    else if( stringp(limbs) ) {
   limbs = ({ limbs });
    }
    else if( !arrayp(limbs) ) {
   return -1;
    }
    if( internal ) {
   limbs = filter(limbs, (: !AddHealthPoints(-$(x), $1, $(agent)) :));
   map(limbs, (: (Limbs[$1] ? this_object()->RemoveLimb($1, $(agent)) : 0) :));
   AddHealthPoints(-x, 0, (agent || agentname));
   return x;
    }
    else {
   int i, y, maxi;

   y = 0;
   for(i=0, maxi = sizeof(limbs); i < maxi; i++) {
       object *obs;
       int j, z;

       z = x;
       if(!Limbs[limbs]) {          /* no limb, no damage
      y += z;
      continue;
       }
       if(!(j = sizeof(obs = GetWorn(limbs)))) { /* no armor
      y += z;                     /* add to total damage
      if( !AddHealthPoints(-z, limbs, (agent || agentname)) )
          this_object()->RemoveLimb(limbs, (agent || agentname));
      continue;
       }
       while(j--) {
      z -= (int)obs[j]->eventReceiveDamage((agent || agentname),type, z, 0, limbs);
      if(z < 1) break;
       }
       if(z < 1) continue;
       else {
      y += z;
      if(!AddHealthPoints(-z, limbs, agent))
          this_object()->RemoveLimb(limbs, (agent || agentname));
       }
   }
   y = y / (maxi ? maxi : 1);
   if( y ) {
       AddHealthPoints(-y, 0, (agent || agentname));
       AddStaminaPoints(-y/2);
   }
   return y;
    }
    AddHealthPoints(-x, 0, agent);
    AddStaminaPoints(-x/2);
    if(HealthPoints < 1) eventDie((agent || agentname));
    return x;
}
*/
varargs int eventReceiveDamage(mixed agent, int type, int x) {
    string agentname;
    if(agent && stringp(agent)){
        agentname = agent;
        agent = 0;
    }
    AddHealthPoints(-x, 0, (agent || agentname));
    return x;
}
   
/*  int eventCheckProtection(object agent, int type, int damage)
 *
 *  agent  : object doing the damage
 *  type   : damage type(s)
 *  damage : original amount damage being done
 *
 *  This function cycles through any magic protection found, reducing
 *  damage accordingly.
 *
 *  returns modified damage

int eventCheckProtection(object agent, int type, int damage) {
    int i, y;
    if( !i = sizeof(Protection) ) return damage;
    while(i--) {
   int x;

   if( (type & Protection->bits) != type ) continue;
   if( Protection->absorb ) {
       if( (x = (Protection->absorb - damage)) < 1 ) {
      x = Protection->absorb;
      RemoveMagicProtection(i);
      damage -= x;
      if( damage < 1 ) return 0;
      continue;
       }
       Protection->absorb -= damage;
   }
   else if( Protection->protect )
       x = (random(Protection->protect / 2) +
         (Protection->protect / 2));
   else {
       RemoveMagicProtection(i);
       continue;
   }
   if( y = functionp(Protection->hit) ) {
       if( y == FP_OWNER_DESTED ) {
      RemoveMagicProtection(i);
      continue;
       }
       else x = (int)evaluate(Protection->hit, this_object(),
        agent, x, Protection);
   }
   damage -= x;
   if( damage < 1 ) return 0;
    }
    return damage;
}


mixed eventReceiveThrow(object who, object what) {
    int x;

    if( what->GetClass() > 1 ) {
   int mod = who->GetSkillLevel("projectile attack") +
   who->GetStatLevel("strength");

   x = what->eventStrike(this_object()) * 3;
   x = (x*mod)/100;
   if( what->GetWeaponType() != "projectile" ) {
       x = x/4;
   }
   x = eventReceiveDamage(who, what->GetDamageType(), x, 0,
     GetRandomLimb("torso"));
   if( x > 0 ) {
       who->AddSkillPoints("projectile attack", x);
   }
    }
    else {
   x = 0;
    }
    if( x < 1 ) {
   environment()->eventPrint(GetName() + " catches " +
     possessive_noun(who->GetName()) + " " +
     what->GetKeyName() + ".",
     ({ this_object(), who }));
   eventPrint("You catch " + possessive_noun(who->GetName()) + " " +
     what->GetKeyName() + ".");
   who->eventPrint(GetName() + " catches your " + what->GetKeyName()
     + ".");
    }
    else {
   environment()->eventPrint(GetName() + " takes damage from " +
     possessive_noun(who->GetName()) + " " +
     what->GetKeyName() + ".",
     ({ this_object(), who }));
   eventPrint("You take damage from " + possessive_noun(who->GetName()) +
     " " + what->GetKeyName() + ".");
   who->eventPrint(GetName() + " takes damage from your " +
     what->GetKeyName() + ".");
    }
    what->eventMove(this_object());
    return 1;
}
*/

/* varargs int eventDie(mixed agent)
 * mixed agent - the agent responsible for the death (optional)
 *
 * description
 * Kills the owner of this body if not already dying
 *
 * returns true if the thing is dying
 */
varargs int eventDie(mixed agent) {
    int x;
    string killer, death_annc;
    object crime_scene;

    if(DeathEvents) return 1;
    DeathEvents = 1;

    //tc("stack: "+get_stack());
    //if(agent) tc("agent: "+identify(agent),"green");
    //tc("prevs: "+identify(previous_object(-1)));

    if(agent && stringp(agent)) killer = agent;
    else {
   if(!agent) killer = "UNKNOWN";
   else killer = agent->GetName();
    }

    death_annc = killer + " has slain "+ this_object()->GetName()+".";

    CHAT_D->eventSendChannel("SYSTEM","death",death_annc,0);

    if( Sleeping > 0 ) Sleeping = 0;

    if( agent && objectp(agent) ) {
   if( x ) agent->eventDestroyEnemy(this_object());
   else agent->eventKillEnemy(this_object());
    }
    crime_scene = environment();
    if( crime_scene ) {
   object *obs;
   string *currs;
   object ob;
   string curr;
   int i;
   object *riders = GetRiders();

   //I'd like to move the living body out first, but for now this
   //misfeature stays.
   //this_object()->eventMove(ROOM_VOID);

   if(riders && sizeof(riders)){
       foreach(object rider in riders) eventBuck(rider);
   }
   if(GetRace() == "android" || GetRace() == "bot" ) ob = new(LIB_BOT_CORPSE);
   else if(member_array(GetRace(), RACES_D->GetNonMeatRaces()) != -1) {
       ob = crime_scene;
       if(GetBodyComposition()){
      ob = new(LIB_CLAY);
      ob->SetComposition(GetBodyComposition());
       }
   }
   else {
       ob = new(LIB_CORPSE);
       ob->SetCorpse(this_object());
   }
   if(ob != crime_scene) ob->eventMove(crime_scene);
   obs = filter(all_inventory(), (: !((int)$1->GetRetainOnDeath()) :));
   i = sizeof(obs);
   obs->eventMove(ob);
   currs = (string *)this_object()->GetCurrencies() || ({});
   foreach(curr in currs) {
       object pile;
       int amt;

       if( amt = (int)this_object()->GetCurrency(curr) ) {
      pile = new(LIB_PILE);
      pile->SetPile(curr, amt);
      pile->eventMove(ob);
      this_object()->AddCurrency(curr, -amt);
       }
   }
    }

    SetUndead(!(x = GetUndead()));

    evaluate( function() { Dying = 0; });
      flush_messages();
      return 1;
  }

  /* int eventRemoveItem(object ob)
   * object ob - the item being removed
   *
   * Removes a worn or wielded item from the list
   *
   * returns 1 on success, 0 on failure
   
    int eventRemoveItem(object ob) {
   string limb;

   foreach(limb in keys(WornItems)) {
       if( !WornItems[limb] ) continue;
       if( member_array(ob, WornItems[limb]) != -1) {
      WornItems[limb] -= ({ ob });
       }
   }
   return 1;
    }
*/

int eventRemoveItem(object ob) {
    string eqslot;
    foreach(eqslot in keys(WornItems)) {
        if( !WornItems[eqslot] ) continue;
        if( member_array(ob, WornItems[eqslot]) != -1) {
            WornItems[eqslot] -= ({ ob });
        }
    }
    return 1;
}
    /* int eventWear(object ob, mixed limbs)
     * object ob - the item being worn (wielded)
     * mixed limbs - string or array of limbs on which it is being worn
     *
     * description
     * marks the limbs "limbs" as being protected by the armor "ob"
     *
     * returns 1 if successful, 0 if failure
     
    int eventWear(object ob, mixed limbs) {
   string limb,s1;
   string *target_limb;
   target_limb = ({});

   if( stringp(limbs) ) {
       limbs = ({ limbs });
   }
   if( CanWear(ob, limbs) != 1 ) {
       return 0;
   }
   if(!inherits(LIB_WEAPON, ob)){
       foreach(limb in limbs) {
      if(sscanf(limb,"%s foot",s1) || sscanf(limb,"%s hand",s1) ){
          if(!sizeof(GetWorn(limb))) target_limb = ({ limb });
      }
       }
   }
   if(sizeof(target_limb)) limbs = target_limb;
   foreach(limb in limbs) {
       if( !WornItems[limb] ) WornItems[limb] = ({ ob });
       else WornItems[limb] += ({ ob });
   }
   return 1;
    }
*/
int eventWear(object ob, mixed eqslots) {
    string eqslot, s1;
    string *target_eqslot;
    target_eqslot = ({});
    if ( stringp(eqslots)){
        eqslots = ({ eqslots });
    }
    if( CanWear(ob, eqslots) != 1 ){
        return 0;
    }
    if(!inherits(LIB_WEAPON, ob)){
        if(!sizeof(GetWorn("wielded"))) target_eqslot = ({"wielded"});
    }
    if(sizeof(target_eqslot)) eqslots = target_eqslot;
    foreach(eqslot in eqslots) {
        if( !WornItems[eqslot] ) WornItems[eqslot] = ({ob});
        else WornItems[eqslot] += ({ob});
    }
    return 1;
}

    string *GetEquippedSlots(){
   string *equipped_slots = ({});
   object *wornstuff = filter(all_inventory(this_object()), (: $1->GetWorn() :) );

   foreach(object item in wornstuff){
       equipped_slots += item->GetWorn();
   }
   return equipped_slots;
    }
    /************     /lib/body.c Data manipulation functions      *************/
    void NewBody(string race) {
   eqslots = ([]);
    }

   mixed CanManipulate(){
   return 1;
    }
   
mixed CanWear(object ob, switch *eqslots) {
    string eqslot, verb_pr, verb_pt, short;
    int type, bad_types, i, maxi;
   
    if( !ob ) return 0;
    short = (string)ob->GetShort();
    if(!(type = (int)ob->GetArmorType()))
        return capitalize(short) + " cannot be worn!";
    if( type & A_WEAPON ) {
        verb_pr = "wield";
        verb_pt = "wielded";
    }
    else {
        verb_pr = "wear";
        verb_pt = "worn";
    }
/*    if( !slots || !(maxi = sizeof(slots)) )
        return "where should " + short + " be "+ verb_pt + "?";
*/
    if( (string *)ob->GetWorn() )
        return "It is already being "+ verb_pt + ".";
    switch(type) {
    case A_RING:
        if(!WornItems["other"]) return 1;
        else return "You're aleady wearing something there.";
    case A_GLOVE:
        if(!WornItems["hands"]) return 1;
        else return "You're already wearing something there.";
    case A_BOOT:
        if(!WornItems["feet"]) return 1;
        else return "You're already wearing something there.";
    case A_HELMET:
        if(!WornItems["head"]) return 1;
        else return "You're already wearing something there.";
    case A_SHIRT:
        if(!WornItems["body"]) return 1;
        else return "You're already wearing something there.";
    case A_PANTS:
        if(!WornItems["legs"]) return 1;
        else return "You're already wearing something there.";
    case A_SHIELD:
        if(!WornItems["shield"])
            if(!WornItems["offhand"]) return 1;
            else return "You cannot wield two weapons and hold a shield.";
        else return "You're already wearing something there.";
    case A_CLOAK:
        if(!WornItems["cloak"]) return 1;
        else return "You're already wearing something there.";
    case A_WEAPON:
        object worn_item;
        int tmp = 0;
        if(!WornItems["wielded"]) return 1;
        else if(!WornItems["offhand"] && !WornItems["shield"]) return 1;
        else return "Your hands are already full.";
    default: return 0;
    }
    return 1;
}

    int CanFly(){/*
   string clipped = identify(this_player()->GetMissingLimbs());

   if(creatorp(this_player())) return 1;

   if(!RACES_D->CanFly(this_player()->GetRace())) {
       return 0;
   }

   if(!clipped || !sizeof(clipped)) return 1;
   if(!grepp(lower_case(clipped),"wing")) return 1;*/
   return 0;
    }


    /* int AddLimb(string limb, string parent, int classes, int *armors)
     * string limb - the limb being added (required)
     * string parent - the limb to which this one is being attached (required)
     * int classes - rating of the limb's strength (optional)
     * int *armors - the types of armors which can be worn here (optional)
     *
     * defaults
     * classes defaults to 1
     * armors defaults to ({})
     *
     * description
     * adds the named limb to the body, attached at the named point
     * the limb classes starts at 1 for a torso (strongest)
     * to whatever the documentation rates as the weakest
     *
     * returns 1 on success, 0 on failure
     */
/*
    varargs int AddLimb(string limb, string parent, int classes, int *armors) {
   int arm = 0;

   if(!limb || Limbs[limb] || (parent && !Limbs[parent])) return 0;
   if(armors) {
       int i;

       i = sizeof(armors);
       while(i--) arm |= armors;
   }
   if(MissingLimbs[limb]) map_delete(MissingLimbs, limb);
   if( parent ) Limbs[parent]["children"] += ({ limb });
   else Torso = limb;
   if( !classes ) classes = 5;
   Limbs[limb] = ([ "parent" : parent, "children" : ({}), "class" : classes,
     "armors" : arm ]);
   Limbs[limb]["health"] = GetMaxHealthPoints(limb);
   return 1;
    }


    int HealLimb(string limb){
   Limbs[limb]["health"] = GetMaxHealthPoints(limb);
   return Limbs[limb]["health"];
    }

    // Restore Limb has been bugfixed and modified to
    // handle missing parents and missing children. To restore
    // a limb, RestoreLimb("right arm") will restore the arm only.
    // To restore the arm plus its children (in this case, a
    // hand) use RestoreLimb("right arm",1) and this will enable
    // the recursive restore of the limb. Trying to restore
    // a limb will fail if the parent is missing.

    varargs int RestoreLimb(string limb, int recurse) {
   if( !MissingLimbs[limb] ) return 0;
   if(!sizeof(Limbs[MissingLimbs[limb]["parent"]])) return 0; 
   Limbs[limb] = MissingLimbs[limb];
   map_delete(MissingLimbs, limb);
   Limbs[limb]["health"] = GetMaxHealthPoints(limb);

   // This ensures that the parent of the current limb has this
   // limb added to its children array.
   if(member_array(limb,Limbs[Limbs[limb]["parent"]]["children"]) == -1){
       Limbs[Limbs[limb]["parent"]]["children"] += ({ limb });
   }

   if(recurse && sizeof(MissingLimbs)){
       string *kinder = ({});
       foreach(string key, mixed val in MissingLimbs){
      if(MissingLimbs[key]["parent"] == limb) kinder += ({ key });
       }
       if(sizeof(kinder)){
      foreach(string element in kinder) this_object()->RestoreLimb(element, 1);
       }
   }

   return 1;
    }
*/
    /* int DestLimb(string limb)
     * string limb - the limb being removed
     *
     * description
     * removes a limb from the limbs mapping.  The limb isn't marked as mising,
     * and the monster doesn't die even if you remove a fatal limb.  Useful for
     * removing limbs from standard race types.  Removing the torso isn't allowed.
     *
     * returns -1 on error, 0 on failure, 1 on success
     */
     
/*
    int DestLimb(string limb) {
   string *kiddies;
   int i;

   if(!limb || !Limbs[limb]) return -1;
   if(!Limbs[limb]["parent"]) {
       return -1;
   }
   Limbs[Limbs[limb]["parent"]]["children"] -= ({ limb });
   if( (i = sizeof(kiddies = Limbs[limb]["children"])) )
       while(i--) DestLimb(kiddies);
   map_delete(Limbs, limb);
   return 1;
    }
*/
    /* int this_object()->RemoveLimb(string limb, object agent)
     * string limb - the limb being removed
     * object agent - the agent who is responsible for the limb removal
     *
     * description
     * removes a limb from the limbs mapping and stores vital data in the
     * missing limbs mapping
     *
     * returns -1 on error, 0 on failure, 1 on success
     */
/*
    int RemoveLimb(string limb, mixed agent) {
   string *kiddies;
   string limbname,adjname,templimbname, agentname;
   int i;

   if(agent && stringp(agent)){
       agentname = agent;
       agent = 0;
   }

   if(limb == "torso" || limb == "neck") return 0;

   if( sscanf(limb, "%s %s", adjname, templimbname) == 2 ) limbname=templimbname;
   else limbname=limb;

   if(!limb || !Limbs[limb]) return -1;
   if(!Limbs[limb]["parent"] || Limbs[limb]["class"] == 1) {
       object objict;
       message("environment", possessive_noun(GetName()) + " " + limb +
         " is severed!", environment(), ({ this_object() }));
       message("environment", "Your "+ limb + " is severed!", this_object());


       if(GetRace() == "golem") {
      objict = new(LIB_CLAY);
      if(GetBodyComposition()) objict->SetComposition(GetBodyComposition());
       }
       else {
      if(GetRace() == "android" || GetRace() == "bot") objict = new(LIB_BOT_LIMB);
      else objict = new(LIB_LIMB);
      objict->SetLimb(limb, GetCapName(), GetRace());
      objict->SetId( ({ limb, limbname, "limb" }));
       }
       objict->eventMove(environment());
       i = sizeof(WornItems[limb]);
       while(i--) {
      WornItems[limb]->SetWorn(0);
      WornItems[limb]->eventMove(objict);
       }
       while( i = sizeof(WornItems[limb]) )
      eventRemoveItem(WornItems[limb]);

       HealthPoints = 0;
       if( !Dying ) {
      Dying = 1;
      Agent = agent;
      eventDie((Agent ? Agent : agentname));
       }
       return 0;
   }
   MissingLimbs[limb] = copy(Limbs[limb]);
   Limbs[Limbs[limb]["parent"]]["children"] -= ({ limb });
   if( (i = sizeof(kiddies = Limbs[limb]["children"])) )
       while(i--) this_object()->RemoveLimb(kiddies, agent);
   map_delete(Limbs, limb);
   if( environment() ) {
       object ob;

       message("environment", possessive_noun(GetName()) + " " + limb +
         " is severed!", environment(), ({ this_object() }));
       message("environment", "Your "+ limb + " is severed!", this_object());
       if(GetRace() == "golem") {
      ob = new(LIB_CLAY);
      if(GetBodyComposition()) ob->SetComposition(GetBodyComposition());
       }
       else {
      if(GetRace() == "android" || GetRace() == "bot") ob = new(LIB_BOT_LIMB);
      else ob = new(LIB_LIMB);
      ob->SetLimb(limb, GetCapName(), GetRace());
      ob->SetId( ({ limb, limbname, "limb" }));
       }
       ob->eventMove(environment());
       i = sizeof(WornItems[limb]);
       while(i--) {
      WornItems[limb]->SetWorn(0);
      WornItems[limb]->eventMove(ob);
       }
       while( i = sizeof(WornItems[limb]) )
      eventRemoveItem(WornItems[limb]);
   }

   return 1;
    }
*/
/*
    mapping GetLimb(string limb) {
   if(!limb || !Limbs[limb]) return 0;
   else return copy(Limbs[limb]);
    }
*/
    /* string GetRandomLimb(string targ)
     * string targ - the targetted limb
     *
     * description
     * returns a random limb weighted towards the targetted limb
     */
/*
    string GetRandomLimb(string targ) {
   string array limbs;

   if( !targ ) {
       targ = GetTorso();
   }
   if( member_array(targ, (limbs=keys(Limbs))) == -1) {
       targ= GetTorso(); /* no target or illegal target, weight torso
   }
   targ = (limbs + (targ ? ({ targ, targ }) : ({})))[random(sizeof(limbs)+2)];
   return targ;
    }
*/
/*
    string GetTorso() {
   string *limbs;
   int i;

   i = sizeof(limbs = keys(Limbs));
   while(i--) {
       if(!Limbs[limbs]["parent"]) {
      return limbs;
       }
   }
   return 0;
    }

    string array GetLimbs() {
   return (Limbs ? keys(Limbs) : 0);
    }

    int GetLimbClass(string limb) { return Limbs[limb]["class"]; }

    string GetLimbParent(string limb) { return Limbs[limb]["parent"]; }


    //The following function courtesy of Garfield @ M*U*D
    string GetMissingLimbParent(string limb) { return MissingLimbs[limb]["parent"]; }

    //The following function courtesy of Garfield @ M*U*D
    string *GetMissingLimbParents(string limb) {
   string *limbs;

   limbs = ({ limb });

   while(memberp(keys(MissingLimbs),GetMissingLimbParent(limbs[0]))){
       limbs = ({ GetMissingLimbParent(limbs[0]) }) + limbs;
   }

   return limbs;
    }

    string array GetLimbChildren(string limb) {
   return Limbs[limb]["children"] + ({});
    }

    mapping GetMissingLimb(string limb) {
   return (limb ? copy(MissingLimbs[limb]) : 0);
    }

    // This function courtesy of Garfield
    // and Javelin at M*U*D
    int eventCompareLimbs(string limb1, string limb2){
   if (memberp(GetMissingLimbParents(limb1), limb2)){
       return 1;
   }
   if (memberp(GetMissingLimbParents(limb2), limb1)){
       return -1;
   }
   return strcmp(limb1, limb2);    }

    // New comparison functionality courtesy of
    // Garfield and Javelin at M*U*D
    varargs string array GetMissingLimbs(int not_default) {
   if(not_default) {
       string *tmp_arr = ({});
       if(sizeof(keys(MissingLimbs))){
      tmp_arr = sort_array(keys(MissingLimbs), (: eventCompareLimbs :) );
       }
       return tmp_arr;
   }
   else return keys(MissingLimbs);
    }
*/
    string GetLong(string nom) {
   string *eqslots;
   string *exempt;
   string str;
   float h;

   str = "";
   exempt = ({"bot","android","tree","plant"});

   if(!(this_object()->GetNoCondition())){
       if(member_array(this_object()->GetRace(),exempt) == -1 &&
         !this_object()->GetUndead() ) {
      str = "The "+this_object()->GetGender()+" ";
      str += this_object()->GetRace();
      h = percent(GetHealthPoints(), GetMaxHealthPoints());
      if( h < 0.0 ) str += " is mortally wounded.\n";
      else if( h < 15.0 ) str += " is near death.\n";
      else if( h < 30.0 ) str += " is terribly injured.\n";
      else if( h < 45.0 ) str += " is badly injured.\n";
      else if( h < 60.0 ) str += " is hurting.\n";
      else if( h < 70.0 ) str += " is slightly injured.\n";
      else if( h < 80.0 ) str += " is slightly injured.\n";
      else if( h < 90.0 ) str += " is in decent shape.\n";
      else str += " is in top condition.\n";
       }
   }
   if(this_object()->GetUndead()) {
       str = capitalize(nominative(this_object()))+" has been killed, and ";
       str +=  "is one of the Walking Undead.\n";
   }
/*
   limbs = GetMissingLimbs();
   if( sizeof(limbs) ) {
       int i, maxi;

       str += capitalize(nom) + " is missing " + add_article(limbs[0]);
       for(i=1, maxi = sizeof(limbs); i<maxi; i++) {
      if( i < maxi-1 ) str += ", " + add_article(limbs);
      else {
          if( maxi > 2 ) str += ",";
          str += " and " + add_article(limbs);
      }
       }
       str += ".\n";
   }
*/
   return str;
    }

//    string array GetWieldingLimbs() {
//   return filter(keys(Limbs), (: (Limbs[$1]["armors"] & A_WEAPON) :));
//    }

    /* int AddFingers(string limb, int x)
     * string limb - the limb to which fingers will be added
     * int x - the number of fingers being added, can be negative
     *
     * description
     * adds the given number of fingers to the given limb
     *
     * returns the total number of fingers after addition
     */
/*
    varargs int AddFingers(string limb, int x) {
   if((Fingers[limb] += x) < 1) Fingers[limb] = 1;
   return Fingers[limb];
    }

    int GetFingers(string limb) {
   return Fingers[limb];
    }
*/
    varargs object *GetWorn(string eqslot) {
   if(!eqslot) {
       object *ret = ({});
       string *eqslots;
       int i;

       i = sizeof(eqslots = keys(eqslots));
       while(i--) if(WornItems[eqslot]) ret += ({ WornItems[eqslot] });
       return distinct_array(ret);
   }
   else if(!WornItems[eqslot]) return ({});
   else return (WornItems[eqslot] + ({}));
    }

    varargs mixed GetWielded(string eqslot) {
   if(!eqslot) {
       object *ret = ({});
       string *eqslots;
       int i;

       i = sizeof(eqslots = keys(eqslots));
       while(i--) {
      if(!WornItems[eqslots]) continue;
      else ret += filter(WornItems[eqslots],
            (: (int)$1->GetArmorType() == A_WEAPON :));
       }
       return distinct_array(ret);
   }
   else if(!WornItems[eqslot]) return 0;
   else {
       object *ret;

       ret = filter(WornItems[eqslot], (: (int)$1->GetArmorType() == A_WEAPON :));
       if(sizeof(ret)) return ret[0];
       else return 0;
   }
    }

    /* varargs static int AddHealthPoints(int x, string limb, object agent)
     * int x - number of points being added, may be negative (required)
     * string limb - the limb to which health is being added (optional)
     * object agent - the living responsible for this damage
     *
     * defaults
     * limb defaults to 0
     *
     * description
     * if the value of limb is not zero, then "x" number of health points will
     * be added to limb "limb"
     * if he value is 0, then the overall health points will be modified
     *
     * returns the remaining number of health points for the limb in question
     * or for the overall health points
     */

    varargs static int AddHealthPoints(int x, string limb, mixed agent) {
   int y = 0;
   string agentname;

   //tc("gent: "+identify(agent),"blue");
   if(agent && stringp(agent)){
       agentname = agent;
       agent = 0;
   }
/*
   if( limb ) {
       if( !Limbs[limb] ) return -1;
       y = GetMaxHealthPoints(limb);
       if(y < 1) return y;
       if((Limbs[limb]["health"] += x) < 1) Limbs[limb]["health"] = 0;
       else if(Limbs[limb]["health"] > y)
      Limbs[limb]["health"] = y;
       return Limbs[limb]["health"];
   }
*/
   
       if((HealthPoints += x) < 1) HealthPoints = 0;
       else if(HealthPoints > (y = GetMaxHealthPoints())) HealthPoints = y;
       if( HealthPoints < 1 ) {
      if( !Dying ) {
          Dying = 1;
          Agent = agent;
          eventDie((Agent ? Agent : agentname));
      }
       }
       else {
      float h = percent(GetHealthPoints(), GetMaxHealthPoints());

      if( h < COLLAPSE_AT ) {
          eventCollapse();
      }
       }
       return HealthPoints;
    }

    varargs int GetHealthPoints(string limb) {
        return HealthPoints;
    }

    varargs int GetMaxHealthPoints(string limb) { return 0; }

    /* int AddMagicPoints(int x)
     * int x - the number of magic points being added, may be negative
     *
     * description
     * adds magic points to the body
     *
     * returns the remaining magic points
     */
/*
    int AddMagicPoints(int x) {
   int y;

   if((MagicPoints += x) < 1) MagicPoints = 0;
   else if(MagicPoints > (y = GetMaxMagicPoints())) MagicPoints = y;
   return MagicPoints;
    }

    int GetMagicPoints() { return MagicPoints; }

    int GetMaxMagicPoints() { return 0; }
*/


   


    /* int AddStaminaPoints(int x)
     * int x - number of stamina points being added
     *
     * description
     * adds "x" stamina points, can be negative
     *
     * returns the remaining number of stamina points
     */
/*
    int AddLead(string ammo,int number){
   if( !intp(number) ) error("Bad argument 2 to AddLead().\n");
   if( !stringp(ammo) ) error("Bad argument 1 to AddLead().\n");
   if( ammo == "gunshot_wounds" ) gunshot_wounds += number;
   if( ammo == "rifleshot_wounds" ) rifleshot_wounds += number;
   if( rifleshot_wounds + gunshot_wounds < 0 ) {
       gunshot_wounds = 0;
       rifleshot_wounds = 0;
   }
   return 1;
    }

    int GetLead(string ammo){
   int number;
   number = 0;
   if(!ammo || !stringp(ammo)) number = gunshot_wounds + rifleshot_wounds;
   if(!ammo || !stringp(ammo)) return number;
   if(ammo == "gunshot_wounds") return gunshot_wounds;
   if(ammo == "rifleshot_wounds") return rifleshot_wounds;
   return 0;
    }


    float AddStaminaPoints(mixed x) {
   float y;

   if( !intp(x) && !floatp(x) )
       error("Bad argument 1 to AddStaminaPoints().\n");
   if( intp(x) ) x = to_float(x);
   if((StaminaPoints += x) < 0.1) StaminaPoints = 0.0;
   else if(StaminaPoints > (y = GetMaxStaminaPoints())) StaminaPoints = y;
   return StaminaPoints;
    }

    int GetStaminaPoints() { return to_int(StaminaPoints); }

    float GetMaxStaminaPoints() {  return 0; }
*/

    int AddExperiencePoints(mixed x) {
   if( !intp(x)) error("Bad argument 1 to AddExperiencePoints().\n");
   if((ExperiencePoints += x) < 0) ExperiencePoints = 0;
   return ExperiencePoints;
    }

    int GetExperiencePoints() { return ExperiencePoints; }

    int AddQuestPoints(mixed x) {
   if( !intp(x)) error("Bad argument 1 to AddQuestPoints().\n");
   if((QuestPoints+= x) < 0) QuestPoints = 0;
   return QuestPoints;
    }

    int GetQuestPoints() { return QuestPoints; }
/*
    int AddMagicProtection(class MagicProtection cl) {
   if( ( !cl->absorb && !(cl->protect && cl->time) ) ||
     ( cl->hit && !functionp(cl->hit) ) ||
     ( cl->end && !functionp(cl->end) ) ||
     ( !cl->bits )
   ) {
       error("Illegal class setting passed to AddMagicProtection.\n");
       return 0;
   }
   cl->timestamp = time();
   Protection += ({ cl });
   return 1;
    }

    class MagicProtection array GetMagicProtection() { return Protection; }

    int RemoveMagicProtection(int i) {
   if( i > sizeof(Protection) - 1 ) return 0;
   if( Protection->end ) {
       if( !(functionp(Protection->end) & FP_OWNER_DESTED) ) {
      evaluate(Protection->end, this_object());
       }
   }
   Protection -= ({ Protection });
   return 1;
    }
*/
    // This is for creatures that do not use weapons.
    // I had to crank down unarmed combat for humanoids,
    // so if your npc's are, say, dumb animals, be sure
    // to include "SetMelee(1)" so they can fight
    //
//    int SetMelee(int i) { melee = i; return melee; }
int SetMelee(int i) {return 1;}

    int GetMelee() { return melee; }


    int GetDying() { return Dying; }

//    int SetSleeping(int x) { return (Sleeping = x); }

//    int GetSleeping() { return Sleeping; }

    int AddAlcohol(int x) { return (Alcohol += x); }

    int GetAlcohol() { return Alcohol; }

//    int AddCaffeine(int x) { return (Caffeine += x); }

//    int GetCaffeine() { return Caffeine; }

//    int AddDrink(int x) { return (Drink += x); }

//    int GetDrink() { return Drink; }

//    int AddFood(int x) { return (Food += x); }

//    int GetFood() { return Food; }

    int AddPoison(int x) {
   Poison += x;
   if( Poison < 1 ) {
       Poison = 0;
   }
   return Poison;
    }

    int GetPoison() { return Poison; }

    string GetResistance(int type) { return "none"; }

    string GetRace() { return 0; }

    string GetName() { return 0; }

    string GetCapName() { return 0; }

    int GetHeartRate() {
/*   int rate;

   rate = (GetAlcohol() - GetCaffeine());
   if( rate > 50 ) rate = 6;
   else if( rate > 25 ) rate = 5;
   else if( rate > 0 ) rate = 4;
   else if( rate > -25 ) rate = 3;
   else rate = 2;
   rate += HeartModifier;
   if( rate < 1 ) {
       rate = 1;
   }
   else if( rate > 10 ) {
       rate = 10;
   }
   return rate;
*/
  return 5;
    }

    int GetHealRate() {
/*
   int heal;

   heal = 1 - (GetPoison() / 5);
   heal += (GetDrink() + GetFood()) / 10;
   heal *= (1 + (GetSleeping() > 1) + (GetAlcohol() > 10));
   return heal;
*/
    int heal = RACES_D->GetRaceHealRate(GetRace());
    return heal;
    }

    string GetHealthShort() {
   string cl, sh;
   float h;

   if( !(sh = GetShort()) ) return 0;
   h = percent(GetHealthPoints(), GetMaxHealthPoints());
   if( this_object()->GetNoCondition() || h > 90.0 ) cl = "%^BOLD%^GREEN%^";
   else if( h > 75.0 ) cl = "%^GREEN%^";
   else if( h > 50.0 ) cl = "%^BOLD%^BLUE%^";
   else if( h > 35.0 ) cl = "%^BLUE%^";
   else if( h > 20.0 ) cl = "%^BOLD%^RED%^";
   else cl = "%^RED%^";
   return cl + capitalize(sh);
    }

    mixed SetProtect(function f) { return (Protect = f); }

    function GetProtect() { return Protect; }

    int GetHeartModifier() {
   return HeartModifier;
    }

    varargs int AddHeartModifier(int x, int t) {
   HeartModifier += x;
   if( t > 0 ) {
       call_out((: AddHeartModifier(-$(x)) :), t);
   }
   return HeartModifier;
    }

    int AddHP(int hp){
   AddHealthPoints(hp);
   return hp;
    }

    string GetAffectLong(){
   object dude;
   string ret;
   int alclevel;

   dude = this_object();
   alclevel = dude->GetAlcohol();
   ret = "";

   if(dude->GetSleeping() > 0) {
       ret += dude->GetName()+" is a

9
Dead Souls Support / combat...
« on: November 01, 2007, 02:24:10 PM »
hey all, this is my first post in the forums.  i hope you're all doing fine.

i've made some kinda minor revisions to the stock combat.c file (mostly just commenting out sections and changing a few words and numbers).

i basically want melee combat to behave the same as weapons combat, in terms of hitrate and such (so i just made the numbers for chance match up), though i am looking to reduce the damage later.  i really want to have pros/cons check against some armor class variable as opposed to the type + " defense" skill, but i left those in for now since i have no idea how to code that part yet.  i also want hitpoints to be done just as one number as opposed to limbs, although i left "targetlimb" in some places because i wasn't sure how to swap it out/how to change the body/race files yet.  it's hard working with just one file when it works in parallel with like 5 others...

so yea, tell me if you think this stuff would work, thanks!

Code: [Select]
/*    /lib/combat.c
 *    from the Dead Souls LPC Library
 *    combat events and data
 *    created by Descartes of Borg 950124
 *    Version: @(#) combat.c 1.40@(#)
 *    Last modified: 96/11/17
 */

#include <lib.h>
#include <rounds.h>
#include <config.h>
#include <daemons.h>
#include <position.h>
#include <damage_types.h>
#include <function.h>

inherit LIB_RACE;
inherit LIB_CLASSES;
inherit LIB_COMBATMSG;

private int Wimpy, Dead;
private string WimpyCommand;
private static int cParalyzed, tNextRound;
private static string TargetLimb, Party;
private static object CurrentEnemy;
private static function fParalyzed, fNextRound;
private static object *Hostiles, *Enemies, *SpecialTargets, *NonTargets;
private static object *PriorEnemies;

string GetName();
mixed GetProperty(string key);
string array AddChannel(mixed val);
string array RemoveChannel(mixed val);
int eventForce(mixed args);
int eventExecuteAttack(mixed target);
int eventWeaponRound(mixed target, mixed val);
void eventWeaponAttack(object target, object weapon, int num);
int eventMeleeRound(mixed target, function f);
void eventMeleeAttack(object target, string limb);
int eventMagicRound(mixed target, function f);
int eventWimpy(int i);

static void create() {
    race::create();
    classes::create();
    Hostiles = ({});
    Enemies = ({});
    NonTargets = ({});
    CurrentEnemy = SpecialTargets = 0;
    Party = 0;
    fParalyzed = 0;
    fNextRound = 0;
    cParalyzed = 0;
    tNextRound = ROUND_UNDEFINED;
    Wimpy = 0.20;
    WimpyCommand = "go out";
}

/*  *****************  /lib/combat.c data functions  *****************  */
varargs int GetMaxHealthPoints(string limb){
    return race::GetMaxHealthPoints(limb);
}

int GetDead(){
    return Dead;
}

int SetDead(int i){
    if(!i) Dead = 0;
    else Dead = 1;
    return Dead;
}

object array GetEnemies() {
    return Enemies;
}

int AddEnemy(object ob) {
    if( !ob || (member_array(ob, Enemies) != -1) ) {
return 0;
    }
    if( !living(ob) ) {
return 0;
    }
    Enemies += ({ ob });
    return 1;
}

int RemoveEnemy(object ob) {
    if( !ob || (member_array(ob, Enemies) == -1) ) {
return 0;
    }
    Enemies -= ({ ob });
    return 1;
}

object SetCurrentEnemy(object ob) {
    if( !ob ) {
return (CurrentEnemy = 0);
    }
    if( !living(ob) ) {
return CurrentEnemy;
    }
    if( member_array(ob, Enemies) == -1 ) {
AddEnemy(ob);
    }
    return (CurrentEnemy = ob);
}

static object ResetCurrentEnemy() {
    object array obs;

    obs = filter(GetEnemies(), (: $1 && environment() == environment($1) :));
    if( !sizeof(obs) ) {
return 0;
    }
    return SetCurrentEnemy(obs[random(sizeof(obs))]);
}

object GetCurrentEnemy() {
    return CurrentEnemy;
}

private static void SortEnemies() {
    if( !sizeof(Enemies = filter(Enemies, (: ($1 && living($1)) :))) ) {
Hostiles = ({});
CurrentEnemy = 0;
return;
    }
    Hostiles = (Hostiles & Enemies);
}

mixed *AddNonTargets(mixed val){
    if(!arrayp(val)) val = ({ val });
    foreach(object member in val){
if(member_array(member,NonTargets) == -1){
    if(base_name(this_object()) != base_name(member)) NonTargets += ({ member });
}
    }
    return NonTargets;
}

mixed *RemoveNonTargets(mixed val){
    if(!val) val = ({});
    if(!arrayp(val)) val = ({ val });
    if(!sizeof(val)){
NonTargets = ({});
return NonTargets;
    }
    foreach(object member in val){
if(member_array(member,NonTargets) != -1){
    NonTargets -= ({ member });
}
    }
    return NonTargets;
}

object *GetNonTargets(){
    return NonTargets;
}


int AddHostile(object ob) {
    if( !ob || (member_array(ob, Hostiles) != -1) ) {
return 0;
    }
    if( !living(ob) ) {
return 0;
    }
    Hostiles += ({ ob });
    return 1;
}

int RemoveHostile(object ob) {
    if( !ob || (member_array(ob, Hostiles) == -1) ) {
return 0;
    }
    Hostiles -= ({ ob });
    return 1;
}

object array GetHostiles() {
    return Hostiles;
}

object array GetSpecialTarget() {
    return SpecialTargets;
}

object array SetSpecialTarget(object *cibles) {
    if(cibles) SpecialTargets = cibles;
    return SpecialTargets;
}

varargs int SetParalyzed(int count, function f) {
    if(count < 1) {
count = cParalyzed = 0;
fParalyzed = 0;
    }
    else {
fParalyzed = f;
cParalyzed = count;
    }
    return count;
}

int GetParalyzed() { return cParalyzed; }

int eventQuell(){
    object *truced;
    truced = get_livings(environment(this_object()));
    if(sizeof(Enemies)) PriorEnemies = Enemies;
    Enemies = ({});
    AddNonTargets(truced);
    return 1;
}

int eventUnQuell(){
    object *truced;
    truced = GetNonTargets();
    if(sizeof(PriorEnemies)) Enemies += PriorEnemies;
    if(sizeof(truced)) RemoveNonTargets(truced);
    return 1;
}

string SetParty(string str) {
    if( file_name(previous_object()) != PARTY_D ) return Party;
    if( str ) AddChannel(str);
    else RemoveChannel(Party);
    return (Party = str);
}

string GetParty() {
    return Party;
}

varargs int SetAttack(mixed target, function callback, int type) {
    int i;
    string *voibs = ({ "kill", "target", "smite", "waste", "hit", "attack" });

    if( objectp(target) ) target = ({ target });
    if( target ) {
if( member_array(this_object(), target) != -1 ) return 0;
if(sizeof(NonTargets) && member_array(query_verb(),voibs) != -1){
    foreach(object individual in target){
if(member_array(individual,NonTargets) != -1){
    NonTargets -= ({ individual });
}
    }
}
else if(sizeof(NonTargets)){
    foreach(object individual in target){
if(member_array(individual,NonTargets) != -1) target -= ({ individual });
    }
    if(!sizeof(target)) return 0;
}

if( !GetCurrentEnemy() ) call_out((: eventExecuteAttack :), 0, target);
i = sizeof(target);
while(i--) if( AddEnemy(target[i]) ) AddHostile(target[i]);
if(!sizeof(SpecialTargets) ) SpecialTargets = target;
else {
    int spec_targ_here;
    foreach(object t in SpecialTargets){
if(t && present(t->GetKeyName(),environment(this_player()))) spec_targ_here = 1;
    }
    if(!spec_targ_here) SpecialTargets = target;
}
    }
    fNextRound = callback;
    tNextRound = (type || ROUND_UNDEFINED);
    return 1;
}

int GetLevel() {
    return classes::GetLevel();
}

int GetInCombat() {
    return sizeof(filter(GetEnemies(),
(: $1 && (environment($1) == environment()) :)));
}

int GetBaseStatLevel(string stat) {
    return race::GetBaseStatLevel(stat);
}

float SetWimpy(float wimpy) {
    return (Wimpy = wimpy);
}

float GetWimpy() {
    return Wimpy;
}

string SetWimpyCommand(string cmd) {
    return (WimpyCommand = cmd);
}

string GetWimpyCommand() {
    return WimpyCommand;
}

int GetMaxCarry() {
    return race::GetMaxCarry();
}

//int GetMagicChance(int val) {
//    val = GetStatLevel("intelligence")/2 + (3*val)/2;
//    return val + GetLuck();
//}

//int GetMagicResistance() {
//    int val = GetStatLevel("wisdom")/2 + (3*GetSkillLevel("magic defense"))/2;
//
//    return val + GetLuck();
//}

//int GetCombatChance(int val) {
//    val = val + random((val * GetMobility())/50);
//    val = (val/(3- visibility()) + GetLuck());
//    if( GetBlind() ) {
// return val/10;
//    }
//    else {
// return val;
//    }
//}

//int GetDefenseChance(int val) {
//    val = (val * GetMobility())/50;
//    val = (val/(3- visibility()) + (GetLuck()/2));
//    if( GetBlind() ) {
// return val/10;
//    }
//    else {
// return val;
//    }
//}

//int GetCombatBonus(int level) {
//    int diff = level - GetLevel();
//
//    if( diff >= 6 && diff < 16 ) {
// return 4;
//    }
//    else if( diff >= 1 && diff < 6 ) {
// return 3;
//    }
//    else if( diff >= -9 && diff < 1 ) {
// return 2;
//    }
//    else if( diff >= -20 && diff < -9 ) {
// return 1;
//    }
//    else {
// return 0;
//    }
//}

static int GetDamage(int power, string skill) {
    int x = GetSkillLevel(skill);

    if( power < 1 ) {
return 0;
    }
    else if( power > 100 ) {
power = 100;
    }
    if( x < 1 ) {
x = 1;
    }
    else if( x > 100 ) {
x = 100;
    }
    x = (x * (power/2 + random(power/2))/10);
    x += (GetLuck()/2) + GetStatLevel("strength")/8;
    if( x < 1 ) { // negative luck or cursed strength
return 1;
    }
    return x;
}

/*
int CanWeapon(object target, string type, int hands, int num) {
    string limb = target->GetRandomLimb(TargetLimb);
    int chance = (7*GetSkillLevel(type+" attack") +
      3*GetStatLevel("coordination"))/10;
    int div = 2;
    int x, y;

    if(hands > 1) { 
if(GetSkillLevel("multi-hand")) {
    chance = (chance/2) +
    (GetSkillLevel("multi-hand")/75)*(chance/2);
}
else { /* If you are really strong you can use multihand a bit */
    chance *= GetStatLevel("strength")/300;
    div += (hands-1);
}
    }
    if(num > 1) {
if(GetSkillLevel("multi-weapon")) {
    chance = (chance/2) +
    (GetSkillLevel("multi-weapon")/75)*(chance/2);
}   
else { /* If you are really coordinated you can use multiweap a bit */
    chance *= GetStatLevel("coordination")/300;
    div += (num-1);
}
    }
    chance = GetCombatChance(chance/div);
    x = random(chance);
    y = random(10);
    if( x <= y ) {
if( x > y/2 ) {
    TargetLimb = target->GetRandomLimb(0);
}
else {
    TargetLimb = 0;
}
    }
    else {
TargetLimb = limb;
    }
    return chance;
}
*/

int CanWeapon(object target, string type, int hands, int num) {
    int chance = (7*GetSkillLevel(type) + 3*GetStatLevel("dexterity"))/10;
    chance = GetCombatChance(chance/2);
    return chance;
}

/*
int CanMelee(object target) {
    if(!this_object()->GetMelee()){

string limb = target->GetRandomLimb(TargetLimb);
int chance = ( 6*GetSkillLevel("melee attack") +
  2*GetStatLevel("coordination") )/20;
int y = random(10);
int x;

chance = GetCombatChance(chance/3);
x = random(chance);
if( x <= y ) {
    if( x > y/2 ) {
TargetLimb = target->GetRandomLimb(0);
    }
    else {
TargetLimb = 0;
    }
}
else {
    TargetLimb = limb;
}
return chance;
    }
    else {
string limb = target->GetRandomLimb(TargetLimb);
int chance = ( 7*GetSkillLevel("melee attack") +
  3*GetStatLevel("coordination") )/10;
int y = random(10);
int x;

chance = GetCombatChance(chance/2);
x = random(chance);
if( x <= y ) {
    if( x > y/2 ) {
TargetLimb = target->GetRandomLimb(0);
    }
    else {
TargetLimb = 0;
    }
}
else {
    TargetLimb = limb;
}
return chance;
    }
}
*/

int CanMelee(object target) {
    int chance = (7*GetSkillLevel("melee") + 3*GetStatLevel("dexterity"))/10;
    chance = GetCombatChance(chance/2);
    return chance;
}

static int Destruct() {
    if( GetParty() ) PARTY_D->eventLeaveParty(this_object());
    return 1;
}

/*  *****************   /lib/combat.c events  ***************** */

varargs int eventDie(mixed agent) {
    object ob;
    int x;

    if(Dead) return 1;
    Dead = 1;

    x = race::eventDie(agent);
    if( x != 1 ) {
return x;
    }
    foreach(ob in GetEnemies()) {
if( ob ) {
    ob->eventEnemyDied(this_object());
}
    }
    environment()->eventLivingDied(this_object(), agent);
    Enemies = ({});
    flush_messages();
    return 1;
}

int eventExecuteAttack(mixed target) {
    object array weapons;
    function f = fNextRound;
    int type = tNextRound;
    int position = GetPosition();

    if(Dead) return 1;
    if(target->GetDead()) return 1;

    fNextRound = 0;
    tNextRound = ROUND_UNDEFINED;
/*
    if( position == POSITION_LYING || position == POSITION_SITTING &&
      RACES_D->GetLimblessCombatRace(this_object()->GetRace()) != 1) {
if(this_object()->CanFly()) {
    this_object()->eventFly();
}
else if(RACES_D->GetLimblessCombatRace(GetRace()) != 1){
    eventPrint("You can't fight unless you are up!");
    return 0;
}
    }
    if(this_object()->GetPacifist()) {
tell_object(this_object(),"As a pacifist, you choose not to fight.");
return 0;
    }
*/
    if( arrayp(target) ) {
if( !f || (functionp(f) & FP_OWNER_DESTED) ) {
    return 0; /* built in only handles 1 targ */
}
target = filter(target, function(object ob) {
      if( !ob ) {
  return 0;
      }
      if( !ob->eventPreAttack(this_object()) ) {
  return 0;
      }
      return 1;
    });
  if( !sizeof(target) ) {
      return 0;
  }
      }
else if( !target->eventPreAttack(this_object()) ) {
    return 0;
}
// this_object()->AddStaminaPoints(-1);
switch(type) {
case ROUND_UNDEFINED:
    if( functionp(f) && !(functionp(f) & FP_OWNER_DESTED) ) {
return evaluate(f, target);
    }
    if( sizeof(weapons = GetWielded()) ) {
return eventWeaponRound(target, weapons);
    }
    else {
return eventMeleeRound(target, 0);
    }

case ROUND_MAGIC:
    return eventMagicRound(target, f);

case ROUND_MELEE:
    return eventMeleeRound(target, functionp(f) ? f : 0);

case ROUND_WEAPON:
    return eventWeaponRound(target, functionp(f) ? f : GetWielded());

case ROUND_OTHER:
    if( functionp(f) && !(functionp(f) & FP_OWNER_DESTED) ) {
return evaluate(f);
    }
    else {
return 0;
    }

default: return 0;
}
return 0;
    }

    int eventWeaponRound(mixed target, mixed val) {
object array weapons = 0;
function f = 0;

if(Dead) return 1;
if(target->GetDead()) return 1;

if( arrayp(val) ) {
    weapons = val;
}
else if( functionp(val) && !(functionp(val) & FP_OWNER_DESTED) ) {
    f = val;
}
else {
    return 0;
}
if( f ) {
    evaluate(f, target);
}
else {
    int count = sizeof(weapons);

    foreach(object weapon in weapons) {
if( !target ) {
    break;
}
eventWeaponAttack(target, weapon, count);
    }
}
return target->GetDying();
    }

    void eventWeaponAttack(object target, object weapon, int num){
        string weapon_type = weapon->GetWeaponType();
        int hands = weapon->GetHands();
        int level = target->GetLevel();
        int bonus = GetCombatBonus(level);
        int power, pro, con;

if(Dead) return;
if(target->GetDead()) return;

if( target->GetDying() ) {
    return;
}
pro = CanWeapon(target, weapon_type, hands, num);
power = random(pro);
con = target->GetDefenseChance(target->GetSkillLevel(weapon_type + " defense"));
if( !TargetLimb ) { // If the thing stood still, I still missed
    eventTrainSkill(weapon_type, pro, 0, 0, bonus);
/*     if( hands > 1 ) {
eventTrainSkill("multi-hand", pro, 0, 0, bonus);
    }
    if( num > 1 ) {
eventTrainSkill("multi-weapon", pro, 0, 0, bonus);
    }
*/     SendWeaponMessages(target, -2, weapon, TargetLimb);
}
else if( !target->eventReceiveAttack(power, weapon_type, this_object()) ) {
    // Target avoided the attack
    eventTrainSkill(weapon_type, pro, con, 0, bonus);
/*     if( hands > 1 ) {
eventTrainSkill("multi-hand", pro, con, 0, bonus);
    }
    if( num > 1 ) {
eventTrainSkill("multi-weapon", pro, con, 0, bonus);
    }
*/     SendWeaponMessages(target, -1, weapon, TargetLimb);
}
else { // I hit, but how hard did I hit?
    int damage_type, damage, weapon_damage, actual_damage, encumbrance;
    encumbrance = this_object()->GetEncumbrance();
    if(encumbrance > 20){
tell_object(this_object(),"You struggle to fight while carrying stuff.");
    }
    eventTrainSkill(weapon_type, pro*2, con, 1, bonus);
    damage_type = weapon->GetDamageType();
    damage = (weapon->eventStrike(target) * pro)/(GetLevel()*2);
    damage = GetDamage(damage, weapon_type);
    damage -= encumbrance;
    if(damage < 0) damage = 0;
    actual_damage = target->eventReceiveDamage(this_object(), damage_type,
      damage, 0, TargetLimb);
    if( actual_damage < 0 ) {
actual_damage = 0;
    }
    weapon_damage = damage - actual_damage;
    if( weapon_damage > 0 ) {
weapon->eventReceiveDamage(this_object(), BLUNT, weapon_damage,
  0, TargetLimb);
    }
    if( !target->GetDying() ) {
SendWeaponMessages(target, actual_damage, weapon, TargetLimb);
    }
    else {
eventPrint(possessive_noun(target) + " death is now on your "
  "head.");
target->eventPrint(GetName() + " is your murderer.");
environment()->eventPrint(possessive_noun(target) +
  " death is now on " +
  possessive_noun(this_object())
  + " head.", ({ this_object(), target }));
    }
}
    }

/*
    int eventMeleeRound(mixed target, function f) {
string array limbs = GetLimbs() - ({ GetTorso() });
int count = sizeof(limbs);
int attacks;

if(Dead) return 1;
if(target->GetDead()) return 1;

if( count < 2 ) {
    if(RACES_D->GetLimblessCombatRace(this_object()->GetRace())){
limbs = GetLimbs();
count = sizeof(limbs);
    }
    else return 0;
}
if( !f || (functionp(f) & FP_OWNER_DESTED) ) {
    attacks = 1 + random(GetSkillLevel("melee attack"))/30;
    while( attacks-- ) {
if( target->GetDying() ) {
    break;
}
eventMeleeAttack(target, limbs[random(count)]);
    }
}
else {
    evaluate(f, target, limbs[random(count)]);
}
return target->GetDying();
    }
*/

    int eventMeleeRound(mixed target, function f) {
        int attacks;

        if(Dead) return 1;
        if(target->GetDead()) return 1;

        if ( !f || (functionp(f) & FP_OWNER_DESTED) ) {
            attacks = 1 + random(GetSkillLevel("melee"))/30;
            while( attacks-- ) {
                if( target->GetDying() ) {
                    break;
                }
                eventMeleeAttack(target, limbs[random(count)]);
            }
        }
        else {
            evaluate(f, target, limbs[random(count)]);
        }
        return target->GetDying();
    }

    void eventMeleeAttack(object target, string limb) {
int pro, con;
int chance;

if( target->GetDead() || Dead || target->GetDying() ) {
    return;
}
/*
if(limb == "head" && this_object()->GetCanBite()) {
    eventBite(target);
    return;
}
*/
pro = CanMelee(target);
con = target->GetDefenseChance(target->GetSkillLevel("melee defense"));
chance = random(pro);
if( !TargetLimb ) { // I *really* missed
    SendMeleeMessages(target, -2);
    eventTrainSkill("melee attack", pro, 0, 0,
      GetCombatBonus(target->GetLevel()));
}
else if( !target->eventReceiveAttack(chance, "melee", this_object()) ) {
    // Enemy dodged my attack
    SendMeleeMessages(target, -1);
    eventTrainSkill("melee", pro, con, 0,
      GetCombatBonus(target->GetLevel()));
}
else {
    int x, encumbrance;
    encumbrance = this_object()->GetEncumbrance();
    if(encumbrance > 20){
tell_object(this_object(),"You struggle to fight while carrying stuff.");
    }
    // I hit, how hard?
    eventTrainSkill("melee", pro, con, 1,
      GetCombatBonus(target->GetLevel()));
    if(this_object()->GetMelee()) x = GetDamage(3*chance/4, "melee");
    else x = GetDamage(4*chance/20, "melee");
    x -= encumbrance;
    if(x < 0) x = 0;
    x = target->eventReceiveDamage(this_object(), BLUNT, x, 0,
      TargetLimb);
    if( !target->GetDying() ) {
SendMeleeMessages(target, (x > 0) ? x : 0, TargetLimb);
    }
    else {
eventPrint(possessive_noun(target) + " death is now "
  "on your head.");
target->eventPrint(GetName() + " is your murderer.");
environment()->eventPrint(possessive_noun(target) +
  " death is now on " +
  possessive_noun(this_object()) +
  " head.", ({ this_object(), target }));
    }
            AddExperiencePoints(x / 2);
}
    }
/*
    int eventMagicRound(mixed target, function f) {
if(target->GetDead()) return 1;
evaluate(f, target);
return target->GetDying();
    }

    mixed eventBite(object target) {
int pro = CanMelee(target);
int con = target->GetDefenseChance(target->GetSkillLevel("melee defense"));
int x = random(pro);

if(target->GetDead()) return 1;

if( environment() != environment(target) ) {
    eventPrint(target->GetName() + " has gone away.");
    return 1;
}
if( TargetLimb ) {
    if( target->eventReceiveAttack(x, "melee", this_object()) ) {
x = GetDamage(pro*2, "melee attack");
x = target->eventReceiveDamage(this_object(), BITE, x, 0,
  TargetLimb);
if( x < 1 ) {
    target->eventPrint(possessive_noun(this_object()) + " bite "
      "is nothing more than a pinch.");
    eventPrint("Your bite is nothing more than a pinch.");
    environment()->eventPrint(possessive_noun(this_object()) +
      " bite is nothing more than a "
      "pinch.",
      ({ target, this_object() }));
}
else {
    target->eventPrint(GetName() + " bites you in the " +
      TargetLimb + "!");
    eventPrint("You bite " + target->GetName() + " in the " +
      TargetLimb + "!");
    environment()->eventPrint(GetName() + " bites " +
      target->GetName() + " in the " +
      TargetLimb + "!",
      ({ target, this_object() }));
}
eventTrainSkill("melee attack", pro, con, 1,
  GetCombatBonus(target->GetLevel()));
    }
    else {
target->eventPrint("You avoid " + possessive_noun(this_object()) +
  " bite.");
eventPrint(target->GetName() + " avoids your bite.");
environment()->eventPrint(target->GetName() + " avoids " +
  possessive_noun(this_object()) +
  " bite.",
  ({ this_object(), target }));
eventTrainSkill("melee attack", pro, con, 0,
  GetCombatBonus(target->GetLevel()));
    }
}
else {
    eventPrint("You flounder about like a buffoon.");
    environment()->eventPrint(GetName() + " flounders about like a "
      "buffoon.", this_object());
}
return 1;
    }
*/
    int eventPreAttack(object agent) {
if( agent == this_object() ) {
    return 0;
}
if( environment()->GetProperty("no attack") ) {
    return 0;
}
if( GetDying() ) {
    return 0;
}
if( playerp(this_object()) && playerp(agent) && !PLAYER_KILL) {
    if( !environment()->CanAttack( agent, this_object() ) ) {
return 0;
    }
}
if( AddEnemy(agent) ) {
    AddHostile(agent);
}
return 1;
    }

    varargs int eventReceiveAttack(int speed, string def, object agent) {
int x, pro, level, bonus;

if(Dead) return 0;

if( !agent ) {
    agent = previous_object();
}
if( !living(agent) ) {
    level = 1;
    bonus = 1;
}
else {
    level = agent->GetLevel();
    bonus = GetCombatBonus(level);
}
if( AddEnemy(agent) ) {
    AddHostile(agent);
}
/* if( def == "magic" ) {
    pro = GetMagicResistance();
    if( (x = random(pro)) > speed ) {
eventTrainSkill("magic defense", pro, speed, 1, bonus);
return 0;
    }
    else {
eventTrainSkill("magic defense", pro, speed, 0, bonus);
return 1;
    }
}
*/
// else {
    pro = GetDefenseChance(GetSkillLevel(def + " defense"));
    x = random(pro = pro/2);
    if( x > speed ) {
eventTrainSkill(def + " defense", pro, speed, 1, bonus);
return 0;
    }
    else {
eventTrainSkill(def + " defense", pro, speed, 0, bonus);
return 1;
    }
// }
    }

    void eventKillEnemy(object ob) {
int level;

if( !ob ) return;
level = ob->GetLevel();
if(ob->GetCustomXP()) this_object()->AddExperiencePoints(ob->GetCustomXP());
else this_object()->AddExperiencePoints(level * 80);
if( member_array(ob, GetHostiles()) == -1 ) {
    int x;

    eventTrainSkill("murder", GetLevel(), level, 1,GetCombatBonus(level));
    x = (int)ob->GetMorality();
    if( x > 0 ) x = -x;
    else if( GetMorality() > 200 ) x = 100;
    else x = 0;
    eventMoralAct(x);
}
    }

    void eventDestroyEnemy(object ob) {
int level;

if( !ob ) return;
level = ob->GetLevel();
if(ob->GetCustomXP()) this_object()->AddExperiencePoints(ob->GetCustomXP());
else this_object()->AddExperiencePoints(level * 80);
eventTrainSkill("faith", GetLevel(), level, 1, GetCombatBonus(level));
    }

    void eventEnemyDied(object ob) {
if( !ob ) return;
Enemies -= ({ ob });
Hostiles -= ({ ob });
if(!sizeof(SpecialTargets) || (!sizeof(Enemies) || !sizeof(Hostiles)))
    NonTargets = ({});
    }

    varargs int eventReceiveDamage(mixed agent, int type, int x, int internal,
      mixed limbs) {
int hp,encumbrance;

//tc("ok.","green");

encumbrance = this_object()->GetEncumbrance();

if(Dead) return 0;
if(encumbrance > 200){
    if(GetInCombat()) tell_object(this_object(),"You try to dodge while weighed down.");
}
x = race::eventReceiveDamage(agent, type, x, internal, limbs);
if( !Wimpy ) return x;
if( (hp = GetHealthPoints()) < 1 ) return x;
if( Wimpy < percent(hp, GetMaxHealthPoints()) )
    return x;
call_out((: eventWimpy :), 0);
return x;
    }
/*
    mixed eventTurn(object who) {
int defense;

if( !GetUndead() ) {
    return 0;
}
if( GetProperty("no turn") ) {
    if( !who ) {
return 0;
    }
    else {
int x = GetProperty("no turn");

environment(who)->eventPrint("The power of the undead "
  "turns on " + who->GetName() +
  ".", who);
who->eventPrint("The power of the undead turns on you.");
if( x > random(100) + 1 ) {
    who->eventDie(this_object());
}
else {
    who->eventReceiveDamage(this_object(), MAGIC, random(50), 1);
}
return 0;
    }
}
if( !who ) {
    race::eventTurn(who);
    return 1;
}
defense = GetMagicResistance();
if( who->GetSkillLevel("faith") < defense ) {
    who->eventPrint("You writhe in pain.");
    environment(who)->eventPrint(who->GetName() + " writhes in pain.",
      who);
    who->eventReceiveDamage(this_object(), MAGIC, random(defense), 1);
    eventTrainSkill("magic defense", defense, who->GetSkillLevel("faith"),
      1, GetCombatBonus(who->GetLevel()));
    return 0;
}
race::eventTurn(who);
return 1;
    }
*/
    int eventWimpy(int i) {
object env = environment();
string dir, cmd;

if( !env || !GetInCombat() ) {
    if(!i) return 0;
}
cmd = WimpyCommand || "go out";
if( (sscanf(cmd, "go %s", dir) && !((string)env->GetExit(dir))) ||
  (sscanf(cmd, "enter %s", dir) && !((string)env->GetEnter(dir))) ) {
    string *tmp;

    tmp = filter((string *)environment()->GetExits(),
      (: !((string)environment()->GetDoor($1)) :));
    if( !sizeof(tmp) ) {
tmp = filter((string *)environment()->GetEnters(),
  (: !((string)environment()->GetDoor($1)) :));
if( !sizeof(tmp) ) {
    eventPrint("You need to escape, but you have nowhere to go!");
    return 0;
}
cmd = "enter " + tmp[random(sizeof(tmp))];
    }
    else cmd = "go " + tmp[random(sizeof(tmp))];
}
return eventForce(cmd);
    }

    static void heart_beat() {
race::heart_beat();
if( GetSleeping() || GetDying() ) {
    return;
}
if( cParalyzed > 0 ) {
    cParalyzed--;
    if( cParalyzed < 1 ) {
function f;

f = fParalyzed;
fParalyzed = 0;
if( functionp(f) && !(functionp(f) & FP_OWNER_DESTED) ) {
    evaluate(f);
}
else {
    eventPrint("You can move again.");
}
    }
    return;
}
if( sizeof(Enemies) ) {
    SortEnemies();
    foreach(object dude in Enemies){
if(member_array(dude,NonTargets) != -1){
    RemoveEnemy(dude);
    RemoveHostile(dude);
}
    }
}
if( sizeof(Enemies) ) {
    object ob;

    SortEnemies();

    if( SpecialTargets ) {
foreach(object target in SpecialTargets) {

    if( objectp(SetCurrentEnemy(target)) ) {
break;
    }
}
eventExecuteAttack(SpecialTargets);
SpecialTargets = 0;
    }
    else if( ob = ResetCurrentEnemy() ) {
eventExecuteAttack(ob);
    }
}
else if( tNextRound != ROUND_UNDEFINED && functionp(fNextRound) ) {
    function f;

    f = fNextRound;
    tNextRound = ROUND_UNDEFINED;
    evaluate(f);
}
    }

ps, i see some tabs in there now, so it might make spacing a little wonky... i'll replace those when i actually place them into ed.  i havn't actually tested this yet as i wasn't sure if i was going in the right direction, and also i'm at work currently... so yea.

thanks for taking the time to read this over!  and feedback is definitely appreciated.

Pages: [1]