mud_dist/area/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David   *
 *  Love, Guilherme 'Willie' Arnold, and Mitchell Tse.                     *
 *                                                                         *
 *  In order to use any part of this Envy Diku Mud, you must comply with   *
 *  the original Diku license in 'license.doc', the Merc license in        *
 *  'license.txt', as well as the Envy license in 'license.nvy'.           *
 *  In particular, you may not remove either of these copyright notices.   *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/*$Id: fight.c,v 1.121 2005/04/10 16:29:00 tyrion Exp $*/

#if defined( macintosh )
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"

extern char* target_name;

/*
 * Local functions.
 */
int     damclass_adjust      args( ( CHAR_DATA *victim, int dam, int sn) );
void	damclass_shield_weaken args( ( CHAR_DATA *vic, int dam, int sn) );
bool	check_dodge	     args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
bool	check_enhanced_dodge args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
void	check_killer	     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool	check_parry	     args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
bool	check_enhanced_parry args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
bool	check_shield_block   args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount ) );
void	dam_message	     args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam,
				    int dt ) );
void	death_cry	     args( ( CHAR_DATA *ch ) );
void	group_gain	     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
int	xp_compute	     args( ( CHAR_DATA *gch, CHAR_DATA *victim ) );
int     damreduce 	     args( ( CHAR_DATA *ch,  CHAR_DATA *victim, int dam, int dt ) );

bool	is_safe		     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
bool    is_wielding_poisoned args( ( CHAR_DATA *ch ) );
bool    is_wielding_flaming  args( ( CHAR_DATA *ch ) );
bool    is_wielding_chaos    args( ( CHAR_DATA *ch ) );
bool    is_wielding_icy      args( ( CHAR_DATA *ch ) );
bool    is_wielding_sparking args( ( CHAR_DATA *ch ) );
bool    is_wielding_dispelling args( ( CHAR_DATA *ch ) );
void	make_corpse	     args( ( CHAR_DATA *ch ) );
bool	check_hit		 args( ( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount, bool dual ) );
void	one_hit		     args( ( CHAR_DATA *ch, CHAR_DATA *victim,
				    int dt ) );
void	one_dual	     args( ( CHAR_DATA *ch, CHAR_DATA *victim,
				    int dt ) );
void	raw_kill	     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void	set_fighting	     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void	disarm		     args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
void    item_damage             args( ( CHAR_DATA *ch, int dam ) );
void    use_magical_item     args( ( CHAR_DATA *ch ) );
void    miss_message	     args( ( CHAR_DATA* ch, CHAR_DATA* victim, bool dual ) );
bool	can_use_attack	     args( ( int attack_num, CHAR_DATA* ch ) );
bool	can_dual			 args( ( CHAR_DATA* ch ) );


int     dam_class_value; /* global damclass value. ewwy */

/*
 * Control the fights going on.
 * Called periodically by update_handler.
 * Slightly less efficient than Merc 2.2.  Takes 10% of
 *  total CPU time.
 */
void violence_update( void )
{
    CHAR_DATA *ch;
    CHAR_DATA *victim;
    CHAR_DATA *rch;
    bool       mobfighting;
    int stun;

    for ( ch = char_list; ch; ch = ch->next )
    {
	if ( !ch->in_room || ch->deleted )
	    continue;

	for (stun = 0; stun < STUN_MAX; stun++)
	{
	  if ( IS_STUNNED( ch, stun ) )
	    ch->stunned[stun]--;
	}

	if ( ( victim = ch->fighting ) )
	{
	    if ( IS_AWAKE( ch ) && ch->in_room == victim->in_room )
	        multi_hit( ch, victim, TYPE_UNDEFINED );
	    else
	        stop_fighting( ch, FALSE );
	    continue;
	}


	if ( IS_AFFECTED( ch, AFF_BLIND )
	    || ( IS_NPC( ch ) && ch->pIndexData->pShop ) )
	    continue;

	/* Ok. So ch is not fighting anyone.
	 * Is there a fight going on?
	 */

	mobfighting = FALSE;

	for ( rch = ch->in_room->people; rch; rch = rch->next_in_room )
	{
	    if ( rch->deleted
		|| !IS_AWAKE( rch )
		|| !( victim = rch->fighting ) )
	        continue;

	    if ( !IS_NPC( ch )
		&& ( !IS_NPC( rch ) || IS_AFFECTED( rch, AFF_CHARM ) )
		&& is_same_group( ch, rch )
		&& IS_NPC( victim ) )
		break;

	    if ( IS_NPC( ch )
		&& IS_NPC( rch )
		&& !IS_NPC( victim ) )
	    {
		mobfighting = TRUE;
		break;
	    }
	}

	if ( !victim || !rch )
	    continue;

	/*
	 * Now that someone is fighting, consider fighting another pc
	 * or not at all.
	 */
	if ( mobfighting )
	{
	    CHAR_DATA *vch;
	    int        number;

	    number = 0;
	    for ( vch = ch->in_room->people; vch; vch = vch->next_in_room )
	    {
		if ( can_see( ch, vch )
		    && ( vch->level > 5 )
		    && is_same_group( vch, victim )
		    && number_range( 0, number ) == 0 )
		{
		    victim = vch;
		    number++;
		}
	    }

	    if ( ( rch->pIndexData != ch->pIndexData && number_bits( 3 ) != 0 )
		|| ( IS_GOOD( ch ) && IS_GOOD( victim ) )
		|| abs( victim->level - ch->level ) > 3 )
	        continue;
	}
        mprog_hitprcnt_trigger( ch, victim );
        mprog_fight_trigger( ch, victim );
	multi_hit( ch, victim, TYPE_UNDEFINED );

    }

    return;
}

/*
 * Do one group of attacks.
 */
void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    bool berserk;
    bool hit;
    bool dual_atk;
    int chance;
    int chance2;
    int chance3;
    int attack = 0;


    if (!IS_NPC(ch) && ch->pcdata->craft_timer)
   	destroy_craft(ch, FALSE);

    if ( IS_NPC( ch ) )
    {
      mprog_hitprcnt_trigger( ch, victim );
      mprog_fight_trigger( ch, victim );
    }


    if ( ( IS_AFFECTED2( ch, AFF_CONFUSED ) )
       && number_percent ( ) < 30 )
    {
      act(AT_YELLOW, "$n looks around confused at what's going on.", ch, NULL, NULL, TO_ROOM );
      send_to_char( AT_YELLOW, "You stand confused.\n\r", ch );
      return;
    }

    dual_atk = FALSE;
    hit = FALSE;

    /* FIRST ATTACK */
    one_hit( ch, victim, dt );

    if ( ch->fighting != victim || dt == skill_lookup("backstab") )
	return;
    if ( ch->fighting != victim || dt == skill_lookup("assassinate") )
	return;
    if ( ch->fighting != victim || dt == skill_lookup("double backstab") )
	return;
    if ( ch->fighting != victim || dt == skill_lookup("leap of torfi") )
  	return;
    if ( ch->fighting != victim || dt == skill_lookup("triple backstab") )
	return;


    chance = number_percent( );
    chance2 = number_percent( ) / 2;
    chance3 = number_percent( );
    berserk = FALSE;

    if(IS_AFFECTED2(ch, AFF_BERSERK) || IS_AFFECTED3(ch, AFF_BLOODTHIRSTY) )
    {
	berserk = TRUE;
    }

	for (attack = 2; attack <= MAX_ATTACKS; attack++)
	{
		hit       = FALSE;
		dual_atk  = FALSE;

		if (victim->position == POS_DEAD || victim->deleted)
			return;

		if ( can_use_attack( attack, ch ) )
		{
			if ( ( check_hit(ch, victim, attack, FALSE) ) || berserk )
			{
				hit  = TRUE;
				one_hit( ch, victim, dt );
				if ( ch->fighting != victim )
				{
					return;
				}
			}
			else if ( can_dual( ch ) && (dual_atk  = TRUE) && check_hit(ch, victim, attack, TRUE) )
			{
				hit  = TRUE;
				one_dual( ch, victim, dt );
				if ( ch->fighting != victim )
				{
					return;
				}
			}

			if (!hit)
				miss_message( ch, victim, dual_atk  );
		    
		}
	}

    hit  = FALSE;
    dual_atk  = FALSE;

    /* HASTE ATTACK */
    if( is_affected( ch, skill_lookup("quickness") ) || IS_AFFECTED( ch, AFF_HASTE ) )
    {
	if (victim->position == POS_DEAD || victim->deleted )
		return;

        if ( ( check_hit(ch, victim, 1, FALSE) ) || berserk )
        {
			hit = TRUE;
            one_hit( ch, victim, dt );
            if ( ch->fighting != victim )
            {
                return;
            }
        }
        else if (  can_dual( ch ) && (dual_atk  = TRUE) && check_hit(ch, victim, 1, TRUE) )
        {
			hit = TRUE;
            one_dual( ch, victim, dt );
            if ( ch->fighting != victim )
            {
                return;
			}
		}

		if (!hit)
			miss_message(ch, victim, dual_atk );
    }

    hit  = FALSE;
    dual_atk  = FALSE; 


    if (victim->position == POS_DEAD || victim->deleted )
	return;

    /* WILDERNESS MASTERY ATTACK */
    if( can_use_skspell( ch, skill_lookup("wilderness mastery") ) )
    {
	if( !IS_NPC( ch ) )
        {
		if( ( number_percent( ) < ( ch->pcdata->learned[skill_lookup("wilderness mastery")] / 10 ) ) && IS_OUTSIDE( ch ) && IS_IN_NATURE( ch ) )
		{
			update_skpell( ch, skill_lookup("wilderness mastery"), 0 );
			if ( ( check_hit(ch, victim, 1, FALSE) ) || berserk )
			{
				hit = TRUE;
				one_hit( ch, victim, dt );
				if ( ch->fighting != victim )
				{
					return;
				}
			}
			else if (  can_dual( ch ) && (dual_atk  = TRUE) && check_hit(ch, victim, 1, TRUE) )
			{
				hit = TRUE;
				one_dual( ch, victim, dt );
				if ( ch->fighting != victim )
				{
					return;
				}
			
			}

			if (!hit)
				miss_message( ch, victim, dual_atk  );
	    	}
	}
    }


    return;
}

/*
	Logic to determine if a character hits his victim and deals damage to him.
		ch is the character trying to hit
		victim is the character being hit
		attackCount is which attack this is a check for, first, second third, etc.
		dual is whether or not this is a check for your main attack, or the dualed.
*/
bool check_hit( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount, bool dual ) {
	/* now defined in merc.h
	int MAX_ATTACKS = 8;
	*/
	int toHit = 0;
	int chDex;
	int victimDex;
	char buf[1000];
	OBJ_DATA* wield= NULL;
	OBJ_DATA* ammo = NULL;

	if (!dual)
		wield = get_eq_char( ch, WEAR_WIELD );
	else
		wield = get_eq_char( ch, WEAR_WIELD_2 );

	if ( !IS_NPC(ch) && wield && wield->value[3] == flag_value( weapon_flags, "shot" ) )
	{
		if (wield->value[0] == flag_value( ammo_flags, "arrow" ) )
			ammo = find_arrows( ch );
		else if (wield->value[0] == flag_value( ammo_flags, "bullet" ) )
			ammo = find_bullets( ch );
		else if (wield->value[0] == flag_value( ammo_flags, "bolt" ) )
			ammo = find_bolts( ch );
		else
			ammo = NULL;

		if (ammo)
		{
		/* I don't think this needs to be here, it is causing you to lose double ammo during combat rounds - Tyrion */
		/* Leave it here. Remove it from one_hit. This will take care of 99% of ammo checks - Ahsile */
			if (!--ammo->value[0])
			{
				sprintf( buf, "%s has just run out of shots!\n\r", ammo->short_descr );
				send_to_char( AT_RED, buf, ch );
				extract_obj( ammo );
			}
		}
	}


	chDex = get_curr_dex(ch);
	victimDex = get_curr_dex(victim);

	toHit = GET_HITROLL(ch);

	toHit += (chDex - victimDex) * 20;

	if (!IS_NPC(ch)) {
		if ( can_use_skspell(ch, skill_lookup("enhanced hit")) ) {
			toHit += ( ch->pcdata->learned[skill_lookup("enhanced hit")] / 10 );
			update_skpell( ch, skill_lookup("enhanced hit"), 0 );
		}
		if ( can_use_skspell(ch, skill_lookup("enhanced hit two")) ) {
			toHit += ( ch->pcdata->learned[skill_lookup("enhanced hit two")] / 10 );
			update_skpell( ch, skill_lookup("enhanced hit two"), 0 );
		}
	}
	else {
		toHit += 100;
	};


	toHit += number_range((MAX_ATTACKS - 2)*50, (MAX_ATTACKS)*50);

	toHit = toHit*(16-attackCount)/16;

	/* Do all the dodge/parry/shield block checks here. */
	sprintf(buf, "%s's hitroll value for attack num %d is %d", ch->name, attackCount, toHit);
/*if(!IS_NPC(ch))	bug(buf, 0);*/

	/* If this is the dual attack, but they don't have enhanced dual, half the chance to hit */
	if (dual)
	{
		if (!can_use_skspell(ch, skill_lookup("enhanced dual"))) 
		{
			toHit /= 2;
		}
		else
		{
			update_skpell( ch, skill_lookup("enhanced dual"), 0 );
		}
	}

	if ( number_percent() > toHit/10 ) {
		/*
			sprintf(buf, "Attack #: %d", attackCount);
			bug(buf, 0);
		    if ( IS_SET( ch->act, PLR_COMBAT ) )
				act(AT_GREEN, "You attack $N, but miss.", ch, NULL, victim, TO_CHAR    );
			if ( IS_SET( victim->act, PLR_COMBAT ) )
				act(AT_GREEN, "$n attacks you, but misses.",  ch, NULL, victim, TO_VICT    );
		*/
		return FALSE;
	}

	if (check_parry( ch, victim, attackCount ) )
		return FALSE;
	if (check_shield_block( ch, victim, attackCount ))
		return FALSE;
	if (check_dodge( ch, victim, attackCount ))
		return FALSE;
	if (check_enhanced_parry( ch, victim, attackCount ) )
		return FALSE;
	if (check_enhanced_dodge( ch, victim, attackCount ) )
		return FALSE;

	return TRUE;
}




/*
 * Hit one guy once.
 */
void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    OBJ_DATA *wield;
    OBJ_DATA *dual;
    char      buf [ MAX_STRING_LENGTH ];
    int       dam;
    int	      val = 0;
    int	      ammo_bonus = 0;
    int       divisor= 1; /* this is to cut firearm dmg down if no ammo is present */

    /*
     * Can't beat a dead char!
     * Guard against weird room-leavings.
     */
    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
		return;

    if ( IS_STUNNED( ch, STUN_NON_MAGIC ) ||
	 IS_STUNNED( ch, STUN_TOTAL ) )
      return;

    /*
     * Figure out the type of damage message.
     */
    wield = get_eq_char( ch, WEAR_WIELD );
    dual  = get_eq_char( ch, WEAR_WIELD_2  );
    if ( dt == TYPE_UNDEFINED )
    {
	dt = TYPE_HIT;
	if ( wield && wield->item_type == ITEM_WEAPON )
	    dt += wield->value[3];
    }

    /*
     * Hit.
     * Calc damage.
     */
         if ( IS_AFFECTED( victim, AFF_FIRESHIELD ) )
           {
             if ( number_percent( ) < 50 )
	     {
			damage( victim, ch, spell_fireball ( skill_lookup("fireball"), 25, victim, ch ), skill_lookup("fireball"));
	     }
           }
         if ( IS_AFFECTED4( victim, AFF_LEAF_SHIELD ) )
           {
             if ( number_percent( ) < 50 )
             {
                 damage( victim, ch, spell_leaf_strike ( skill_lookup("leaf strike"), 25, victim, ch ), skill_lookup("leaf strike"));
             }
           }

         if ( IS_AFFECTED3( victim, AFF_DEMONSHIELD ) )
           {
             if ( number_percent( ) < 30 )
	     {
		 damage( victim, ch, spell_demonfire ( skill_lookup("demonfire"), 25, victim, ch ), skill_lookup("demonfire"));
	     }
 }
         if ( IS_AFFECTED3( victim, AFF_ACIDSHIELD ) )
           {
             if ( number_percent( ) < 75 )
		 damage( victim, ch, spell_acid_blast ( skill_lookup("acid blast"), 25, victim, ch ), skill_lookup("acid blast"));

           }

	 if ( IS_AFFECTED3( victim, AFF_AURA_ANTI_MAGIC ) )
	   {
	     if ( number_percent ( ) < 25 )
	     {
		 spell_dispel_magic (skill_lookup("dispel magic"), 80, victim, ch );
	     }
	   }
         if ( IS_AFFECTED3( victim, AFF_COFIRE ) )
           {
             if ( number_percent( ) < 50 )
	     {
		 damage( victim, ch, spell_fireball ( skill_lookup("fireball"), 25, victim, ch ), skill_lookup("fireball"));
	     }
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED( victim, AFF_ICESHIELD ) )
           {
             if ( number_percent( ) < 40 ) 
	     {
		 damage( victim, ch, spell_iceball ( skill_lookup("iceball"), 40, victim, ch ), skill_lookup("iceball"));
	     }
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED3(victim, AFF_BLOODSHIELD ) )
	   {
	     if ( number_percent( ) < 40 )
	     {
		   damage( victim, ch, spell_blood_gout( skill_lookup("blood gout"), 40, victim, ch ), skill_lookup("blood gout"));
	     }
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED2(victim, AFF_UNHOLY_STRENGTH ) )
	   {
	     if ( number_percent( ) < 40 )
	     {
		   damage( victim, ch, spell_blood_gout( skill_lookup("blood gout"), 40, victim, ch ), skill_lookup("blood gout"));
	     }
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) )
           {
             if ( number_percent( ) < 50 )
	     {
		 damage( victim, ch, spell_lightning_bolt ( skill_lookup("lightning bolt"), 35, victim, ch ), skill_lookup("lightning bolt"));
	     }
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED4( victim, AFF_ESSENCE_OF_GAIA ) )
	   {
	     if ( ( number_percent( ) < 40 ) )
	     {
		 damage( victim, ch, spell_lightning_bolt( skill_lookup("lightning bolt"), 35, victim, ch ), skill_lookup("lightning bolt") );
	     }
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED( victim, AFF_CHAOS ) )
           {
             if ( number_percent( ) < 40 )
	     {
		 damage( victim, ch, spell_energy_drain ( skill_lookup("energy drain"), 40, victim, ch ), skill_lookup("energy drain"));
	     }
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED( victim, AFF_INERTIAL ) )
           {
             if ( number_percent( ) < 35 )
	     {
	       damage( victim, ch, spell_psionic_blast ( skill_lookup("psionic blast"), 25, victim, ch ), skill_lookup("psionic blast"));
	     }
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED2( victim, AFF_GHOST_SHIELD ) )
	   {
	     if ( number_percent( ) < 50 )
	       damage( victim, ch, spell_harm ( skill_lookup("harm"), 35, victim, ch ), skill_lookup("harm"));
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
        return;
        if ( IS_AFFECTED3( victim, AFF_SATANIC_INFERNO ) )
           {
             if ( number_percent( ) < 40 )
	     {
               damage( victim, ch, spell_unholy_fires ( skill_lookup("unholy fires"), 35, victim, ch ), skill_lookup("unholy fires"));
	     }
           }
 if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED2( victim, AFF_SHADOW_IMAGE ) )
	   {
	     if ( number_percent( ) < 20 )
	       damage( victim, ch, spell_energy_drain ( skill_lookup("energy drain"), 35, victim, ch ),skill_lookup("energy drain"));
	   }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED2( victim, AFF_BLADE ) )
           {
             if ( number_percent( ) < 40 )
                damage( victim, ch, spell_daggers_of_pain ( skill_lookup("daggers of pain"), 25, victim, ch ),skill_lookup("daggers of pain"));
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
        return;
        if ( IS_AFFECTED4( victim, AFF_ANGELIC_AURA ) )
           {
             if ( number_percent( ) < 40 )
                damage( victim, ch, spell_holy_fires ( skill_lookup("holy fires"), 40, victim, ch ),skill_lookup("holy fires"));
           }  
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
        return;
        if ( IS_AFFECTED4( victim, AFF_LIQUID_SKIN ) )
           {
             if ( number_percent( ) < 35 )
               damage( victim, ch, spell_waterspike ( skill_lookup("waterspike"), 30, victim, ch ),skill_lookup("waterspike"));
           }

  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED4( victim, AFF_ETHEREAL_WOLF ) )
	   {
	     if ( number_percent( ) < 40 )
		spell_ethereal_wolf_bite ( skill_lookup("ethereal wolf bite"), 35, victim, ch );
	   }

  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
	if ( IS_AFFECTED4( victim, AFF_ETHEREAL_SNAKE ) )
	   {
	     if ( number_percent( ) < 40 )
		spell_ethereal_snake_strike ( skill_lookup("ethereal snake strike"), 35, victim, ch );
	   }

  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
        return;
        if ( IS_AFFECTED3( victim, AFF_RANDOMSHIELD ) )
           {
	     int choice = number_range(1, 7);
             if ( number_percent( ) < 40 )
	     switch( choice )
	     {
		default:
		    damage( victim, ch, spell_fireball( skill_lookup("fireball"), 25, victim, ch ),skill_lookup("fireball"));
		    break;
		case 1:
		    damage( victim, ch, spell_fireball( skill_lookup("fireball"), 25, victim, ch ),skill_lookup("fireball"));
		    break;
		case 2:
		    damage( victim, ch, spell_energy_drain ( skill_lookup("energy drain"), 25, victim, ch ),skill_lookup("energy drain"));
		    break;
		case 3:
		    damage( victim, ch, spell_harm ( skill_lookup("harm"), 25, victim, ch ),skill_lookup("harm"));
		    break;
		case 4:
		    damage( victim, ch, spell_unholy_fires ( skill_lookup("unholy fires"), 25, victim, ch ),skill_lookup("unholy fires"));
		    break;
		case 5:
		    damage( victim, ch, spell_lightning_bolt ( skill_lookup("lightning bolt"), 25, victim, ch ),skill_lookup("lightning bolt"));
		    break;
		case 6:
		    damage( victim, ch, spell_daggers_of_pain ( skill_lookup("daggers of pain"), 50, victim, ch ),skill_lookup("daggers of pain"));
		    break;
                case 7:
                    damage( victim, ch, spell_waterspike ( skill_lookup("waterspike"), 25, victim, ch ),skill_lookup("waterspike"));
                    break;
	     }
           }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
        if ( IS_AFFECTED2( victim, AFF_IMAGE ) && victim->clan == 3 )
	    {
	      AFFECT_DATA *iaf;

	      for ( iaf = victim->affected2; iaf; iaf = iaf->next )
	      {
		if ( iaf->deleted )
		  continue;

		if ( iaf->type == skill_lookup("image") )
		{
		  if ( number_percent( ) < (iaf->modifier * 7) )
		    spell_curse(skill_lookup("curse"),
					(iaf->modifier * 4), victim, ch );
		  break;
		}
	      }
	    }
  if ( !victim || victim->position == POS_DEAD || ch->in_room != victim->in_room )
        return;

/* bow stuff here */

	if (!IS_NPC(ch) && wield &&  wield->value[3] == flag_value( weapon_flags, "shot" ) )
	{
		OBJ_DATA* ammo = NULL;
		if ( IS_SET(wield->extra_flags2, ITEM_MAGIC_SHOT) )
			ammo = (OBJ_DATA*) 1; // fake out
		else if (wield->value[0] ==  flag_value( ammo_flags, "arrow"))
			ammo = 	find_arrows( ch );
		else if (wield->value[0] ==  flag_value( ammo_flags, "bullet"))
			ammo = 	find_bullets( ch );
		else if (wield->value[0] == flag_value( ammo_flags, "bolt"))
			ammo = 	find_bolts( ch );
		else
			ammo = NULL;

		if (!ammo)
		{
			dt = TYPE_HIT + flag_value( weapon_flags, "crush" ); /* force bludg damage */
			divisor 	= 2;  /* half damage if you have no ammo */
			ammo_bonus 	= 0; /* no ammo bonus */
		} else
		{
			if ((int) ammo == 1)
			{
				ammo_bonus = number_range( ch->level, ch->level / 2 );
				val = DAMCLASS_MAGIC;
			} else
			{
				val = ammo->value[1];
				ammo_bonus = number_range( ammo->value[2], ammo->value[3] );	
			}
			divisor    = 1; /* make sure damage = 100% */
			
		}
	} else
	{
		divisor = 1;
		ammo_bonus = 0;
	}


/* end bow stuff */


    if ( IS_NPC( ch ) )
    {
	dam = number_range( ch->level / 3, ch->level * 3 / 2 );
	if ( wield )
	    dam += dam / 3;
    }
    else
    {
	if ( wield )
	{
	    dam  = number_range( wield->value[1], wield->value[2] );
	    dam += ammo_bonus;
	    dam  = (int) (dam / divisor); /* only necessary for firearms */
	}
	else
	{
	    if ( ch->class == CLASS_MONK || ch->multied == CLASS_MONK || ch->class == CLASS_WEREWOLF || ch->multied == CLASS_WEREWOLF )
	    {
		dam = number_range( 1, ( ch->level / 20 ) + 4 ) * race_table[ ch->race ].size;
	    }
	    else
	    {
		dam = number_range( 1, 4 ) * race_table[ ch->race ].size;
	    }
	}
	if ( wield && dam > 1000 && !IS_IMMORTAL(ch) )
	{
	    sprintf( buf, "One_hit dam range > 1000 from %d to %d",
		    wield->value[1], wield->value[2] );
	    bug( buf, 0 );
	    if ( wield->name )
	      bug( wield->name, 0 );
	}
    }

    /*
     * Bonuses.
     */
    dam += GET_DAMROLL( ch );

    if ( ( ch->class == CLASS_MONK || ch->multied == CLASS_MONK ) && !wield && !dual )
        dam += ch->level/2;
    if ( ( ch->class == CLASS_WEREWOLF || ch->multied == CLASS_WEREWOLF ) && !wield && !dual )
	dam += ch->level/2 + 10;
    /* VAMP Mods */
    if (ch->class == CLASS_VAMPIRE || ch->multied == CLASS_VAMPIRE)
    {
	if (time_info.hour < 6 || time_info.hour >= 19)
	{
	    dam += dam / 3;
	}
	else
	{
	    dam -= dam / 3;
	}
    }

    if ( wield && IS_SET( wield->extra_flags, ITEM_POISONED ) )
        dam += dam / 16;
    if ( wield && IS_SET( wield->extra_flags, ITEM_FLAME ) )
        dam += dam / 16;
     if ( wield && IS_SET( wield->extra_flags, ITEM_CHAOS ) )
        dam += dam / 16;
    if ( wield && IS_SET( wield->extra_flags, ITEM_ICY   ) )
        dam += dam / 16;
    if ( wield && IS_SET( wield->extra_flags2, ITEM_SPARKING ) )
        dam += dam / 16;
/*     if ( wield && IS_SET( wield->extra_flags, ITEM_ACID ) )
        dam += dam / 16;
*/
  if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage")] > 0 )
    {
	dam += dam / 2 * ch->pcdata->learned[skill_lookup("enhanced damage")] / 1000;
	update_skpell( ch, skill_lookup("enhanced damage"), 0 );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage two")] > 0 )
    {
        dam += dam / 6 * ch->pcdata->learned[skill_lookup("enhanced damage two")] / 1000;
	update_skpell( ch, skill_lookup("enhanced damage two"), 0 );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage three")] > 0 )
    {
        dam += dam / 6 * ch->pcdata->learned[skill_lookup("enhanced damage three")] / 1600;
	update_skpell( ch, skill_lookup("enhanced damage three"), 0 );
    }
    if ( !IS_AWAKE( victim ) )
	dam *= 2;
    if ( dt == skill_lookup( "backstab" ) )
    {
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );
    }
    if ( dt == skill_lookup( "assassinate" ) )
    {
	dam = (int)(dam * (1.65 * (2 + UMIN( ( ch->level / 8) , 4 ) ) ));
    }
    if ( dt == skill_lookup( "leap of torfi" ) )
    {
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );
        if (!str_cmp(ch->name,"Torfi"))
	{
	   dam = (int)(dam * 1.1);
	}
    }
    if ( dt == skill_lookup( "double backstab" ) )
    {
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );
    }

    if ( dt == skill_lookup( "triple backstab" ) )
    {
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );
    }

    if ( dam <= 0 )
	dam = 1;

    if (!IS_NPC(victim))
    	dam = damreduce( ch, victim, dam, dt );    

    dam_class_value = val;
    damage( ch, victim, dam, dt );
    dam_class_value = 0;

    tail_chain( );
    return;
}

void one_dual( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
    OBJ_DATA *wield;
    OBJ_DATA *dual;
    char      buf [MAX_STRING_LENGTH ];
    int       dam;
    int	      val = 0;
    int	      divisor = 1;
    int	      ammo_bonus = 0;

    /*
     * Can't beat a dead char!
     * Guard against weird room-leavings.
     */
    if (!get_eq_char ( ch, WEAR_WIELD_2 ) && ( IS_SET( race_table[ch->race].race_abilities,
			 RACE_WEAPON_WIELD ) ) )
       return;
    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;

    if ( IS_STUNNED( ch, STUN_NON_MAGIC ) ||
	 IS_STUNNED( ch, STUN_TOTAL ) )
      return;

    /*
     * Figure out the type of damage message.
     */
    wield = get_eq_char( ch, WEAR_WIELD_2 );
    dual = get_eq_char( ch, WEAR_WIELD );
    if ( dt == TYPE_UNDEFINED )
    {
	dt = TYPE_HIT;
	if ( wield && wield->item_type == ITEM_WEAPON )
	    dt += wield->value[3];
    }


/* bow stuff here */

	if ( !IS_NPC( ch) && wield && wield->value[3] == flag_value( weapon_flags, "shot" ) )
	{
		OBJ_DATA* ammo = NULL;
		if (wield->value[0] ==  flag_value( ammo_flags, "arrow"))
			ammo = 	find_arrows( ch );
		else if (wield->value[0] ==  flag_value( ammo_flags, "bullet"))
			ammo = 	find_bullets( ch );
		else if (wield->value[0] == flag_value( ammo_flags, "bolt"))
			ammo = 	find_bolts( ch );
		else
			ammo = NULL;	
	
		if (!ammo)
		{
			dt = TYPE_HIT + flag_value( weapon_flags, "crush" ); /* force bludg damage */
			divisor 	= 2;  /* half damage if you have no ammo */
			ammo_bonus 	= 0; /* no ammo bonus */
		} else
		{
			val 	   = ammo->value[1];
			divisor    = 1; /* make sure damage = 100% */
			ammo_bonus = number_range( ammo->value[2], ammo->value[3] );			
			if (!--ammo->value[0])
			{
				sprintf(buf, "You have just run out of %s!\n\r", ammo->short_descr);
				send_to_char(AT_RED, buf, ch );
				extract_obj( ammo );
			}
		}
	} else
	{
		divisor = 1;
		ammo_bonus = 0;
	}


/* end bow stuff */


    /*
     * Hit.
     * Calc damage.
     */

    if ( IS_NPC( ch ) )
    {
	dam = number_range( ch->level / 3, ch->level * 3 / 2 );
	if ( wield )
	    dam += dam / 3;
    }
    else
    {
        if ( wield )
        {
            dam  = number_range( wield->value[1], wield->value[2] );
	    dam += ammo_bonus;
	    dam  = (int) (dam / divisor);
        }
        else
        {
	    if ( ch->class == CLASS_MONK || ch->multied == CLASS_MONK || ch->class == CLASS_WEREWOLF || ch->multied == CLASS_WEREWOLF )
	    {
		dam = number_range( 1, (ch->level / 20 ) + 4 ) * race_table[ ch->race ].size;
	    }
	    else
	    {
		dam = number_range( 1, 4 ) * race_table[ ch->race ].size;
	    }
	}
	if ( wield && dam > 1000 && !IS_IMMORTAL(ch) )
	{
	    sprintf( buf, "One_hit dam range > 1000 from %d to %d",
		    wield->value[1], wield->value[2] );
	    bug( buf, 0 );
	    if( wield->name )
	      bug( wield->name, 0 );
	}
    }

    /*
     * Bonuses.
     */
    dam += GET_DAMROLL( ch );

    if ( ch->race == 13 )
	dam += ch->level;
    if ( ( ch->class == CLASS_MONK || ch->multied == CLASS_MONK ) && !wield && !dual)
        dam += ch->level/2;
    if ( ( ch->class == CLASS_WEREWOLF || ch->multied == CLASS_WEREWOLF ) && !wield && !dual )
	dam += ch->level/2 + 10;
    /* VAMP mods */
    if ( ch->class == CLASS_VAMPIRE || ch->multied == CLASS_VAMPIRE)
    {
	if (time_info.hour < 6 || time_info.hour >= 19)
	{
	    dam += dam / 3;
	}
	else
	{
	    dam -= dam / 3;
	}
    }

    if ( wield && IS_SET( wield->extra_flags, ITEM_POISONED ) )
        dam += dam / 16;
    if ( wield && IS_SET( wield->extra_flags, ITEM_FLAME ) )
        dam += dam / 16;
    if ( wield && IS_SET( wield->extra_flags, ITEM_CHAOS ) )
        dam += dam / 16;
    if ( wield && IS_SET( wield->extra_flags, ITEM_ICY   ) )
        dam += dam / 16;
    if ( wield && IS_SET( wield->extra_flags2, ITEM_SPARKING ) )
        dam += dam / 16;
    if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage")] > 0 )
    {
	dam += dam / 2 * ch->pcdata->learned[skill_lookup("enhanced damage")] / 1000;
	update_skpell( ch, skill_lookup("enhanced damage"), 0 );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage two")] > 0 )
    {
        dam += dam / 6 * ch->pcdata->learned[skill_lookup("enhanced damage two")] / 1000;
	update_skpell( ch, skill_lookup("enhanced damage two"), 0 );
    }
    if ( !IS_NPC( ch ) && ch->pcdata->learned[skill_lookup("enhanced damage three")] > 0 )
    {
        dam += dam / 6 * ch->pcdata->learned[skill_lookup("enhanced damage three")] / 1000;
	update_skpell( ch, skill_lookup("enhanced damage three"), 0 );
    }
    if ( !IS_AWAKE( victim ) )
	dam *= 2;
    if ( dt == skill_lookup("backstab") )
    {
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );
    }
    if ( dt == skill_lookup("assassinate") )
    {
	dam = (int)(dam * (1.5 * (2 + UMIN( ( ch->level / 8) , 4 ) ) ));
    }
    if ( dt == skill_lookup("leap of torfi") )
    {
	dam = (int)(dam * (1.5 * (2 + UMIN( ( ch->level / 8) , 4 ) ) ));
    }
    if ( dt == skill_lookup("double backstab") )
    {
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );
    }
    if ( dt == skill_lookup("triple backstab") )
    {
	dam *= 2 + UMIN( ( ch->level / 8) , 4 );
    }

    if ( dam <= 0 )
	dam = 1;

    if (!IS_NPC(victim))
       dam = damreduce( ch, victim, dam, dt );

    dam_class_value = val;
    damage( ch, victim, dam, dt );
    dam_class_value = 0;
    tail_chain( );
    update_skpell( ch, skill_lookup("dual"), 0 );

    return;
}

/* removes an object and put it right back on,
   we need this so that when a player get pkilled
   the spells on objs don't disappear. */
void remove_requip(  CHAR_DATA *ch, int iWear )
{
    OBJ_DATA *obj;

    if ( !( obj = get_eq_char( ch, iWear ) ) )
        return;

    unequip_char( ch, obj );
    equip_char( ch, obj, iWear );
}


/*
 * Inflict damage from a hit.
 */
void damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{

    AFFECT_DATA *paf;
    AFFECT_DATA *paf_next;
    int iWear;

    if ( victim->position == POS_DEAD )
	return;

    /* Combat Timer for PVP, and immunity for self damaging attacks
	IE: Poison, Meteor Swarm - Ahsile */
    if(!IS_NPC(ch) && !IS_NPC(victim) && (victim!=ch) && (dt != skill_lookup("incinerate") 
	&& dt != skill_lookup("deadly poison") && dt != skill_lookup("tortured soul") 
	&& dt != skill_lookup("pestilence") && dt != skill_lookup("breathe water") 
	&& dt != skill_lookup("poison") ) )
    {
        ch->combat_timer = 90;
        victim->combat_timer = 90;
    }

    /*
     * Lets stick in the enhanced spell damage from spellcraft.
     */
    /* FIXME  needs to check to make sure the damage is magical */
    if (!IS_NPC(ch) && (number_percent() < (ch->pcdata->learned[skill_lookup("improved concentration")]/10)))
    {
		if (skill_table[dt].is_spell) /* FIXED - Ahsile */
		{
			update_skpell( ch, skill_lookup("improved concentration"), 0 );
	       dam = number_range(dam , (int) (dam * 1.25));
		}
	}
    /*
     * Stop up any residual loopholes.
     */
    if ( dam > 6000 )
    {
        char buf [ MAX_STRING_LENGTH ];

//        if ( ( dt != 91 && dt != 268 && dt != 269 && dt != 92 && dt != 229 && dt != 347 && dt != 402 && dt != 304 && dt != 353 && dt != 37 ) && ch->level <= LEVEL_DEMIGOD )
	/*  37 - Energy Dragin */
	/* 174 - Ultrablast */
	/* 269 - Assassinate */
	/* 445 - Death Strike */
        if ( ( dt != 37 && dt != 174 && dt != 445 && dt != 269 ) && ch->level <= LEVEL_DEMIGOD )
        {
            if ( IS_NPC( ch ) && ch->desc && ch->desc->original )
	    sprintf( buf,
		    "Damage: %d from %s by %s: > 6000 points with %d dt!",
		    dam, ch->name, ch->desc->original->name, dt );
            else
	    sprintf( buf,
		    "Damage: %d from %s: > 6000 points with %d dt!",
		    dam, ch->name, dt );

            bug( buf, 0 );
        }
    }

    if ( victim != ch )
    {
	/*
	 * Certain attacks are forbidden.
	 * Most other attacks are returned.
	 */

        if ( !IS_NPC(ch) && !IS_NPC(victim) && !is_pkillable( ch, victim)  )
        {
            return;
        }
	if ( is_safe( ch, victim ) )
	    return;

	check_killer( ch, victim );

	if ( victim->position > POS_STUNNED )
	{
	    if ( !victim->fighting )
		set_fighting( victim, ch );
	    victim->position = POS_FIGHTING;
	}

	if ( victim->position > POS_STUNNED )
	{
	    if ( !ch->fighting )
	    {
		ch->initiated = TRUE;
		set_fighting( ch, victim );
	    }
	    /*
	     * If victim is charmed, ch might attack victim's master.
	     */
	    if (   IS_NPC( ch )
		&& IS_NPC( victim )
		&& IS_AFFECTED( victim, AFF_CHARM )
		&& victim->master
		&& victim->master->in_room == ch->in_room
		&& number_bits( 3 ) == 0 )
	    {
		stop_fighting( ch, FALSE );
		set_fighting( ch, victim->master );
		return;
	    }
	}

	/*
	 * More charm stuff.
	 */
	if ( victim->master == ch )
	    stop_follower( victim );

	/*
	 * Inviso attacks ... not.
	 */
	if ( IS_AFFECTED( ch, AFF_INVISIBLE ) )
	{
	    affect_strip( ch, skill_lookup("invis")      );
	    affect_strip( ch, skill_lookup("mass invis") );
	    REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
	    act(AT_GREY, "$n fades into existence.", ch, NULL, NULL, TO_ROOM );
	}
	if (IS_AFFECTED2( ch, AFF_PHASED ) )
	{
	    affect_strip( ch, skill_lookup("phase shift") );
	    REMOVE_BIT( ch->affected_by2, AFF_PHASED );
	    act(AT_GREY, "$n returns from an alternate plane.", ch, NULL, NULL, TO_ROOM );
	}

	/* if you or target has shadow plane, and there is combat, this here gets rid of it */

        if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ) )
        {
	    affect_strip( ch, skill_lookup("shadow plane") );
	    REMOVE_BIT( ch->affected_by2, AFF_SHADOW_PLANE );
	    act(AT_BLOOD, "$n returns to reality!", ch, NULL, NULL, TO_ROOM );
        }
        if ( IS_AFFECTED4( ch, AFF_BURROW ) )
        {
	    affect_strip( ch, skill_lookup("tomba di vemon")     );
	    REMOVE_BIT( ch->affected_by4, AFF_BURROW );
	    act(AT_BLOOD, "$n is expelled from the earth!", ch, NULL, NULL, TO_ROOM );
        }

        if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ) )
	{
	    affect_strip (victim, skill_lookup("shadow plane") );
	    REMOVE_BIT( victim->affected_by2, AFF_SHADOW_PLANE );
	    act(AT_BLOOD, "$n returns to reality!", victim, NULL, NULL, TO_ROOM );
	}
        if ( IS_AFFECTED4( victim, AFF_BURROW ) )
	{
	    affect_strip (victim, skill_lookup("tomba di vemon") );
	    REMOVE_BIT( victim->affected_by4, AFF_BURROW );
	    act(AT_BLOOD, "$n is expelled from the earth!", victim, NULL, NULL, TO_ROOM );
	}


	/*
	 * Proficiency modifiers
	 */
	 if (dt > TYPE_HIT && !IS_NPC(ch) )
	 {
		 int prof = dt - TYPE_HIT;
		 int sn = 0;

		 if ( ( 
				   flag_value(weapon_flags, "hit")		== prof 
				|| flag_value(weapon_flags, "claw")		== prof
				|| flag_value(weapon_flags, "blast")	== prof
				|| flag_value(weapon_flags, "whip")		== prof
				|| flag_value(weapon_flags, "grep")		== prof
				|| flag_value(weapon_flags, "bite")		== prof
				|| flag_value(weapon_flags, "suction")	== prof
			  )
			 && ch->pcdata->learned[(sn = skill_lookup("proficiency hit"))] )
		 {

			dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
			 update_skpell( ch, sn, 0 );

		 } else if ( (
						   flag_value(weapon_flags, "stab")		== prof
						|| flag_value(weapon_flags, "pierce")	== prof
					 )
					 && ch->pcdata->learned[(sn = skill_lookup("proficiency pierce"))] )
		{

			dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
			update_skpell( ch, sn, 0 );

		}  else if ( (
						   flag_value(weapon_flags, "slash")	== prof
					 )
					 && ch->pcdata->learned[(sn = skill_lookup("proficiency slash"))] )
		{

			dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
			update_skpell( ch, sn, 0 );

		}  else if ( (
						   flag_value(weapon_flags, "slice")	== prof
					 )
					 && ch->pcdata->learned[(sn = skill_lookup("proficiency slice"))] )
		{

			dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
			update_skpell( ch, sn, 0 );

		}  else if ( (
							flag_value(weapon_flags, "crush")	== prof
						 || flag_value(weapon_flags, "pound")	== prof
					 )
					 && ch->pcdata->learned[(sn = skill_lookup("proficiency crush"))] )
		{

			dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
			update_skpell( ch, sn, 0 );

		}  else if ( (
							flag_value(weapon_flags, "chop")	== prof
					 )
					 && ch->pcdata->learned[(sn = skill_lookup("proficiency chop"))] )
		{

			dam += (int) ( dam * (ch->pcdata->learned[sn] / 10000.0f) );
			update_skpell( ch, sn, 0 );

		}
	 }

	/*
	 * Damage modifiers.
	 */

	if ( !IS_NPC(victim) && !IS_NPC(ch))
	   {
           dam -= dam / 2;
           ch->pkill_timer = 0;  /* added to insure that if a player is damaging another
                                 player, his pk timer is set to 0 */
         }
        if ( ch->race == 0 && ch->class == 7)
	    dam = (int)(dam * 0.8);

        if ( IS_AFFECTED( victim, AFF_SANCTUARY ) || IS_AFFECTED4( victim, AFF_BIOFEEDBACK ) || IS_AFFECTED4( victim, AFF_ESSENCE_OF_GAIA ) || IS_SET( race_table[ victim->race ].race_abilities, RACE_SANCT ) )
            dam  = (int)(dam / 1.5);
	if ( IS_AFFECTED4( victim, AFF_EARTHSHIELD ) )
	    dam = (int)(dam / 1.3);
	if ( IS_AFFECTED2( victim, AFF_THICK_SKIN ) )
	    dam = (int)(dam / 1.15);
	if ( IS_AFFECTED2( victim, AFF_GOLDEN_ARMOR ) )
	    dam = (int)(dam / 1.35);
        if ( IS_AFFECTED4( victim, AFF_GOLDEN_SANCTUARY ) )
	    dam = (int)(dam / 1.5);
	if ( IS_AFFECTED2( victim, AFF_SHADOW_IMAGE ) )
	    dam = (int)(dam / 1.25);
	if ( IS_AFFECTED2( victim, AFF_GHOST_SHIELD ) )
            dam = (int)(dam / 1.05);
	if ( IS_AFFECTED3( victim, AFF_SATANIC_INFERNO ) )
            dam = (int)(dam / 1.05);
	if ( IS_AFFECTED2( victim, AFF_DANCING ) )
	    dam = (int)(dam * 1.25);
	if ( IS_AFFECTED( victim, AFF_FIRESHIELD ) )
	    dam = (int)(dam / 1.05);
	if ( IS_AFFECTED4( victim, AFF_LEAF_SHIELD ) )
	    dam = (int)(dam / 1.05);
	if ( IS_AFFECTED3( victim, AFF_COFIRE ) )
	    dam = (int)(dam / 1.05);
	if ( IS_AFFECTED3( victim, AFF_AURA_ANTI_MAGIC ) )
	    dam = (int)(dam / 1.05);
	if ( IS_AFFECTED( victim, AFF_ICESHIELD ) )
	    dam = (int)(dam / 1.05);
	if ( IS_AFFECTED2( victim, AFF_MIST) )
	    dam = (int)(dam / 1.25);
        if ( IS_AFFECTED( victim, AFF_CHAOS ) )
	    dam = (int)(dam / 1.05);
	if ( IS_AFFECTED( victim, AFF_SHOCKSHIELD ) )
	    dam = (int)(dam / 1.15);
	if ( IS_AFFECTED3( victim, AFF_BLOODSHIELD ) )
	    dam = (int)(dam / 1.15);
	if ( IS_AFFECTED2( victim, AFF_UNHOLY_STRENGTH ) )
	    dam = (int)(dam / 1.12);
	if ( IS_AFFECTED( victim, AFF_INERTIAL ) )
	    dam = (int)(dam / 1.05);
	if ( IS_AFFECTED3( victim, AFF_DEMONSHIELD ) )
	    dam = (int)(dam / 1.10);
        if ( IS_AFFECTED3( victim, AFF_ACIDSHIELD ) )
            dam = (int)(dam / 1.15);
	if ( IS_AFFECTED4( victim, AFF_LIQUID_SKIN ) )
	    dam = (int)(dam / 1.15);
	if ( IS_AFFECTED4( victim, AFF_ANGELIC_AURA ) )
	    dam = (int)(dam / 1.10);
        if ( IS_AFFECTED4( victim, AFF_FORCE_OF_NATURE ) )
	    dam = (int)(dam / 1.15 );

        if ( IS_SET( victim->act, PLR_UNDEAD ) )
            dam = (int)(dam / 1.05);
        if ( (   IS_AFFECTED( victim, AFF_PROTECT      )
              || IS_SET( race_table[ victim->race ].race_abilities,
                        RACE_PROTECTION )              )
            && IS_EVIL( ch )                           )
            dam  = (int)(dam / 1.1);
	if ( IS_AFFECTED2( victim, AFF_PROTECTION_GOOD ) )
	    dam = (int)(dam / 1.1);
/* Damclass Stuff --Manaux */
	dam = damclass_adjust(victim, dam, dt);

	if ( dam < 0 )
	    dam = 0;

	/*
	 * Check for disarm, trip, parry, and dodge.
	 */
	if ( dt >= TYPE_HIT || dt == skill_lookup("kick") || dt == skill_lookup("feed") || dt == skill_lookup("punch") )
	{
	    int leveldiff = ch->level - victim->level;

	    if ( IS_NPC( ch ) && number_percent( )
		< ( leveldiff < -5 ? ch->level / 2 : UMAX( 10, leveldiff ) )
		&& dam == 0 && number_bits(4) == 0)
	        disarm( ch, victim );
            if ( IS_NPC( ch )
                && IS_SET( race_table[ ch->race ].race_abilities,
                          RACE_WEAPON_WIELD )
                && number_percent() < UMIN( 25, UMAX( 10, ch->level ) )
                && !IS_NPC( victim ) )
                use_magical_item( ch );
	}

    }
    if ( ( !IS_NPC(ch) ) && ( !IS_NPC(victim) ) )
       dam -= dam/4;

    /*
     * Hurt the victim.
     * Inform the victim of his new state.
     */

/* tell the victim how much he got hurt */
     if ( dt != TYPE_UNDEFINED )
        dam_message( ch, victim, dam, dt );
     if ( dam > 25 && number_range( 0, 100 ) <= 15 )
        item_damage(victim, dam);
     victim->hit -= dam;

     if ( !IS_NPC( victim )
	&& victim->level >= LEVEL_IMMORTAL
	&& victim->hit < 1 )
	victim->hit = 1;

     if ( IS_AFFECTED4( victim, AFF_IMMORTAL ) && ( victim->hit < 1 ) )
     {
         victim->hit = 1;
     }

/*
    if ( !IS_NPC( victim )
	&& victim->clev == 5
	&& victim->clan == 8
        && victim->hit < 1 )
        victim->hit = 1;
*/

    if ( dam > 0 && dt > TYPE_HIT
	&& is_wielding_poisoned( ch )
	&& !saves_spell( ch->level, victim ) )
    {
	AFFECT_DATA af;

	if( !IS_AFFECTED( victim, AFF_POISON ) )
	{
	    af.type      = skill_lookup("poison");
	    af.duration  = 1;
	    af.location  = APPLY_STR;
	    af.modifier  = -2;
	    af.bitvector = AFF_POISON;
	    affect_join( victim, &af );
	    add_poison( victim, 1 );
	}
    }
    if ( dam > 0 && dt > TYPE_HIT
       && is_wielding_flaming( ch )
       && number_percent( ) < 30 )
          damage( ch, victim, spell_fireball ( skill_lookup("fireball"), 20, ch, victim ), skill_lookup("fireball"));

    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
    if ( dam > 0 && dt > TYPE_HIT
       && is_wielding_icy( ch )
       && number_percent( ) < 30 )
          damage( ch, victim, spell_icestorm ( skill_lookup("iceball"), 20, ch, victim ), skill_lookup("iceball"));

    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;
    if ( dam > 0 && dt > TYPE_HIT && is_wielding_sparking( ch )
       && number_percent( ) < 30 )
        damage( ch, victim, spell_lightning_bolt ( skill_lookup("lightning bolt"), 20, ch, victim ), skill_lookup("lightning bolt"));

    if ( dam > 0 && dt > TYPE_HIT && is_wielding_dispelling( ch )
       && number_percent( ) < 30 )
        spell_dispel_magic ( skill_lookup("dispel magic"), 30, ch, victim );

    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;

    if ( dam > 0 && dt > TYPE_HIT
       && is_wielding_chaos( ch )
       && number_percent( ) < 30 )
          damage( ch, victim, spell_energy_drain ( skill_lookup("energy drain"), 45, ch, victim ), skill_lookup("energy drain"));

    if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
	return;

    if (  IS_SET( ch->act, PLR_UNDEAD )
       && !saves_spell(ch->level, victim ) )
    {
	AFFECT_DATA af;

	af.type      = skill_lookup("poison");
	af.duration  = 2;
	af.location  = APPLY_CON;
	af.modifier  = -1;
	af.bitvector = AFF_POISON;
	affect_join( victim, &af );
	add_poison( victim, 2 );
    }

    update_pos( victim );

    switch( victim->position )
    {
    case POS_MORTAL:
	send_to_char(AT_RED,
	    "You are mortally wounded, and will die soon, if not aided.\n\r",
	    victim );
	act(AT_RED, "$n is mortally wounded, and will die soon, if not aided.",
	    victim, NULL, NULL, TO_ROOM );
	break;

    case POS_INCAP:
	send_to_char(AT_RED,
	    "You are incapacitated and will slowly die, if not aided.\n\r",
	    victim );
	act(AT_RED, "$n is incapacitated and will slowly die, if not aided.",
	    victim, NULL, NULL, TO_ROOM );
	break;

    case POS_STUNNED:
	send_to_char(AT_WHITE,"You are stunned, but will probably recover.\n\r",
	    victim );
	act(AT_WHITE, "$n is stunned, but will probably recover.",
	    victim, NULL, NULL, TO_ROOM );
	break;

    case POS_DEAD:
	send_to_char(AT_BLOOD, "You have been KILLED!!\n\r\n\r", victim );
	act(AT_BLOOD, "$n is DEAD!!", victim, NULL, NULL, TO_ROOM );
	break;

    default:
	if ( dam > victim->max_hit / 4 )
	    send_to_char(AT_RED, "That really did HURT!\n\r", victim );
	if ( victim->hit < victim->max_hit / 4 )
	    send_to_char(AT_RED, "You sure are BLEEDING!\n\r", victim );
	break;
    }

    /*
     * Payoff for killing things.
     */
    if ( victim->position == POS_DEAD )
    {

	group_gain( ch, victim );

	stop_fighting( victim, FALSE );
	stop_fighting( ch, FALSE	 );

        if(((ch->guild != NULL) ? ch->guild->type & GUILD_CHAOS : 0)
            && ch->guild == victim->guild
            && victim->guild_rank > ch->guild_rank)
        {
            int temp;
            temp = ch->guild_rank;
            ch->guild_rank = victim->guild_rank;
            victim->guild_rank = temp;
        }
        if ( !IS_NPC(ch) && !IS_NPC(victim) && (ch->name != victim->name) )
        {
            CLAN_DATA  *pClan;
            CLAN_DATA  *Cland;
            RELIGION_DATA  *pReligion;
            RELIGION_DATA  *Religiond;
            pClan = get_clan_index(ch->clan);
            Cland = get_clan_index(victim->clan);
            if(ch->clan != victim->clan )
            {
                pClan->pkills++;
                Cland->pdeaths++;
            }
            pReligion = get_religion_index(ch->religion );
            Religiond = get_religion_index(victim->religion );
            if(ch->religion != victim->religion )
            {
                pReligion->pkills++;
                Religiond->pdeaths++;
            }
        }
        if ( ( !IS_NPC(ch) ) && ( IS_NPC(victim) ) )
        {
            CLAN_DATA    *pClan;
            pClan=get_clan_index(ch->clan);
            pClan->mkills++;
        }
	if ( ( !IS_NPC(ch) ) && ( IS_NPC(victim) ) )
        {
            RELIGION_DATA  *pReligion;
            pReligion=get_religion_index(ch->religion);
            pReligion->mkills++;
	}
        if ( ( IS_NPC(ch) ) && (!IS_NPC(victim)) )
        {
            CLAN_DATA   *pClan;
            pClan=get_clan_index(victim->clan);
            pClan->mdeaths++;
        }
	if ( ( IS_NPC(ch) ) && (!IS_NPC( victim ) ) )
	{
            RELIGION_DATA  *pReligion;
            pReligion=get_religion_index(victim->religion );
            pReligion->mdeaths++;
	}
        if ( !IS_NPC(ch) ) {
            if ( is_affected( ch, skill_lookup("berserk") ) )
            {
                affect_strip( ch, skill_lookup("berserk") );
                send_to_char(C_DEFAULT, skill_table[skill_lookup("berserk")].msg_off,ch);
                send_to_char(C_DEFAULT, "\n\r",ch);
            }
            if ( IS_AFFECTED2(ch, AFF_BERSERK) )
                REMOVE_BIT(ch->affected_by2, AFF_BERSERK);

            if ( is_affected( ch, skill_lookup("bloodthirsty") ) )
            {
                affect_strip( ch, skill_lookup("bloodthirsty") );
                send_to_char(C_DEFAULT, skill_table[skill_lookup("bloodthirsty")].msg_off,ch);
                send_to_char(C_DEFAULT, "\n\r",ch);
            }
            if ( IS_AFFECTED3(ch, AFF_BLOODTHIRSTY) )
                REMOVE_BIT(ch->affected_by3, AFF_BLOODTHIRSTY);
	}

	if ( !IS_NPC( victim ) )
	{
	    /*
	     * Dying penalty:
	     * 1/2 way back to previous level.
	     */
	    if ( IS_NPC(ch))
	    {
                if ( ( victim->exp > 1000 * victim->level ) && ( !IS_SET(victim->act, PLR_GHOST ) ) )
                {
                    gain_exp( victim, ( 1000 * victim->level - victim->exp ) / 2 );
                }
	    }
	    sprintf( log_buf, "%s killed by %s at %d.", victim->name,
	        ch->name, victim->in_room->vnum );
	    log_string( log_buf, CHANNEL_LOG, -1 );
	    sprintf( log_buf, "%s was slaughtered by %s.", victim->name, ch->name);
	    if(IS_NPC ( ch ) )
	    {
		sprintf( log_buf, "%s was slaughtered by %s.", victim->name, ch->short_descr );
	    }
	    if(!IS_NPC( ch ) && !IS_NPC( victim ) )
	    {
		broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death8.wav V=100 L=1 P=100 T=Pkill)");
	    }
	    else
	    {
		int tempvar = number_range( 1, 6 );
		switch( tempvar )
		{
		    default:
			broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death6.wav V=100 L=1 P=50 T=Combat)");
			break;
		    case 1:
			broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death1.wav V=100 L=1 P=50 T=Combat)");
			break;
		    case 2:
			broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death2.wav V=100 L=1 P=50 T=Combat)");
			break;
		    case 3:
			broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death3.wav V=100 L=1 P=50 T=Combat)");
			break;
		    case 4:
			broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death4.wav V=100 L=1 P=50 T=Combat)");
			break;
		    case 5:
			broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death5.wav V=100 L=1 P=50 T=Combat)");
			break;
		    case 6:
			broadcast_channel( ch, log_buf, CHANNEL_INFO, "!!SOUND(death7.wav V=100 L=1 P=50 T=Combat)");
			break;
		}
	    }
            stop_fighting(ch,TRUE);
            victim->hit = 1;
            victim->pkill_timer = time( NULL );
            if ( !IS_NPC(ch) && (ch->name != victim->name ) ) {
            	ch->pcdata->awins += 1;
                victim->pcdata->alosses += 1;
	    }
/* strip the guy */
            for ( paf = victim->affected; paf; paf = paf_next )
            {
                paf_next = paf->next;
                if( !paf->deleted )
                affect_remove( victim, paf );
            }
            for ( paf = victim->affected2; paf; paf = paf_next )
            {
                paf_next = paf->next;
                if( !paf->deleted )
                affect_remove2( victim, paf );
            }
            for ( paf = victim->affected3; paf; paf = paf_next )
            {
                paf_next = paf->next;
                if( !paf->deleted )
                affect_remove3( victim, paf );
            }
            for ( paf = victim->affected4; paf; paf = paf_next )
            {
                paf_next = paf->next;
                if( !paf->deleted && paf->type != skill_lookup("newbie slayer"))
		{
                	affect_remove4( victim, paf );
		}
            }
            for ( paf = victim->affected_powers; paf; paf = paf_next )
            {
                paf_next = paf->next;
                if( !paf->deleted )
                affect_remove_powers( victim, paf );
            }
            for ( paf = victim->affected_weaknesses; paf; paf = paf_next )
            {
                paf_next = paf->next;
                if( !paf->deleted )
                affect_remove_weaknesses( victim, paf );
            }
            update_pos( victim );
	    victim->shields = 0;
            save_clans();
            save_religions();

            if(!IS_NPC( ch ) && !IS_NPC( victim ) && (ch->name != victim->name ) )
            {
		RELIGION_DATA* pRel = get_religion_index(victim->religion);

                char_from_room(victim);

		if (pRel->recall != ROOM_VNUM_OUTSIDEMETH )
			char_to_room(victim, get_room_index(ROOM_VNUM_ALOSER) );
		else
	                char_to_room(victim,get_room_index(pRel->recall));

                for ( iWear = 0; iWear < MAX_WEAR; iWear++ )
                {
                    remove_requip( victim, iWear );
                }

            return;
            }
        }

	raw_kill( ch, victim );
	if( IS_NPC( victim ) && !IS_NPC( ch ) )
	{
	    ch->pcdata->mobkills ++;
	}
	/* Ok, now we want to remove the deleted flag from the
	 * PC victim.
	 */
	if ( !IS_NPC( victim ) )
	    victim->deleted = FALSE;

	if ( !IS_NPC( ch ) && IS_NPC( victim ) )
	{
	    if ( IS_SET( ch->act, PLR_AUTOLOOT ) )
		do_get( ch, "all corpse" );
	    else
		do_look( ch, "in corpse" );

	    if ( IS_SET( ch->act, PLR_AUTOGOLD ) )
	        do_get( ch, "gold corpse" );
	    if ( IS_SET( ch->act, PLR_AUTOSAC  ) )
		do_sacrifice( ch, "corpse" );
	}

	return;
    }

    /*
     * Sleep spells and extremely wounded folks.
     */
    if ( !IS_AWAKE( victim ) )
	stop_fighting(victim, FALSE);

    if ( victim == ch )
	return;

    /*
     * Take care of link dead people.
     */
    if ( !IS_NPC( victim ) && !victim->desc )
    {
	if ( number_range( 0, victim->wait ) == 0 )
	{
	    do_recall( victim, "" );
	    return;
	}
    }

    /*
     * Wimp out?
     */
    if ( IS_NPC( victim ) && dam >= 0 )
    {
	if ( ( IS_SET( victim->act, ACT_WIMPY ) && number_bits( 1 ) == 0
	      && victim->hit < victim->max_hit / 2 )
	    || ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master
		&& victim->master->in_room != victim->in_room ) )
	    do_flee( victim, "" );
    }

    if ( ( !IS_NPC( victim )
	&& victim->hit > 0
	&& victim->hit <= victim->wimpy
	&& victim->wait == 0 )
        && !IS_AFFECTED3(victim, AFF_BLOODTHIRSTY)
        && !IS_AFFECTED2(victim, AFF_BERSERK) )
	do_flee( victim, "" );

    tail_chain( );
    return;
}

void item_damage( CHAR_DATA *ch, int dam )
{
	OBJ_DATA  *obj_lose;
	OBJ_DATA  *obj_next;

	for ( obj_lose = ch->carrying; obj_lose; obj_lose = obj_next )
	{
		char *msg;
		int damage = 0;

		obj_next = obj_lose->next_content;
		if( obj_lose->deleted )
		    continue;
		if( number_bits( 2 ) != 0 )
		    continue;
		if( obj_lose->wear_loc == WEAR_NONE )
		    continue;
		if( IS_SET( obj_lose->extra_flags, ITEM_NO_DAMAGE ) )
		    continue;
		damage =  obj_lose->durability_cur % 10;
		if( damage >= 5 )
		    damage = 5;
		if( damage <= 0 )
		    continue;
		if( obj_lose->weight <= 25 )
		{
			if( obj_lose->weight * 2 <= number_percent( ) )
			    continue;
		}
		else
		{
			if( number_percent( ) <= 50 )
			    continue;
		}

		switch ( obj_lose->item_type )
		{
		default:
		    msg = "Your $p gets ruined!";
		    extract_obj( obj_lose );
		    break;

		case ITEM_DRINK_CON:
		case ITEM_POTION:
		case ITEM_CONTAINER:
		case ITEM_LIGHT:
		    msg = "Your $p shatters!";
		    extract_obj( obj_lose );
		    break;

		case ITEM_WEAPON:
		case ITEM_ARMOR:
		    if( obj_lose->durability_cur > 0 )
		    {
			obj_lose->durability_cur -= damage;
		    }

		    if( obj_lose->durability_cur <= 0 )
		    {
			OBJ_DATA       *pObj;
			OBJ_INDEX_DATA *pObjIndex;
			char           *name;
			char           buf[MAX_STRING_LENGTH];

			pObjIndex = get_obj_index(4);
			pObj = create_object(pObjIndex, obj_lose->level);
			name = obj_lose->short_descr;
			sprintf(buf, pObj->description, name);
			free_string(pObj->description);
			pObj->description = str_dup(buf);
			pObj->weight = obj_lose->weight;
			pObj->timer = obj_lose->level;
			msg = "$p has been destroyed!";
			extract_obj( obj_lose );
			obj_to_room ( pObj, ch->in_room );
		    }
		    else
		    {
			msg = "$p has been damaged!";
		    }
		    break;
		}

		act(AT_YELLOW, msg, ch, obj_lose, NULL, TO_CHAR );
		return;
	}
	return;
}

bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim )
{

  if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE ) ||
       IS_SET( victim->in_room->room_flags, ROOM_SAFE ) )
    return TRUE;

  if( ch->position == POS_GHOST || victim->position == POS_GHOST )
    return TRUE;

  if ( !IS_NPC(ch) && !IS_NPC(victim) &&
       (IS_SET(ch->in_room->room_flags, ROOM_NO_PKILL) ||
	IS_SET(victim->in_room->room_flags, ROOM_NO_PKILL)) )
    return TRUE;

  if ( IS_SET( ch->in_room->room_flags, ROOM_PKILL ) &&
       IS_SET( victim->in_room->room_flags, ROOM_PKILL ) )
    return FALSE;

  if ( IS_NPC( victim ) )
    return FALSE;

  if ( IS_NPC( ch ) )
  {
    if ( IS_SET(ch->affected_by, AFF_CHARM) && ch->master )
    {
      CHAR_DATA *nch;

      for ( nch = ch->in_room->people; nch; nch = nch->next )
	if ( nch == ch->master )
	  break;

      if ( nch == NULL )
	return FALSE;
      else
	ch = nch; /* Check person who ordered mob for clan stuff.. */
    }
    else
      return FALSE;
  }

/* give pkill guilds ability to pkill */
/* Err.. we might not want pkill guilds attacking unguilded.. */
  if ( (ch->guild && (ch->guild->type & GUILD_PKILL)) &&
       (victim->guild && (victim->guild->type & GUILD_PKILL)) )
  {
    return FALSE;
  }

/* can murder self for testing =) */
  if ( ch->clan == victim->clan && ch != victim && (ch->clan != 0 && victim->clan != 0))
  {
    send_to_char(AT_WHITE, "You cannot murder your own clan member.\n\r",ch);
    return TRUE;
  }

  if ( IS_SET( victim->act, PLR_KILLER ) )
    return FALSE;


  return FALSE;
}



/*
 * See if an attack justifies a KILLER flag.
 */
void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
{
    /*
     * NPC's are fair game.
     */
    if ( IS_NPC( victim ) )
        return;

    /* In arena rooms player killing is legal. Doesn't give you any
     * experience gain or loss either. -- Maniac --
     */

    /*
     * NPC's are fair game.
     * So are killers and thieves.
     */
    if ( IS_SET( victim->act, PLR_KILLER )
	|| IS_SET( victim->act, PLR_THIEF  ) )
	return;

    /*
     * NPC's are cool of course
     * Hitting yourself is cool too (bleeding).
     * And current killers stay as they are.
     */
    if ( IS_NPC( ch )
	|| ch == victim
	|| IS_SET( ch->act, PLR_KILLER     ) )
	return;

    if ( ch->clan != 0 )
       return;
    return;
}

/*
 * Check to see if weapon is poisoned.
 */
bool is_wielding_poisoned( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
	&& IS_SET( obj->extra_flags, ITEM_POISONED ) )
        return TRUE;

    return FALSE;

}
bool is_wielding_flaming( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
	&& IS_SET( obj->extra_flags, ITEM_FLAME ) )
        return TRUE;

    return FALSE;

}
bool is_wielding_sparking( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
	&& IS_SET( obj->extra_flags2, ITEM_SPARKING ) )
	return TRUE;

    return FALSE;
}
bool is_wielding_acid( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
        && IS_SET( obj->extra_flags, ITEM_ACID ) )
        return TRUE;

    return FALSE;

}
bool is_wielding_dispelling( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
	&& IS_SET( obj->extra_flags2, ITEM_DISPEL ) )
	return TRUE;

    return FALSE;
}



bool is_wielding_icy( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
	&& IS_SET( obj->extra_flags, ITEM_ICY ) )
        return TRUE;

    return FALSE;

}
bool is_wielding_chaos( CHAR_DATA *ch )
{
    OBJ_DATA *obj;

    if ( ( obj = get_eq_char( ch, WEAR_WIELD ) )
	&& IS_SET( obj->extra_flags, ITEM_CHAOS ) )
        return TRUE;

    return FALSE;

}


/*
 * Check for parry.
 */
bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
    int chance;

    if ( !IS_AWAKE( victim ) )
	return FALSE;

    if ( IS_NPC( victim ) )
    {
	chance	= UMIN( 50, 2 * victim->level );
	if ( !get_eq_char( victim, WEAR_WIELD ) )
	    return FALSE;
    }
    else
    {
	if ( !get_eq_char( victim, WEAR_WIELD ) )
	    return FALSE;
	if (!can_use_skspell( victim, skill_lookup("parry")))
	{
	    return FALSE;
	}
	chance	= victim->pcdata->learned[skill_lookup("parry")] / 20;
    }

    /* STR mod for high str victim */
    chance += get_curr_str(victim) - get_curr_str(ch);

    /* Mod for what attack this is in a round */
    chance -= (attackCount - 1) * 4;

    if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
    {
	chance /= 2;
    }

    if ( ch->wait == 0 )
	chance /= 2;

    if ( victim->wait != 0 )
	chance /= 2;

    if ( !IS_NPC( victim ) )
    {
	if ( chance < victim->pcdata->learned[skill_lookup("parry")] / 50 )
	{
	    chance = victim->pcdata->learned[skill_lookup("parry")] / 50;
	}
    }

    if ( ( number_percent( ) >= chance ) || IS_AFFECTED2( ch, AFF_BERSERK ) || IS_AFFECTED3( ch, AFF_BLOODTHIRSTY ) )
	return FALSE;

    update_skpell( victim, skill_lookup("parry"), 0 );

    if ( IS_SET( ch->act, PLR_COMBAT ) )
      act(AT_GREEN, "$N parries your attack.", ch, NULL, victim, TO_CHAR    );
    if ( IS_SET( victim->act, PLR_COMBAT ) )
      act(AT_GREEN, "You parry $n's attack.",  ch, NULL, victim, TO_VICT    );
    return TRUE;
}

bool check_enhanced_parry( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
    int chance;

    if ( !IS_AWAKE( victim ) )
	return FALSE;

    if ( IS_NPC( victim ) )
    {
	return FALSE;
    }
    else
    {
	if ( !get_eq_char( victim, WEAR_WIELD ) )
	    return FALSE;
	if (!can_use_skspell( victim, skill_lookup("enhanced parry")))
	{
	    return FALSE;
	}
	chance	= victim->pcdata->learned[skill_lookup("enhanced parry")] / 40;
    }

    /* STR mod for high str victim */
    chance += get_curr_str(victim) - get_curr_str(ch);

    /* Mod for what attack this is in a round */
    chance -= (attackCount - 1) * 4;

    if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
    {
	chance /= 2;
    }

    if ( ch->wait == 0 )
	chance /= 2;

    if ( victim->wait != 0 )
	chance /= 2;

    if ( !IS_NPC( victim ) )
    {
	if ( chance < victim->pcdata->learned[skill_lookup("enhanced parry")] / 50 )
	{
	    chance = victim->pcdata->learned[skill_lookup("enhanced parry")] / 50;
	}
    }

    if ( ( number_percent( ) >= chance ) || IS_AFFECTED2( ch, AFF_BERSERK ) || IS_AFFECTED3( ch, AFF_BLOODTHIRSTY ) )
	return FALSE;

    update_skpell( victim, skill_lookup("enhanced parry"), 0 );

    if ( IS_SET( ch->act, PLR_COMBAT ) )
      act(AT_GREEN, "$N parries your attack.", ch, NULL, victim, TO_CHAR    );
    if ( IS_SET( victim->act, PLR_COMBAT ) )
      act(AT_GREEN, "You parry $n's attack.",  ch, NULL, victim, TO_VICT    );
    return TRUE;
}

bool check_shield_block( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
    int chance;

    if ( !IS_AWAKE( victim ) )
	return FALSE;

    if ( !get_eq_char( victim, WEAR_SHIELD ) )
		return FALSE;

    if ( IS_NPC( victim ) )
    {
	chance	= UMIN( 50, 2 * victim->level );
    }
    else
    {
	if( victim->pcdata->learned[skill_lookup("shield block")] < 300 )
	{
	    chance = number_range( 1, 15 );
	}
	else
	{
	    chance = victim->pcdata->learned[skill_lookup("shield block")] / 20;
	}
    }

    if ( ch->wait == 0 )
    	chance /= 2;

    if ( victim->wait != 0 )
	chance /= 2;

    /* STR mod for high str victim */
    chance += get_curr_str(victim) - get_curr_str(ch);

    /* Mod for what attack this is in a round */
    chance -= (attackCount - 1) * 4;

    if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
    {
	chance /= 2;
    }

    if ( number_percent( ) >= chance + 10 )
	return FALSE;

    update_skpell( victim, skill_lookup("shield block"), 0 );

    if ( IS_SET( ch->act, PLR_COMBAT ) )
      act(AT_GREEN, "$N's shield blocks your attack.", ch, NULL, victim, TO_CHAR    );
    if ( IS_SET( victim->act, PLR_COMBAT ) )
      act(AT_GREEN, "Your shield blocks $n's attack.",  ch, NULL, victim, TO_VICT    );
    return TRUE;
}

/*
 * Check for dodge.
 */
bool check_dodge( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
    int chance;

    if ( !IS_AWAKE( victim ) )
	return FALSE;

    if ( IS_NPC( victim ) )
    {
	return FALSE;
    }
    else
    {
	if (!can_use_skspell( victim, skill_lookup("dodge")))
	{
	    return FALSE;
	}
	chance	= victim->pcdata->learned[skill_lookup("dodge")] / 20;
    }

    /* DEX mod for high str victim */
    chance += get_curr_dex(victim) - get_curr_dex(ch);

    /* Mod for what attack this is in a round */
    chance -= (attackCount - 1) * 4;

    if( can_use_skspell( ch, skill_lookup("wilderness lore") ) )
    {
        if( !IS_NPC( ch ) )
        {
	    if( ( number_percent( ) < ( ch->pcdata->learned[skill_lookup("wilderness master")] / 10 ) ) && IS_OUTSIDE( ch ) && IS_IN_NATURE( ch ) )
	    {
		chance += ch->pcdata->learned[skill_lookup("wilderness lore")] / 80;
		update_skpell( ch, skill_lookup("wilderness lore"), 0 );
	    }
	}
    }

    if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
    {
	chance /= 2;
    }

    if ( ch->wait == 0 )
	chance /= 2;

    if ( victim->wait != 0 )
	chance /= 2;

    if ( !IS_NPC( victim ) )
    {
	if ( chance < victim->pcdata->learned[skill_lookup("dodge")] / 50 )
	{
	    chance = victim->pcdata->learned[skill_lookup("dodge")] / 50;
	}
    }

    if ( ( number_percent( ) >= chance ) || IS_AFFECTED2( ch, AFF_BERSERK ) || IS_AFFECTED3( ch, AFF_BLOODTHIRSTY ) )
	return FALSE;

    update_skpell( victim, skill_lookup("dodge"), 0 );

    if ( IS_SET( ch->act, PLR_COMBAT ) )
      act(AT_GREEN, "$N dodges your attack.", ch, NULL, victim, TO_CHAR    );
    if ( IS_SET( victim->act, PLR_COMBAT ) )
      act(AT_GREEN, "You dodge $n's attack.", ch, NULL, victim, TO_VICT    );
    return TRUE;
}

bool check_enhanced_dodge( CHAR_DATA *ch, CHAR_DATA *victim, int attackCount )
{
    int chance;

    if ( !IS_AWAKE( victim ) )
	return FALSE;

    if ( IS_NPC( victim ) )
    {
	return FALSE;
    }
    else
    {
	if (!can_use_skspell( victim, skill_lookup("enhanced dodge")))
	{
	    return FALSE;
	}
	chance	= victim->pcdata->learned[skill_lookup("enhanced dodge")] / 40;
    }

    /* DEX mod for high str victim */
    chance += get_curr_dex(victim) - get_curr_dex(ch);

    /* Mod for what attack this is in a round */
    chance -= (attackCount - 1) * 4;

    if(IS_AFFECTED2(victim, AFF_BERSERK) || IS_AFFECTED3(victim, AFF_BLOODTHIRSTY) )
    {
	chance /= 2;
    }

    if ( ch->wait == 0 )
	chance /= 2;

    if ( victim->wait != 0 )
	chance /= 2;

    if ( !IS_NPC( victim ) )
    {
	if ( chance < victim->pcdata->learned[skill_lookup("enhanced dodge")] / 50 )
	{
	    chance = victim->pcdata->learned[skill_lookup("enhanced dodge")] / 50;
	}
    }

    if ( ( number_percent( ) >= chance ) || IS_AFFECTED2( ch, AFF_BERSERK ) || IS_AFFECTED3( ch, AFF_BLOODTHIRSTY ) )
	return FALSE;

    update_skpell( victim, skill_lookup("enhanced dodge"), 0 );

    if ( IS_SET( ch->act, PLR_COMBAT ) )
      act(AT_GREEN, "$N dodges your attack.", ch, NULL, victim, TO_CHAR    );
    if ( IS_SET( victim->act, PLR_COMBAT ) )
      act(AT_GREEN, "You dodge $n's attack.", ch, NULL, victim, TO_VICT    );
    return TRUE;
}

/*
 * Set position of a victim.
 */
void update_pos( CHAR_DATA *victim )
{
    if ( victim->hit > 0 )
    {
    	if ( victim->position < POS_STUNNED )
	    victim->position = POS_STANDING;
		return;
    }

    if ( IS_NPC( victim ) || victim->hit <= -11 )
    {
	//raw_kill( victim, victim );
	victim->position = POS_DEAD;
	return;
    }

         if ( victim->hit <= -6 ) victim->position = POS_MORTAL;
    else if ( victim->hit <= -3 ) victim->position = POS_INCAP;
    else                          victim->position = POS_STUNNED;

    return;
}



/*
 * Start fights.
 */
void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim )
{

    char buf [ MAX_STRING_LENGTH ];

    if ( ch->fighting )
    {
	bug( "Set_fighting: already fighting", 0 );
	sprintf( buf, "...%s attacking %s at %d",
		( IS_NPC( ch )     ? ch->short_descr     : ch->name     ),
		( IS_NPC( victim ) ? victim->short_descr : victim->name ),
		victim->in_room->vnum );
	bug( buf , 0 );
	return;
    }

    if ( IS_AFFECTED( ch, AFF_SLEEP ) )
	affect_strip( ch, skill_lookup("sleep") );

    ch->fighting = victim;
    ch->position = POS_FIGHTING;

    return;
}



/*
 * Stop fights.
 */
void stop_fighting( CHAR_DATA *ch, bool fBoth )
{
    CHAR_DATA *fch;

    for ( fch = char_list; fch; fch = fch->next )
    {
	if ( fch == ch || ( fBoth && fch->fighting == ch ) )
	{
	    fch->fighting	= NULL;
	    /* fch->hunting        = NULL; */
	    fch->position	= POS_STANDING;
	    fch->initiated	= FALSE;

	    if ( is_affected( fch, skill_lookup("berserk") ) )
	    {
	      affect_strip( fch, skill_lookup("berserk") );
	      send_to_char(C_DEFAULT, skill_table[skill_lookup("berserk")].msg_off,fch);
	      send_to_char(C_DEFAULT, "\n\r",fch);
	    }
	    if ( IS_AFFECTED2(fch, AFF_BERSERK) )
	      REMOVE_BIT(fch->affected_by2, AFF_BERSERK);
	    if ( is_affected( fch, skill_lookup("bloodthirsty") ) )
	    {
	      affect_strip( fch, skill_lookup("bloodthirsty") );
	      send_to_char(C_DEFAULT, skill_table[skill_lookup("bloodthirsty")].msg_off,fch);
	      send_to_char(C_DEFAULT, "\n\r",fch);
	    }
	    if ( IS_AFFECTED3(fch, AFF_BLOODTHIRSTY) )
	      REMOVE_BIT(fch->affected_by3, AFF_BLOODTHIRSTY);
	    update_pos( fch );
	}
    }

    return;
}



/*
 * Make a corpse out of a character.
 */
void make_corpse( CHAR_DATA *ch )
{
    OBJ_DATA        *corpse;
    OBJ_DATA        *obj;
    OBJ_DATA        *obj_next;
    char            *name;
    char             buf [ MAX_STRING_LENGTH ];

    if ( IS_NPC( ch ) )
    {
        /*
	 * This longwinded corpse creation routine comes about because
	 * we dont want anything created AFTER a corpse to be placed
	 * INSIDE a corpse.  This had caused crashes from obj_update()
	 * in extract_obj() when the updating list got shifted from
	 * object_list to obj_free.          --- Thelonius (Monk)
	 */

	if ( ch->gold > 0 )
	{
	    OBJ_DATA * coins;

	    coins         = create_money( ch->gold );
	    name	  = ch->short_descr;
	    if( IS_SET( ch->act, ACT_VEHICLE ) )
	    {
		corpse	  = create_object(
					  get_obj_index( OBJ_VNUM_CORPSE_VEHICLE ),
					  0 );
		corpse->value[0] = TAN_NONE;
		corpse->value[1] = 0;
	    }
	    else
	    {
		corpse	  = create_object(
					  get_obj_index( OBJ_VNUM_CORPSE_NPC ),
					  0 );
		
		corpse->value[0] = TAN_NPC;
		corpse->value[1] = ch->pIndexData->vnum;
	    }
	    corpse->timer = number_range( 2, 4 );
	    obj_to_obj( coins, corpse );
	    ch->gold = 0;
	}
	else
	{
	    name	  = ch->short_descr;
	    if( IS_SET( ch->act, ACT_VEHICLE ) )
	    {
		corpse	  = create_object(
					  get_obj_index( OBJ_VNUM_CORPSE_VEHICLE ),
					  0 );
		corpse->value[0] = TAN_NONE;
		corpse->value[1] = 0;
	    }
	    else
	    {
		corpse	  = create_object(
					  get_obj_index( OBJ_VNUM_CORPSE_NPC ),
					  0 );
		corpse->level    = ch->pIndexData->level;
		corpse->value[0] = TAN_NPC;
		corpse->value[1] = ch->pIndexData->vnum;

	    }
	    corpse->timer = number_range( 2, 4 );
	}
    }
    else
    {
	name		= ch->name;
	corpse		= create_object(
					get_obj_index( OBJ_VNUM_CORPSE_PC ),
					0 );
	corpse->value[0] = TAN_PC;
	corpse->value[1] = ch->level;
	corpse->timer	= number_range( 25, 40 );
	if ( ( ch->gold > 0 ) && ( ch->level > 5 ) )
	{
	  OBJ_DATA * coins;
	  coins = create_money( ch->gold );
	  obj_to_obj( coins, corpse );
	  ch->gold = 0;
	}
    }

    sprintf( buf, corpse->short_descr, name );
    free_string( corpse->short_descr );
    corpse->short_descr = str_dup( buf );

    sprintf( buf, corpse->description, name );
    free_string( corpse->description );
    corpse->description = str_dup( buf );

    for ( obj = ch->carrying; obj; obj = obj_next )
    {
	obj_next = obj->next_content;

        if ( obj->deleted )
	    continue;
	obj_from_char( obj );
	if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
	    extract_obj( obj );
	else
	    obj_to_obj( obj, corpse );
    }

    /* quill */
    if (  ( ch->level <= 50 && number_percent() <= 1 && number_percent() < 10)
	||( ch->level >  50 && ch->level < 90        && number_percent() < 2 )
	||( ch->level >= 90 && number_percent() < 3 ) )
    {
	obj = create_object( get_obj_index( OBJ_VNUM_QUILL ) , 1);
	obj_to_obj(obj, corpse);
    }

    /* pestle */
    if (  ( ch->level <= 50 && number_percent() <= 1 && number_percent() < 10)
	||( ch->level >  50 && ch->level < 90        && number_percent() < 2 )
	||( ch->level >= 90 && number_percent() < 3 ) )
    {
	obj = create_object( get_obj_index( OBJ_VNUM_PESTLE ) , 1);
	obj_to_obj(obj, corpse);
    }

    /* needle */
    if (  ( ch->level <= 50 && number_percent() <= 1 && number_percent() < 10)
	||( ch->level >  50 && ch->level < 90        && number_percent() < 2 )
	||( ch->level >= 90 && number_percent() < 3 ) )
    {
	obj = create_object( get_obj_index( OBJ_VNUM_NEEDLE ) , 1);
	obj_to_obj(obj, corpse);
    }


    sprintf( buf, "NPC killed: %s -> %d", ch->name, ch->in_room->vnum );
    log_string( buf, CHANNEL_NONE, -1 );
    if ( ( IS_NPC( ch ) ) && ( !IS_SET( ch->act, PLR_UNDEAD ) ) )
       corpse->ac_vnum=ch->pIndexData->vnum;
    if( !IS_SET( ch->act, ACT_NO_CORPSE ) )
    {
	obj_to_room( corpse, ch->in_room );
    }
    else
    {
	extract_obj( corpse );
    }

    if( !IS_NPC( ch ) )
    {
	corpse_back(ch, corpse );
    }

    return;
}



/*
 * Improved Death_cry contributed by Diavolo.
 */
void death_cry( CHAR_DATA *ch )
{
    ROOM_INDEX_DATA *was_in_room;
    char            *msg;
    int              vnum;
    int              door;

    vnum = 0;
    switch ( number_bits( 4 ) )
    {
    default: msg  = "You hear $n's death cry.";				break;
    case  0: msg  = "$n hits the ground ... DEAD.";			break;
    case  1: msg  = "$n splatters blood on your armor.";		break;
    case  2: msg  = "$n's innards fall to the ground with a wet splat.";     break;
    case  3: msg  = "$n's severed head plops on the ground.";
	     vnum = OBJ_VNUM_SEVERED_HEAD;				break;
    case  4: msg  = "$n's heart is torn from $s chest.";
	     vnum = OBJ_VNUM_TORN_HEART;				break;
    case  5: msg  = "$n's arm is sliced from $s dead body.";
	     vnum = OBJ_VNUM_SLICED_ARM;				break;
    case  6: msg  = "$n's leg is sliced from $s dead body.";
	     vnum = OBJ_VNUM_SLICED_LEG;				break;
    }

    act(AT_BLOOD, msg, ch, NULL, NULL, TO_ROOM );

    if ( vnum != 0 )
    {
	OBJ_DATA *obj;
	char     *name;
	char      buf [ MAX_STRING_LENGTH ];

	name		= IS_NPC( ch ) ? ch->short_descr : ch->name;
	obj		= create_object( get_obj_index( vnum ), 0 );
	obj->timer	= number_range( 4, 7 );

	sprintf( buf, obj->short_descr, name );
	free_string( obj->short_descr );
	obj->short_descr = str_dup( buf );

	sprintf( buf, obj->description, name );
	free_string( obj->description );
	obj->description = str_dup( buf );

	obj_to_room( obj, ch->in_room );
    }

    vnum = OBJ_VNUM_FINAL_TURD;
    if ( vnum != 0 )
    {
	OBJ_DATA *obj;

	obj		= create_object( get_obj_index( vnum ), 0 );
	obj->timer	= number_range( 3, 5 );

	obj_to_room( obj, ch->in_room );
    }
    if ( IS_NPC( ch ) )
	msg = "You hear something's death cry.";
    else
	msg = "You hear someone's death cry.";

    was_in_room = ch->in_room;
    for ( door = 0; door <= 5; door++ )
    {
	EXIT_DATA *pexit;

	if ( ( pexit = was_in_room->exit[door] )
	    && pexit->to_room
	    && pexit->to_room != was_in_room )
	{
	    ch->in_room = pexit->to_room;
	    act(AT_BLOOD, msg, ch, NULL, NULL, TO_ROOM );
	}
    }
    ch->in_room = was_in_room;

    return;
}



void raw_kill( CHAR_DATA *ch, CHAR_DATA *victim )
{
    AFFECT_DATA *paf;
    AFFECT_DATA *paf_next;
    ROOM_INDEX_DATA *location;

	if (victim->fighting)
		stop_fighting( victim, TRUE );
    if ( IS_NPC( victim) )
    {
        mprog_death_trigger( victim, ch );
    }
    rprog_death_trigger( victim->in_room, victim );
    make_corpse( victim );

    for ( paf = victim->affected; paf; paf = paf_next )
        {
     	 paf_next = paf->next;
         affect_remove( victim, paf );
        }
    for ( paf = victim->affected2; paf; paf = paf_next )
      {
       paf_next = paf->next;
       affect_remove2( victim, paf );
      }
    for ( paf = victim->affected3; paf; paf = paf_next )
      {
       paf_next = paf->next;
       affect_remove3( victim, paf );
      }
    for ( paf = victim->affected4; paf; paf = paf_next )
      {
       paf_next = paf->next;
       if (paf->type != skill_lookup("newbie slayer"))
	       affect_remove4( victim, paf );
      }
    for ( paf = victim->affected_powers; paf; paf = paf_next )
      {
       paf_next = paf->next;
       affect_remove_powers( victim, paf );
      }
    for ( paf = victim->affected_weaknesses; paf; paf = paf_next )
      {
       paf_next = paf->next;
       affect_remove_weaknesses( victim, paf );
      }

    victim->affected_by	= 0;
    victim->affected_by2 &= CODER;
    victim->affected_by3 = 0;
    victim->affected_by4 = 0;
    victim->affected_by_powers = 0;
    victim->affected_by_weaknesses = 0;
    victim->shields = 0;
    victim->poison_level = 0;
    if(!IS_NPC(victim) )
    {
	victim->pcdata->mod_str = 0;
	victim->pcdata->mod_int = 0;
	victim->pcdata->mod_dex = 0;
	victim->pcdata->mod_wis = 0;
	victim->pcdata->mod_con = 0;
    }
    if ( IS_NPC( victim ) )
    {
	victim->pIndexData->killed++;
	kill_table[URANGE( 0, victim->level, MAX_LEVEL-1 )].killed++;
	extract_char( victim, TRUE );
	return;
    }

    location = ch->in_room;
    extract_char( victim, FALSE );
    if( IS_SET( victim->act, PLR_GHOST ) )
    {
	char_from_room ( victim );
	char_to_room( victim, location );
    }

    victim->armor        = 100;
    if(IS_SET(victim->act, PLR_GHOST ) )
    {
        victim->position = POS_GHOST;
	victim->speaking = SPIRITSPEAK;
    }
    else
    {
        victim->position     = POS_RESTING;
    }
/*
    victim->hit	         = UMAX( 1, victim->hit  );
    victim->mana         = UMAX( 1, victim->mana );
    victim->bp           = UMAX( 1, victim->bp   );
    victim->move         = UMAX( 1, victim->move );
*/
    victim->hit		 = 1;
    victim->mana	 = 1;
    victim->bp		 = 1;
    victim->move	 = 1;
    victim->hitroll      = 0;
    victim->damroll      = 0;
    victim->saving_throw = 0;
    victim->carry_weight = 0;
    victim->carry_number = 0;
    victim->mounted	 = 0;
    victim->mountshort   = "";
    victim->mountcharmed = 0;

    victim->damage_mods[0] = 0;
    victim->damage_mods[1] = 0;
    victim->damage_mods[2] = 0;
    victim->damage_mods[3] = 0;
    victim->damage_mods[4] = 0;
    victim->damage_mods[5] = 0;
    victim->damage_mods[6] = 0;
    victim->damage_mods[7] = 0;
    victim->damage_mods[8] = 0;
    victim->damage_mods[9] = 0;
    victim->damage_mods[10] = 0;
    victim->damage_mods[11] = 0;
    victim->damage_mods[12] = 0;
    victim->damage_mods[13] = 0;
    victim->damage_mods[14] = 0;
    victim->damage_mods[15] = 0;
    victim->damage_mods[16] = 0;
    victim->damage_mods[17] = 0;
    victim->damage_mods[18] = 0;
    victim->damage_mods[19] = 0;

    save_char_obj( victim, FALSE );
    return;
}



void group_gain( CHAR_DATA *ch, CHAR_DATA *victim )
{
    CHAR_DATA *gch;
    CHAR_DATA *lch;
    char       buf[ MAX_STRING_LENGTH ];
    int        members;
    int        xp;

    /*
     * Monsters don't get kill xp's or alignment changes.
     * P-killing doesn't help either.
     * Dying of mortal wounds or poison doesn't give xp to anyone!
     */
    if ( IS_NPC( ch ) || victim == ch )
	return;

   /*
    * Killing in an arena won't get you anywhere either...
    * Arena's are for fun not experience...
    *                                           -- The Maniac! --
    */
    /* if ( !IS_NPC ( victim ) )
        return; */

    /*
     * If you're fighting a PC, and your victim is peaceful
     * then no xp for you!
     */
    if ((!IS_NPC(victim)) && (!victim->pkill))
	return;

    members = 0;
    for ( gch = ch->in_room->people; gch; gch = gch->next_in_room )
    {
	if ( is_same_group( gch, ch ) )
	    members++;
    }

    if ( members == 0 )
    {
	bug( "Group_gain: members.", members );
	members = 1;
    }

    lch = ( ch->leader ) ? ch->leader : ch;

    for ( gch = ch->in_room->people; gch; gch = gch->next_in_room )
    {
	OBJ_DATA *obj;
	OBJ_DATA *obj_next;

	if ( !is_same_group( gch, ch ) )
	    continue;

	// Newbie slayer code.
	// If victim is single class, and killer is multi. Tag with newbie slayer.
	if ( !IS_NPC(victim) && victim->class == victim->multied && gch->class != gch->multied && !victim->initiated)
	{
		tag_newbie_slayer( gch );
	}

	gch->initiated = FALSE;

        if (IS_SET(gch->act, PLR_QUESTOR)&&IS_NPC(victim))
        {
            if (gch->questmob == victim->pIndexData->vnum)
            {
                send_to_char(AT_WHITE, "You have almost completed your QUEST!\n\r",ch);
                send_to_char(AT_WHITE, "Return to the questmaster before your time runs out!\n\r",ch);
                ch->questmob = -1;
            }
        } else if(IS_SET(gch->act2, PLR_RELQUEST)&&IS_NPC(victim))
	{
	    if (gch->rquestmob[gch->relquest_level] == victim->pIndexData->vnum)
	    {
		DESCRIPTOR_DATA* d;
		for (d=descriptor_list; d; d = d->next)
                {
                	if ( d->connected != CON_PLAYING )
                        	continue;
                	if (is_same_group(d->character, gch))
                	{
				send_to_char(AT_WHITE, "This section of your religious quest is almost over!\n\r", d->character);
				d->character->rquestmob[gch->relquest_level] = -1;
                        }
                }

	    }
	}


	if ( gch->level - lch->level >= 6 )
	{
	    send_to_char(AT_BLUE, "You are too high level for this group.\n\r", gch );
	    continue;
	}

	if ( gch->level - lch->level <= -6 )
	{
	    send_to_char(AT_BLUE, "You are too low level for this group.\n\r",  gch );
	    continue;
	}

        // No xp for non pk's in pk fights
        if (!gch->pkill && !IS_NPC(victim))
        {
           continue;
        }

	if (((gch->level - victim->level) < -PKILL_RANGE) 
		&& (!IS_NPC(victim)))
        {
           send_to_char(AT_BLUE, "You must be within pkill level range for pkill xp.\n\r", gch);
	   continue;
        }

	if (((gch->level - victim->level) >= PKILL_RANGE) && (!IS_NPC(victim)))
        {
           send_to_char(AT_BLUE, "You must be within pkill level range for pkill xp.\n\r", gch);
	   continue;
        }

	if (members > 1)
        {
		// 150% xp because of group
		xp = (int) ((float) (xp_compute( gch, victim ) / members) * 1.5);

		// 10% bonus for leader
		if ( gch == lch )
      		{
      	   		xp = (int) ((float) xp * 1.1);
		}

		// 10% bonus for killer
		if ( ch == gch )
        	{
      	   		xp = (int) ((float) xp * 1.1);
		}

		// 10% bonus for mob's target
		if (gch == victim->fighting)
		{
      		   xp = (int) ((float) xp * 1.1);
		}
 	} else
        {
           xp = xp_compute(gch, victim);
        }

	if ( IS_AFFECTED4( gch, AFF_LUCK_SHIELD ) )
	{
	    if( gch->level < LEVEL_CHAMP )
	    {	
		xp += number_range( 50, 400 );
	    }
/*	    if( gch->level == LEVEL_CHAMP || gch->level == LEVEL_DEMIGOD ) */
	    if( gch->level == LEVEL_CHAMP )
 	    {
		xp += number_range( 50, 200 );
	    }
	    send_to_char(AT_YELLOW, "The luck of the gods grants you experience.\n\r", gch );
	}

	if (!gch->pkill || ( gch->level == LEVEL_DEMIGOD ) )
	{
        if ( xp > 450 )
          {
	    xp = 450;
          }

	if (gch->multied != gch->class )
	{
            xp /= 2;
	}

	if (gch->level == 1 || gch->level == 2 )
	{
	    xp *= 2;
	}
	if (gch->level == 3 || gch->level == 4 )
	{
	    xp *= 3 / 2;
	}

	}
        if ( !str_infix( race_table[lch->race].race_full,
                        race_table[gch->race].hate) && members > 1 )
          {
            send_to_char(AT_WHITE, "You lost a third of your exps due to grouping with scum.\n\r", ch );
            xp = (int)(xp * .66);
          }
        sprintf( buf, "%s -> gains %dxp", gch->name, xp);
        log_string( buf, CHANNEL_NONE, -1 );
	sprintf( buf, "You receive %d experience points.\n\r", xp );
	send_to_char(AT_WHITE, buf, gch );
	gain_exp( gch, xp );

	for ( obj = ch->carrying; obj; obj = obj_next )
	{
	    obj_next = obj->next_content;
	    if ( obj->deleted )
	        continue;
	    if ( obj->wear_loc == WEAR_NONE )
		continue;

            if ( !IS_NPC( ch ) )
	    if (   ( IS_OBJ_STAT( obj, ITEM_ANTI_EVIL    )
		    && IS_EVIL   ( ch ) )
		|| ( IS_OBJ_STAT( obj, ITEM_ANTI_GOOD    )
		    && IS_GOOD   ( ch ) )
		|| ( IS_OBJ_STAT( obj, ITEM_ANTI_NEUTRAL )
		    && IS_NEUTRAL( ch ) ) )
	    {
		act(AT_BLUE, "You are zapped by $p.", ch, obj, NULL, TO_CHAR );
		act(AT_BLUE, "$n is zapped by $p.",   ch, obj, NULL, TO_ROOM );
		obj_from_char( obj );
		obj_to_room( obj, ch->in_room );
	    }
	}
    }

    return;
}



/*
 * Compute xp for a kill.
 * Also adjust alignment of killer.
 * Edit this function to change xp computations.
 */
int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
    OBJ_DATA *obj;
    float     bonus;
    int xp;
    int align;
    int extra;
    int level;
    int number;

    bonus = 1.0;
    xp    = 150 - URANGE( -30, gch->level - victim->level, 5 ) * 30;
    align = gch->alignment - victim->alignment;

    if ( align >  500 )
    {
	gch->alignment  = UMIN( gch->alignment + ( align - 500 ) / 4,  1000 );
	xp = 5 * xp / 4;
    }
    else if ( align < -500 )
    {
	gch->alignment  = UMAX( gch->alignment + ( align + 500 ) / 4, -1000 );
	xp = 5 * xp / 4;
    }
    else
    {
	gch->alignment -= victim->alignment / 3;
	xp = 3 * xp / 4;
    }

    if ( IS_AFFECTED( victim, AFF_SANCTUARY )
        || IS_SET( race_table[ victim->race ].race_abilities, RACE_SANCT ) )
    {
        bonus += 1.0/2;
    }
    if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) )
    {
        bonus += 1.0/4;
    }

    if ( ( obj = get_eq_char( victim, WEAR_WIELD_2 ) ) )
    {
        bonus +=(float) (1.0/5);
    }

    if ( !str_infix( race_table[victim->race].race_full,
                    race_table[gch->race].hate ) )
    {
        bonus += (float)(1.0/10);
    }
    if ( victim->race == gch->race )
    {
        bonus -= (float)(1.0/8);
    }
    if ( IS_NPC( victim ) )
    {
        if ( IS_SET( victim->act, ACT_AGGRESSIVE ) )
        {
            bonus += (float)(1.0/20);
        }

        if ( victim->pIndexData->pShop != 0 )
            bonus -= (float)(1.0/4);

        if ( victim->spec_fun != 0 )
        {
            if (   victim->spec_fun == spec_lookup( "spec_breath_any"       )
                || victim->spec_fun == spec_lookup( "spec_cast_psionicist"  )
                || victim->spec_fun == spec_lookup( "spec_cast_undead"      )
                || victim->spec_fun == spec_lookup( "spec_breath_gas"       )
                || victim->spec_fun == spec_lookup( "spec_cast_mage"        ) )
                bonus += (float)(1.0/3);

            if (   victim->spec_fun == spec_lookup( "spec_breath_fire"      )
                || victim->spec_fun == spec_lookup( "spec_breath_cold"      )
                || victim->spec_fun == spec_lookup( "spec_breath_acid"      )
                || victim->spec_fun == spec_lookup( "spec_breath_lightning" )
                || victim->spec_fun == spec_lookup( "spec_cast_cleric"      )
                || victim->spec_fun == spec_lookup( "spec_cast_judge"       )
                || victim->spec_fun == spec_lookup( "spec_cast_ghost"       ) )
                bonus += (float)(1.0/5);

            if (   victim->spec_fun == spec_lookup( "spec_poison"           )
                || victim->spec_fun == spec_lookup( "spec_thief"            ) )
                bonus += (float)(1.0/20);

            if ( victim->spec_fun == spec_lookup( "spec_cast_adept"         ) )
                bonus -= (float)(1.0/2);
        }
    }
    else
    {
            bonus *= 2;
    }
    xp = (int) (xp * bonus);



    /*
     * Adjust for popularity of target:
     *   -1/8 for each target over  'par' (down to - 50%)
     *   +1/8 for each target under 'par' (  up to + 25%)
     */
    level  = URANGE( 0, victim->level, 99 );
    number = UMAX( 1, kill_table[level].number );
    if(IS_NPC(victim))
      extra  = victim->pIndexData->killed - kill_table[level].killed / number;
    else
      extra = 0;
    xp    -= xp * URANGE( -2, extra, 4 ) / 8;

    xp     = number_range( xp * 3 / 4, xp * 5 / 4 );
    xp     = UMAX( 0, xp );

    if(IS_NPC(victim) && IS_SET(victim->act, ACT_NO_EXP ) )
    {
	xp = 0;
    }

    if( ( victim->level < LEVEL_HERO ) && gch->level >= LEVEL_CHAMP )
    {
	xp = 0;
    }
    return xp;

}



void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
{
    static char * const  attack_table [ ] =
    {
	"hit",
	"slice",  "stab",    "slash", "whip", "claw",
	"blast",  "pound",   "crush", "grep", "bite",
	"pierce", "suction", "chop", "blast", "shot"
    };
    static char * const  damclass_attack_table [ ] =
    {
	"%s hit",
	"%s slice",  "%s stab",    "%s slash", "%s whip", "%s claw",
	"%s blast",  "%s pound",   "%s crush", "%s grep", "%s bite",
	"%s pierce", "%s suction", "%s chop", "%s blast", "%s shot"
    };

    const  char         *vs;
    const  char         *vp;
    const  char         *attack;
           char          buf          [ MAX_STRING_LENGTH ];
           char          buf1         [ 256 ];
           char          buf2         [ 256 ];
           char          buf3         [ 256 ];
           char          buf4         [ 256 ];
           char          buf5         [ 256 ];
	   char		 damclassbuf  [ MAX_STRING_LENGTH ];
           char          punct;

	 if ( dam <=   0 ) { vs = "miss";	vp = "misses";		}
    else if ( dam <=   4 ) { vs = "scratch";	vp = "scratches";	}
    else if ( dam <=   8 ) { vs = "graze";	vp = "grazes";		}
    else if ( dam <=  12 ) { vs = "hit";	vp = "hits";		}
    else if ( dam <=  16 ) { vs = "injure";	vp = "injures";		}
    else if ( dam <=  20 ) { vs = "wound";	vp = "wounds";		}
    else if ( dam <=  24 ) { vs = "maul";       vp = "mauls";		}
    else if ( dam <=  28 ) { vs = "decimate";	vp = "decimates";	}
    else if ( dam <=  32 ) { vs = "devastate";	vp = "devastates";	}
    else if ( dam <=  36 ) { vs = "maim";	vp = "maims";		}
    else if ( dam <=  40 ) { vs = "MUTILATE";	vp = "MUTILATES";	}
    else if ( dam <=  44 ) { vs = "DISEMBOWEL";	vp = "DISEMBOWELS";	}
    else if ( dam <=  48 ) { vs = "EVISCERATE";	vp = "EVISCERATES";	}
    else if ( dam <=  52 ) { vs = "MASSACRE";	vp = "MASSACRES";	}
    else if ( dam <= 100 ) { vs = "*** DEMOLISH ***";
			     vp = "*** DEMOLISHES ***";			}
    else if ( dam <= 150 ) { vs = "*** DEVASTATE ***";
			     vp = "*** DEVASTATES ***";			}
    else if ( dam <= 250 ) { vs = "*** OBLITERATE ***";
			     vp = "*** OBLITERATES ***";		}
    else if ( dam <= 300 ) { vs = "=== OBLITERATE ===";
			     vp = "=== OBLITERATES ===";		}
    else if ( dam <= 500 ) { vs = "*** ANNIHILATE ***";
			     vp = "*** ANNIHILATES ***";		}
    else if ( dam <= 750 ) { vs = ">>> ANNIHILATE <<<";
			     vp = ">>> ANNIHILATES <<<";		}
    else if ( dam <= 1000) { vs = "<<< ERADICATE >>>";
			     vp = "<<< ERADICATES >>>";			}
    else if ( dam <= 2000) { vs = "do UNSPEAKABLE things to";
			     vp = "does UNSPEAKABLE things to";		}
    else if ( dam <= 6000) { vs = "open a can of WOOP ASS on";
			     vp = "opens a can of WOOP ASS on";         }
    else                   { vs = "deal GODLIKE DAMAGE to";
			     vp = "deals GODLIKE DAMAGE to";    	}

    punct   = ( dam <= 24 ) ? '.' : '!';

    if ( dt == TYPE_HIT )
    {
        if ( ch->race > MAX_RACE )
        {
            bug( "Dam_message:  %d invalid race", ch->race );
            ch->race = 0;
        }

        attack = race_table[ ch->race ].dmg_message;

        sprintf( buf1, "Your %s %s $N%c (&R%d&W pts)",	attack, vp, punct, dam );
        sprintf( buf2, "$n's %s %s you%c (&R%d&W pts)",	attack, vp, punct, dam );
        sprintf( buf3, "$n's %s %s $N%c (&R%d&W pts)",	attack, vp, punct, dam );
        sprintf( buf4, "You %s %s yourself%c (&R%d&W pts)",	attack, vp, punct, dam );
        sprintf( buf5, "$n's %s %s $m%c (&R%d&W pts)",	attack, vp, punct, dam );
    }
    else
    {
	if ( is_sn(dt) )
	    attack	= skill_table[dt].noun_damage;
	else if (   dt >= TYPE_HIT
		 && dt  < TYPE_HIT
		        + sizeof( attack_table )/sizeof( attack_table[0] ) )
	{
   	  if (!dam_class_value)
	    attack	= attack_table[dt - TYPE_HIT];
	  else
	  {
	    sprintf(damclassbuf, damclass_attack_table[dt - TYPE_HIT], flag_string( damage_flags, dam_class_value ) );
	    attack = damclassbuf; 	
	  }
	}
	else
	{
	    sprintf( buf, "Dam_message: bad dt %d caused by %s.", dt,
		    ch->name );
	    bug( buf, 0 );
	    dt      = TYPE_HIT;
	    attack  = attack_table[0];
	}

	if ( dt > TYPE_HIT && is_wielding_poisoned( ch ) )
	{
	    sprintf( buf1, "Your poisoned %s %s $N%c (&R%d&W pts)", attack, vp, punct, dam );
	    sprintf( buf2, "$n's poisoned %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
	    sprintf( buf3, "$n's poisoned %s %s $N%c (&R%d&W pts)", attack, vp, punct, dam );
	    sprintf( buf4, "Your poisoned %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
	    sprintf( buf5, "$n's poisoned %s %s $n%c (&R%d&W pts)", attack, vp, punct, dam );
	}
	else
	{
	    sprintf( buf1, "Your %s %s $N%c (&R%d&W pts)",  attack, vp, punct, dam );
	    sprintf( buf2, "$n's %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
	    sprintf( buf3, "$n's %s %s $N%c (&R%d&W pts)",  attack, vp, punct, dam );
	    sprintf( buf4, "Your %s %s you%c (&R%d&W pts)", attack, vp, punct, dam );
	    sprintf( buf5, "$n's %s %s $n%c (&R%d&W pts)",  attack, vp, punct, dam );
	}
    }

    if ( victim != ch )
    {
        if ( dam != 0 || IS_SET( ch->act, PLR_COMBAT ) )
	  act(AT_WHITE, buf1, ch, NULL, victim, TO_CHAR    );
	if ( dam != 0 || IS_SET( victim->act, PLR_COMBAT ) )
	  act(AT_WHITE, buf2, ch, NULL, victim, TO_VICT    );
	act(AT_GREY, buf3, ch, NULL, victim,
	    dam == 0 ? TO_COMBAT : TO_NOTVICT );
    }
    else
    {
        if ( dam != 0 || IS_SET( ch->act, PLR_COMBAT ) )
	  act(AT_WHITE, buf4, ch, NULL, victim, TO_CHAR    );
  	act(AT_GREY, buf5, ch, NULL, victim,
	    dam == 0 ? TO_COMBAT : TO_NOTVICT );
     }

    return;
}



/*
 * Disarm a creature.
 * Caller must check for successful attack.
 */
void disarm( CHAR_DATA *ch, CHAR_DATA *victim )
{
    OBJ_DATA *obj;

    if ( ( race_table[ ch->race ].size - race_table[ victim->race ].size )
        < -2 )
        return;

    if ( !( obj = get_eq_char( victim, WEAR_WIELD ) ) )
	if ( !( obj = get_eq_char( victim, WEAR_WIELD_2 ) ) )
	   return;

    if ( !get_eq_char( ch, WEAR_WIELD ) && number_bits( 1 ) == 0 )
	if ( !get_eq_char( ch, WEAR_WIELD_2 ) && number_bits( 1 ) == 0 )
	   return;

    act(AT_YELLOW, "You disarm $N!",  ch, NULL, victim, TO_CHAR    );
    act(AT_YELLOW, "$n DISARMS you!", ch, NULL, victim, TO_VICT    );
    act(AT_GREY, "$n DISARMS $N!",  ch, NULL, victim, TO_NOTVICT );

    obj_from_char( obj );
    if ( IS_NPC( victim ) )
	obj_to_char( obj, victim );
    else
	obj_to_char( obj, victim );
    return;
}


void do_kill( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];

    one_argument( argument, arg );

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
      send_to_char( AT_WHITE, "That person is not here.\n\r", ch );
      return;
    }

    if ( is_safe( ch, victim ) )
      {
       send_to_char( AT_WHITE, "You cannot.\n\r", ch );
       return;
      }

    if ( arg[0] == '\0' )
    {
	send_to_char(AT_WHITE, "Kill whom?\n\r", ch );
	return;
    }

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
	send_to_char(AT_WHITE, "They aren't here.\n\r", ch );
	return;
    }

    if ( IS_AFFECTED(victim, AFF_PEACE ))
    {
      send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ))
    {
      send_to_char(AT_WHITE, "You must leave the shadow realm.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED4( ch, AFF_BURROW ))
    {
      send_to_char(AT_WHITE, "You must wait until the earth heals you!\n\r", ch);
      return;
    }
    if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ))
    {
      send_to_char(AT_WHITE, "You can not attack someone who is in the shadow plane.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED4( victim, AFF_BURROW ))
    {
      send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED( ch, AFF_PEACE ) )
    {
	    affect_strip( ch, skill_lookup("aura of peace" ));
	    REMOVE_BIT( ch->affected_by, AFF_PEACE );
    }
    if ( !IS_NPC( victim ) )
    {
	if (   !IS_SET( victim->act, PLR_KILLER )
	    && !IS_SET( victim->act, PLR_THIEF  ) )
	{
	    send_to_char(AT_WHITE, "You must MURDER a player.\n\r", ch );
	    return;
	}
    }
    else
    {
	if ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master )
	{
	    send_to_char(AT_WHITE, "You must MURDER a charmed creature.\n\r", ch );
	    return;
	}
    }

    if ( victim == ch )
    {
	send_to_char(AT_RED, "You hit yourself.  Stupid!\n\r", ch );
	multi_hit( ch, ch, TYPE_UNDEFINED );
	return;
    }

    if ( IS_AFFECTED( ch, AFF_CHARM ) && ch->master == victim )
    {
	act(AT_BLUE, "$N is your beloved master!", ch, NULL, victim, TO_CHAR );
	return;
    }

    if ( ch->position == POS_FIGHTING )
    {
	send_to_char(C_DEFAULT, "You do the best you can!\n\r", ch );
	return;
    }

    WAIT_STATE( ch, PULSE_VIOLENCE );
    check_killer( ch, victim );
    multi_hit( ch, victim, TYPE_UNDEFINED );
    return;
}



void do_murde( CHAR_DATA *ch, char *argument )
{
    send_to_char(C_DEFAULT, "If you want to MURDER, spell it out.\n\r", ch );
    return;
}



void do_murder( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    char       buf [ MAX_STRING_LENGTH ];
    char       arg [ MAX_INPUT_LENGTH  ];

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char(C_DEFAULT, "Murder whom?\n\r", ch );
	return;
    }

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
	send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	return;
    }

    if ( victim == ch ){
        send_to_char(C_DEFAULT, "Suicide is a mortal sin.\n\r", ch );
	return;
    }

    if ( !is_pkillable( ch, victim ) ) {
    	return;
    }

    if ( IS_AFFECTED(victim, AFF_PEACE ))
    {
      send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ))
    {
      send_to_char(AT_WHITE, "You must leave the shadow realm.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED4( ch, AFF_BURROW ))
    {
      send_to_char(AT_WHITE, "You must wait until the earth heals you!\n\r", ch);
      return;
    }
    if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ))
    {
      send_to_char(AT_WHITE, "You can not attack someone who is in the shadow plane.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED4( victim, AFF_BURROW ))
    {
      send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch);
      return;
    }
    if ( IS_AFFECTED( ch, AFF_PEACE ))
    {
	    affect_strip( ch, skill_lookup("aura of peace") );
	    REMOVE_BIT( ch->affected_by, AFF_PEACE );
    }

    if (!IS_NPC(victim))
    	ch->pkill_timer = 0;

    if ( IS_AFFECTED( ch, AFF_CHARM ) && ch->master == victim )
    {
	act(C_DEFAULT, "$N is your beloved master!", ch, NULL, victim, TO_CHAR );
	return;
    }

    if ( ch->position == POS_FIGHTING )
    {
	send_to_char(C_DEFAULT, "You do the best you can!\n\r", ch );
	return;
    }

    WAIT_STATE( ch, PULSE_VIOLENCE );
    sprintf( buf, "Help!  I am being attacked by %s!", ch->name );
    if( IS_NPC( ch ) )
    {
	sprintf( buf, "Help!  I am being attacked by %s!", ch->short_descr );
    }
    do_shout( victim, buf );
    multi_hit( ch, victim, TYPE_UNDEFINED );
    return;
}



int skill_backstab( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA  *obj;
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];

    one_argument( target_name, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char(C_DEFAULT, "Backstab whom?\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
	send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	return SKPELL_BOTCHED;
    }

    if ( victim == ch )
    {
	send_to_char(C_DEFAULT, "How can you sneak up on yourself?\n\r", ch );
	return SKPELL_BOTCHED;
    }

    if ( !( obj = get_eq_char( ch, WEAR_WIELD ) )
	|| obj->value[3] != 11 )
    {
	send_to_char(C_DEFAULT, "You need to wield a piercing weapon.\n\r", ch );
	return SKPELL_BOTCHED;
    }

    if ( victim->fighting )
    {
	send_to_char(C_DEFAULT, "You can't backstab a fighting person.\n\r", ch );
	return SKPELL_BOTCHED;
    }

    if ( victim->hit < (victim->max_hit-200) )
    {
	act(C_DEFAULT, "$N is hurt and suspicious ... you can't sneak up.",
	    ch, NULL, victim, TO_CHAR );
	return SKPELL_BOTCHED;
    }

    if ( !is_pkillable( ch, victim ) ) {
    	return SKPELL_MISSED;
    }

    if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ))
    {
      send_to_char(AT_WHITE, "You must leave the shadow realm.\n\r", ch);
      return SKPELL_MISSED;
    }
    if ( IS_AFFECTED4( ch, AFF_BURROW ))
    {
      send_to_char(AT_WHITE, "You must wait until the earth heals you!\n\r", ch);
      return SKPELL_MISSED;
    }

    if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ))
    {
      send_to_char(AT_WHITE, "You can not attack someone who is in the shadow plane.\n\r", ch);
      return SKPELL_MISSED;
    }
    if ( IS_AFFECTED4( victim, AFF_BURROW ))
    {
      send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch);
      return SKPELL_MISSED;
    }

    if ( IS_AFFECTED( victim, AFF_PEACE ) )
    {
      send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
      return SKPELL_MISSED;
    }

    if (!IS_NPC(victim))
    	ch->pkill_timer = 0;

    check_killer( ch, victim );
    WAIT_STATE( ch, skill_table[sn].beats );
    if ( !IS_AWAKE( victim )
	|| IS_NPC( ch )
	|| number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	multi_hit( ch, victim, sn );
    }
    else
		damage( ch, victim, 0, sn );

    return SKPELL_NO_DAMAGE; 
}

int skill_assassinate( int sn, int level, CHAR_DATA *ch, void *vo )
{
    OBJ_DATA  *obj;
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
    int	       chance;


    chance = IS_NPC( ch ) ? 0 : ( ch->pcdata->learned[skill_lookup("mind of fanoom")] / 10 ) ;
    if( chance > 0 && !IS_IMMORTAL( ch ) && !IS_NPC( ch ) )
    {
	chance = chance - ( 10 * ( LEVEL_DEMIGOD - ch->level ) );
    }

    one_argument( target_name, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char(C_DEFAULT, "Assassinate whom?\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
	send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( victim == ch )
    {
	send_to_char(C_DEFAULT, "How can you sneak up on yourself?\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( victim->fighting )
    {
	send_to_char(C_DEFAULT, "You can't assassinate a fighting person.\n\r", ch );
	return SKPELL_MISSED;
    }

    if( chance <= 0 )
    {
	if ( victim->hit < (victim->max_hit - 200) )
	{
	    act(C_DEFAULT, "$N is hurt and suspicious ... you can't sneak up.",
		ch, NULL, victim, TO_CHAR );
	    return SKPELL_MISSED;
        }
    }
    else
    {
	if ( ( victim->hit < victim->max_hit/2 || chance < number_percent( ) ) && ( victim->hit < victim->max_hit - 200 ) )
	{
	    act(C_DEFAULT, "$N is hurt and suspicious ... you can't sneak up.",
		ch, NULL, victim, TO_CHAR );
	    return SKPELL_MISSED;
	}
    }

    if ( !( obj = get_eq_char( ch, WEAR_WIELD ) )
	|| obj->value[3] != 11 )
    {
	send_to_char(C_DEFAULT, "You need to wield a piercing weapon.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !is_pkillable( ch, victim ) ) {
    	return SKPELL_MISSED;
    }

    if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE ))
    {
      send_to_char(AT_WHITE, "You must leave the shadow realm.\n\r", ch);
      return SKPELL_MISSED;
    }
    if ( IS_AFFECTED4( ch, AFF_BURROW ))
    {
      send_to_char(AT_WHITE, "You must wait until the earth heals you!\n\r", ch);
      return SKPELL_MISSED;
    }

    if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE ))
    {
      send_to_char(AT_WHITE, "You can not attack someone who is in the shadow plane.\n\r", ch);
      return SKPELL_MISSED;
    }
    if ( IS_AFFECTED4( victim, AFF_BURROW ))
    {
      send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch);
      return SKPELL_MISSED;
    }

    if ( IS_AFFECTED( victim, AFF_PEACE ) )
    {
      send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch);
      return SKPELL_MISSED;
    }
    if ( !IS_NPC ( ch ) )
    {
	if ( number_percent( ) > ( ch->pcdata->learned[sn] / 10 )  )
	{
	    send_to_char(C_DEFAULT, "You failed.\n\r", ch );
	    return SKPELL_MISSED;
	}
    }

    if (!IS_NPC(victim))
    	ch->pkill_timer = 0;

    WAIT_STATE( ch, skill_table[sn].beats );
    update_skpell( ch, skill_lookup("mind of fanoom"), 0 );
    multi_hit( ch, victim, sn );

    return SKPELL_NO_DAMAGE;
}



void do_flee( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA       *victim;
    ROOM_INDEX_DATA *was_in;
    ROOM_INDEX_DATA *now_in;
    int              attempt;

    if ( IS_AFFECTED( ch, AFF_ANTI_FLEE ) )
    {
      send_to_char( AT_RED, "You cannot!\n\r", ch );
      return;
    }

    if ( !IS_NPC(ch) && (IS_AFFECTED3(ch, AFF_BLOODTHIRSTY) || IS_AFFECTED2(ch, AFF_BERSERK)) )
    {
      send_to_char( AT_RED, "You cannot!\n\r", ch );
      return;
    }

    if ( !( victim = ch->fighting ) )
    {
	if ( ch->position == POS_FIGHTING )
	    ch->position = POS_STANDING;
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return;
    }
    if ( IS_SET( ch->in_room->room_flags, ROOM_NO_FLEE ) )
      {
       send_to_char(C_DEFAULT, "You failed!  You lose 10 exps.\n\r", ch );
       gain_exp( ch, -10 );
       return;
      }

    was_in = ch->in_room;
    for ( attempt = 0; attempt < 6; attempt++ )
    {
	EXIT_DATA *pexit;
	int        door;

	door = number_door( );
	if ( ( pexit = was_in->exit[door] ) == 0
	    ||   !pexit->to_room
            ||   (IS_SET(pexit->to_room->room_flags, ROOM_SAFE) && ch->pkill)
	    ||   IS_SET( pexit->exit_info, EX_CLOSED )
            || (IS_SET( pexit->exit_info, EX_HIDDEN)
                &&
!IS_SET (race_table[ch->race].race_abilities,RACE_DETECT_HIDDEN_EXIT ) )
	    || ( IS_NPC( ch )
		&& ( IS_SET( pexit->to_room->room_flags, ROOM_NO_MOB )
		    || ( IS_SET( ch->act, ACT_STAY_AREA )
			&& pexit->to_room->area != ch->in_room->area ) ) ) )
	    continue;

	move_char( ch, door );
	if ( ( now_in = ch->in_room ) == was_in )
	    continue;

	ch->in_room = was_in;
	act(C_DEFAULT, "$n has fled!", ch, NULL, NULL, TO_ROOM );
	ch->in_room = now_in;

	if ( !IS_NPC( ch ) )
	{
	    send_to_char(C_DEFAULT, "You flee from combat!  You lose 25 exps.\n\r", ch );
	    gain_exp( ch, -25 );
	}

        if ( ch->fighting && IS_NPC( ch->fighting ) )
          if ( IS_SET( ch->fighting->act, ACT_TRACK ) )
            ch->fighting->hunting = ch;

	stop_fighting( ch, TRUE );
	return;
    }

    send_to_char(C_DEFAULT, "You failed!  You lose 10 exps.\n\r", ch );
    gain_exp( ch, -10 );
    return;
}

int skill_retreat( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA       *victim;
    ROOM_INDEX_DATA *was_in;
    ROOM_INDEX_DATA *now_in;
    int              attempt;

    if (IS_AFFECTED( ch, AFF_ANTI_FLEE ) )
    {
      send_to_char( AT_RED, "You cannot!\n\r", ch );
      return SKPELL_BOTCHED;
    }

    if ( !( victim = ch->fighting ) )
    {
	if ( ch->position == POS_FIGHTING )
	    ch->position = POS_STANDING;
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }
    if ( IS_SET( ch->in_room->room_flags, ROOM_NO_FLEE ) )
      {
       send_to_char(C_DEFAULT, "You failed your retreat!\n\r", ch );
       return SKPELL_MISSED;
      }

    was_in = ch->in_room;
    for ( attempt = 0; attempt < 6; attempt++ )
    {
	EXIT_DATA *pexit;
	int        door;

	door = number_door( );
	if ( ( pexit = was_in->exit[door] ) == 0
	    ||   !pexit->to_room
            ||   (IS_SET(pexit->to_room->room_flags, ROOM_SAFE) && ch->pkill)
	    ||   IS_SET( pexit->exit_info, EX_CLOSED )
	    || ( IS_NPC( ch )
		&& ( IS_SET( pexit->to_room->room_flags, ROOM_NO_MOB )
		    || ( IS_SET( ch->act, ACT_STAY_AREA )
			&& pexit->to_room->area != ch->in_room->area ) ) ) )
	    continue;

	move_char( ch, door );
	if ( ( now_in = ch->in_room ) == was_in )
	    continue;

	ch->in_room = was_in;
	act(C_DEFAULT, "$n has retreated!", ch, NULL, NULL, TO_ROOM );
	ch->in_room = now_in;

	if ( !IS_NPC( ch ) )
	{
	    send_to_char(C_DEFAULT, "You retreated successfully!\n\r", ch );
	}

        if ( ch->fighting && IS_NPC( ch->fighting ) )
          if ( IS_SET( ch->fighting->act, ACT_TRACK ) )
            ch->fighting->hunting = ch;

	stop_fighting( ch, TRUE );
	return SKPELL_NO_DAMAGE;
    }

    send_to_char(C_DEFAULT, "You failed your retreat!\n\r", ch );
    return SKPELL_MISSED;
}

int skill_rescue( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    CHAR_DATA *fch;
    char       arg [ MAX_INPUT_LENGTH ];

    one_argument( target_name, arg );

    if ( arg[0] == '\0' )
    {
	send_to_char(C_DEFAULT, "Rescue whom?\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
	send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( victim == ch )
    {
	send_to_char(C_DEFAULT, "What about fleeing instead?\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !IS_NPC( ch ) && IS_NPC( victim ) )
    {
	send_to_char(C_DEFAULT, "Doesn't need your help!\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( ch->fighting == victim )
    {
	send_to_char(C_DEFAULT, "Too late.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !( fch = victim->fighting ) )
    {
	send_to_char(C_DEFAULT, "That person is not fighting right now.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !is_same_group( ch, victim ) && (ch->clan != victim->clan))
    {
	send_to_char(C_DEFAULT, "Why would you want to?\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind ( ch ) )
        return SKPELL_MISSED;

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( !IS_NPC( ch ) && number_percent( ) > ( ch->pcdata->learned[sn] / 10 )  )
    {
	send_to_char(C_DEFAULT, "You fail the rescue.\n\r", ch );
	return SKPELL_MISSED;
    }

    act(C_DEFAULT, "You rescue $N!",  ch, NULL, victim, TO_CHAR    );
    act(C_DEFAULT, "$n rescues you!", ch, NULL, victim, TO_VICT    );
    act(C_DEFAULT, "$n rescues $N!",  ch, NULL, victim, TO_NOTVICT );

    stop_fighting( fch, FALSE );

    set_fighting( fch, ch );

    return SKPELL_NO_DAMAGE;
}



int skill_gouge( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam = 0;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	dam = number_range(ch->level * 2, ch->level * 5);// damage( ch, victim, number_range( ch->level*2, ch->level*5 ), sn );

	if IS_AFFECTED(victim, AFF_BLIND)
	return dam;

	if IS_AFFECTED2(victim, AFF_BLINDFOLD)
	return dam;

        else
	if ( number_percent( ) < 50 )
        {
	AFFECT_DATA af;

	af.type      = skill_lookup("blindness");
	af.level     = ch->level;
	af.duration  = 5;
	af.location  = APPLY_HITROLL;
	af.modifier  = -50;
	af.bitvector = AFF_BLIND;
	affect_join( victim, &af );

        act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_CHAR    );
        send_to_char(AT_WHITE, "You are blinded!\n\r", victim );
        act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_NOTVICT );
        return dam;
        }

    update_pos( victim );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_gouge );

    return dam;
}

int skill_rake( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam = 0;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
		dam = number_range(ch->level * 2,ch->level * 5); //damage( ch, victim, number_range( ch->level*2, ch->level*5 ), sn );

	if IS_AFFECTED2(victim, AFF_BLINDFOLD)
		return dam;

	if IS_AFFECTED(victim, AFF_BLIND)
		return dam;

        else
	if ( number_percent( ) < 50 )
        {
	AFFECT_DATA af;

	af.type      = skill_lookup("blindness");
	af.level     = ch->level;
	af.duration  = 5;
	af.location  = APPLY_HITROLL;
	af.modifier  = -50;
	af.bitvector = AFF_BLIND;
	affect_join( victim, &af );

        act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_CHAR    );
        send_to_char(AT_WHITE, "You are blinded!\n\r", victim );
        act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_NOTVICT );
        return dam;
        }

    update_pos( victim );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_rake );

    return dam;
}

int skill_back_kick( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam = 0;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    one_argument( target_name, arg);

    victim = ch->fighting;

    if ( arg[0] != '\0' )
       if ( !(victim = get_char_room( ch, arg ) ) )
       {
	send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	return SKPELL_MISSED;
       }

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
		dam = number_range( ch->level*5, ch->level*13 );
	//damage( ch, victim, number_range( ch->level*5, ch->level*13 ), sn );
    }
    else
		dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, sn );

    return dam;
}


int skill_circle( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam = 0;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats/2 );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	 dam = number_range(ch->level*5, ch->level*14); //damage( ch, victim, number_range( ch->level*5, ch->level*14 ), gsn_circle );
        update_pos( victim );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_circle );

    return dam;
}

int skill_dim_mak( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam;
      

    if ( IS_NPC( ch ) )
      if ( IS_SET( ch->affected_by, AFF_CHARM ) )
        return SKPELL_MISSED;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < (ch->pcdata->learned[sn]/20) )
    {
		dam = number_range( (int)(victim->hit * .5), (int)(victim->hit * .6) ); //damage( ch, victim, number_range( (int)(victim->hit * .5), (int)(victim->hit * .6) ), gsn_dim_mak );
        update_pos( victim );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_dim_mak );

    return dam;
}

int skill_kick( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	dam = number_range(ch->level*3, ch->level*9); //damage( ch, victim, number_range( ch->level*3, ch->level*9 ), gsn_kick );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_kick );

    return dam; 
}

int skill_slam( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	dam = number_range(ch->level * 8, ch->level * 19); //damage( ch, victim, number_range( ch->level*8, ch->level*19 ), gsn_slam );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_slam );

    return dam;
}

int skill_claw( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	dam = number_range(ch->level * 5, ch->level * 7); //damage( ch, victim, number_range( ch->level*5, ch->level*7 ), gsn_claw );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_claw );

    return dam;
}

int skill_bite( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam = 0;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	dam = number_range(ch->level * 7, ch->level * 10); //damage( ch, victim, number_range( ch->level*7, ch->level*10 ), sn );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, sn );

    return dam;
}
int skill_shriek( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam = 0;
      

    if IS_AFFECTED2( ch, AFF_SLIT )
    {
	send_to_char(AT_BLOOD, "You gargle through your slit throat.\n\r", ch);
	return SKPELL_MISSED;
    }

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
		dam = number_range(ch->level * 5, ch->level * 10); //damage( ch, victim, number_range( ch->level*5, ch->level*10),gsn_shriek );

        send_to_char(AT_BLOOD, "Your deadly wail shatters the air!\n\r",ch);
        send_to_char(AT_BLOOD, "Your hearing is damaged!\n\r", victim );
        act(AT_BLOOD, "$n shatters the air with a deadly wail!", ch, NULL, NULL, TO_ROOM );
        return dam;
     }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_shriek );

    return dam;
}

int skill_dirt_kick( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You kick some dirt into the air.\n\r", ch );
	return SKPELL_MISSED;
    }


    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	dam = number_range(ch->level * 2, ch->level * 5); //damage( ch, victim, number_range( ch->level*2, ch->level*5 ), gsn_dirt_kick );

	if IS_AFFECTED(victim, AFF_BLIND)
	return dam;

	if IS_AFFECTED2(victim, AFF_BLINDFOLD)
	return dam;

        else
	if ( number_percent( ) < 40 )
        {
	AFFECT_DATA af;

	af.type      = skill_lookup("blindness");
	af.level     = ch->level;
	af.duration  = 1;
	af.location  = APPLY_HITROLL;
	af.modifier  = -50;
	af.bitvector = AFF_BLIND;
	affect_join( victim, &af );

        act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_CHAR    );
        send_to_char(AT_WHITE, "The dirt blinds you!!\n\r", victim );
        act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_NOTVICT );
        return dam;
        }

    update_pos( victim );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, sn );

    return dam;
}


int skill_chop( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam = 0;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	dam = number_range(ch->level * 3, (int)(ch->level * 6.15)); //damage( ch, victim, number_range( ch->level*3, (int)(ch->level*6.15) ), gsn_chop );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_chop );

    return dam;
}

int skill_head_butt( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ];
	int dam = 0;

    if ( !ch->fighting )
    {
	send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
	return SKPELL_MISSED;
    }

    if ( !check_blind( ch ) )
        return SKPELL_MISSED;

    one_argument( target_name, arg );

    victim = ch->fighting;

    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
	{
	    send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
	    return SKPELL_MISSED;
	}

    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
	 dam = number_range(ch->level * 3, ch->level * 8); //damage( ch, victim, number_range( ch->level*3, ch->level*8 ), gsn_head_butt );
    }
    else
	dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_head_butt );

    return dam;
}

int damclass_adjust(CHAR_DATA *victim, int dam, int sn)
{
    int 	mod = 0;
     
   if (sn < TYPE_HIT)

	switch (skill_table[sn].damclass)
	{
	case DAMCLASS_NULL:
	break;
	case DAMCLASS_ACID :
	    mod = victim->damage_mods[0];
	    break;
	case DAMCLASS_HOLY :
	    mod = victim->damage_mods[1];
	    break;
	case DAMCLASS_MAGIC :
	    mod = victim->damage_mods[2];
	    break;
	case DAMCLASS_FIRE :
	    mod = victim->damage_mods[3];
	    break;
	case DAMCLASS_ENERGY :
	    mod = victim->damage_mods[4];
	    break;
	case DAMCLASS_WIND :
	    mod = victim->damage_mods[5];
	    break;
	case DAMCLASS_WATER :
	    mod = victim->damage_mods[6];
	    break;
	case DAMCLASS_ILLUSION :
	    mod = victim->damage_mods[7];
	    break;
	case DAMCLASS_DISPEL :
	    mod = victim->damage_mods[8];
	    break;
	case DAMCLASS_EARTH :
	    mod = victim->damage_mods[9];
	    break;
	case DAMCLASS_PSYCHIC :
	    mod = victim->damage_mods[10];
	    break;
	case DAMCLASS_POISON :
	    mod = victim->damage_mods[11];
	    break;
	case DAMCLASS_BREATH :
	    mod = victim->damage_mods[12];
	    break;
	case DAMCLASS_SUMMON :
	    mod = victim->damage_mods[13];
	    break;
	case DAMCLASS_PHYSICAL :
	    mod = victim->damage_mods[14];
	    break;
	case DAMCLASS_EXPLOSIVE :
	    mod = victim->damage_mods[15];
	    break;
	case DAMCLASS_SONG :
	    mod = victim->damage_mods[16];
	    break;
	case DAMCLASS_NAGAROM :
	    mod = victim->damage_mods[17];
	    break;
	case DAMCLASS_UNHOLY :
	    mod = victim->damage_mods[18];
	    break;
	case DAMCLASS_CLAN :
	    mod = victim->damage_mods[19];
	    break;
	default:
		break;
	}
    if (sn >=TYPE_HIT || sn == TYPE_UNDEFINED)
    {
	if (!dam_class_value)
		mod = victim->damage_mods[14];
	else
		mod = victim->damage_mods[dam_class_value];
    }
	mod = URANGE( -75, mod, 75);
	damclass_shield_weaken(victim, dam, sn);

	dam = dam - (dam * mod) / 100;
	return dam;
}

bool can_use_skspell(CHAR_DATA *ch, int skspellNum)
{
	/*char buf[1000];
	sprintf(buf, "gsn: %d, skillName: %s, level: %d, multi: %d",
			skspellNum, skill_table[skspellNum].name,
			skill_table[skspellNum].skill_level[ch->class],
			skill_table[skspellNum].skill_level[ch->multied]);
	if( !IS_NPC(ch) ) {
		bug(buf, 0);
	}*/
	if ( !IS_NPC( ch )&&(( ch->level < skill_table[skspellNum].skill_level[ch->class] )
        && (ch->level < skill_table[skspellNum].skill_level[ch->multied]))) {
		return FALSE;
	} else if (IS_NPC( ch ))
	{
		int gsn   = skspellNum;

		if (ch->level < 5 && ( gsn == skill_lookup("second attack") || gsn == skill_lookup("second strike") ) )
			return FALSE;
		if (ch->level < 15 && ( gsn == skill_lookup("third attack") || gsn == skill_lookup("third strike") ) )
			return FALSE;
		if (ch->level < 25 && ( gsn == skill_lookup("fourth attack") || gsn == skill_lookup("fourth strike") ) )
			return FALSE;
		if (ch->level < 35 && ( gsn == skill_lookup("fifth attack") || gsn == skill_lookup("fifth strike") ) )
			return FALSE;
		if (ch->level < 40 && ( gsn == skill_lookup("sixth attack") || gsn == skill_lookup("sixth strike") ) )
			return FALSE;
		if (ch->level < 45 && ( gsn == skill_lookup("seventh attack") || gsn == skill_lookup("seventh strike") ) )
			return FALSE;
		if (ch->level < 50 && ( gsn == skill_lookup("eighth attack") || gsn == skill_lookup("eighth strike") ) )
			return FALSE;
	}


	return TRUE;
}

void damclass_shield_weaken(CHAR_DATA *victim, int dam, int dt)
{
	int adjustment = dam /200;
	int damclass = 0;
	bool found = FALSE;
	int index = 0;
	int apply_loc = APPLY_NONE;
	AFFECT_DATA * paf;
	if (dt >= TYPE_HIT)
		damclass = DAMCLASS_PHYSICAL;
	else
		damclass = skill_table[dt].damclass;

	switch (damclass)
	{
	case DAMCLASS_ACID:
		apply_loc = APPLY_DAM_ACID;
		index = 0;
		break;
	case DAMCLASS_HOLY:
		apply_loc = APPLY_DAM_HOLY;
		index = 1;
		break;
	case DAMCLASS_MAGIC:
		apply_loc = APPLY_DAM_MAGIC;
		index = 2;
		break;
	case DAMCLASS_FIRE:
		apply_loc = APPLY_DAM_FIRE;
		index = 3;
		break;
	case DAMCLASS_ENERGY:
		apply_loc = APPLY_DAM_ENERGY;
		index = 4;
		break;
	case DAMCLASS_WIND:
		apply_loc = APPLY_DAM_WIND;
		index = 5;
		break;
	case DAMCLASS_WATER:
		apply_loc = APPLY_DAM_WATER;
		index = 6;
		break;
	case DAMCLASS_ILLUSION:
		apply_loc = APPLY_DAM_ILLUSION;
		index = 7;
		break;
	case DAMCLASS_DISPEL:
		apply_loc = APPLY_DAM_DISPEL;
		index = 8;
		break;
	case DAMCLASS_EARTH:
		apply_loc = APPLY_DAM_EARTH;
		index = 9;
		break;
	case DAMCLASS_PSYCHIC:
		apply_loc = APPLY_DAM_PSYCHIC;
		index = 10;
		break;
	case DAMCLASS_POISON:
		apply_loc = APPLY_DAM_POISON;
		index = 11;
		break;
	case DAMCLASS_BREATH:
		apply_loc = APPLY_DAM_BREATH;
		index = 12;
		break;
	case DAMCLASS_SUMMON:
		apply_loc = APPLY_DAM_SUMMON;
		index = 13;
		break;
	case DAMCLASS_PHYSICAL:
		apply_loc = APPLY_DAM_PHYSICAL;
		index = 14;
		break;
	case DAMCLASS_EXPLOSIVE:
		apply_loc = APPLY_DAM_EXPLOSIVE;
		index = 15;
		break;
	case DAMCLASS_SONG:
		apply_loc = APPLY_DAM_SONG;
		index = 16;
		break;
	case DAMCLASS_NAGAROM:
		apply_loc = APPLY_DAM_NAGAROM;
		index = 17;
		break;
	case DAMCLASS_UNHOLY:
		apply_loc = APPLY_DAM_UNHOLY;
		index = 18;
		break;
	case DAMCLASS_CLAN:
		apply_loc = APPLY_DAM_CLAN;
		index = 19;
		break;
	default:
		return;
	}

	for (paf = victim->affected; paf; paf = paf->next)
	{
		if (paf->deleted)
			continue;
		if (found)
			break;
		/* Ok, first we find the right affect... */
		if ((paf->location == apply_loc) && (paf->modifier > 0) )
		{
			victim->damage_mods[index] -=UMIN( adjustment, paf->modifier);
			paf->modifier -= adjustment;
			paf->modifier = UMAX(0,paf->modifier);
			found = TRUE;
		}
	}
	for (paf = victim->affected2; paf; paf = paf->next)
	{
		if (paf->deleted)
			continue;
		if (found)
			break;
		/* Ok, first we find the right affect... */
		if ((paf->location == apply_loc) && paf->modifier > 0 )
		{
			victim->damage_mods[index] -= UMIN( adjustment, paf->modifier);
			paf->modifier -= adjustment;
			paf->modifier = UMAX(0, paf->modifier);
			found = TRUE;
		}
	}
	for (paf = victim->affected3; paf; paf = paf->next)
	{
		if (paf->deleted)
			continue;
		if (found)
			break;
		/* Ok, first we find the right affect... */
		if ((paf->location == apply_loc) && paf->modifier > 0 )
		{
			victim->damage_mods[index] -= UMIN( adjustment, paf->modifier);
			paf->modifier -= adjustment;
			paf->modifier = UMAX(0, paf->modifier);
			found = TRUE;
		}
	}
	for (paf = victim->affected4; paf; paf = paf->next)
	{
		if (paf->deleted)
			continue;
		if (found)
			break;
		/* Ok, first we find the right affect... */
		if ((paf->location == apply_loc) && paf->modifier > 0 )
		{
			victim->damage_mods[index] -= UMIN(adjustment, paf->modifier);
			paf->modifier -= adjustment;
			paf->modifier = UMAX(0, paf->modifier);
			found = TRUE;
		}
	}
	return;
}

int skill_axe_kick( int sn, int level, CHAR_DATA *ch, void *vo )
{
    CHAR_DATA *victim;
    char       arg [ MAX_INPUT_LENGTH ]; 
    int dam = 0;
	
    if ( !ch->fighting )
    {   
        send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch );
        return SKPELL_MISSED;
    }
        
    if ( !check_blind( ch ) )
        return SKPELL_MISSED;
 
    one_argument( target_name, arg );
    
    victim = ch->fighting;
      
    if ( arg[0] != '\0' )
        if ( !( victim = get_char_room( ch, arg ) ) )
        {
            send_to_char(C_DEFAULT, "They aren't here.\n\r", ch );
            return SKPELL_MISSED;
        }
        
    WAIT_STATE( ch, skill_table[sn].beats );
    if ( IS_NPC( ch ) || number_percent( ) < ( ch->pcdata->learned[sn] / 10 )  )
    {
        dam = number_range(ch->level * 4, ch->level * 11); //damage( ch, victim, number_range( ch->level*4, ch->level*11 ), gsn_axe_kick );
    }
    else
        dam = SKPELL_ZERO_DAMAGE; //damage( ch, victim, 0, gsn_axe_kick );
    
    return dam;
}
// AC Damage Reduction - Ahsile
int damreduce (CHAR_DATA* ch, CHAR_DATA* victim, int dam, int dt)
{
    float mod;
    //char buf [MAX_STRING_LENGTH];

    // No reduction for certain skills
    if ( dt == skill_lookup("backstab") || dt == skill_lookup("double backstab") || dt == skill_lookup("assassinate") || dt == skill_lookup("triple backstab") )
        return dam;

    // Hitroll (you got good aim!)
    mod = -(victim->armor) - (IS_NPC(ch) ? (float)(ch->hitroll/4) : (float)(ch->hitroll/2));
    
    // Max out at MAX_ARMOR
    mod = (mod > MAX_ARMOR) ? MAX_ARMOR : (mod < -MAX_ARMOR ? -MAX_ARMOR : mod);

    // Translate into a number between -0.5 to 0.5
    mod /= (MAX_ARMOR*2);

    //sprintf(buf, "Mod: %f Orig Dam: %d", mod, dam);
    //send_to_char(AT_WHITE, buf, victim);
    dam -= (int)(dam*mod);
    //sprintf(buf, " New Damage: %d\n\r", dam);
    //send_to_char(AT_WHITE, buf, victim);
    return dam;
}

/* rewrite insane wield checks - Ahsile */
bool can_use_attack( int attack_num, CHAR_DATA* ch)
{
	char buf_att[MAX_STRING_LENGTH];
	char buf_str[MAX_STRING_LENGTH];
	char buf_sht[MAX_STRING_LENGTH];

	char buf    [MAX_STRING_LENGTH];
	static char* att = "%s attack";
	static char* str = "%s strike";
	static char* sht = "%s shot";


	OBJ_DATA* wielded = get_eq_char( ch, WEAR_WIELD );
	OBJ_DATA* dualed  = get_eq_char( ch, WEAR_WIELD_2 );
	
	int value	  = flag_value( weapon_flags, "shot" );

	if ( attack_num > 2 && attack_num < 7 && IS_AFFECTED3(ch, AFF_TALE_OF_TERROR) )
		return FALSE;

	switch ( attack_num )
	{
		case 2:
			strcpy(buf, "second");
			break;
		case 3:
			strcpy(buf, "third");
			break;
		case 4:
			strcpy(buf, "fourth");
			break;
		case 5:
			strcpy(buf, "fifth");
			break;
		case 6:
			strcpy(buf, "sixth");
			break;
		case 7:
			strcpy(buf, "seventh");
			break;
		case 8:
			strcpy(buf, "eighth");
			break;
		default:
			return FALSE;
	}

	sprintf(buf_att, att, buf); /* make "second attack", etc */
	sprintf(buf_str, str, buf); /* make "second strike", etc */
	sprintf(buf_sht, sht, buf); /* make "second shot", etc   */

    if ( 
	   (
       	 	( can_use_skspell( ch, skill_lookup( buf_att ) )	) &&  
         	( wielded != NULL || dualed != NULL 			) &&
		( ( wielded ? wielded->value[3] != value : FALSE ) || ( dualed ? dualed->value[3] != value : FALSE   ) ) &&
 		( IS_NPC(ch) || ( !IS_NPC(ch) && number_percent( ) < ( ch->pcdata->learned[ skill_lookup( buf_att )] / 10 ) ) )
	   )
       ||  (
         	( can_use_skspell( ch, skill_lookup( buf_str ) ) 	) && 
		( wielded == NULL && dualed == NULL  			) &&
 		( IS_NPC(ch) || ( !IS_NPC(ch) && number_percent( ) < ( ch->pcdata->learned[ skill_lookup( buf_str )] / 10 ) ) )
	   )
       ||  (
         	( can_use_skspell( ch, skill_lookup( buf_sht ) ) 	) && 
		( wielded != NULL || dualed != NULL  			) &&
		( ( wielded ? wielded->value[3] == value : FALSE ) || ( dualed ? dualed->value[3] == value : FALSE   ) ) &&
 		( IS_NPC(ch) || ( !IS_NPC(ch) && number_percent( ) < ( ch->pcdata->learned[ skill_lookup( buf_sht )] / 10 )  ) )
	   )
       )
     {
		if (!wielded && !dualed)
			update_skpell(ch, skill_lookup( buf_str ), 0 );
		else
		{
			if (wielded && !dualed)
			{
				if (IS_SET( wielded->extra_flags2, ITEM_TWO_HANDED ) && wielded->value[3] != flag_value( weapon_flags, "shot" ) )
				{
					if ( IS_NPC(ch) || number_percent() < (ch->pcdata->learned[skill_lookup("two handed")]/10 ) )
					{
						update_skpell( ch, skill_lookup("two handed"), 0 );
					} else
					{
						return FALSE; // wielding a two handed weapon, and two handed check failed
					}

				}
			}

			if ((wielded && wielded->value[3] == value) || (dualed && dualed->value[3] == value ))
				update_skpell( ch, skill_lookup( buf_sht ), 0 );

			if ((wielded && wielded->value[3] != value) || (dualed && dualed->value[3] != value ))	
				update_skpell( ch, skill_lookup( buf_att ), 0 );
		}
		return TRUE;
     }
     
    return FALSE;
}

/* dual actually depends on your skill % now */
bool can_dual( CHAR_DATA* ch)
{

	int pct = number_percent();
	int sn  = skill_lookup("dual");

	/* no know dual? fail */
	if ( !can_use_skspell(ch, sn ) )
		return FALSE;

	/* two handed weapon? fail */
	if (get_eq_char(ch, WEAR_WIELD) != NULL && IS_SET(get_eq_char(ch, WEAR_WIELD)->extra_flags2, ITEM_TWO_HANDED))
		return FALSE;

	/* bare fisted? succeed if % check succeeds */
	if (get_eq_char(ch, WEAR_WIELD) == NULL && get_eq_char(ch,WEAR_WIELD_2) == NULL )
	{
		if (IS_NPC(ch) || pct < ( ch->pcdata->learned[sn] / 10 ) )
		{
			update_skpell( ch, sn, 0 );
			return TRUE;
		}
	} 
	/* are you actually dual wielding? if so and % check succeeds */
	else if (get_eq_char(ch, WEAR_WIELD) != NULL && get_eq_char(ch, WEAR_WIELD_2) != NULL )
	{
		if (IS_NPC(ch) || pct < ( ch->pcdata->learned[sn] / 10 ) )
		{
			update_skpell( ch, sn, 0 );
			return TRUE;
		}
	}


	/* otherwise, you failed the checks because:
		a) you failed a % check 
			or
		b) you are wielding one weapon (either hand)
	*/
	
	return FALSE;
			
}

void miss_message( CHAR_DATA* ch, CHAR_DATA* victim, bool dual )
{
    if ( IS_SET( ch->act, PLR_COMBAT ) )
    {
	if (!dual)
		act(AT_GREEN, "You attack $N, but miss.", ch, NULL, victim, TO_CHAR    );
	else
		act(AT_GREEN, "You attack $N and miss both primary and dual attacks.", ch, NULL, victim, TO_CHAR);
    }

    if ( IS_SET( victim->act, PLR_COMBAT ) )
    {
	act(AT_GREEN, "$n attacks you, but misses.",  ch, NULL, victim, TO_VICT    );
    }
}