/***************************************************************************

Star Wars Life 3.0a
Unarmed Combat/Martial Arts file

For credits see 'Help Credits' in game.

(c) 2001, 2002; FRPG Ltd.
All rights reserved

****************************************************************************/

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include "mud.h"

//from skills.c
void learn_style (CHAR_DATA *ch );

//from fight.c
ch_ret damage (CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt);
sh_int ris_damage( CHAR_DATA *ch, sh_int dam, int ris );

//ok first a preliminary check to see how many combo attacks will hit.

ch_ret combo_kick (CHAR_DATA *ch, CHAR_DATA *victim)
{
   ch_ret retcode;
   char buf[MAX_STRING_LENGTH];
   int dam;



    /*
     * 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;


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

    
    dam += GET_DAMROLL(ch);
    
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += (int) (dam * ch->pcdata->learned[gsn_enhanced_damage] / 120);
	learn_from_success( ch, gsn_enhanced_damage );
    }
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_unarmed] > 0 )
    {
	dam *= ( 1 + ch->pcdata->learned[gsn_unarmed] / 100 );
	learn_from_success( ch, gsn_unarmed );
    }
    dam = ris_damage( victim, dam, RIS_NONMAGIC );
    if ( dam <= 0 )
	dam = 1.5;

    if (ch->fstyle != 0 )
    {
	if ( number_percent() < 4 )
		learn_style(ch);
    }

    //combo damage mod
    dam *= 3.5;

    if ( GET_DAMAGE_RESISTANCE(victim) > 0)
    {
	dam = ( dam * ( 100 - UMIN(GET_DAMAGE_RESISTANCE(victim), 80 ) ) / 100 );
    }

    sprintf( buf, "&YYou kick %s&w\n\r", victim->name ); 
    send_to_char( buf, ch );

    if ( !IS_NPC(victim) )
    {
	sprintf( buf, "&Y%s kicks you!&w\n\r", ch->name ); 
	send_to_char( buf, victim );
    }
    if ( (retcode = damage( ch, victim, dam, TYPE_HIT )) != rNONE )
      return retcode;
    if ( char_died(ch) )
      return rCHAR_DIED;
    if ( char_died(victim) )
      return rVICT_DIED;

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

    tail_chain( );
    return rNONE;
}

ch_ret combo_jab (CHAR_DATA *ch, CHAR_DATA *victim)
{
   ch_ret retcode;
   char buf[MAX_STRING_LENGTH];
   int dam;



    /*
     * 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;


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

    
    dam += GET_DAMROLL(ch);
    
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += (int) (dam * ch->pcdata->learned[gsn_enhanced_damage] / 120);
	learn_from_success( ch, gsn_enhanced_damage );
    }
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_unarmed] > 0 )
    {
	dam *= ( 1 + ch->pcdata->learned[gsn_unarmed] / 100 );
	learn_from_success( ch, gsn_unarmed );
    }
    dam = ris_damage( victim, dam, RIS_NONMAGIC );
    if ( dam <= 0 )
	dam = 1;

    if (ch->fstyle != 0 )
    {
	if ( number_percent() < 4 )
		learn_style(ch);
    }

    //combo damage mod
    dam *= 2.5;


    if ( GET_DAMAGE_RESISTANCE(victim) > 0)
    {
	dam = ( dam * ( 100 - UMIN(GET_DAMAGE_RESISTANCE(victim), 80 ) ) / 100 );
    }

    sprintf( buf, "&YYou jab %s&w\n\r", victim->name ); 
    send_to_char( buf, ch );

    if ( !IS_NPC(victim) )
    {
	sprintf( buf, "&Y%s jabs you!&w\n\r", ch->name ); 
	send_to_char( buf, victim );
    }
    if ( (retcode = damage( ch, victim, dam, TYPE_HIT)) != rNONE )
      return retcode;
    if ( char_died(ch) )
      return rCHAR_DIED;
    if ( char_died(victim) )
      return rVICT_DIED;

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

    tail_chain( );
    return retcode;
}

ch_ret combo_punch (CHAR_DATA *ch, CHAR_DATA *victim)
{
   ch_ret retcode;
   char buf[MAX_STRING_LENGTH];
   int dam;



    /*
     * 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;


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

    
    dam += GET_DAMROLL(ch);
    
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += (int) (dam * ch->pcdata->learned[gsn_enhanced_damage] / 120);
	learn_from_success( ch, gsn_enhanced_damage );
    }
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_unarmed] > 0 )
    {
	dam *= ( 1 + ch->pcdata->learned[gsn_unarmed] / 100 );
	learn_from_success( ch, gsn_unarmed );
    }
    dam = ris_damage( victim, dam, RIS_NONMAGIC );
    if ( dam <= 0 )
	dam = 1;

    if (ch->fstyle != 0 )
    {
	if ( number_percent() < 4 )
		learn_style(ch);
    }

    //combo damage mod
    dam *= 3;


    if ( GET_DAMAGE_RESISTANCE(victim) > 0)
    {
	dam = ( dam * ( 100 - UMIN(GET_DAMAGE_RESISTANCE(victim), 80) ) / 100 );
    }

    sprintf( buf, "&YYou punch %s&w\n\r", victim->name ); 
    send_to_char( buf, ch );

    if ( !IS_NPC(victim) )
    {
	sprintf( buf, "&Y%s punches you!&w\n\r", ch->name ); 
	send_to_char( buf, victim );
    }
    if ( (retcode = damage( ch, victim, dam, TYPE_HIT )) != rNONE )
      return retcode;
    if ( char_died(ch) )
      return rCHAR_DIED;
    if ( char_died(victim) )
      return rVICT_DIED;

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

    tail_chain( );
    return retcode;
}

ch_ret combo_elbow (CHAR_DATA *ch, CHAR_DATA *victim)
{
   ch_ret retcode;
   char buf[MAX_STRING_LENGTH];
   int dam;

    /*
     * 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;


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

    
    dam += GET_DAMROLL(ch);
    
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += (int) (dam * ch->pcdata->learned[gsn_enhanced_damage] / 120);
	learn_from_success( ch, gsn_enhanced_damage );
    }
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_unarmed] > 0 )
    {
	dam *= ( 1 + ch->pcdata->learned[gsn_unarmed] / 100 );
	learn_from_success( ch, gsn_unarmed );
    }
    dam = ris_damage( victim, dam, RIS_NONMAGIC );
    if ( dam <= 0 )
	dam = 1;

    if (ch->fstyle != 0 )
    {
	if ( number_percent() < 4 )
		learn_style(ch);
    }
    //combo damage mod
    dam *= 3.5;


    if ( GET_DAMAGE_RESISTANCE(victim) > 0)
    {
	dam = ( dam * ( 100 - UMIN(GET_DAMAGE_RESISTANCE(victim), 80 ) ) / 100 );
    }

    sprintf( buf, "&YYou elbow %s in the back!&w\n\r", victim->name ); 
    send_to_char( buf, ch );



    if ( !IS_NPC(victim) )
    {
	sprintf( buf, "&Y%s elbows you in the back!&w\n\r", ch->name ); 
	send_to_char( buf, victim );
    }
    if ( (retcode = damage( ch, victim, dam, TYPE_HIT )) != rNONE )
      return retcode;
    if ( char_died(ch) )
      return rCHAR_DIED;
    if ( char_died(victim) )
      return rVICT_DIED;

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

    tail_chain( );
    return retcode;
}

ch_ret combo_knee (CHAR_DATA *ch, CHAR_DATA *victim)
{
   ch_ret retcode;
   char buf[MAX_STRING_LENGTH];
   int dam;

    /*
     * 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;


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

    
    dam += GET_DAMROLL(ch);
    
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
    {
	dam += (int) (dam * ch->pcdata->learned[gsn_enhanced_damage] / 120);
	learn_from_success( ch, gsn_enhanced_damage );
    }
    if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_unarmed] > 0 )
    {
	dam *= ( 1 + ch->pcdata->learned[gsn_unarmed] / 100 );
	learn_from_success( ch, gsn_unarmed );
    }
    dam = ris_damage( victim, dam, RIS_NONMAGIC );
    if ( dam <= 0 )
	dam = 1;

    if (ch->fstyle != 0 )
    {
	if ( number_percent() < 4 )
		learn_style(ch);
    }
    //combo damage mod
    dam *= 6.5;

    if ( GET_DAMAGE_RESISTANCE(victim) > 0)
    {
	dam = ( dam * ( 100 - UMIN(GET_DAMAGE_RESISTANCE(victim), 80 ) ) / 100 );
    }

    sprintf( buf, "&YYou knee %s in the groin!&w\n\r", victim->name ); 
    send_to_char( buf, ch );

    if ( !IS_NPC(victim) )
    {
	sprintf( buf, "&Y%s knees you in the groin!&w\n\r", ch->name ); 
	send_to_char( buf, victim );
    }
    if ( (retcode = damage( ch, victim, dam, TYPE_HIT )) != rNONE )
      return retcode;
    if ( char_died(ch) )
      return rCHAR_DIED;
    if ( char_died(victim) )
      return rVICT_DIED;

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

    tail_chain( );
    return retcode;
}



ch_ret combo_finish (CHAR_DATA *ch, CHAR_DATA *victim)
{
   ch_ret retcode;
   char buf[MAX_STRING_LENGTH];
   int dam;
    AFFECT_DATA af;



    /*
     * 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;

    sprintf( buf, "&YYou uppercut %s!&w\n\r", victim->name ); 
    send_to_char( buf, ch );

    if ( !IS_NPC(victim) )
    {
	sprintf( buf, "&Y%s gives you a devestating uppercut&w\n\r", ch->name ); 
	send_to_char( buf, victim );
    }

    if ( number_percent() < 8 )
{
    sprintf( buf, "%s goes down under the blow!!&w\n\r", victim->name ); 
    send_to_char( buf, ch );

    if ( !IS_NPC(victim) )
    {
	sprintf( buf, "&Y%s's blow knocks you out!&w\n\r", ch->name ); 
	send_to_char( buf, victim );
    }

		stop_fighting( victim, TRUE );
		if ( !IS_AFFECTED( victim, AFF_PARALYSIS ) )
		{
	  	   af.type      = gsn_stun;
	  	   af.location  = APPLY_AC;
	  	   af.modifier  = 2000;
	  	   af.duration  = 14;
	  	   af.bitvector = AFF_PARALYSIS;
	  	   affect_to_char( victim, &af );
	  	   update_pos( victim );
	  	   if ( IS_NPC(victim) )
	  	   {
	  	       start_hating( victim, ch );
	  	       start_hunting( victim, ch );
	  	       victim->was_stunned = 10;
	  	   }
		}

}

//	dam = GET_DAMCAP(ch);

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

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

    tail_chain( );
    return retcode;
}



bool check_combohit (CHAR_DATA *ch, CHAR_DATA *victim)
{
    int victim_ac;
    int diceroll;
    int thac0;
    int thac0_00;
    int thac0_32;
  


    //calculate thac0
    thac0_00 = 20;
    thac0_32 = 10;
    thac0     = interpolate( ch->skill_level[COMBAT_ABILITY] , thac0_00, thac0_32 ) - GET_HITROLL(ch);

    
    victim_ac = (int) (GET_AC(victim) / 150);

	// caps AC at the standard D&d  max of -10 and 10
	if (victim_ac > 10)
		victim_ac = 10;
	if (victim_ac < -10 )
		victim_ac = -10;

    /* Give tired people a penalty to hit in a bonus to enemies AC */
    if ( ch->move <= ( 50 ) && !IS_NPC(ch))
    {
	act( AT_YELLOW, "You are FAR to tired to effectively fight", ch, NULL, victim, TO_CHAR    );                   
        victim_ac -= 4;
    }
    if ( victim->move <= ( 50 ) && !IS_NPC(victim))
    {
	act( AT_YELLOW, "You are FAR to tired to effectively fight", victim, NULL, ch, TO_CHAR    );                   
        victim_ac += 4;
    }

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

    if ( ch->race == RACE_DEFEL )
        victim_ac += 2; 

    if ( !IS_AWAKE ( victim ) )
        victim_ac += 5;
    


	// second AC Cap -- after all modifications
	if (victim_ac > 10)
		victim_ac = 10;
	if (victim_ac < -10 )
		victim_ac = -10;


    diceroll = number_range( 1,20 );

    if ( diceroll == 1
    || ( diceroll < 20 && diceroll < thac0 - victim_ac ) )
    {
	//missed!
	return FALSE;
    }
    return TRUE;
}



ch_ret combo_hit(CHAR_DATA *ch, CHAR_DATA *victim)
{
  int maxhits;
  int hits;
  int loopvariable;
  int hittype;
  int finishertype;
  ch_ret retcode;
  char log_buf[MAX_STRING_LENGTH];

  if (ch->subclass == SUBCLASS_MARTIST)
	maxhits = 12;
  else if (ch->race == RACE_SPACEDRAGON)
	maxhits = 4;
  else
	maxhits = 3;

	hits = 0;

  for ( loopvariable=1; loopvariable <= maxhits; loopvariable++)
  {
	if (!check_combohit(ch, victim))
		break;
	else
		hits++;
  }

  
  if( hits == 0)
   {
	retcode = damage( ch, victim, 0, TYPE_HIT );
	return retcode;
}
  //apply all hits that hit, choosing randomly between the 'standard' 5
  for (loopvariable=hits; loopvariable > 0; loopvariable--)
  {
	hittype = number_percent();
	if ( hittype <= 30 )
	{
            retcode = combo_kick( ch, victim);
            if ( retcode != rNONE || who_fighting( ch ) != victim )
	            return retcode;
	}	
	else if ( hittype <= 60 && hittype >= 31)
	{
            retcode = combo_jab( ch, victim);
            if ( retcode != rNONE || who_fighting( ch ) != victim )
	            return retcode;
	}	
	else if ( hittype <= 75 && hittype >= 61)
	{
            retcode = combo_punch( ch, victim);
            if ( retcode != rNONE || who_fighting( ch ) != victim )
	            return retcode;
	}	
	else if ( hittype <= 90 && hittype >= 76)
	{
            retcode = combo_elbow( ch, victim);
            if ( retcode != rNONE || who_fighting( ch ) != victim )
	            return retcode;
	}	
	else if ( hittype >= 91)
	{
            retcode = combo_elbow( ch, victim);
            if ( retcode != rNONE || who_fighting( ch ) != victim )
	            return retcode;
	}	
	else
	{
		strcpy(log_buf, "BUG: combo_hit (unarmed.c) - Invalid Normal Hittype");
		log_string(log_buf);
		bug(log_buf, 0);
	}
  }


  //if all combohits hit, then apply a bonus 'finishing' hit
  if (hits == maxhits)
  {
      retcode = combo_finish( ch, victim);
      if ( retcode != rNONE || who_fighting( ch ) != victim )
	 return retcode;
  }
//		strcpy(log_buf, "BUG: combo_hit (unarmed.c) - Combo Ends");
//		log_string(log_buf);

  tail_chain( );
  return retcode;

}