Beispiel #1
0
bool sp_damage( OBJ_DATA * obj, CHAR_DATA * ch, CHAR_DATA * victim, int dam, int type, int sn, bool show_msg )
{
    int ch_strong, ch_weak, ch_race, ch_suscept, ch_resist, vi_strong, vi_weak, vi_race, vi_suscept, vi_resist;
    float dam_modifier = 1.0;
    float tmp = 0;
    bool can_reflect = TRUE;
    bool can_absorb = TRUE;

    if ( victim == NULL )
        return FALSE;

    /*
     *  First, check caster's strengths and weaknesses.
     *
     */

    if ( IS_SET( type, NO_REFLECT ) )
    {
        REMOVE_BIT( type, NO_REFLECT );
        can_reflect = FALSE;
    }
    if ( IS_SET( type, NO_ABSORB ) )
    {
        REMOVE_BIT( type, NO_ABSORB );
        can_absorb = FALSE;
    }
    if ( obj == NULL )
    {
        if ( ( can_reflect )
                && ( skill_table[sn].target == TAR_CHAR_OFFENSIVE )
                && ( IS_AFFECTED( victim, AFF_CLOAK_REFLECTION ) )
                && ( ch != victim ) && ( number_percent(  ) < ( victim->get_level("psuedo") - 70 ) ) )
        {

            act( "@@N$n's @@lc@@el@@ro@@ya@@ak@@N glows brightly as $Nn's spell hits it, and the spell is reflected@@N!!", ch,
                 victim, NULL, TO_ROOM );
            act( "@@N$N's @@lc@@el@@ro@@ya@@ak@@N glows brightly, and reflects your spell back on you@@N!!", ch, NULL, victim,
                 TO_CHAR );
            act( "@@NYour @@lc@@el@@ro@@ya@@ak@@N glows brightly, and reflects the spell back on $N@@N!!!", victim, NULL, ch,
                 TO_CHAR );
            ( *skill_table[sn].spell_fun ) ( sn, 60, ch, ( void * )ch, NULL );
            return FALSE;

        }


        else if ( ( can_reflect )
                  && ( skill_table[sn].target == TAR_CHAR_OFFENSIVE )
                  && ( IS_AFFECTED( victim, AFF_CLOAK_ABSORPTION ) )
                  && ( ch != victim ) && ( number_percent(  ) < ( victim->get_level("psuedo") - 55 ) ) )
        {
            int mana;
            mana = mana_cost( ch, sn );
            victim->mana = UMIN( victim->max_mana, victim->mana + mana );

            act( "@@N$n's @@lcloak@@N glows brightly as $N's spell hits it, then fades@@N!!", victim, NULL, ch, TO_ROOM );
            act( "@@N$N's @@lcloak@@N glows brightly, and absorbs your spell@@N!!", ch, NULL, victim, TO_CHAR );
            act( "@@NYour @@lcloak@@N glows brightly, and absorbs $N's spell@@N!!!", victim, NULL, ch, TO_CHAR );
            return FALSE;
        }




        ch_strong = ( IS_NPC( ch ) ?
                      ( ( ( ch->race > 0 )
                          && ( ch->race < MAX_RACE ) ) ?
                        race_table[ch->race].strong_realms : ch->npcdata->strong_magic ) : race_table[ch->race].strong_realms );
        ch_resist = ( IS_NPC( ch ) ?
                      ( ( ( ch->race > 0 )
                          && ( ch->race < MAX_RACE ) ) ?
                        race_table[ch->race].resist_realms : ch->npcdata->resist ) : race_table[ch->race].resist_realms );
        ch_weak = ( IS_NPC( ch ) ?
                    ( ( ( ch->race > 0 )
                        && ( ch->race < MAX_RACE ) ) ?
                      race_table[ch->race].weak_realms : ch->npcdata->weak_magic ) : race_table[ch->race].weak_realms );
        ch_suscept = ( IS_NPC( ch ) ?
                       ( ( ( ch->race > 0 )
                           && ( ch->race < MAX_RACE ) ) ?
                         race_table[ch->race].suscept_realms : ch->npcdata->suscept ) : race_table[ch->race].suscept_realms );
        ch_race = ( IS_NPC( ch ) ?
                    ( ( ( ch->race > 0 )
                        && ( ch->race < MAX_RACE ) ) ?
                      race_table[ch->race].race_flags : ch->race_mods ) : race_table[ch->race].race_flags );

        if ( IS_SET( ch_strong, type ) )
        {
            dam_modifier += .35;
        }
        else if ( IS_SET( ch_weak, type ) )
        {
            dam_modifier -= .35;
        }

        if ( IS_SET( ch_race, RACE_MOD_STRONG_MAGIC ) )
        {
            dam_modifier += .25;
        }
        else if ( IS_SET( ch_race, RACE_MOD_WEAK_MAGIC ) )
        {
            dam_modifier -= .25;
        }
        else if ( IS_SET( ch_race, RACE_MOD_NO_MAGIC ) )
        {
            dam_modifier -= .50;
        }

        if ( ch->stance == STANCE_CASTER )
            dam_modifier += .10;
        else if ( ch->stance == STANCE_WIZARD )
            dam_modifier += .25;
        else if ( ch->stance == STANCE_MAGI )
            dam_modifier += .30;

        if ( ( !IS_NPC( ch ) ) && ( !IS_SET( type, REALM_MIND ) ) )
        {
            if ( ch->pcdata->learned[gsn_potency] > 0 )
            {
                dam_modifier += ( get_curr_int( ch ) * ch->pcdata->learned[gsn_potency] / 5000 );
            }

            if ( ch->pcdata->learned[gsn_thaumatergy] > 0 )
            {
                dam_modifier += ( get_curr_int( ch ) * ch->pcdata->learned[gsn_thaumatergy] / 2500 );
            }
        }
        if ( is_affected( ch, skill_lookup( "mystical focus" ) ) )
        {
            dam_modifier += .5;
        }
    }  /* obj == NULL */
    else if ( obj->carried_by != NULL )
    {
        ch = obj->carried_by;
    }
    else
    {
        snprintf( log_buf, (2 * MIL), "Error, object %s casting spell, but not carried by anyone.", obj->short_descr );
        monitor_chan( log_buf, MONITOR_DEBUG );
        return FALSE;
    }

    /*
     *  Next, the victim
     *
     */
    vi_strong = ( IS_NPC( victim ) ?
                  ( ( ( victim->race > 0 )
                      && ( victim->race < MAX_RACE ) ) ?
                    race_table[victim->race].strong_realms :
                    victim->npcdata->strong_magic ) : race_table[victim->race].strong_realms );
    vi_resist = ( IS_NPC( victim ) ?
                  ( ( ( victim->race > 0 )
                      && ( victim->race < MAX_RACE ) ) ?
                    race_table[victim->race].resist_realms : victim->npcdata->resist ) : race_table[victim->race].resist_realms );
    vi_weak = ( IS_NPC( victim ) ?
                ( ( ( victim->race > 0 )
                    && ( victim->race < MAX_RACE ) ) ?
                  race_table[victim->race].weak_realms : victim->npcdata->weak_magic ) : race_table[victim->race].weak_realms );
    vi_suscept = ( IS_NPC( victim ) ?
                   ( ( ( victim->race > 0 )
                       && ( victim->race < MAX_RACE ) ) ?
                     race_table[victim->race].suscept_realms : victim->npcdata->suscept ) : race_table[victim->race].suscept_realms );
    vi_race = ( IS_NPC( victim ) ?
                ( ( ( victim->race > 0 )
                    && ( victim->race < MAX_RACE ) ) ?
                  race_table[victim->race].race_flags : victim->race_mods ) : race_table[victim->race].race_flags );

    if ( IS_SET( vi_suscept, type ) )
    {
        dam_modifier += .45;
    }
    else if ( IS_SET( vi_resist, type ) )
    {
        dam_modifier -= .45;
    }

    else if ( IS_SET( vi_race, RACE_MOD_NO_MAGIC ) )
    {
        dam_modifier -= .25;
    }

    if ( MAGIC_STANCE( ch ) )
        dam_modifier += .15;

    if ( ( IS_SET( type, REALM_MIND ) ) && ( !HAS_MIND( victim ) ) )
        dam_modifier = 0.0;
    else if ( ( ( IS_SET( type, REALM_IMPACT ) )
                || ( IS_SET( type, REALM_ACID ) ) || ( IS_SET( type, REALM_GAS ) ) ) && ( !HAS_BODY( victim ) ) )
        dam_modifier = 0.0;

    if ( ( IS_SET( type, REALM_POISON ) ) && ( IS_SET( vi_race, RACE_MOD_IMMUNE_POISON ) ) )
        dam_modifier = 0.0;

    if ( ( IS_SET( type, REALM_DRAIN ) ) && ( IS_UNDEAD( victim ) ) )
        dam_modifier = 0.0;

    tmp = dam;
    tmp *= dam_modifier;

    if ( check_charm_aff(ch, CHARM_AFF_MAGE) )
        tmp *= ((100 + get_charm_bonus(ch, CHARM_AFF_MAGE)) / 100);

    dam = static_cast<int>(tmp);
    dam += number_range(static_cast<int>((dam * -0.10)), static_cast<int>((dam * 0.10))); /* Lets add a little randomness to things. --Kline */

    if ( victim != ch )
    {
        /*
         * Certain attacks are forbidden.
         * Most other attacks are returned.
         */
        if ( is_safe( ch, victim ) )
            return FALSE;
        if ( victim != ch->fighting )
            check_killer( ch, victim );

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

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


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

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

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

        /*
         * Damage modifiers.
         */

        if ( dam < 0 )
            dam = 0;

        /*
         * Stop up any residual loopholes.
         */
        if ( dam > sysdata.damcap )
        {
            char buf[MAX_STRING_LENGTH];
            snprintf( buf, MSL, "Spell: %d damage by %s, spell %s", dam, ( obj == NULL ) ? ch->get_name() : obj->short_descr, skill_table[sn].name );
            if ( ch->level < 82 )
                monitor_chan( buf, MONITOR_MAGIC );
            log_f( "%s", buf );
            dam = sysdata.damcap;
        }


        if ( ( show_msg ) && ( dam >= 0 ) )
            sp_dam_message( obj, ch, victim, dam, type, sn );

    }

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

    if ( !IS_NPC(ch) )
    {
        if ( dam > ch->pcdata->records->mdam_amt )
        {
            send_to_char("@@yYou've broken your magical damage record!@@N\r\n", ch);
            ch->pcdata->records->mdam_amt = dam;
            ch->pcdata->records->mdam_gsn = sn;
        }
    }

    if ( !IS_NPC( victim ) )
        check_adrenaline( victim, dam );

    if ( !IS_NPC( victim ) && IS_WOLF( victim ) && ( dam > 350 ) )
        do_rage( victim, "FORCE" );

    update_pos( victim );

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

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

            case POS_STUNNED:
                act( "$n is too stunned to do anything!", victim, NULL, NULL, TO_ROOM );
                send_to_char( "You are too stunned to do anything!\r\n", victim );
                break;

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

            default:
                if ( dam > victim->max_hit / 4 )
                    send_to_char( "That really did HURT!\r\n", victim );
                if ( victim->hit < victim->max_hit / 4 )
                    send_to_char( "You sure are BLEEDING!\r\n", victim );
                break;
        }
    }  /* end of if statement */
    /*
     * Sleep spells and extremely wounded folks.
     */
    if ( !IS_AWAKE( victim ) )
        stop_fighting( victim );

    /*
     * Payoff for killing things.
     */



    if ( victim->position == POS_DEAD && ( IS_NPC( victim ) || !IS_VAMP( victim ) || ( deathmatch ) ) )
    {
        group_gain( ch, victim );

        /*
         * Sort out kill counts.....
         */
        if ( !IS_NPC( ch ) )
        {
            if ( !IS_NPC( victim ) )
                ch->pcdata->records->pk++;
            else
                ch->pcdata->records->mk++;
        }

        if ( !IS_NPC( victim ) )
        {
            if ( !IS_NPC( ch ) )
                victim->pcdata->records->pd++;
            else
                victim->pcdata->records->md++;
        }

        if ( !IS_NPC( victim ) || victim->act.test(ACT_INTELLIGENT) )
        {


            snprintf( log_buf, (2 * MIL), "%s killed by %s at %d", victim->get_name(), ch->get_name(), victim->in_room->vnum );
            log_string( log_buf );

            notify( log_buf, 82 );

            /*
             * As level gain is no longer automatic, a dead char loses
             * * 1/2 their gained exp.  -S-
             * * Fixed my bug here too, hehe!
             */

            if ( victim->exp > 0 )
            {
                int lose = (victim->exp / 2);
                lose *= -1;
                victim->gain_exp(lose);
            }

        }

        if ( IS_NPC( ch ) )
            raw_kill( victim, "" );
        else
        {
            char name_buf[MAX_STRING_LENGTH];
            snprintf( name_buf, MSL, "%s", ch->name.c_str() );
            raw_kill( victim, name_buf );
        }

        if ( deathmatch && !IS_NPC( victim ) )
            do_quit( victim, "" );

        if ( IS_NPC( ch ) && IS_NPC( victim ) && ch->act.test(ACT_INTELLIGENT) )
        {
            do_get( ch, "all corpse" );
            do_sacrifice( ch, "corpse" );
        }

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

            if ( ch->act.test(ACT_AUTOSAC) )
                do_sacrifice( ch, "corpse" );
        }

        return FALSE;
    }

    if ( victim == ch )
        return TRUE;

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

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

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

    return TRUE;

}
Beispiel #2
0
/*
 * Alert: As of bpl14, this function returns the following codes:
 *	< 0	Victim died.
 *	= 0	No damage.
 *	> 0	How much damage done.
 */
int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype)
{
  if (GET_POS(victim) <= POS_DEAD) {
    /* This is "normal"-ish now with delayed extraction. -gg 3/15/2001 */
    if (PLR_FLAGGED(victim, PLR_NOTDEADYET) || MOB_FLAGGED(victim, MOB_NOTDEADYET))
      return (-1);

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

  /* peaceful rooms */
  if (ch != victim && ROOM_FLAGGED(IN_ROOM(ch), ROOM_PEACEFUL)) {
    send_to_char(ch, "This room just has such a peaceful, easy feeling...\r\n");
    return (0);
  }

  /* shopkeeper protection */
  if (!ok_damage_shopkeeper(ch, victim))
    return (0);

  /* You can't damage an immortal! */
  if (!IS_NPC(victim) && (GET_LEVEL(victim) >= LVL_IMMORT))
    dam = 0;

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

    /* Start the victim fighting the attacker */
    if (GET_POS(victim) > POS_STUNNED && (FIGHTING(victim) == NULL)) {
      set_fighting(victim, ch);
      if (MOB_FLAGGED(victim, MOB_MEMORY) && !IS_NPC(ch))
	remember(victim, ch);
    }
  }

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

  /* If the attacker is invisible, he becomes visible */
  if (AFF_FLAGGED(ch, AFF_INVISIBLE | AFF_HIDE))
    appear(ch);

  /* Cut damage in half if victim has sanct, to a minimum 1 */
  if (AFF_FLAGGED(victim, AFF_SANCTUARY) && dam >= 2)
    dam /= 2;

  /* Check for PK if this is not a PK MUD */
  if (!pk_allowed) {
    check_killer(ch, victim);
    if (PLR_FLAGGED(ch, PLR_KILLER) && (ch != victim))
      dam = 0;
  }

  /* Set the maximum damage per round and subtract the hit points */
  dam = MAX(MIN(dam, 100), 0);
  GET_HIT(victim) -= dam;

  /* Gain exp for the hit */
  if (ch != victim)
    gain_exp(ch, GET_LEVEL(victim) * dam);

  update_pos(victim);

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

  /* Use send_to_char -- act() doesn't send message if you are DEAD. */
  switch (GET_POS(victim)) {
  case POS_MORTALLYW:
    act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, CommTarget::TO_ROOM);
    send_to_char(victim, "You are mortally wounded, and will die soon, if not aided.\r\n");
    break;
  case POS_INCAP:
    act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, CommTarget::TO_ROOM);
    send_to_char(victim, "You are incapacitated an will slowly die, if not aided.\r\n");
    break;
  case POS_STUNNED:
    act("$n is stunned, but will probably regain consciousness again.", TRUE, victim, 0, 0, CommTarget::TO_ROOM);
    send_to_char(victim, "You're stunned, but will probably regain consciousness again.\r\n");
    break;
  case POS_DEAD:
    act("$n is dead!  R.I.P.", FALSE, victim, 0, 0, CommTarget::TO_ROOM);
    send_to_char(victim, "You are dead!  Sorry...\r\n");
    break;

  default:			/* >= POSITION SLEEPING */
    if (dam > (GET_MAX_HIT(victim) / 4))
      send_to_char(victim, "That really did HURT!\r\n");

    if (GET_HIT(victim) < (GET_MAX_HIT(victim) / 4)) {
      send_to_char(victim, "%sYou wish that your wounds would stop BLEEDING so much!%s\r\n",
		CCRED(victim, C_SPR), CCNRM(victim, C_SPR));
      if (ch != victim && MOB_FLAGGED(victim, MOB_WIMPY))
	do_flee(victim, NULL, 0, 0);
    }
    if (!IS_NPC(victim) && GET_WIMP_LEV(victim) && (victim != ch) &&
	GET_HIT(victim) < GET_WIMP_LEV(victim) && GET_HIT(victim) > 0) {
      send_to_char(victim, "You wimp out, and attempt to flee!\r\n");
      do_flee(victim, NULL, 0, 0);
    }
    break;
  }

  /* Help out poor linkless people who are attacked */
  if (!IS_NPC(victim) && !(victim->desc) && GET_POS(victim) > POS_STUNNED) {
    do_flee(victim, NULL, 0, 0);
    if (!FIGHTING(victim)) {
      act("$n is rescued by divine forces.", FALSE, victim, 0, 0, CommTarget::TO_ROOM);
      GET_WAS_IN(victim) = IN_ROOM(victim);
      char_from_room(victim);
      char_to_room(victim, 0);
    }
  }

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

  /* Uh oh.  Victim died. */
  if (GET_POS(victim) == POS_DEAD) {
    if (ch != victim && (IS_NPC(victim) || victim->desc)) {
      if (AFF_FLAGGED(ch, AFF_GROUP))
	group_gain(ch, victim);
      else
        solo_gain(ch, victim);
    }

    if (!IS_NPC(victim)) {
      mudlog(BRF, LVL_IMMORT, TRUE, "%s killed by %s at %s", GET_NAME(victim), GET_NAME(ch), world[IN_ROOM(victim)].name);
      if (MOB_FLAGGED(ch, MOB_MEMORY))
	forget(ch, victim);
    }
    die(victim);
    return (-1);
  }
  return (dam);
}
Beispiel #3
0
void damage(struct char_data *ch, struct char_data *victim,
            int dam, int attacktype)
{
	char buf[MAX_STRING_LENGTH];
	struct message_type *messages;
	int i,j,nr,max_hit,exp;

	int hit_limit(struct char_data *ch);

	assert(GET_POS(victim) > POSITION_DEAD);

	if ((GET_LEVEL(victim)>20) && !IS_NPC(victim)) /* You can't damage an immortal! */
		dam=0;
		
	if (victim != ch) {
		if (GET_POS(victim) > POSITION_STUNNED) {
			if (!(victim->specials.fighting))
				set_fighting(victim, ch);
			GET_POS(victim) = POSITION_FIGHTING;
		}

		if (GET_POS(ch) > POSITION_STUNNED) {
			if (!(ch->specials.fighting))
				set_fighting(ch, victim);

			if (IS_NPC(ch) && IS_NPC(victim) &&
          victim->master &&
			    !number(0,10) && IS_AFFECTED(victim, AFF_CHARM) &&
			    (victim->master->in_room == ch->in_room)) {
				if (ch->specials.fighting)
					stop_fighting(ch);
				hit(ch, victim->master, TYPE_UNDEFINED);
				return;
			}
		}
	}

	if (victim->master == ch)
		stop_follower(victim);
			
	if (IS_AFFECTED(ch, AFF_INVISIBLE))
		appear(ch);

	if (IS_AFFECTED(victim, AFF_SANCTUARY))
		dam = MIN(dam, 18);  /* Max 18 damage when sanctuary */

	dam=MIN(dam,100);

	dam=MAX(dam,0);

	GET_HIT(victim)-=dam;

	if (ch != victim)
		gain_exp(ch,GET_LEVEL(victim)*dam);

	update_pos(victim);


	if ((attacktype >= TYPE_HIT) && (attacktype <= TYPE_SLASH)) {
		if (!ch->equipment[WIELD]) {
			dam_message(dam, ch, victim, TYPE_HIT);
		} else {
			dam_message(dam, ch, victim, attacktype);
		}
	} else {

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

			if (!IS_NPC(victim) && (GET_LEVEL(victim) > 20)) {
				act(messages->god_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR);
				act(messages->god_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT);
				act(messages->god_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT);
			} else if (dam != 0) {
				if (GET_POS(victim) == POSITION_DEAD) {
					act(messages->die_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR);
					act(messages->die_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT);
					act(messages->die_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT);
				} else {
					act(messages->hit_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR);
					act(messages->hit_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT);
					act(messages->hit_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT);
				}
			} else { /* Dam == 0 */
				act(messages->miss_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR);
				act(messages->miss_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT);
				act(messages->miss_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT);
			}
		}
	}
	}
	switch (GET_POS(victim)) {
		case POSITION_MORTALLYW:
			act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, TO_ROOM);
			act("You are mortally wounded, and will die soon, if not aided.", FALSE, victim, 0, 0, TO_CHAR);
			break;
		case POSITION_INCAP:
			act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, TO_ROOM);
			act("You are incapacitated an will slowly die, if not aided.", FALSE, victim, 0, 0, TO_CHAR);
			break;
		case POSITION_STUNNED:
			act("$n is stunned, but will probably regain conscience again.", TRUE, victim, 0, 0, TO_ROOM);
			act("You're stunned, but will probably regain conscience again.", FALSE, victim, 0, 0, TO_CHAR);
			break;
		case POSITION_DEAD:
			act("$n is dead! R.I.P.", TRUE, victim, 0, 0, TO_ROOM);
			act("You are dead!  Sorry...", FALSE, victim, 0, 0, TO_CHAR);
			break;

		default:  /* >= POSITION SLEEPING */

			max_hit=hit_limit(victim);

			if (dam > (max_hit/5))
				act("That Really did HURT!",FALSE, victim, 0, 0, TO_CHAR);

			if (GET_HIT(victim) < (max_hit/5)) {

				act("You wish that your wounds would stop BLEEDING that much!",FALSE,victim,0,0,TO_CHAR);
				if (IS_NPC(victim))
					if (IS_SET(victim->specials.act, ACT_WIMPY))
						do_flee(victim, "", 0);
			}
			break;		
	}

	if (!IS_NPC(victim) && !(victim->desc)) {
		do_flee(victim, "", 0);
		if (!victim->specials.fighting) {
			act("$n is rescued by divine forces.", FALSE, victim, 0, 0, TO_ROOM);
			victim->specials.was_in_room = victim->in_room;
			char_from_room(victim);
			char_to_room(victim, 0);
		}
	}

	if (GET_POS(victim) < POSITION_STUNNED)
		if (ch->specials.fighting == victim)
			stop_fighting(ch);

	if (!AWAKE(victim))
		if (victim->specials.fighting)
			stop_fighting(victim);

	if (GET_POS(victim) == POSITION_DEAD) {
		if (IS_NPC(victim) || victim->desc)
			if (IS_AFFECTED(ch, AFF_GROUP)) {
					group_gain(ch, victim);
			} else {
				/* Calculate level-difference bonus */
				exp = GET_EXP(victim)/3;
				if (IS_NPC(ch))
					exp += (exp*MIN(4, (GET_LEVEL(victim) - GET_LEVEL(ch))))>>3;
				else
					exp += (exp*MIN(8, (GET_LEVEL(victim) - GET_LEVEL(ch))))>>3;
				exp = MAX(exp, 1);
				gain_exp(ch, exp);
				change_alignment(ch, victim);
			}
		if (!IS_NPC(victim)) {
			sprintf(buf, "%s killed by %s at %s",
				GET_NAME(victim),
				(IS_NPC(ch) ? ch->player.short_descr : GET_NAME(ch)),
				world[victim->in_room].name);
			log(buf);
		}
		die(victim);
	}