#include "define.h" #include "struct.h" /* * LOCAL FUNCTIONS */ const char* get_attack ( char_data*, obj_data* ); bool absorb_armor ( char_data*, char_data*, const char*, int&, const char*& ); bool absorb_bracers ( char_data*, char_data*, int&, int, const char* ); bool absorb_shield ( char_data*, char_data*, const char*, int& ); bool can_defend ( char_data*, char_data* ); bool block_shield ( char_data*, char_data*, const char* ); void damage_modifiers ( char_data*, char_data*, obj_data*, int& ); bool damage_weapon ( char_data*, obj_data*& ); bool dodge ( char_data*, char_data*, int& ); bool tumble ( char_data*, char_data*, int& ); bool fire_shield ( char_data*, char_data* ); bool thorn_shield ( char_data*, char_data* ); bool ion_shield ( char_data*, char_data* ); bool flaming_weapon ( char_data*, char_data*, obj_data* ); bool misses_blindly ( char_data*, char_data*, int&, const char* ); bool parry ( char_data*, char_data*, int& ); bool counter_attack ( char_data*, char_data*, int& ); bool guard ( char_data*, char_data*, int& ); bool shadow_dance ( char_data*, char_data*, const char* ); bool switch_victim ( char_data*, char_data* ); bool trip ( char_data*, char_data*, obj_data* ); int damage_armor ( char_data*, int ); int backstab_damage ( char_data* ); int charge_damage ( char_data* ); void act_spam_notvict ( char*, char_data*, obj_data*, char_data* ); void confused_char ( char_data* ); void critical_hit ( char_data*, char_data*, obj_data*, int& ); bool is_blocked ( char_data*, char_data*, obj_data*, char* ); void leap_message ( char_data*, char_data* ); void modify_roll ( char_data*, char_data*, obj_data*, int& ); void power_strike ( char_data*, char_data*, obj_data*, int& ); void stun ( char_data*, char_data*, const char* ); void trigger_hit ( char_data*, char_data*, obj_data* ); void player_multi ( char_data*, char_data* ); void barkskin ( char_data*, int& ); void invulnerable ( char_data*, int& ); void protgood ( char_data*, char_data*, int& ); void protevil ( char_data*, char_data*, int& ); /* * LOCAL CONSTANTS */ const char* dam_loc_name [] = { "light", "finger", "finger", "neck", "neck", "body", "head", "leg", "feet", "hand", "arm", "shield", "about", "waist", "left wrist", "right wrist", "wield", "hold" }; const char* weapon_attack [MAX_WEAPON] = { "punch", "pierce", "slash", "bash", "swing", "slash", "pound", "whip", "chop", "missile weapon", "pierce" }; /* * EXTERNAL SUPPORT ROUTINES */ int initiative( char_data* ) { return number_range( 5,30 ); } int response( char_data* ) { return number_range( 5,30 ); } char_data* opponent( char_data* ch ) { char_data* rch; if( ( rch = ch->fighting ) != NULL ) return rch; for( int i = 0; i < *ch->array; i++ ) if( ( rch = character( ch->array->list[i] ) ) != NULL && rch->fighting == ch ) return rch; return NULL; } char_data* has_enemy( char_data* ch ) { char_data* rch; if( ch->fighting != NULL ) return ch->fighting; for( int i = 0; i < *ch->array; i++ ) if( ( rch = character( ch->array->list[i] ) ) != NULL && rch->position > POS_SLEEPING && includes( rch->aggressive, ch ) ) return rch; if( ch->cast != NULL && spell_table[ ch->cast->spell ].type == STYPE_OFFENSIVE ) return (char_data*) ch->cast->target; return NULL; } /* * TOP LEVEL ROUND HANDLER */ void leap_message( char_data* ch, char_data* victim ) { char_data* rch; if( victim->fighting == ch ) { send( ch, "You counterattack %s!!\r\n", victim ); if( ch->Seen( victim ) ) send( victim, "%s%s counterattacks you!!%s\r\n", bold_v( victim ), ch, normal( victim ) ); for( int i = 0; i < *victim->array; i++ ) if( ( rch = character( victim->array->list[i] ) ) != NULL && rch != victim && rch != ch && ch->Seen( rch ) && rch->link != NULL ) send( rch, "%s%s counterattacks %s!!%s\r\n", damage_color( rch, ch, victim ), ch, victim, normal( rch ) ); } else { send( ch, "You leap to attack %s!!\r\n", victim ); if( ch->Seen( victim ) ) send( victim, "%s%s leaps to attack you!!%s\r\n", bold_v( victim ), ch, normal( victim ) ); for( int i = 0; i < *victim->array; i++ ) if( ( rch = character( victim->array->list[i] ) ) != NULL && rch != victim && rch != ch && ch->Seen( rch ) && rch->link != NULL ) send( rch, "%s%s leaps to attack %s!!%s\r\n", damage_color( rch, ch, victim ), ch, victim, normal( rch ) ); } } bool jump_feet( char_data* ch ) { if( ch->position != POS_RESTING && ch->position != POS_MEDITATING ) return FALSE; send( ch, "You quickly jump to your feet.\r\n" ); send_seen( ch, "%s jumps to %s feet.\r\n", ch, ch->His_Her( ) ); ch->position = POS_STANDING; return TRUE; } /* * PLAYER FIGHT ROUTINES */ int player_round( char_data* ch, char_data* victim ) { int attack_skills [] = { SKILL_SECOND, SKILL_THIRD, SKILL_FOURTH, SKILL_FIFTH, SKILL_OFFHAND_ATTACK }; obj_data* wield = NULL; obj_data* secondary = NULL; obj_data* shield = NULL; obj_data* left; obj_data* right; int skill; int rate; int weight; int i; if( is_set( ch->pcdata->pfile->flags, PLR_PARRY ) ) return 25; if( ( left = ch->Wearing( WEAR_HELD_L ) ) != NULL ) { if( left->pIndexData->item_type == ITEM_WEAPON ) secondary = left; else if( left->pIndexData->item_type == ITEM_ARMOR ) shield = left; } if( ( right = ch->Wearing( WEAR_HELD_R ) ) != NULL ) { if( right->pIndexData->item_type == ITEM_WEAPON ) wield = right; else if( right->pIndexData->item_type == ITEM_ARMOR ) shield = right; } if( wield == NULL || ( number_range( 0,2 ) == 0 && secondary != NULL ) ) wield = secondary; if( wield != NULL ) { i = ( shield == NULL && secondary == NULL ? 3 : 2 ); weight = max( 0, wield->Weight( 1 )-10*i*ch->Strength( ) ) ; skill = WEAPON_FIRST+wield->value[3]; } else { weight = 0; skill = WEAPON_UNARMED; } if( ( i = number_range( -1, 4 ) ) == -1 ) ch->improve_skill( skill ); else ch->improve_skill( attack_skills[i] ); attack( ch, victim, get_attack( ch, wield ), wield, -1, ATT_PHYSICAL ); skill = ch->shdata->skill[ skill ]; rate = 0; for( i = 0; i < ( secondary == NULL ? 3 : 4 ); i++ ) rate += ch->shdata->skill[ attack_skills[i] ]; rate = 10+rate/2; rate = (320+weight/5-5*skill-5*ch->Dexterity( ))/rate; rate = number_range( rate/2, 3*rate/2 ); return rate; } /* * SPECIES FIGHT ROUTINES */ int mob_round( char_data* ch, char_data* victim ) { ch->shown = 1; victim->shown = 1; if( switch_victim( ch, victim ) ) return 16; var_mob = ch; var_room = ch->in_room; var_ch = victim; var_victim = victim; execute( ch->species->attack ); return 32; } bool switch_victim( char_data* ch, char_data* victim ) { char_data* rch; if( victim->pcdata == NULL || !is_set( victim->pcdata->pfile->flags, PLR_PARRY ) || number_range( 0, 4 ) != 0 ) return FALSE; for( int i = 0; ; i++ ) { if( i >= *ch->array ) return FALSE; if( ( rch = character( ch->array->list[i] ) ) != NULL && rch != victim && rch->fighting == ch ) break; } ch->fighting = rch; fsend( victim, "%s stops attacking you and leaps to attack %s.", ch, rch ); fsend( rch, "%s stops attacking %s and leaps to attack you.", ch, victim ); fsend_seen( ch, "%s stops attacking %s and leaps to attack %s.", ch, victim, rch ); return TRUE; } void add_round( species_data* species, int delay ) { if( number_range( 0,32 ) > delay ) return; if( species->exp > 1e8 || species->rounds++ > 1e8 || species->damage > 1e8 || species->damage_taken > 1e8 ) { species->rounds /= 2; species->damage /= 2; species->damage_taken /= 2; species->shdata->deaths /= 2; species->shdata->kills /= 2; species->exp /= 2; species->special /= 2; } } /* * DAMAGE AND ATTACK NAME ROUTINES */ const char* get_attack( char_data* ch, obj_data* wield ) { int skill [] = { SKILL_DEMON_SLASH, SKILL_DRAGON_STRIKE, SKILL_EAGLE_CLAW, SKILL_BEAR_GRASP, SKILL_LOCUST_KICK, SKILL_TIGER_PAW }; int weapon; int i; weapon = ( wield == NULL ? 0 : wield->value[3] ); if( ch->species != NULL || weapon != 0 ) return weapon_attack[weapon]; if( ch->shdata->skill[ SKILL_TIGER_PAW ] != 0 ) for( i = 0; i < 6; i++ ) { if( number_range( 0, 63-9*i ) < ch->shdata->skill[ skill[i] ] ) { ch->improve_skill( skill[i] ); return skill_table[ skill[i] ].name; } } if( wield == NULL && ch->shdata->race == RACE_LIZARD && ch->Wearing( WEAR_HANDS ) == NULL ) return "claw"; return "punch"; } int get_damage( char_data* ch, obj_data* wield, char letter ) { int damage; if( wield != NULL ) { damage = roll_dice( wield->value[1], wield->value[2] ); } else { damage = roll_dice( 1, letter == 'c' ? 6 : 4 ); } if( ch->species == NULL && ( wield == NULL || wield->value[3] == 0 ) ) { damage += ch->shdata->skill[SKILL_PUNCH]/3; switch( letter ) { case 't' : damage = roll_dice( 2, 6 ); break; case 'l' : damage = roll_dice( 2, 8 ); break; case 'b' : damage = roll_dice( 2, 10 ); break; case 'e' : damage = roll_dice( 2, 12 ); break; case 'd' : damage = roll_dice( 2, 14 ); break; case '*' : damage = roll_dice( 2, 16 ); break; } } return damage; } void damage_modifiers( char_data* ch, char_data* victim, obj_data* wield, int& damage ) { damage += (int) ch->Damroll( wield ); if( ch->move > 0 && is_set( &ch->status, STAT_BERSERK ) ) { ch->move--; damage += 2+ch->shdata->skill[ SKILL_BERSERK ]/3; if( number_range( 1, 4 ) == 4 ) { if( ch->shdata->skill[ SKILL_FRENZY ] > 0 ) { ch->improve_skill( SKILL_FRENZY ); damage += ch->shdata->skill[ SKILL_FRENZY ]/2; send( ch, "You attack with FRENZY!!\r\n" ); send_seen( ch, "%s attacks with FRENZY!!\r\n", ch ); } } } if( victim->position == POS_RESTING ) damage = 3*damage/2; else if( victim->position <= POS_SLEEPING ) damage *= 4; return; } float char_data :: Hitroll( obj_data* obj ) { float x; x = hitroll+float( Dexterity( ) )/3-3; if( species == NULL && shdata->skill[SKILL_BLIND_FIGHTING] > 0 ) { x = x + 1+ float( shdata->skill[SKILL_BLIND_FIGHTING])/3 ; improve_skill( SKILL_BLIND_FIGHTING ); } if( obj == NULL || obj->pIndexData->item_type != ITEM_WEAPON ) return x; if( obj->value[3] == WEAPON_AXE-WEAPON_UNARMED && is_set( affected_by, AFF_AXE_PROF ) ) x++; if( obj->value[3] == WEAPON_SWORD-WEAPON_UNARMED && is_set( affected_by, AFF_SWORD_PROF ) ) x++; x += obj->value[0]; return x; } float char_data :: Damroll( obj_data* obj ) { float x; x = damroll+float( Strength( ) )/3-4; if( obj == NULL || obj->pIndexData->item_type != ITEM_WEAPON ) return x; if( obj->value[3] == WEAPON_AXE-WEAPON_UNARMED && is_set( affected_by, AFF_AXE_PROF ) ) x++; if( obj->value[3] == WEAPON_SWORD-WEAPON_UNARMED && is_set( affected_by, AFF_SWORD_PROF ) ) x++; x += obj->value[0]; return x; } /* * MAIN BATTLE ROUTINES */ bool attack( char_data* ch, char_data* victim, const char* dt, obj_data* wield, int damage, int modifier, int type ) { int roll; bool active; bool backstab; bool charge; const char* loc_name; if( ch->position < POS_FIGHTING ) return FALSE; roll = number_range( -250, 250 ); roll += modifier; modify_roll( ch, victim, wield, roll ); active = can_defend( victim, ch ); backstab = !strcmp( dt, "backstab" ); charge = !strcmp( dt, "charge" ); if( ( !backstab && !charge ) && type == ATT_PHYSICAL && misses_blindly( ch, victim, roll, dt ) ) return FALSE; if( active && dodge( ch, victim, roll ) ) return FALSE; if( active && tumble( ch, victim, roll ) ) return FALSE; if( type == ATT_PHYSICAL ) { if( fire_shield( ch, victim ) || ( ion_shield( ch, victim ) ) || ( thorn_shield( ch, victim ) ) ) return FALSE; if( damage_weapon( ch, wield ) || ( active && !backstab && !charge && ( parry( ch, victim, roll ) || ( active && !backstab && !charge && ( guard( ch, victim, roll ) || block_shield( ch, victim, dt ) || trip( ch, victim, wield ) ) ) ) ) ) return FALSE; } if( active && ( !backstab && !charge ) && shadow_dance( ch, victim, dt ) ) return FALSE; if( damage == -1 ) { damage = get_damage( ch, wield, dt[0] ); if( backstab ) damage *= backstab_damage( ch ); if( charge ) damage *= charge_damage(ch); } damage_modifiers( ch, victim, wield, damage ); damage = max( 1, damage ); if( victim->species != NULL && victim->hit > 0 && !is_set( &victim->status, STAT_PET ) ) victim->species->damage_taken += min( victim->hit, damage ); if( ch->species != NULL ) ch->species->damage += damage/2; switch( type ) { case ATT_PHYSICAL: critical_hit( ch, victim, wield, damage ); power_strike( ch, victim, wield, damage ); barkskin( victim, damage ); invulnerable( victim, damage ); protgood( victim, ch, damage ); protevil( victim, ch, damage ); if( absorb_shield( victim, ch, dt, damage ) || absorb_armor( victim, ch, dt, damage, loc_name ) ) return FALSE; dam_local( victim, ch, damage, dt, loc_name ); if( !inflict( victim, ch, damage, "" ) && !flaming_weapon( ch, victim, wield ) ) { stun( ch, victim, dt ); trigger_hit( ch, victim, wield ); } break; case ATT_ACID: damage_acid( victim, ch, damage, dt ); break; case ATT_COLD: damage_cold( victim, ch, damage, dt ); break; case ATT_SHOCK: damage_shock( victim, ch, damage, dt ); break; case ATT_FIRE: damage_fire( victim, ch, damage, dt ); break; default: bug( "Attack: Impossible attack type." ); break; } if( ch->species != NULL ) ch->species->damage -= damage/2; return( damage > 0 ); } void modify_roll( char_data* ch, char_data* victim, obj_data* wield, int& roll ) { int weapon = ( wield == NULL ? 0 : wield->value[3] ); roll -= victim->mod_armor; roll += ch->shdata->level + 5 * (int) ch->Hitroll( wield ); roll += ( ch->species == NULL ? 8*ch->get_skill( WEAPON_UNARMED+weapon ) : 80 ); if( victim->position != POS_FIGHTING ) roll += 50; if( victim->position <= POS_SLEEPING ) roll += 100; return; } bool can_defend( char_data* victim, char_data* ch ) { if( victim->position < POS_FIGHTING || is_set( victim->affected_by, AFF_ENTANGLED ) || !ch->Seen( victim ) ) return FALSE; return TRUE; } /* * WEAPON ROUTINES */ bool damage_weapon( char_data* ch, obj_data*& wield ) { if( wield == NULL || number_range( 0, 15-4*wield->rust ) > (!is_set( wield->extra_flags, OFLAG_SANCT ) ? 0 : 1) || number_range( 1,4+wield->value[0] ) > 4 || --wield->condition > 0 ) return FALSE; send( ch, "%s you are wielding shatters into pieces.\r\n", wield ); send_seen( ch, "%s which %s is wielding shatters into pieces.\r\n", wield, ch ); wield->Extract( ); wield = NULL; return TRUE; } void trigger_hit( char_data* ch, char_data* victim, obj_data* wield ) { oprog_data* oprog; if( wield == NULL || ch->fighting != victim ) return; for( oprog = wield->pIndexData->oprog; oprog != NULL; oprog = oprog->next ) { if( oprog->trigger == OPROG_TRIGGER_HIT ) { var_ch = ch; var_victim = victim; var_obj = wield; var_room = ch->in_room; execute( oprog ); } } return; } bool flaming_weapon( char_data*, char_data*, obj_data* wield ) { if( wield == NULL || !is_set( wield->extra_flags, OFLAG_FLAMING ) ) return FALSE; return FALSE; } /* * ARMOR ROUTINES */ bool absorb_armor( char_data* victim, char_data* ch, const char* dt, int& damage, const char*& loc_name ) { char tmp [ TWO_LINES ]; int roll; int absorbed; int i; int loc; roll = number_range( 0, 1000 ); if( victim->species == NULL || is_set( &victim->species->act_flags, ACT_HUMANOID ) ) { if( roll < 450 ) loc = WEAR_BODY; else if( roll < 600 ) loc = WEAR_HEAD; else if( roll < 700 ) loc = WEAR_LEGS; else if( roll < 750 ) loc = WEAR_FEET; else if( roll < 850 ) loc = WEAR_HANDS; else if( roll < 990 ) loc = WEAR_ARMS; else if( roll < 1000 ) loc = WEAR_FINGER_L; else loc = WEAR_FINGER_R; absorbed = damage_armor( victim, loc ); damage -= absorbed; if( damage <= 0 ) { send( victim, "Your %s armor absorbs %s's %s.\r\n", dam_loc_name[loc], ch->Name( victim ), dt ); send( ch, "%s's %s armor absorbs your %s.\r\n", victim->Name( ch ), dam_loc_name[loc], dt ); send( *ch->array, "%s's %s armor absorbs %s's %s.\r\n", victim, dam_loc_name[loc], ch, dt ); return TRUE; } if( absorb_bracers( victim, ch, damage, absorbed, dt ) ) return TRUE; loc_name = dam_loc_name[loc]; return FALSE; } for( i = 0; i < MAX_ARMOR-1; i++ ) if( roll < victim->species->chance[i] ) break; damage -= number_range( 0, victim->species->armor[i] ); if( damage > 0 ) { loc_name = victim->species->part_name[i]; return FALSE; } if( *victim->species->part_name[i] != '\0' ) { sprintf( tmp, "Your %s absorbs %s's attack.\r\n", victim->species->part_name[i], ch->Name( victim ) ); spam_char( victim, tmp ); sprintf( tmp, "You %s %s's %s inflicting no damage.\r\n", dt, victim->Name( ch ), victim->species->part_name[i] ); spam_char( ch, tmp ); sprintf( tmp, "%%s's %s absorbs %%s's %s.\r\n", victim->species->part_name[i], dt ); spam_room( tmp, victim, ch ); } else { spam_char( victim, "Your armor absorbs %s's attack.\r\n", ch ); sprintf( tmp, "You %s %s inflicting no damage.\r\n", dt, victim->Name( ch ) ); spam_char( ch, tmp ); spam_room( "%s's armor absorbs %s's attack.\r\n", victim, ch ); } return TRUE; } int damage_armor( char_data* ch, int loc ) { obj_data* armor; int absorbed = 0; for( int i = ch->wearing-1; i >= 0; i-- ) { if( ( armor = object( ch->wearing[i] ) ) != NULL && armor->position == loc ) { if( armor->pIndexData->item_type == ITEM_ARMOR ) absorbed += number_range( 0, armor_class( armor ) ); if( number_range( 0, 15-4*armor->rust ) <= (!is_set( armor->extra_flags, OFLAG_SANCT ) ? 0 : 1) && number_range( 1,4+armor->value[0] ) <= 4 && --armor->condition < 0 ) { send( ch, "%s you are wearing shatters into pieces.\r\n", armor ); send_seen( ch, "%s which %s is wearing shatters into pieces.\r\n", armor, ch ); armor->Extract( ); } } } return absorbed; } /* * ATTACK ROUTINES */ void critical_hit( char_data* ch, char_data* victim, obj_data* wield, int& damage ) { int weapon; if( ch->species != NULL || ch->shdata->skill[SKILL_CRITICAL_HIT] == 0 ) return; weapon = ( wield == NULL ? 0 : wield->value[3] ); if( number_range( 1,50 ) > ch->get_skill( WEAPON_UNARMED+weapon ) ) return; if( ch->shdata->skill[SKILL_DEATH_STRIKE] != 0 && number_range( 0, 30 ) < ch->get_skill( SKILL_DEATH_STRIKE ) ) { send( ch, "You call upon the SHADOWS to DESTROY %s!\r\n", victim ); send( victim, "%s calls upon the SHADOWS to DESTROY you!\r\n", ch ); send( *ch->array, "%s calls upon the SHADOWS to DESTROY %s!\r\n", ch, victim ); ch->improve_skill( SKILL_DEATH_STRIKE ); damage *= 8; } else if( number_range( 0, 20 ) < ch->get_skill( SKILL_CRITICAL_HIT ) ) { send( ch, "You CRITICALLY hit %s!\r\n", victim ); send( victim, "%s CRITICALLY hits you!\r\n", ch ); send( *ch->array, "%s CRITICALLY hits %s!\r\n", ch, victim ); ch->improve_skill( SKILL_CRITICAL_HIT ); damage *= 5; } } void power_strike( char_data* ch, char_data* victim, obj_data* wield, int& damage ) { int weapon; if( ch->species != NULL || ch->shdata->skill[SKILL_POWER_STRIKE] == 0 ) return; weapon = ( wield == NULL ? 0 : wield->value[3] ); if( number_range( 1,75 ) > ch->get_skill( WEAPON_UNARMED+weapon ) ) return; if( number_range( 0, 25 ) < ch->get_skill( SKILL_POWER_STRIKE ) ) { send(ch, "Your POWER STRIKE hits %s!\r\n", victim ); send( victim, "%s hits you with a POWER STRIKE!\r\n", ch ); send( *ch->array, "%s hits %s with a POWER STRIKE!\r\n", ch, victim ); ch->improve_skill( SKILL_POWER_STRIKE ); damage *= 3; } } /* * OFFENSIVE ROUTINES */ void stun( char_data* ch, char_data* victim, const char* dt ) { char tmp [ MAX_INPUT_LENGTH ]; char_data* rch; if( victim->position <= POS_STUNNED || victim->shdata->race == RACE_PLANT ) return; if( ch->pcdata == NULL || ch->shdata->skill[SKILL_STUN] == 0 || ch->get_skill( SKILL_STUN ) <= number_range( 0, 100 +5*victim->shdata->level ) ) return; ch->improve_skill( SKILL_STUN ); if( victim->Seen( ch ) ) send( ch, "-* Your %s momentarily STUNS %s! *-\r\n", dt, victim->Seen_Name( ch ) ); send( victim, "%s's %s momentarily STUNS you!\r\n", ch->Name( victim ), dt ); for( int i = 0; i < *ch->array; i++ ) { if( ( rch = character( ch->array->list[i] ) ) == NULL || rch == ch || rch == victim || rch->link == NULL || !victim->Seen( rch ) ) continue; sprintf( tmp, "%s's %s momentarily STUNS %s.\r\n", ch->Name( rch ), dt, victim->Seen_Name( rch ) ); send( tmp, rch ); } disrupt_spell( victim ); set_delay( victim, 40 ); } bool trip( char_data* ch, char_data* victim, obj_data* wield ) { if( victim->position < POS_FIGHTING ) return FALSE; if( ch->species == NULL ) { if( ( wield != NULL && wield->pIndexData->value[3] != 0 ) && ch->shdata->skill[SKILL_TRIP] == 0 ) return FALSE; if( victim->species != NULL && ( !is_set( &victim->species->act_flags, ACT_HUMANOID ) ) ) { if( ch->shdata->skill[SKILL_TRIP] == 0 ) return FALSE; } } if( victim->species != NULL && ( is_set( &victim->species->act_flags, ACT_GHOST ) ) ) return FALSE; if( ch->species != NULL && ( !is_set( &ch->species->act_flags, ACT_HUMANOID ) || is_set( &ch->species->act_flags, ACT_GHOST ) ) ) return FALSE; if( ch->species == NULL ) { if( number_range( 0, 500 ) > 2*ch->get_skill( SKILL_TRIP ) + ch->get_skill( SKILL_KICK ) ) return FALSE; } else if( number_range( 0, 200 ) > 5 ) return FALSE; send( ch, "With a well timed kick you knock the feet out from under %s!\r\n", victim ); fsend( victim, "%s delivers a sweeping kick to your feet, knocking you to\ the ground!", ch ); send( *ch->array, "%s kicks %s's leg, knocking %s to the ground.\r\n", ch, victim, victim->Him_Her( ) ); if( ch->species == NULL && ch->shdata->skill[SKILL_TRIP] > 0 ) ch->improve_skill( SKILL_TRIP ); disrupt_spell( victim ); victim->position = POS_RESTING; return TRUE; } int charge_damage( char_data* ch ) { int i; if( ch->species != NULL ) return 5; ch->improve_skill( SKILL_CHARGE ); i = 10*ch->shdata->skill[ SKILL_CHARGE ] + ch->shdata->level/2 + ch->Strength( ); i = 1+i/25; return i; } int backstab_damage( char_data* ch ) { int i; if( ch->species != NULL ) return 5; if( ch->shdata->skill[ SKILL_ASSASSINATE] == 0 ) ch->improve_skill( SKILL_BACKSTAB ); else ch->improve_skill( SKILL_ASSASSINATE ); i = 10*ch->shdata->skill[ SKILL_BACKSTAB ] +10*ch->shdata->skill[ SKILL_ASSASSINATE ] +ch->shdata->level; i = 1+i/25; return i; } /* * DEFENSIVE ROUTINES */ bool absorb_bracers( char_data* victim, char_data* ch, int& damage, int armor, const char* dt ) { char tmp [ MAX_INPUT_LENGTH ]; obj_data* bracers; if( ( bracers = victim->Wearing( WEAR_WRIST_L ) ) != NULL ) armor -= bracers->value[2]; if( ( bracers = victim->Wearing( WEAR_WRIST_R ) ) != NULL ) armor -= bracers->value[2]; if( armor >= 0 || ( damage -= number_range( 0, -armor ) ) > 0 ) return FALSE; spam_char( victim, "Your bracers glow briefly and %s's %s is deflected.\r\n", ch, dt ); spam_char( ch, "%s's bracers glow briefly and your %s is magically deflected.\r\n", victim, dt ); sprintf( tmp, "%%s's bracers glow briefly and %%s's %s is deflected.", dt ); spam_room( tmp, victim, ch ); return TRUE; } bool absorb_shield( char_data* victim, char_data* ch, const char* dt, int& damage ) { char tmp [ TWO_LINES ]; if( !is_set( victim->affected_by, AFF_PROTECT ) ) return FALSE; damage -= number_range( 0, 3 ); if( damage > 0 ) return FALSE; spam_char( victim, "The air crackles as %s's %s is mysteriously blocked.\r\n", ch, dt ); spam_char( ch, "The air around %s crackles as your %s is mysteriously blocked.\r\n", victim, dt ); sprintf( tmp, "The air crackles as %%s's %s is mysteriously blocked.\r\n", dt ); spam_room( tmp, ch, victim ); return TRUE; } bool ion_shield( char_data* ch, char_data* victim ) { if( IS_AFFECTED( victim, AFF_ION_SHIELD ) ) { damage_shock( ch, victim, roll_dice( 4,8 ), "electric spark" ); if( ch->hit <= 0 ) return TRUE; } return FALSE; } bool thorn_shield( char_data* ch, char_data* victim ) { if( IS_AFFECTED( victim, AFF_THORN_SHIELD ) ) { damage_acid( ch, victim, roll_dice( 3,6 ), "thorn shield" ); if( ch->hit <= 0 ) return TRUE; } return FALSE; } bool fire_shield( char_data* ch, char_data* victim ) { if( IS_AFFECTED( victim, AFF_FIRE_SHIELD ) ) { damage_fire( ch, victim, roll_dice( 2,4 ), "fire shield" ); if( ch->hit <= 0 ) return TRUE; } return FALSE; } bool block_shield( char_data* ch, char_data* victim, const char* dt ) { char tmp [ TWO_LINES ]; obj_data* shield; int roll; if( ( shield = victim->Wearing( WEAR_HELD_L ) ) == NULL || shield->pIndexData->item_type != ITEM_ARMOR ) return FALSE; if( ( roll = number_range( 0, 100 ) ) > 25 ) return FALSE; if( roll > shield->value[1]/2+( victim->pcdata == NULL ? 7 : victim->get_skill( SKILL_SHIELD ) ) ) return FALSE; damage_armor( ch, WEAR_SHIELD ); victim->improve_skill( SKILL_SHIELD ); spam_char( victim, "%s's %s is blocked by your shield.\r\n", ch, dt ); spam_char( ch, "%s blocks your %s with %s shield.\r\n", victim, dt, victim->His_Her( ) ); sprintf( tmp, "%%s blocks %%s's %s with %s shield.\r\n", dt, victim->His_Her( ) ); spam_room( tmp, victim, ch ); return TRUE; } bool shadow_dance( char_data* ch, char_data* victim, const char* dt ) { char tmp [ TWO_LINES ]; if( victim->pcdata == NULL || number_range( 0, 35 ) >= victim->shdata->skill[SKILL_SHADOW_DANCE] ) return FALSE; victim->improve_skill( SKILL_SHADOW_DANCE ); spam_char( victim, "You meld with the shadows avoiding %s's %s.\r\n", ch, dt ); spam_char( ch, "%s melds with the shadows avoiding your %s.\r\n", victim, dt ); sprintf( tmp, "%%s melds with the shadows avoiding %%s's %s.\r\n", dt ); spam_room( tmp, victim, ch ); return TRUE; } bool counter_attack( char_data* ch, char_data* victim, int& roll ) { return FALSE; /* if( victim->get_skill( SKILL_COUNTER_ATTACK ) < 1 ) return FALSE; if( victim->species != NULL ) { if( victim->Wearing( WEAR_HELD_R ) != NULL ) roll -= 25; } else roll -= 4*victim->get_skill( SKILL_COUNTER_ATTACK ); if( roll >= 0 ) return FALSE; spam_char( victim, "You counter-attack %s's attack!\r\n", ch ); spam_char( ch, "%s counters your attack!\r\n", victim ); spam_room( "%s counters %s's attack!\r\n", victim, ch ); one_round( ch, victim ); victim->improve_skill( SKILL_COUNTER_ATTACK ); return TRUE; */ } bool parry( char_data* ch, char_data* victim, int& roll ) { if( victim->species != NULL ) { if( victim->Wearing( WEAR_HELD_R ) != NULL ) roll -= 25; } else roll -= 4*victim->get_skill( SKILL_PARRY ); if( roll >= 0 ) return FALSE; spam_char( victim, "You parry %s's attack.\r\n", ch ); spam_char( ch, "%s parries your attack.\r\n", victim ); spam_room( "%s parries %s's attack.\r\n", victim, ch ); victim->improve_skill( SKILL_PARRY ); return TRUE; } bool guard( char_data* ch, char_data* victim, int& roll ) { if( victim->species != NULL ) { if( victim->Wearing( WEAR_HELD_R ) != NULL ) roll -= 30; } else roll -= 5*victim->get_skill( SKILL_GUARD ); if( roll >= 0 ) return FALSE; spam_char( victim, "You guard yourself from %s's attack.\r\n", ch ); spam_char( ch, "%s guards from your attack.\r\n", victim ); spam_room( "%s guards from %s's attack.\r\n", victim, ch ); victim->improve_skill( SKILL_GUARD ); return TRUE; } bool tumble( char_data* ch, char_data* victim, int& roll ) { int dex; if( victim->species != NULL ) return FALSE; if( victim->get_skill( SKILL_TUMBLE ) < 1 ) return FALSE; dex = victim->Dexterity( ); roll -= victim->get_skill( SKILL_TUMBLE)+4*dex-20; if( roll > 0 ) return FALSE; spam_char( ch, "%s tumbles away, avoiding your attack.\r\n", victim ); spam_char( victim, "You tumble away, avoiding %s's attack.\r\n", ch ); spam_room( "%s tumbles away, avoiding %s's attack.\r\n", victim, ch ); victim->improve_skill( SKILL_TUMBLE ); return TRUE; } bool dodge( char_data* ch, char_data* victim, int& roll ) { int dex; dex = victim->Dexterity( ); if( victim->species == NULL ) roll -= 2*victim->get_skill( SKILL_DODGE )+4*dex-20; else roll -= 4*dex; if( roll > 0 ) return FALSE; spam_char( ch, "%s dodges your attack.\r\n", victim ); spam_char( victim, "You dodge %s's attack.\r\n", ch ); spam_room( "%s dodges %s's attack.\r\n", victim, ch ); victim->improve_skill( SKILL_DODGE ); return TRUE; } bool misses_blindly( char_data* ch, char_data* victim, int& chance, const char* dt ) { if( chance < 0 ) { spam_char( victim, "%s's attack misses you.\r\n", ch ); spam_char( ch, "You miss %s.\r\n", victim ); spam_room( "%s's attack misses %s.\r\n", ch, victim ); return TRUE; } if( !ch->in_room->Seen( ch ) && ( chance -= 30 ) < 0 ) { spam_char( ch, "You swing wildly in the dark missing everything.\r\n" ); spam_room( "%s swings wildly missing everything.\r\n", ch, NULL ); return TRUE; } if( !victim->Seen( ch ) ) { if( ( chance -= 30 ) < 0 ) { spam_char( ch, "You swing at your unseen victim, but hit nothing.\r\n" ); spam_char( victim, "%s tries to hit you, but swings in the wrong direction.\r\n", ch ); spam_room( "%s tries to hit %s, but swings in the wrong direction.\r\n", ch, victim ); return TRUE; } } else { if( is_set( victim->affected_by, AFF_DISPLACE ) && ( chance -= 10 ) < 0 ) { spam_char( ch, "Your %s seems to hit %s, but passes through %s.\r\n", dt, victim, victim->Him_Her( ) ); spam_char( victim, "%s's %s strikes your displaced image, doing you no harm.\r\n", ch, dt ); spam_room( "%s strikes the displaced image of %s.\r\n", ch, victim ); return TRUE; } } return FALSE; } void invulnerable( char_data* ch, int& damage ) { if( IS_AFFECTED( ch, AFF_INVULNERABILITY ) ) { if( ch->species == NULL && ch->pcdata->clss == CLSS_CLERIC ) damage = 9*damage/10; else damage = 8*damage/10; } return; } void barkskin( char_data* ch, int& damage ) { if( IS_AFFECTED( ch, AFF_BARKSKIN ) ) damage = 9*damage/10; return; } void protgood( char_data* ch, char_data* victim, int& damage ) { if( IS_AFFECTED( ch, AFF_PROTECT_GOOD ) && is_good( victim ) && is_evil( ch ) ) damage = 8*damage/10; return; } void protevil( char_data* ch, char_data* victim, int& damage ) { if(IS_AFFECTED( ch, AFF_PROTECT_EVIL ) && is_evil( victim ) && is_good( ch ) ) damage = 8*damage/10; return; } /* * CONFUSED CHARACTER ROUTINE */ void confused_char( char_data* ch ) { /* char *word[] = { "hop", "pout", "smile", "growl", "sulk", "drool", "clap", "fume" }; char_data* rch; int i = number_range( 0, 24 ); if( i < 8 ) { interpret( ch, word[i] ); return; } if( i < 16 ) if( ( rch = rand_victim( ch ) ) != NULL && rch != ch ) { start_fight( ch, rch ); multi_hit( ch, rch ); } */ return; }