6D/
6D/area/
6D/boards/
6D/city/
6D/color/
6D/corpses/
6D/councils/
6D/htowns/
6D/news/
6D/specials/
6D/src/specials/
6D/src/trades/
/***************************************************************************
 * - Chronicles Copyright 2001, 2002 by Brad Ensley (Orion Elder)          *
 * - SMAUG 1.4  Copyright 1994, 1995, 1996, 1998 by Derek Snider           *
 * - Merc  2.1  Copyright 1992, 1993 by Michael Chastain, Michael Quan,    *
 *   and Mitchell Tse.                                                     *
 * - DikuMud    Copyright 1990, 1991 by Sebastian Hammer, Michael Seifert, *
 *   Hans-Henrik Stærfeldt, Tom Madsen, and Katja Nyboe.                   *
 ***************************************************************************
 * - Battle and death module                                               *
 ***************************************************************************/

#include <ctype.h>  /* fixes tolower implicit declarations */
#include <string.h>
#include "h/mud.h"
#include "h/files.h"
#include "h/clans.h"
#include "h/polymorph.h"
#include "h/damage.h"
#include "h/arena.h"
#include "h/city.h"
#include "h/hometowns.h"

extern char             lastplayercmd[MIL];
extern CHAR_DATA       *gch_prev;
void                    add_pkill(CHAR_DATA *ch, CHAR_DATA *victim);
PKILLED_DATA           *has_pkilled(CHAR_DATA *ch, char *name);
void                    set_soldier(CHAR_DATA *soldier, CHAR_DATA *ch, bool archer);
bool                    IS_STEED(CHAR_DATA *ch);
void                    animal_change(CHAR_DATA *ch, bool tohuman);

#define MIN_DISTANCE 1

//Following will be declared through header once testing is finished. -Taon
extern bool             arena_underway;
extern void             find_arena_winner(CHAR_DATA *ch);

void                    lodge_projectile(CHAR_DATA *ch, CHAR_DATA *victim);

OBJ_DATA               *used_weapon;  /* Used to figure out which weapon later */

#define NEW_AUTH(ch)         (!IS_NPC(ch) && (ch)->level == 1)

bool                    countpkill(CHAR_DATA *ch, CHAR_DATA *victim);

/*
 * Local functions.
 */
void                    set_distance(CHAR_DATA *ch, int distance);
void group_gain         args((CHAR_DATA *ch, CHAR_DATA *victim));
int xp_compute          args((CHAR_DATA *gch, CHAR_DATA *victim));
int                     align_compute(CHAR_DATA *gch, CHAR_DATA *victim);
ch_ret one_hit          args((CHAR_DATA *ch, CHAR_DATA *victim, int dt));
int obj_hitroll         args((OBJ_DATA *obj));
void show_condition     args((CHAR_DATA *ch, CHAR_DATA *victim));
void make_corpse        args((CHAR_DATA *ch, CHAR_DATA *killer));
void make_blood         args((CHAR_DATA *ch));
void                    to_channel(const char *argument, const char *xchannel, int level);
void                    increase_clan_pdeaths(CLAN_DATA * clan, int level);
void                    increase_clan_pkills(CLAN_DATA * clan, int level);

/*
 * Check to see if player's attacks are (still?) suppressed
 * #ifdef TRI
 */
bool is_attack_supressed(CHAR_DATA *ch)
{
  TIMER                  *timer;

  if(IS_NPC(ch))
    return FALSE;

  timer = get_timerptr(ch, TIMER_ASUPRESSED);

  if(!timer)
    return FALSE;

  /*
   * perma-supression -- bard? (can be reset at end of fight, or spell, etc) 
   */
  if(timer->value == -1)
    return TRUE;

  /*
   * this is for timed supressions 
   */
  if(timer->count >= 1)
    return TRUE;

  return FALSE;
}

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

  if(!used_weapon)
    return FALSE;

  if((obj = get_eq_char(ch, WEAR_WIELD)) != NULL && used_weapon == obj && IS_OBJ_STAT(obj, ITEM_POISONED))
    return TRUE;
  if((obj = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL && used_weapon == obj && IS_OBJ_STAT(obj, ITEM_POISONED))
    return TRUE;

  return FALSE;
}

/*
 * hunting, hating and fearing code     -Thoric
 */
bool is_hunting(CHAR_DATA *ch, CHAR_DATA *victim)
{
  if(!ch->hunting || ch->hunting->who != victim)
    return FALSE;

  return TRUE;

}

bool is_hating(CHAR_DATA *ch, CHAR_DATA *victim)
{
  if(!ch->hating || ch->hating->who != victim)
    return FALSE;

  return TRUE;
}

bool is_fearing(CHAR_DATA *ch, CHAR_DATA *victim)
{
  if(!ch->fearing || ch->fearing->who != victim)
    return FALSE;

  return TRUE;
}

void stop_hunting(CHAR_DATA *ch)
{
  if(ch->hunting)
  {
    STRFREE(ch->hunting->name);
    DISPOSE(ch->hunting);
    ch->hunting = NULL;
  }
  return;
}

void stop_hating(CHAR_DATA *ch)
{
  if(ch->hating)
  {
    STRFREE(ch->hating->name);
    DISPOSE(ch->hating);
    ch->hating = NULL;
  }
  return;
}

void stop_fearing(CHAR_DATA *ch)
{
  if(ch->fearing)
  {
    STRFREE(ch->fearing->name);
    DISPOSE(ch->fearing);
    ch->fearing = NULL;
  }
  return;
}

void stop_summoning(CHAR_DATA *ch)
{
  CHAR_DATA              *vch, *vch_next;

  if(!ch || !ch->in_room)
    return;
  for(vch = ch->in_room->first_person; vch; vch = vch_next)
  {
    vch_next = vch->next_in_room;

    if(vch->hunting && vch->hunting->who == ch)
      stop_hunting(vch);
    if(vch->hating && vch->hating->who == ch)
      stop_hating(vch);
  }
}

void start_hunting(CHAR_DATA *ch, CHAR_DATA *victim)
{
  if(ch->hunting)
    stop_hunting(ch);

  CREATE(ch->hunting, HHF_DATA, 1);
  ch->hunting->name = QUICKLINK(victim->name);
  ch->hunting->who = victim;
  return;
}

void start_hating(CHAR_DATA *ch, CHAR_DATA *victim)
{
  if(ch->hating)
    stop_hating(ch);

  CREATE(ch->hating, HHF_DATA, 1);
  ch->hating->name = QUICKLINK(victim->name);
  ch->hating->who = victim;
  return;
}

void start_fearing(CHAR_DATA *ch, CHAR_DATA *victim)
{
  if(ch->fearing)
    stop_fearing(ch);

  CREATE(ch->fearing, HHF_DATA, 1);
  ch->fearing->name = QUICKLINK(victim->name);
  ch->fearing->who = victim;
  return;
}

short DRAGON_AC(CHAR_DATA *ch)
{
  short                   hide;

  if(ch->race == RACE_DRAGON)
  {
    hide = (short)(ch->armor + ((ch->level + 20) * -2.0));
    return hide;
  }
  else
    return 0;
}

/*
 * Get the current armor class for a vampire based on time of day
 * Though wasnt my Idea, I found it left undone and coded it. -Taon
 */
short VAMP_AC(CHAR_DATA *ch)
{
  short                   armor_value = 0;

  if(IS_OUTSIDE(ch) && (ch->Class == CLASS_VAMPIRE))
  {
    switch (time_info.sunlight)
    {
      case SUN_LIGHT:
        armor_value = 50;
        break;
      case SUN_RISE:
      case SUN_SET:
        armor_value = 25;
        break;
    }
  }

  if(armor_value == 0)  // Must be dark or inside, small
    // bonus!
    armor_value = -get_curr_dex(ch) - 10;

  return armor_value;
}

//Currently in use. -Taon

short MONK_AC(CHAR_DATA *ch)
{
  short                   flesh_armor;

  if(ch->Class == CLASS_MONK)
    flesh_armor = -get_curr_dex(ch);
  else
    flesh_armor = 0;

  return flesh_armor;
}

int max_fight(CHAR_DATA *ch)
{
  return 8;
}

/*
 * Control the fights going on.
 * Called periodically by update_handler.
 * Many hours spent fixing bugs in here by Thoric, as noted by residual
 * debugging checks.  If you never get any of these error messages again
 * in your logs... then you can comment out some of the checks without
 * worry.
 *
 * Note:  This function also handles some non-violence updates.
 */
void violence_update(void)
{
  CHAR_DATA              *ch;
  CHAR_DATA              *lst_ch;
  CHAR_DATA              *victim;
  CHAR_DATA              *rch, *rch_next;
  AFFECT_DATA            *paf, *paf_next;
  TIMER                  *timer, *timer_next;
  ch_ret                  retcode;
  int                     attacktype, cnt;
  SKILLTYPE              *skill;
  static int              pulse = 0;

  lst_ch = NULL;
  pulse = (pulse + 1) % 100;

  for(ch = last_char; ch; lst_ch = ch, ch = gch_prev)
  {
    set_cur_char(ch);

    if(ch == first_char && ch->prev)
    {
      bug("%s", "ERROR: first_char->prev != NULL, fixing...");
      ch->prev = NULL;
    }

    gch_prev = ch->prev;

    if(gch_prev && gch_prev->next != ch)
    {
      bug("FATAL: %s: %s->prev->next doesn't point to ch. Short-cutting here", __FUNCTION__, ch->name);
      ch->prev = NULL;
      gch_prev = NULL;
    }

    /*
     * See if we got a pointer to someone who recently died...
     * if so, either the pointer is bad... or it's a player who
     * "died", and is back at the healer...
     * Since he/she's in the char_list, it's likely to be the later...
     * and should not already be in another fight already
     */
    if(char_died(ch))
      continue;

    /*
     * See if we got a pointer to some bad looking data...
     */
    if(!ch->in_room || !ch->name)
    {
      log_string("violence_update: bad ch record!  (Shortcutting.)");
      log_printf("ch: %ld  ch->in_room: %ld  ch->prev: %ld  ch->next: %ld", (long)ch, (long)ch->in_room, (long)ch->prev, (long)ch->next);
      log_string(lastplayercmd);
      if(lst_ch)
        log_printf("lst_ch: %ld  lst_ch->prev: %ld  lst_ch->next: %ld", (long)lst_ch, (long)lst_ch->prev, (long)lst_ch->next);
      else
        log_string("lst_ch: NULL");
      gch_prev = NULL;
      continue;
    }

    /*
     * Experience gained during battle deceases as battle drags on
     */
    if(ch->fighting)
      if((++ch->fighting->duration % 24) == 0)
        ch->fighting->xp = ((ch->fighting->xp * 10) / 6);

    if(IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM) && who_fighting(ch->master) != NULL && !xIS_SET(ch->act, ACT_MOUNTABLE))
    {
      if(!ch->fighting)
      {
        victim = who_fighting(ch->master);
        if(victim != NULL)
        {
          set_fighting(ch, victim);
        }
      }
    }

    for(timer = ch->first_timer; timer; timer = timer_next)
    {
      timer_next = timer->next;
      if(--timer->count <= 0)
      {
        if(timer->type == TIMER_ASUPRESSED)
        {
          if(timer->value == -1)
          {
            timer->count = 1000;
            continue;
          }
        }
        if(timer->type == TIMER_NUISANCE)
        {
          DISPOSE(ch->pcdata->nuisance);
        }

        if(timer->type == TIMER_DO_FUN)
        {
          int                     tempsub;

          tempsub = ch->substate;
          ch->substate = timer->value;
          (timer->do_fun) (ch, (char *)"");
          if(char_died(ch))
            break;
          ch->substate = tempsub;
        }
        extract_timer(ch, timer);
      }
    }

    if(char_died(ch))
      continue;

    /*
     * We need spells that have shorter durations than an hour.
     * So a melee round sounds good to me... -Thoric
     */
    for(paf = ch->first_affect; paf; paf = paf_next)
    {
      paf_next = paf->next;
      if(paf->duration > 0)
        paf->duration--;
      else if(paf->duration < 0);
      else
      {
        if(!paf_next || paf_next->type != paf->type || paf_next->duration > 0)
        {
          skill = get_skilltype(paf->type);
          if(paf->type > 0 && skill && skill->msg_off)
          {
            set_char_color(AT_GREY, ch);
            send_to_char(skill->msg_off, ch);
            send_to_char("\r\n", ch);
          }
        }
        if(paf->type == gsn_possess)
        {
          ch->desc->character = ch->desc->original;
          ch->desc->original = NULL;
          ch->desc->character->desc = ch->desc;
          ch->desc->character->switched = NULL;
          ch->desc = NULL;
        }

        if(paf->type == gsn_taunt && !ch->fighting)
        {
          xREMOVE_BIT(ch->affected_by, AFF_HATE);
          ch->hate_level = 0;
        }

        if(IS_AFFECTED(ch, AFF_SILENCE) && xIS_SET(ch->act, PLR_SILENCE))
        {
          xREMOVE_BIT(ch->act, PLR_SILENCE);
        }

        if(IS_AFFECTED(ch, AFF_IMPRISONED))
        {
          ROOM_INDEX_DATA        *pRoomIndex;

          char_from_room(ch);
          pRoomIndex = get_room_index(ch->regoto);
          char_to_room(ch, pRoomIndex);
          do_look(ch, (char *)"auto");

          OBJ_DATA               *obj;

          for(obj = first_object; obj; obj = obj->next)
          {
            if(obj->pIndexData->vnum == 41032 && obj->in_room != NULL)
              break;
          }
          if(obj)
            make_scraps(obj);
        }

        if(paf->type == gsn_enrage && !ch->fighting)
        {
          xREMOVE_BIT(ch->affected_by, AFF_HATE);
          ch->hate_level = 0;
        }

        if(paf->type == gsn_human_form)
        {
          humanform_change(ch, FALSE);
        }

        affect_remove(ch, paf);

      }
    }

    if(char_died(ch))
      continue;

    /*
     * check for exits moving players around 
     */
    if((retcode = pullcheck(ch, pulse)) == rCHAR_DIED || char_died(ch))
      continue;

    /*
     * Let the battle begin! 
     */
    if((victim = who_fighting(ch)) == NULL || IS_AFFECTED(ch, AFF_PARALYSIS))
      continue;

    retcode = rNONE;

    if(IS_SET(ch->in_room->room_flags, ROOM_SAFE))
    {
      log_printf("violence_update: %s is attempting to fight %s in a SAFE room.", ch->name, victim->name);
      stop_fighting(ch, TRUE);
    }
    else if(IS_AWAKE(ch) && ch->in_room == victim->in_room)
    {
      retcode = multi_hit(ch, victim, TYPE_UNDEFINED);
      if(!IS_NPC(ch) && xIS_SET(ch->act, PLR_AUTOGLANCE) && ch != NULL && victim != NULL && who_fighting(ch) == victim && !char_died(victim) && !char_died(ch))
      {
        show_condition(ch, victim);
      }
    }
    else
      stop_fighting(ch, FALSE);

    if(char_died(ch))
      continue;

    if(retcode == rCHAR_DIED || (victim = who_fighting(ch)) == NULL)
      continue;

    /*
     *  Mob triggers
     *  -- Added some victim death checks, because it IS possible.. -- Alty
     */
    rprog_rfight_trigger(ch);
    if(char_died(ch) || char_died(victim))
      continue;
    mprog_hitprcnt_trigger(ch, victim);
    if(char_died(ch) || char_died(victim))
      continue;
    mprog_fight_trigger(ch, victim);
    if(char_died(ch) || char_died(victim))
      continue;

    if(get_eq_char(ch, WEAR_WIELD))
    {
      oprog_fight_trigger(ch, get_eq_char(ch, WEAR_WIELD), victim);
      if(char_died(ch))
        continue;
    }
    if(get_eq_char(ch, WEAR_DUAL_WIELD))
    {
      oprog_fight_trigger(ch, get_eq_char(ch, WEAR_DUAL_WIELD), victim);
      if(char_died(ch))
        continue;
    }

    /*
     * NPC special attack flags     -Thoric
     */
    if(IS_NPC(ch))
    {
      if(!xIS_EMPTY(ch->attacks))
      {
        attacktype = -1;
        if(30 + (ch->level / 4) >= number_percent())
        {
          cnt = 0;
          for(;;)
          {
            if(cnt++ > 10)
            {
              attacktype = -1;
              break;
            }
            attacktype = number_range(7, MAX_ATTACK_TYPE - 1);
            if(xIS_SET(ch->attacks, attacktype))
              break;
          }
          switch (attacktype)
          {
            case ATCK_LOWBLOW:
              do_low_blow(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_STUN:
              do_stun(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_EBOLT:
              do_eldritch_bolt(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_GOUGE:
              do_gouge(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_FEED:
              do_feed(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_DRAIN:
              act(AT_MAGIC, "$n utters a few incantations.", ch, NULL, NULL, TO_ROOM);
              retcode = spell_energy_drain(skill_lookup("energy drain"), ch->level, ch, victim);
              break;
            case ATCK_MENTALASSAULT:
              do_mental_assault(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_GSMITE:
              retcode = spell_greater_smite(skill_lookup("greater smite"), ch->level, ch, victim);
              break;
            case ATCK_BREATHE:
              do_breathe(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_GUT:
              do_gut(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_BLIGHTNING:
              retcode = spell_black_lightning(skill_lookup("black lightning"), ch->level, ch, victim);
              break;
            case ATCK_LTOUCH:
              retcode = spell_smaug(skill_lookup("lich touch"), ch->level, ch, victim);
              break;
            case ATCK_INFERNO:
              act(AT_MAGIC, "$n utters a few incantations.", ch, NULL, NULL, TO_ROOM);
              do_inferno(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_BRAINBOIL:
              do_brain_boil(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_BLIZZARD:
              act(AT_MAGIC, "$n utters a few incantations.", ch, NULL, NULL, TO_ROOM);
              do_blizzard(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_IMPALE:
              do_impale(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_FROST:
              do_frost(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_POISON:
              act(AT_MAGIC, "$n utters a few incantations.", ch, NULL, NULL, TO_ROOM);
              retcode = spell_poison(gsn_poison, ch->level, ch, victim);
              break;
            case ATCK_SLOW:
              retcode = spell_slow(skill_lookup("slow"), ch->level, ch, victim);
              break;
            case ATCK_THROATPUNCH:
              do_throat_punch(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_RAKE:
              do_rake(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_THAITIN:
              do_thaitin(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_JUDOCHOP:
              do_judo(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_SHRIEKINGNOTE:
              do_shrieking_note(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_MURAZORWHIP:
              do_whip_of_murazor(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_BUTTERFLYKICK:
              do_butterfly_kick(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_SNATCH:
              do_snatch(ch, (char *)"");
              retcode = global_retcode;
              break;
            case ATCK_FIREBALL:
              act(AT_MAGIC, "$n utters a few incantations.", ch, NULL, NULL, TO_ROOM);
              retcode = spell_fireball(skill_lookup("fireball"), ch->level, ch, victim);
              break;
            case ATCK_LIGHTNING:
              retcode = spell_lightning(skill_lookup("lightning"), ch->level, ch, victim);
              break;
            case ATCK_WEAKEN:
              act(AT_MAGIC, "$n utters a few incantations.", ch, NULL, NULL, TO_ROOM);
              retcode = spell_weaken(skill_lookup("weaken"), ch->level, ch, victim);
              break;

          }
          if(attacktype != -1 && (retcode == rCHAR_DIED || char_died(ch)))
            continue;
        }
      }
      /*
       * NPC special defense flags     -Thoric
       */
      if(!xIS_EMPTY(ch->defenses))
      {
        attacktype = -1;
        if(50 + (ch->level / 4) > number_percent())
        {
          cnt = 0;
          for(;;)
          {
            if(cnt++ > 10)
            {
              attacktype = -1;
              break;
            }
            attacktype = number_range(2, (MAX_DEFENSE_TYPE - 1));
            if(xIS_SET(ch->defenses, attacktype))
              break;
          }

          switch (attacktype)
          {

            case DFND_NETTLESKIN:
              act(AT_MAGIC, "$n mutters a few incantations...and looks a little better.", ch, NULL, NULL, TO_ROOM);
              retcode = spell_nettle_skin(skill_lookup("nettle skin"), ch->level, ch, ch);
              break;

            case DFND_SPECTRALWARD:
              do_spectral_ward(ch, (char *)"");
              break;

            case DFND_MINORRESTORE:
              if(ch->hit < ch->max_hit)
              {
                do_minor_restore(ch, (char *)"self");
              }
              break;

            case DFND_TORPOR:
              act(AT_MAGIC, "$n mutters a few incantations...and looks a little better.", ch, NULL, NULL, TO_ROOM);
              retcode = spell_torpor(skill_lookup("torpor"), ch->level, ch, ch);

              break;

            case DFND_KINETICBARRIER:
              do_kinetic_barrier(ch, (char *)"");
              break;

            case DFND_HAWKSPIRIT:
              do_hawk_spirit(ch, (char *)"");
              break;

            case DFND_LICK:
              do_lick(ch, ch->name);
              break;

            case DFND_COMBATHEAL:
              do_combat_heal(ch, ch->name);
              break;

            case DFND_WILLOWSKIN:
              do_willow_skin(ch, ch->name);
              break;
            case DFND_GRENDALSTANCE:
              if(ch->hit < ch->max_hit)
              {
                do_grendals_stance(ch, (char *)"");
              }
              break;
            case DFND_DISPELMAGIC:
              if(victim->first_affect)
              {
                act(AT_MAGIC, "$n utters an incantation...", ch, NULL, NULL, TO_ROOM);
                retcode = spell_dispel_magic(skill_lookup("dispel magic"), ch->level, ch, victim);
              }
              break;
            case DFND_WOLFSPIRIT:
              act(AT_MAGIC, "$n utters an incantation...", ch, NULL, NULL, TO_ROOM);
              retcode = spell_wolf_spirit(skill_lookup("wolf spirit"), ch->level, ch, victim);
              break;
            case DFND_REGENERATE:
              break;
            case DFND_BIOFEEDBACK:
              break;

            case DFND_MAINTAINPOSITION:
              do_maintain_position(ch, (char *)"");
              break;

            case DFND_HUNKERDOWN:
              do_hunker_down(ch, (char *)"");
              break;

            case DFND_ACIDMIST:
              if(!IS_AFFECTED(ch, AFF_ACIDMIST))
              {
                act(AT_MAGIC, "$n utters a few incantations ...", ch, NULL, NULL, TO_ROOM);
                retcode = spell_smaug(skill_lookup("acidmist"), ch->level, ch, ch);
              }
              else
                retcode = rNONE;
              break;
            case DFND_FINDWEAKNESS:
              break;

            case DFND_BEARSPIRIT:
              do_bear_spirit(ch, (char *)"");
              break;

            case DFND_SHIELD:
              if(!IS_AFFECTED(ch, AFF_SHIELD))
              {
                act(AT_MAGIC, "$n utters a few incantations...", ch, NULL, NULL, TO_ROOM);
                do_shield(ch, (char *)"");
              }
              else
                retcode = rNONE;
              break;

            case DFND_SANCTUARY:
              if(!IS_AFFECTED(ch, AFF_SANCTUARY))
              {
                act(AT_MAGIC, "$n utters a few incantations...", ch, NULL, NULL, TO_ROOM);
                retcode = spell_smaug(skill_lookup("sanctuary"), ch->level, ch, ch);
              }
              else
                retcode = rNONE;
              break;
          }
          if(attacktype != -1 && (retcode == rCHAR_DIED || char_died(ch)))
            continue;
        }
      }
    }

    /*
     * Fun for the whole family!
     */
    for(rch = ch->in_room->first_person; rch; rch = rch_next)
    {
      rch_next = rch->next_in_room;

      /*
       *   Group Fighting Styles Support:
       *   If ch is tanking
       *   If rch is using a more aggressive style than ch
       *   Then rch is the new tank   -h
       */
      /*
       * &&(is_same_group(ch, rch)) 
       */

      if((!IS_NPC(ch) && !IS_NPC(rch)) && (rch != ch) && (rch->fighting) && (who_fighting(rch->fighting->who) == ch) && (!xIS_SET(rch->fighting->who->act, ACT_AUTONOMOUS)) && (rch->style < ch->style))
      {
        rch->fighting->who->fighting->who = rch;

      }

      if(IS_AWAKE(rch) && !rch->fighting)
      {
        /*
         * PC's auto-assist others in their group.
         */
        if(!IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM))
        {
          if(((!IS_NPC(rch) && rch->desc) || IS_AFFECTED(rch, AFF_CHARM)) && is_same_group(ch, rch) && !is_safe(rch, victim, TRUE))
            multi_hit(rch, victim, TYPE_UNDEFINED);
          continue;
        }

        /*
         * NPC's assist NPC's of same type or 12.5% chance regardless.
         * Volk changed this to only assisting same type.
         */
        if(IS_NPC(rch) && !IS_AFFECTED(rch, AFF_CHARM) && !xIS_SET(rch->act, ACT_NOASSIST))
        {
          if(char_died(ch))
            break;
          if(rch->pIndexData == ch->pIndexData)
          {
            CHAR_DATA              *vch;
            CHAR_DATA              *target;
            int                     number;

            target = NULL;
            number = 0;
            for(vch = ch->in_room->first_person; vch; vch = vch->next_in_room)
            {
              if(can_see(rch, vch) && is_same_group(vch, victim) && number_range(0, number) == 0)
              {
                if(vch->mount && vch->mount == rch)
                  target = NULL;
                else
                {
                  target = vch;
                  number++;
                }
              }
            }

            if(target)
              multi_hit(rch, target, TYPE_UNDEFINED);
          }
        }
      }
    }
  }
}

/*
 * Do one group of attacks.
 */
ch_ret multi_hit(CHAR_DATA *ch, CHAR_DATA *victim, int dt)
{
  int                     chance;
  int                     dual_bonus;
  ch_ret                  retcode;

  /*
   * add timer to pkillers
   * Volk: And support for arena! 
   */
  if(!IS_NPC(ch) && !IS_NPC(victim) && !in_arena(ch) && !in_arena(victim))
  {
    add_timer(ch, TIMER_RECENTFIGHT, 11, NULL, 0);
    add_timer(victim, TIMER_RECENTFIGHT, 11, NULL, 0);
  }

  ch->success_attack = 1;

  if(is_attack_supressed(ch))
    return rNONE;

  if(IS_NPC(ch) && xIS_SET(ch->act, ACT_NOATTACK))
    return rNONE;
  /*
   * -- Altrag 
   */
  chance = IS_NPC(ch) ? 100 : (LEARNED(ch, gsn_berserk) * 5 / 2);
  if(IS_AFFECTED(ch, AFF_BERSERK) && number_percent() < chance)
  {
    ch->success_attack = number_range(1, 2);
    retcode = one_hit(ch, victim, dt);

    if(retcode != rNONE || who_fighting(ch) != victim)
      return retcode;
  }

  if(get_eq_char(ch, WEAR_DUAL_WIELD))
  {
    if(IS_NPC(ch))
    {
      chance = number_range(65, 100);
    }
    else
    {
      chance = number_range(1, 100);
    }
    if(get_curr_dex(ch) > 15)
    {
      chance += 20;
    }
    else if(get_curr_dex(ch) > 17)
    {
      chance += 35;
    }
    else if(get_curr_dex(ch) > 19)
    {
      chance += 55;
    }

    learn_from_success(ch, gsn_dual_wield);
    ch->success_attack += 1;
    if(!IS_NPC(ch))
    {
      if(ch->pcdata->learned[gsn_second_attack] > 0 && chance > 15)
      {
        ch->success_attack = 2;
      }
      if(ch->pcdata->learned[gsn_third_attack] > 0 && chance > 25)
      {
        ch->success_attack = 3;
      }
      if(ch->pcdata->learned[gsn_fourth_attack] > 0 && chance > 25)
      {
        ch->success_attack = 4;
      }
      if(ch->pcdata->learned[gsn_fifth_attack] > 0 && chance > 25)
      {
        ch->success_attack = 5;
      }
      if(ch->pcdata->learned[gsn_sixth_attack] > 0 && chance > 35)
      {
        ch->success_attack = 6;
      }
      if(ch->pcdata->learned[gsn_seventh_attack] > 0 && chance > 35)
      {
        ch->success_attack = 7;
      }
      if(ch->pcdata->learned[gsn_eighth_attack] > 0 && chance > 45)
      {
        ch->success_attack = 8;
      }
    }

    if(IS_AFFECTED(ch, AFF_SLOW))
    {
      if(ch->success_attack > 2)
      {
        ch->success_attack = ch->success_attack - number_range(1, 2);
      }
    }

    if(IS_NPC(ch))
    {
      ch->success_attack = ch->numattacks;
      if(IS_AFFECTED(ch, AFF_SLOW))
      {
        if(ch->success_attack > 2)
        {
          ch->success_attack = ch->success_attack - number_range(1, 3);
        }
      }

    }
    if(ch->success_attack < 2)
    {
      ch->success_attack = 2;
    }
    ch->success_attack = (ch->success_attack / 2);
    retcode = one_hit(ch, victim, dt);

    if(retcode != rNONE || who_fighting(ch) != victim)
      return retcode;
  }
  else
    learn_from_failure(ch, gsn_dual_wield);

/* Start of compressed attacks */

  /*
   * NPC predetermined number of attacks -Thoric 
   */
  if(IS_NPC(ch) && ch->numattacks > 0)
  {
    for(chance = 0; chance < ch->numattacks; chance++)
    {
      ch->success_attack += 1;
    }
    short                   bslow;

    bslow = number_range(1, 4);
    if(IS_AFFECTED(ch, AFF_SLOW))
    {
      if(ch->success_attack > 2 && bslow < 3)
      {
        ch->success_attack = ch->success_attack / 2;
      }
      else if(ch->success_attack > 2 && bslow > 2)
      {
        ch->success_attack = ch->success_attack - number_range(1, 2);
      }
    }

    retcode = one_hit(ch, victim, dt);
    return retcode;
  }
  if(IS_AFFECTED(ch, AFF_SURREAL_SPEED) || IS_AFFECTED(ch, AFF_FURY))
    chance += 10;
  if((IS_AFFECTED(ch, AFF_BLINDNESS) && !IS_AFFECTED(ch, AFF_NOSIGHT)) || IS_AFFECTED(ch, AFF_SLOW))
    chance -= 10;
  if(IS_AFFECTED(ch, AFF_SURREAL_SPEED) || IS_AFFECTED(ch, AFF_FURY))
    chance += 10;
  if((IS_AFFECTED(ch, AFF_BLINDNESS) && !IS_AFFECTED(ch, AFF_NOSIGHT)) || IS_AFFECTED(ch, AFF_SLOW))
    chance -= 10;

  /*
   * Volk added 'autofeed' for vampires 
   */
  if(!IS_NPC(ch) && IS_VAMPIRE(ch) && number_percent() > 80)
  {

    chance = IS_NPC(ch) ? ch->level : LEARNED(ch, gsn_bite);
    if(number_percent() < chance)
    {
      if(number_percent() > 80 && LEARNED(ch, gsn_feed) > 0)
        do_feed(ch, (char *)"");
      else
        do_bite(ch, (char *)"");
    }
  }

  if(!IS_NPC(ch) && IS_DRAGON(ch) && number_percent() >= 95)
  {
    if(number_range(1, 10) > 4)
    {
      if(LEARNED(ch, gsn_bite) > 0)
        do_bite(ch, (char *)"");
    }
    else
    {
      if(LEARNED(ch, gsn_claw) > 0)
        do_claw(ch, (char *)"");

    }
  }

  /*
   * If fighting blind, should up blindsight gsn - Volk 
   */
  if(!IS_NPC(ch) && IS_AFFECTED(ch, AFF_NOSIGHT) && IS_AFFECTED(ch, AFF_BLINDNESS))
    learn_from_success(ch, gsn_nosight);

  /*
   * Check for berserk attack 
   */
  chance = IS_NPC(ch) ? 100 : (LEARNED(ch, gsn_berserk) * 5 / 2);
  if(IS_AFFECTED(ch, AFF_BERSERK) && number_percent() < chance)
  {
    ch->success_attack += 1;
  }

  /*
   * Roll for first attack 
   */
  chance = number_range(1, 20);
  chance += get_curr_str(ch) / 5;
  chance += get_curr_dex(ch) / 5;
  if(chance < 1)
  {
    chance = 1;
  }
  if(chance > 15)
    ch->success_attack = 1;

  /*
   * Roll for second attack 
   */
  chance = IS_NPC(ch) ? ch->level : (int)(LEARNED(ch, gsn_second_attack));

  if(get_eq_char(ch, WEAR_DUAL_WIELD) && !IS_NPC(ch))
  {
    if(get_curr_dex(ch) > 15)
    {
      chance += 20;
    }
    else if(get_curr_dex(ch) > 17)
    {
      chance += 35;
    }
    else if(get_curr_dex(ch) > 19)
    {
      chance += 55;
    }
  }

  if(number_percent() < chance)
  {
    learn_from_success(ch, gsn_second_attack);
    ch->success_attack += 1;
  }
  else
    learn_from_failure(ch, gsn_second_attack);

  /*
   * Roll for third attack 
   */
  chance = IS_NPC(ch) ? ch->level : (int)(LEARNED(ch, gsn_third_attack));

  if(number_percent() < chance)
  {
    learn_from_success(ch, gsn_third_attack);
    ch->success_attack += 1;
  }
  else
    learn_from_failure(ch, gsn_third_attack);

  /*
   * Roll for forth attack 
   */
  chance = IS_NPC(ch) ? ch->level : (int)(LEARNED(ch, gsn_fourth_attack));

  if(number_percent() < chance)
  {
    learn_from_success(ch, gsn_fourth_attack);
    ch->success_attack += 1;
  }
  else
    learn_from_failure(ch, gsn_fourth_attack);

  /*
   * Roll for fifth attack 
   */
  chance = IS_NPC(ch) ? ch->level : (int)(LEARNED(ch, gsn_fifth_attack));

  if(number_percent() < chance)
  {
    learn_from_success(ch, gsn_fifth_attack);
    ch->success_attack += 1;
  }
  else
    learn_from_failure(ch, gsn_fifth_attack);

  /*
   * Roll for sixth attack 
   */
  chance = IS_NPC(ch) ? ch->level : (int)(LEARNED(ch, gsn_sixth_attack) + (get_curr_dex(ch) * 2));

  if(number_percent() < chance)
  {
    learn_from_success(ch, gsn_sixth_attack);
    ch->success_attack += 1;
  }
  else
    learn_from_failure(ch, gsn_sixth_attack);

  /*
   * Roll for seventh attack 
   */
  chance = IS_NPC(ch) ? ch->level : (int)(LEARNED(ch, gsn_seventh_attack) + (get_curr_dex(ch) * 2));

  if(number_percent() < chance)
  {
    learn_from_success(ch, gsn_seventh_attack);
    ch->success_attack += 1;
  }
  else
    learn_from_failure(ch, gsn_seventh_attack);

  /*
   * Roll for eighth attack 
   */
  chance = IS_NPC(ch) ? ch->level : (int)(LEARNED(ch, gsn_eighth_attack) + (get_curr_dex(ch) * 2));

  if(number_percent() < chance)
  {
    learn_from_success(ch, gsn_eighth_attack);
    ch->success_attack += 1;
  }
  else
    learn_from_failure(ch, gsn_eighth_attack);

  if(get_eq_char(ch, WEAR_DUAL_WIELD))
  {
    if(ch->success_attack < 2)
    {
      ch->success_attack = 2;
    }
    ch->success_attack = (ch->success_attack / 2);
  }

  if(IS_AFFECTED(ch, AFF_SLOW))
  {
    if(ch->success_attack > 2)
    {
      ch->success_attack = ch->success_attack - number_range(1, 2);
    }
  }

  // speed assault
  if((IS_AFFECTED(ch, AFF_BLINDING_SPEED) && ch->race == RACE_VAMPIRE) || IS_AFFECTED(ch, AFF_QUICK_BLADE))
    ch->success_attack *= 2;

  if(IS_AFFECTED(ch, AFF_HUNKER_DOWN))
    ch->success_attack /= 2;

  // two-handers
  OBJ_DATA               *obj;

  if((obj = get_eq_char(ch, WEAR_WIELD)) != NULL)
  {
    if(obj->value[4] == WEP_2H_LONG_BLADE || obj->value[4] == WEP_2H_AXE || obj->value[4] == WEP_2H_BLUDGEON)
    {
      ch->success_attack /= 2;
      if(ch->success_attack < 2)
      {
        ch->success_attack = 1;
      }
    }
  }

/* End of compressed attacks */

  if(IS_AFFECTED(ch, AFF_WOLF_SPIRIT) && ch->success_attack > 0)
  {
    short                   wolf = number_range(1, 10);

    if(wolf > 8)
    {
      short                   attacks = get_curr_dex(ch) / 5 - 2;

      if(attacks < 1)
        attacks = 1;
      ch_printf(ch, "&cThe spirit of the wolf speeds up your attacks by %d\r\n", attacks);
      ch->success_attack += attacks;
    }
  }

  if((retcode = one_hit(ch, victim, dt)) != rNONE)
    return retcode;

  retcode = rNONE;

  if(retcode == rNONE)
  {
    int                     move = 0;

    if(!IS_AFFECTED(ch, AFF_FLYING) && !IS_AFFECTED(ch, AFF_FLOATING))
      if(ch->in_room && ch->in_room->sector_type)
        move = encumbrance(ch, movement_loss[URANGE(0, ch->in_room->sector_type, SECT_MAX - 1)]);
      else
        move = encumbrance(ch, 1);
    if(ch->move)
      ch->move = UMAX(0, ch->move - move);
  }
  return retcode;

}

/*
 * Weapon types, haus
 */

int weapon_prof_bonus_check(CHAR_DATA *ch, OBJ_DATA *wield, int *gsn_ptr)
{
  int                     bonus = 0;

  *gsn_ptr = gsn_pugilism;  /* Change back to -1 if this fails horribly */

  if(!IS_NPC(ch) && wield)
  {
    switch (wield->value[4])
    {
        /*
         * Restructured weapon system - Samson 11-20-99 
         */
      default:
        *gsn_ptr = -1;
        break;
      case WEP_2H_LONG_BLADE:
        *gsn_ptr = gsn_2h_long_blades;
        break;
      case WEP_1H_LONG_BLADE:
        *gsn_ptr = gsn_1h_long_blades;
        break;
      case WEP_1H_SHORT_BLADE:
        *gsn_ptr = gsn_1h_short_blades;
        break;
      case WEP_WHIP:
        *gsn_ptr = gsn_whips;
        break;
      case WEP_2H_BLUDGEON:
        *gsn_ptr = gsn_2h_bludgeons;
        break;
      case WEP_LANCE:
        *gsn_ptr = gsn_lances;
        break;
      case WEP_FLAIL:
        *gsn_ptr = gsn_flails;
        break;
      case WEP_TALON:
        *gsn_ptr = gsn_talons;
        break;
      case WEP_1H_BLUDGEON:
        *gsn_ptr = gsn_1h_bludgeons;
        break;
      case WEP_ARCHERY:
        *gsn_ptr = gsn_archery;
        break;
      case WEP_BLOWGUN:
        *gsn_ptr = gsn_blowguns;
        break;
      case WEP_2H_AXE:
        *gsn_ptr = gsn_2h_axes;
        break;
      case WEP_1H_AXE:
        *gsn_ptr = gsn_1h_axes;
        break;
      case WEP_SPEAR:
        *gsn_ptr = gsn_spears;
        break;
      case WEP_STAFF:
        *gsn_ptr = gsn_staves;
        break;
      case WEP_POLEARM:
        *gsn_ptr = gsn_polearms;
        break;
    }
    if(*gsn_ptr != -1)
      bonus = (int)((LEARNED(ch, *gsn_ptr) - 50) / 10);
  }

  return bonus;
}

/*
 * Calculate the tohit bonus on the object and return RIS values.
 * -- Altrag
 */
int obj_hitroll(OBJ_DATA *obj)
{
  int                     tohit = 0;
  AFFECT_DATA            *paf;

  for(paf = obj->pIndexData->first_affect; paf; paf = paf->next)
    if(paf->location == APPLY_HITROLL)
      tohit += paf->modifier;
  for(paf = obj->first_affect; paf; paf = paf->next)
    if(paf->location == APPLY_HITROLL)
      tohit += paf->modifier;
  return tohit;
}

/*
 * Offensive shield level modifier
 */
short off_shld_lvl(CHAR_DATA *ch, CHAR_DATA *victim)
{
  short                   lvl;

  lvl = ch->level / 2;
  if(number_percent() + (victim->level - lvl) <= 100)
    return lvl;
  else
    return 0;
}

/*
 * Hit one guy once.
 */
ch_ret one_hit(CHAR_DATA *ch, CHAR_DATA *victim, int dt)
{
  OBJ_DATA               *wield;
  int                     victim_ac;
  int                     thac0, thac0_00, thac0_32;
  int                     plusris;
  int                     dam;
  int                     diceroll;
  int                     attacktype, cnt;
  int                     prof_bonus;
  int                     prof_gsn = -1;
  ch_ret                  retcode = rNONE;
  static bool             dual_flip = FALSE;
  int                     bonus;
  int                     feet;
  int                     chance, fw_chance;

  /*
   * int w_index; 
   */

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

  if(IS_AFFECTED(victim, AFF_UNHOLY_SPHERE))
  {
    send_to_char("You cannot get near their unholy sphere.\r\n", ch);
    return rNONE;
  }

//  chance = number_chance( 1, 10 );

  if(number_chance(1, 10) == 10)
  {
    if(IS_AFFECTED(ch, AFF_SLOW))
    {
      act(AT_GREEN, "You try to attack, but move in a slow motion state.", ch, NULL, NULL, TO_CHAR);
      act(AT_GREEN, "$n tries to attack, but moves in a slow motion state.", ch, NULL, NULL, TO_ROOM);
      return rNONE;
    }
  }

  // Flaming shield support. -Taon
  if(IS_AFFECTED(victim, AFF_FLAMING_SHIELD) && number_chance(1, 15) >= 9)
  {

    ch_printf(victim, "&rYour flaming shield strikes %s.&D\r\n", ch->name);

    if(IS_NPC(victim))
      ch_printf(ch, "&rYou're struck with %s's flaming shield..&D\r\n", victim->short_descr);
    else
      ch_printf(ch, "&rYou're struck with %s's flaming shield..&D\r\n", victim->name);

    global_retcode = damage(victim, ch, number_chance(1, 20), gsn_flaming_shield);
  }

  used_weapon = NULL;
  /*
   * Figure out the weapon doing the damage   -Thoric
   * Dual wield support -- switch weapons each attack
   */
  if((wield = get_eq_char(ch, WEAR_DUAL_WIELD)) != NULL)
  {
    if(dual_flip == FALSE)
    {
      dual_flip = TRUE;
      wield = get_eq_char(ch, WEAR_WIELD);
    }
    else
      dual_flip = FALSE;
  }
  else
    wield = get_eq_char(ch, WEAR_WIELD);

  used_weapon = wield;

  if(wield)
    prof_bonus = weapon_prof_bonus_check(ch, wield, &prof_gsn);
  else
    prof_bonus = 0;

  if(ch->fighting /* make sure fight is already started */
     && dt == TYPE_UNDEFINED && IS_NPC(ch) && !xIS_EMPTY(ch->attacks))
  {
    cnt = 0;
    for(;;)
    {
      attacktype = number_range(0, (MAX_ATTACK_TYPE - 1));
      if(xIS_SET(ch->attacks, attacktype))
        break;
      if(cnt++ > 16)
      {
        attacktype = -1;
        break;
      }
    }
    if(attacktype == ATCK_BACKSTAB)
      attacktype = -1;
    if(wield && number_percent() > 25)
      attacktype = -1;
    if(!wield && number_percent() > 50)
      attacktype = -1;

    switch (attacktype)
    {
      default:
        break;

      case ATCK_BITE:
        do_bite(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_CLAWS:
        do_claw(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_TAIL_SWIPE:
        do_tail_swipe(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_STATICPULSE:
        retcode = spell_static_pulse(skill_lookup("static pulse"), ch->level, ch, victim);
        break;

      case ATCK_PUNCH:
        do_punch(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_KICK:
        do_kick(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_ELBOW:
        do_elbow(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_CORROSIVE:
        do_corrosive(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_HEADBUTT:
        do_headbutt(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_FLYBY:
        do_flyby(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_BLURATTACK:
        do_blur_attack(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_ACIDSPRAY:
        do_acid_spray(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_SWARM:
        do_swarm(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_ASTRALATTACK:
        do_astral_attack(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_BODYDROP:
        do_body_drop(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_MISTACID:
        do_mist_acid(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_CREEPINGDOOM:
        do_creeping_doom(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_ARTERIES:
        do_arteries(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_SPIKE:
        do_spike(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_QUIVERINGPALM:
        do_quivering_palm(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_THUNDEROUSHYMN:
        do_thunderous_hymn(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_PARALYZE:
        retcode = spell_paralyze(skill_lookup("paralyze"), ch->level, ch, victim);
        break;

      case ATCK_FEAR:
        do_fear(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_STOMP:
        do_stomp(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_CRITIC:
        do_critic(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_PSIONICBLAST:
        do_psionic_blast(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_FEROCIOUSSTRIKE:
        do_ferocious_strike(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_PLUCK:
        do_pluck(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_CRANEKICK:
        do_crane_kick(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_HHANDS:
        do_heavy_hands(ch, (char *)"");
        retcode = global_retcode;
        break;

      case ATCK_BACKHAND:
        do_backhand(ch, (char *)"");
        retcode = global_retcode;
        break;
    }
    if(attacktype >= 0)
      return retcode;
  }

  if(dt == TYPE_UNDEFINED)
  {
    dt = TYPE_HIT;
    if(wield && wield->item_type == ITEM_WEAPON)
      dt += wield->value[3];
  }

  /*
   * Calculate to-hit-armor-class-0 versus armor.
   */
  if(IS_NPC(ch))
  {
    thac0_00 = ch->mobthac0;
    thac0_32 = 0;
  }
  else
  {
    thac0_00 = class_table[ch->Class]->thac0_00;
    thac0_32 = class_table[ch->Class]->thac0_32;
  }

  if(ch->race == RACE_ANIMAL && !IS_NPC(ch))
  {
    thac0 = interpolate(ch->level, thac0_00, thac0_32) - (GET_HITROLL(ch) + ch->level / 5);
  }
  else
  {
    thac0 = interpolate(ch->level, thac0_00, thac0_32) - GET_HITROLL(ch);
  }
  victim_ac = UMAX(-19, (int)(GET_AC(victim) / 10));

  /*
   * if you can't see what's coming... 
   */
  if(wield && !can_see_obj(victim, wield))
    victim_ac += 1;
  if(!can_see(ch, victim))
    victim_ac -= 4;

  if(victim->race == RACE_DRAGON)
    victim_ac -= 10;

  /*
   * "learning" between combatants.  Takes the intelligence difference,
   * and multiplies by the times killed to make up a learning bonus
   * given to whoever is more intelligent  -Thoric
   * (basically the more intelligent one "learns" the other's fighting style)
   */
  if(ch->fighting && ch->fighting->who == victim)
  {
    short                   times = ch->fighting->timeskilled;

    if(times)
    {
      short                   intdiff = get_curr_int(ch) - get_curr_int(victim);

      if(intdiff != 0)
        victim_ac += (intdiff * times) / 10;
    }
  }

  /*
   * Weapon proficiency bonus 
   */
  victim_ac += prof_bonus;
  /*
   * The moment of excitement! 
   */
  diceroll = number_chance(1, 20);
  if(diceroll == 0 || (diceroll != 19 && diceroll < thac0 - victim_ac))
  {
    int                     bonus = 10;

    if(prof_gsn != -1)
      learn_from_failure(ch, prof_gsn);

    /*
     * Physical hit with no damage (hit natural AC) -Shade 
     */
    if(!IS_NPC(victim) && race_table[victim->race])
      bonus = race_table[victim->race]->ac_plus;
    if(diceroll < thac0 - victim_ac && diceroll >= thac0 - (10 + (dex_app[get_curr_dex(ch)].defensive / 10) + (bonus / 10) && diceroll != 19 && diceroll != 0))
    {
      short                   drama;  // Changed from int to short

      // -Taon.
      drama = number_range(1, 100);

      if(victim->Class == CLASS_MAGE)
      {
        if(drama > 50)
        {
          act(AT_LBLUE, "Your attack bounces off $N's shimmering wall of energy.", ch, NULL, victim, TO_CHAR);
          act(AT_LBLUE, "Your wall of energy shimmers as it deflects $n's attack.", ch, NULL, victim, TO_VICT);
          act(AT_LBLUE, "$n's attack bounces off $N's shimmering wall of energy.", ch, NULL, victim, TO_NOTVICT);
        }
        else
        {
          act(AT_ORANGE, "Your attack penetrates $N's shimmering wall of energy, but glances off $m.", ch, NULL, victim, TO_CHAR);
          act(AT_ORANGE, "Your wall of energy fails to deflects $n's attack, but it glances off you.", ch, NULL, victim, TO_VICT);
          act(AT_ORANGE, "$n's attack penetrates $N's wall of energy, but it glances off $m.", ch, NULL, victim, TO_NOTVICT);
        }
      }
      if(victim->race == RACE_DRAGON)
      {
        if(drama > 50)
        {
          act(AT_YELLOW, "Sparks fly as your attack is deflected by $N's thick dragon scales.", ch, NULL, victim, TO_CHAR);
          act(AT_YELLOW, "Sparks fly as your dragon hide deflects $n's attack.", ch, NULL, victim, TO_VICT);
          act(AT_YELLOW, "Sparks fly as $n's attack is deflected by $N's thick dragon scales.", ch, NULL, victim, TO_NOTVICT);
        }
        else
        {
          act(AT_ORANGE, "Your attack barely penetrates $N's smooth dragon scales.", ch, NULL, victim, TO_CHAR);
          act(AT_ORANGE, "$n's attack barely penetrates your smooth dragon scales.", ch, NULL, victim, TO_VICT);
          act(AT_ORANGE, "$n's attack barely penetrates $N's smooth dragon scales.", ch, NULL, victim, TO_NOTVICT);
        }
      }
      if(victim->Class != CLASS_MAGE && victim->race != RACE_DRAGON)
      {
        if(drama > 50)
        {
          act(AT_YELLOW, "Sparks fly as your attack is deflected by $N's armor.", ch, NULL, victim, TO_CHAR);
          act(AT_YELLOW, "Sparks fly as your armor deflects $n's attack.", ch, NULL, victim, TO_VICT);
          act(AT_YELLOW, "Sparks fly as $n's attack is deflected by $N's armor.", ch, NULL, victim, TO_NOTVICT);
        }
        else
        {
          act(AT_ORANGE, "Your attack gets through $N's armor, but is only superficial in damage.", ch, NULL, victim, TO_CHAR);
          act(AT_ORANGE, "$n's attack penetrates your armor, but only causes superficial damage.", ch, NULL, victim, TO_VICT);
          act(AT_ORANGE, "$n's attack penetrates $N's armor, but only causes supericial damage.", ch, NULL, victim, TO_NOTVICT);
        }
      }

      if(!victim->fighting && victim->in_room == ch->in_room)
        set_fighting(victim, ch);
      tail_chain();
      return rNONE;
    }
    else
    {
      /*
       * Miss. 
       */
      damage(ch, victim, 0, dt);
      tail_chain();
      return rNONE;
    }
  }

  short                   hull = 0;

  hull = number_range(1, 10);

  if(!IS_NPC(ch) && ch->pcdata->ship > 0 && hull > 8)
  {
    if(ch->pcdata->hull < 11)
    {
      ch->pcdata->hull = 0;
      ch_printf(ch, "&CThe first mate hollars, all hands for themself, the ship is sinking!\r\n");
      // add do_depart abandon for all players on ship.
      if(ch->pcdata->ship == 1)
      {
        int                     lroom, hroom;

        lroom = 56300;
        hroom = 56305;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 2)
      {
        int                     lroom, hroom;

        lroom = 56306;
        hroom = 56311;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 3)
      {
        int                     lroom, hroom;

        lroom = 56312;
        hroom = 56317;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 4)
      {
        int                     lroom, hroom;

        lroom = 56318;
        hroom = 56323;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 5)
      {
        int                     lroom, hroom;

        lroom = 56324;
        hroom = 56329;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 6)
      {
        int                     lroom, hroom;

        lroom = 56330;
        hroom = 56335;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 7)
      {
        int                     lroom, hroom;

        lroom = 56336;
        hroom = 56341;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 8)
      {
        int                     lroom, hroom;

        lroom = 56342;
        hroom = 56347;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 9)
      {
        int                     lroom, hroom;

        lroom = 56348;
        hroom = 56353;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 10)
      {
        int                     lroom, hroom;

        lroom = 56354;
        hroom = 56359;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 11)
      {
        int                     lroom, hroom;

        lroom = 56360;
        hroom = 56365;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 12)
      {
        int                     lroom, hroom;

        lroom = 56366;
        hroom = 56371;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 13)
      {
        int                     lroom, hroom;

        lroom = 56372;
        hroom = 56377;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 14)
      {
        int                     lroom, hroom;

        lroom = 56378;
        hroom = 56383;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 15)
      {
        int                     lroom, hroom;

        lroom = 56384;
        hroom = 56389;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 16)
      {
        int                     lroom, hroom;

        lroom = 56390;
        hroom = 56395;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 17)
      {
        int                     lroom, hroom;

        lroom = 56396;
        hroom = 56401;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 18)
      {
        int                     lroom, hroom;

        lroom = 56402;
        hroom = 56407;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 19)
      {
        int                     lroom, hroom;

        lroom = 56408;
        hroom = 56413;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }
      else if(ch->pcdata->ship == 20)
      {

        int                     lroom, hroom;

        lroom = 56414;
        hroom = 56419;
        for(ch = first_char; ch; ch = ch->next)
        {
          if(!IS_NPC(ch) && (ch->in_room->vnum <= hroom || ch->in_room->vnum >= lroom))
          {
            interpret(ch, (char *)"depart abandon");
          }
        }
      }

    }

    if(ch && ch->pcdata->hull > 10)
    {
      ch->pcdata->hull -= 1;
      ch_printf(ch, "&CThe first mate hollars, Captain the ship hull integrity is at %d\r\n", ch->pcdata->hull);
      if(xIS_SET(ch->act, PLR_COMMUNICATION))
        send_to_char("!!SOUND(sound/downwithhisship.wav)\r\n", ch);

    }
    if(!ch)
      return rNONE;

  }

  /*
   * Hit.
   * Calc damage.
   */

  dam = number_range(ch->barenumdie, ch->baresizedie * ch->barenumdie) + ch->damplus;

  if(!IS_NPC(ch) && get_eq_char(ch, WEAR_WIELD) == NULL)
  {
    if(ch->Class != CLASS_MONK)
    {
      if(ch->pcdata->learned[gsn_pugilism] > 0 && ch->pcdata->learned[gsn_pugilism] < 40)
        dam += get_curr_str(ch) / 4;
      else if(ch->pcdata->learned[gsn_pugilism] > 39 && ch->pcdata->learned[gsn_pugilism] < 80)
        dam += get_curr_str(ch) / 2;
      else if(ch->pcdata->learned[gsn_pugilism] > 79)
        dam += get_curr_str(ch);
    }
    if(ch->Class == CLASS_MONK)
    {
      if(ch->pcdata->learned[gsn_pugilism] > 0 && ch->pcdata->learned[gsn_pugilism] < 40)
        dam += 1;
      else if(ch->pcdata->learned[gsn_pugilism] > 39 && ch->pcdata->learned[gsn_pugilism] < 80)
        dam += number_range(1, 3);
      else if(ch->pcdata->learned[gsn_pugilism] > 79)
        dam += number_range(1, 4);
    }
  }

  if(IS_NPC(ch) && IS_ATTACK(ch, ATCK_PUGILISM))
  {
    dam += get_curr_str(ch) / 4;
  }

  if(IS_NPC(ch) && (xIS_SET(victim->act, PLR_EXTREME)))
  {
    dam *= 2;
  }

  if(wield)
  { /* bare hand dice formula fixed by Thoric */
    dam += number_range(wield->value[1], wield->value[2]);

    if(IS_NPC(ch) && (xIS_SET(victim->act, PLR_EXTREME)))
    {
      dam *= 2;
    }

    if(CAN_SHARPEN(wield) && wield->value[6] > 10 && wield->pIndexData->vnum != 41002)
    {

      if(number_chance(1, 20) == 1)
      {

        ch_printf(ch, "&wAs you attack, a small nick forms in %s, it will need to be sharpened.&D\r\n", wield->short_descr);
        wield->value[6]--;
        // update_weapon(ch, wield);
      }

      else if(number_range(1, 100) == 1)
      {
        ch_printf(ch, "&wAs you attack, a crack forms in %s it will need to be sharpened!&D\r\n", wield->short_descr);
        wield->value[6] -= 1;
//        update_weapon(ch, wield);
      }
      if(wield->value[6] < 25)
        wield->value[6] = 25;
    }
  }

  if(!IS_NPC(ch))
  {
    if(ch->pcdata->condition[COND_DRUNK] > 8 && ch->race == RACE_DWARF)
    {
      dam += (ch->pcdata->condition[COND_DRUNK] / 8);
    }
  }

/* 
 * Critical Hit Snippet
 *   By Josh Jenks [ Haelyn ]
 */

  chance = number_range(1, 100);
  chance += lck_app[get_curr_lck(ch)].luck; // make luck relevant
  if(chance > 99)
  {
    act(AT_FIRE, "You attempt a critical strike on $N!", ch, NULL, victim, TO_CHAR);
    act(AT_FIRE, "$n attempts a critical strike on you!", ch, NULL, victim, TO_VICT);
    act(AT_FIRE, "$n attempts a critical strike on $N!", ch, NULL, victim, TO_NOTVICT);
    dam += (int)(get_curr_str(ch) * 2);
  }

  if(ch->race == RACE_CENTAUR && chance < 26)
  {
    act(AT_ORANGE, "Your hooves trample $N!", ch, NULL, victim, TO_CHAR);
    act(AT_ORANGE, "$n's hooves trample you!", ch, NULL, victim, TO_VICT);
    act(AT_ORANGE, "$n's hooves trample $N!", ch, NULL, victim, TO_NOTVICT);
    dam += (int)(get_curr_str(ch) * 2);
  }

  /*
   * Bonuses.
   */
  // two-handers
  OBJ_DATA               *obj;

  if((obj = get_eq_char(ch, WEAR_WIELD)) != NULL)
  {
    if(obj->value[4] == WEP_2H_LONG_BLADE || obj->value[4] == WEP_2H_AXE || obj->value[4] == WEP_2H_BLUDGEON)
    {
      dam *= 4;
    }
  }

  /*
   * Blind people shouldnt hit as hard, or as often. -Taon 
   */
  if(IS_AFFECTED(ch, AFF_BLINDNESS) && !IS_AFFECTED(ch, AFF_NOSIGHT))
    dam = (int)(dam - ch->level / 2);

  if(!IS_NPC(ch) && ch->pcdata->learned[gsn_martial_arts] > 0 && get_eq_char(ch, WEAR_WIELD) == NULL && get_eq_char(ch, WEAR_DUAL_WIELD) == NULL)
  {
    short                   martial = 0;

    if(ch->level <= 4)
      martial += number_chance(1, 5);
    else if(ch->level <= 9)
      martial += number_chance(3, 8);
    else if(ch->level <= 19)
      martial += number_chance(3, 8);
    else if(ch->level <= 25)
      martial += number_chance(4, 8);
    else if(ch->level <= 34)
      martial += number_chance(4, 8);
    else if(ch->level <= 44)
      martial += number_chance(5, 8);
    else if(ch->level <= 54)
      martial += number_chance(6, 8);
    else if(ch->level <= 64)
      martial += number_chance(7, 9);
    else if(ch->level <= 74)
      martial += number_chance(8, 9);
    else if(ch->level <= 84)
      martial += number_chance(9, 10);
    else if(ch->level <= 99)
      martial += number_chance(9, 10);
    else
      martial += 10;

    if(ch->pcdata->learned[gsn_martial_arts] <= 10)
      dam += martial / 2;
    else if(ch->pcdata->learned[gsn_martial_arts] <= 20)
      dam += martial / 2;
    else if(ch->pcdata->learned[gsn_martial_arts] <= 30)
      dam += martial / 2;
    else if(ch->pcdata->learned[gsn_martial_arts] <= 40)
      dam += martial + 2;
    else if(ch->pcdata->learned[gsn_martial_arts] <= 50)
      dam += martial + 4;
    else if(ch->pcdata->learned[gsn_martial_arts] <= 70)
      dam += martial + 5;
    else if(ch->pcdata->learned[gsn_martial_arts] <= 90)
      dam += martial + 6;
    else
      dam += martial + 7;

    if(number_chance(0, 5) == 1)
      learn_from_success(ch, gsn_martial_arts);

  }

  if(ch->race == RACE_ANIMAL && !IS_NPC(ch))
  {
    dam += ch->level / 5;
  }

  if(ch->race == RACE_DRAGON && !IS_NPC(ch))
  {
    feet = ch->level + get_curr_str(ch);
    if(feet < 2)
    {
      feet = 1;
    }
    dam += (GET_DAMROLL(ch) + feet);
  }
  dam += GET_DAMROLL(ch);

  if(!IS_NPC(victim) && IS_NPC(ch) && victim->race == RACE_DRAGON)
  {
    if(ch->level >= victim->level)
    {
      if(victim->level < 10)
      {
        dam += number_range(1, 10);
      }
      else if(victim->level > 9 && victim->level < 20)
      {
        dam += number_range(5, 20);
      }
      else if(victim->level > 19 && victim->level < 30)
      {
        dam += number_range(10, 30);

      }
      else if(victim->level > 29 && victim->level < 40)
      {
        dam += number_range(20, 40);
      }
      else if(victim->level > 39 && victim->level < 50)
      {
        dam += number_range(30, 60);
      }
      else if(victim->level > 49 && victim->level < 60)
      {
        dam += number_range(40, 80);
      }
      else if(victim->level > 59 && victim->level < 70)
      {
        dam += number_range(50, 100);
      }
      else if(victim->level > 69 && victim->level < 80)
      {
        dam += number_range(60, 120);
      }
      else if(victim->level > 79)
      {
        dam += number_range(60, 150);
      }
    }
  }

  if(ch->position == POS_CRAWL)
  {
    dam /= 2;
  }

  if(prof_bonus)
    dam += prof_bonus / 4;

  if(victim->position == POS_BERSERK)
    dam = (int)(dam * 1.8);
  if(ch->position == POS_BERSERK)
    dam = (int)(dam * 2.0);

  // Some fury, sidestep support. -Taon
  if(IS_AFFECTED(victim, AFF_FURY))
    dam = (int)(dam + number_range(1, 4));
  if(IS_AFFECTED(ch, AFF_FURY))
    dam = (int)(dam + number_range(1, 4));

  // Following supports autoskill combat mind. -Taon
  if(!IS_NPC(ch) && ch->pcdata->learned[gsn_combat_mind] > 0 && number_chance(0, 10) > 8)
  {

    if(ch->pcdata->learned[gsn_combat_mind] < 30)
      dam += (int)(dam + number_range(1, 2));
    else if(ch->pcdata->learned[gsn_combat_mind] < 60)
      dam += (int)(dam + number_range(1, 3));
    else if(ch->pcdata->learned[gsn_combat_mind] < 85)
      dam += (int)(dam + number_range(1, 4));
    else
      dam += (int)(dam + number_range(2, 4));

    learn_from_success(ch, gsn_combat_mind);
  }

  // Following supports autoskill find weakness. -Taon
  fw_chance = number_chance(1, 10);

  if(xIS_SET(ch->defenses, DFND_FINDWEAKNESS))
  {
    dam += (int)(get_curr_str(ch) * 2);
    ch->move -= 2;
  }

  if(!IS_NPC(ch) && ch->pcdata->learned[gsn_find_weakness] > 0 && fw_chance > 9)
  {
    send_to_char("&WYou find a weakness in your foe's armor.&D\r\n", ch);
    dam += (int)(get_curr_str(ch) * 2);
    ch->move -= 2;
    learn_from_success(ch, gsn_find_weakness);
  }

  // Masters eye autoskill, near mock of enhanced damage but stronger -Taon
  if(!IS_NPC(ch) && ch->pcdata->learned[gsn_masters_eye] > 0)
  {
    dam += (int)(dam + number_range(1, 4));
    learn_from_success(ch, gsn_masters_eye);
  }

  if(IS_NPC(ch) && (xIS_SET(victim->act, PLR_EXTREME)))
  {
    dam *= 2;
  }

  // Added bonus damage for targets whom are sitting or resting. -Taon
  if(victim->position == POS_SITTING || victim->position == POS_RESTING)
    dam = (int)(dam * 1.1);
  if(!IS_AWAKE(victim))
    dam *= 2;
  if(dt == gsn_backstab)
    dam *= (2 + URANGE(2, ch->level - (victim->level / 4), 30) / 10);

  if(dam <= 0)
    dam = 1;

  plusris = 0;

  if(wield)
  {
    if(IS_OBJ_STAT(wield, ITEM_MAGIC))
      dam = ris_damage(victim, dam, RIS_MAGIC);
    else
      dam = ris_damage(victim, dam, RIS_NONMAGIC);

    /*
     * Handle PLUS1 - PLUS6 ris bits vs. weapon hitroll  -Thoric
     */
    plusris = obj_hitroll(wield);
  }
  else
    dam = ris_damage(victim, dam, RIS_NONMAGIC);

  /*
   * check for RIS_PLUSx      -Thoric 
   */
  if(dam)
  {
    int                     x, res, imm, sus, mod;

    if(plusris)
      plusris = RIS_PLUS1 << UMIN(plusris, 7);

    /*
     * initialize values to handle a zero plusris 
     */
    imm = res = -1;
    sus = 1;

    /*
     * find high ris 
     */
    for(x = RIS_PLUS1; x <= RIS_PLUS6; x <<= 1)
    {
      if(IS_SET(victim->immune, x))
        imm = x;
      if(IS_SET(victim->resistant, x))
        res = x;
      if(IS_SET(victim->susceptible, x))
        sus = x;
    }
    mod = 10;
    if(imm >= plusris)
      mod -= 10;
    if(res >= plusris)
      mod -= 3;

    if(sus <= plusris)
      mod += 2;

    /*
     * check if immune 
     */
    if(mod <= 0)
      dam = -1;
    if(mod != 10)
      dam = (dam * mod) / 10;
  }

  if(prof_gsn != -1)
  {
    if(dam > 0)
      learn_from_success(ch, prof_gsn);
    else
      learn_from_failure(ch, prof_gsn);
  }

  /*
   * immune to damage 
   */
  if(dam == -1)
  {
    if(dt >= 0 && dt < top_sn)
    {
      SKILLTYPE              *skill = skill_table[dt];
      bool                    found = FALSE;

      if(skill->imm_char && skill->imm_char[0] != '\0')
      {
        act(AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR);
        found = TRUE;
      }
      if(skill->imm_vict && skill->imm_vict[0] != '\0')
      {
        act(AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT);
        found = TRUE;
      }
      if(skill->imm_room && skill->imm_room[0] != '\0')
      {
        act(AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT);
        found = TRUE;
      }
      if(found)
        return rNONE;
    }
    dam = 0;
  }

  if(IS_NPC(victim) && xIS_SET(victim->act, ACT_IMMORTAL))
  {
    victim->hit += dam;
    if(number_bits(4) == 0)
    {
      act(AT_RED, "$N seems unaffected by your attacks.", ch, NULL, victim, TO_CHAR);
      act(AT_RED, "$N seems unaffected by $n's attacks.", ch, NULL, victim, TO_ROOM);
    }
  }

  if(IS_AFFECTED(victim, AFF_INVISIBLE))
  {
    affect_strip(victim, gsn_invis);
    xREMOVE_BIT(victim->affected_by, AFF_INVISIBLE);
  }

  if(IS_AFFECTED(victim, AFF_KINETIC))
  {
    if(victim->kinetic_dam > dam)
    {
      act(AT_YELLOW, "Your attack strikes $N's kinetic barrier.", ch, NULL, victim, TO_CHAR);
      if(ch != victim)
        act(AT_YELLOW, "$n's attack strikes your kinetic barrier.", ch, NULL, victim, TO_ROOM);
      else
        act(AT_YELLOW, "$n's attack strikes $N's kinetic barrier.", ch, NULL, victim, TO_ROOM);
      victim->kinetic_dam -= dam;
      dam = 0;
    }
    else
    {
      act(AT_YELLOW, "Your attack has shattered $N's kinetic barrier!", ch, NULL, victim, TO_CHAR);
      if(ch != victim)
        act(AT_YELLOW, "$n's attack has shattered your kinetic barrier!", ch, NULL, victim, TO_ROOM);
      else
        act(AT_YELLOW, "$n's attack has shattered $N's kinetic barrier!", ch, NULL, victim, TO_ROOM);
      affect_strip(victim, gsn_kinetic_barrier);
      xREMOVE_BIT(victim->affected_by, AFF_KINETIC);
    }
  }

  if(IS_AFFECTED(victim, AFF_WARD) || IS_AFFECTED(victim, AFF_ETHEREAL))
  {
    if(victim->ward_dam > dam)
    {
      act(AT_YELLOW, "Your attack strikes $N's protective ward.", ch, NULL, victim, TO_CHAR);
      act(AT_YELLOW, "$n's attack strikes $N's protective ward.", ch, NULL, victim, TO_ROOM);
      victim->ward_dam -= dam;
      dam = 0;
    }
    else
    {
      act(AT_YELLOW, "Your attack has shattered $N's protective ward!", ch, NULL, victim, TO_CHAR);
      act(AT_YELLOW, "$n's attack has shattered $N's protective ward!", ch, NULL, victim, TO_ROOM);
      affect_strip(victim, gsn_spirits_ward);
      affect_strip(victim, gsn_spectral_ward);
      affect_strip(victim, gsn_ward_of_ethereal);
      xREMOVE_BIT(victim->affected_by, AFF_WARD);
      xREMOVE_BIT(victim->affected_by, AFF_ETHEREAL);
    }
  }

  // mb 0 = I can use mb
  // mb 1 = using mb now in a fight
  // mb 2 = mb used can't use

  // Monk's possibly have damage mitigated to move points
  if(victim->Class == CLASS_MONK && !IS_NPC(victim))
  {
    if(victim->move / 4 > victim->pcdata->monkblood && (victim->pcdata->mb == 0 || victim->pcdata->mb == 1))
    {
      victim->pcdata->monkblood += dam;
      victim->move -= dam;
      dam = dam - get_curr_con(victim);
    }
    if(victim->move / 4 <= victim->pcdata->monkblood)
    {
      dam = victim->pcdata->monkblood;
      ch->success_attack = 1;
      victim->pcdata->monkblood = 0;
      victim->pcdata->mb = 2;
    }
  }

  if(IS_AFFECTED(victim, AFF_ETHEREAL))
  {
    dam = dam - (get_curr_con(victim) / 2);

  }

  if((retcode = damage(ch, victim, dam, dt)) != rNONE)
    return retcode;
  if(char_died(ch))
    return rCHAR_DIED;
  if(char_died(victim))
    return rVICT_DIED;

  retcode = rNONE;
  if(dam == 0)
    return retcode;

  /*
   * Weapon spell support     -Thoric
   * Each successful hit casts a spell
   */
  if(wield && !IS_SET(victim->immune, RIS_MAGIC) && !IS_SET(victim->in_room->room_flags, ROOM_NO_MAGIC))
  {
    AFFECT_DATA            *aff;

    for(aff = wield->pIndexData->first_affect; aff; aff = aff->next)
      if(aff->location == APPLY_WEAPONSPELL && IS_VALID_SN(aff->modifier) && skill_table[aff->modifier]->spell_fun)
        retcode = (*skill_table[aff->modifier]->spell_fun) (aff->modifier, (wield->level + 3) / 3, ch, victim);
    if(retcode != rNONE || char_died(ch) || char_died(victim))
      return retcode;
    for(aff = wield->first_affect; aff; aff = aff->next)
      if(aff->location == APPLY_WEAPONSPELL && IS_VALID_SN(aff->modifier) && skill_table[aff->modifier]->spell_fun)
        retcode = (*skill_table[aff->modifier]->spell_fun) (aff->modifier, (wield->level + 3) / 3, ch, victim);
    if(retcode != rNONE || char_died(ch) || char_died(victim))
      return retcode;
  }

  /*
   * magic shields that retaliate     -Thoric
   */

  if(IS_AFFECTED(victim, AFF_FIRESHIELD) && !IS_AFFECTED(ch, AFF_FIRESHIELD))
    retcode = spell_smaug(skill_lookup("flare"), off_shld_lvl(victim, ch), victim, ch);
  if(retcode != rNONE || char_died(ch) || char_died(victim))
    return retcode;

  if(IS_AFFECTED(victim, AFF_SPROUT_SPIKES) && !IS_AFFECTED(ch, AFF_SPROUT_SPIKES))
    retcode = spell_stick(skill_lookup("stick"), off_shld_lvl(victim, ch), victim, ch);
  if(retcode != rNONE || char_died(ch) || char_died(victim))
    return retcode;

  if(IS_AFFECTED(victim, AFF_NETTLE) && !IS_AFFECTED(ch, AFF_NETTLE))
    retcode = spell_barbs(skill_lookup("barbs"), off_shld_lvl(victim, ch), victim, ch);
  if(retcode != rNONE || char_died(ch) || char_died(victim))
    return retcode;

  if(IS_AFFECTED(victim, AFF_ICESHIELD) && !IS_AFFECTED(ch, AFF_ICESHIELD))
    retcode = spell_iceshard(skill_lookup("iceshard"), off_shld_lvl(victim, ch), victim, ch);
  if(retcode != rNONE || char_died(ch) || char_died(victim))
    return retcode;

  if(IS_AFFECTED(victim, AFF_SHOCKSHIELD) && !IS_AFFECTED(ch, AFF_SHOCKSHIELD))
    retcode = spell_smaug(skill_lookup("torrent"), off_shld_lvl(victim, ch), victim, ch);
  if(retcode != rNONE || char_died(ch) || char_died(victim))
    return retcode;

  if(IS_AFFECTED(victim, AFF_ACIDMIST) && !IS_AFFECTED(ch, AFF_ACIDMIST))
    retcode = spell_smaug(skill_lookup("acidshot"), off_shld_lvl(victim, ch), victim, ch);
  if(retcode != rNONE || char_died(ch) || char_died(victim))
    return retcode;

  if(IS_AFFECTED(victim, AFF_VENOMSHIELD) && !IS_AFFECTED(ch, AFF_VENOMSHIELD))
    retcode = spell_smaug(skill_lookup("venomshot"), off_shld_lvl(victim, ch), victim, ch);
  if(retcode != rNONE || char_died(ch) || char_died(victim))
    return retcode;

  tail_chain();
  return retcode;
}

/*
 * Calculate damage based on resistances, immunities and suceptibilities
 *     -Thoric
 */
short ris_damage(CHAR_DATA *ch, short dam, int ris)
{
  short                   modifier;

  if(IS_SET(ch->immune, ris) && !IS_SET(ch->no_immune, ris))
    return -1;

  /*
   * Change it based on resistance 
   */
  if(IS_SET(ch->resistant, ris) && !IS_SET(ch->no_resistant, ris))
  {
    modifier = 0;
    if(dam > 0)
      modifier = (dam / 10);
    dam -= modifier;
  }

  /*
   * Increase if susceptible 
   */
  if(IS_SET(ch->susceptible, ris) && !IS_SET(ch->no_susceptible, ris))
  {
    modifier = 0;
    if(dam > 0)
      modifier = (dam / 10);
    dam += modifier;
  }

  if(IS_AFFECTED(ch, AFF_UNSEARING_SKIN) && ris == RIS_FIRE);
  {
    modifier = 0;
    if(dam > 0)
      modifier = (dam / 5);
    dam -= modifier;
  }

  if(dam <= 0)
    return -1;
  return dam;
}

/* Inflict damage from a hit.   This is one damn big function. */
void                    new_dam_message(CHAR_DATA *ch, CHAR_DATA *victim, int dam, unsigned int dt, OBJ_DATA *obj);

ch_ret damage(CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt)
{
  OBJ_DATA               *damobj;
  OBJ_DATA               *pObj;
  CHAR_DATA              *gch;
  char                    buf[MSL], buf1[MSL];
  short                   dameq, maxdam, dampmod;
  short                   anopc = 0, bnopc = 0;
  bool                    npcvict, loot;
  ch_ret                  retcode = rNONE;

  if(!ch)
  {
    bug("%s Damage: null ch!", __FUNCTION__);
    return rERROR;
  }
  if(!victim)
  {
    bug("%s: null victim!", __FUNCTION__);
    return rVICT_DIED;
  }

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

  if(IS_AFFECTED(victim, AFF_FEIGN))
    return rVICT_DIED;

  if(IS_AFFECTED(ch, AFF_ENTHRALLED))
    return rNONE;

  /*
   * Lets set up the soldier to fight better 
   */
  if(IS_NPC(ch) && !ch->soldierset && ch->city && ch->siege)
  {
    CITY_DATA              *city = ch->city;

    if(city && (city->soldier_mob == ch->pIndexData->vnum || city->archer_mob == ch->pIndexData->vnum || city->guard_mob == ch->pIndexData->vnum || city->warrior_mob == ch->pIndexData->vnum))
    {
      if(city->soldier_mob == ch->pIndexData->vnum || city->archer_mob == ch->pIndexData->vnum || city->guard_mob == ch->pIndexData->vnum || city->warrior_mob == ch->pIndexData->vnum)
        set_soldier(ch, victim, FALSE);
      else
        set_soldier(ch, victim, TRUE);
    }
  }
  else if(IS_NPC(victim) && !victim->soldierset && victim->city && victim->siege)
  {
    CITY_DATA              *city = victim->city;

    if(city
       && (city->soldier_mob == victim->pIndexData->vnum
           || city->archer_mob == victim->pIndexData->vnum || city->guard_mob == victim->pIndexData->vnum || city->warrior_mob == victim->pIndexData->vnum))
    {
      if(city->soldier_mob == victim->pIndexData->vnum || city->archer_mob == victim->pIndexData->vnum || city->guard_mob == victim->pIndexData->vnum || city->warrior_mob == victim->pIndexData->vnum)
        set_soldier(victim, ch, FALSE);
      else
        set_soldier(victim, ch, TRUE);
    }
  }

  npcvict = IS_NPC(victim);

  /*
   * Check damage types for RIS     -Thoric
   */
  if(dam && dt != TYPE_UNDEFINED)
  {
    if(IS_FIRE(dt))
      dam = ris_damage(victim, dam, RIS_FIRE);
    else if(IS_COLD(dt))
      dam = ris_damage(victim, dam, RIS_COLD);
    else if(IS_ACID(dt))
      dam = ris_damage(victim, dam, RIS_ACID);
    else if(IS_ELECTRICITY(dt))
      dam = ris_damage(victim, dam, RIS_ELECTRICITY);
    else if(IS_ENERGY(dt))
      dam = ris_damage(victim, dam, RIS_ENERGY);
    else if(IS_DRAIN(dt))
      dam = ris_damage(victim, dam, RIS_DRAIN);
    else if(dt == gsn_poison || IS_POISON(dt))
      dam = ris_damage(victim, dam, RIS_POISON);
    else if(dt == (TYPE_HIT + DAM_CRUSH))
    {
      /*
       * Added checks for the 3 new dam types, and removed DAM_PEA - Grimm 
       * Removed excess duplication, added hack and lash RIS types - Samson 1-9-00 
       */
      dam = ris_damage(victim, dam, RIS_BLUNT);
    }
    else if(dt == (TYPE_HIT + DAM_STAB) || dt == (TYPE_HIT + DAM_PIERCE) || dt == (TYPE_HIT + DAM_THRUST))
      dam = ris_damage(victim, dam, RIS_PIERCE);
    else if(dt == (TYPE_HIT + DAM_SLASH))
      dam = ris_damage(victim, dam, RIS_SLASH);
    else if(dt == (TYPE_HIT + DAM_HACK))
      dam = ris_damage(victim, dam, RIS_HACK);
    else if(dt == (TYPE_HIT + DAM_LASH))
      dam = ris_damage(victim, dam, RIS_LASH);

    if(dam == -1)
    {
      if(dt >= 0 && dt < top_sn)
      {
        bool                    found = FALSE;
        SKILLTYPE              *skill = skill_table[dt];

        if(skill->imm_char && skill->imm_char[0] != '\0')
        {
          act(AT_HIT, skill->imm_char, ch, NULL, victim, TO_CHAR);
          found = TRUE;
        }
        if(skill->imm_vict && skill->imm_vict[0] != '\0')
        {
          act(AT_HITME, skill->imm_vict, ch, NULL, victim, TO_VICT);
          found = TRUE;
        }
        if(skill->imm_room && skill->imm_room[0] != '\0')
        {
          act(AT_ACTION, skill->imm_room, ch, NULL, victim, TO_NOTVICT);
          found = TRUE;
        }
        if(found)
          return rNONE;
      }
      dam = 0;
    }
  }

  /*
   * Precautionary step mainly to prevent people in Hell from finding
   * a way out. --Shaddai
   */
  if(IS_SET(victim->in_room->room_flags, ROOM_SAFE))
    dam = 0;

  if(dam && npcvict && ch != victim)
  {
    if(!xIS_SET(victim->act, ACT_SENTINEL))
    {
      if(victim->hunting)
      {
        if(victim->hunting->who != ch)
        {
          STRFREE(victim->hunting->name);
          victim->hunting->name = QUICKLINK(ch->name);
          victim->hunting->who = ch;
        }
      }
      else if(!xIS_SET(victim->act, ACT_PACIFIST))
        start_hunting(victim, ch);
    }

    if(victim->hating)
    {
      if(victim->hating->who != ch)
      {
        STRFREE(victim->hating->name);
        victim->hating->name = QUICKLINK(ch->name);
        victim->hating->who = ch;
      }
    }
    else if(!xIS_SET(victim->act, ACT_PACIFIST))  /* Gorog */
      start_hating(victim, ch);
  }

  /*
   * Stop up any residual loopholes.
   */
  maxdam = ch->level * 100;

  if(dam > maxdam && IS_NPC(victim))
  {
//    bug("Damage: %d more than %d points!", dam, maxdam);
//    bug("** %s (lvl %d) -> %s **", ch->name, ch->level, victim->name);
    dam = maxdam;
  }

  if(victim != ch)
  {
    /*
     * Lets change the hate_level if need be 
     * Not sure if we should change it up and down but shrug 
     * Feel free to modify it how you want, this is just mainly testing for now 
     * Depending on how much damage is normaly done on how many you might need to
     * give Different spots for I just did up to 50 for now 
     */
    if(!IS_AFFECTED(ch, AFF_HATE))
    {
      if(dam > 0)
      {
        if(dam <= 10)
          ch->hate_level = 0;
        else if(dam <= 20)
          ch->hate_level = 1;
        else if(dam <= 30)
          ch->hate_level = 2;
        else if(dam <= 40)
          ch->hate_level = 3;
        else if(dam <= 50)
          ch->hate_level = 4;
        else if(dam <= 60)
          ch->hate_level = 5;
        else if(dam <= 70)
          ch->hate_level = 6;
        else if(dam <= 80)
          ch->hate_level = 7;
        else if(dam <= 90)
          ch->hate_level = 8;
        else if(dam <= 100)
          ch->hate_level = 9;
        else if(dam <= 150)
          ch->hate_level = 10;
        else if(dam <= 200)
          ch->hate_level = 11;
        else if(dam <= 250)
          ch->hate_level = 12;
        else if(dam <= 300)
          ch->hate_level = 13;
        else if(dam <= 350)
          ch->hate_level = 14;
        else if(dam <= 400)
          ch->hate_level = 15;
        else if(dam <= 450)
          ch->hate_level = 16;
        else if(dam <= 500)
          ch->hate_level = 17;
        else if(dam <= 550)
          ch->hate_level = 18;
        else if(dam <= 600)
          ch->hate_level = 19;
        else if(dam <= 650)
          ch->hate_level = 20;
        else if(dam <= 700)
          ch->hate_level = 21;
        else if(dam <= 800)
          ch->hate_level = 22;
        else if(dam <= 850)
          ch->hate_level = 23;
        else if(dam <= 875)
          ch->hate_level = 24;
        else if(dam <= 900)
          ch->hate_level = 25;
        else if(dam <= 950)
          ch->hate_level = 26;
        else if(dam <= 975)
          ch->hate_level = 27;
        else if(dam <= 900)
          ch->hate_level = 28;
        else if(dam <= 950)
          ch->hate_level = 29;
        else if(dam <= 1000)
          ch->hate_level = 30;
        else if(dam <= 1100)
          ch->hate_level = 31;
        else if(dam <= 1200)
          ch->hate_level = 32;
        else if(dam <= 1300)
          ch->hate_level = 33;
        else if(dam <= 1400)
          ch->hate_level = 34;
        else if(dam <= 1500)
          ch->hate_level = 35;
        else if(dam <= 1600)
          ch->hate_level = 36;
        else if(dam <= 1800)
          ch->hate_level = 37;
        else if(dam <= 1900)
          ch->hate_level = 38;
        else if(dam <= 2000)
          ch->hate_level = 39;
        else if(dam <= 2100)
          ch->hate_level = 40;
        else if(dam <= 2200)
          ch->hate_level = 41;
        else if(dam <= 2300)
          ch->hate_level = 42;
        else  /* Shrug might as well have a * * * * * * * * * * default for * * anything
               * * * else */
          ch->hate_level = 43;
      }
    }

    /*
     * Certain attacks are forbidden.
     * Most other attacks are returned.
     */
    if(is_safe(ch, victim, TRUE))
      return rNONE;

/* So you're safe. Or are you? Still need to check peacefuls/deadlies, and config +nice - volk */
/* On second thought, HTF to check if they HAVEN'T used murder command? need a bool-in-function.
   Or even better, let's move this mess to the ch_ret spell_smaug func where this happened in the
   first place! */

    check_attacker(ch, victim);

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

      /*
       * vwas: victim->position = POS_FIGHTING; 
       */
      if(IS_NPC(victim) && victim->fighting)
        set_position(victim, POS_FIGHTING);
      else if(victim->fighting)
      {
        switch (victim->style)
        {
          case (STYLE_EVASIVE):
            set_position(victim, POS_EVASIVE);
            break;
          case (STYLE_DEFENSIVE):
            set_position(victim, POS_DEFENSIVE);
            break;
          case (STYLE_AGGRESSIVE):
            set_position(victim, POS_AGGRESSIVE);
            break;
          case (STYLE_BERSERK):
            set_position(victim, POS_BERSERK);
            break;
          default:
            set_position(victim, POS_FIGHTING);
        }
      }
    }

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

      /*
       * If victim is charmed, ch might attack victim's master.
       */
      if(IS_NPC(ch) && npcvict && IS_AFFECTED(victim, AFF_CHARM) && victim->master && victim->master->in_room == ch->in_room && number_bits(3) == 0)
      {
        stop_fighting(ch, FALSE);
        retcode = multi_hit(ch, victim->master, TYPE_UNDEFINED);
        return retcode;
      }
    }

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

    /*
     * Pkill stuff.  If a deadly attacks another deadly or is attacked by
     * one, then ungroup any nondealies.  Disabled untill I can figure out
     * the right way to do it.
     */

    /*
     * count the # of non-pkill pc in a(not including == ch) 
     */
    for(gch = ch->in_room->first_person; gch; gch = gch->next_in_room)
      if(is_same_group(ch, gch) && !IS_NPC(gch) && !IS_PKILL(gch) && (ch != gch))
        anopc++;

    /*
     * count the # of non-ekill pc in b(not including == victim) 
     */
    for(gch = victim->in_room->first_person; gch; gch = gch->next_in_room)
      if(is_same_group(victim, gch) && !IS_NPC(gch) && !IS_PKILL(gch) && (victim != gch))
        bnopc++;

    /*
     * only consider disbanding if both groups have 1(+) non-pk pc,
     * or when one participant is pc, and the other group has 1(+)
     * pk pc's (in the case that participant is only pk pc in group) 
     */
    if((bnopc > 0 && anopc > 0) || (bnopc > 0 && !IS_NPC(ch)) || (anopc > 0 && !IS_NPC(victim)))
    {
      /*
       * Disband from same group first 
       */
      if(is_same_group(ch, victim))
      {
        /*
         * Messages to char and master handled in stop_follower 
         */
        act(AT_ACTION, "$n disbands from $N's group.", (ch->leader == victim) ? victim : ch, NULL, (ch->leader == victim) ? victim->master : ch->master, TO_NOTVICT);
        if(ch->leader == victim)
          stop_follower(victim);
        else
          stop_follower(ch);
      }
      /*
       * if leader isnt pkill, leave the group and disband ch 
       */
      if(ch->leader != NULL && !IS_NPC(ch->leader) && !IS_PKILL(ch->leader))
      {
        act(AT_ACTION, "$n disbands from $N's group.", ch, NULL, ch->master, TO_NOTVICT);
        stop_follower(ch);
      }
      else
      {
        for(gch = ch->in_room->first_person; gch; gch = gch->next_in_room)
          if(is_same_group(gch, ch) && !IS_NPC(gch) && !IS_PKILL(gch) && gch != ch)
          {
            act(AT_ACTION, "$n disbands from $N's group.", ch, NULL, gch->master, TO_NOTVICT);
            stop_follower(gch);
          }
      }
      /*
       * if leader isnt pkill, leave the group and disband victim 
       */
      if(victim->leader != NULL && !IS_NPC(victim->leader) && !IS_PKILL(victim->leader))
      {
        act(AT_ACTION, "$n disbands from $N's group.", victim, NULL, victim->master, TO_NOTVICT);
        stop_follower(victim);
      }
      else
      {
        for(gch = victim->in_room->first_person; gch; gch = gch->next_in_room)
          if(is_same_group(gch, victim) && !IS_NPC(gch) && !IS_PKILL(gch) && gch != victim)
          {
            act(AT_ACTION, "$n disbands from $N's group.", gch, NULL, gch->master, TO_NOTVICT);
            stop_follower(gch);
          }
      }
    }

    /*
     * Inviso attacks ... not.
     */
    if(IS_AFFECTED(ch, AFF_INVISIBLE))
    {
      affect_strip(ch, gsn_invis);
      affect_strip(ch, gsn_mass_invis);
      xREMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
      act(AT_MAGIC, "$n fades into existence.", ch, NULL, NULL, TO_ROOM);
    }

    if(IS_AFFECTED(ch, AFF_HIDE) || IS_AFFECTED(ch, AFF_SNEAK))
    {
      affect_strip(ch, gsn_sneak);
      affect_strip(ch, gsn_hide);
      xREMOVE_BIT(ch->affected_by, AFF_HIDE);
      xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
    }

    /*
     * Damage modifiers.
     */

    if(IS_NPC(ch) && (xIS_SET(victim->act, PLR_EXTREME)))
    {
      dam *= 2;
    }

    if(victim && victim->level > 20)
    {
      if(xIS_SET(victim->act, ACT_BEASTPET))
        dam /= 2;
    }

    bool                    defense = FALSE;  // need to set all these damage reductions
                                              // to TRUE and check if FALSE to work.

    if(!IS_NPC(victim))
    {
      if(defense == FALSE && (victim->Class == CLASS_FISH || victim->race == RACE_DRAGON))
      {
        if(dam > 0 && victim->pcdata->learned[gsn_hardened_scales] > 0)
        {
          short                   skin;

          skin = number_range(1, 10);
          defense = TRUE;
          if(victim->Class == CLASS_FISH)
          {
            dam = (int)(dam / 2);
          }
          else
          {
            if(victim->pcdata->learned[gsn_hardened_scales] < 25 && skin > 4)
              dam = (int)(dam / 2);
            if((victim->pcdata->learned[gsn_hardened_scales] < 50 && victim->pcdata->learned[gsn_hardened_scales] > 24) && skin > 3)
              dam = (int)(dam / 4);
            if((victim->pcdata->learned[gsn_hardened_scales] < 100 && victim->pcdata->learned[gsn_hardened_scales] > 49))
              dam = (int)(dam / 5);
          }
          if(skin == 8)
            learn_from_success(victim, gsn_hardened_scales);
        }
      }
      if(defense == FALSE && (victim->Class == CLASS_WOLF || victim->Class == CLASS_BEAR || victim->Class == CLASS_GRYPHON || victim->Class == CLASS_OWL))
      {
        if(dam > 0 && victim->pcdata->learned[gsn_thick_hide] > 0)
        {
          short                   skin;

          defense = TRUE;
          skin = number_range(1, 10);

          if(victim->pcdata->learned[gsn_thick_hide] < 25 && skin > 4)
            dam = (int)(dam / 10);
          if((victim->pcdata->learned[gsn_thick_hide] < 50 && victim->pcdata->learned[gsn_thick_hide] > 24) && skin > 3)
            dam = (int)(dam / 5);
          if((victim->pcdata->learned[gsn_thick_hide] < 100 && victim->pcdata->learned[gsn_thick_hide] > 49) && skin > 1)
            dam = (int)(dam / 2);
          if(skin <= 2)
            learn_from_success(victim, gsn_thick_hide);
        }
      }
      if(defense == FALSE && (victim->Class == CLASS_TREANT || victim->Class == CLASS_DRUID))
      {
        if(dam > 0 && victim->pcdata->learned[gsn_bark_skin] > 0)
        {
          short                   skin;

          defense = TRUE;
          skin = number_range(1, 10);

          if(victim->pcdata->learned[gsn_bark_skin] < 25 && skin > 4)
            dam = (int)(dam / 10);
          if((victim->pcdata->learned[gsn_bark_skin] < 50 && victim->pcdata->learned[gsn_bark_skin] > 24) && skin > 3)
            dam = (int)(dam / 5);
          if((victim->pcdata->learned[gsn_bark_skin] < 100 && victim->pcdata->learned[gsn_bark_skin] > 49) && skin > 1)
            dam = (int)(dam / 2);
          if(skin == 8)
            learn_from_success(victim, gsn_bark_skin);
        }
      }

      if(IS_AFFECTED(victim, AFF_SANCTUARY))
        dam /= 2;
      if(IS_AFFECTED(victim, AFF_PROTECT))
        dam -= (int)(dam / 10);
      if(IS_AFFECTED(victim, AFF_SHIELD))
        dam = (int)(dam / 2);
    }
    else
    {
      if(IS_AFFECTED(victim, AFF_SANCTUARY))
        dam /= 2;
      if(IS_AFFECTED(victim, AFF_PROTECT))
        dam -= (int)(dam / 10);
      if(IS_AFFECTED(victim, AFF_SHIELD))
        dam = (int)(dam / 2);
    }

    if(victim->race == RACE_DRAGON)
      dam /= 2; // stop dragons from getting ass
    // handed to them from non-dragons

    if(!IS_NPC(victim))
    {
      if(dam > 0 && defense == FALSE && (victim->pcdata->learned[gsn_iron_skin] > 0))
      {
        short                   iron = 0;

        defense = TRUE;
        number_range(1, 10);
        dam = (int)(dam / 2);

        if(iron == 10)
          learn_from_success(victim, gsn_iron_skin);
      }
    }
    bool                    shield = FALSE;
    short                   deflect;
    int                     iWear;

    deflect = number_range(1, 4);
    // Lets reduce damage if wearing wear_shield 
    for(iWear = 0; iWear < MAX_WEAR; iWear++)
    {
      for(pObj = victim->first_carrying; pObj; pObj = pObj->next_content)
      {
        if(pObj->wear_loc == iWear)
        {
          if(get_eq_char(victim, WEAR_SHIELD))
          {
            shield = TRUE;
          }
        }
      }
    }

    OBJ_DATA               *obj;

    if((obj = get_eq_char(victim, WEAR_SHIELD)) != NULL && deflect >= 2)
    {
      if(obj->value[0] != 1)
      {
        if(obj->level <= 20)
        {
          obj->value[0] -= 1;
        }
        else if(obj->level <= 40 && obj->level > 20)
        {
          obj->value[0] -= 2;
        }
        else if(obj->level <= 60 && obj->level > 40)
        {
          obj->value[0] -= 3;
        }
        else if(obj->level > 60)
        {
          obj->value[0] -= 4;
        }
      }
      if(obj->value[0] < 1)
      {
        obj->value[0] = 2;
      }
      if(obj->value[0] < obj->value[1] / 2 && obj->value[0] != 1)
      {
        obj->value[0] = 1;
        act(AT_ACTION, "Your shield crumples around your arm and is now useless.", victim, NULL, NULL, TO_CHAR);
        act(AT_ACTION, "$n's shield crumples around $s arm and is now useless.", victim, NULL, NULL, TO_ROOM);
      }
    }

    /*
     * Need a check in here to check shield object condition, and whether it would scrap 
     * from the amount of damage it is taking. -- Vladaar 
     */

    if(shield == TRUE && deflect >= 2 && obj->value[0] != 1)
    {
      act(AT_ACTION, "Your attack strikes $N's shield.", ch, NULL, victim, TO_CHAR);
      act(AT_ACTION, "$n's attack strikes $N's shield.", ch, NULL, victim, TO_ROOM);
      dam = (int)(dam / 2);
    }

    if(dam > 0 && defense == FALSE && !IS_NPC(victim) && (victim->pcdata->learned[gsn_ethereal_body] > 0))
    {
      short                   meep = number_range(1, 10);

      defense = TRUE;
      dam = (int)(dam / 2);

      if(meep == 10)
        learn_from_success(victim, gsn_ethereal_body);

    }

    if(!IS_NPC(victim) && get_eq_char(victim, WEAR_WIELD) == NULL)
    {
      if(victim->pcdata->learned[gsn_pugilism] > 0 && (number_range(1, 20) > 15))
        learn_from_success(victim, gsn_pugilism);
    }

    if(dam > 0 && defense == FALSE && !IS_NPC(victim) && (victim->pcdata->learned[gsn_mitigate] > 0))
    {
      short                   mitty;

      defense = TRUE;

      mitty = number_range(1, 10);
      // need checks so multiclass don't stack damage reductions
      if(victim->pcdata->learned[gsn_tumble] == 0)
      {
        dam = (int)(dam / 2);

        if(IS_AFFECTED(victim, AFF_HUNKER_DOWN))
          dam = (int)(dam / 2);

        if(mitty == 7)
          learn_from_success(victim, gsn_mitigate);
      }
    }

    if(dam > 0 && defense == FALSE && !IS_NPC(victim) && (victim->pcdata->learned[gsn_density] > 0))
    {
      short                   den;

      den = number_range(1, 10);
      defense = TRUE;
      if(victim->secondclass == -1)
      {
        dam = (int)(dam / 2);

        if(den == 7)
          learn_from_success(victim, gsn_density);
      }
    }

    if(dam > 0 && defense == FALSE && !IS_NPC(victim) && (victim->pcdata->learned[gsn_tumble] > 0))
    {
      short                   tum;

      defense = TRUE;
      tum = number_range(1, 10);
      // don't let it stack for multiclass
      if(victim->pcdata->learned[gsn_mitigate] == 0)
      {
        dam = (int)(dam / 2);

        if(tum == 7)
          learn_from_success(victim, gsn_tumble);
      }
    }

    if(dam > 0 && defense == FALSE && !IS_NPC(victim) && (victim->pcdata->learned[gsn_marble_skin] > 0))
    {
      short                   skin;

      defense = TRUE;
      skin = number_range(1, 10);
      dam = (int)(dam / 2);
      if(skin >= 8)
      {
        learn_from_success(victim, gsn_marble_skin);
      }
    }

    if(dam > 0 && defense == FALSE && !IS_NPC(victim) && (victim->pcdata->learned[gsn_glacial_armor] > 0))
    {
      short                   glacial;

      defense = TRUE;
      glacial = number_range(1, 10);

      if(victim->secondclass == -1)
      {

        if(glacial == 7)
          learn_from_success(victim, gsn_glacial_armor);
        dam = (int)(dam / 2);
      }

    }
    if(dam < 0)
      dam = 0;

    SKILLTYPE              *skill;
    int                     mod;

    mod = abs(dt);
    if(IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL
       && skill->type == SKILL_SPELL && IS_SINGLECLASS(ch) && NOT_FWARRIOR(ch)
       && ch->Class != CLASS_ANGEL && ch->Class != CLASS_HELLSPAWN && ch->race != RACE_DRAGON && ch->Class != CLASS_DRAGONLORD && ch->Class != CLASS_BARD)
    {
      dam *= 2;
    }

    if(IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL && skill->type == SKILL_SPELL && NOT_FWARRIOR(ch) && NOT_SWARRIOR(ch) && NOT_TWARRIOR(ch) && ch->secondclass != -1)
    {
      dam = (int)(dam * 1.5);
    }

    if(mod == gsn_kick || mod == gsn_heavy_hands || mod == gsn_punch || mod == gsn_bite
       || mod == ATCK_FIREBALL || mod == ATCK_CLAWS || mod == ATCK_TAIL_SWIPE
       || mod == ATCK_STATICPULSE || mod == ATCK_BACKHAND || mod == ATCK_LOWBLOW || mod == ATCK_EBOLT
       || mod == ATCK_STUN || mod == ATCK_GOUGE || mod == ATCK_BACKSTAB || mod == ATCK_FEED
       || mod == ATCK_DRAIN || mod == ATCK_MENTALASSAULT || mod == ATCK_GSMITE
       || mod == ATCK_BREATHE || mod == ATCK_GUT || mod == ATCK_IMPALE
       || mod == ATCK_FROST || mod == ATCK_POISON || mod == ATCK_SLOW
       || mod == ATCK_THROATPUNCH || mod == ATCK_RAKE || mod == ATCK_THAITIN
       || mod == ATCK_JUDOCHOP || mod == ATCK_SHRIEKINGNOTE || mod == ATCK_MURAZORWHIP
       || mod == ATCK_BUTTERFLYKICK || mod == ATCK_SNATCH || mod == ATCK_FIREBALL
       || mod == ATCK_LIGHTNING || mod == ATCK_WEAKEN || mod == ATCK_PUGILISM || mod == ATCK_INFERNO || mod == ATCK_BLIZZARD || mod == ATCK_BLIGHTNING || mod == ATCK_BRAINBOIL || mod == ATCK_LTOUCH)
    {
      ch->success_attack = 1;
    }

    if(IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL && skill->type == SKILL_SPELL && ch->success_attack != 1)
    {
      ch->success_attack = 1;
    }
    else if(IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL && skill->type == SKILL_SPELL && victim->success_attack != 1)
    {
      victim->success_attack = 1;
    }
    else if(IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL && skill->type == SKILL_SKILL && ch->success_attack != 1)
    {
      ch->success_attack = 1;
    }
    else if(IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL && skill->type == SKILL_SKILL && dt > TYPE_HIT && victim->success_attack != 1)
    {
      victim->success_attack = 1;
    }

    if(IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL && skill->type == SKILL_SKILL && IS_NPC(victim))
    {
      dam = (int)(dam * 1.8);
    }

    ch->damage_amount = 0;
    dam = dam * ch->success_attack; // Fury
    ch->damage_amount = dam;

    /*
     * Check for disarm, trip, parry, dodge, tumble and phase, 
     shieldblock, and displacement.
     */
    if(dt >= TYPE_HIT && ch->in_room == victim->in_room)
    {
      if(IS_NPC(ch) && xIS_SET(ch->defenses, DFND_DISARM) && ch->level > 9 && number_percent() < ch->level / 3)
        disarm(ch, victim);
      // lets make this occur less often from mobs. -Taon
      if(IS_NPC(ch) && number_chance(0, 10) > 8)
      {
        if(IS_NPC(ch) && xIS_SET(ch->attacks, ATCK_BACKHAND) && ch->level > 5 && number_percent() < ch->level / 2)
          trip(ch, victim);
      }

      if(check_parry(ch, victim))
      {
        if(xIS_SET(ch->act, PLR_BATTLE))
          send_to_char("!!SOUND(sound/parry.wav)\r\n", ch);
        return rNONE;
      }

      if(check_dodge(ch, victim))
      {
        if(xIS_SET(ch->act, PLR_BATTLE))
          send_to_char("!!SOUND(sound/miss.wav)\r\n", ch);
        return rNONE;
      }

      if(check_tumble(ch, victim))
      {
        if(xIS_SET(ch->act, PLR_BATTLE))
          send_to_char("!!SOUND(sound/miss.wav)\r\n", ch);
        return rNONE;
      }

      if(check_phase(ch, victim))
      {
        if(xIS_SET(ch->act, PLR_BATTLE))
          send_to_char("!!SOUND(sound/miss.wav)\r\n", ch);
        return rNONE;
      }

      if(check_displacement(ch, victim))
      {
        if(xIS_SET(ch->act, PLR_BATTLE))
          send_to_char("!!SOUND(sound/miss.wav)\r\n", ch);
        return rNONE;
      }
    }

    /*
     * Check control panel settings and modify damage
     */
    if(IS_NPC(ch))
    {
      if(npcvict)
        dampmod = sysdata.dam_mob_vs_mob;
      else
        dampmod = sysdata.dam_mob_vs_plr;
    }
    else
    {
      if(npcvict)
        dampmod = sysdata.dam_plr_vs_mob;
      else
        dampmod = sysdata.dam_plr_vs_plr;
    }
// Volk Jan-16: Bug fix to prevent 0 damage when above settings are below 100%
    if(dampmod > 0)
    {
      dam = (dam * dampmod);
      if(dam > 0 && dam < 100)
        dam = 100;
      dam = dam / 100;
    }
  }

  /*
   * Code to handle equipment getting damaged, and also support  -Thoric
   * bonuses/penalties for having or not having equipment where hit
   */

  if(dam > 50 && dt != TYPE_UNDEFINED && dt != gsn_poison)
  {
    /*
     * get a random body eq part 
     */
    // Lets not let eq damage in the arena. -Taon
    if(!in_arena(victim))
    {
      dameq = number_range(WEAR_LIGHT, WEAR_R_WING);
      damobj = get_eq_char(victim, dameq);
      if(damobj)
      {
        if(dam > get_obj_resistance(damobj) && number_bits(1) == 0 && number_chance(1, 10) >= 8)
        {
          set_cur_obj(damobj);
          damage_obj(damobj);
        }
        dam -= 5; /* add a bonus for having something to block the blow */
      }
      else
        dam += 5; /* add penalty for bare skin! */
    }
  }

  if(dam == 0)
    ch->success_attack = 0;

  if(ch != victim)
    dam_message(ch, victim, dam, dt);

  /*
   * Hurt the victim, Inform the victim of his new state.
   */
  victim->hit -= dam;

  short                   arrow = number_range(1, 4);

  if(!IS_NPC(ch))
  {
    if(ch->pcdata->learned[gsn_archery] > 80)
      arrow += 1;
    if(get_curr_dex(ch) > 18)
      arrow += 1;
    if(get_curr_dex(ch) < 15)
      arrow -= 1;
  }

  if(dam > 0 && arrow == 4)
    lodge_projectile(ch, victim);

  short                   chance;

  chance = number_range(1, 4);
  if(victim->secondclass == -1)
  {
    chance += 1;
  }

  if(IS_AFFECTED(victim, AFF_REACTIVE) && dam > 0 && victim->hit > 0 && number_percent() > 40 && chance > 1)
  {
    act(AT_MAGIC, "$n reactively heals some damage.", victim, NULL, NULL, TO_ROOM);
    act(AT_MAGIC, "An energy fills you and you reactively heal some of the damage.", victim, NULL, NULL, TO_CHAR);
    if(victim->level < 20)
      victim->hit += number_range(3, 18);
    if(victim->level > 19 && victim->level < 40)
      victim->hit += number_range(6, 36);
    if(victim->level > 39 && victim->level < 60)
      victim->hit += number_range(9, 54);
    if(victim->level > 59 && victim->level < 80)
      victim->hit += number_range(18, 72);
    if(victim->level > 79)
      victim->hit += number_range(40, 120);
    if(victim->hit > victim->max_hit)
      victim->hit = victim->max_hit;
  }

  // Not sure how this will work out just want to make it beneficial to be baker,
  // may
  // adjust later.
  if((IS_AFFECTED(victim, AFF_CRAFTED_FOOD1) || IS_AFFECTED(victim, AFF_CRAFTED_FOOD2) || IS_AFFECTED(victim, AFF_CRAFTED_FOOD3)) && number_percent() > 40 && chance > 2)
  {
    act(AT_MAGIC, "Your belly feels warm as the crafted food regeneration begins.", victim, NULL, NULL, TO_CHAR);

    if(IS_AFFECTED(victim, AFF_CRAFTED_FOOD1) && (!IS_NPC(victim)))
      victim->hit += (int)(double)number_range(1, 12);
    if(IS_AFFECTED(victim, AFF_CRAFTED_FOOD2) && (!IS_NPC(victim)))
      victim->hit += (int)(double)number_range(3, 18);
    if(IS_AFFECTED(victim, AFF_CRAFTED_FOOD3) && (!IS_NPC(victim)))
      victim->hit += (int)(double)number_range(6, 36);
    if(victim->hit > victim->max_hit)
      victim->hit = victim->max_hit;
  }

  /*
   * Get experience based on % of damage done       -Thoric
   */
  if(dam && ch != victim && !IS_NPC(ch) && ch->fighting && ch->fighting->xp && (!IS_NPC(victim) || !xIS_SET(victim->act, ACT_IMMORTAL)))
  {
    int                     xp_gain = 0;

    if(!IS_AFFECTED(ch, AFF_FEIGN))
    {
      if(ch->fighting->who == victim)
        xp_gain = ((ch->fighting->xp * dam) / (victim->max_hit)) * (victim->level / ch->level);
      else
        xp_gain = (int)(xp_compute(ch, victim) * 0.85 * dam) / victim->max_hit;
      // Stop players from losing exp during combat. -Taon
      if(xp_gain <= 0)
        xp_gain = 0;
      gain_exp(ch, xp_gain);
    }
  }

  /*
   * If immortal or new player don't let them die 
   */
  if(!IS_NPC(victim) && (victim->level >= LEVEL_IMMORTAL || NEW_AUTH(victim)) && victim->hit < 1)
    victim->hit = 1;

  if(dam > 0 && dt > TYPE_HIT && !IS_AFFECTED(victim, AFF_POISON) && is_wielding_poisoned(ch) && !IS_SET(victim->immune, RIS_POISON) && !saves_poison_death(ch->level, victim))
  {
    AFFECT_DATA             af;

    af.type = gsn_poison;
    af.duration = 20;
    af.location = APPLY_STR;
    af.modifier = -2;
    af.level = ch->level;
    af.bitvector = meb(AFF_POISON);
    affect_join(victim, &af);
    if(IS_SECONDCLASS(ch))
      victim->degree = 2;
    if(IS_THIRDCLASS(ch))
      victim->degree = 3;
    if(ch->secondclass == -1)
      victim->degree = 1;

    victim->mental_state = URANGE(20, victim->mental_state + (IS_PKILL(victim) ? 1 : 2), 100);
  }

  /*
   * Vampire self preservation     -Thoric
   */
  if(IS_BLOODCLASS(victim) && victim->level < 50)
  {
    if(dam >= (victim->max_hit / 10))
      victim->blood = (victim->blood - 1 - (victim->level / 20));

    if(victim->hit <= (victim->max_hit / 8) && victim->blood > 5)
    {
      if(victim->blood >= victim->blood / 2)
      {
        victim->hit += URANGE(12, (victim->max_hit / 30), 45);
        victim->blood = (victim->blood - URANGE(6, victim->level / 10, 12));
      }
      else
      {
        victim->blood = (victim->blood - URANGE(3, victim->level / 10, 8));
        victim->hit += URANGE(4, (victim->max_hit / 30), 15);
      }
      set_char_color(AT_BLOOD, victim);
      send_to_char("You howl with rage as the beast within stirs!\r\n", victim);
    }
  }

  if(IS_BLOODCLASS(victim) && victim->level > 49)
  {
    if(dam >= (victim->hit / 4))
      victim->blood = (victim->blood - 1 - (victim->level / 20));

    if(victim->hit <= (victim->max_hit / 4) && victim->blood > 5)
    {
      if(victim->blood >= victim->blood / 2)
      {
        victim->hit += URANGE(12, (victim->max_hit / 30), victim->level * 2);
        victim->blood = (victim->blood - URANGE(6, victim->level / 10, 12));
      }
      else
      {
        victim->blood = (victim->blood - URANGE(3, victim->level / 10, 8));
        victim->hit += URANGE(4, (victim->max_hit / 30), victim->level * 2);
      }
      set_char_color(AT_BLOOD, victim);
      send_to_char("You howl with rage as the beast within stirs!\r\n", victim);
    }

  }

  if(!npcvict && get_trust(victim) >= LEVEL_IMMORTAL && get_trust(ch) >= LEVEL_IMMORTAL && victim->hit < 1)
    victim->hit = 1;
  if(!IS_NPC(victim) && NEW_AUTH(victim) && victim->hit < 1)
    victim->hit = 1;

  update_pos(victim);

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

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

    case POS_STUNNED:
      if(!IS_AFFECTED(victim, AFF_PARALYSIS))
      {
        act(AT_ACTION, "$n is stunned, but will probably recover.", victim, NULL, NULL, TO_ROOM);
        act(AT_RED, "You are stunned, but will probably recover.", victim, NULL, NULL, TO_CHAR);
      }
      break;

    case POS_DEAD:
      if(dt >= 0 && dt < top_sn)
      {
        SKILLTYPE              *skill = skill_table[dt];

        if(skill->die_char && skill->die_char[0] != '\0')
          act(AT_RED, skill->die_char, ch, NULL, victim, TO_CHAR);
        if(skill->die_vict && skill->die_vict[0] != '\0')
          act(AT_RED, skill->die_vict, ch, NULL, victim, TO_VICT);
        if(skill->die_room && skill->die_room[0] != '\0')
          act(AT_RED, skill->die_room, ch, NULL, victim, TO_NOTVICT);
      }
      act(AT_RED, "$n is DEAD!!", victim, 0, 0, TO_ROOM);
      act(AT_RED, "You have been KILLED!!\r\n", victim, 0, 0, TO_CHAR);
      break;

    default:
      /*
       * Victim mentalstate affected, not attacker -- oops ;)
       * Thanks to gfinello@mail.karmanet.it for finding this bug
       */
      if(dam > victim->max_hit / 4)
      {
        act(AT_RED, "That really did HURT!", victim, 0, 0, TO_CHAR);
        if(number_bits(3) == 0)
          worsen_mental_state(victim, 1);
      }
      if(victim->hit < victim->max_hit / 6)
      {
        act(AT_RED, "You wish that your wounds would stop BLEEDING so much!", victim, 0, 0, TO_CHAR);
        if(number_bits(2) == 0)
          worsen_mental_state(victim, 1);
      }
      break;
  }

  /*
   * Sleep spells and extremely wounded folks.
   */
  if(!IS_AWAKE(victim) && !IS_AFFECTED(victim, AFF_PARALYSIS))
  {
    stop_summoning(victim);

    if(!npcvict && IS_NPC(ch))
      stop_fighting(victim, TRUE);
    else
      stop_fighting(victim, FALSE);
  }

  /*
   * Payoff for killing things.
   */
  if(victim->position == POS_DEAD)
  {
    /*
     * Let's put arena code at the top. We DON'T want to hit group_gain. 
     */
    if(!IS_NPC(ch) && !IS_NPC(victim) && in_arena(victim))
    {
      if(victim != ch)
        snprintf(buf, MSL, "%s has been slain by %s!", victim->name, ch->name);
      else
        snprintf(buf, MSL, "%s has been slain!", victim->name);

      if(victim->position == POS_DEAD)
      {
        set_position(victim, POS_STANDING);
      }

      CLAN_DATA              *clan;

      clan = ch->pcdata->clan;

      if(victim != ch && IS_CLANNED(ch) && IS_CLANNED(victim) && victim->pcdata->clan == clan)
      {
        if(!clan->warmaster || !str_cmp(clan->warmaster, victim->name))
        {
          if(!clan->chieftain || str_cmp(clan->chieftain, ch->name))
          {
            if(clan->warmaster)
              STRFREE(clan->warmaster);
            clan->warmaster = STRALLOC(ch->name);
            save_clan(clan);
          }
        }
      }

      // Clan members gain points for the clan with kills.
      if(!IS_NPC(ch) && victim != ch && !IS_NPC(victim))
      {
        if(ch->pcdata->clan)
        {
          clan = ch->pcdata->clan;
          ch->pcdata->clanpoints += 3;
          clan->totalpoints += 3;
          ch_printf(ch, "&G%s clan has gained 3 points from your kill, now totaling %d clan status points!\r\n", clan->name, clan->totalpoints);
          if(countpkill(ch, victim))
            increase_clan_pkills(ch->pcdata->clan, ch->level);
          save_clan(clan);
        }
        if(victim->pcdata->clan && countpkill(ch, victim))
        {
          increase_clan_pdeaths(victim->pcdata->clan, victim->level);
          save_clan(victim->pcdata->clan);
        }
        ch->pcdata->pkills++;
        victim->pcdata->pdeaths++;
        add_pkill(ch, victim);
        save_char_obj(ch);
      }

      arena_population--;
      victim->arena_loss++;
      arena_chan(buf);

      /*
       * Volk: Let's send them on their way, restored 
       */
      restore_char(victim);
      char_from_room(victim);
      char_to_room(victim, get_room_index(victim->pcdata->htown->recall));
      affect_strip(victim, gsn_maim);
      affect_strip(victim, gsn_brittle_bone);
      affect_strip(victim, gsn_festering_wound);
      affect_strip(victim, gsn_poison);
      affect_strip(victim, gsn_toxin);
      affect_strip(victim, gsn_corrosive);
      xREMOVE_BIT(victim->affected_by, AFF_BRITTLE_BONES);
      xREMOVE_BIT(victim->affected_by, AFF_FUNGAL_TOXIN);
      xREMOVE_BIT(victim->affected_by, AFF_TOXIN);
      xREMOVE_BIT(victim->affected_by, AFF_MAIM);
      xREMOVE_BIT(victim->affected_by, AFF_CORROSIVE);
      /*
       * So players don't drown if returning underwater from the water arena, heh 
       */
      if(victim->pcdata && !IS_NPC(victim))
        victim->pcdata->holdbreath = 0;

      if(arena_population == 1 && arena_underway && victim != ch)
      {
        find_arena_winner(ch);
        char_from_room(ch);
        char_to_room(ch, get_room_index(ch->pcdata->htown->recall));

        if(ch->pcdata)
          ch->pcdata->holdbreath = 0;
      }

      return rNONE;
    }

    group_gain(ch, victim);

    /*
     * Always loose 8% exp for each class on death 
     */
    if(!npcvict)
    {
      if(IS_THIRDCLASS(victim))
      {
        if(xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->firstexp -= (int)(exp_class_level(victim, victim->firstlevel + 1, victim->Class) * .8);
        }
        else if(!xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->firstexp -= (int)(exp_class_level(victim, victim->firstlevel + 1, victim->Class) * .5);
        }

        if(victim->firstexp < 0)
          victim->firstexp = 0;
        if(xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->secondexp -= (int)(exp_class_level(victim, victim->secondlevel + 1, victim->secondclass) * .8);
        }
        else if(!xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->secondexp -= (int)(exp_class_level(victim, victim->secondlevel + 1, victim->secondclass) * .5);
        }

        if(victim->secondexp < 0)
          victim->secondexp = 0;

        if(xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->thirdexp -= (int)(exp_class_level(victim, victim->thirdlevel + 1, victim->thirdclass) * .8);
        }
        else if(!xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->thirdexp -= (int)(exp_class_level(victim, victim->thirdlevel + 1, victim->thirdclass) * .5);
        }

        if(victim->thirdexp < 0)
          victim->thirdexp = 0;
      }
      else if(IS_SECONDCLASS(victim))
      {
        if(xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->firstexp -= (int)(exp_class_level(victim, victim->firstlevel + 1, victim->Class) * .8);
        }
        else if(!xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->firstexp -= (int)(exp_class_level(victim, victim->firstlevel + 1, victim->Class) * .5);
        }

        if(victim->firstexp < 0)
          victim->firstexp = 0;
        if(xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->secondexp -= (int)(exp_class_level(victim, victim->secondlevel + 1, victim->secondclass) * .8);
        }
        else if(!xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->secondexp -= (int)(exp_class_level(victim, victim->secondlevel + 1, victim->secondclass) * .5);
        }

        if(victim->secondexp < 0)
          victim->secondexp = 0;
      }
      else
      {
        if(xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->exp -= (int)(exp_level(victim, victim->level + 1) * .8);;
        }
        else if(!xIS_SET(victim->act, PLR_EXTREME))
        {
          victim->exp -= (int)(exp_level(victim, victim->level + 1) * .5);
        }
        if(victim->exp < 0)
          victim->exp = 0;
      }
    }
    else if(!IS_NPC(ch) && IS_NPC(victim))
    { /* keep track of mob vnum killed */
      if(!happyhouron || !IS_GROUPED(ch) || sysdata.happy)
      {
        add_kill(ch, victim);
        /*
         * Add to kill tracker for grouped chars, as well. -Halcyon 
         */
        for(gch = ch->in_room->first_person; gch; gch = gch->next_in_room)
          if(is_same_group(gch, ch) && !IS_NPC(gch) && gch != ch)
            add_kill(gch, victim);
      }
    }
    check_killer(ch, victim);

    if(ch->in_room == victim->in_room)
      loot = legal_loot(ch, victim);
    else
      loot = FALSE;

    set_cur_char(victim);
    raw_kill(ch, victim);

    if(victim == ch)
      return rNONE;

    if(!IS_NPC(ch) && loot)
    {
      /*
       * Automoney by Scryn 8/12 . Editted by Volk to pay clan tithes!
       */
      if(xIS_SET(ch->act, PLR_AUTOMONEY))
      {
        int                     init, diff;
        OBJ_DATA               *corpse;
        bool                    members = FALSE;

        if((corpse = get_obj_here(ch, (char *)"corpse")))
        {
          OBJ_DATA               *mobj;
          char                    mbuf[80];

          for(mobj = corpse->first_content; mobj; mobj = mobj->next_content)
          {
            if(mobj->item_type != ITEM_MONEY)
              continue;
            init = GET_MONEY(ch, mobj->value[2]);
            snprintf(mbuf, 80, "%s corpse", curr_types[mobj->value[2]]);
            do_get(ch, mbuf); /* Get the gold/silver from the corpse */
            diff = GET_MONEY(ch, mobj->value[2]) - init;
            if(diff > 1)
            {
              for(gch = ch->in_room->first_person; gch; gch = gch->next_in_room)
              {
                if(is_same_group(gch, ch) && gch != ch && !IS_NPC(gch))
                {
                  members = TRUE;
                  snprintf(buf1, MSL, "%d %s", diff, curr_types[mobj->value[2]]);
                  do_split(ch, buf1);
                }
              }
              /*
               * if (!members) clan_tithe(ch, diff, mobj->value[2]); 
               */
            }
          }
        }
      }
      if(xIS_SET(ch->act, PLR_AUTOLOOT) && victim != ch)
        do_get(ch, (char *)"all corpse");
      else
        do_look(ch, (char *)"in corpse");

      if(xIS_SET(ch->act, PLR_AUTOTRASH))
        do_trash(ch, (char *)"corpse");
    }

    if(xIS_SET(sysdata.save_flags, SV_KILL))
      save_char_obj(ch);
    return rVICT_DIED;
  }

  /*
   * Take care of link dead people.
   */
  if(!npcvict && !victim->desc && !IS_SET(victim->pcdata->flags, PCFLAG_NORECALL))
  {
    if(number_range(0, victim->wait) == 0)
    {
      do_recall(victim, (char *)"");
      return rNONE;
    }
  }

  /*
   * Wimp out?
   */
  if(npcvict && dam > 0)
  {
    if((xIS_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))
    {
    }
  }

  if(!npcvict && victim->hit > 0 && victim->hit <= victim->wimpy && victim->wait == 0)
    do_flee(victim, (char *)"");
  else if(!npcvict && xIS_SET(victim->act, PLR_FLEE))
    do_flee(victim, (char *)"");


  /*
   * Now I fiqure this is the best place to switch victims :) 
   * Should we do same group only or just anyone fighting it? 
   */
  if(ch->fighting && victim != ch)
    for(gch = victim->in_room->first_person; gch; gch = gch->next_in_room)
      if(is_same_group(victim, gch) && (victim != gch) && gch->hate_level > victim->hate_level)
      {
        stop_fighting(ch, FALSE); /* Stop the current fighting for ch only */
        set_fighting(ch, gch);  /* Start them on the next one? */
        snprintf(buf, MSL, "\r\n&O Yell [%s] %s you will die for that!", ch->name, gch->name);
        do_recho(ch, buf);
      }

  tail_chain();
  return retcode;
}

/*
 * Changed is_safe to have the show_messg boolian.  This is so if you don't
 * want to show why you can't kill someone you can turn it off.  This is
 * useful for things like area attacks.  --Shaddai
 */
/* Volk - needs restrictions for peacefuls/nice flag/etc */
bool is_safe(CHAR_DATA *ch, CHAR_DATA *victim, bool show_messg)
{
  if(char_died(victim) || char_died(ch))
    return TRUE;

  /*
   * Thx Josh! 
   */
  if(who_fighting(ch) == ch)
    return FALSE;

  if(!victim)
  { /* Gonna find this is_safe crash bug -Blod */
    bug("%s: %s opponent does not exist!", __FUNCTION__, ch->name);
    return TRUE;
  }
  if(!victim->in_room)
  {
    bug("%s: %s has no physical location!", __FUNCTION__, victim->name);
    return TRUE;
  }

  if(IS_SET(victim->in_room->room_flags, ROOM_SAFE))
  {
    if(show_messg)
    {
      set_char_color(AT_MAGIC, ch);
      send_to_char("A magical force prevents you from attacking.\r\n", ch);
    }
    return TRUE;
  }

  if((IS_PACIFIST(ch)) && !IN_ARENA(ch))
  { /* Fireblade */
    if(show_messg)
    {
      set_char_color(AT_MAGIC, ch);
      ch_printf(ch, "You are a pacifist and will not fight.\r\n");
    }
    return TRUE;
  }

  if(IS_PACIFIST(victim) && !IS_AFFECTED(victim, AFF_DISABLED))
  { /* Gorog */
    if(show_messg)
    {
      set_char_color(AT_MAGIC, ch);
      ch_printf(ch, "%s is a pacifist and will not fight.\r\n", capitalize(victim->short_descr));
    }
    return TRUE;
  }

  if(IS_AFFECTED(ch, AFF_IMPRISONED))
    return TRUE;

  if(in_arena(ch))
    return FALSE;

  if(!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
    return FALSE;

  if(!IS_NPC(ch) && !IS_NPC(victim) && ch != victim && (IS_SET(victim->in_room->area->flags, AFLAG_ANTIPKILL) || IS_SET(victim->in_room->area->flags, AFLAG_NOPKILL)))
  {
    if(show_messg)
    {
      set_char_color(AT_IMMORT, ch);
      send_to_char("The staff have forbidden player killing in this area.\r\n", ch);
    }
    return TRUE;
  }

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

  if(IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM) && (ch->level - victim->level > 10) && !in_arena(ch))
    return FALSE;

  if((ch->level < 5) && !in_arena(ch))
  {
    if(show_messg)
    {
      set_char_color(AT_WHITE, ch);
      send_to_char("You are not yet ready, needing age or experience, if not both. \r\n", ch);
    }
    return TRUE;
  }

  if((victim->level < 5) && !in_arena(victim))
  {
    if(show_messg)
    {
      set_char_color(AT_WHITE, ch);
      send_to_char("They are yet too young to die.\r\n", ch);
    }
    return TRUE;
  }

  if(ch->level <= 10 && !in_arena(ch))
  { /* 10 and lower */
    if((ch->level - victim->level >= 3) || (victim->level - ch->level >= 3))
    {
      if(show_messg)
      {
        set_char_color(AT_IMMORT, ch);
        send_to_char("The STAFF of 6 Dragons do not allow murder when there is such a difference in level.\r\n", ch);
      }
      return TRUE;
    }
  }

  if(ch->level > 29 && !in_arena(ch))
  { /* 30 and upwards */
    if((ch->level - victim->level > 10) || (victim->level - ch->level > 10))
    {
      if(show_messg)
      {
        set_char_color(AT_IMMORT, ch);
        send_to_char("The STAFF of 6 Dragons do not allow murder when there is such a difference in level.\r\n", ch);
      }
      return TRUE;
    }
  }
  else if(ch->level < 30 && !in_arena(ch))
  { /* less than 30 */
    if((ch->level - victim->level > 5) || (victim->level - ch->level > 5))
    {
      if(show_messg)
      {
        set_char_color(AT_IMMORT, ch);
        send_to_char("The STAFF of 6 Dragons do not allow murder when there is such a difference in level.\r\n", ch);
      }
      return TRUE;
    }
  }

  if((get_timer(victim, TIMER_PKILLED) > 0) && !in_arena(victim))
  {
    if(show_messg)
    {
      set_char_color(AT_GREEN, ch);
      send_to_char("That character has died within the last 1 minute.\r\n", ch);
    }
    return TRUE;
  }

  /*
   * You have killed them 
   */
  if(!in_arena(ch) && has_pkilled(ch, victim->name))
  {
    if(show_messg)
    {
      set_char_color(AT_RED, ch);
      send_to_char("You have pkilled that character within the past 30 minutes.\r\n", ch);
    }
    return TRUE;
  }

  /*
   * Should always check both sides 
   */
  if(!in_arena(victim) && has_pkilled(victim, ch->name))
  {
    if(show_messg)
    {
      set_char_color(AT_RED, ch);
      send_to_char("They have pkilled you within the past 30 minutes.\r\n", victim);
    }
    return TRUE;
  }

  if((get_timer(ch, TIMER_PKILLED) > 0) && !in_arena(ch))
  {
    if(show_messg)
    {
      set_char_color(AT_GREEN, ch);
      send_to_char("You have been killed within the last 1 minute.\r\n", ch);
    }
    return TRUE;
  }

  return FALSE;
}

/*
 * just verify that a corpse looting is legal
 */
bool legal_loot(CHAR_DATA *ch, CHAR_DATA *victim)
{
  /*
   * anyone can loot mobs 
   */
  if(IS_NPC(victim))
    return TRUE;
  /*
   * non-charmed mobs can loot anything 
   */
  if(IS_NPC(ch) && !ch->master)
    return TRUE;
  /*
   * members of different clans can loot too! -Thoric 
   */
  if(!IS_NPC(ch) && !IS_NPC(victim) && IS_SET(ch->pcdata->flags, PCFLAG_DEADLY) && IS_SET(victim->pcdata->flags, PCFLAG_DEADLY))
    return TRUE;
  return FALSE;
}

/*
 * See if an attack justifies a KILLER flag.
 */
void check_killer(CHAR_DATA *ch, CHAR_DATA *victim)
{
  int                     level_ratio;

  /*
   * NPC's are fair game. 
   */
  if(IS_NPC(victim))
    return;

  level_ratio = URANGE(1, ch->level / victim->level, 50);
  if(!IS_NPC(ch))
  {

    ch->pcdata->mkills++;
    if(ch->pcdata->clan)
      ch->pcdata->clan->mkills++;
    // update_member(ch);
    ch->in_room->area->mkills++;
  }

  /*
   * If you kill yourself nothing happens.
   */

  if(ch == victim || ch->level >= LEVEL_IMMORTAL)
    return;

  /*
   * Any character in the arena is ok to kill.
   * Added pdeath and pkills here
   */
  if(in_arena(ch) || in_arena(victim))
    return;

  if(xIS_SET(victim->act, PLR_KILLER) || xIS_SET(victim->act, PLR_THIEF))
    return;

  /*
   * clan checks     -Thoric 
   */
  if(!IS_NPC(ch) && !IS_NPC(victim) && IS_SET(ch->pcdata->flags, PCFLAG_DEADLY) && IS_SET(victim->pcdata->flags, PCFLAG_DEADLY))
  {
    /*
     * not of same clan? Go ahead and kill!!! 
     */
    if(!ch->pcdata->clan || !victim->pcdata->clan || ch->pcdata->clan != victim->pcdata->clan)
    {
      // update_member(ch);
      ch->hit = ch->max_hit;
      ch->mana = ch->max_mana;
      ch->move = ch->max_move;
      if(IS_BLOODCLASS(ch))
      {
        ch->blood = ch->max_blood;
      }
      update_pos(victim);
      if(victim != ch)
      {
        act(AT_MAGIC, "Bolts of blue energy rise from the corpse, seeping into $n.", ch, victim->name, NULL, TO_ROOM);
        act(AT_MAGIC, "Bolts of blue energy rise from the corpse, seeping into you.", ch, victim->name, NULL, TO_CHAR);
      }

      add_timer(victim, TIMER_PKILLED, 23, NULL, 0);
      WAIT_STATE(victim, 3 * PULSE_VIOLENCE);
      /*
       * xSET_BIT(victim->act, PLR_PK); 
       */
      return;
    }
  }

  /*
   * Charm-o-rama.
   */
  if(IS_AFFECTED(ch, AFF_CHARM))
  {
    if(!ch->master)
    {
      bug("Check_killer: %s bad AFF_CHARM", IS_NPC(ch) ? ch->short_descr : ch->name);
      xREMOVE_BIT(ch->affected_by, AFF_CHARM);
      return;
    }

    /*
     * stop_follower(ch); 
     */
    if(ch->master)
      check_killer(ch->master, victim);
    return;
  }

  /*
   * NPC's are cool of course (as long as not charmed).
   * Hitting yourself is cool too (bleeding).
   * So is being immortal (Alander's idea).
   * And current killers stay as they are.
   */
  if(IS_NPC(ch))
  {
    if(!IS_NPC(victim))
    {
      int                     level_ratio;

      victim->pcdata->mdeaths++;
      if(victim->pcdata->clan)
        victim->pcdata->clan->mdeaths++;
      // update_member(ch);

    }
    return;
  }

  if(!IS_NPC(ch))
  {
    if(ch->pcdata->clan)
      ch->pcdata->clan->illegal_pk++;
    ch->pcdata->illegal_pk++;
    ch->in_room->area->illegal_pk++;
  }

  if(!IS_NPC(victim))
  {
    victim->in_room->area->pdeaths++;
  }

  set_char_color(AT_WHITE, ch);
  send_to_char("A strange feeling grows deep inside you, and a tingle goes up your spine...\r\n", ch);
  set_char_color(AT_IMMORT, ch);
  send_to_char("A deep voice booms inside your head, 'Thou shall now be known as a deadly murderer!!!'\r\n", ch);
  set_char_color(AT_WHITE, ch);
  send_to_char("You feel as if your soul has been revealed for all to see.\r\n", ch);
  save_char_obj(ch);
  return;
}

/*
 * See if an attack justifies a ATTACKER flag.
 */
void check_attacker(CHAR_DATA *ch, CHAR_DATA *victim)
{

/* 
 * Made some changes to this function Apr 6/96 to reduce the prolifiration
 * of attacker flags in the realms. -Narn
 */
  /*
   * NPC's are fair game.
   * So are killers and thieves.
   */
  if(IS_NPC(victim) || xIS_SET(victim->act, PLR_KILLER) || xIS_SET(victim->act, PLR_THIEF))
    return;

  if(IN_ARENA(ch) || IN_ARENA(victim) || in_arena(ch) || in_arena(victim))
    return;

/* Pkiller versus pkiller will no longer ever make an attacker flag
    { if(!(ch->pcdata->clan && victim->pcdata->clan
      && ch->pcdata->clan == victim->pcdata->clan))  return; }
*/

  /*
   * Charm-o-rama.
   */
  if(IS_AFFECTED(ch, AFF_CHARM))
  {
    if(!ch->master)
    {
      // bug( "Check_attacker: %s bad AFF_CHARM", IS_NPC( ch ) ? ch->short_descr :
      // ch->name );
      xREMOVE_BIT(ch->affected_by, AFF_CHARM);
      return;
    }

    /*
     * Won't have charmed mobs fighting give the master an attacker 
     * flag.  The killer flag stays in, and I'll put something in 
     * do_murder. -Narn 
     */
    /*
     * xSET_BIT(ch->master->act, PLR_ATTACKER);
     */
    /*
     * stop_follower(ch); 
     */
    return;
  }

  /*
   * NPC's are cool of course (as long as not charmed).
   * Hitting yourself is cool too (bleeding).
   * So is being immortal (Alander's idea).
   * And current killers stay as they are.
   */
  if(IS_NPC(ch) || ch == victim || ch->level >= LEVEL_IMMORTAL || xIS_SET(ch->act, PLR_ATTACKER) || xIS_SET(ch->act, PLR_KILLER) || IN_ARENA(ch))
    return;

  // xSET_BIT( ch->act, PLR_ATTACKER );
  save_char_obj(ch);
  return;
}

/* Set position of a victim. */
void update_pos(CHAR_DATA *victim)
{
  if(!victim)
  {
    bug("%s: null victim", __FUNCTION__);
    return;
  }

  if(victim->hit > 0)
  {
    if(victim->position == POS_STUNNED)
      set_position(victim, POS_STANDING);
    if(IS_AFFECTED(victim, AFF_PARALYSIS))
      set_position(victim, POS_STUNNED);
    return;
  }

  if(IS_NPC(victim) || victim->hit <= -11)
  {
    if(victim->mount)
    {
      act(AT_ACTION, "$n falls from $N.", victim, NULL, victim->mount, TO_ROOM);
      xREMOVE_BIT(victim->mount->act, ACT_MOUNTED);
      victim->mount = NULL;
      xREMOVE_BIT(victim->affected_by, AFF_MOUNTED);
    }
    set_position(victim, POS_DEAD);
    return;
  }

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

  if(victim->position > POS_STUNNED && IS_AFFECTED(victim, AFF_PARALYSIS))
    set_position(victim, POS_STUNNED);

  if(victim->mount)
  {
    act(AT_ACTION, "$n falls unconscious from $N.", victim, NULL, victim->mount, TO_ROOM);
    xREMOVE_BIT(victim->mount->act, ACT_MOUNTED);
    victim->mount = NULL;
  }
}

void set_distance(CHAR_DATA *ch, int distance)
{
  if(ch->fighting == NULL)
    return;

  ch->fighting->distance = distance;
  if(ch->fighting->who && ch->fighting->who->fighting && ch->fighting->who->fighting->who == ch)
  {
    ch->fighting->who->fighting->distance = distance;
  }
}

void do_rush(CHAR_DATA *ch, char *argument)
{
  int                     distance;

  if(ch->fighting == NULL || ch->fighting->who == NULL)
  {
    send_to_char("You aren't fighting anyone.\r\n", ch);
    return;
  }
  if(ch->fighting->distance == MIN_DISTANCE)
    send_to_char("You can't get any closer!\r\n", ch);
  else
  {
    distance = ch->fighting->distance - number_chance(1, 4);
//    ch->fighting->who->fighting->distance = ch->fighting->distance;
    if(distance < MIN_DISTANCE)
      distance = MIN_DISTANCE;
    set_distance(ch, distance);

    act(AT_GREEN, "Yelling a battle cry you rush in towards $N.", ch, NULL, ch->fighting->who, TO_CHAR);
    act(AT_GREEN, "$n yelling a battle cry rushes in towards you.", ch, NULL, ch->fighting->who, TO_VICT);
    act(AT_GREEN, "$n yelling a battle cry rushes in towards $N.", ch, NULL, ch->fighting->who, TO_NOTVICT);
    WAIT_STATE(ch, 12);
  }
}

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

  if(ch->fighting)
  {
    bug("%s: %s -> %s (already fighting %s)", __FUNCTION__, ch->name, victim->name, ch->fighting->who->name);
    return;
  }

  if(IS_AFFECTED(ch, AFF_SLEEP))
    affect_strip(ch, gsn_sleep);

  /*
   * Limit attackers -Thoric 
   */
  if(victim->num_fighting > max_fight(victim))
  {
    send_to_char("There are too many people fighting for you to join in.\r\n", ch);
    return;
  }

  if(IS_AFFECTED(ch, AFF_IMPRISONED))
    return;

// stop arena fleeing from saying multiple characers

  if(!in_arena(ch) && !IS_NPC(victim))
  {
    if(victim->fightingip != NULL && !IS_NPC(ch))
    {
      if(ch->pcdata->lastip)
      {
        if(!str_cmp(victim->fightingip, ch->pcdata->lastip))
        {
          send_to_char("You are already fighting them with one of your characters.\r\n", ch);
          return;
        }
      }
    }
  }
  CREATE(fight, FIGHT_DATA, 1);
  fight->who = victim;

  if(in_arena(ch))
    fight->xp = 0;
  else
    fight->xp = (int)xp_compute(ch, victim) * 2;
  fight->align = align_compute(ch, victim);
  if(!IS_NPC(ch) && IS_NPC(victim))
    fight->timeskilled = times_killed(ch, victim);
  ch->num_fighting = 1;
  ch->fighting = fight;
  set_distance(ch, STARTING_DISTANCE);
  /*
   * ch->position = POS_FIGHTING; 
   */

  if(!IS_NPC(ch) && !IS_NPC(victim))
  {
    if(ch->pcdata->lastip)
    {
      if(victim->fightingip)
      {
        STRFREE(victim->fightingip);
      }
      victim->fightingip = STRALLOC(ch->pcdata->lastip);
    }
  }

  if(IS_NPC(ch))
    set_position(ch, POS_FIGHTING);
  else
    switch (ch->style)
    {
      case (STYLE_EVASIVE):
        set_position(ch, POS_EVASIVE);
        break;
      case (STYLE_DEFENSIVE):
        set_position(ch, POS_DEFENSIVE);
        break;
      case (STYLE_AGGRESSIVE):
        set_position(ch, POS_AGGRESSIVE);
        break;
      case (STYLE_BERSERK):
        set_position(ch, POS_BERSERK);
        break;
      default:
        set_position(ch, POS_FIGHTING);
    }
  victim->num_fighting++;
  if(victim->switched && IS_AFFECTED(victim->switched, AFF_POSSESS))
  {
    send_to_char("You are disturbed!\r\n", victim->switched);
    do_return(victim->switched, (char *)"");
  }
  return;
}

CHAR_DATA              *who_fighting(CHAR_DATA *ch)
{
  if(!ch)
  {
    bug("%s who_fighting: null ch", __FUNCTION__);
    return NULL;
  }
  if(!ch->fighting)
    return NULL;
  return ch->fighting->who;
}

void free_fight(CHAR_DATA *ch)
{
  if(!ch)
  {
    bug("%s: null ch!", __FUNCTION__);
    return;
  }
  if(ch->fighting)
  {
    if(!char_died(ch->fighting->who))
      --ch->fighting->who->num_fighting;
    DISPOSE(ch->fighting);
  }
  ch->fighting = NULL;
  if(ch->mount)
    set_position(ch, POS_MOUNTED);
  else
    set_position(ch, POS_STANDING);

  // Tangle wears off after combat. -Taon
  if(IS_AFFECTED(ch, AFF_TANGLED))
  {
    affect_strip(ch, gsn_entangle);
    set_char_color(AT_WEAROFF, ch);
    send_to_char(skill_table[gsn_entangle]->msg_off, ch);
    send_to_char("\r\n", ch);
  }

  /*
   * Berserk wears off after combat. -- Altrag 
   */
  if(IS_AFFECTED(ch, AFF_BERSERK))
  {
    affect_strip(ch, gsn_berserk);
    set_char_color(AT_WEAROFF, ch);
    send_to_char(skill_table[gsn_berserk]->msg_off, ch);
    send_to_char("\r\n", ch);
  }
  return;
}

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

  free_fight(ch);
  update_pos(ch);

  // Strip Berserk, fighting has stopped. -Taon
  if(IS_AFFECTED(ch, AFF_BERSERK))
  {
    affect_strip(ch, gsn_berserk);
    xREMOVE_BIT(ch->affected_by, AFF_BERSERK);
  }
  if(!fBoth)  /* major short cut here by Thoric */
    return;

  for(fch = first_char; fch; fch = fch->next)
  {
    if(who_fighting(fch) == ch)
    {
      free_fight(fch);
// make sure feign death and gust of wind work properly - Vladaar
      if(fch->fightingip != NULL)
      {
        STRFREE(fch->fightingip);
      }

      update_pos(fch);
    }
  }
  return;
}

/* Vnums for the various bodyparts */
int                     part_vnums[] = { 12,  /* Head */
  14, /* arms */
  15, /* legs */
  13, /* heart */
  44, /* brains */
  16, /* guts */
  45, /* hands */
  46, /* feet */
  47, /* fingers */
  48, /* ear */
  49, /* eye */
  50, /* long_tongue */
  51, /* eyestalks */
  52, /* tentacles */
  53, /* fins */
  54, /* wings */
  55, /* tail */
  56, /* scales */
  59, /* claws */
  87, /* fangs */
  58, /* horns */
  57, /* tusks */
  55, /* tailattack */
  85, /* sharpscales */
  84, /* beak */
  86, /* haunches */
  83, /* hooves */
  82, /* paws */
  81, /* forelegs */
  80, /* feathers */
  0,  /* r1 */
  0 /* r2 */
};

/* Messages for flinging off the various bodyparts */
const char             *part_messages[] = {
  "$n's severed head plops from its neck.",
  "$n's arm is sliced from $s dead body.",
  "$n's leg is sliced from $s dead body.",
  "$n's heart is torn from $s chest.",
  "$n's brains spill grotesquely from $s head.",
  "$n's guts spill grotesquely from $s torso.",
  "$n's hand is sliced from $s dead body.",
  "$n's foot is sliced from $s dead body.",
  "A finger is sliced from $n's dead body.",
  "$n's ear is sliced from $s dead body.",
  "$n's eye is gouged from its socket.",
  "$n's tongue is torn from $s mouth.",
  "An eyestalk is sliced from $n's dead body.",
  "A tentacle is severed from $n's dead body.",
  "A fin is sliced from $n's dead body.",
  "A wing is severed from $n's dead body.",
  "$n's tail is sliced from $s dead body.",
  "A scale falls from the body of $n.",
  "A claw is torn from $n's dead body.",
  "$n's fangs are torn from $s mouth.",
  "A horn is wrenched from the body of $n.",
  "$n's tusk is torn from $s dead body.",
  "$n's tail is sliced from $s dead body.",
  "A ridged scale falls from the body of $n.",
  "$n's beak is sliced from $s dead body.",
  "$n's haunches are sliced from $s dead body.",
  "A hoof is sliced from $n's dead body.",
  "A paw is sliced from $n's dead body.",
  "$n's foreleg is sliced from $s dead body.",
  "Some feathers fall from $n's dead body.",
  "r1 message.",
  "r2 message."
};

/*
 * Improved Death_cry contributed by Diavolo.
 * Additional improvement by Thoric (and removal of turds... sheesh!)  
 * Support for additional bodyparts by Fireblade
 */
void death_cry(CHAR_DATA *ch)
{
  ROOM_INDEX_DATA        *was_in_room;
  const char             *msg;
  EXIT_DATA              *pexit;
  int                     vnum, index, i;

  if(!ch)
  {
    bug("%s DEATH_CRY: null ch!", __FUNCTION__);
    return;
  }

  vnum = 0;
  msg = NULL;

  switch (number_chance(0, 5))
  {
    default:
      msg = "You hear $n's death cry.";
      break;
    case 0:
      msg = "$n screams furiously as $e falls to the ground in a heap!";
      break;
    case 1:
      msg = "$n hits the ground ... DEAD.";
      break;
    case 2:
      msg = "$n catches $s guts in $s hands as they pour through $s fatal" " wound!";
      break;
    case 3:
      msg = "$n splatters blood on your armor.";
      break;
    case 4:
      msg = "$n gasps $s last breath and blood spurts out of $s " "mouth and ears.";
      break;

    case 5:
      /*
       * Why waste time if it isn't needed? -Orion
       */
      if(xIS_EMPTY(ch->xflags))
      {
        msg = "You hear $n's death cry.";
        break;
      }

      index = number_range(0, MAX_PARTS - 1);

      for(i = 0; i < MAX_PARTS; i++)
      {
        if(HAS_BODYPART(ch, index))
        {
          msg = part_messages[index];
          vnum = part_vnums[index];
          break;
        }
        else
        {
          index = number_range(0, MAX_PARTS - 1);
        }
      }

      if(!msg)
        msg = "You hear $n's death cry.";
      break;
  }

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

  if(vnum)
  {
    char                    buf[MSL];
    OBJ_DATA               *obj;
    char                   *name;

    if(!get_obj_index(vnum))
    {
      bug("%s: invalid vnum", __FUNCTION__);
      return;
    }

    name = IS_NPC(ch) ? ch->short_descr : ch->name;
    obj = create_object(get_obj_index(vnum), 0);
    obj->timer = number_chance(4, 7);
    if(IS_AFFECTED(ch, AFF_POISON))
      obj->value[3] = 10;

    snprintf(buf, MSL, obj->short_descr, name);
    STRFREE(obj->short_descr);
    obj->short_descr = STRALLOC(buf);

    snprintf(buf, MSL, obj->description, name);
    STRFREE(obj->description);
    obj->description = STRALLOC(buf);

    obj = 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(pexit = was_in_room->first_exit; pexit; pexit = pexit->next)
  {
    if(pexit->to_room && pexit->to_room != was_in_room)
    {
      ch->in_room = pexit->to_room;
      act(AT_CARNAGE, msg, ch, NULL, NULL, TO_ROOM);
    }
  }
  ch->in_room = was_in_room;

  return;
}

void raw_kill(CHAR_DATA *ch, CHAR_DATA *victim)
{
  char                    buf[MSL];
  char                    arg[MSL];
  char                    buf2[MSL];

  if(!victim)
  {
    bug("%s: null victim!", __FUNCTION__);
    return;
  }

  /*
   * backup in case hp goes below 1 
   */
  if(!IS_NPC(victim) && victim->level < 2)
  {
    bug("%s: killing someone still in tutorial.", __FUNCTION__);
    return;
  }

  if(!IS_NPC(ch))
  {
    ch->pcdata->failsafe = 0;
    if(victim->level > ch->level)
      ch->pcdata->failsafe = victim->level - ch->level;
  }

// This check will be for Pet fighting alongside beast master killed mob 
  if(xIS_SET(ch->act, ACT_BEASTPET) && !xIS_SET(ch->act, ACT_BEASTMELD))
  {
    CHAR_DATA              *master = NULL;

    if(ch->master)
      master = ch->master;

    if(master)
    {
      if(ch->level - master->level > 15)
      {
        send_to_char("Your pet cannot gain any more experience until you level the beastmaster.\r\n", master);
      }
      else
      {
        if(master->pcdata->petlevel < 100)
        {
          master->pcdata->petexp += 1;
          gain_exp(master, number_range(5000, 8000));
          ch_printf(master, "&WYour pet gains experience from this battle!\r\n");
        }

        if(master->pcdata->petexp > 17)
        {
          master->pcdata->petexp = 0;
          if(master->pcdata->petlevel < 100)
          {
            master->pcdata->petlevel += 1;
            ch_printf(master, "&WYour pet has advanced to level %d!\r\n", master->pcdata->petlevel);
            ch->level += 1;
            ch->hit += number_range(60, 80);
            ch->max_hit = ch->hit;
            master->pcdata->pethp = ch->max_hit;
            set_hitroll(ch->level);
            set_damroll(ch->level);
          }
        }
      }
    }
  }

// This check will be for Pet fighting alongside beast master killed mob 
  if(victim->level >= ch->level)
  {
    if(BEASTMELD(ch))
    {
      CHAR_DATA              *temp;

      temp = ch->master;

      if(ch->level - temp->level > 15)
      {
        send_to_char("You cannot gain any more experience until you level your beastmaster.\r\n", ch);
      }
      else
      {
        if(temp->pcdata->petlevel < 100)
        {
          temp->pcdata->petexp += 1;
          ch_printf(ch, "&WYour pet gains experience from this battle!\r\n");
        }

        if(temp->pcdata->petexp > 17)
        {
          temp->pcdata->petexp = 0;
          if(temp->pcdata->petlevel < 100)
          {
            temp->pcdata->petlevel += 1;
            ch_printf(ch, "&WYour pet has advanced to level %d!\r\n", temp->pcdata->petlevel);
            ch->level += 1;
            ch->hit += number_range(60, 80);
            ch->max_hit = ch->hit;
            set_hitroll(ch->level);
            set_damroll(ch->level);
          }
        }
      }
    }
  }

// if Beast Master killed the mob Give pet gain 
  if(ch->Class == CLASS_BEAST && !xIS_SET(ch->act, ACT_BEASTMELD) && (victim->level >= ch->level))
  {
// Only perform if the pet is present in the same room 
    CHAR_DATA              *beastpet;

    for(beastpet = first_char; beastpet; beastpet = beastpet->next)
    {
      if(xIS_SET(beastpet->act, ACT_BEASTPET) && beastpet->master)
        if(!str_cmp(ch->name, beastpet->master->name))
          if(ch->in_room->vnum == beastpet->in_room->vnum)
          {
            if(ch->level - beastpet->level > 15)
            {
              send_to_char("Your pet cannot gain anymore levels, until you level the Beastmaster.\r\n", ch);
            }
            else
            {
              if(ch->pcdata->petlevel < 100)
              {
                ch->pcdata->petexp += 1;
                ch_printf(ch, "&WYour pet gains experience from this battle!\r\n");
              }
              if(ch->pcdata->petexp > 17)
              {
                ch->pcdata->petexp = 0;
                if(ch->pcdata->petlevel < 100)
                {
                  ch->pcdata->petlevel += 1;
                  ch_printf(ch, "&WYour pet has advanced to level %d!\r\n", ch->pcdata->petlevel);
                  beastpet->level += 1;
                  beastpet->hit += number_range(60, 80);
                  beastpet->max_hit = beastpet->hit;
                  set_hitroll(beastpet->level);
                  set_damroll(beastpet->level);
                }
              }
            }

          }
    }

  }

  if(victim->race == RACE_ANIMAL)
  {
    affect_strip(victim, gsn_animal_form);
    xREMOVE_BIT(victim->affected_by, AFF_ANIMALFORM);
    animal_change(victim, FALSE);
    save_char_obj(victim);
  }

  /*
   * Take care of morphed characters
   */
  if(victim->morph)
  {
    do_unmorph_char(victim);
    save_char_obj(victim);
  }

  if(VLD_STR(victim->fightingip))
  {
    STRFREE(victim->fightingip);
    victim->fightingip = NULL;
  }

  if(VLD_STR(ch->fightingip))
  {
    STRFREE(ch->fightingip);
    ch->fightingip = NULL;
  }

  if(IS_AFFECTED(victim, AFF_DRAGONLORD) || victim->Class == CLASS_DRAGONLORD)
  {
    affect_strip(victim, gsn_human_form);
    xREMOVE_BIT(victim->affected_by, AFF_DRAGONLORD);
    victim->hit = number_range(10, 50);
    save_char_obj(victim);
  }

  if(IS_AFFECTED(victim, AFF_SHRINK))
  {
    xREMOVE_BIT(victim->affected_by, AFF_SHRINK);
    if ( !IS_NPC(victim )) {
    if ( victim->height != victim->pcdata->tmpheight )
       {
         victim->height = victim->pcdata->tmpheight;
         victim->pcdata->tmpheight = 0;
        }
    if ( victim->weight != victim->pcdata->tmpweight )
       {
         victim->weight = victim->pcdata->tmpweight;
         victim->pcdata->tmpweight = 0;
       }

       }

  }

  if(IS_AFFECTED(victim, AFF_ENLARGE))
  {
    xREMOVE_BIT(victim->affected_by, AFF_ENLARGE);
    if ( !IS_NPC(victim )) {

    if ( victim->height != victim->pcdata->tmpheight )
       {
         victim->height = victim->pcdata->tmpheight;
         victim->pcdata->tmpheight = 0;
        }
    if ( victim->weight != victim->pcdata->tmpweight )
       {
         victim->weight = victim->pcdata->tmpweight;
         victim->pcdata->tmpweight = 0;
       }


       }
  }

  if(IS_AFFECTED(victim, AFF_INSANE))
  {
    xREMOVE_BIT(victim->affected_by, AFF_INSANE);
  }

  if(xIS_SET(victim->affected_by, AFF_MOUNTED))
  {
    do_dismount(victim, (char *)"");
    save_char_obj(victim);
  }

  if(IS_NPC(victim))
  {
    if(victim->pIndexData->vnum == MOB_VNUM_SOLDIERS || victim->pIndexData->vnum == MOB_VNUM_ARCHERS || victim->pIndexData->vnum == MOB_VNUM_GUARDS || victim->pIndexData->vnum == MOB_VNUM_WARRIORS)
    {
      short                   rand;

      rand = number_range(1, 10);
      if(rand > 6)
      {
        send_to_char("&WYou gain one glory for killing the enemy in this siege!\r\n", ch);
        ch->quest_curr += 1;
      }
      else
      {
        gain_exp(ch, number_range(3000, 8000));
      }
      if(!IS_NPC(ch))
      {
        if(ch->pcdata->city)
        {
          CITY_DATA              *city = NULL;

          // Check which city to remove a point from
          if(ch->in_room->vnum == PALEON_DEFEND || ch->in_room->vnum == PALEON_DEFEND2 || ch->in_room->vnum == PALEON_DEFEND3)
          {
            city = get_city("Paleon City");
            if(city->dguards > 0 && city->defense > 0)
            {
              city->dguards -= 1;
              city->defense -= 1;
            }
            save_city(city);
          }
          else if(ch->in_room->vnum == FORBIDDEN_DEFEND || ch->in_room->vnum == FORBIDDEN_DEFEND2 || ch->in_room->vnum == FORBIDDEN_DEFEND3)
          {
            city = get_city("Forbidden City");
            if(city->dguards > 0 && city->defense > 0)
            {
              city->dguards -= 1;
              city->defense -= 1;
            }
            save_city(city);
          }
          else if(ch->in_room->vnum == DAKAR_DEFEND || ch->in_room->vnum == DAKAR_DEFEND2 || ch->in_room->vnum == DAKAR_DEFEND3)
          {
            city = get_city("Dakar City");
            if(city->dguards > 0 && city->defense > 0)
            {
              city->dguards -= 1;
              city->defense -= 1;
            }
            save_city(city);
          }
          else if(ch->in_room->vnum == DAKAR_SIEGE || ch->in_room->vnum == DAKAR_SIEGE2 || ch->in_room->vnum == DAKAR_SIEGE3)
          {
            city = get_city(ch->pcdata->city_name);
            if(city->osoldiers > 0 && city->offense > 0)
            {
              city->osoldiers -= 1;
              city->offense -= 1;
            }
            save_city(city);
          }
          else if(ch->in_room->vnum == FORBIDDEN_SIEGE || ch->in_room->vnum == FORBIDDEN_SIEGE2 || ch->in_room->vnum == FORBIDDEN_SIEGE3)
          {
            city = get_city(ch->pcdata->city_name);
            if(city->osoldiers > 0 && city->offense > 0)
            {
              city->osoldiers -= 1;
              city->offense -= 1;
            }
            save_city(city);
          }
          else if(ch->in_room->vnum == PALEON_SIEGE || ch->in_room->vnum == PALEON_SIEGE2 || ch->in_room->vnum == PALEON_SIEGE3)
          {
            city = get_city(ch->pcdata->city_name);
            if(city->osoldiers > 0 && city->offense > 0)
            {
              city->osoldiers -= 1;
              city->offense -= 1;
            }
            save_city(city);
          }
        }
      }
    }
  }
  if(!IS_NPC(victim) && (victim->pcdata->tmpcrawl > victim->height))
  {
    victim->height = victim->pcdata->tmpcrawl;
    save_char_obj(victim);
  }

/* Hack way to try to make players think they get some exp gains from mounts when crusader or shadowknight */
  if(ch->Class == CLASS_BEAST)
  {
    CHAR_DATA              *mob;
    bool                    beast;

    beast = FALSE;
    for(mob = first_char; mob; mob = mob->next)
    {
      if(IS_NPC(mob) && mob->in_room && ch == mob->master)
      {
        beast = TRUE;
        break;
      }
    }

    if(beast == TRUE && ch->in_room->vnum == mob->in_room->vnum && victim->level >= ch->level)
    {
      int                     extra = 0;

      extra = number_range(ch->level * 100, ch->level * 1000) + (get_curr_lck(ch) * 2);
      if(extra > 32000)
        extra = 32000 + number_range(1, 1000);
      if(ch->pcdata->petaffection < 50)
        ch->pcdata->petaffection += 1;

      ch_printf(ch, "&WYour affinity with animals in battle gains you %d experience.\r\n", extra);
      gain_exp(ch, extra);
    }
  }

/* Hack way to try to make players think they get some exp gains from mounts when crusader or shadowknight */
  if(ch->Class == CLASS_SHADOWKNIGHT || ch->secondclass == CLASS_SHADOWKNIGHT
     || ch->thirdclass == CLASS_SHADOWKNIGHT || ch->Class == CLASS_CRUSADER || ch->secondclass == CLASS_CRUSADER || ch->thirdclass == CLASS_CRUSADER)
  {
    if(ch->mount && ch->in_room == ch->mount->in_room && IS_STEED(ch) && victim->level >= ch->level)
    {
      int                     extra = 0;

      extra = number_range(ch->level * 100, ch->level * 1000) + (get_curr_lck(ch) * 2);
      if(extra > 32000)
        extra = 32000 + number_range(1, 1000);
      ch_printf(ch, "&WYour affinity with your warhorse in battle gains you %d experience.\r\n", extra);
      gain_exp(ch, extra);
    }
  }

  if(xIS_SET(ch->act, PLR_BATTLE))
  {
    short                   sound;

    sound = number_range(1, 10);

    if(sound < 6)
      send_to_char("!!SOUND(sound/deathcry1.wav)\r\n", ch);
    else if(sound > 5)
      send_to_char("!!SOUND(sound/deathcry2.wav)\r\n", ch);
  }

  if(!IS_NPC(victim) && (victim->height < victim->pcdata->tmpheight))
  {
    short                   ability;

    victim->max_hit = victim->pcdata->tmpmax_hit;
    victim->height = victim->pcdata->tmpheight;
    victim->weight = victim->pcdata->tmpweight;
    victim->race = victim->pcdata->tmprace;
    victim->Class = victim->pcdata->tmpclass;
    ability = skill_lookup("cone");
    victim->pcdata->learned[ability] = 0;
    ability = skill_lookup("fly");
    victim->pcdata->learned[ability] = 0;
    ability = skill_lookup("defend");
    victim->pcdata->learned[ability] = 0;
    save_char_obj(victim);
  }

  /*
   * Deal with switched imms
   */
  if(victim->desc && victim->desc->original)
  {
    CHAR_DATA              *temp = victim;

    interpret(victim, (char *)"return");
    save_char_obj(victim);
  }

  stop_summoning(victim);

  stop_fighting(victim, TRUE);

  // Clan members gain points for the clan with kills.
  if(!IS_NPC(ch))
  {
    CLAN_DATA              *clan;

    if(IS_NPC(victim))
    {
      if(ch->pcdata->clan && victim->level >= ch->level)
      {
        ch->pcdata->clanpoints += 1;
        ch->pcdata->clan->totalpoints += 1;
        clan = ch->pcdata->clan;
        ch_printf(ch, "&G%s clan has gained a point from your kill, now totaling %d clan status points!\r\n", clan->name, clan->totalpoints);
        save_clan(ch->pcdata->clan);
        save_char_obj(ch);
      }
      ch->pcdata->mkills++;
      if(ch->pcdata->clan)
        ch->pcdata->clan->mkills++;
      ch->in_room->area->mkills++;
    }
    if(!IS_NPC(victim) && victim != ch)
    {
      ch->pcdata->clanpoints += 3;

      if(ch->pcdata->clan)
      {
        ch->pcdata->clan->totalpoints += 3;
        clan = ch->pcdata->clan;
        ch_printf(ch, "&G%s clan has gained 3 points from your kill, now totaling %d clan status points!\r\n", clan->name, clan->totalpoints);
        if(countpkill(ch, victim))
          increase_clan_pkills(ch->pcdata->clan, ch->level);
        save_clan(clan);
      }
      if(victim->pcdata->clan && countpkill(ch, victim))
      {
        increase_clan_pdeaths(victim->pcdata->clan, victim->level);
        save_clan(victim->pcdata->clan);
      }
      ch->pcdata->pkills++;
      victim->pcdata->pdeaths++;
      add_pkill(ch, victim);
      save_char_obj(ch);
    }
  }

/*  Not sure where else to put the announcement - Volk  */

  if(!IS_NPC(victim))
  {
    if(victim != ch)
      snprintf(buf, MSL, "%s has been killed by %s!", victim->name, (IS_NPC(ch) ? ch->short_descr : ch->name));
    else
      snprintf(buf, MSL, "%s has been killed!", victim->name);
    announce(buf);

    if(victim != ch)
      snprintf(buf, MSL, "%s (%d) killed by %s at %d", victim->name, victim->level, (IS_NPC(ch) ? ch->short_descr : ch->name), victim->in_room->vnum);
    else
      snprintf(buf, MSL, "%s (%d) bled to death at %d", victim->name, victim->level, victim->in_room->vnum);
    log_string(buf);
    to_channel(buf, "Monitor", LEVEL_IMMORTAL);

  }

  if(xIS_SET(victim->act, PLR_BATTLE))
  {
    send_to_char("!!SOUND(sound/victimdeath.wav)\r\n", victim);
  }

  mprog_death_trigger(ch, victim);
  if(char_died(victim))
    return;

  rprog_death_trigger(ch, victim);
  if(char_died(victim))
    return;

  if(IS_NPC(victim))
    make_corpse(victim, ch);

  if(victim->in_room->sector_type == SECT_OCEANFLOOR
     || victim->in_room->sector_type == SECT_UNDERWATER || victim->in_room->sector_type == SECT_WATER_SWIM || victim->in_room->sector_type == SECT_WATER_NOSWIM)
    act(AT_BLOOD, "$n's blood slowly clouds the surrounding water.", victim, NULL, NULL, TO_ROOM);
  else if(victim->in_room->sector_type == SECT_AIR)
    act(AT_BLOOD, "$n's blood sprays wildly through the air.", victim, NULL, NULL, TO_ROOM);
  else
    make_blood(victim);

  if(IS_NPC(victim))
  {
    victim->pIndexData->killed++;
    extract_char(victim, TRUE);
    victim = NULL;
    return;
  }

  set_char_color(AT_DIEMSG, victim);

  if(victim->pcdata->mdeaths + victim->pcdata->pdeaths < 3)
    do_help(victim, (char *)"new_death");
  else
    do_help(victim, (char *)"_DIEMSG_");
  make_corpse(victim, ch);

  strcpy(arg, victim->name);

  extract_char(victim, FALSE);

  if(!victim)
  {
    bug("%s", "oops! raw_kill: extract_char destroyed pc char");
    return;
  }
  while(victim->first_affect)
    affect_remove(victim, victim->first_affect);
  victim->affected_by = race_table[victim->race]->affected;
  victim->resistant = 0;
  victim->susceptible = 0;
  victim->immune = 0;
  victim->carry_weight = 0;
  victim->armor = 100;
  victim->armor += race_table[victim->race]->ac_plus;
  victim->attacks = race_table[victim->race]->attacks;
  victim->defenses = race_table[victim->race]->defenses;
  victim->mod_str = 0;
  victim->mod_dex = 0;
  victim->mod_wis = 0;
  victim->mod_int = 0;
  victim->mod_con = 0;
  victim->mod_cha = 0;
  victim->mod_lck = 0;
  victim->damroll = 0;
  victim->hitroll = 0;
  victim->mental_state = -10;
  victim->alignment = URANGE(-1000, victim->alignment, 1000);

  victim->saving_poison_death = race_table[victim->race]->saving_poison_death;
  victim->saving_wand = race_table[victim->race]->saving_wand;
  victim->saving_para_petri = race_table[victim->race]->saving_para_petri;
  victim->saving_breath = race_table[victim->race]->saving_breath;
  victim->saving_spell_staff = race_table[victim->race]->saving_spell_staff;
  victim->position = POS_RESTING;
  victim->hit = UMAX(1, victim->hit);
  /*
   * Shut down some of those naked spammer killers - Blodkai 
   */
  if(!IS_AVATAR(ch) && !IS_DUALAVATAR(ch) && !IS_TRIAVATAR(ch))
    victim->mana = UMAX(1, victim->mana);
  else
    victim->mana = 1;
  victim->move = UMAX(1, victim->move);

  /*
   * Pardon crimes...  -Thoric 
   */
  if(xIS_SET(victim->act, PLR_KILLER))
  {
    xREMOVE_BIT(victim->act, PLR_KILLER);
    send_to_char("The City officials have pardoned you for your murderous acts.\r\n", victim);
  }
  if(xIS_SET(victim->act, PLR_THIEF))
  {
    xREMOVE_BIT(victim->act, PLR_THIEF);
    send_to_char("The City officials have pardoned you for your thievery.\r\n", victim);
  }
  victim->pcdata->condition[COND_FULL] = 50;
  victim->pcdata->condition[COND_THIRST] = 50;
  if(IS_BLOODCLASS(victim))
    victim->blood = (victim->level / 2);
  if(xIS_SET(sysdata.save_flags, SV_DEATH))
    save_char_obj(victim);
}

void align_zap(CHAR_DATA *ch)
{
  OBJ_DATA               *obj, *obj_next;

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

    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_MAGIC, "You are zapped by $p.", ch, obj, NULL, TO_CHAR);
      act(AT_MAGIC, "$n is zapped by $p.", ch, obj, NULL, TO_ROOM);
      obj_from_char(obj);
      obj = obj_to_room(obj, ch->in_room);
      oprog_zap_trigger(ch, obj); /* mudprogs */
      if(char_died(ch))
        return;
    }
  }
}

/* The new and improved mob xp_flag formula. Data used is according to information from Dwip.
 * Sue him if this isn't working right :)
 * This is gonna be one big, ugly set of ifchecks.
 * Samson 5-18-01, Modified by Volk 04-Sep-06
 * This will now take an input experience and mob, and output modified experience for that mob.
 * Renamed to 'ExpRatio' and highly modified.
 */
int ExpRatio(CHAR_DATA *mob, int xp)
{
  int                     flags = 0;

  if(mob->armor < 0)
    flags++;

  if(mob->numattacks > 4)
    flags += 2;

  if(IS_ACT_FLAG(mob, ACT_AGGRESSIVE) || IS_ACT_FLAG(mob, ACT_WILD_AGGR))
    flags++;

  if(IS_ACT_FLAG(mob, ACT_WIMPY))
    flags -= 1;

  if(IS_AFFECTED(mob, AFF_DETECT_INVIS) || IS_AFFECTED(mob, AFF_DETECT_HIDDEN) || IS_AFFECTED(mob, AFF_TRUESIGHT))
    flags++;

  if(IS_AFFECTED(mob, AFF_SANCTUARY))
    flags++;

  if(IS_AFFECTED(mob, AFF_SNEAK) || IS_AFFECTED(mob, AFF_HIDE) || IS_AFFECTED(mob, AFF_INVISIBLE))
    flags++;

  if(IS_AFFECTED(mob, AFF_FIRESHIELD))
    flags++;

  if(IS_AFFECTED(mob, AFF_SHOCKSHIELD))
    flags++;

  if(IS_AFFECTED(mob, AFF_ICESHIELD))
    flags++;

  if(IS_AFFECTED(mob, AFF_VENOMSHIELD))
    flags += 2;

  if(IS_AFFECTED(mob, AFF_ACIDMIST))
    flags += 2;
/*
   if( IS_AFFECTED( mob, AFF_BLADEBARRIER ) )
      flags += 2;
*/
  if(IS_RESIS(mob, RIS_FIRE) || IS_RESIS(mob, RIS_COLD) || IS_RESIS(mob, RIS_ELECTRICITY) || IS_RESIS(mob, RIS_ENERGY) || IS_RESIS(mob, RIS_ACID))
    flags++;

  if(IS_RESIS(mob, RIS_BLUNT) || IS_RESIS(mob, RIS_SLASH) || IS_RESIS(mob, RIS_PIERCE) || IS_RESIS(mob, RIS_HACK) || IS_RESIS(mob, RIS_LASH))
    flags++;

  if(IS_RESIS(mob, RIS_SLEEP) || IS_RESIS(mob, RIS_CHARM) || IS_RESIS(mob, RIS_HOLD) || IS_RESIS(mob, RIS_POISON) || IS_RESIS(mob, RIS_PARALYSIS))
    flags++;

  if(IS_RESIS(mob, RIS_PLUS1) || IS_RESIS(mob, RIS_PLUS2) || IS_RESIS(mob, RIS_PLUS3) || IS_RESIS(mob, RIS_PLUS4) || IS_RESIS(mob, RIS_PLUS5) || IS_RESIS(mob, RIS_PLUS6))
    flags++;

  if(IS_RESIS(mob, RIS_MAGIC))
    flags += 2;

  if(IS_RESIS(mob, RIS_NONMAGIC))
    flags++;

  if(IS_IMMUNE(mob, RIS_FIRE) || IS_IMMUNE(mob, RIS_COLD) || IS_IMMUNE(mob, RIS_ELECTRICITY) || IS_IMMUNE(mob, RIS_ENERGY) || IS_IMMUNE(mob, RIS_ACID))
    flags += 2;

  if(IS_IMMUNE(mob, RIS_BLUNT) || IS_IMMUNE(mob, RIS_SLASH) || IS_IMMUNE(mob, RIS_PIERCE) || IS_IMMUNE(mob, RIS_HACK) || IS_IMMUNE(mob, RIS_LASH))
    flags += 2;

  if(IS_IMMUNE(mob, RIS_SLEEP) || IS_IMMUNE(mob, RIS_CHARM) || IS_IMMUNE(mob, RIS_HOLD) || IS_IMMUNE(mob, RIS_POISON) || IS_IMMUNE(mob, RIS_PARALYSIS))
    flags += 2;

  if(IS_IMMUNE(mob, RIS_PLUS1) || IS_IMMUNE(mob, RIS_PLUS2) || IS_IMMUNE(mob, RIS_PLUS3) || IS_IMMUNE(mob, RIS_PLUS4) || IS_IMMUNE(mob, RIS_PLUS5) || IS_IMMUNE(mob, RIS_PLUS6))
    flags += 2;

  if(IS_IMMUNE(mob, RIS_MAGIC))
    flags += 2;

  if(IS_IMMUNE(mob, RIS_NONMAGIC))
    flags++;

  if(IS_SUSCEP(mob, RIS_FIRE) || IS_SUSCEP(mob, RIS_COLD) || IS_SUSCEP(mob, RIS_ELECTRICITY) || IS_SUSCEP(mob, RIS_ENERGY) || IS_SUSCEP(mob, RIS_ACID))
    flags -= 2;

  if(IS_SUSCEP(mob, RIS_BLUNT) || IS_SUSCEP(mob, RIS_SLASH) || IS_SUSCEP(mob, RIS_PIERCE) || IS_SUSCEP(mob, RIS_HACK) || IS_SUSCEP(mob, RIS_LASH))
    flags -= 3;

  if(IS_SUSCEP(mob, RIS_SLEEP) || IS_SUSCEP(mob, RIS_CHARM) || IS_SUSCEP(mob, RIS_HOLD) || IS_SUSCEP(mob, RIS_POISON) || IS_SUSCEP(mob, RIS_PARALYSIS))
    flags -= 3;

  if(IS_SUSCEP(mob, RIS_PLUS1) || IS_SUSCEP(mob, RIS_PLUS2) || IS_SUSCEP(mob, RIS_PLUS3) || IS_SUSCEP(mob, RIS_PLUS4) || IS_SUSCEP(mob, RIS_PLUS5) || IS_SUSCEP(mob, RIS_PLUS6))
    flags -= 2;

  if(IS_SUSCEP(mob, RIS_MAGIC))
    flags -= 3;

  if(IS_SUSCEP(mob, RIS_NONMAGIC))
    flags -= 2;
/*
   if( IS_ABSORB( mob, RIS_FIRE ) || IS_ABSORB( mob, RIS_COLD ) || IS_ABSORB( mob, RIS_ELECTRICITY )
       || IS_ABSORB( mob, RIS_ENERGY ) || IS_ABSORB( mob, RIS_ACID ) )
      flags += 3;

   if( IS_ABSORB( mob, RIS_BLUNT ) || IS_ABSORB( mob, RIS_SLASH ) || IS_ABSORB( mob, RIS_PIERCE )
       || IS_ABSORB( mob, RIS_HACK ) || IS_ABSORB( mob, RIS_LASH ) )
      flags += 3;

   if( IS_ABSORB( mob, RIS_SLEEP ) || IS_ABSORB( mob, RIS_CHARM ) || IS_ABSORB( mob, RIS_HOLD )
    || IS_ABSORB( mob, RIS_POISON ) || IS_ABSORB( mob, RIS_PARALYSIS ) )
	flags += 3;

   if( IS_ABSORB( mob, RIS_PLUS1 ) || IS_ABSORB( mob, RIS_PLUS2 ) || IS_ABSORB( mob, RIS_PLUS3 )
       || IS_ABSORB( mob, RIS_PLUS4 ) || IS_ABSORB( mob, RIS_PLUS5 ) || IS_ABSORB( mob, RIS_PLUS6 ) )
      flags += 3;

   if( IS_ABSORB( mob, RIS_MAGIC ) )
      flags += 3;

   if( IS_ABSORB( mob, RIS_NONMAGIC ) )
      flags += 2;
*/
  if(IS_ATTACK(mob, ATCK_LOWBLOW))
    flags++;

  if(IS_ATTACK(mob, ATCK_STUN))
    flags++;

  if(IS_ATTACK(mob, ATCK_EBOLT))
    flags += 3;

  if(IS_ATTACK(mob, ATCK_BLIGHTNING) || IS_ATTACK(mob, ATCK_LTOUCH))
    flags += 3;

  if(IS_ATTACK(mob, ATCK_BACKSTAB))
    flags += 2;

  if(IS_ATTACK(mob, ATCK_MENTALASSAULT) || IS_ATTACK(mob, ATCK_BREATHE) || IS_ATTACK(mob, ATCK_GUT) || IS_ATTACK(mob, ATCK_IMPALE) || IS_ATTACK(mob, ATCK_FROST) || IS_ATTACK(mob, ATCK_GSMITE))
    flags += 2;

  if(IS_ATTACK(mob, ATCK_JUDOCHOP) || IS_ATTACK(mob, ATCK_FIREBALL) || IS_ATTACK(mob, ATCK_LIGHTNING))
    flags += 2;

  if(IS_ATTACK(mob, ATCK_PUGILISM) || IS_ATTACK(mob, ATCK_ACIDSPRAY) || IS_ATTACK(mob, ATCK_SWARM)
     || IS_ATTACK(mob, ATCK_ASTRALATTACK) || IS_ATTACK(mob, ATCK_PARALYZE) || IS_ATTACK(mob, ATCK_FEAR) || IS_ATTACK(mob, ATCK_STOMP))
    flags += 2;

  if(IS_ATTACK(mob, ATCK_BITE) || IS_ATTACK(mob, ATCK_CLAWS)
     || IS_ATTACK(mob, ATCK_TAIL_SWIPE) || IS_ATTACK(mob, ATCK_STATICPULSE) || IS_ATTACK(mob, ATCK_PLUCK)
     || IS_ATTACK(mob, ATCK_PUNCH) || IS_ATTACK(mob, ATCK_KICK) || IS_ATTACK(mob, ATCK_FEROCIOUSSTRIKE)
     || IS_ATTACK(mob, ATCK_BACKHAND) || IS_ATTACK(mob, ATCK_GOUGE) || IS_ATTACK(mob, ATCK_PSIONICBLAST)
     || IS_ATTACK(mob, ATCK_DRAIN) || IS_ATTACK(mob, ATCK_POISON) || IS_ATTACK(mob, ATCK_CRITIC)
     || IS_ATTACK(mob, ATCK_SLOW) || IS_ATTACK(mob, ATCK_THROATPUNCH) || IS_ATTACK(mob, ATCK_CRANEKICK)
     || IS_ATTACK(mob, ATCK_RAKE) || IS_ATTACK(mob, ATCK_THAITIN) || IS_ATTACK(mob, ATCK_BLURATTACK)
     || IS_ATTACK(mob, ATCK_SHRIEKINGNOTE) || IS_ATTACK(mob, ATCK_MURAZORWHIP) || IS_ATTACK(mob, ATCK_FLYBY)
     || IS_ATTACK(mob, ATCK_BUTTERFLYKICK) || IS_ATTACK(mob, ATCK_SNATCH) || IS_ATTACK(mob, ATCK_HEADBUTT)
     || IS_ATTACK(mob, ATCK_WEAKEN) || IS_ATTACK(mob, ATCK_HHANDS) || IS_ATTACK(mob, ATCK_CORROSIVE))
    flags++;

  if(IS_DEFENSE(mob, DFND_PARRY))
    flags++;

  if(IS_DEFENSE(mob, DFND_DODGE))
    flags++;

  if(IS_DEFENSE(mob, DFND_NETTLESKIN))
    flags++;

  if(IS_DEFENSE(mob, DFND_DISPELMAGIC))
    flags++;

  if(IS_DEFENSE(mob, DFND_DISARM))
    flags++;

  if(IS_DEFENSE(mob, DFND_SANCTUARY))
    flags += 2;

  if(IS_DEFENSE(mob, DFND_SPECTRALWARD) || IS_DEFENSE(mob, DFND_SHIELD)
     || IS_DEFENSE(mob, DFND_TORPOR) || IS_DEFENSE(mob, DFND_KINETICBARRIER)
     || IS_DEFENSE(mob, DFND_HAWKSPIRIT)
     || IS_DEFENSE(mob, DFND_LICK) || IS_DEFENSE(mob, DFND_COMBATHEAL)
     || IS_DEFENSE(mob, DFND_WILLOWSKIN)
     || IS_DEFENSE(mob, DFND_GRENDALSTANCE) || IS_DEFENSE(mob, DFND_WOLFSPIRIT)
     || IS_DEFENSE(mob, DFND_REGENERATE) || IS_DEFENSE(mob, DFND_MAINTAINPOSITION)
     || IS_DEFENSE(mob, DFND_HUNKERDOWN) || IS_DEFENSE(mob, DFND_FINDWEAKNESS) || IS_DEFENSE(mob, DFND_BEARSPIRIT) || IS_DEFENSE(mob, DFND_MINORRESTORE))
    flags++;

  /*
   * Gotta do this because otherwise mobs with negative flags will take xp AWAY from the player. 
   */
  if(flags < 0)
    flags = 0;

  /*
   * And cap all mobs to no more than 12 flags to keep xp from going haywire 
   */
  if(flags > 12)
    flags = 12;

  /*
   * At 12 flags, we would double the experience (100%). At 0 flags, do nothing. 
   */

  int                     modxp = xp * flags / 5;

  return modxp;
}

void group_gain(CHAR_DATA *ch, CHAR_DATA *victim)
{
  CHAR_DATA              *gch, *gch_next, *lch;
  int                     xp = 0, max_level = 0, members = 0;

  /*
   * Monsters don't get kill xp's or alignment changes ( exception: charmies )
   * Dying of mortal wounds or poison doesn't give xp to anyone!
   */
  if(victim == ch)
    return;

  /*
   * We hope this works of course 
   */
  if(IS_NPC(ch))
  {
    if(ch->leader)
    {
      if(!IS_NPC(ch->leader) && ch->leader == ch->master && IS_AFFECTED(ch, AFF_CHARM) && ch->in_room == ch->leader->in_room)
        ch = ch->master;
    }
  }

  /*
   * See above. If this is STILL an NPC after that, then yes, we need to bail out now. 
   */
  if(IS_NPC(ch))
    return;

  members = 0;
  for(gch = ch->in_room->first_person; gch; gch = gch->next_in_room)
  {
    if(!is_same_group(gch, ch))
      continue;
    /*
     * Count members only if they're PCs so charmies don't dillute the kill 
     */
    if(!IS_NPC(gch))
    {
      members++;
      max_level = UMAX(max_level, gch->level);
    }
  }
  if(members == 0)
  {
    bug("%s", "Group_gain: members.");
    members = 1;
  }

  lch = ch->leader ? ch->leader : ch;
  for(gch = ch->in_room->first_person; gch; gch = gch_next)
  {
    gch_next = gch->next_in_room;

    if(!is_same_group(gch, ch))
      continue;
    xp = (int)(xp_compute(gch, victim) * 0.1765) / members;
    if(!gch->fighting)
      xp /= 2;
    gch->alignment = align_compute(gch, victim);
    /*
     * class_monitor( gch ); 
     */
    if(!IS_NPC(victim) || !xIS_SET(victim->act, ACT_IMMORTAL))
      gain_exp(gch, xp);  /* group gain */
    align_zap(gch);
  }
  return;
}

int align_compute(CHAR_DATA *gch, CHAR_DATA *victim)
{
  int                     align, newalign, divalign;

  align = (gch->alignment - victim->alignment);

  /*
   * slowed movement in good & evil ranges by a factor of 5, h 
   * Added divalign to keep neutral chars shifting faster -- Blodkai 
   * This is obviously gonna take a lot more thought 
   */

  if(gch->alignment > -350 && gch->alignment < 350)
    divalign = 4;
  else
    divalign = 20;

  if(align > 500)
    newalign = UMIN(gch->alignment + (align - 500) / divalign, 1000);
  else if(align < -500)
    newalign = UMAX(gch->alignment + (align + 500) / divalign, -1000);
  else
    newalign = gch->alignment - (int)(gch->alignment / divalign);

  return newalign;
}

/*
 * Calculate how much XP gch should gain for killing victim
 * Lots of redesigning for new exp system by Thoric
 *
*/
int xp_compute(CHAR_DATA *gch, CHAR_DATA *victim)
{
  int                     xp;
  int                     gchlev = gch->level;

//   xp = ( get_exp_worth( victim ) * URANGE( 0, ( victim->level - gchlev ) + 15, 20 ) ) / 20;
/*  This URANGE - return b if between a or c, otherwise return one of those two. */
  xp = (get_exp_worth(victim) * URANGE(0, (victim->level - gchlev) + 21, 10)) / 10;

  if(gch->race == RACE_DRAGON && (victim->level - gchlev < 20) && xp < 1000)
  {
    xp = number_range(8000, 15000);
  }

/*  In affect, this should allow players to fight within 20 levels of their own (+21). It
 *  caps at 10, so you don't gain too much for killing at your own level (or over), but is only
 *  divide by 10 too (so potential to gain more experience than normal for lower/higher mobs) */

  /*
   * get 1/4 exp for players               -Thoric 
   */
  if(!IS_NPC(victim))
    xp /= 4;

  /*
   * reduce exp for killing the same mob repeatedly    -Thoric 
   */
  if(!IS_NPC(gch) && IS_NPC(victim))
  {
    int                     times = times_killed(gch, victim);

    if(times >= 10)
      xp = 0;
    else if(times)
    {
      xp = (xp * (20 - times)) / 20;
      if(times > 8)
        xp /= 3;
      else if(times > 5)
        xp >>= 1;
    }
  }

  if(!IS_NPC(gch))
  {
    if(xp < 1000)
    {
      if(gch->pcdata->failsafe == 1)
        xp += number_range(300, 600);
      else if(gch->pcdata->failsafe == 2)
        xp += number_range(700, 1000);
      else if(gch->pcdata->failsafe == 3)
        xp += number_range(1000, 2000);
      else if(gch->pcdata->failsafe == 4)
        xp += number_range(2000, 3000);
      else if(gch->pcdata->failsafe > 4)
        xp += number_range(3000, 8000);
    }
  }

/*  Volk - After all that, throw experience through ExpRatio (to give more
 * XP for stronger mobs) then cap it off to ensure players don't gain too much */
  xp = ExpRatio(victim, xp);
  xp /= 3;

  return URANGE(0, xp, exp_level(gch, gchlev + 1) - exp_level(gch, gchlev));
}

/*
 * Revamped by Thoric to be more realistic
 * Added code to produce different messages based on weapon type - FB
 * Added better bug message so you can track down the bad dt's -Shaddai
 */
void new_dam_message(CHAR_DATA *ch, CHAR_DATA *victim, int dam, unsigned int dt, OBJ_DATA *obj)
{
  char                    buf1[256], buf2[256], buf3[256];
  const char             *vs;
  const char             *vp;
  const char             *attack;
  char                    punct;
  short                   dampc;
  struct skill_type      *skill = NULL;
  bool                    gcflag = FALSE;
  bool                    gvflag = FALSE;
  int                     d_index = 1, w_index;
  ROOM_INDEX_DATA        *was_in_room;
  short                   chance;

  if(!dam)
    dampc = 0;
  else
    dampc = ((dam * 1000) / victim->max_hit) + (50 - ((victim->hit * 50) / victim->max_hit));

  if(ch->in_room != victim->in_room)
  {
    was_in_room = ch->in_room;
    char_from_room(ch);
    char_to_room(ch, victim->in_room);
  }
  else
    was_in_room = NULL;

  if(dt > 0 && dt < (unsigned int)top_sn)
    w_index = 0;
  else if(dt >= (unsigned int)TYPE_HIT && dt < (unsigned int)TYPE_HIT + sizeof(attack_table) / sizeof(attack_table[0]))
    w_index = (dt - TYPE_HIT);
  else
  {
//      bug ( "Dam_message: bad dt %d from %s in %d.", dt, ch->name, ch->in_room->vnum );
    dt = TYPE_HIT;
    w_index = 0;
  }

  /*
   * get the damage index 
   */
  if(dam == 0)
    d_index = 0;
  else if(dampc < 0)
    d_index = 1;
  else if(dampc <= 100)
    d_index = 1 + dampc / 10;
  else if(dampc <= 200)
    d_index = 11 + (dampc - 100) / 20;
  else if(dampc <= 900)
    d_index = 16 + (dampc - 200) / 100;
  else
    d_index = 23;

  /*
   * Lookup the damage message 
   */
  vs = s_message_table[w_index][d_index];
  vp = p_message_table[w_index][d_index];

  punct = (dampc <= 30) ? '.' : '!';

  if(dam == 0 && (!IS_NPC(ch) && (IS_SET(ch->pcdata->flags, PCFLAG_GAG))))
    gcflag = TRUE;

  if(dam == 0 && (!IS_NPC(victim) && (IS_SET(victim->pcdata->flags, PCFLAG_GAG))))
    gvflag = TRUE;

  if(dt >= 0 && dt < (int unsigned)top_sn)
    skill = skill_table[dt];

  chance = number_range(1, 100);

  if(ch->success_attack > 0 && (w_index != 0 || dt == TYPE_HIT + DAM_HIT) && !IS_AFFECTED(victim, AFF_DISABLED))
  {
    if(xIS_SET(ch->act, PLR_BATTLE))
      send_to_char("!!SOUND(sound/playerhit.wav)\r\n", ch);

  }
  if(ch->success_attack < 1 && (w_index != 0 || dt == TYPE_HIT + DAM_HIT) && !IS_AFFECTED(victim, AFF_DISABLED))
  {
    if(xIS_SET(ch->act, PLR_BATTLE))
      send_to_char("!!SOUND(sound/miss.wav)\r\n", ch);

  }

// Add failsafe here for w_index == 0 even though wielded this alos makes sn == -1 which I haven't solved yet
  OBJ_DATA               *weapon;

/*            if ( dt >= 0 && dt < top_sn ) {
                SKILLTYPE              *skill = skill_table[dt];
              }
*/

  if((weapon = get_eq_char(ch, WEAR_WIELD)) != NULL)
  {
    if(w_index == 0)
    {
      dt = TYPE_HIT + weapon->value[3];
      w_index = (dt - TYPE_HIT);
/*            if ( skill )
            bug( "Dam_message: bad sn less than 0 from %s dt is %s w_index is %d.", ch->name, skill->name, w_index );
*/
    }
  }

  if(dt == TYPE_HIT && (!IS_NPC(ch) && ch->martialarts == 0 && (ch->pcdata->learned[gsn_martial_arts] > 0)))
  {

    if(ch->level > 49 && chance <= 5) // small proc at level 50 to compete with small
                                      // proc grapple has
      interpret(ch, (char *)"judo");
    if(chance <= 10)
    {
      snprintf(buf1, 256, "$n's elbow %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your elbow %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's elbow %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 30)
    {
      snprintf(buf1, 256, "$n's palmheel attack %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your palmheel attack %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's palmheel attack %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 40)
    {
      snprintf(buf1, 256, "$n's sidekick %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your sidekick %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's sidekick %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 50)
    {
      snprintf(buf1, 256, "$n's knifehand strike %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your knifehand strike %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's knifehand strike %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 60)
    {
      snprintf(buf1, 256, "$n's axekick %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your axekick %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's axekick %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 70)
    {
      snprintf(buf1, 256, "$n's hammer fist %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your hammer fist %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's hammer fist %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    // Following three added in by Taon.
    else if(chance <= 80)
    {
      snprintf(buf1, 256, "$n's right hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your right hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's right hook %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);

    }
    else if(chance <= 90)
    {
      snprintf(buf1, 256, "$n's left hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your left hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's left hook %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else
    {
      snprintf(buf1, 256, "$n's jab %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your jab %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's jab %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
  }
  else if(ch->martialarts == 1 && (ch->pcdata->learned[gsn_grapple] > 0) && get_eq_char(ch, WEAR_WIELD) == NULL)
  {
    if(ch->level > 49 && chance <= 5) // small proc at level 50 to compete with small
                                      // proc grapple has
      interpret(ch, (char *)"disarm");

    if(number_chance(0, 5) == 1)
      learn_from_success(ch, gsn_grapple);

    if(chance <= 10)
    {
      snprintf(buf1, 256, "$n's guillotine choke %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your guillotine choke %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's guillotine choke %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 30)
    {
      snprintf(buf1, 256, "$n's arm bar %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your arm bar %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's arm bar %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 40)
    {
      snprintf(buf1, 256, "$n's rear naked choke %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your rear naked choke %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's rear naked choke %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 50)
    {
      snprintf(buf1, 256, "$n's ankle lock %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your ankle lock %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's ankle lock %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 60)
    {
      snprintf(buf1, 256, "$n's arm triangle %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your arm triangle %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's arm triangle %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 70)
    {
      snprintf(buf1, 256, "$n's hip throw %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your hip throw %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's hip throw %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance <= 80)
    {
      snprintf(buf1, 256, "$n's half nelson %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your half nelson %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's half nelson %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);

    }
    else if(chance <= 90)
    {
      snprintf(buf1, 256, "$n's head lock %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your head lock %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's head lock %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else
    {
      snprintf(buf1, 256, "$n's elbow crank %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your elbow crank %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's elbow crank %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
  }
  else if(ch->martialarts == 3 && !IS_NPC(ch))
  {
    short                   bustamove = number_range(1, 100);

    dam = dam + get_curr_dex(ch);

    if(bustamove < 30)
    {
      snprintf(buf1, 256, "Moving with the morris dance $n's left knee lauches upward and %s $N %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Moving with the morris dance your left knee launches upward and %s $N %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "Moving with the morris dance $n's left knee launches upward and %s you %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }

    if(bustamove < 60 && bustamove > 29)
    {
      snprintf(buf1, 256, "$n's held out arms from the morris dance smack %s $N %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your held out arms from the morris dance smack %s $N %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's held out arms from the morris dance smack %s you %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }

    if(bustamove > 59)
    {
      snprintf(buf1, 256, "Moving with the morris dance $n leaps into the air which %s $N %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Moving with the morris dance you leap into the air which %s $N %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "Moving with the morris dance $n leaps into the air which %s you %d %s for %d total damage%c", vp,
               ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
  }

  else if(!IS_NPC(ch) && ch->pcdata->learned[gsn_pugilism] > 0 && get_eq_char(ch, WEAR_WIELD) == NULL && get_eq_char(ch, WEAR_MISSILE_WIELD) == NULL && ch->Class != CLASS_MONK && ch->martialarts == 0
          && ch->race != RACE_ANIMAL && ch->race != RACE_DRAGON && dt < (unsigned int)TYPE_HIT + sizeof(attack_table) / sizeof(attack_table[0]) && !IS_VALID_SN(dt))
  {
    chance = number_range(1, 100);

    if(chance <= 50)
    {
      snprintf(buf1, 256, "$n's right hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your right hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's right hook %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);

    }
    else if(chance >= 51)
    {
      snprintf(buf1, 256, "$n's left hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your left hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's left hook %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
  }
  else if(IS_NPC(ch) && IS_ATTACK(ch, ATCK_PUGILISM) && get_eq_char(ch, WEAR_WIELD) == NULL && ch->success_attack > 0)
  {
    chance = number_range(1, 100);

    if(chance <= 50)
    {
      snprintf(buf1, 256, "$n's right hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your right hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's right hook %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);

    }
    else if(chance >= 51)
    {
      snprintf(buf1, 256, "$n's left hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your left hook %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's left hook %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
  }
// start of animal form damage
  else if(((ch)->Class == CLASS_OWL || (ch)->Class == CLASS_GRYPHON))
  {
    snprintf(buf1, 256, "$n's talons %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf2, 256, "Your talons %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf3, 256, "$n's talons %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
  }
  else if(((ch)->Class == CLASS_BEAR || (ch)->Class == CLASS_WOLF))
  {

    if(dt == gsn_crushing_jaw)
    {
      snprintf(buf1, 256, "$n's crushing jaw attack %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your crushing jaw attack %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's crushing jaw attack %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else
    {
      snprintf(buf1, 256, "$n's claw %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your claws %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's claws %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
  }
  else if(((ch)->Class == CLASS_FISH))
  {
    snprintf(buf1, 256, "$n's bite %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf2, 256, "Your bite %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf3, 256, "$n's bite %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
  }
  else if(((ch)->Class == CLASS_TREANT))
  {
    snprintf(buf1, 256, "$n's branches %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf2, 256, "Your branches %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf3, 256, "$n's branches %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
  }

// end of animal

  else if(dt == TYPE_HIT && ((ch)->race == RACE_DRAGON))
  {
    if(chance <= 33)
    {
      snprintf(buf1, 256, "$n's talons %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your talons %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's talons %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else if(chance >= 34 && chance < 75)
    {
      snprintf(buf1, 256, "$n's massive maw %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your massive maw %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's massive maw %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
    else
    {
      snprintf(buf1, 256, "$n's tail %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf2, 256, "Your tail %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
      snprintf(buf3, 256, "$n's tail %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    }
  }
  else if(dt == TYPE_HIT && ch->martialarts != 3)
  {
    snprintf(buf1, 256, "$n %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf2, 256, "You %s $N %d %s for %d total damage%c", vs, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf3, 256, "$n %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
  }
  else if(dt > (unsigned int)TYPE_HIT && is_wielding_poisoned(ch))
  {
    if(dt < (unsigned int)TYPE_HIT + sizeof(attack_table) / sizeof(attack_table[0]))
      attack = attack_table[dt - TYPE_HIT];
    else
    {
      bug("Dam_message: bad dt %d from %s in %d.", dt, ch->name, ch->in_room->vnum);
      dt = TYPE_HIT;
      attack = attack_table[0];
    }

    set_char_color(AT_GREEN, ch);
    snprintf(buf1, 256, "$n's poisoned %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf2, 256, "Your poisoned %s $N %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf3, 256, "$n's poisoned %s you %d %s for %d total damage%c", vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
  }
  else
  {
    if(skill)
    {
      attack = skill->noun_damage;
      if(dam == 0)
      {
        bool                    found = FALSE;

        if(skill->miss_char && skill->miss_char[0] != '\0')
        {
          act(AT_CYAN, skill->miss_char, ch, NULL, victim, TO_CHAR);
          found = TRUE;
        }
        if(skill->miss_vict && skill->miss_vict[0] != '\0')
        {
          act(AT_GREEN, skill->miss_vict, ch, NULL, victim, TO_VICT);
          found = TRUE;
        }
        if(skill->miss_room && skill->miss_room[0] != '\0')
        {
          if(strcmp(skill->miss_room, "supress"))
            act(AT_WHITE, skill->miss_room, ch, NULL, victim, TO_NOTVICT);
          found = TRUE;
        }
        if(found)
        { /* miss message already sent */
          if(was_in_room)
          {
            char_from_room(ch);
            char_to_room(ch, was_in_room);
          }
          return;
        }
      }
      else
      {
        if(skill->hit_char && skill->hit_char[0] != '\0')
          act(AT_CYAN, skill->hit_char, ch, NULL, victim, TO_CHAR);
        if(skill->hit_vict && skill->hit_vict[0] != '\0')
          act(AT_DGREY, skill->hit_vict, ch, NULL, victim, TO_VICT);
        if(skill->hit_room && skill->hit_room[0] != '\0')
          act(AT_GREEN, skill->hit_room, ch, NULL, victim, TO_NOTVICT);
      }
    }
    else if(dt >= (unsigned int)TYPE_HIT && dt < (unsigned int)TYPE_HIT + sizeof(attack_table) / sizeof(attack_table[0]))
    {
      if(obj)
        attack = obj->short_descr;
      else
        attack = attack_table[dt - TYPE_HIT];
    }
    else
    {
      bug("Dam_message: bad dt %d from %s in %d.", dt, ch->name, ch->in_room->vnum);
      dt = TYPE_HIT;
      attack = attack_table[0];

    }
    snprintf(buf1, 256, "$n's %s %s $N %d %s for %d total damage%c", attack, vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf2, 256, "Your %s %s $N %d %s for %d total damage%c", attack, vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
    snprintf(buf3, 256, "$n's %s %s you %d %s for %d total damage%c", attack, vp, ch->success_attack, (ch->success_attack == 1) ? "time" : "times", ch->damage_amount, punct);
  }

  act(AT_GREEN, buf1, ch, NULL, victim, TO_NOTVICT);
  if(!gcflag && !IS_AFFECTED(victim, AFF_DISABLED))
    act(AT_CYAN, buf2, ch, NULL, victim, TO_CHAR);
  if(!gvflag)
    act(AT_DGREY, buf3, ch, NULL, victim, TO_VICT);

  if(was_in_room)
  {
    char_from_room(ch);
    char_to_room(ch, was_in_room);
  }
}

#ifndef dam_message
void dam_message(CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt)
{
  new_dam_message(ch, victim, dam, dt);
}
#endif

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

  one_argument(argument, arg);

  if(ch->position == POS_MEDITATING)
  {
    send_to_char("You are concentrating too much for that!\r\n", ch);
    return;
  }

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

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

  if(IS_AFFECTED(victim, AFF_UNHOLY_SPHERE))
  {
    send_to_char("You cannot get near their unholy sphere.\r\n", ch);
    return;
  }

  if(IS_AFFECTED(victim, AFF_ENTHRALLED))
  {
    xREMOVE_BIT(victim->affected_by, AFF_ENTHRALLED);
  }

  if(IS_AFFECTED(ch, AFF_HIDE) || IS_AFFECTED(ch, AFF_SNEAK))
  {
    affect_strip(ch, gsn_sneak);
    affect_strip(ch, gsn_hide);
    xREMOVE_BIT(ch->affected_by, AFF_HIDE);
    xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
  }

  if(IS_NPC(victim) && victim->morph)
  {
    send_to_char("This creature appears strange to you.  Look upon it more closely before attempting to kill it.", ch);
    return;
  }

  if(!IS_NPC(victim))
  {
/* Volk: Support for arena. */
    if(in_arena(ch) && in_arena(victim))
    {
      do_murder(ch, victim->name);
      return;
    }

    if(!xIS_SET(victim->act, PLR_KILLER) && !xIS_SET(victim->act, PLR_THIEF))
    {
      send_to_char("You must MURDER a player.\r\n", ch);
      return;
    }
  }

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

  if(is_safe(ch, victim, TRUE))
    return;

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

  if(ch->position == POS_FIGHTING || ch->position == POS_EVASIVE || ch->position == POS_DEFENSIVE || ch->position == POS_AGGRESSIVE || ch->position == POS_BERSERK)
  {
    send_to_char("You do the best you can!\r\n", ch);
    return;
  }
  if(xIS_SET(ch->act, PLR_BATTLE) && ch->Class == CLASS_MONK)
    send_to_char("!!SOUND(sound/brucelee.wav)\r\n", ch);

  WAIT_STATE(ch, 1 * PULSE_VIOLENCE);
  check_attacker(ch, victim);
  multi_hit(ch, victim, TYPE_UNDEFINED);
  return;
}

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

  one_argument(argument, arg);

  if(ch->position == POS_MEDITATING)
  {
    send_to_char("You are concentrating too much for that!\r\n", ch);
    return;
  }
  if(arg[0] == '\0')
  {
    send_to_char("Murder whom?\r\n", ch);
    return;
  }

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

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

  if(!IS_NPC(victim) && xIS_SET(ch->act, PLR_PKSAFE))
  {
    send_to_char("You cannot do that during this event!\r\n", ch);
    return;
  }

  if(IS_AFFECTED(victim, AFF_ENTHRALLED))
  {
    xREMOVE_BIT(victim->affected_by, AFF_ENTHRALLED);
  }

  if(IS_AFFECTED(victim, AFF_UNHOLY_SPHERE))
  {
    send_to_char("You cannot get near their unholy sphere.\r\n", ch);
    return;
  }

  if(is_safe(ch, victim, TRUE))
    return;

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

  if(ch->position == POS_FIGHTING || ch->position == POS_EVASIVE || ch->position == POS_DEFENSIVE || ch->position == POS_AGGRESSIVE || ch->position == POS_BERSERK)
  {
    send_to_char("You do the best you can!\r\n", ch);
    return;
  }
/* Volk: Going to put this in here. I don't feel it's fair if a player
 * gets shunted in the arena for accidentally being flagged PLR_NICE :P */
  if(in_arena(ch) && in_arena(victim))
  {
    multi_hit(ch, victim, TYPE_UNDEFINED);
    return;
  }

  if(!IS_NPC(victim))
  {
    char                    logbuf[MSL];

    snprintf(logbuf, MSL, "%s: murder %s.", ch->name, victim->name);
    log_string_plus(logbuf, LOG_NORMAL, ch->level);
  }

  WAIT_STATE(ch, 1 * PULSE_VIOLENCE);
  snprintf(buf, MSL, "Wartalk: %s 'Help! I am being attacked by %s!", victim->name, IS_NPC(ch) ? ch->short_descr : ch->name);
  echo_to_all(AT_RED, buf, ECHOTAR_ALL);

  if(!in_arena(ch) || !in_arena(victim))
    check_illegal_pk(ch, victim);

  if(xIS_SET(ch->act, PLR_BATTLE) && ch->Class == CLASS_MONK)
    send_to_char("!!SOUND(sound/brucelee.wav)\r\n", ch);

  check_attacker(ch, victim);
  multi_hit(ch, victim, TYPE_UNDEFINED);
  return;
}

/*
 * Check to see if the player is in an "Arena".
 */
bool in_arena(CHAR_DATA *ch)
{
  if(IS_SET(ch->in_room->room_flags, ROOM_ARENA))
    return TRUE;
  if(IS_SET(ch->in_room->area->flags, AFLAG_FREEKILL))
    return TRUE;
  if(ch->in_room->vnum >= arena_low_vnum && ch->in_room->vnum <= arena_high_vnum)
    return TRUE;
  if(!str_cmp(ch->in_room->area->filename, "arena.are"))
    return TRUE;

  return FALSE;
}

bool check_illegal_pk(CHAR_DATA *ch, CHAR_DATA *victim)
{
  char                    buf[MSL];
  char                    buf2[MSL];
  char                    logbuf[MSL];

  if(!IS_NPC(victim) && !IS_NPC(ch))
  {
    if((!IS_SET(victim->pcdata->flags, PCFLAG_DEADLY)
        || ch->level - victim->level > 10 || !IS_SET(ch->pcdata->flags, PCFLAG_DEADLY)) && !in_arena(ch) && ch != victim && !(IS_IMMORTAL(ch) && IS_IMMORTAL(victim)))
    {
      if(IS_NPC(ch))
        snprintf(buf, MSL, " (%s)", ch->name);
      if(IS_NPC(victim))
        snprintf(buf2, MSL, " (%s)", victim->name);
      snprintf(logbuf, MSL,
               "&p%s on %s%s in &W***&rILLEGAL PKILL&W*** &pattempt at %d",
               (lastplayercmd), (IS_NPC(victim) ? victim->short_descr : victim->name), (IS_NPC(victim) ? buf2 : ""), victim->in_room->vnum);
      last_pkroom = victim->in_room->vnum;
      log_string(logbuf);
      to_channel(logbuf, "Monitor", LEVEL_IMMORTAL);

/*
      snprintf(buf, MSL, "Wartalk: %s 'Help! I am being attacked by %s!", victim->name, IS_NPC(ch) ? ch->short_descr : ch->name);

 // Volk - do we need this more than the first check?? (pfft we'll use the one in do_murder)
      if(who_fighting(victim) != ch)
        echo_to_all(AT_RED, buf, ECHOTAR_ALL);
*/
      check_attacker(ch, victim);
      return TRUE;
    }
  }
  return FALSE;
}

//Adjusted flee to take much less exp. -Taon

void do_flee(CHAR_DATA *ch, char *argument)
{
  ROOM_INDEX_DATA        *was_in;
  ROOM_INDEX_DATA        *now_in;
  int                     attempt, los;
  short                   door;
  EXIT_DATA              *pexit;

  if(!who_fighting(ch))
  {
    if(ch->position == POS_FIGHTING || ch->position == POS_EVASIVE || ch->position == POS_DEFENSIVE || ch->position == POS_AGGRESSIVE || ch->position == POS_BERSERK)
    {
      if(ch->mount)
        set_position(ch, POS_MOUNTED);
      else
        set_position(ch, POS_STANDING);
    }
    send_to_char("You aren't fighting anyone.\r\n", ch);
    return;
  }
  if(IS_AFFECTED(ch, AFF_BERSERK))
  {
    send_to_char("Flee while berserking?  You aren't thinking very clearly...\r\n", ch);
    return;
  }
   


  if(IS_AFFECTED(ch, AFF_SNARE))
  {
    send_to_char("You cannot flee while ensnared!\r\n", ch);
    return;
  }
  if(IS_AFFECTED(ch, AFF_TANGLED))
  {
    send_to_char("You cannot flee while tangled.\r\n", ch);
    return;
  }
  if(ch->move <= 0)
  {
    send_to_char("You're too exhausted to flee from combat!\r\n", ch);
    return;
  }

  /*
   * No fleeing while more aggressive than standard or hurt. - Haus 
   */
  if(!IS_NPC(ch) && ch->position < POS_FIGHTING)
  {
    send_to_char("You can't flee in an aggressive stance...\r\n", ch);
    return;
  }

  if(IS_NPC(ch) && ch->position <= POS_SLEEPING)
    return;

  was_in = ch->in_room;
  for(attempt = 0; attempt < 8; attempt++)
  {
    door = number_door();

  if(xIS_SET(ch->act, PLR_AUTODOOR) && pexit )
  { 
    if(pexit != NULL && get_exit(ch->in_room, DIR_EAST) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open east");
    if(pexit != NULL && get_exit(ch->in_room, DIR_WEST) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open west");
    if(pexit != NULL && get_exit(ch->in_room, DIR_NORTH) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open north");
    if(pexit != NULL && get_exit(ch->in_room, DIR_SOUTH) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open south");
    if(pexit != NULL && get_exit(ch->in_room, DIR_NORTHEAST) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open ne");
    if(pexit != NULL && get_exit(ch->in_room, DIR_NORTHWEST) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open nw");
    if(pexit != NULL && get_exit(ch->in_room, DIR_SOUTHEAST) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open se");
    if(pexit != NULL && get_exit(ch->in_room, DIR_SOUTHWEST) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open sw");
    if(pexit != NULL &&get_exit(ch->in_room, DIR_DOWN) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open down");    
    if(pexit != NULL && get_exit(ch->in_room, DIR_UP) != NULL && pexit->to_room && IS_SET(pexit->exit_info, EX_CLOSED))
      interpret(ch, (char *)"open UP");
     }

    if((pexit = get_exit(was_in, door)) == NULL
       || !pexit->to_room
       || IS_SET(pexit->exit_info, EX_NOFLEE) || (IS_SET(pexit->exit_info, EX_CLOSED) && !IS_AFFECTED(ch, AFF_PASS_DOOR)) || (IS_NPC(ch) && IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB))) 
      continue;

    affect_strip(ch, gsn_sneak);
    xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
    if(ch->mount && ch->mount->fighting)
      stop_fighting(ch->mount, TRUE);
    move_char(ch, pexit, 0, FALSE);
    if((now_in = ch->in_room) == was_in)
      continue;
    ch->in_room = was_in;
    act(AT_FLEE, "$n flees head over heels!", ch, NULL, NULL, TO_ROOM);
    ch->in_room = now_in;
    act(AT_FLEE, "$n glances around for signs of pursuit.", ch, NULL, NULL, TO_ROOM);
    if(!IS_NPC(ch))
    {
      act(AT_FLEE, "You flee head over heels from combat!", ch, NULL, NULL, TO_CHAR);
      los = (int)((exp_level(ch, ch->level + 1) - exp_level(ch, ch->level)) / 8);

      if(ch->level < 20)
        los = 3500 + number_range(1, 100);

      // Capping loss -Taon
      if(los > 12400)
        los = 12400 + number_range(1, 100);

      if(xIS_SET(ch->act, PLR_EXTREME))
      {
        los *= 3;
      }

      if(!IS_AVATAR(ch) && !IS_DUALAVATAR(ch) && !IS_TRIAVATAR(ch))
        gain_exp(ch, 0 - los);
    }
    stop_fighting(ch, TRUE);
    return;
  }

  los = (int)((exp_level(ch, ch->level + 1) - exp_level(ch, ch->level)) / 7);

  if(ch->level < 20)
    los = 3500 + number_range(1, 100);

  // Capping loss -Taon
  if(los > 12400)
    los = 12400 + number_range(1, 100);

  if(xIS_SET(ch->act, PLR_EXTREME))
  {
    los *= 3;
  }



  act(AT_FLEE, "You attempt to flee from combat but can't break away!", ch, NULL, NULL, TO_CHAR);


  if(!IS_AVATAR(ch) && !IS_DUALAVATAR(ch) && !IS_TRIAVATAR(ch)
     && number_bits(1) == 0 && ch->fighting && ch->fighting->who && (!IS_NPC(ch->fighting->who) || !xIS_SET(ch->fighting->who->act, ACT_IMMORTAL)))
    gain_exp(ch, 0 - los);
  return;
}

/*
 * Make a corpse out of a character.
 */
void make_corpse(CHAR_DATA *ch, CHAR_DATA *killer)
{
  char                    buf[MSL], extra_buf[MSL];
  OBJ_DATA               *corpse;
  OBJ_DATA               *obj;
  OBJ_DATA               *obj_next;
  char                   *name;
  int                     x = 0;

  if(IS_NPC(ch))
  {
    if(ch->pIndexData->vnum == MOB_VNUM_ANIMATED_CORPSE || ch->pIndexData->vnum == MOB_VNUM_ANIMATED_SKEL)
    {
      act(AT_MAGIC, "$n disintegrates to the dust from whence it came.", ch, NULL, ch->short_descr, TO_ROOM);
      return;
    }
    name = ch->short_descr;
    if(!(corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0)))
    {
      bug("%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_CORPSE_NPC);
      return;
    }

    // extra desc?
    if(ch->description)
    {
      sprintf(extra_buf, "%s\r\n", ch->description);

      EXTRA_DESCR_DATA       *ed;

      CREATE(ed, EXTRA_DESCR_DATA, 1);

      LINK(ed, corpse->first_extradesc, corpse->last_extradesc, next, prev);
      ed->keyword = STRALLOC("cor corpse corp");
      ed->description = STRALLOC(extra_buf);
    }

    corpse->timer = 6;
    corpse->value[3] = 100;
    /*
     * if(IS_NPC(ch) && ch->slicevnum > 0 ) { corpse->serial = ch->slicevnum; }
     * if(IS_NPC(ch) && ch->pIndexData->slicevnum > 0 ) { corpse->pIndexData->serial
     * = ch->slicevnum; } 
     */

    /*
     * used. corpse->value[0] = (int)ch->pIndexData->vnum; corpse->value[1] = * * * *
     * * (int)ch->max_hit; 
     *//*
     * Using corpse cost to cheat, since corpses not sellable 
     */

    if(!IN_WILDERNESS(ch) && !IN_RIFT(ch))
    {
      if(ch->level > 1 && ch->level < 10)
        obj_to_obj(create_money(number_range(1, 50), CURR_COPPER), corpse);
      else if(ch->level > 9 && ch->level < 20)
        obj_to_obj(create_money(number_range(1, 40), CURR_BRONZE), corpse);
      else if(ch->level > 19 && ch->level < 60)
        obj_to_obj(create_money(number_range(1, 25), CURR_SILVER), corpse);
      else if(ch->level > 59 && ch->level < 100)
        obj_to_obj(create_money(number_range(1, 20), CURR_GOLD), corpse);

    }

    corpse->cost = (-(int)ch->pIndexData->vnum);
    corpse->currtype = DEFAULT_CURR;
    corpse->weight = 30;
    if(corpse->weight < 5)
      corpse->weight = number_range(20, 30);
  }
  else
  {
    name = ch->name;
    if(!(corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0)))
    {
      bug("%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_CORPSE_PC);
      return;
    }
    corpse->value[5] = 0;
    if(in_arena(ch))
      corpse->timer = 0;
    else
      corpse->timer = 40;
    corpse->value[2] = (int)(corpse->timer / 8);
    corpse->value[4] = ch->level;
    if(CAN_PKILL(ch) && sysdata.pk_loot)
      xSET_BIT(corpse->extra_flags, ITEM_CLANCORPSE);

    if(ch->level > 19)
    {
      short                   gold = 0, silver = 0, copper = 0, bronze = 0;

      if(GET_MONEY(ch, CURR_GOLD) > 0)
      {
        gold = GET_MONEY(ch, CURR_GOLD);
        GET_MONEY(ch, CURR_GOLD) = 0;
      }
      if(GET_MONEY(ch, CURR_SILVER) > 0)
      {
        silver = GET_MONEY(ch, CURR_SILVER);

        GET_MONEY(ch, CURR_SILVER) = 0;
      }
      if(GET_MONEY(ch, CURR_BRONZE) > 0)
      {
        bronze = GET_MONEY(ch, CURR_BRONZE);
        GET_MONEY(ch, CURR_BRONZE) = 0;
      }
      if(GET_MONEY(ch, CURR_COPPER) > 0)
      {
        copper = GET_MONEY(ch, CURR_COPPER);
        GET_MONEY(ch, CURR_COPPER) = 0;
      }
      if(gold > 0)
        obj_to_obj(create_money(gold, CURR_GOLD), corpse);
      if(silver > 0)
        obj_to_obj(create_money(silver, CURR_SILVER), corpse);
      if(bronze > 0)
        obj_to_obj(create_money(bronze, CURR_BRONZE), corpse);
      if(copper > 0)
        obj_to_obj(create_money(copper, CURR_COPPER), corpse);
    }

    /*
     * Pkill corpses get save timers, in ticks (approx 70 seconds)
     * This should be anough for the killer to type 'get all corpse'. 
     */
    if(!IS_NPC(ch) && !IS_NPC(killer))
      corpse->value[3] = 1;
    else
      corpse->value[3] = 0;
  }
  if(CAN_PKILL(ch) && CAN_PKILL(killer) && ch != killer)
  {
    snprintf(buf, MSL, "%s", killer->name);
    if(corpse->action_desc)
      STRFREE(corpse->action_desc);
    corpse->action_desc = STRALLOC(buf);
  }
  /*
   * Added corpse name - make locate easier , other skills 
   */
  snprintf(buf, MSL, "corpse %s", name);
  STRFREE(corpse->name);
  corpse->name = STRALLOC(buf);
  snprintf(buf, MSL, corpse->short_descr, name);
  STRFREE(corpse->short_descr);
  corpse->short_descr = STRALLOC(buf);
  snprintf(buf, MSL, corpse->description, name);
  STRFREE(corpse->description);
  corpse->description = STRALLOC(buf);
  for(obj = ch->first_carrying; obj; obj = obj_next)
  {
    obj_next = obj->next_content;
    obj_from_char(obj);
    if(IS_OBJ_STAT(obj, ITEM_INVENTORY))
      extract_obj(obj);
    else
      obj_to_obj(obj, corpse);
  }
  obj_to_room(corpse, ch->in_room);

  return;
}

void make_blood(CHAR_DATA *ch)
{
  OBJ_DATA               *obj;

  if(!(obj = create_object(get_obj_index(OBJ_VNUM_BLOOD), 0)))
  {
    bug("%s: couldn't create object vnum %d", __FUNCTION__, OBJ_VNUM_BLOOD);
    return;
  }
  obj->timer = number_chance(2, 4);
  obj->value[1] = number_range(3, UMIN(5, ch->level));
  obj_to_room(obj, ch->in_room);
}

PKILLED_DATA           *new_pkill(void)
{
  PKILLED_DATA           *pkill;

  CREATE(pkill, PKILLED_DATA, 1);
  pkill->name = NULL;
  pkill->timekilled = current_time;
  return pkill;
}

void free_pkill(PKILLED_DATA * pkill)
{
  if(!pkill)
    return;
  STRFREE(pkill->name);
  DISPOSE(pkill);
}

void free_all_pkills(CHAR_DATA *ch)
{
  PKILLED_DATA           *pkill, *pkill_next;

  if(!ch || !ch->pcdata)
    return;
  for(pkill = ch->pcdata->first_pkill; pkill; pkill = pkill_next)
  {
    pkill_next = pkill->next;
    UNLINK(pkill, ch->pcdata->first_pkill, ch->pcdata->last_pkill, next, prev);
    free_pkill(pkill);
  }
}

PKILLED_DATA           *has_pkilled(CHAR_DATA *ch, char *name)
{
  PKILLED_DATA           *pkill, *pkill_next;

  if(!ch || !ch->pcdata)
    return NULL;

  for(pkill = ch->pcdata->first_pkill; pkill; pkill = pkill_next)
  {
    pkill_next = pkill->next;

    /*
     * First lets check and see if 30 mins is up if so free it 
     */
    if((current_time - pkill->timekilled) >= 1800)
    {
      UNLINK(pkill, ch->pcdata->first_pkill, ch->pcdata->last_pkill, next, prev);
      free_pkill(pkill);
      continue;
    }

    /*
     * Ok lets see if this is the one we need to check 
     */
    if(!str_cmp(pkill->name, name))
      return pkill;
  }
  return NULL;
}

void add_pkill(CHAR_DATA *ch, CHAR_DATA *victim)
{
  PKILLED_DATA           *pkill;

  if(!ch || !victim || IS_NPC(ch) || IS_NPC(victim))
    return;
  /*
   * Previous kill lets update time (Note it should have been removed in check but just
   * incase 
   */
  if((pkill = has_pkilled(ch, victim->name)))
  {
    pkill->timekilled = current_time;
    return;
  }
  pkill = new_pkill();
  if(!pkill)
    return;
  pkill->name = STRALLOC(victim->name);
  pkill->timekilled = current_time;
  LINK(pkill, ch->pcdata->first_pkill, ch->pcdata->last_pkill, next, prev);
}

bool countpkill(CHAR_DATA *ch, CHAR_DATA *victim)
{
  if(ch->level >= 30)
    if((ch->level - victim->level > 10) || (victim->level - ch->level > 10))
      return FALSE;
  if(ch->level > 10 && ch->level < 30)
    if((ch->level - victim->level > 5) || (victim->level - ch->level > 5))
      return FALSE;
  if(ch->level <= 10)
    if((ch->level - victim->level > 3) || (victim->level - ch->level > 3))
      return FALSE;
  if(victim->level >= 30)
    if((ch->level - victim->level > 10) || (victim->level - ch->level > 10))
      return FALSE;
  if(victim->level > 10 && victim->level < 30)
    if((ch->level - victim->level > 5) || (victim->level - ch->level > 5))
      return FALSE;
  if(victim->level <= 10)
    if((ch->level - victim->level > 3) || (victim->level - ch->level > 3))
      return FALSE;
  return TRUE;
}