/*___________________________________________________________________________* )()( DalekenMUD 1.12 (C) 2000 )()( `][' by Martin Thomson, Lee Brooks, `][' || Ken Herbert and David Jacques || || ----------------------------------------------------------------- || || Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, || || David Love, Guilherme 'Willie' Arnold, and Mitchell Tse. || || Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael || || Chastain, Michael Quan, and Mitchell Tse. || || Original Diku Mud copyright (C) 1990, 1991 || || by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt, || || Tom Madsen, and Katja Nyboe. || || ----------------------------------------------------------------- || || Any use of this software must follow the licenses of the || || creators. Much time and thought has gone into this software and || || you are benefitting. We hope that you share your changes too. || || What goes around, comes around. || || ----------------------------------------------------------------- || || fight.c || || Combat, combat skills and death code. || *_/<>\_________________________________________________________________/<>\_*/ #include <math.h> #include "mud.h" #include "event.h" #if !defined( PI ) #define PI 3.14159265358979323846 #endif /* fight.c functions */ void set_fighting args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); bool disarm args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void one_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt, int wpn ) ); bool check_atemi args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); CHAR_DATA *find_target( CHAR_DATA *ch, const char *argument, const char *cmd ) { CHAR_DATA *victim; if( ch->fighting ) return ch->fighting; if( argument == NULL || argument[0] == '\0' ) { charprintf( ch, "%s whom?\n\r", cmd ); return NULL; } if( !check_blind( ch ) ) return NULL; if( !( victim = get_char_room( ch, argument ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return NULL; } if( !IS_NPC( victim ) ) { if( ch != victim && !xIS_SET( victim->act, PLR_OUTLAW ) && !xIS_SET( victim->act, PLR_BATTLE ) && !IS_SET( ch->in_room->room_flags, ROOM_ARENA ) && !is_clan_enemy( victim, ch ) ) { send_to_char( "You must MURDER a player.\n\r", ch ); return NULL; } } else { if( IS_AFFECTED( victim, AFF_CHARM ) && victim->master ) { send_to_char( "You must MURDER a charmed creature.\n\r", ch ); return NULL; } } if( is_safe( ch, victim ) ) return NULL; if( IS_AFFECTED( ch, AFF_CHARM ) && ( !IS_NPC( victim ) || ch->master == victim ) ) { send_to_char( "You lack the self control to attack someone!\n\r", ch ); return NULL; } if( ch->fighting && ch->fighting != victim ) { send_to_char( "You are too busily occupied fighting someone else.\n\r", ch ); return NULL; } check_killer( ch, victim ); return victim; } void do_kill( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; if( !( victim = find_target( ch, argument, "Kill" ) ) ) return; if( ch->fighting ) { send_to_char( "You do the best you can!\n\r", ch ); return; } if( victim == ch ) { send_to_char( "You hit yourself. Ouch!\n\r", ch ); multi_hit( ch, ch, TYPE_UNDEFINED ); return; } WAIT_STATE( ch, PULSE_PER_SECOND ); multi_hit( ch, victim, TYPE_UNDEFINED ); return; } /* * I'm only allowing backstabbing with the primary weapon...immortals * who wield two weapons, with the first not being a dagger, will be * unable to backstab or circle. Tough cookie. --- Thelonius */ void do_backstab( CHAR_DATA *ch, const char *argument ) { OBJ_DATA *obj; CHAR_DATA *victim; if( !IS_NPC( ch ) && !can_use( ch, gsn_backstab ) ) { send_to_char( "You better leave the assassin trade to thieves.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Backstab" ) ) ) return; if( victim == ch ) { send_to_char( "How can you sneak up on yourself?\n\r", ch ); return; } if( ( !( obj = get_eq_char( ch, WEAR_WIELD_R ) ) && !( obj = get_eq_char( ch, WEAR_WIELD_DOUBLE ) ) ) || obj->value[3] != 11 ) { send_to_char( "You need to wield a piercing weapon.\n\r", ch ); return; } if( victim->fighting ) { send_to_char( "You can't backstab a fighting person.\n\r", ch ); return; } if( IS_AWAKE( victim ) && victim->hit < victim->max_hit ) { act( "$N is hurt and suspicious ... you can't sneak up.", ch, NULL, victim, TO_CHAR ); return; } WAIT_STATE( ch, skill_table[gsn_backstab].beats ); if( !IS_AWAKE( victim ) || IS_NPC_CLASS( ch ) || get_success( ch, gsn_backstab, 100 ) ) { if( !IS_AWAKE( victim ) ) victim->position = POS_STANDING; if( check_atemi( ch, victim ) ) multi_hit( ch, victim, gsn_atemi ); else multi_hit( ch, victim, gsn_backstab ); } else damage( ch, victim, 0, gsn_backstab, obj->wear_loc ); return; } bool check_atemi( CHAR_DATA *ch, CHAR_DATA *victim ) { OBJ_DATA *obj; if( !get_success( ch, gsn_atemi, 100 ) || number_bits( 3 ) != 0 ) return FALSE; switch( number_bits( 4 ) ) { default: break; case 0: /* Knock them unconcious for a moment (extra damage later) */ act( "$n crumple$% to the ground.", victim, NULL, ch, TO_ALL ); victim->position = POS_SLEEPING; WAIT_STATE( victim, 2 * PULSE_VIOLENCE ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, 2 * PULSE_VIOLENCE ); return TRUE; case 1: case 2: case 3: /* effectively a ram */ send_to_char( "You are stuck from behind and find yourself reeling.\n\r", victim ); act( "$n reels backwards from $O savage blow.", victim, NULL, ch, TO_ROOM ); victim->position = POS_SMASHED; WAIT_STATE( victim, 3 * PULSE_VIOLENCE ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, 3 * PULSE_VIOLENCE ); return TRUE; case 4: case 5: case 6: case 7: /* lag the opponent a little, make them get up */ act( "$n is forced to $s knees by $O strike!", victim, NULL, ch, TO_ALL ); victim->position = POS_GETTING_UP; WAIT_STATE( victim, PULSE_VIOLENCE ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, PULSE_VIOLENCE ); return TRUE; case 8: /* double backstab with each weapon */ if( !( obj = get_eq_char( ch, WEAR_WIELD_R ) ) ) return FALSE; if( !( obj = get_eq_char( ch, WEAR_WIELD_L ) ) || obj->value[3] != 11 ) return FALSE; act( "$n strike$% $N with each hand, ONE-TWO!", ch, NULL, victim, TO_ALL ); one_hit( ch, victim, gsn_atemi, WEAR_WIELD_L ); return TRUE; case 9: /* drop weapon/shield */ if( !( obj = get_eq_char( victim, WEAR_WIELD_R ) ) && !( obj = get_eq_char( victim, WEAR_WIELD_L ) ) && !( obj = get_eq_char( victim, WEAR_WIELD_DOUBLE ) ) && !( obj = get_eq_char( victim, WEAR_SHIELD ) ) ) return FALSE; act( "$O strike paralyses $n and forces $m to drop $p.", victim, obj, ch, TO_ROOM ); act( "Your arm goes numb and you drop $p.", victim, obj, victim, TO_CHAR ); obj_from_char( obj ); obj_to_room( obj, victim->in_room ); return TRUE; case 10: case 11: /* Remove all dodges and parries etc. for the next round */ act( "$O strike momentarily stuns $n.", victim, NULL, ch, TO_ALL ); act( "You're stunned by $n's blow.", victim, NULL, ch, TO_CHAR ); victim->extra_bits |= CH_EX_RESET; return TRUE; } return FALSE; } void do_circle( CHAR_DATA *ch, const char *argument ) { OBJ_DATA *obj; CHAR_DATA *rch; CHAR_DATA *victim; if( ( !IS_NPC( ch ) && !can_use( ch, gsn_circle ) ) || ( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) ) ) { send_to_char( "You'd better leave the assassin trade to thieves.\n\r", ch ); return; } if( !ch->fighting ) { send_to_char( "You must be fighting in order to do that.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Circle around" ) ) ) return; if( victim == ch ) { send_to_char( "You spin around in a circle. Whee!\n\r", ch ); return; } if( victim != ch->fighting ) { send_to_char( "One fight at a time.\n\r", ch ); return; } if( !victim->fighting ) { act( "Why? $E isn't bothering anyone.", ch, NULL, victim, TO_CHAR ); return; } if( !is_same_group( ch, victim->fighting ) ) { send_to_char( "Why call attention to yourself?\n\r", ch ); return; } for( rch = ch->in_room->people; rch; rch = rch->next_in_room ) if( rch->fighting == ch ) break; if( rch ) { send_to_char( "You're too busy being hit right now.\n\r", ch ); return; } if( ( !( obj = get_eq_char( ch, WEAR_WIELD_R ) ) && !( obj = get_eq_char( ch, WEAR_WIELD_DOUBLE ) ) ) || obj->value[3] != 11 ) { send_to_char( "You need to wield a piercing weapon.\n\r", ch ); return; } act( "$n circle$% around behind $N...", ch, NULL, victim, TO_ALL ); WAIT_STATE( ch, skill_table[gsn_circle].beats ); if( IS_NPC_CLASS( ch ) || get_success( ch, gsn_circle, 50 ) ) { stop_fighting( victim, FALSE ); multi_hit( ch, victim, gsn_circle ); } else act( "You failed to get around $M", ch, NULL, victim, TO_CHAR ); return; } void do_flee( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; ROOM_INDEX_DATA *was_in; ROOM_INDEX_DATA *now_in; int attempt; if( !( victim = ch->fighting ) ) { if( ch->position == POS_FIGHTING ) ch->position = POS_STANDING; send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if( ch->position < POS_FIGHTING ) { send_to_char( "Get up first.\n\r", ch ); return; } if( !IS_NPC( ch->fighting ) && ch->fighting->pcdata->pc_bits >= PC_BIT_STRANGLE ) { act( "$N has $S hands around your throat, free yourself first!", ch, NULL, ch->fighting, TO_CHAR ); return; } if( IS_AFFECTED( ch, AFF_BERSERK ) ) { send_to_char( "You can't flee, you're BERSERK!\n\r", ch ); return; } if( IS_AFFECTED( ch, AFF_HOLD ) ) { send_to_char( "You are stuck in a snare! You can't move!\n\r", ch ); act( "$n wants to flee, but is caught in a snare!", ch, NULL, NULL, TO_ROOM ); return; } was_in = ch->in_room; for( attempt = 0; attempt < 6; attempt++ ) { EXIT_DATA *pexit; int door; door = number_door( ); if( ( pexit = was_in->exit[door] ) == 0 || !pexit->to_room || IS_SET( pexit->exit_info, EX_CLOSED ) || ( IS_NPC( ch ) && ( IS_SET( pexit->to_room->room_flags, ROOM_NO_MOB ) || ( xIS_SET( ch->act, ACT_STAY_AREA ) && pexit->to_room->area != ch->in_room->area ) ) ) ) continue; stop_fighting( ch, TRUE ); move_char( ch, door ); if( ( now_in = ch->in_room ) == was_in ) continue; ch->in_room = was_in; act( "$n has fled!", ch, NULL, NULL, TO_ROOM ); ch->in_room = now_in; if( !IS_NPC( ch ) ) { send_to_char( "&rYou flee from combat! You lose 25 exps.&n\n\r", ch ); gain_exp( ch, -2500 ); if( IS_NPC( victim ) && xIS_SET( victim->act, ACT_HUNTER ) ) { victim->tracking = ch; create_char_event( victim, evn_hunt_fleer, number_range( PULSE_MOBILE / 2, 3 * PULSE_MOBILE / 2 ) ); } } else { ch->tracking = NULL; strip_events( &ch->events, evn_hunt_fleer ); ch->fearing = victim; } return; } send_to_char( "You failed! You lose 10 exps.\n\r", ch ); gain_exp( ch, -10 ); return; } void do_berserk( CHAR_DATA *ch, const char *argument ) { AFFECT_DATA af; /* Don't allow charmed mobs to do this, check player's level */ if( ( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) ) || ( !IS_NPC_CLASS( ch ) && !can_use( ch, gsn_berserk ) ) ) { send_to_char( "You're not enough of a warrior to go Berserk.\n\r", ch ); return; } if( IS_AFFECTED( ch, AFF_CALM ) ) { send_to_char( "You are feeling too mellow to berserk.\n\r", ch ); return; } if( !ch->fighting ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if( IS_AFFECTED( ch, AFF_BERSERK ) ) return; send_to_char( "Your weapon hits your foe and blood splatters all over!\n\r", ch ); send_to_char( "The taste of blood begins to drive you crazy!\n\r", ch ); if( get_success( ch, gsn_berserk, 100 ) ) { af.type = gsn_berserk; af.level = LEVEL_HERO; af.duration = -1; af.location = APPLY_HITROLL; af.modifier = ch->level / 6; vset( af.bitvector, AFF_BERSERK ); affect_to_char( ch, &af, NULL ); af.location = APPLY_DAMROLL; affect_to_char( ch, &af, NULL ); af.location = APPLY_AC; af.modifier *= 7; affect_to_char( ch, &af, NULL ); send_to_char( "You have gone BERSERK!\n\r", ch ); act( "$n has gone BERSERK!", ch, NULL, NULL, TO_ROOM ); return; } send_to_char( "You shake off the madness.\n\r", ch ); return; } void do_rescue( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; CHAR_DATA *fch; int count; /* Don't allow charmed mobs to do this, check player's level */ if( ( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) ) || ( !IS_NPC( ch ) && !can_use( ch, gsn_rescue ) ) ) { send_to_char( "You'd better leave the heroic acts to warriors.\n\r", ch ); return; } if( IS_AFFECTED( ch, AFF_BERSERK ) ) { send_to_char( "You can't rescue anyone, you're BERSERK!\n\r", ch ); return; } if( argument[0] == '\0' ) { send_to_char( "Rescue whom?\n\r", ch ); return; } if( !check_blind( ch ) ) return; if( !( victim = get_char_room( ch, argument ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if( victim == ch ) { send_to_char( "What about fleeing instead?\n\r", ch ); return; } if( !IS_NPC( ch ) && IS_NPC( victim ) ) { send_to_char( "They don't need your help!\n\r", ch ); return; } if( ch->fighting == victim ) { send_to_char( "Too late.\n\r", ch ); return; } if( !victim->fighting ) { send_to_char( "That person is not fighting right now.\n\r", ch ); return; } if( !is_same_group( ch, victim ) ) { send_to_char( "Why would you want to?\n\r", ch ); return; } WAIT_STATE( ch, skill_table[gsn_rescue].beats ); count = 0; for( fch = victim->in_room->people; fch; fch = fch->next_in_room ) { if( !IS_NPC( fch ) || fch->deleted ) continue; if( fch->fighting == victim ) { if( number_range( 0, count ) == 0 ) break; count++; } } if( !fch || ( !IS_NPC( ch ) && !get_success( ch, gsn_rescue, 100 ) ) ) { send_to_char( "You fail the rescue.\n\r", ch ); return; } act( "&c$n rescue$% $N!", ch, NULL, victim, TO_ALL ); for( fch = victim->in_room->people; fch; fch = fch->next_in_room ) { if( fch->fighting != victim ) continue; if( IS_AFFECTED( fch, AFF_BERSERK ) ) { act( "$N's blind rage prevents you from distracting him.", ch, NULL, fch, TO_CHAR ); continue; } stop_fighting( fch, FALSE ); set_fighting( fch, ch ); } return; } void do_taunt( CHAR_DATA *ch, const char *argument ) { AFFECT_DATA af; if( IS_NPC( ch ) || !can_use( ch, gsn_taunt ) ) { send_to_char( "You can laugh, but you still don't get the joke.\n\r", ch ); return; } if( argument[0] == '\0' ) { WAIT_STATE( ch, skill_table[gsn_taunt].beats ); affect_strip( ch, gsn_taunt ); if( get_success( ch, gsn_taunt, 100 ) ) { if( IS_AFFECTED( ch, AFF_TAUNT ) ) send_to_char( "You try to behave with more decorum.\n\r", ch ); else { act( "$n begins to laugh at everyone viciously.", ch, NULL, NULL, TO_ROOM ); send_to_char( "You now invite trouble.\n\r", ch ); af.type = gsn_taunt; af.level = 0; af.duration = -1; af.location = APPLY_SPEED; af.modifier = 2 + ch->level / 50; vset( af.bitvector, AFF_TAUNT ); affect_to_char( ch, &af, NULL ); } } } else { CHAR_DATA *vch; if( !( vch = get_char_room( ch, argument ) ) ) { send_to_char( "You can't taunt someone who isn't here.\n\r", ch ); return; } WAIT_STATE( ch, skill_table[gsn_taunt].beats ); if( IS_AFFECTED( vch, AFF_BERSERK ) ) { act( "You taunt $N but $E is raging too much to notice.", ch, NULL, vch, TO_CHAR ); act( "$n is trying to attract your attention, unsuccessfully.", ch, NULL, vch, TO_VICT ); act( "$n taunts $N but $E is raging too much to notice.", ch, NULL, vch, TO_NOTVICT ); return; } act( "You taunt $N mercilessly and $E turns on you in a rage!", ch, NULL, vch, TO_CHAR ); act( "$n says something derogatory about your mother, ARRGGGHHHH!", ch, NULL, vch, TO_VICT ); act( "$n taunts $N and $E turns to attack!", ch, NULL, vch, TO_NOTVICT ); af.type = gsn_berserk; af.level = LEVEL_HERO; af.duration = -1; af.location = APPLY_HITROLL; af.modifier = vch->level / 6; vset( af.bitvector, AFF_BERSERK ); affect_to_char( vch, &af, NULL ); stop_fighting( vch, FALSE ); set_fighting( vch, ch ); } return; } void do_kick( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; /* Don't allow charmed mobs to do this, check player's level */ if( ( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) ) || ( !IS_NPC( ch ) && !can_use( ch, gsn_kick ) ) ) { send_to_char( "You'd better leave the martial arts to fighters.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Kick" ) ) ) return; WAIT_STATE( ch, skill_table[gsn_kick].beats ); if( get_success( ch, gsn_kick, 100 ) ) damage( ch, victim, number_range( 1, ch->level ), gsn_kick, WEAR_NONE ); else damage( ch, victim, 0, gsn_kick, WEAR_NONE ); return; } void do_snapkick( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; int dam, success; /* Don't allow charmed mobs to do this, check player's level */ if( ( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) ) || ( !IS_NPC( ch ) && !can_use( ch, gsn_snapkick ) ) ) { send_to_char( "You'd better leave the martial arts to martial artists.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Kick" ) ) ) return; success = victim->level - ch->level; success *= 3; success += ( get_size( victim ) - get_size( ch ) ) / 3; success = URANGE( 5, success + number_percent( ), 100 ); dam = get_success( ch, gsn_snapkick, 100 ) / 2; success -= dam; if( success < 0 && number_bits( 3 ) == 0 && victim->position >= POS_FIGHTING ) { act( "$o snapkick slams $N into the ground!", ch, NULL, victim, TO_ALL ); victim->position = POS_SMASHED; WAIT_STATE( victim, UMIN( success, skill_table[gsn_snapkick].beats * 2 ) ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, UMIN( success, skill_table[gsn_snapkick].beats * 2 ) ); } if( dam ) { dam = number_range( ch->level / 2, ch->level * 3 / 2 ); dam *= get_curr_str( ch ) + get_curr_dex( ch ); dam /= 30; } else dam = 0; WAIT_STATE( ch, skill_table[gsn_snapkick].beats ); damage( ch, victim, dam, gsn_snapkick, WEAR_NONE ); return; } void do_disarm( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; int percent; /* Don't allow charmed mobiles to do this, check player's level */ if( ( IS_NPC( ch ) && IS_AFFECTED( ch, AFF_CHARM ) ) || ( !IS_NPC( ch ) && !can_use( ch, gsn_disarm ) ) ) { send_to_char( "You don't know how to disarm opponents.\n\r", ch ); return; } if( !get_eq_char( ch, WEAR_WIELD_R ) && !get_eq_char( ch, WEAR_WIELD_L ) && ( IS_NPC( ch ) || ch->pcdata->learned[gsn_barehand] <= 0 ) ) { send_to_char( "You must wield a weapon to disarm.\n\r", ch ); return; } if( !ch->fighting ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Disarm" ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if( victim->fighting != ch && ch->fighting != victim ) { act( "$E is not fighting you!", ch, NULL, victim, TO_CHAR ); return; } if( !get_eq_char( victim, WEAR_WIELD_R ) && !get_eq_char( victim, WEAR_WIELD_L ) && !get_eq_char( victim, WEAR_WIELD_DOUBLE ) ) { send_to_char( "Your opponent is not wielding a weapon.\n\r", ch ); return; } WAIT_STATE( ch, skill_table[gsn_disarm].beats ); percent = 100 + victim->level - ch->level; percent = percent * 2 / 3; if( !get_success( ch, gsn_disarm, percent ) || !disarm( ch, victim ) ) send_to_char( "You failed to disarm.\n\r", ch ); return; } void do_sla( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *rch; rch = get_char( ch ); if( !authorized( rch, "slay" ) ) return; send_to_char( "If you want to SLAY, spell it out.\n\r", ch ); return; } void do_slay( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; CHAR_DATA *rch; char arg[MAX_INPUT_LENGTH]; rch = get_char( ch ); if( !authorized( rch, "slay" ) ) return; argument = one_argument( argument, arg ); if( arg[0] == '\0' ) { send_to_char( "Usage: slay <character> [type]\n\r" "[type] is one of the following:\n\r" "9mm, deheart, demon, immolate, laughing, pounce,\n\r" " shatter, skin, slit.\n\r", ch ); return; } if( !( victim = get_char_room( ch, arg ) ) ) { send_to_char( "They aren't here.\n\r", ch ); return; } if( ch == victim ) { send_to_char( "Suicide is a mortal sin.\n\r", ch ); return; } if( !IS_NPC( victim ) && victim->level >= ch->level ) { send_to_char( "You failed.\n\r", ch ); return; } if( argument[0] == '\0' ) act( "$n slay$% $N in cold blood!", ch, NULL, victim, TO_ALL ); else if( !str_prefix( argument, "9mm" ) ) { act( "$n pull$% out $s 9mm and bust$% a cap in $O ass.", ch, NULL, victim, TO_ALL ); } else if( !str_prefix( argument, "deheart" ) ) { act( "You rip through $N's chest and pull out $M beating " "heart in your hand.", ch, NULL, victim, TO_CHAR ); act( "You feel a sharp pain as $n rips into your chest and tears " "out your still beating heart.", ch, NULL, victim, TO_VICT ); act( "Specks of blood hit your face as $n rips through $N's chest " "pulling out $S beating heart.", ch, NULL, victim, TO_NOTVICT ); } else if ( !str_cmp( argument, "demon" ) ) { act( "$N gesture$%, and a slavering demon appears.", ch, NULL, victim, TO_ALL ); act( "With a horrible grin, the foul creature turns on $N...\n\r" "...who screams in panic before being eaten alive.", victim, NULL, NULL, TO_ROOM ); act( "With a horrible grin, the foul creature turns on you...\n\r" "...you scream in panic before being eaten alive.", victim, NULL, NULL, TO_CHAR ); } else if( !str_prefix( argument, "immolate" ) ) { act( "Your fireball turns $N into a blazing inferno.", ch, NULL, victim, TO_CHAR ); act( "$n releases a searing fireball in your direction.", ch, NULL, victim, TO_VICT ); act( "$n points at $N, who bursts into a flaming inferno.", ch, NULL, victim, TO_NOTVICT ); } else if( !str_prefix( argument, "laughing" ) ) { act( "$N point$% at $n and fall$% down laughing. $E dies laughing.", victim, NULL, ch, TO_ROOM ); act( "$N points at you and falls down laughing.\n\r" "You die from the humility!", victim, NULL, ch, TO_CHAR ); } else if( !str_prefix( argument, "pounce" ) ) { act( "Leaping upon $N with bared fangs, you tear open $S throat and " "toss the corpse to the ground...", ch, NULL, victim, TO_CHAR ); act( "In a heartbeat, $n rips $s fangs through your throat!\n\r" "Your blood sprays and pours to the ground as your life ends...", ch, NULL, victim, TO_VICT ); act( "Leaping suddenly, $n sinks $s fangs into $N's throat.\n\r" "As blood sprays and gushes to the ground, $n tosses $N's " "dying body away.", ch, NULL, victim, TO_NOTVICT ); } else if( !str_prefix( argument, "shatter" ) ) { act( "$n freeze$% $N with a glance and shatter$% your frozen body " "into tiny shards.", ch, NULL, victim, TO_ALL ); } else if( !str_prefix( argument, "skin" ) ) { act( "You rip the flesh from $N and send his soul to " "the fiery depths of hell.", ch, NULL, victim, TO_CHAR ); act( "Your flesh is torn from your bones and you are sent to " "the flames of hell.", ch, NULL, victim,TO_VICT ); act( "$n rips the flesh off of $N, releasing his soul into " "the fiery depths of hell.", ch, NULL, victim, TO_NOTVICT ); } else if( !str_prefix( argument, "slit" ) ) { act( "You calmly slit $N's throat.", ch, NULL, victim, TO_CHAR ); act( "$n reaches out with a clawed finger and calmly slits $O throat.", ch, NULL, victim, TO_ROOM ); } raw_kill( ch, victim ); return; } void do_fee( CHAR_DATA *ch, const char *argument ) { send_to_char( "IF you wish to feed on someone or something, type FEED!\n\r", ch ); return; } /* Vampiric bite. Feeding */ void do_feed( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; OBJ_DATA *obj; AFFECT_DATA af; int dam; int heal; if( !( victim = find_target( ch, argument, "Feed on" ) ) ) return; if( victim == ch ) { send_to_char( "You cannot lunge for your own throat.\n\r", ch ); return; } send_to_char( "You must have blooood!\n\r", ch ); act( "$n lunges for $O throat!", ch, NULL, victim, TO_ROOM ); WAIT_STATE( ch, PULSE_VIOLENCE ); if( !victim->fighting ) set_fighting( victim, ch ); if( str_cmp( race_table[ch->race].name, "Vampire" ) ) { send_to_char( "You missed!\n\r", ch ); if( !ch->fighting ) set_fighting( ch, victim ); return; } if( ch->fighting ) { if( number_percent( ) > ch->level + dice( 3, 5 ) ) { send_to_char( "You missed!\n\r", ch ); return; } } /* If the victim is asleep, he deserves to be bitten. : ) */ if( !ch->fighting ) { if( number_percent( ) > ( ch->level * 1.75 ) && IS_AWAKE( victim ) ) { send_to_char( "You missed!\n\r", ch ); set_fighting( ch, victim ); return; } } dam = dice( 3, ch->level ); damage( ch, victim, dam, gsn_vampiric_bite, WEAR_NONE ); /* Lets see if we can get some food from this attack */ if( !IS_NPC( ch ) && number_percent( ) < ( 34 - victim->level + ch->level ) ) { /* If not hungry, thirsty or damaged, then continue */ if( ch->pcdata->condition[COND_FULL] > race_table[ch->race].hunger_mod * 40 / 5 && ch->pcdata->condition[COND_THIRST] > race_table[ch->race].thirst_mod * 40 / 5 && ( ch->hit * 100 / ch->max_hit > 75 ) ) { return; } else { send_to_char( "Ahh! Blood! Food! Drink!\n\r", ch ); heal = number_range( 1, dam ) / 2; ch->hit = UMIN( ch->max_hit, ch->hit + heal ); /* Get full as per drinking blood */ gain_condition( ch, COND_FULL, heal * 25 ); /* Quench thirst as per drinking blood absolute value */ gain_condition( ch, COND_THIRST, heal * 12 ); } } /* Ok now we see if we can infect the victim */ /* if( IS_NPC( victim ) ) --This might turn out to be fun :) return; */ if( victim->level < 11 || get_age( victim ) < 21 ) return; if( saves_spell( ch->level, victim, ch, gsn_vampiric_bite ) || number_bits( 1 ) == 0 ) return; if( ( obj = get_eq_char( victim, ITEM_HOLD ) ) ) { if( IS_OBJ_STAT( obj, ITEM_VAMPIRE_BANE ) && ch->level < 21 ) return; else if( IS_OBJ_STAT( obj, ITEM_HOLY ) ) { if( ch->level < 32 ) return; else if( victim->level > ch->level ) return; } } af.type = gsn_vampiric_bite; af.duration = UMAX( 5, 30 - ch->level ); af.location = APPLY_NONE; af.modifier = 0; vset( af.bitvector, AFF_VAMP_BITE ); affect_join( victim, &af ); send_to_char( "Ahh! Taste the power!\n\r", ch ); send_to_char( "Your blood begins to burn!\n\r", victim ); return; } void do_stake( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; OBJ_DATA *obj; bool found = FALSE; int chance; if( !( victim = find_target( ch, argument, "Stake" ) ) ) return; if( IS_NPC( victim ) ) { send_to_char( "You may not stake NPC's.\n\r", ch ); return; } /* Check here to see if they have a stake in hand. * Changed slightly to allow any wooden weapon that is wielded * and can stab or pierce. --Symposium */ for( obj = ch->carrying; obj; obj = obj->next_content ) { if( obj->item_type == ITEM_WEAPON && ( obj->value[3] == 2 || obj->value[3] == 11 ) && ( obj->wear_loc == WEAR_WIELD_R || obj->wear_loc == WEAR_WIELD_L || obj->wear_loc == WEAR_WIELD_DOUBLE ) && !str_cmp( flag_string( material_flags, &obj->pIndexData->material ), "wood" ) ) { found = TRUE; break; } } if( !found ) { send_to_char( "You lack a wielded stake to stake.\n\r", ch ); act( "$n screams and lunges at $N then realizes $e doesnt have a stake", ch, NULL, victim, TO_ROOM ); multi_hit( ch, victim, TYPE_UNDEFINED ); return; } act( "$n screams and lunges at $N with $p.", ch, obj, victim, TO_ALL ); /* Calculate chances -> autokill the vampire. */ chance = IS_NPC( ch ) ? UMIN( 60, ch->level ) : ch->pcdata->learned[gsn_stake]; chance = chance - victim->level + ch->level; if( number_percent( ) < chance || !IS_AWAKE( victim ) || str_cmp( race_table[ch->race].name, "Vampire" ) ) { if( !str_cmp( race_table[victim->race].name, "Vampire" ) ) { /* remove the curse, this isn't done when they are killed */ affect_strip( victim, gsn_vampiric_bite ); victim->hit = 1; damage( ch, victim, 4, gsn_stake, WEAR_NONE ); } else multi_hit( ch, victim, TYPE_UNDEFINED ); } else /* vampire staking another vampire, strange?, feed instead. */ do_feed( victim, ch->name ); return; } void do_impale( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; OBJ_DATA *obj; if( !can_use( ch, gsn_impale ) ) { send_to_char( "Learn how to do this first please.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Impale" ) ) ) return; if( ( !( obj = get_eq_char( ch, WEAR_WIELD_R ) ) && !( obj = get_eq_char( ch, WEAR_WIELD_DOUBLE ) ) ) || obj->value[3] != 11 ) { send_to_char( "You need to wield a piercing weapon.\n\r", ch ); return; } if( ch->level + get_success( ch, gsn_impale, 500 ) + get_curr_str( ch ) > number_percent( ) + victim->level + get_curr_str( victim ) ) { act( "You pull back then shove your weapon into $N's chest!", ch, NULL, victim, TO_CHAR ); act( "$n drives $s weapon straight into you!.", ch, NULL, victim, TO_VICT ); act( "$n impales $N on $s weapon!", ch, NULL, victim, TO_NOTVICT ); one_hit( ch, victim, gsn_impale, obj->wear_loc ); WAIT_STATE( victim, 2 * PULSE_VIOLENCE ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, 2 * PULSE_VIOLENCE ); } else { act( "You try to impale $N but $E manages to avoid you.", ch, NULL, victim, TO_CHAR ); act( "$n tries to impale you but you manage to avoid $m.", ch, NULL, victim, TO_VICT ); act( "$n barely misses impaling $N.", ch, NULL, victim, TO_NOTVICT ); damage( ch, victim, 0, gsn_impale, obj->wear_loc ); } WAIT_STATE( ch, skill_table[gsn_impale].beats ); return; } void do_headbutt( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; OBJ_DATA *helmet; AFFECT_DATA af; int hps, num, move = 25; /* Don't allow charmed mobs to do this, check player's level */ if( !can_use( ch, gsn_headbutt ) ) { send_to_char( "You'd better leave the power fighting to fighters.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Headbutt" ) ) ) return; if( ch->move < move ) { if( !get_success( ch, gsn_stamina, 100 ) ) { send_to_char( "You are too exhausted.\n\r", ch ); return; } if( ch->hit < ch->max_hit / 3 ) { send_to_char( "Your body is too exhausted, " "your tired muscles will move no more.\n\r", ch ); return; } send_to_char( "You push your tired body past it's limits.\n\r", ch ); move -= ch->move; ch->move = 0; ch->hit -= move; WAIT_STATE( ch, skill_table[gsn_stamina].beats ); } else ch->move -= move; helmet = get_eq_char( ch, WEAR_HEAD ); hps = victim->hit; WAIT_STATE( ch, skill_table[gsn_headbutt].beats ); if( ( num = get_success( ch, gsn_headbutt, 100 ) ) ) { one_hit( ch, victim, gsn_headbutt, WEAR_WIELD_R ); } else { damage( ch, victim, 0, gsn_headbutt, WEAR_NONE ); one_hit( ch, ch, gsn_headbutt, WEAR_NONE ); if( !helmet || number_percent( ) > ch->pcdata->learned[gsn_headbutt] / 3 ) victim = ch; } if( victim == ch->fighting && hps > victim->hit && ( ( ch != victim && number_percent( ) < num / 7 ) || ( ch == victim && number_percent( ) > num / 2 ) ) ) { af.type = skill_lookup( "sleep" ); af.duration = number_range( 0, 2 ); af.location = APPLY_NONE; af.modifier = 0; vset( af.bitvector, AFF_SLEEP ); act( "$o eyes glaze over and $e crumple$% to the ground.", victim, NULL, NULL, TO_ALL ); stop_fighting( victim, TRUE ); do_sleep( victim, "" ); } return; } void do_smash( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; if( !can_use( ch, gsn_smash ) ) { send_to_char( "You should learn how to use the skill first.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Smash" ) ) ) return; WAIT_STATE( ch, skill_table[gsn_smash].beats ); if( get_success( ch, gsn_smash, 90 ) ) one_hit( ch, victim, gsn_smash, WEAR_NONE ); else damage( ch, victim, 0, gsn_smash, WEAR_NONE ); } void do_ram( CHAR_DATA *ch, const char *argument ) { int success, wait; CHAR_DATA *victim; if( !can_use( ch, gsn_ram ) ) { send_to_char( "You should learn how to use the skill first.\n\r", ch ); return; } if( !get_eq_char( ch, WEAR_SHIELD ) ) { send_to_char( "I would advise wearing a shield first.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Ram" ) ) ) return; success = ch->level - victim->level; success *= 3; success += ( get_size( ch ) - get_size( victim ) ) / 3; if( !IS_NPC_CLASS( ch ) ) success += get_success( ch, gsn_ram, 500 ); else success += UMIN( ch->level, 90 ); success += get_curr_str( ch ) - 30; if( victim->position <= POS_SMASHED ) success /= 2; success -= number_percent( ); if( success > 0 ) { if( victim->position <= POS_SMASHED ) { send_to_char( "Let them get up first.\n\r", ch ); return; } act( "$n ram$% into $N sending $M sprawling.", ch, NULL, victim, TO_ALL ); stop_juggling( victim ); victim->position = POS_SMASHED; damage( ch, victim, number_range( ch->level / 2, ch->level * 3 / 2 ), gsn_ram, WEAR_NONE ); wait = skill_table[gsn_ram].beats + UMIN( success, 4 * skill_table[gsn_ram].beats ); WAIT_STATE( victim, wait ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, wait ); WAIT_STATE( ch, skill_table[gsn_ram].beats ); } else { act( "You try to ram into $N but you fall over.", ch, NULL, victim, TO_CHAR ); act( "$n trie$% to ram into $N but $e fall$% over.", ch, NULL, victim, TO_ROOM ); ch->position = POS_SMASHED; if( !victim->fighting ) multi_hit( victim, ch, TYPE_UNDEFINED ); WAIT_STATE( ch, 2 * skill_table[gsn_ram].beats ); } return; } /* * Slit throat, specialised backstab. * More damage, better maximum damage etc... */ void do_slit_throat( CHAR_DATA *ch, const char *argument ) { OBJ_DATA *obj; CHAR_DATA *victim; if( !IS_NPC_CLASS( ch ) && !can_use( ch, gsn_slit_throat ) ) { send_to_char( "You better leave the assassin trade to thieves.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Slit the throat of" ) ) ) return; if( victim == ch ) { send_to_char( "How can you sneak up on yourself?\n\r", ch ); return; } if( !( obj = get_eq_char( ch, WEAR_WIELD_R ) ) || ( obj->value[3] != 1 && obj->value[3] != 3 ) ) { send_to_char( "You need to wield a slicing or slashing weapon.\n\r", ch ); return; } WAIT_STATE( ch, skill_table[gsn_slit_throat].beats ); act( "You slit $N a nice new smile.", ch, NULL, victim, TO_CHAR ); act( "$n sneaks up on $N and slashes $S throat!", ch, NULL, victim, TO_NOTVICT ); if( !IS_AWAKE( victim ) || get_success( ch, gsn_slit_throat, 100 ) ) { multi_hit( ch, victim, gsn_slit_throat ); xSET_BIT( victim->affected_by, AFF_BLEEDING ); } else damage( ch, victim, 0, gsn_slit_throat, WEAR_WIELD_R ); return; } void do_tend( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; OBJ_DATA *band; if( !( *argument ) ) victim = ch; else victim = get_char_room( ch, argument ); if( !( victim ) ) { send_to_char( "Tend whom?\n\r", ch ); return; } if( !IS_AFFECTED( victim, AFF_BLEEDING ) && !victim->damaged_parts ) { send_to_char( "They have no need of your assistance.\n\r", ch ); return; } if( ( !IS_NPC( victim ) || ch != victim ) && ( victim->damaged_parts & victim->body_parts ) ) { if( can_use( ch, gsn_field_dressing ) ) { WAIT_STATE( ch, skill_table[gsn_field_dressing].beats ); if( !get_success( ch, gsn_field_dressing, 100 ) ) { act( "$n tries to use $s field dressing techniques on $N, but fails.", ch, NULL, victim, TO_ROOM ); act( "You fail to properly use your field dressing techniques.", ch, NULL, victim, TO_CHAR ); return; } act( "$n use$% field dressing techniques to repair $O wounds.", ch, NULL, victim, TO_ALL ); } else /* can't use field dressing */ { for( band = ch->carrying; band; band = band->next_content ) if( band->pIndexData->vnum == OBJ_VNUM_BANDAGES ) break; if( !band ) { send_to_char( "You can't repair their wounds without bandages.\n\r", ch ); return; } if( ch == victim ) { act( "$n wrap$% $s wounds with $p.", ch, band, NULL, TO_ALL ); } else { act( "$n wraps $O wounds with $p.", ch, band, victim, TO_ALL ); } extract_obj( band ); WAIT_STATE( ch, PULSE_VIOLENCE * 2 ); } victim->damaged_parts = 0; } xREMOVE_BIT( victim->affected_by, AFF_BLEEDING ); if( ch != victim ) { act( "$n tend$% $O wounds.", ch, NULL, victim, TO_ALL ); } else { act( "$n tend$% $s own wounds.", ch, NULL, NULL, TO_ALL ); } WAIT_STATE( ch, PULSE_VIOLENCE ); return; } void do_stomp( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; if( !can_use( ch, gsn_stomp ) ) { bad_command( ch ); return; } if( !( victim = find_target( ch, argument, "Stomp on" ) ) ) return; if( victim->position >= POS_FIGHTING ) { send_to_char( "They must be on the ground before you can stomp on them.\n\r", ch ); return; } if( ch->level + get_success( ch, gsn_stomp, 500 ) + get_curr_str( ch ) > number_percent( ) + victim->level + get_curr_str( victim ) ) { act( "$n stomp$% down on $N's head with a sickening crunching sound!", ch, NULL, victim, TO_ALL ); one_hit( ch, victim, gsn_stomp, WEAR_WIELD_L ); WAIT_STATE( victim, PULSE_VIOLENCE ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, PULSE_VIOLENCE ); } else { act( "You try to stomp on $N but $E rolls out of the way.", ch, NULL, victim, TO_CHAR ); act( "$n tries to stomp on you but you manage to avoid $m.", ch, NULL, victim, TO_VICT ); act( "$n barely misses stomping on $N.", ch, NULL, victim, TO_NOTVICT ); damage( ch, victim, 0, gsn_stomp, WEAR_NONE ); } WAIT_STATE( ch, 3 * PULSE_VIOLENCE ); return; } void do_strangle( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; AFFECT_DATA af; if( IS_NPC( ch ) || !can_use( ch, gsn_strangle ) ) { send_to_char( "You don't know how to strangle yet.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Strangle" ) ) ) return; if( victim->fighting != ch ) { victim->fighting = ch; if( victim->position != POS_SMASHED ) victim->position = POS_FIGHTING; } ch->fighting = victim; WAIT_STATE( ch, 3 * PULSE_VIOLENCE ); if( !get_success( ch, gsn_strangle, 100 ) ) { send_to_char( "You fail to get a good grip.\n\r", ch ); return; } af.type = gsn_strangle; af.level = LEVEL_HERO; af.location = APPLY_NONE; af.modifier = 0; af.duration = ch->level; vset( af.bitvector, AFF_HOLD ); affect_to_char( victim, &af, NULL ); act( "$n grab$% hold of $N and start$% throttling $M!", ch, NULL, victim, TO_ALL ); SET_BIT( ch->pcdata->pc_bits, PC_BIT_STRANGLE ); if( get_time_left( ch->in_room->events, evn_room_violence ) < 0 ) create_room_event( ch->in_room, evn_room_violence, PULSE_VIOLENCE ); return; } /* * for those strangling */ void strangle_hit( CHAR_DATA *ch ) { int pwr; int dam; if( IS_NPC( ch ) || !ch->fighting ) return; pwr = ch->pcdata->pc_bits / PC_BIT_STRANGLE; dam = number_range( ch->level / 2, ch->level ); dam += get_damroll( ch ); if( IS_SET( ch->pcdata->pc_bits, PC_BIT_HANDOFKAZ ) ) { dam += get_curr_int( ch ) * 2; dam = power( dam, get_success( ch, gsn_hand_of_kaz, 250 ), pwr ); ch->pcdata->pc_bits += PC_BIT_STRANGLE; damage( ch, ch->fighting, dam, gsn_hand_of_kaz, WEAR_NONE ); } else { dam += get_curr_dex( ch ) * 2; dam = power( dam, get_success( ch, gsn_strangle, 250 ), pwr ); ch->pcdata->pc_bits += PC_BIT_STRANGLE; damage( ch, ch->fighting, dam, gsn_strangle, WEAR_NONE ); } return; } /* * for those being strangled */ void strangle_struggle( CHAR_DATA *ch ) { int chance; if( !ch->fighting || IS_NPC( ch->fighting ) ) return; if( IS_SET( ch->fighting->pcdata->pc_bits, PC_BIT_HANDOFKAZ ) ) { chance = get_curr_int( ch ) - get_curr_int( ch->fighting ); chance -= ch->fighting->pcdata->learned[gsn_hand_of_kaz] / 2; chance += ch->level - ch->fighting->level; if( chance + 75 > number_percent( ) ) { act( "$n wrenches free of $O death grip.", ch, NULL, ch->fighting, TO_ALL ); ch->fighting->pcdata->pc_bits %= PC_BIT_STRANGLE; REMOVE_BIT( ch->fighting->pcdata->pc_bits, PC_BIT_HANDOFKAZ ); /* * Optional -- Symposium * multi_hit( ch, ch->fighting, TYPE_UNDEFINED ); */ } else { act( "You strain to free yourself of $N's death grip", ch, NULL, ch->fighting, TO_CHAR ); act( "$n is straining to free $mself from $N's death grip.", ch, NULL, ch->fighting, TO_NOTVICT ); act( "You feel $n's heart beat weakly in your fist.", ch, NULL, ch->fighting, TO_VICT ); } } else { chance = get_curr_dex( ch ) - get_curr_dex( ch->fighting ); chance -= ch->fighting->pcdata->learned[gsn_strangle] / 2; chance += ch->level - ch->fighting->level; if( chance + 75 > number_percent( ) ) { act( "You struggle free of $N's stranglehold.", ch, NULL, ch->fighting, TO_CHAR ); act( "$n frees $mself from $N's stranglehold.", ch, NULL, ch->fighting, TO_NOTVICT ); act( "$n slips from your grasp.", ch, NULL, ch->fighting, TO_VICT ); ch->fighting->pcdata->pc_bits %= PC_BIT_STRANGLE; /* * Optional -- Symposium * multi_hit( ch, ch->fighting, TYPE_UNDEFINED ); */ } else { act( "You struggle to free yourself of $N's stranglehold.", ch, NULL, ch->fighting, TO_CHAR ); act( "$n is struggling to free $mself from $N's stranglehold.", ch, NULL, ch->fighting, TO_NOTVICT ); act( "$n is struggling but you hold firm.", ch, NULL, ch->fighting, TO_VICT ); } } return; } void do_trip( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; if( !IS_NPC_CLASS( ch ) && !can_use( ch, gsn_trip ) ) { send_to_char( "You can't use that yet.\n\r", ch ); return; } if( !( victim = find_target( ch, argument, "Trip" ) ) ) return; if( !ch->fighting ) set_fighting( ch, victim ); if( IS_SET( victim->body_parts, BODY_PART_WINGS ) || xIS_SET( victim->affected_by, AFF_FLYING ) ) { act( "You watch as your leg sweeps underneath $N.", ch, NULL, victim, TO_CHAR ); act( "$n try to trip you but $s leg passes under you.", ch, NULL, victim, TO_VICT ); act( "$n tries to trip $N but $s leg passes under $E.", ch, NULL, victim, TO_NOTVICT ); WAIT_STATE( ch, PULSE_VIOLENCE * 2 ); if( !victim->fighting ) set_fighting( victim, ch ); return; } if( !IS_NPC( ch ) && get_success( ch, gsn_trip, 200 ) + 2 * ( get_curr_dex( ch ) + ch->level - victim->level ) - 45 < number_percent( ) ) { act( "You try to trip $N and you stumble.", ch, NULL, victim, TO_CHAR ); act( "$n trie$% to trip $N and $e stumble$%.", ch, NULL, victim, TO_ROOM ); WAIT_STATE( ch, 2 * PULSE_VIOLENCE ); if( !victim->fighting ) set_fighting( victim, ch ); return; } WAIT_STATE( ch, PULSE_VIOLENCE ); if( victim->position < POS_FIGHTING ) { send_to_char( "Let them get up first, eh?\n\r", ch ); return; } if( !IS_NPC( ch ) || victim->wait == 0 ) { int wait; victim->fighting = NULL; act( "You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR ); act( "$n trips you and you go down!", ch, NULL, victim, TO_VICT ); act( "$n trips $N and $N goes down!", ch, NULL, victim, TO_NOTVICT ); wait = number_range( 3 * PULSE_VIOLENCE, 5 * PULSE_VIOLENCE ); WAIT_STATE( victim, wait ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, wait ); stop_juggling( victim ); victim->position = POS_SLEEPING; } return; } bool throw( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; if( !( victim = find_target( ch, argument, "Throw" ) ) ) return FALSE; if( !IS_NPC_CLASS( ch ) && !can_use( ch, gsn_throw ) ) { send_to_char( "Maybe you should learn the proper technique " "before trying to throw people.\n\r", ch ); return TRUE; } if( !ch->fighting ) set_fighting( ch, victim ); if( !IS_NPC_CLASS( ch ) && get_success( ch, gsn_throw, 200 ) + get_curr_str( ch ) + get_curr_dex( ch ) + 2 * ( ch->level - victim->level ) - 45 < number_percent( ) ) { act( "You try to throw $N but $E slips from your grasp.", ch, NULL, victim, TO_CHAR ); act( "$n tries to throw you but you manage to slip $s grasp.", ch, NULL, victim, TO_VICT ); act( "$n tries to throw $N but $E slips out of $s grasp.", ch, NULL, victim, TO_NOTVICT ); WAIT_STATE( ch, 3 * PULSE_VIOLENCE ); } else if( !IS_NPC_CLASS( ch ) || victim->wait == 0 ) { int wait; victim->fighting = NULL; act( "$n grab$% $N throw$% $M to the ground!", ch, NULL, victim, TO_ALL ); WAIT_STATE( ch, PULSE_VIOLENCE ); wait = number_range( 3 * PULSE_VIOLENCE, 5 * PULSE_VIOLENCE ); WAIT_STATE( victim, wait ); if( IS_NPC( victim ) ) create_char_event( victim, evn_stand_up, wait ); stop_juggling( victim ); victim->position = POS_SLEEPING; } return TRUE; } void do_whirlwind( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; CHAR_DATA *next; OBJ_DATA *obj; int move = 100; if( !can_use( ch, gsn_whirlwind ) ) { send_to_char( "Maybe you should learn how first.\n\r", ch ); return; } if( !( obj = get_eq_char( ch, WEAR_WIELD_R ) ) && !( obj = get_eq_char( ch, WEAR_WIELD_DOUBLE ) ) && !( obj = get_eq_char( ch, WEAR_WIELD_L ) ) ) { send_to_char( "You should be wearing a weapon.\n\r", ch ); return; } if( ch->move < move ) { if( !get_success( ch, gsn_stamina, 100 ) ) { send_to_char( "You are too exhausted.\n\r", ch ); return; } if( ch->hit < ch->max_hit / 3 ) { send_to_char( "Your body is too exhausted, " "your tired muscles will move no more.\n\r", ch ); return; } send_to_char( "You push your tired body past it's limits.\n\r", ch ); move -= ch->move; ch->move = 0; ch->hit -= move; WAIT_STATE( ch, skill_table[gsn_stamina].beats ); } else ch->move -= move; send_to_char( "You sweep your weapon around viciously.\n\r", ch ); act( "$n sweeps $s weapon around the room!", ch, NULL, NULL, TO_ROOM ); if( !get_success( ch, gsn_whirlwind, 100 ) ) return; WAIT_STATE( ch, skill_table[gsn_whirlwind].beats ); for( victim = ch->in_room->people; victim; victim = next ) { next = victim->next_in_room; if( !IS_NPC( ch ) && !IS_NPC( victim ) && !xIS_SET( ch->act, PLR_BATTLE ) && !xIS_SET( victim->act, PLR_BATTLE ) && !IS_SET( ch->in_room->room_flags, ROOM_ARENA ) ) continue; if( IS_NPC( ch ) && IS_NPC( victim ) ) continue; if( !IS_NPC( ch ) && is_affected( victim, AFF_CHARM ) ) continue; one_hit( ch, victim, gsn_whirlwind, obj->wear_loc ); } return; } #define MAX_COMBO 5 void do_combo( CHAR_DATA *ch, const char *argument ) { static const int type_hit = TYPE_HIT; const struct combo_type { const char *name; const int * hit_gsn[MAX_COMBO]; } combo_table[] = { { "eagle combo", { &gsn_jab, &type_hit, &gsn_jab, &gsn_backhand } }, { "pummel combo", { &gsn_jab, &gsn_jab, &gsn_backhand, &gsn_uppercut } }, { "bull combo", { &gsn_backhand, &gsn_knee, &gsn_uppercut } }, { "viper combo", { &gsn_backhand, &gsn_knee, &gsn_elbow, &gsn_uppercut, &gsn_roundhouse } }, { "dragon combo", { &gsn_elbow, &gsn_knee, &gsn_uppercut, &gsn_roundhouse, &gsn_uppercut } }, { NULL, { 0 } } }; CHAR_DATA *victim; int typ, sn, i, savehit; if( IS_NPC( ch ) ) return; if( !( victim = ch->fighting ) ) { send_to_char( "You should be fighting first.\n\r", ch ); return; } if( argument[0] == '\0' ) { send_to_char( "Which combo?\n\r", ch ); return; } if( get_eq_char( ch, WEAR_WIELD_DOUBLE ) || get_eq_char( ch, WEAR_WIELD_R ) || get_eq_char( ch, WEAR_WIELD_L ) || get_eq_char( ch, WEAR_SHIELD ) || get_eq_char( ch, WEAR_HOLD_L ) || get_eq_char( ch, WEAR_HOLD_R ) ) { send_to_char( "Are you joking? Your gear gets in the way!\n\r", ch ); return; } for( typ = 0; combo_table[typ].name; typ++ ) { if( !str_prefix( argument, combo_table[typ].name ) ) break; } if( !combo_table[typ].name ) { send_to_char( "That combination is not possible.\n\r", ch ); return; } sn = skill_lookup( combo_table[typ].name ); if( sn <= 0 || !can_use( ch, sn ) ) { send_to_char( "You wave your hands about and" " succeed in making an idiot of yourself.\n\r", ch ); return; } WAIT_STATE( ch, skill_table[sn].beats ); if( !get_success( ch, sn, 100 ) ) { send_to_char( "You wave your hands about and" " succeed in making an idiot of yourself.\n\r", ch ); return; } i = 0; savehit = victim->hit; one_hit( ch, victim, TYPE_HIT, WEAR_WIELD_R ); while( i < MAX_COMBO && *combo_table[typ].hit_gsn[i] > 0 ) { if( victim->deleted || victim != ch->fighting || victim->hit >= savehit ) return; if( *combo_table[typ].hit_gsn[i] == TYPE_HIT || get_success( ch, *combo_table[typ].hit_gsn[i], 100 ) ) { savehit = victim->hit; one_hit( ch, victim, *combo_table[typ].hit_gsn[i], WEAR_WIELD_R ); ++i; continue; } damage( ch, victim, 0, *combo_table[typ].hit_gsn[i], WEAR_WIELD_R ); return; } return; } void do_blink( CHAR_DATA *ch, const char *argument ) { if( IS_NPC( ch ) || !can_prac( ch, gsn_blink ) ) { send_to_char( "You can't use this skill.\n\r", ch ); return; } if( argument[0] == '\0' ) { if( ch->pcdata->blink > 0 ) charprintf( ch, "You are blinking at %d%%.\n\r", ch->pcdata->blink ); else if( ch->pcdata->blink == 0 ) send_to_char( "You aren't blinking incoming attacks.\n\r", ch ); else charprintf( ch, "If you were blinking you would be at %d%%.\n\r", ch->pcdata->blink * -1 ); return; } if( !str_cmp( argument, "on" ) ) { if( ch->pcdata->blink >= 0 ) { send_to_char( "Please specify the rate of blinking.\n\r", ch ); return; } ch->pcdata->blink = URANGE( 0, ch->pcdata->blink * -1, 50 ); charprintf( ch, "You will attempt to blink at a rate of %d.\n\r", ch->pcdata->blink ); return; } if( !str_cmp( argument, "off" ) ) { if( ch->pcdata->blink <= 0 ) { send_to_char( "You weren't blinking attacks.\n\r", ch ); return; } ch->pcdata->blink *= -1; send_to_char( "You wont attempt to blink incoming attacks.\n\r", ch ); return; } if( !is_number( argument ) ) { send_to_char( "Please specify a rate of blinking, 'on' or 'off'.\n\r", ch ); return; } ch->pcdata->blink = URANGE( 0, atoi( argument ), 50 ); charprintf( ch, "You will attempt to blink incoming attacks %d%% of the time.\n\r", ch->pcdata->blink ); return; }