/
mudtem/
mudtem/area/scripts/
mudtem/bin/
mudtem/log/
mudtem/player/
mudtem/slang/autoconf/
mudtem/slang/doc/
mudtem/slang/doc/OLD/help/
mudtem/slang/doc/internal/
mudtem/slang/doc/text/
mudtem/slang/doc/tm/tools/
mudtem/slang/examples/
mudtem/slang/modules/
mudtem/slang/slsh/
mudtem/slang/slsh/lib/
mudtem/slang/slsh/scripts/
mudtem/slang/src/mkfiles/
mudtem/slang/src/util/
mudtem/src/CVS/
mudtem/src/include/
mudtem/src/include/CVS/
mudtem/src/var/CVS/
FRetVal	damage		args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam,
			        int dt, int class, bool show ) );

/*
 * Inflict damage from a hit.
 */
FRetVal damage(CHAR_DATA *ch,CHAR_DATA *victim,int dam,int dt,int dam_type,
	    bool show) 
{
    bool immune;
    OBJ_DATA *corpse;
    FIGHT_DATA * fd;

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

    /*
     * Stop up any residual loopholes.
     */
    if ( dam > 1200 && dt >= TYPE_HIT)
    {
	bugf( "Damage: %d, maximo 1200, char %s, victima %s, vnum %d.",
		dam, ch->name, victim->name, CHARVNUM(victim) );
	dam = 1200;
	if (!IS_IMMORTAL(ch))
	{
	    OBJ_DATA *obj;
	    obj = get_eq_char( ch, WEAR_WIELD );
	    send_to_char("Realmente, no debieras hacer trampas.\n\r",ch);
	    if (obj != NULL)
	    {
		bugf( "Obj %s, vnum %d.", obj->name, obj->pIndexData->vnum );
		extract_obj(obj);
	    }
	}
    }

    /* damage reduction */
    if ( dam > 35)
	dam = (dam - 35)*0.5 + 35;
    if ( dam > 80)
	dam = (dam - 80)*0.5 + 80;

    if ( !IS_NPC(ch) )
       	dam *= pcdam / 100;
    else
	dam *= mobdam / 100;

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

	if ( victim->position > POS_STUNNED )
	{
	    if ( victim->fighting == NULL )
 	    {
		set_fighting( victim, ch );
 		if ( IS_NPC( victim ) && HAS_TRIGGER( victim, TRIG_KILL ) )
		    mp_percent_trigger( victim, ch, NULL, NULL, TRIG_KILL );
	    }
	    if (victim->timer <= 4)
	    	victim->position = POS_FIGHTING;
	}

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

	    /*
	     * If victim is charmed, ch might attack victim's master.
	     taken out by Russ! */
/*
	    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, FALSE );
		multi_hit( ch, victim->master, TYPE_UNDEFINED );
		return FAIL;
	    }
*/
	}

	/*
	 * 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 );
	affect_strip( ch, gsn_predinvis );
	REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
	act( "$n aparece en esta realidad.", ch, NULL, NULL, TO_ROOM );
    }

    /*
     * Damage modifiers.
     */

    if ( dam > 1 && !IS_NPC(victim) 
    &&   victim->pcdata->condition[COND_DRUNK]  > 10 )
	dam = 9 * dam / 10;

    if ( dam > 1 && IS_AFFECTED(victim, AFF_SANCTUARY) && ch != victim )
	dam = 3 * dam / 4; /* /2 */

    if ( dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch) )
    ||		     (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch) )))
	dam -= dam / 4;

    immune = FALSE;

    /*
     * Check for parry, and dodge.
     */
    if ( dt >= TYPE_HIT && ch != victim)
    {
        if ( check_parry( ch, victim ) )
	    return FAIL;
	if ( check_dodge( ch, victim ) )
	    return FAIL;
	if ( check_shield_block(ch,victim))
	    return FAIL;
    }

    switch(check_immune(victim,dam_type))
    {
	case(IS_IMMUNE):
	    immune = TRUE;
	    dam = 0;
	    break;
	case(IS_RESISTANT):
	    dam -= dam/4; /* 3 */
	    break;
	case(IS_VULNERABLE):
	    dam += dam/4; /* 2 */
	    break;
    }

    if (show)
    	dam_message( ch, victim, dam, dt, immune );

    if (dam < 1)
	return FAIL;

    /*
     * Hurt the victim.
     * Inform the victim of his new state.
     */
    if ( ch != victim )
    {
    	fd = fdata_lookup( ch, victim->id );

    	if ( !fd )
		fd = give_fd( ch, victim );
    	else
    		fd->dam += dam;
    }

    victim->hit -= dam;
    if ( !IS_NPC(victim) && victim->hit < 1 )
    {
    	if ( victim->level >= LEVEL_IMMORTAL
	||   (ch == victim && EN_ARENA(victim))
	||   IS_SET(victim->in_room->room_flags, ROOM_PROTOTIPO) )
		victim->hit = 1;
    }

    update_pos( victim );

    switch( victim->position )
    {
    case POS_MORTAL:
	act( "$n esta mortalmente herido, y morira pronto, si no es ayudado.",
	    victim, NULL, NULL, TO_ROOM );
	send_to_char( 
	    "Estas mortalmente herido, y moriras pronto, si no te ayudan.\n\r",
	    victim );
	break;

    case POS_INCAP:
	act( "$n esta incapacitado y morira lentamente, si no es ayudado.",
	    victim, NULL, NULL, TO_ROOM );
	send_to_char(
	    "Estas incapacitado y moriras lentamente, si no te ayudan.\n\r",
	    victim );
	break;

    case POS_STUNNED:
	act( "$n esta inconsciente, pero probablemente se recuperara.",
	    victim, NULL, NULL, TO_ROOM );
	send_to_char("Estas inconsciente, pero probablemente te recuperaras.\n\r",
	    victim );
	break;

    case POS_DEAD:
	act( "$n ha #BMUERTO#b!!", victim, 0, 0, TO_ROOM );
	send_to_char( "Has #BMUERTO#b!!\n\r\n\r", victim );
	break;

    default:
	if ( dam > victim->max_hit / 4 )
	    send_to_char( "Eso realmente #BDOLIO#b!\n\r", victim );
	if ( victim->hit < victim->max_hit / 4 )
	    send_to_char( "Seguramente estas #3SANGRANDO#n!\n\r", victim );
	break;
    }

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

    /*
     * Payoff for killing things.
     */
    if ( victim->position == POS_DEAD )
    {
	if ( !IS_NPC(victim) && EN_ARENA(victim) )
	{
		check_arena(ch, victim);
		return victdead;
	}

	if ( !EN_ARENA(victim) )
		group_gain( ch, victim );

	if ( !IS_NPC(victim) )
	{
	    sprintf( log_buf, "%s murio a manos de %s en %d",
		victim->name,
		(IS_NPC(ch) ? ch->short_descr : ch->name),
		ch->in_room->vnum );
	    log_string( log_buf );

	    /*
	     * Dying penalty:
	     * 2/3 way back to previous level.
	     */
	    if ( victim->exp > EXP_NIVEL(victim,victim->level-1) + 2*EXP_NIVEL(victim,1)/3 )
	    {
		int xp_lose;

		xp_lose = (EXP_NIVEL(victim,victim->level - 1) + EXP_NIVEL(victim,1)/3 - victim->exp) / 2 + 50;
		xp_lose = UMAX(-1 * exp_per_level(victim,victim->pcdata->points), xp_lose);

		if ( xp_lose < 0 )
			gain_exp( victim, xp_lose );
	    }
	}

        sprintf( log_buf, "%s got toasted by %s at %s [room %d]",
            (IS_NPC(victim) ? victim->short_descr : victim->name),
            (IS_NPC(ch) ? ch->short_descr : ch->name),
            ch->in_room->name, ch->in_room->vnum);

        if (IS_NPC(victim))
            wiznet(log_buf,NULL,NULL,WIZ_MOBDEATHS,0,0);
        else
            wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0);

	if ( !IS_NPC(ch) && is_clan(ch) )
	{
		if ( IS_NPC(victim) )
			get_clan_table(ch->clan)->mkills++;
		else
			get_clan_table(ch->clan)->pkills++;
	}
			
	if ( !IS_NPC(victim) && is_clan(victim) )
	{
		if ( IS_NPC(ch) )
			get_clan_table(victim->clan)->mdeaths++;
		else
			get_clan_table(victim->clan)->pdeaths++;
	}

	if ( !IS_NPC(ch) && !IS_NPC(victim) && is_clan(ch)
	  && is_clan(victim) && is_same_clan(ch, victim) )
	{
		get_clan_table(victim->clan)->illpkills++;
		if ( ch->pcdata->clan_status < victim->pcdata->clan_status )
		{
			int temp = ch->pcdata->clan_status;
			char buf[MIL];

			ch->pcdata->clan_status = victim->pcdata->clan_status;
			victim->pcdata->clan_status = temp;
			sprintf( buf, "Ahora eres #B%s#b del clan #B%s#b!\n\r",
				lookup_clan_status(ch->pcdata->clan_status),
				get_clan_table(ch->clan)->name );
			send_to_char( buf, ch );
			sprintf( buf, "Ahora eres #B%s#b del clan #B%s#b!\n\r",
				lookup_clan_status(victim->pcdata->clan_status),
				get_clan_table(ch->clan)->name );
			send_to_char( buf, victim );
			REMOVE_BIT( ch->act, PLR_KILLER );
			REMOVE_BIT( victim->act, PLR_KILLER );
		}
	}

	/*
	 * Death trigger
	 */
	if ( IS_NPC( victim ) && HAS_TRIGGER( victim, TRIG_DEATH) )
	{
	    victim->position = POS_STANDING;
	    mp_percent_trigger( victim, ch, NULL, NULL, TRIG_DEATH );
	}

        /* dump the flags */
        if (ch != victim
	&& !IS_NPC(ch)
        && !IS_NPC(victim)
        && (!is_clan(ch)
         || !is_clan(victim)
         || ( is_clan(ch) && is_clan(victim) && !is_same_clan(ch,victim) ) ) )
        {
            if (IS_SET(victim->act,PLR_KILLER))
                REMOVE_BIT(victim->act,PLR_KILLER);
	    if (IS_SET(victim->act,PLR_THIEF))
                REMOVE_BIT(victim->act,PLR_THIEF);
        }

        raw_kill ( ch, victim, dam_type );
         
        /* RT new auto commands */

	if (!IS_NPC(ch)
	&&  (corpse = get_obj_list(ch,"corpse",ch->in_room->contents)) != NULL
	&&  corpse->item_type == ITEM_CORPSE_NPC && can_see_obj(ch,corpse))
	{
	    OBJ_DATA *coins;

	    if ( IS_SET(ch->act, PLR_AUTOLOOT)
		&& corpse->contains) /* not empty */
		do_get( ch, "all corpse" );

 	    if (IS_SET(ch->act,PLR_AUTOGOLD)
		&& corpse->contains  && /* exists and not empty */
		!IS_SET(ch->act,PLR_AUTOLOOT))
		if ((coins = get_obj_list(ch,"gcash",corpse->contains))
		     != NULL)
	      	    do_get(ch, "all.gcash corpse");
            
	    if ( IS_SET(ch->act, PLR_AUTOSAC) )
	    {
		if ( IS_SET(ch->act,PLR_AUTOLOOT) && corpse->contains)
			return victdead;  /* leave if corpse has treasure */
		else
			do_sacrifice( ch, "corpse" );
	    }
	}

	return victdead;
    }

    if ( victim == ch )
	return OK;

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

    /*
     * Wimp out?
     */
    if ( IS_NPC(victim) && dam > 0 && victim->wait < PULSE_VIOLENCE / 2)
    {
	if ( ( IS_SET(victim->act, ACT_WIMPY) && number_bits( 2 ) == 0
	&&   victim->hit < victim->max_hit / 4)
	||   ( 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 < PULSE_VIOLENCE / 2 )
	{
	    do_flee( victim, "" );
	}

    tail_chain( );
    return OK;
}

bool	obj_damage	args( ( OBJ_DATA *obj, CHAR_DATA *victim, int dam,
				int dt, int class, bool show ) );

/*
 * Inflict damage from a hit.
 */
bool obj_damage(OBJ_DATA *obj,CHAR_DATA *victim,int dam,int dt,int dam_type,
	    bool show) 
{
    char buf[MAX_STRING_LENGTH];
    bool immune;

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

    /*
     * Stop up any residual loopholes.
     */
    if ( dam > 1200 && dt >= TYPE_HIT)
    {
	bug( "Damage: %d: maximo es 1200 puntos!", dam );
	sprintf( buf, "Objeto %s.", obj->short_descr );
	bug( buf, 0 );
	dam = 1200;
    }

    
    /* damage reduction */
    if ( dam > 35)
	dam = (dam - 35)/2 + 35;
    if ( dam > 80)
	dam = (dam - 80)/2 + 80; 

    /*
     * Damage modifiers.
     */

    if ( dam > 1 && !IS_NPC(victim) 
    &&   victim->pcdata->condition[COND_DRUNK]  > 10 )
	dam = 9 * dam / 10;

    if ( dam > 1 && IS_AFFECTED(victim, AFF_SANCTUARY) )
	dam /= 2;

    immune = FALSE;

    switch(check_immune(victim,dam_type))
    {
	case(IS_IMMUNE):
	    immune = TRUE;
	    dam = 0;
	    break;
	case(IS_RESISTANT):	
	    dam -= dam/3;
	    break;
	case(IS_VULNERABLE):
	    dam += dam/2;
	    break;
    }

    if (show)
    	dam_obj_message( obj, victim, dam, dt, immune );

    if (dam == 0)
	return FALSE;

    /*
     * Hurt the victim.
     * Inform the victim of his new state.
     */
    victim->hit -= dam;
    if ( !IS_NPC(victim)
    &&   victim->level >= LEVEL_IMMORTAL
    &&   victim->hit < 1 )
	victim->hit = 1;
    update_pos( victim );

    switch( victim->position )
    {
    case POS_MORTAL:
	act( "$n esta mortalmente herido, y morira pronto, si no es ayudado.",
	    victim, NULL, NULL, TO_ROOM );
	send_to_char( 
	    "Estas mortalmente herido, y moriras pronto, si no te ayudan.\n\r",
	    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.\n\r",
	    victim );
	break;

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

    case POS_DEAD:
	act( "$n ha #BMUERTO#b!!", victim, 0, 0, TO_ROOM );
	send_to_char( "Has #BMUERTO#b!!\n\r\n\r", victim );
	break;

    default:
	if ( dam > victim->max_hit / 4 )
	    send_to_char( "Eso realmente #BDOLIO#b!\n\r", victim );
	if ( victim->hit < victim->max_hit / 4 )
	    send_to_char( "Seguramente estas #3SANGRANDO#n!\n\r", victim );
	break;
    }

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

    /*
     * Payoff for killing things.
     */
    if ( victim->position == POS_DEAD )
    {
	if ( !IS_NPC(victim) )
	{
	    sprintf( log_buf, "%s murio a manos de %s (obj)",
		victim->name,
		obj->short_descr );
	    log_string( log_buf );

	    /*
	     * Dying penalty:
	     * 2/3 way back to previous level.
	     */
	    if ( victim->exp > EXP_NIVEL(victim,victim->level-1) + 2*EXP_NIVEL(victim,1)/3 )
	    {
		int xp_lose;

		xp_lose = (EXP_NIVEL(victim,victim->level - 1) + EXP_NIVEL(victim,1)/2 - victim->exp) / 2 + 50;
		gain_exp( victim, UMAX( -1 * exp_per_level(victim,victim->pcdata->points), xp_lose) );
	    }
	}

        sprintf( log_buf, "%s got toasted by %s (obj)",
            (IS_NPC(victim) ? victim->short_descr : victim->name),
            obj->short_descr);

        if (IS_NPC(victim))
            wiznet(log_buf,NULL,NULL,WIZ_MOBDEATHS,0,0);
        else
            wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0);

        raw_kill ( NULL, victim, dam_type );
         
	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;
	}
    }

    tail_chain( );
    return TRUE;
}

void dam_obj_message( OBJ_DATA *obj, CHAR_DATA *victim,int dam,int dt,bool immune )
{
    char buf1[256], buf3[256];
    const char *vs;
    const char *vp;
    const char *attack;
    char punct;

    if (obj == NULL || victim == NULL)
	return;

	 if ( dam ==   0 ) { vs = "yerra";	vp = "yerra";		}
    else if ( dam <=   4 ) { vs = "rozas";	vp = "roza";		}
    else if ( dam <=   8 ) { vs = "rasgunas";	vp = "rasguna";		}
    else if ( dam <=  12 ) { vs = "aranas";	vp = "arana";		}
    else if ( dam <=  16 ) { vs = "lastimas";	vp = "lastima";		}
    else if ( dam <=  20 ) { vs = "hieres";	vp = "hiere";		}
    else if ( dam <=  24 ) { vs = "danas";       vp = "dana";		}
    else if ( dam <=  28 ) { vs = "diezmas";	vp = "diezma";		}
    else if ( dam <=  32 ) { vs = "rompes";	vp = "rompe";		}
    else if ( dam <=  36 ) { vs = "quiebras";	vp = "quiebra";		}
    else if ( dam <=  40 ) { vs = "#BMUTILAS#b";	vp = "#BMUTILA#b";	}
    else if ( dam <=  44 ) { vs = "#BDESTRIPAS#b";	vp = "#BDESTRIPA#b";	}
    else if ( dam <=  48 ) { vs = "#BDESMIEMBRAS#b";	vp = "#BDESMIEMBRA#b";	}
    else if ( dam <=  52 ) { vs = "#BMASACRAS#b";	vp = "#BMASACRA#b";	}
    else if ( dam <=  56 ) { vs = "#BDESGARRAS#b";	vp = "#BDESGARRA#b";	}
    else if ( dam <=  60 ) { vs = "#BDESTROZAS#b";	vp = "#BDESTROZA#b";	}
    else if ( dam <=  67 ) { vs = "*** #BDEMUELES#b ***";
			     vp = "*** #BDEMUELE#b ***";	}
    else if ( dam <=  75 ) { vs = "*** #BDEVASTAS#b ***";
			     vp = "*** #BDEVASTA#b ***";	}
    else if ( dam <= 100)  { vs = "=== #BELIMINAS#b ===";
			     vp = "=== #BELIMINA#b ===";	}
    else if ( dam <= 125)  { vs = "#B#F>>> ANIQUILAS <<<#b#f";
			     vp = "#B#F>>> ANIQUILA <<<#b#f";	}
    else if ( dam <= 150)  { vs = "#B#F<<< ERRADICAS >>>#b#f";
			     vp = "#B#F<<< ERRADICA >>>#b#f";	}
    else if ( dam <= 175)  { vs = "#B#F<<<- DESTRUYES ->>>#b#f";
    			     vp = "#B#F<<<- DESTRUYE ->>>#b#f";	}
    else                   { vs = "hace cosas #BINDESCRIPTIBLES#b";
			     vp = "hace cosas #BINDESCRIPTIBLES#b";	}

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

    if ( dt == TYPE_HIT )
    {
	    sprintf( buf1, "$p %s a $n%c", vp, punct );
	    sprintf( buf3, "$p te %s %c", vp, punct );
    }
    else
    {
	if ( dt >= 0 && dt < MAX_SKILL )
	    attack	= skill_table[dt].noun_damage;
	else if ( dt >= TYPE_HIT
	&& dt < TYPE_HIT + MAX_DAMAGE_MESSAGE) 
	    attack	= attack_table[dt - TYPE_HIT].noun;
	else
	{
	    bug( "Dam_message: bad dt %d.", dt );
	    dt  = TYPE_HIT;
	    attack  = attack_table[0].name;
	}

	if (immune)
	{
	    	sprintf(buf1,"$n no fue afectado por %s %s de $p!", TIPO(attack), attack);
	    	sprintf(buf3,"%s %s de $p es inutil en tu contra.", TIPO(attack), attack);
	}
	else
	{
	    	sprintf( buf1, "%s %s de $p %s a $n%c", TIPO(attack), attack, vp, punct );
	    	sprintf( buf3, "%s %s de $p te %s%c", TIPO(attack), attack, vp, punct );
	}
    }

    	act( buf1, victim, obj, NULL, TO_ROOM );
    	act( buf3, victim, obj, NULL, TO_CHAR );

    return;
}