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