empiremud/cnf/
empiremud/doc/
empiremud/lib/boards/
empiremud/lib/etc/
empiremud/lib/misc/
empiremud/lib/plralias/F-J/
empiremud/lib/plralias/K-O/
empiremud/lib/plralias/P-T/
empiremud/lib/plralias/U-Z/
empiremud/lib/plrobjs/
empiremud/lib/plrobjs/F-J/
empiremud/lib/plrobjs/K-O/
empiremud/lib/plrobjs/P-T/
empiremud/lib/plrobjs/U-Z/
empiremud/lib/world/
empiremud/lib/world/mob/
empiremud/lib/world/obj/
empiremud/log/
/* ************************************************************************
*   File: fight.c                                        EmpireMUD AD 1.0 *
*  Usage: Combat system                                                   *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Code base by Paul Clarke.  EmpireMUD Project, a tbgMUD Production.     *
*  Based upon CircleMUD 3.0, beta patch level 17, by Jeremy Elson.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "handler.h"
#include "interpreter.h"
#include "db.h"
#include "skills.h"
#include "vnums.h"
#include "empire.h"


/* Structures */
Creature combat_list = NULL;	/* head of l-list of fighting chars */
Creature next_combat_list = NULL;

/* External structures */
extern struct message_list fight_messages[MAX_MESSAGES];
extern int rev_dir[];

/* External procedures */
extern char *fread_action(FILE * fl, int nr);
ACMD(do_flee);


/* Weapon attack texts */
struct attack_hit_type attack_hit_text[] = {
	{ "hit",		"hits"		},	/* 0 */
	{ "slash",		"slashes"	},
	{ "slice",		"slices"	},
	{ "jab",		"jabs"		},
	{ "stab",		"stabs"		},
	{ "pound",		"pounds"	},	/* 5 */
	{ "hammer",		"hammers"	},
	{ "whip",		"whips"		},
	{ "jab",		"jabs"		},
	{ "bite",		"bites"		},
	{ "claw",		"claws"		},	/* 10 */
	{ "kick",		"kicks"		},
	{ "burn",		"burns"		},
	{ "claw",		"claws"		},
	{ "slash",		"slashes"	},
	{ "hit",		"hits"		}
	};

#define IS_WEAPON(type) (((type) >= TYPE_RESERVED) && ((type) < TYPE_SUFFERING))


/* The Fight related routines */


/*
 * can_fight()
 * Controls player-killing.  It sends its own message, so use it
 * appropriately.  Also, it stops people from fighting, so they
 * aren't spammed.
 */
bool can_fight(Creature ch, Creature victim) {
	extern struct time_info_data *real_time_passed(time_t t2, time_t t1);

	struct empire_political_data *emp_pol;
	extern bitvector_t pk_ok;
	struct time_info_data playing_time, playing_time2;

	if (!ch || !victim) {
		syslog(0, TRUE, "SYSERR: can_fight() called without ch or victim");
		if (ch && FIGHTING(ch))
			stop_fighting(ch);
		return FALSE;
		}

	if (ch == victim)
		return TRUE;

	/* charmies don't attack people */
	if (AFF_FLAGGED(ch, AFF_CHARM) && !IS_NPC(victim))
		return FALSE;

	/* Already fighting */
	if (FIGHTING(victim) == ch)
		return TRUE;

	if (AFF_FLAGGED(victim, AFF_NO_ATTACK) || AFF_FLAGGED(ch, AFF_NO_ATTACK))
		return FALSE;

	if (DSC_FLAGGED(victim, DSC_MAJESTY) && ww_dice(GET_COURAGE(ch), GET_CHARISMA(victim) + GET_INTIMIDATION(victim)) < 1)
		return FALSE;

	if (GET_RIDING(ch) == victim || GET_RIDDEN_BY(ch) == victim) {
		msg_to_char(ch, "You can't attack your mount!\r\n");
		return FALSE;
		}

	if (IS_NPC(ch) || IS_NPC(victim))
		return TRUE;

	/* calculate play time: 1 day minimum to pk */
	playing_time = *real_time_passed((time(0) - ch->player.time.logon) + ch->player.time.played, 0);
	playing_time2 = *real_time_passed((time(0) - victim->player.time.logon) + victim->player.time.played, 0);

	// let em kill eachother
	if (playing_time.day > 0 || playing_time2.day > 0){
		return TRUE;
	} else {
		return TRUE;
	}

	if (DSC_FLAGGED(victim, DSC_BITUMENOUS_FLESH))
		return FALSE;

	if (SECT(victim->in_room) == SECT_TOWER_OF_SOULS) {
		msg_to_char(ch, "You can't attack anyone here!\r\n");
		return FALSE;
		}

	if ((IS_GOD(ch) && !IS_GOD(victim)) || (IS_GOD(victim) && !IS_GOD(ch)))
		return FALSE;

	if (IS_IMMORTAL(ch) || IS_IMMORTAL(victim))
		return FALSE;

	if ((IS_HARDCORE(ch) && !IS_HARDCORE(victim)) || (IS_HARDCORE(victim) && !IS_HARDCORE(ch)))
		return FALSE;

	if (IS_SET(pk_ok, PK_FULL))
		return TRUE;

	if (IS_SET(pk_ok, PK_WAR)) {
		if ((emp_pol = find_relation(real_empire(GET_LOYALTY(ch)), real_empire(GET_LOYALTY(victim)))))
			if (IS_SET(emp_pol->type, DIPL_WAR))
				return TRUE;

		/* owned territory */
		if (CAN_USE_ROOM(ch, ch->in_room, 1) && !CAN_USE_ROOM(victim, victim->in_room, 0))
			return TRUE;
		}

	/* Oops... we shouldn't be fighting */

	if (FIGHTING(ch) == victim)
		stop_fighting(ch);
	if (FIGHTING(victim) == ch)
		stop_fighting(victim);

	return FALSE;
	}


void appear(Creature ch) {
	REMOVE_BIT(AFF_FLAGS(ch), AFF_HIDE | AFF_INVISIBLE);
	REMOVE_BIT(DSC_FLAGS(ch), DSC_UNSEEN_PRESENCE);

	if (GET_LEVEL(ch) < LVL_GOD) {
		act("$n slowly fades into existence.", FALSE, ch, 0, 0, TO_ROOM);
		msg_to_char(ch, "You fade back into view.\r\n");
		}
	else
		act("You feel a strange presence as $n appears, seemingly from nowhere.", FALSE, ch, 0, 0, TO_ROOM);
	}


void load_messages(void) {
	FILE *fl;
	int i, type;
	struct message_type *messages;
	char chk[128];

	if (!(fl = fopen(MESS_FILE, "r"))) {
		log("SYSERR: Error reading combat message file %s: %s", MESS_FILE, strerror(errno));
		exit(1);
		}
	for (i = 0; i < MAX_MESSAGES; i++) {
		fight_messages[i].a_type = 0;
		fight_messages[i].number_of_attacks = 0;
		fight_messages[i].msg = 0;
		}

	fgets(chk, 128, fl);
	while (!feof(fl) && (*chk == '\n' || *chk == '*'))
		fgets(chk, 128, fl);

	while (*chk == 'M') {
		fgets(chk, 128, fl);
		sscanf(chk, " %d\n", &type);
		for (i = 0; (i < MAX_MESSAGES) && (fight_messages[i].a_type != type) && (fight_messages[i].a_type); i++);
		if (i >= MAX_MESSAGES) {
			log("SYSERR: Too many combat messages.  Increase MAX_MESSAGES and recompile.");
			exit(1);
			}
		CREATE(messages, struct message_type, 1);
		fight_messages[i].number_of_attacks++;
		fight_messages[i].a_type = type;
		messages->next = fight_messages[i].msg;
		fight_messages[i].msg = messages;

		messages->die_msg.attacker_msg = fread_action(fl, i);
		messages->die_msg.victim_msg = fread_action(fl, i);
		messages->die_msg.room_msg = fread_action(fl, i);
		messages->miss_msg.attacker_msg = fread_action(fl, i);
		messages->miss_msg.victim_msg = fread_action(fl, i);
		messages->miss_msg.room_msg = fread_action(fl, i);
		messages->hit_msg.attacker_msg = fread_action(fl, i);
		messages->hit_msg.victim_msg = fread_action(fl, i);
		messages->hit_msg.room_msg = fread_action(fl, i);
		messages->god_msg.attacker_msg = fread_action(fl, i);
		messages->god_msg.victim_msg = fread_action(fl, i);
		messages->god_msg.room_msg = fread_action(fl, i);
		fgets(chk, 128, fl);
		while (!feof(fl) && (*chk == '\n' || *chk == '*'))
			fgets(chk, 128, fl);
		}

	fclose(fl);
	}


void update_pos(Creature victim) {
	if (GET_DAMAGE(victim) < 7 && GET_POS(victim) > POS_STUNNED)
		return;
	else if (GET_DAMAGE(victim) == 7)
		GET_POS(victim) = POS_INCAP;
	else if (GET_DAMAGE(victim) >= 8)
		GET_POS(victim) = POS_DEAD;
	else
		GET_POS(victim) = POS_STUNNED;
	}


/* start one char fighting another (yes, it is horrible, I know... )  */
void set_fighting(Creature ch, Creature vict, byte mode) {
	if (ch == vict)
		return;

	if (FIGHTING(ch))
		return;

	ch->next_fighting = combat_list;
	combat_list = ch;

	FIGHTING(ch) = vict;
	FIGHT_MODE(ch) = mode;
	if (mode == FMODE_WAITING)
		FIGHT_WAIT(ch) = MAX(1, MIN(3, 10 - GET_DEXTERITY(ch)));
	GET_POS(ch) = POS_FIGHTING;
	}


/* remove a char from the list of fighting chars */
void stop_fighting(Creature ch) {
	Creature temp;

	if (ch == next_combat_list)
		next_combat_list = ch->next_fighting;

	REMOVE_FROM_LIST(ch, combat_list, next_fighting);
	ch->next_fighting = NULL;
	FIGHTING(ch) = NULL;
	GET_POS(ch) = POS_STANDING;
	update_pos(ch);
	}


Object make_corpse(Creature ch) {
	Object corpse, o, next_o;
	int i;

	corpse = read_object(o_CORPSE, VIRTUAL);

	GET_OBJ_WEIGHT(corpse) = 100 + IS_CARRYING_W(ch);
	GET_OBJ_VAL(corpse, 0) = IS_NPC(ch) ? GET_MOB_VNUM(ch) : -1;
	GET_OBJ_VAL(corpse, 1) = IS_NPC(ch) ? MOB_SKIN(ch) : 100;
	GET_OBJ_VAL(corpse, 2) = 0;

	/* transfer character's inventory to the corpse */
	corpse->contains = ch->carrying;
	for (o = corpse->contains; o != NULL; o = o->next_content)
		o->in_obj = corpse;
	object_list_new_owner(corpse, NULL);

	/* check for large objects and put them in the room */
	if (ch->in_room != NOWHERE)
		for (o = corpse->contains; o != NULL; o = next_o) {
			next_o = o->next_content;
			if (IS_OBJ_STAT(o, ITEM_LARGE))
				obj_to_room(o, ch->in_room);
			}

	/* transfer character's equipment to the corpse */
	for (i = 0; i < NUM_WEARS; i++)
		if (GET_EQ(ch, i))
			obj_to_obj(unequip_char(ch, i), corpse);

	ch->carrying = NULL;
	IS_CARRYING_N(ch) = 0;
	IS_CARRYING_W(ch) = 0;

	return corpse;
	}


void death_cry(Creature ch) {
	int door;

	act("Your blood freezes as you hear $n's death cry.", FALSE, ch, 0, 0, TO_ROOM);

	if ((SECT(ch->in_room) == SECT_BUILDING || SECT(ch->in_room) == SECT_MULTI || SECT(ch->in_room) == SECT_MONUMENT_CLOSED || SECT(ch->in_room) == SECT_INSIDE) && (IS_COMPLETE(ch->in_room) || ALWAYS_CLOSED(ch->in_room))) {
		for (door = 0; door < NUM_OF_DIRS; door++)
			if (CAN_GO(ch, door))
				send_to_room("Your blood freezes as you hear someone's death cry.\r\n", world[ch->in_room].dir_option[door]->to_room);
		}
	for (door = 0; door < NUM_2D_DIRS; door++)
		send_to_room("Your blood freezes as you hear someone's death cry.\r\n", real_shift(ch->in_room, shift_dir[door][0], shift_dir[door][1]));
	}


void die(Creature ch) {
	void delete_empire(int rnum);
	extern const char *hardcore_slain_msg;
	int emp;

	/* Free restore */
	if (!IS_NPC(ch)) {
		if (GET_COND(ch, FULL) > 0)
			GET_COND(ch, FULL) = 0;
		if (GET_COND(ch, DRUNK) > 0)
			GET_COND(ch, DRUNK) = 0;
		if (GET_COND(ch, THIRST) > 0)
			GET_COND(ch, THIRST) = 0;
		if (GET_COND(ch, TIRED) > 0)
			GET_COND(ch, TIRED) = 0;
		}

	INJURY_FLAGS(ch) = 0;

	/* Restore Health */
	GET_DAMAGE(ch) = 0;
	GET_AGG_DAMAGE(ch) = 0;
	GET_BLOOD(ch) = GET_MAX_BLOOD(ch);

	if (FIGHTING(ch))
		stop_fighting(ch);

	while (ch->affected)
		affect_remove(ch, ch->affected);

	perform_morph(ch, MORPH_NONE);

	death_cry(ch);

	if (MOB_FLAGGED(ch, MOB_UNDEAD)) {
		while (ch->carrying)
			obj_to_room(ch->carrying, ch->in_room);
		}
	else
		obj_to_room(make_corpse(ch), ch->in_room);

	if (!IS_NPC(ch) && IS_HARDCORE(ch) && !IS_GOD(ch) && !IS_IMMORTAL(ch)) {
		SET_BIT(PLR_FLAGS(ch), PLR_SLAIN);
		msg_to_char(ch, hardcore_slain_msg);

		/* Check that empire */
		if ((emp = real_empire(GET_LOYALTY(ch))) != -1) {
			GET_LOYALTY(ch) = 0;
			GET_RANK(ch) = 0;
			empire[emp].members--;
			if (empire[emp].members == 0)
				delete_empire(emp);
			}
		}

	save_char(ch, NOWHERE);
	extract_char(ch);
	}


char *replace_string(const char *str, const char *weapon_singular, const char *weapon_plural) {
	static char buf[256];
	char *cp = buf;

	for (; *str; str++) {
		if (*str == '#') {
			switch (*(++str)) {
				case 'W':
					for (; *weapon_plural; *(cp++) = *(weapon_plural++));
					break;
				case 'w':
					for (; *weapon_singular; *(cp++) = *(weapon_singular++));
					break;
				default:
					*(cp++) = '#';
					break;
				}
			}
		else
			*(cp++) = *str;

		*cp = 0;
		}

	return (buf);
	}


/* message for doing damage with a weapon */
void dam_message(int dam, Creature ch, Creature victim, int w_type) {
	char *buf;
	int msgnum;

	static struct dam_weapon_type {
		const char *to_room;
		const char *to_char;
		const char *to_victim;
		} dam_weapons[] = {

			/* use #w for singular (i.e. "slash") and #W for plural (i.e. "slashes") */

			{ "$n tries to #w $N, but misses.",		/* 0: 0     */
			  "You try to #w $N, but miss.",
			 "$n tries to #w you, but misses." },

			{ "$n tickles $N as $e #W $M.",			/* 1 */
			  "You tickle $N as you #w $M.",
			  "$n tickles you as $e #W you." },

			{ "$n barely #W $N.",					/* 2 */
			  "You barely #w $N.",
			  "$n barely #W you." },

			{ "$n #W $N.",							/* 3 */
			  "You #w $N.",
			  "$n #W you." },

			{ "$n #W $N hard.",						/* 4 */
			  "You #w $N hard.",
			  "$n #W you hard." },

			{ "$n #W $N very hard.",				/* 5 */
			  "You #w $N very hard.",
			  "$n #W you very hard." },

			{ "$n #W $N extremely hard.",			/* 6 */
			  "You #w $N extremely hard.",
			  "$n #W you extremely hard." },

			{ "$n massacres $N to small fragments with $s #w.",		/* 7 */
			  "You massacre $N to small fragments with your #w.",
			  "$n massacres you to small fragments with $s #w." },

			{ "$n OBLITERATES $N with $s deadly #w!!",				/* 8 */
			  "You OBLITERATE $N with your deadly #w!!",
			  "$n OBLITERATES you with $s deadly #w!!" }
		};

	if (dam < 8)
		msgnum = dam;
	else
		msgnum = 8;

	/* damage message to onlookers */
	buf = replace_string(dam_weapons[msgnum].to_room, attack_hit_text[w_type].singular, attack_hit_text[w_type].plural);
	act(buf, FALSE, ch, NULL, victim, TO_NOTVICT);

	/* damage message to damager */
	if (ch->desc) {
		send_to_char("&3", ch);
		buf = replace_string(dam_weapons[msgnum].to_char, attack_hit_text[w_type].singular, attack_hit_text[w_type].plural);
		act(buf, FALSE, ch, NULL, victim, TO_CHAR);
		send_to_char("&0", ch);
		}

	/* damage message to damagee */
	if (victim->desc) {
		send_to_char("&1", victim);
		buf = replace_string(dam_weapons[msgnum].to_victim, attack_hit_text[w_type].singular, attack_hit_text[w_type].plural);
		act(buf, FALSE, ch, NULL, victim, TO_VICT | TO_SLEEP);
		send_to_char("&0", victim);
		}
	}


/*
 * message for doing damage with a spell or skill
 *  C3.0: Also used for weapon damage on miss and death blows
 */
int skill_message(int dam, Creature ch, Creature vict, int attacktype) {
	int i, j, nr;
	struct message_type *msg;

	Object weap = GET_EQ(ch, WEAR_WIELD);

	for (i = 0; i < MAX_MESSAGES; i++) {
		if (fight_messages[i].a_type == attacktype) {
			nr = dice(1, fight_messages[i].number_of_attacks);
			for (j = 1, msg = fight_messages[i].msg; (j < nr) && msg; j++)
				msg = msg->next;

			if (!IS_NPC(vict) && (IS_IMMORTAL(vict) || (IS_GOD(vict) && !IS_GOD(ch)))) {
				act(msg->god_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
				act(msg->god_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT);
				act(msg->god_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
				}
			else if (dam != 0) {
				if (GET_POS(vict) == POS_DEAD) {
					send_to_char("&3", ch);
					act(msg->die_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
					send_to_char("&0", ch);

					send_to_char("&1", vict);
					act(msg->die_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
					send_to_char("&0", vict);

					act(msg->die_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
					}
				else {
					send_to_char("&3", ch);
					act(msg->hit_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
					send_to_char("&0", ch);

					send_to_char("&1", vict);
					act(msg->hit_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
					send_to_char("&0", vict);

					act(msg->hit_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
					}
				}
			else if (ch != vict) {	/* Dam == 0 */
				send_to_char("&3", ch);
				act(msg->miss_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
				send_to_char("&0", ch);

				send_to_char("&1", vict);
				act(msg->miss_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
				send_to_char("&0", vict);

				act(msg->miss_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
				}
			return (1);
			}
		}
	return (0);
	}


void death_log(Creature ch, Creature killer, int type) {
	char *msg;
	char output[MAX_STRING_LENGTH];

	/* Follow the pattern.  If there IS a killer, i needs to be 1 */
	bool i = 0;

	switch (type) {
		case ATTACK_GUARD_TOWER:
			msg = "%s has been killed by a guard tower at (%d, %d)";
			break;
		case TYPE_SUFFERING:
			msg = "%s has died at (%d, %d)";
			break;
		case ATTACK_EXECUTE:
			msg = "%s has been executed by %s at (%d, %d)";
			i++;
			break;
		default:
			msg = "%s has been killed at (%d, %d)";
			break;
		}

	if (ch == killer && i) {
		free(msg);
		syslog(0, TRUE, "Unusual error in death_log(): ch == killer, but combat attack type passed");
		msg = "%s has been killed at (%d, %d)";
		i = 0;
		}

	if (i) {
		strcpy(buf, PERS(killer, killer, 1));
		sprintf(output, msg, PERS(ch, ch, 1), buf, X_COORD(ch->in_room), Y_COORD(ch->in_room));
		}
	else
		sprintf(output, msg, PERS(ch, ch, 1), X_COORD(ch->in_room), Y_COORD(ch->in_room));

	mortlog(0, output);
	syslog(0, TRUE, "DEATH: %s", output);
	}


void perform_execute(Creature ch, Creature victim, int attacktype, int damtype) {
	char *to_char, *to_vict, *to_room;
	bool ok = FALSE, decap = FALSE, vampire = FALSE, werewolf = FALSE;
	bool revert = TRUE;
	Creature m;
	Object weapon;

	/* stop_fighting() is split around here to help with exp */

	/* Probably sent here by damage() */
	if (ch == victim)
		ok = TRUE;

	/* Sent here by damage() */
	if (attacktype > NUM_ATTACK_TYPES || (IS_NPC(ch) && (MOB_TYPE(ch) == MTYPE_HUMAN || MOB_FLAGGED(ch, MOB_AGGRESSIVE))) || IS_NPC(victim) || (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTOKILL)))
		ok = TRUE;

	/* Sent here by do_execute() */
	if (attacktype == -1)
		ok = TRUE;

	if (!ok) {
		if (FIGHTING(victim))
			stop_fighting(victim);
		if (FIGHTING(ch) == victim)
			stop_fighting(ch);
		/* knock 'em out */
		GET_DAMAGE(victim) = 7;
		GET_POS(victim) = POS_INCAP;
		act("$n is knocked unconscious!", FALSE, victim, 0, 0, TO_ROOM);
		msg_to_char(victim, "You are knocked unconscious.\r\n");
		return;
		}

	/* We will TRY to find a slicing/slashing weapon */
	weapon = GET_EQ(ch, WEAR_WIELD);
	if ((!weapon || (GET_OBJ_VAL(weapon, 2) != TYPE_SLASH && GET_OBJ_VAL(weapon, 2) != TYPE_SLICE)) && GET_EQ(ch, WEAR_HOLD)) {
		weapon = GET_EQ(ch, WEAR_HOLD);
		if (GET_OBJ_TYPE(weapon) != ITEM_WEAPON || (GET_OBJ_VAL(weapon, 2) != TYPE_SLASH && GET_OBJ_VAL(weapon, 2) != TYPE_SLICE))
			weapon = GET_EQ(ch, WEAR_WIELD);
		}

	/* We have now got a slicing/slashing weapon OR the weapon in the right hand */
	if (weapon && (GET_OBJ_VAL(weapon, 2) == TYPE_SLASH || GET_OBJ_VAL(weapon, 2) == TYPE_SLICE))
		decap = TRUE;

	/* This is a special case, to help hide vampires */
	if (IS_VAMPIRE(victim) && !decap && damtype != DAM_AGGRAVATED) {
		vampire = TRUE;
		revert = FALSE;
		}

	/* This case will help with werewolves */
	if (IS_WEREWOLF(victim))
		switch (damtype) {
			case DAM_BASHING:
				revert = FALSE;
			case DAM_LETHAL:
				werewolf = TRUE;
				break;
			}

	/* Now, we can do it and have handled knock-outs.. */
	switch (weapon ? GET_OBJ_VAL(weapon, 2) : TYPE_HIT) {
		case TYPE_STING:
		case TYPE_STAB:
			to_char = "You jab $M through the heart!";
			to_vict = "$n jabs you through the heart!";
			to_room = "$n jabs $N through the heart!";
			break;
		case TYPE_WHIP:
			to_char = "You wrap your weapon around $S neck and strangle $M!";
			to_vict = "$n wraps $s weapon around your neck and strangles you!";
			to_room = "$n wraps $s weapon around $N and strangles $M!";
			break;
		case TYPE_SLASH:
		case TYPE_SLICE:
			to_char = "You swing your weapon hard and decapitate $M!";
			to_vict = "$n swings $s weapon hard, and that's the last thing you see!";
			to_room = "$n swings $s weapon hard, decapitating $N!";
			break;
		case TYPE_POUND:
			to_char = "You hit $M hard upside the head with your weapon!";
			to_vict = "$n hits you hard upside the head with $s weapon... You black out.\r\n";
			to_room = "$n hits $N hard upside the head with $s weapon!";
			break;
		default:
			to_char = "You grab $M by the head and twist sharply!";
			to_vict = "$n grabs you by the head and twists sharply!";
			to_room = "$n grabs $N by the head and twists sharply!";
			break;
			}

	if (ch != victim) {
		act(to_char, FALSE, ch, 0, victim, TO_CHAR);
		act(to_vict, FALSE, ch, 0, victim, TO_VICT);
		act(to_room, FALSE, ch, 0, victim, TO_NOTVICT);
		}

	if (revert && !IS_NPC(victim) && GET_MORPH(victim) != GET_BREED_FORM(victim)) {
		sprintf(buf, "%s reverts into $n!", PERS(victim, victim, 0));

		perform_morph(victim, GET_BREED_FORM(victim));
		act(buf, TRUE, victim, 0, 0, TO_ROOM);
		}

	act("$n is dead!  R.I.P.", FALSE, victim, 0, 0, TO_ROOM);

	if (vampire || werewolf) {
		if (FIGHTING(victim))
			stop_fighting(victim);
		if (FIGHTING(ch) == victim)
			stop_fighting(ch);
		GET_DAMAGE(victim) = 7;
		GET_POS(victim) = POS_INCAP;

		if (vampire)
			msg_to_char(victim, "You are knocked unconscious, though this is not Final Death...\r\n");
		else if (werewolf)
			msg_to_char(victim, "You are knocked unconscious!\r\n");
		}
	else {
		/* logs */
		if (!IS_NPC(victim)) {
			if (ch != victim)
				death_log(victim, ch, ATTACK_EXECUTE);
			else
				death_log(victim, ch, TYPE_SUFFERING);
			}

		/* Actually killed him! */
		if (victim != ch && !IS_NPC(victim)) {
			for (m = world[victim->in_room].people; m; m = m->next_in_room)
				if (FIGHTING(m) == victim && !IS_NPC(m))
					stop_fighting(m);
			if (!IS_NPC(ch))
				gain_experience(victim, -5);
			}
		if (FIGHTING(victim))
			stop_fighting(victim);
		if (FIGHTING(ch) == victim)
			stop_fighting(ch);
		msg_to_char(victim, "You are dead!  Sorry...\r\n");
		if (!IS_NPC(victim) && !IS_NPC(ch)) {
			if (ch == victim) {
				if (attacktype == ATTACK_GUARD_TOWER)
					add_lore(ch, LORE_TOWER_DEATH, 0);
				else
					add_lore(ch, LORE_DEATH, 0);
				}
			else {
				add_lore(ch, LORE_PLAYER_KILL, GET_IDNUM(victim));
				add_lore(victim, LORE_PLAYER_DEATH, GET_IDNUM(ch));
				}
			}
		die(victim);
		}
	}


/*
 *	< 0	Victim died.
 *	= 0	No damage.
 *	> 0	How much damage done.
 */
int damage(Creature ch, Creature victim, int dam, int attacktype, byte damtype) {
	byte soak_difficulty = 6;

	if (GET_POS(victim) <= POS_DEAD) {
		log("SYSERR: Attempt to damage corpse '%s' in room #%d by '%s'.", GET_NAME(victim), GET_ROOM_VNUM(IN_ROOM(victim)), GET_NAME(ch));
		die(victim);
		return (-1);			/* -je, 7/7/92 */
		}

	/* You can't damage an immortal! */
	if (!IS_NPC(victim) && (IS_IMMORTAL(victim) || (IS_GOD(victim) && !IS_GOD(ch))))
		dam = 0;

	if (!can_fight(ch, victim))
		return 0;

	/* Only damage to self (sun) still hurts */
	if (AFF_FLAGGED(victim, AFF_IMMUNE_PHYSICAL) && !(attacktype == ATTACK_SUNBURN || attacktype == TYPE_FIRE))
		dam = 0;

	if (victim != ch) {
		/* Start the attacker fighting the victim */
		if (GET_POS(ch) > POS_STUNNED && (FIGHTING(ch) == NULL))
			set_fighting(ch, victim, FMODE_MELEE);

		/* Start the victim fighting the attacker */
		if (GET_POS(victim) > POS_STUNNED && (FIGHTING(victim) == NULL))
			set_fighting(victim, ch, FMODE_MELEE);
		}

	/* If you attack a pet, it hates your guts */
	if (victim->master == ch)
		stop_follower(victim);

	/* If the attacker is invisible, he becomes visible */
	if (SHOULD_APPEAR(ch))
		appear(ch);

	/* Roll soak: */
	/* Humans can soak bashing damage at 6, lethal at 8 */
	if (IS_HUMAN(ch) && (!IS_WEREWOLF(ch) || (GET_MORPH(ch) == GET_BREED_FORM(ch) && GET_MORPH(ch) != MORPH_CRINOS)) && damtype >= DAM_LETHAL)
		soak_difficulty = 8;

	/* Aggravated damage is ONLY soaked with Fortitude */
	if (damtype != DAM_AGGRAVATED)
		dam -= MAX(0, ww_dice(GET_STAMINA(victim) + GET_SOAK(victim) + GET_FORTITUDE(victim), soak_difficulty));
	else if (IS_WEREWOLF(victim) && (GET_MORPH(victim) != GET_BREED_FORM(victim) || GET_MORPH(victim) == MORPH_CRINOS))
		dam -= MAX(0, ww_dice(GET_STAMINA(victim) + GET_FORTITUDE(victim), soak_difficulty));
	else if (GET_FORTITUDE(victim) >= 1)
		dam -= MAX(0, ww_dice(GET_FORTITUDE(victim), soak_difficulty));

	/* Bashing damage is halved against vampires, AFTER soak */
	if (damtype == DAM_BASHING && IS_VAMPIRE(ch))
		dam /= 2;

	/* Minimum damage of 0.. can't do negative */
	dam = MAX(0, dam);

	/* Add Damage */
	GET_DAMAGE(victim) += dam;
	if (damtype == DAM_AGGRAVATED)
		GET_AGG_DAMAGE(victim) += dam;

	/* Error checking */
	GET_AGG_DAMAGE(victim) = MIN(GET_AGG_DAMAGE(victim), GET_DAMAGE(victim));

	/* Blood-stealing tongue of the asp */
	if (dam > 0 && attacktype == TYPE_SERPENTIS_TONGUE && IS_VAMPIRE(ch) && GET_BLOOD(ch) < GET_MAX_BLOOD(ch) && GET_BLOOD(victim) > 0) {
		if (GET_BLOOD(victim) > 0)
			GET_BLOOD(victim) -= 1;
		if (GET_BLOOD(ch) < GET_MAX_BLOOD(ch))
			GET_BLOOD(ch) += 1;
		}

	update_pos(victim);

	/*
	 * skill_message sends a message from the messages file in lib/misc.
	 * dam_message just sends a generic "You hit $n extremely hard.".
	 * skill_message is preferable to dam_message because it is more
	 * descriptive.
	 *
	 * If we are _not_ attacking with a weapon (i.e. a spell), always use
	 * skill_message. If we are attacking with a weapon: If this is a miss or a
	 * death blow, send a skill_message if one exists; if not, default to a
	 * dam_message. Otherwise, always send a dam_message.
	 */
	if (!IS_WEAPON(attacktype))
		skill_message(dam, ch, victim, attacktype);
	else {
		if (dam == 0 || ch == victim || (GET_POS(victim) == POS_DEAD && !(!IS_NPC(ch) && !IS_NPC(victim) && !PRF_FLAGGED(ch, PRF_AUTOKILL)))) {
			if (!skill_message(dam, ch, victim, attacktype))
				dam_message(dam, ch, victim, attacktype);
			}
		else
			dam_message(dam, ch, victim, attacktype);
		}

	/* Use send_to_char -- act() doesn't send message if you are DEAD. */
	switch (GET_POS(victim)) {
		case POS_MORTALLYW:
			act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, TO_ROOM);
			send_to_char("You are mortally wounded, and will die soon, if not aided.\r\n", victim);
			break;
		case POS_INCAP:
			act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, TO_ROOM);
			send_to_char("You are incapacitated an will slowly die, if not aided.\r\n", victim);
			break;
		case POS_STUNNED:
			act("$n is stunned, but will probably regain consciousness again.", TRUE, victim, 0, 0, TO_ROOM);
			send_to_char("You're stunned, but will probably regain consciousness again.\r\n", victim);
			break;
		case POS_DEAD:
			/* These messages will be handled in perform_execute */
			break;
		default:			/* >= POSITION SLEEPING */
			if (dam > 2)
				send_to_char("&1That really did HURT!&0\r\n", victim);

			if (GET_DAMAGE(victim) >= 6)
				msg_to_char(victim, "&1You wish that your wounds would stop BLEEDING so much!&0\r\n");

			break;
			}

	/* Help out poor linkless people who are attacked */
	if (!IS_NPC(victim) && !(victim->desc) && GET_POS(victim) > POS_STUNNED)
		do_flee(victim, NULL, 0, 0);

	/* stop someone from fighting if they're stunned or worse */
	if ((GET_POS(victim) <= POS_STUNNED) && (FIGHTING(victim) != NULL))
		stop_fighting(victim);

	/* Uh oh.  Victim died. */
	if (GET_POS(victim) == POS_DEAD) {
		perform_execute(ch, victim, attacktype, damtype);
		return -1;
		}

	return dam;
	}


int hit(Creature ch, Creature victim) {
	extern const int dam_type[];

	Object wielded = GET_EQ(ch, WEAR_WIELD);
	int w_type, to_hit, to_dodge = 0, dam;
	byte damtype;

	if (!victim || !ch)
		return -1;

	/* Do some sanity checking, in case someone flees, etc. */
	if (ch->in_room != victim->in_room) {
		if (FIGHTING(ch) && FIGHTING(ch) == victim)
			stop_fighting(ch);
		return -1;
		}

	/* Find the weapon type (for display purposes only) */
	if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON)
		w_type = GET_OBJ_VAL(wielded, 2);
	else {
		if (DSC_FLAGGED(ch, DSC_TALONS_OF_THE_BEAST))
			w_type = TYPE_PROTEAN_CLAWS;
		else if (DSC_FLAGGED(ch, DSC_TONGUE_OF_THE_ASP))
			w_type = TYPE_SERPENTIS_TONGUE;
		else if (IS_NPC(ch) && (MOB_ATTACK_TYPE(ch) != 0))
			w_type = MOB_ATTACK_TYPE(ch);
		else if (!IS_NPC(ch) && GET_MORPH(ch) != MORPH_NONE)
			w_type = get_morph_attack_type(ch);
		else
			w_type = TYPE_HIT;
		}

	/* to_hit is based on dexterity + melee/brawl */
	if (wielded)
		to_hit = ww_dice(GET_DEXTERITY(ch) + GET_MELEE(ch), 6 + GET_BLOCK(victim));
	else
		to_hit = ww_dice(GET_DEXTERITY(ch) + GET_BRAWL(ch), 6 + GET_BLOCK(victim));

	if (AWAKE(victim) && CAN_SEE(victim, ch))
		to_dodge = ww_dice(GET_DEXTERITY(victim) + GET_DODGE(victim), 8);

	/* decide whether this is a hit or a miss */
	if (to_hit BOTCHED)
		return -1;
	else if (to_hit <= to_dodge) {
		/* the attacker missed the victim */
		return damage(ch, victim, 0, w_type, DAM_BASHING);
		}
	else {
		/* okay, we know the guy has been hit.  now calculate damage. */

		/* Melee attacks are based upon strength.. */
		dam = GET_STRENGTH(ch);

		if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) {
			/* Add weapon-based damage if a weapon is being wielded */
			dam += GET_OBJ_VAL(wielded, 1);
			}
		else if (IS_NPC(ch))
			dam = MOB_DAMAGE(ch);

		if (w_type == TYPE_PROTEAN_CLAWS)
			dam += 2;

		dam += to_hit - to_dodge - 1;

		dam = ww_dice(dam, 6);
		dam += GET_POTENCE(ch);

		damtype = dam_type[w_type];

		if (wielded && GET_OBJ_VAL(wielded, 0)) {
			damtype = DAM_AGGRAVATED;
			if (GET_OBJ_VAL(wielded, 0) > 0)
				GET_OBJ_VAL(wielded, 0) -= 1;
			}

		dam = MAX(0, dam);

		/* Fortitude 6 lets us shatter weapons */
		if (wielded && DSC_FLAGGED(victim, DSC_ARMOR_OF_VITALITY) && GET_BLOOD(victim) > 1) {
			GET_BLOOD(victim) -= 1;
			if (ww_dice(GET_FORTITUDE(victim), 7) > 0) {
				act("You strike $N with $p, which shatters against $S flesh!", FALSE, ch, wielded, victim, TO_CHAR);
				act("$n strikes $N with $p, which shatters against $S flesh!", FALSE, ch, wielded, victim, TO_NOTVICT);
				act("$n strikes you with $p, which shatters against your flesh!", FALSE, ch, wielded, victim, TO_VICT);
				extract_obj(wielded);
				return 1;
				}
			}

		return damage(ch, victim, dam, w_type, damtype);
		}
	}


void perform_violence_melee(Creature ch) {
	Object main_weapon, second_weapon;
	int attacks;

	for (attacks = 0; attacks < MAX(1 + ATTACK_BONUS(ch), number(1, 2)); attacks++) {
		main_weapon = GET_EQ(ch, WEAR_WIELD);
		second_weapon = GET_EQ(ch, WEAR_HOLD);
		if (second_weapon && GET_OBJ_TYPE(second_weapon) != ITEM_WEAPON)
			second_weapon = NULL;

		if (!IS_NPC(ch) || !second_weapon || number(0, 3)) {
			if (hit(ch, FIGHTING(ch)) < 0)
				return;
			}
		else {
			GET_EQ(ch, WEAR_WIELD) = second_weapon;
			if (hit(ch, FIGHTING(ch)) < 0) {
				GET_EQ(ch, WEAR_WIELD) = main_weapon;
				return;
				}
			GET_EQ(ch, WEAR_WIELD) = main_weapon;
			}
		}
	}


void perform_violence_missile(Creature ch) {
	Object arrow, bow, quiver;
	int attacks, dam = 0;
	int to_hit, to_dodge = 0;
	byte dam_type = DAM_LETHAL;

	if (!(bow = GET_EQ(ch, WEAR_HOLD)) || GET_OBJ_TYPE(bow) != ITEM_MISSILE_WEAPON) {
		msg_to_char(ch, "You don't have a ranged weapon to shoot with!\r\n");
		if (FIGHT_MODE(FIGHTING(ch)) == FMODE_MISSILE) {
			FIGHT_MODE(ch) = FMODE_WAITING;
			FIGHT_WAIT(ch) = 2;
			}
		else
			FIGHT_MODE(ch) = FMODE_MELEE;
		return;
		}
	if (!(quiver = GET_EQ(ch, WEAR_QUIVER)) || GET_OBJ_TYPE(quiver) != ITEM_CONTAINER) {
		msg_to_char(ch, "You need a quiver full of arrows to shoot!\r\n");
		if (FIGHT_MODE(FIGHTING(ch)) == FMODE_MISSILE) {
			FIGHT_MODE(ch) = FMODE_WAITING;
			FIGHT_WAIT(ch) = 2;
			}
		else
			FIGHT_MODE(ch) = FMODE_MELEE;
		return;
		}

	for (attacks = 0; attacks < GET_OBJ_VAL(bow, 0); attacks++) {
		for (arrow = quiver->contains; arrow; arrow = quiver->next_content)
			if (GET_OBJ_TYPE(arrow) == ITEM_ARROW && GET_OBJ_VAL(arrow, 2) == GET_OBJ_VAL(bow, 2))
				break;

		if (!arrow) {
			msg_to_char(ch, "You don't have anything that you can shoot!\r\n");
			if (FIGHT_MODE(FIGHTING(ch)) == FMODE_MISSILE) {
				FIGHT_MODE(ch) = FMODE_WAITING;
				FIGHT_WAIT(ch) = 2;
				}
			else
				FIGHT_MODE(ch) = FMODE_MELEE;
			return;
			}

		/* to_hit is based upon dexterity + archery, difficulty 7 */
		to_hit = ww_dice(GET_DEXTERITY(ch) + GET_ARCHERY(ch), 7);

		/* to_dodge is based upon dexterity + dodge, difficulty 6 */
		if (AWAKE(FIGHTING(ch)) && CAN_SEE(FIGHTING(ch), ch))
			to_dodge = ww_dice(GET_DEXTERITY(FIGHTING(ch)) + GET_DODGE(FIGHTING(ch)), 8);

		/* Damage is based ONLY on the weapons, not on strength */
		if (to_hit > to_dodge) {
			dam = GET_OBJ_VAL(bow, 1) + GET_OBJ_VAL(arrow, 1) + to_hit - to_dodge;
			dam = ww_dice(dam, 6);
			}

		if (GET_OBJ_VAL(arrow, 0))
			dam_type = DAM_AGGRAVATED;

		extract_obj(arrow);

		if (to_dodge >= to_hit)
			damage(ch, FIGHTING(ch), 0, ATTACK_ARROW, dam_type);
		else if (damage(ch, FIGHTING(ch), dam, ATTACK_ARROW, dam_type) < 0)
			return;
		}
	}


/* control the fights going on.  Called every 2 seconds from comm.c. */
void perform_violence(void) {
	void diag_char_to_char(Creature i, Creature ch);

	Creature ch, vict;

	for (ch = combat_list; ch; ch = next_combat_list) {
		next_combat_list = ch->next_fighting;

		if (FIGHTING(ch) == NULL || ch->in_room != FIGHTING(ch)->in_room) {
			stop_fighting(ch);
			continue;
			}

		if (!IS_NPC(ch) && !IS_NPC(FIGHTING(ch))) {
			GET_QUIT_TIMER(ch) = 45;
			GET_QUIT_TIMER(FIGHTING(ch)) = 45;
			}

		/* Auto-assist */
		if (AFF_FLAGGED(ch, AFF_PARTY) && FIGHTING(ch))
			for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room)
				if (AFF_FLAGGED(vict, AFF_PARTY) && ((vict->master ? vict->master : vict) == (ch->master ? ch->master : ch)) && FIGHTING(ch) != vict && !FIGHTING(vict)) {
					act("You jump to $N's aide!", FALSE, vict, 0, ch, TO_CHAR);
					act("$n jumps to your aide!", FALSE, vict, 0, ch, TO_VICT);
					act("$n jumps to $N's aide!", FALSE, vict, 0, ch, TO_NOTVICT);
					set_fighting(vict, FIGHTING(ch), FMODE_WAITING);
					}

		if (IS_NPC(ch)) {
			if (GET_MOB_WAIT(ch) > 0) {
				GET_MOB_WAIT(ch) -= PULSE_VIOLENCE;
				continue;
				}
			GET_MOB_WAIT(ch) = 0;
			if (GET_POS(ch) < POS_FIGHTING) {
				GET_POS(ch) = POS_FIGHTING;
				act("$n scrambles to $s feet!", TRUE, ch, 0, 0, TO_ROOM);
				}
			}

		if (GET_POS(ch) < POS_FIGHTING) {
			send_to_char("You can't fight while sitting!!\r\n", ch);
			continue;
			}

		/* These functions tend to kill people, so they must be last in the loop. */
		switch (FIGHT_MODE(ch)) {
			case FMODE_MELEE:
				perform_violence_melee(ch);
				break;
			case FMODE_MISSILE:
				perform_violence_missile(ch);
				break;
			case FMODE_WAITING:
				if (IS_NPC(ch) && MOB_TYPE(ch) == MTYPE_ANIMAL && !number(0, 10))
					do_flee(ch, "", 0, 0);
				if (FIGHTING(ch) && ch->in_room == FIGHTING(ch)->in_room) {
					act("You run toward $N!", FALSE, ch, 0, FIGHTING(ch), TO_CHAR);
					act("$n runs toward you!", FALSE, ch, 0, FIGHTING(ch), TO_VICT);
					if ((FIGHT_WAIT(ch)--) <= 0 || FIGHT_MODE(FIGHTING(ch)) != FMODE_MISSILE) {
						act("You engage $M in melee combat!", FALSE, ch, 0, FIGHTING(ch), TO_CHAR);
						act("$e engages you in melee combat!", FALSE, ch, 0, FIGHTING(ch), TO_VICT);
						FIGHT_MODE(ch) = FMODE_MELEE;
						/* Only change modes if he's fighting us, too */
						if (FIGHTING(FIGHTING(ch)) == ch)
							FIGHT_MODE(FIGHTING(ch)) = FMODE_MELEE;
						}
					}
				break;
			default:
				FIGHT_MODE(ch) = FMODE_MELEE;
				break;
			}

		}

	/* Diagnose them all */
	for (ch = combat_list; ch; ch = ch->next_fighting)
		if (ch->desc && FIGHTING(ch) && FIGHTING(ch)->in_room == ch->in_room)
			diag_char_to_char(FIGHTING(ch), ch);
	}


ACMD(do_assist) {
	Creature helpee, opponent;

	if (FIGHTING(ch)) {
		send_to_char("You're already fighting!  How can you assist someone else?\r\n", ch);
		return;
		}
	one_argument(argument, arg);

	if (!*arg)
		send_to_char("Whom do you wish to assist?\r\n", ch);
	else if (!(helpee = get_char_vis(ch, arg, FIND_CHAR_ROOM)))
		send_to_char(NOPERSON, ch);
	else if (helpee == ch)
		send_to_char("You can't help yourself any more than this!\r\n", ch);
	else {
		/*
		 * Hit the same enemy the person you're helping is.
		 */
		if (FIGHTING(helpee))
			opponent = FIGHTING(helpee);
		else
			for (opponent = world[ch->in_room].people; opponent && (FIGHTING(opponent) != helpee); opponent = opponent->next_in_room);

		if (!opponent)
			act("But nobody is fighting $M!", FALSE, ch, 0, helpee, TO_CHAR);
		else if (!CAN_SEE(ch, opponent))
			act("You can't see who is fighting $M!", FALSE, ch, 0, helpee, TO_CHAR);
		else if (FIGHT_MODE(opponent) != FMODE_MELEE)
			msg_to_char(ch, "You can't attack until they've engaged in melee combat.\r\n");
		else if (can_fight(ch, opponent)) {
			send_to_char("You join the fight!\r\n", ch);
			act("$N assists you!", 0, helpee, 0, ch, TO_CHAR);
			act("$n assists $N.", FALSE, ch, 0, helpee, TO_NOTVICT);
			hit(ch, opponent);
			}
		else
			act("You can't attack $N!", FALSE, ch, 0, opponent, TO_CHAR);
		}
	}


ACMD(do_hit) {
	Creature vict;

	one_argument(argument, arg);

	if (!*arg)
		send_to_char("Hit who?\r\n", ch);
	else if (!(vict = get_char_vis(ch, arg, FIND_CHAR_ROOM)))
		send_to_char("They don't seem to be here.\r\n", ch);
	else if (vict == ch) {
		send_to_char("You hit yourself...OUCH!.\r\n", ch);
		act("$n hits $mself, and says OUCH!", FALSE, ch, 0, vict, TO_ROOM);
		}
	else if (AFF_FLAGGED(ch, AFF_CHARM) && (ch->master == vict))
		act("$N is just such a good friend, you simply can't hit $M.", FALSE, ch, 0, vict, TO_CHAR);
	else if (vict == FIGHTING(ch) && FIGHT_MODE(ch) == FMODE_MISSILE) {
		if (FIGHT_MODE(vict) == FMODE_MISSILE) {
			act("You run at $M!", FALSE, ch, 0, vict, TO_CHAR);
			FIGHT_MODE(ch) = FMODE_WAITING;
			FIGHT_WAIT(ch) = 2;
			WAIT_STATE(ch, PULSE_VIOLENCE + 2);
			}
		else
			FIGHT_MODE(ch) = FMODE_MELEE;
		}
	else if (can_fight(ch, vict)) {
		if (AFF_FLAGGED(ch, AFF_CHARM) && !IS_NPC(ch->master) && !IS_NPC(vict))
			return;

		if (FIGHTING(ch) || vict == FIGHTING(ch) || GET_POS(ch) < POS_STANDING)
			msg_to_char(ch, "You do the best that you can!\r\n");
		else if (FIGHTING(vict) && FIGHT_MODE(vict) == FMODE_MISSILE) {
			set_fighting(ch, vict, FMODE_WAITING);
			act("You run at $M!", FALSE, ch, 0, vict, TO_CHAR);
			WAIT_STATE(ch, PULSE_VIOLENCE + 2);
			}
		else {
			hit(ch, vict);
			WAIT_STATE(ch, PULSE_VIOLENCE + 2);
			}
		}
	else
		act("You can't attack $N!", FALSE, ch, 0, vict, TO_CHAR);
	}


ACMD(do_shoot) {
	Creature vict;

	one_argument(argument, arg);

	if (!*arg)
		msg_to_char(ch, "Shoot whom?\r\n");
	else if (!(vict= get_char_vis(ch, arg, FIND_CHAR_ROOM)))
		msg_to_char(ch, NOPERSON);
	else if (vict == ch)
		msg_to_char(ch, "Shooting yourself in the foot will do you no good now.\r\n");
	else if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master == vict)
		act("$N is just such a good friend, you simply can't hit $M.", FALSE, ch, 0, vict, TO_CHAR);
	else if (!GET_EQ(ch, WEAR_HOLD) || GET_OBJ_TYPE(GET_EQ(ch, WEAR_HOLD)) != ITEM_MISSILE_WEAPON)
		msg_to_char(ch, "You don't have anything to shoot!\r\n");
	else if (FIGHTING(ch))
		msg_to_char(ch, "You're already fighting for your life!\r\n");
	else if (can_fight(ch, vict)) {
		if (AFF_FLAGGED(ch, AFF_CHARM) && !IS_NPC(ch->master) && !IS_NPC(vict))
			return;

		msg_to_char(ch, "You take aim.\r\n");
		act("$n takes aim.", TRUE, ch, 0, 0, TO_ROOM);
		set_fighting(ch, vict, FMODE_MISSILE);
		if (!FIGHTING(vict) && GET_POS(vict) == POS_STANDING) {
			if (GET_EQ(vict, WEAR_HOLD) && GET_OBJ_TYPE(GET_EQ(vict, WEAR_HOLD)) == ITEM_MISSILE_WEAPON)
				set_fighting(vict, ch, FMODE_MISSILE);
			else
				set_fighting(vict, ch, FMODE_WAITING);
			}
		WAIT_STATE(ch, PULSE_VIOLENCE + 2);
		}
	else
		act("You can't shoot $N!", FALSE, ch, 0, vict, TO_CHAR);
	}


ACMD(do_slay) {
	Creature vict;

	one_argument(argument, arg);

	if (!*arg)
		send_to_char("Slay whom?\r\n", ch);
	else {
		if (!(vict = get_char_vis(ch, arg, FIND_CHAR_ROOM)))
			send_to_char("They aren't here.\r\n", ch);
		else if (ch == vict)
			send_to_char("Your mother would be so sad.. :(\r\n", ch);
		else {
			act("You chop $M to pieces!  Ah!  The blood!", FALSE, ch, 0, vict, TO_CHAR);
			act("$N chops you to pieces!", FALSE, vict, 0, ch, TO_CHAR);
			act("$n brutally slays $N!", FALSE, ch, 0, vict, TO_NOTVICT);
			die(vict);
			}
		}
	}


ACMD(do_order) {
	char name[MAX_INPUT_LENGTH], message[MAX_INPUT_LENGTH];
	bool found = FALSE;
	room_rnum org_room;
	Creature vict;
	struct follow_type *k;

	half_chop(argument, name, message);

	if (!*name || !*message)
		send_to_char("Order who to do what?\r\n", ch);
	else if (!(vict = get_char_vis(ch, name, FIND_CHAR_ROOM)) && !is_abbrev(name, "followers"))
		send_to_char("That person isn't here.\r\n", ch);
	else if (ch == vict)
		send_to_char("You obviously suffer from skitzofrenia.\r\n", ch);
	else {
		if (AFF_FLAGGED(ch, AFF_CHARM)) {
			send_to_char("Your superior would not aprove of you giving orders.\r\n", ch);
			return;
			}
		if (vict) {
			sprintf(buf, "$N orders you to '%s'", message);
			act(buf, FALSE, vict, 0, ch, TO_CHAR);
			act("$n gives $N an order.", FALSE, ch, 0, vict, TO_ROOM);

			if ((vict->master != ch) || (!AFF_FLAGGED(vict, AFF_CHARM) && !DSC_FLAGGED(vict, DSC_ENTRANCEMENT)))
				act("$n has an indifferent look.", FALSE, vict, 0, 0, TO_ROOM);
			else {
				send_to_char(OK, ch);
				command_interpreter(vict, message);
				}
			}
		else {			/* This is order "followers" */
			sprintf(buf, "$n issues the order '%s'.", message);
			act(buf, FALSE, ch, 0, vict, TO_ROOM);

			org_room = ch->in_room;

			for (k = ch->followers; k; k = k->next) {
				if (org_room == k->follower->in_room)
					if (AFF_FLAGGED(k->follower, AFF_CHARM) || DSC_FLAGGED(k->follower, DSC_ENTRANCEMENT)) {
						found = TRUE;
						command_interpreter(k->follower, message);
						}
				}
			if (found)
				send_to_char(OK, ch);
			else
				send_to_char("Nobody here is a loyal subject of yours!\r\n", ch);
			}
		}
	}


ACMD(do_flee) {
	extern int perform_move(Creature ch, int dir, int need_specials_check, byte mode);
	int i, attempt, to_room;
	Creature was_fighting;

	if (GET_POS(ch) < POS_FIGHTING) {
		send_to_char("You are in pretty bad shape, unable to flee!\r\n", ch);
		return;
		}

	for (i = 0; i < NUM_2D_DIRS; i++) {
		attempt = number(0, NUM_2D_DIRS - 1);	/* Select a random direction, not up/down */
		to_room = real_shift(ch->in_room, shift_dir[attempt][0], shift_dir[attempt][1]);
		if (((SECT(ch->in_room) == SECT_INSIDE || SECT(ch->in_room) == SECT_MULTI || SECT(ch->in_room) == SECT_MONUMENT_CLOSED || SECT(ch->in_room) == SECT_BUILDING) && CAN_GO(ch, attempt)) || (((SECT(to_room) != SECT_MOUNTAIN && SECT(to_room) != SECT_OCEAN && SECT(to_room) != SECT_RIVER) || GET_RIDING(ch)) && SECT(to_room) != SECT_BUILDING && SECT(to_room) != SECT_MULTI)) {
			act("$n panics, and attempts to flee!", TRUE, ch, 0, 0, TO_ROOM);
			was_fighting = FIGHTING(ch);
			if (perform_move(ch, attempt, TRUE, 0))
				send_to_char("You flee head over heels.\r\n", ch);
			else {
				act("$n tries to flee, but can't!", TRUE, ch, 0, 0, TO_ROOM);
				send_to_char("PANIC!  You couldn't escape!\r\n", ch);
				}
			return;
			}
		}
	send_to_char("PANIC!  You couldn't escape!\r\n", ch);
	}


ACMD(do_bash) {
	Creature vict;
	byte to_hit, to_dodge = 0, dam;

	one_argument(argument, arg);

	if (IS_NPC(ch)) {
		send_to_char("You have no idea how.\r\n", ch);
		return;
		}
	if (!GET_EQ(ch, WEAR_WIELD)) {
		send_to_char("You need to wield a weapon to make it a success.\r\n", ch);
		return;
		}
	if (!(vict = get_char_vis(ch, arg, FIND_CHAR_ROOM))) {
		if (FIGHTING(ch) && ch->in_room == FIGHTING(ch)->in_room)
			vict = FIGHTING(ch);
		else {
			send_to_char("Bash who?\r\n", ch);
			return;
			}
		}
	if (vict == ch) {
		send_to_char("Aren't we funny today...\r\n", ch);
		return;
		}

	if (FIGHT_MODE(vict) == FMODE_MISSILE || FIGHT_MODE(ch) == FMODE_MISSILE) {
		msg_to_char(ch, "You aren't close enough.\r\n");
		return;
		}

	if (!can_fight(ch, vict)) {
		act("You can't attack $N!", FALSE, ch, 0, vict, TO_CHAR);
		return;
		}

	/* to_hit is based on dexterity + brawl */
	to_hit = ww_dice(GET_DEXTERITY(ch) + GET_BRAWL(ch), 6 + GET_BLOCK(vict));

	if (AWAKE(vict) && CAN_SEE(vict, ch))
		to_dodge = ww_dice(GET_DEXTERITY(vict) + GET_DODGE(vict), 8);

	if (AFF_FLAGGED(vict, AFF_IMMUNE_BASH) || to_dodge >= to_hit || to_hit BOTCHED) {
		damage(ch, vict, 0, ATTACK_BASH, DAM_BASHING);
		GET_POS(ch) = POS_SITTING;
		}
	else {
		/*
		 * If we bash a player and they wimp out, they will move to the previous
		 * room before we set them sitting.  If we try to set the victim sitting
		 * first to make sure they don't flee, then we can't bash them!  So now
		 * we only set them sitting if they didn't flee. -gg 9/21/98
		 */

		dam = ww_dice(GET_STRENGTH(ch) + to_hit - to_dodge, 6) + GET_POTENCE(ch);

		if (damage(ch, vict, dam, ATTACK_BASH, DAM_BASHING) > 0) {	/* -1 = dead, 0 = miss */
			WAIT_STATE(vict, PULSE_VIOLENCE);
			if (ch->in_room == vict->in_room)
				GET_POS(vict) = POS_SITTING;
			}
		}
	WAIT_STATE(ch, PULSE_VIOLENCE * 2);
	}


ACMD(do_rescue) {
	Creature vict, tmp_ch;

	if (IS_NPC(ch)) {
		send_to_char("You have no idea how to do that.\r\n", ch);
		return;
		}

	one_argument(argument, arg);

	if (!(vict = get_char_vis(ch, arg, FIND_CHAR_ROOM))) {
		send_to_char("Whom do you wish to rescue?\r\n", ch);
		return;
		}
	if (vict == ch) {
		send_to_char("What about fleeing instead?\r\n", ch);
		return;
		}
	if (FIGHTING(ch) == vict) {
		send_to_char("How can you rescue someone you are trying to kill?\r\n", ch);
		return;
		}

	for (tmp_ch = world[ch->in_room].people; tmp_ch && (FIGHTING(tmp_ch) != vict); tmp_ch = tmp_ch->next_in_room);

	if (!tmp_ch) {
		act("But nobody is fighting $M!", FALSE, ch, 0, vict, TO_CHAR);
		return;
		}

	if (FIGHT_MODE(tmp_ch) != FMODE_MELEE) {
		msg_to_char(ch, "You may only rescue someone engaged in melee combat.\r\n");
		return;
		}

	if (!can_fight(ch, tmp_ch)) {
		act("You can't attack $N!", FALSE, ch, 0, tmp_ch, TO_CHAR);
		return;
		}

	/* Rescue is based on melee for unobvious reasons */
	if (ww_dice(GET_MANIPULATION(ch) + GET_MELEE(ch), 6)) {
		send_to_char("You fail the rescue!\r\n", ch);
		return;
		}
	send_to_char("Banzai!  To the rescue...\r\n", ch);
	act("You are rescued by $N, you are confused!", FALSE, vict, 0, ch, TO_CHAR);
	act("$n heroically rescues $N!", FALSE, ch, 0, vict, TO_NOTVICT);

	if (FIGHTING(vict) == tmp_ch)
		stop_fighting(vict);
	if (FIGHTING(tmp_ch))
		stop_fighting(tmp_ch);
	if (FIGHTING(ch))
		stop_fighting(ch);

	set_fighting(ch, tmp_ch, FMODE_MELEE);
	set_fighting(tmp_ch, ch, FMODE_MELEE);

	WAIT_STATE(vict, 2 * PULSE_VIOLENCE);
	}


ACMD(do_kick) {
	Creature vict;
	byte to_hit, to_dodge = 0, dam;

	one_argument(argument, arg);

	if (!(vict = get_char_vis(ch, arg, FIND_CHAR_ROOM))) {
		if (FIGHTING(ch) && ch->in_room == FIGHTING(ch)->in_room)
			vict = FIGHTING(ch);
		else {
			send_to_char("Kick who?\r\n", ch);
			return;
			}
		}

	/* to_hit is based on dexterity + brawl */
	to_hit = ww_dice(GET_DEXTERITY(ch) + GET_BRAWL(ch), 6 + GET_BLOCK(vict));

	if (AWAKE(vict) && CAN_SEE(vict, ch))
		to_dodge = ww_dice(GET_DEXTERITY(vict) + GET_DODGE(vict), 8);

	if (IS_NPC(ch))
		send_to_char("You have no idea how.\r\n", ch);
	else if (vict == ch)
		send_to_char("Aren't we funny today...\r\n", ch);
	else if (FIGHT_MODE(vict) == FMODE_MISSILE || FIGHT_MODE(ch) == FMODE_MISSILE)
		msg_to_char(ch, "You aren't close enough.\r\n");
	else if (!can_fight(ch, vict))
		act("You can't attack $N!", FALSE, ch, 0, vict, TO_CHAR);
	else if (AFF_FLAGGED(vict, AFF_IMMUNE_BASH) || to_dodge >= to_hit || to_hit BOTCHED) {
		damage(ch, vict, 0, ATTACK_KICK, DAM_BASHING);
		WAIT_STATE(ch, PULSE_VIOLENCE * 3);
		}
	else {
		dam = ww_dice(GET_STRENGTH(ch) + 2 + to_hit - to_dodge, 6) + GET_POTENCE(ch);
		damage(ch, vict, dam, ATTACK_KICK, DAM_BASHING);
		WAIT_STATE(ch, PULSE_VIOLENCE * 3);
		}
	}


ACMD(do_throw) {
	extern const char *dirs[];

	int dir = -1;
	Object obj = NULL;
	room_rnum to_room = NOWHERE;

	two_arguments(argument, arg, buf);

	if (!*arg || !*buf)
		msg_to_char(ch, "What would you like to throw, and which direction?\r\n");
	else if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying)))
		msg_to_char(ch, "You don't have anything like that.\r\n");
	else if ((dir = parse_direction(buf)) < 0)
		msg_to_char(ch, "Which way did you want to throw it?\r\n");
	else if (SECT(ch->in_room) == SECT_INSIDE || SECT(ch->in_room) == SECT_BUILDING || SECT(ch->in_room) == SECT_MONUMENT_CLOSED || SECT(ch->in_room) == SECT_MULTI) {
		if (!EXIT(ch, dir) || EXIT(ch, dir)->to_room == NOWHERE)
			msg_to_char(ch, "You can't throw it that way.\r\n");
		else if (IS_SET(EXIT(ch, dir)->exit_info, EX_CLOSED))
			msg_to_char(ch, "You can't throw it through a closed door!\r\n");
		else
			to_room = EXIT(ch, dir)->to_room;
		}
	else {
		if (SECT(real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == SECT_MOUNTAIN)
			msg_to_char(ch, "You can't throw it into the mountains.\r\n");
		else if (SECT(real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == SECT_BUILDING || SECT(real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == SECT_MONUMENT_CLOSED || SECT(real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == SECT_MULTI) {
			if (world[real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])].building_entrance != dir)
				msg_to_char(ch, "You can only throw it through the entrance.\r\n");
			else
				to_room = real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1]);
			}
		else
			to_room = real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1]);
		}

	/* If we came up with a room, lets throw! */
	if (to_room == NOWHERE)
		return;

	sprintf(buf, "You throw $p %s as hard as you can!", dirs[dir]);
	sprintf(buf1, "$n throws $p %s as hard as $e can!", dirs[dir]);
	act(buf, FALSE, ch, obj, 0, TO_CHAR);
	act(buf1, TRUE, ch, obj, 0, TO_ROOM);

	obj_to_room(obj, to_room);
	sprintf(buf, "$p is hurled in from the %s and falls to the ground at your feet!", dirs[rev_dir[dir]]);
	if (world[obj->in_room].people)
		act(buf, FALSE, 0, obj, 0, TO_ROOM);
	}


ACMD(do_catapult) {
	void disperse_resources(room_rnum room);
	void disassociate_building(room_rnum room);
	extern const char *dirs[];
	extern const int max_damage[];

	Creature c, next_c;
	Object catapult, o, next_o;
	struct empire_political_data *emp_pol = NULL;
	int dir, e;
	Resource rocks[2] = { {o_ROCK, 12}, END_RESOURCE_LIST };
	room_rnum to_room, rm;

	/* Find a 'pult */
	for (catapult = world[ch->in_room].contents; catapult; catapult = catapult->next_content)
		if (GET_OBJ_TYPE(catapult) == ITEM_CART && GET_OBJ_VAL(catapult, 2))
			break;

	skip_spaces(&argument);

	if (!catapult)
		msg_to_char(ch, "You don't even have a catapult.\r\n");
	else if (!*argument)
		msg_to_char(ch, "Which direction would you like to shoot?\r\n");
	else if (!has_resources(ch, rocks, FALSE))
		{ /* This line intentionally left blank */ }
	else if ((dir = parse_direction(argument)) == -1)
		msg_to_char(ch, "Which direction is that?\r\n");
	else if ((to_room = real_shift(ch->in_room, shift_dir[dir][0], shift_dir[dir][1])) == NOWHERE)
		msg_to_char(ch, "Unknown error.\r\n");
	else if (GET_OBJ_VAL(catapult, 2) > 1)
		msg_to_char(ch, "You must wait before shooting the catapult again.\r\n");
	else if (SECT(ch->in_room) == SECT_FOREST_3 || SECT(ch->in_room) == SECT_FOREST_4)
		msg_to_char(ch, "You can't aim through the trees!\r\n");
	else if (SECT(ch->in_room) == SECT_BUILDING || SECT(ch->in_room) == SECT_MULTI || SECT(ch->in_room) == SECT_MONUMENT_CLOSED || SECT(ch->in_room) == SECT_INSIDE)
		msg_to_char(ch, "You can't shoot from indoors.\r\n");
	else if (SECT(ch->in_room) == SECT_BARRIER)
		msg_to_char(ch, "You can't shoot from this close to the barrier.\r\n");
	else {
		if ((e = real_empire(world[to_room].owner)) != -1)
			emp_pol = find_relation(real_empire(GET_LOYALTY(ch)), e);
		if (e > 0 && (!emp_pol || !IS_SET(emp_pol->type, DIPL_WAR))) {
			msg_to_char(ch, "You can't attack that acre!\r\n");
			return;
			}
		extract_resources(ch, rocks, FALSE);
		sprintf(buf, "You shoot $p %s!", dirs[dir]);
		act(buf, FALSE, ch, catapult, 0, TO_CHAR);
		sprintf(buf, "$n shoots $p %s!", dirs[dir]);
		act(buf, FALSE, ch, catapult, 0, TO_ROOM);
		GET_OBJ_VAL(catapult, 2) = 2;	/* shot timer, 1 = ready to shoot */

		if (SHOULD_APPEAR(ch))
			appear(ch);

		if (SECT(to_room) == SECT_MULTI || SECT(to_room) == SECT_BUILDING) {
			if (++(world[to_room].damage) > (SECT(to_room) == SECT_MULTI ? 5 : max_damage[(int) world[to_room].type])) {
				disperse_resources(to_room);
				disassociate_building(to_room);
				if (world[to_room].people)
					act("The building is hit and crumbles!", FALSE, world[to_room].people, 0, 0, TO_CHAR | TO_ROOM);
				}
			else {
				if (world[to_room].people)
					act("The building is hit by something and shakes violently!", FALSE, world[to_room].people, 0, 0, TO_CHAR | TO_ROOM);
				for (rm = MAP_SIZE; rm <= top_of_world; rm++)
					if (HOME_ROOM(rm) == to_room && world[rm].people)
						act("The building is hit by something and shakes violently!", FALSE, world[rm].people, 0, 0, TO_CHAR | TO_ROOM);
				return;
				}
			}
		else {
			if (SECT(to_room) == SECT_WELL || SECT(to_room) == SECT_BARRIER || SECT(to_room) == SECT_FOUNTAIN) {
				disperse_resources(to_room);
				disassociate_building(to_room);
				}
			sprintf(buf, "A huge object is hurled in from %s!", dirs[rev_dir[dir]]);
			if (world[to_room].people)
				act(buf, FALSE, world[to_room].people, 0, 0, TO_CHAR | TO_ROOM);
			}

		/* if we got this far, we need to hurt some people */
		for (c = world[to_room].people; c; c = next_c) {
			next_c = c->next_in_room;
			if (!number(0, 1))
				msg_to_char(c, "You leap out of the way!\r\n");
			else {
				msg_to_char(c, "You are hit and killed!\r\n");
				if (!IS_NPC(c)) {
					mortlog(0, "%s has been killed by a catapult at (%d, %d)!", PERS(c, c, 1), X_COORD(c->in_room), Y_COORD(c->in_room));
					syslog(0, TRUE, "DEATH: %s has been killed by a catapult at (%d, %d)", GET_NAME(c), X_COORD(c->in_room), Y_COORD(c->in_room));
					}
				die(c);
				}
			}

		for (o = world[to_room].contents; o; o = next_o) {
			next_o = o->next_content;
			if (!number(0, 1))
				extract_obj(o);
			}
		WAIT_STATE(ch, 5 RL_SEC);
		}
	}


ACMD(do_execute) {
	Creature victim;

	one_argument(argument, arg);

	if (!*arg)
		msg_to_char(ch, "Execute whom?\r\n");
	else if (!(victim = get_char_vis(ch, arg, FIND_CHAR_ROOM)))
		msg_to_char(ch, NOPERSON);
	else if (victim == ch)
		msg_to_char(ch, "Seek professional help.\r\n");
	else if (IS_NPC(victim))
		msg_to_char(ch, "You can only execute people.\r\n");
	else if (GET_POS(victim) >= POS_SLEEPING && !IS_INJURED(victim, INJ_TIED))
		act("You need to knock $M out or tie $M up.", FALSE, ch, 0, victim, TO_CHAR);
	else
		perform_execute(ch, victim, -1, DAM_BASHING);
	}


ACMD(do_stake) {
	Creature victim;
	Object stake;

	one_argument(argument, arg);

	if (!*arg)
		msg_to_char(ch, "%stake whom?\r\n", subcmd ? "Uns" : "S");
	else if (!(victim = get_char_vis(ch, arg, FIND_CHAR_ROOM)))
		msg_to_char(ch, NOPERSON);
	else if (IS_GOD(victim) || IS_IMMORTAL(victim))
		msg_to_char(ch, "You can't tie up a god!\r\n");
	else if (!subcmd && IS_INJURED(victim, INJ_STAKED))
		act("$E is already staked!", FALSE, ch, 0, victim, TO_CHAR);
	else if (subcmd && !IS_INJURED(victim, INJ_STAKED))
		act("$E isn't even staked!", FALSE, ch, 0, victim, TO_CHAR);
	else if (IS_INJURED(victim, INJ_STAKED)) {
		act("You unstake $N.", FALSE, ch, 0, victim, TO_CHAR);
		act("$n unstakes you!", FALSE, ch, 0, victim, TO_VICT | TO_SLEEP);
		act("$n unstakes $N.", FALSE, ch, 0, victim, TO_NOTVICT);
		if (GET_DAMAGE(victim) < 7)
			GET_POS(victim) = POS_RESTING;
		REMOVE_BIT(INJURY_FLAGS(victim), INJ_STAKED);
		obj_to_char(read_object(o_STAKE, VIRTUAL), ch);
		}
	else if (!can_fight(ch, victim))
		act("You can't stake $M!", FALSE, ch, 0, victim, TO_CHAR);
	else if (!(stake = get_obj_in_list_num(real_object(o_STAKE), ch->carrying)))
		msg_to_char(ch, "You don't have a stake!\r\n");
	else {
		WAIT_STATE(ch, PULSE_VIOLENCE * 2);

		if (AWAKE(victim)) {
			int to_hit, to_dodge = 0;

			to_hit = ww_dice(GET_DEXTERITY(ch) + GET_MELEE(ch), 6 + GET_BLOCK(victim));
			to_dodge = ww_dice(GET_DEXTERITY(victim) + GET_DODGE(victim), 6);

			/* decide whether this is a hit or a miss */
			if (to_hit <= to_dodge) {
				act("You lunge at $N with $p, but miss!", FALSE, ch, stake, victim, TO_CHAR);
				act("$n lunges at you with $p, but misses!", FALSE, ch, stake, victim, TO_VICT);
				act("$n lunges at $N with $p, but misses!", FALSE, ch, stake, victim, TO_NOTVICT);
				return;
				}
			}

		act("You jab $p through $N's heart!", FALSE, ch, stake, victim, TO_CHAR);
		act("$n jabs $p through your heart!", FALSE, ch, stake, victim, TO_VICT | TO_SLEEP);
		act("$n jabs $p through $N's heart!", FALSE, ch, stake, victim, TO_NOTVICT);

		if (GET_DISC(victim, DISC_PROTEAN) >= 8 && GET_BLOOD(victim) > 3) {
			GET_BLOOD(victim) -= 2;

			if (ww_dice(GET_WILLPOWER(ch), 8) > 0) {
				act("The stake ejects violently from $n's chest!", FALSE, victim, 0, 0, TO_ROOM);
				msg_to_char(victim, "You eject the stake violently from your chest!\r\n");
				msg_to_char(ch, "You are momentarily stunned!\r\n");
				WAIT_STATE(ch, PULSE_VIOLENCE * 4);
				return;
				}
			}

		SET_BIT(INJURY_FLAGS(victim), INJ_STAKED);
		if (GET_DAMAGE(victim) >= 7) {
			GET_DAMAGE(victim) = 6;
			GET_POS(victim) = POS_STUNNED;
			}
		extract_obj(stake);

		if (!IS_VAMPIRE(victim)) {
			if (!IS_NPC(victim)) {
				death_log(victim, ch, ATTACK_EXECUTE);
				add_lore(ch, LORE_PLAYER_KILL, GET_IDNUM(victim));
				add_lore(victim, LORE_PLAYER_DEATH, GET_IDNUM(ch));
				}
			die(victim);
			}
		}
	}