tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
/*
// Program: /std/living/attack.c
// Written mostly by Buddha@TMI
// Originally based on the attack.c found in the mudlib.n,
// many structural similarites may remain.
// It is is a part of the TMI distribution mudlib.
// Please retain this header if you use this file.
// Much work was done in December of 1991.
// revised 2-16-92 by Buddha
// revised again 3-1-92 by Buddha
// Rewritten to remove the LOC, and to update it for mudlib 0.9, by
// Mobydick@TMI-2, 9-21-92
// Added some stuff to make monsters remember and attack old opponents.
// Mobydick, 2-3-93.
// Added receive_damage() and receive_healing() systems, Watcher 3-27-93
*/
 

// Basic structure:
// The function kill_ob is used to initiate combat. The kill command calls
// it in any monster or player entering combat, as do the combat spells and
// other nastiness. It also turns on a monster's heartbeat if that is
// necessary.
// The heart_beat calls the continue_attack function. This function checks
// to see if the monster is dead and if so, starts the death sequence. It
// then checks the list of current opponents and removes any that are dead
// or otherwise out of the MUD. Opponents that have left the room are moved
// onto the "will_kill" list. It then checks to see if spellcasting or
// other activity has blocked the attack. If not, it calls execute_attack
// which does the actual attack against the first attacker on the list.
// The functions continue_attack and execute_attack are defined seperately
// in each body.

#include <config.h>
#include <stats.h>
#include <mudlib.h>

inherit SECURE_OBJECT ;
 
// Prototypes for things that come in through the body object.

varargs mixed set(string prop, mixed arg, mixed security) ;
static object *attackers, target, *will_attack; // wombled by buddha
static int any_attack ;
mixed link_data(string what);
 
static string qs ;
private static int heal_time ;

// These variables are used in execute_attack() but are declared here to get
// around the limit on number of variables declared in the function. Kludge.

static string *vb, *vb2 ;
static int dmin, dmax, damage ;
static string weapontype ;
static int skill_improve_prob ;

void run_away();
int kill_ob (object victim) ;
void set_verbs(string *verbs) ;
void set_verbs2 (string *verbs) ;
string *get_verb() ;
void cease_all_attacks();
void continue_attack() ;

// This function handles the damage calls from battle. It only accepts
// positive damage calls. receive_healing() should be used for healing.
 
int receive_damage(int damage) {
   int dam;

   set ("last_attacker", previous_object()) ;
   if(damage <= 0 || link_data("dead") || query("hit_points") < 0 ||
      query("linkdead"))  return 0;
 
/*
This stuff is commented out because damage may come from non-living
objects or from spell commands - it's hard to know for sure what
object is the one that you want to attack.

   if(!attackers || member_array(this_player(), attackers) == -1)
      kill_ob(this_player());

*/
 
   dam = query("hit_points") - damage;
   if(dam < 0)  dam = -1;
 
   set("hit_points", dam);
 
return 1; }
 
// This function handles the healing calls from spells. It only accepts
// positive healing calls.  receive_damage() should be used for damage.
 
int receive_healing(int healing) {
   int heal;
 
   if(healing <= 0 || link_data("dead") || query("hit_points") < 0)
	return 0;

   heal = query("hit_points") + healing ;
   if(heal > query("max_hp"))  heal = query("max_hp");
 
   set("hit_points", heal);

return 1; }
 

// This function updates the object's AC. It got moved out of the
// player object so monsters could have it too.

int calc_armor_class() {

        mapping armor ;
        int ac ;
        string *types ;
        int i ;

        armor = query("armor") ;
        if (!armor) {
//  The dude is butt-naked.
                set ("armor_class", 0) ;
                return 0 ;
        }
        ac = 0 ;
        types = keys(armor) ;
        for (i=0;i<sizeof(types);i++) {
                ac = ac + armor[types[i]] ;
        }
        set ("armor_class", ac) ;
        return ac ;
}
// This function is used to prevent a player from attacking for a time.
// Called by the wield command, the various spells, other places. Anything
// a players does that should interfere with his combat should call this.

void block_attack (int t) {

	int i ;

// If we're not in combat, then don't bother.
	if (!any_attack) return ;
#ifdef BLOCK_ATTACK
	i = query("stop_attack") ;
	set ("stop_attack",i+t/2) ;
#endif
}

// This is called in the heart_beat to decrease the blocking time.

void unblock_attack() {

	int i ;

	i = query("stop_attack")-1 ;
	if (i>-1) set ("stop_attack",i) ;
}

// This function returns 1 if the player has stop_attack set and 0 if not.
// It's probably a pretty stupid thing to use, since you should just query
// stop_attack directly, but it's here if you want it.

int player_busy() {
	return query("stop_attack") ;
}

// This function is used to initialize various values.

void init_attack() {
   attackers = ({});
}

// This function returns the object at the top of the attackers list.

object query_attacker() {
	if(!attackers || !sizeof(attackers))  return 0;
	return attackers[0] ;
}

// Remove dead or nonexisting objects out of the list of attackers.
// Return true if there is still an attack going.

/*
// This is the 'kill' command. If the victim is not attacked yet,
// then it is entered first into the list of victims. If it is already
// in the list, then it is moved to the first entry.
*/
int kill_ob (object victim) {
   int i;
 
   if(query("linkdead"))  return 0;

#ifdef NO_PKILL
    if (userp(this_object()) && userp(victim)) {
        if (query("no_attack") || victim->query("no_attack"))
            return 2;
    }
// no_attack for users added by Blue, 941022.
#endif
 
   if (!attackers) {
	init_attack() ;
	attackers = ({ victim }) + attackers;
	any_attack = 1;
	set_heart_beat(1) ;
      victim->kill_ob(this_object());
      return 1;
    }
 
   i = member_array(victim, attackers);
 
   if (i > -1) {
         return 0;
    }
   attackers = ({ victim }) + attackers;
   any_attack = 1;
   victim->kill_ob(this_object());
	set_heart_beat(1) ;
   return 1;
}

// This is a default heart_beat for living objects. There's a player heart_beat
// in user.c and a monster heart_beat in monster.c, both of which should
// override this one.

void heart_beat() {
	unblock_attack() ;
	continue_attack() ;
}

// Continue_attack is called from heart_beat in monster.c and user.c.
// here is where we can try to see if we're dead or in combat.

// Call this to erase the list of opponents to attack. This will NOT stop
// them from attacking you again...  ;)

void cease_all_attacks() {
   attackers = ({});
   any_attack = 0;
}

// Call this function to remove a specific user from the attack array.
 
int remove_attacker(object obj) {
   if(member_array(obj, attackers) != -1)  attackers -= ({ obj });
return 1; }
 
// This function returns the current target if there is one. The "current
// target" could be in another room, or dead, and not cleaned out of the
// list yet, so be reasonably careful with this.

object query_current_attacker() {
   if(sizeof(attackers) == 0)
      return 0;
   else
      return attackers[0];
}

// This function returns the whole attackers list. Same caveat as above.

object *query_attackers() {
	if (sizeof(attackers)==0) {
		return 0 ;
	} else {
		return attackers ;
	}
}


// This lets a wimpy player or monster run away. Buddha got this part
// working for the case of rooms with no exits. (Bad sign for the wimp.)


void run_away() {

	int wimpy ;
	string direction ;
	mapping womble ;

   womble = environment(this_object())->query("exits") ;
   if (!womble) return;
   direction = this_player()->query("wimpydir") ;
   if (!direction || !womble[direction]) {
   	direction = keys(womble)[random(sizeof(womble))] ;
   }
   write ("You flee to the "+direction+"!\n") ;
   this_player()->force_me("go "+direction) ;
   return ;
}

// This function restores spell points and hit points to the player and
// deals with his blood-alcohol level.
// Drunkenness is handled as follows: 0 indicates sobriety. Positive
// numbers indicate drunkenness, and diminish over time. When the player
// reaches drunkenness of 1, we then set his drunkenness to -6, where
// the negative number means hangover rather than drunkenness, and we
// begin counting up until we reach 0, at which time he's sober again.

void heal_up() {

	int hp, sp, maxh, maxs ;
	int time, dr, rate ;

// If he's a ghost we want to skip this entirely.
	if (query("ghost")) return ;
	heal_time = heal_time + 1 ;
	time = query("time_to_heal") ;
// If the healing rate wasn't set, then it's one hp/sp each 10 heartbeats.
	if (time==0) time = 10 ;
// Check to see if it's time to improve hits and spells.
	if (heal_time>time) {
		hp = query("hit_points") ;
		sp = query("spell_points") ;
		maxh = query("max_hp") ;
		maxs = query("max_sp") ;
		heal_time = 0 ;
// The drunkenness comes commented out. If you add the drunkenness stuff,
// put this back in.
/*
		dr = query("drunk") ;
		switch (dr) {
			case -1 : { write ("Your headache clears up.\n") ; break; } 
			case 1 : { write ("Suddenly you have a massive headache.\n") ; break ; }
			case 6 : { write ("Your head is clearing.\n") ; break ;}
			case 11 : { write ("You feel drunk.\n") ; break ; }
			case 16 : { write ("The room stops spinning.\n") ; break ; }
			case 21 : { write ("You can see straight again.\n") ; break ; }
		}
// If the player's drunk is 1, we send him into hangover land.
		if (dr==1) dr=-6 ;
// Dry him out, or fix his hangover, as needed.
		if (dr>0) set ("drunk", dr-1) ;
		if (dr<0) set ("drunk", dr+1) ;
*/
		if (hp==maxh && sp==maxs) return ;
// If drunkenness, put this line back in, and have sp and hp increase by
// rate instead of by 1.
// You could also put rate in but have it affected by things other than
// alcohol, perhaps by food, by rest, or by magic spells.

// Eodon noticed that being drunken won't do any good
// since you'll het dr = -6 and get -6/5+1 = 0 for healing
// Leto 02/27/95
//		rate = dr/5+1 ;
		if (hp<maxh) {
			set ("hit_points", hp+1) ;
		} else {
			set("hit_points", maxh) ;
		}
		if (sp<maxs) {
			set ("spell_points", sp+1) ;
		} else {
			set ("spell_points", maxs) ;
		}
	}
}

// The set_verbs function stores the list of verbs to be used when a player
// or monster makes an attack, and conjugates the verbs by adding an "s" to
// the end of each. You can use set_verbs2, below, to override this
// conjugation if you need to.

void set_verbs(string *verbs) {

        int i ;
        string w1, w2 ;

        vb = verbs ;
        vb2 = allocate(sizeof(vb)) ;
        for (i=0;i<sizeof(verbs);i++) {
                if (sscanf(verbs[i],"%s %s",w1,w2)==2) {
                        vb2[i]=w1+"s "+w2 ;
                } else {
                        vb2[i]=verbs[i]+"s" ;
                }
        }
}

// This function is used to set the conjugated forms of the verbs. Use
// this when one of the attack verbs is irregular: there are some monster
// examples that do it.

void set_verbs2 (string *verbs) {
        vb2 = verbs ;
}

// The get_verb function returns a random verb from the list of verbs.
// It returns bboth forms of the verb in a 2-element array.

string *get_verb() {

        int i ;

        i = random(sizeof(vb)) ;
        return ({ vb[i], vb2[i] }) ;
}