/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * 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. * ***************************************************************************/ #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #endif #include <math.h> #include <stdio.h> #include <string.h> #include <time.h> #include "merc.h" INF_DATA * inf_free; /* * Local functions. */ bool check_dodge args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); bool check_parry args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); bool check_block args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); bool check_shields args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void dam_message args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) ); void death_cry args( ( CHAR_DATA *ch ) ); void group_gain args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); int xp_compute args( ( CHAR_DATA *gch, CHAR_DATA *victim ) ); bool is_safe args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void make_corpse args( ( CHAR_DATA *ch, bool pdox ) ); void one_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) ); void raw_kill args( ( CHAR_DATA *victim, bool pdox ) ); void disarm args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void trip args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); int calc_attacks args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void check_quest args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); int suit_damage args( ( CHAR_DATA *victim, int dam ) ); void essense_gain args( ( CHAR_DATA *ch, CHAR_DATA *victim, int gain, int dt ) ); /* * Control the fights going on. * Called periodically by update_handler. */ void violence_update( void ) { CHAR_DATA *ch; CHAR_DATA *ch_next; CHAR_DATA *victim; CHAR_DATA *rch; CHAR_DATA *rch_next; for ( ch = char_list; ch != NULL; ch = ch->next ) if ( IS_CLASS(ch,CLASS_SAIYAN) && IS_SET(ch->pcdata->actnew,NEW_KIAIHOU) ) REMOVE_BIT(ch->pcdata->actnew,NEW_KIAIHOU); for ( ch = char_list; ch != NULL; ch = ch->next ) { ch_next = ch->next; if ( ( victim = ch->fighting ) == NULL || ch->in_room == NULL ) continue; /* new location, before combat round */ mprog_fight_trigger( ch, victim ); if ( IS_AWAKE(ch) && ch->in_room == victim->in_room && victim->position > POS_STUNNED ) { if ( !IS_SUIT(ch) ) { multi_hit( ch, victim, TYPE_UNDEFINED ); } } else stop_fighting( ch, FALSE ); if ( ( victim = ch->fighting ) == NULL ) continue; mprog_hitprcnt_trigger( ch, victim ); /* original location mprog_fight_trigger( ch, victim ); */ /* * Fun for the whole family! */ for ( rch = ch->in_room->people; rch != NULL; rch = rch_next ) { rch_next = rch->next_in_room; if ( IS_AWAKE(rch) && rch->fighting == NULL ) { /* * everyody auto-assist others in their group. */ if ( is_same_group(ch,rch) && (IS_NPC(rch) || (!IS_TIED(rch) && !IS_SUIT(rch))) ) { if ( !IS_NPC(rch) ) stancecheck( rch, victim ); multi_hit( rch, victim, TYPE_UNDEFINED ); continue; } /* * NPC's assist NPC's of same type or 12.5% chance regardless. */ if ( IS_NPC(rch) && !IS_AFFECTED(rch, AFF_CHARM) ) { if ( rch->pIndexData == ch->pIndexData ) { CHAR_DATA *vch; CHAR_DATA *target; int number; target = NULL; number = 0; for ( vch = ch->in_room->people; vch; vch = vch->next ) { if ( can_see( rch, vch ) && is_same_group( vch, victim ) && number_range( 0, number ) == 0 ) { target = vch; number++; } } if ( target != NULL ) multi_hit( rch, target, TYPE_UNDEFINED ); } } } } } return; } /* * Do one group of attacks. */ void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { int chance, attacks, i, cn; bool isSame = TRUE; if ( victim == NULL ) return; if ( victim->in_room == NULL ) return; if ( IS_CLASS(ch,CLASS_SORCERER) && ch->pcdata->powers[SORC_PREP] > 0 ) { cn = 1; // crummy safety measure for ( i = MAX_CHANT; i > 0; i-- ) { if ( chant_table[i].school == ch->pcdata->powers[SORC_PREP] && chant_table[i].rank <= ch->pcdata->powers[ch->pcdata->powers[SORC_PREP]] && chant_table[i].prep == TRUE ) { cn = i; break; } } dt = 1400 + cn; if ( ch->mana >= chant_table[cn].cost / 2 ) { ch->mana -= chant_table[cn].cost / 2; } else return; } if ( !IS_NPC(ch) && IS_CLASS(victim,CLASS_SAIYAN) && victim->level >= 2 ) { if ( IS_SET(victim->pcdata->actnew,NEW_KIAIHOU) ) { i = victim->pcdata->powers[S_AEGIS_MAX] - victim->pcdata->powers[S_AEGIS]; if ( victim->pcdata->powers[S_POWER] <= i*2 ) act( "You're too tired to refocus your aegis!", victim, NULL, NULL, TO_CHAR ); else { act( "You refocus your aegis!", victim, NULL, NULL, TO_CHAR ); act( "$n's aegis flares with renewed energy.", victim, NULL, NULL, TO_ROOM ); victim->pcdata->powers[S_POWER] -= i*2; victim->pcdata->powers[S_AEGIS] = victim->pcdata->powers[S_AEGIS_MAX]; } } else if ( IS_SET(victim->pcdata->powers[S_TECH],S_KIAIHOU) ) SET_BIT(victim->pcdata->actnew,NEW_KIAIHOU); } if ( IS_CLASS(ch,CLASS_MAZOKU) && IS_SET(ch->pcdata->powers[M_SET],M_ASTRIKE) ) { if ( IS_NPC(victim) && ch->pcdata->powers[M_EGO] <= 1 ) { stc( "You lack the will to execute an astrike.\n\r", ch ); REMOVE_BIT(ch->pcdata->powers[M_SET],M_ASTRIKE); } else { if ( IS_NPC(victim) ) ch->pcdata->powers[M_EGO] -= 1; act( "You materialize.. right behind $N!", ch, NULL, victim, TO_CHAR ); act( "$n phases into existance.. right behind you!", ch, NULL, victim, TO_VICT ); act( "$n phases into existance.. right behind $N!", ch, NULL, victim, TO_NOTVICT ); } } one_hit( ch, victim, dt ); if ( ch->fighting != victim || dt == gsn_backstab ) return; attacks = calc_attacks( ch, victim ); for ( i = 0; i < attacks && isSame; i++ ) { one_hit( ch, victim, dt ); if ( ch->fighting != victim || victim->position <= POS_STUNNED ) isSame = FALSE; } chance = 30; if ( !IS_NPC(ch) ) chance = 50 + ( ch->pcdata->body / 2 ); if ( isSame && number_percent( ) < chance ) { one_hit( ch, victim, dt ); if ( ch->fighting != victim || victim->position <= POS_STUNNED ) isSame = FALSE; } chance = 20; if ( !IS_NPC(ch) ) chance = 10 + ( ch->pcdata->body / 2 ); if ( isSame && number_percent( ) < chance ) { one_hit( ch, victim, dt ); if ( ch->fighting != victim || victim->position <= POS_STUNNED ) isSame = FALSE; } if ( IS_CLASS(ch,CLASS_MAZOKU) && IS_SET(ch->pcdata->powers[M_SET],M_ASTRIKE) ) REMOVE_BIT(ch->pcdata->powers[M_SET],M_ASTRIKE); return; } /* * Hit one guy once. */ void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { OBJ_DATA *wield; int dam, diceroll, chance, kai, roll, i, weapon, cdam, vdam; int stance = 0; /* * Can't beat a dead char! * Guard against weird room-leavings. */ if ( victim->position == POS_DEAD || ch->in_room != victim->in_room ) return; /* * Figure out the type of damage message. */ wield = get_eq_char( ch, WEAR_WIELD ); if ( dt == TYPE_UNDEFINED ) { dt = TYPE_HIT; if ( wield != NULL && wield->item_type == ITEM_WEAPON ) dt += wield->value[3]; } /* Mazoku damage is based off of their arm forms */ if ( IS_CLASS(ch,CLASS_MAZOKU) && wield == NULL && dt >= TYPE_HIT ) { dt = TYPE_HIT; /* magic numbers are bad.. oh well */ if ( IS_SET(ch->pcdata->powers[M_SET],M_CLAWS) ) dt += 5; else if ( IS_SET(ch->pcdata->powers[M_SET],M_SPIKES) ) dt += 2; else if ( IS_SET(ch->pcdata->powers[M_SET],M_BLADES) ) dt += 1; else if ( IS_SET(ch->pcdata->powers[M_SET],M_TENTACLES) ) dt += 4; } /* * Fuck to-hit-armor-class-0 versus armor bullshit. */ if ( IS_NPC(ch) ) { chance = URANGE( 30, (ch->level * 3/2), 95); } else { if ( dt < TYPE_HIT ) chance = dice(10,5)+50; else if ( dt > TYPE_HIT+13 ) chance = 100; else chance = URANGE( 30, ch->pcdata->weapons[dt-1000] , 95); } /* homersexual if ( !can_see( ch, victim ) ) chance -= chance / 4; */ /* * The moment of excitement! */ diceroll = number_percent(); if ( diceroll > chance ) { /* Miss. */ damage( ch, victim, 0, dt ); tail_chain( ); return; } /* * Hit. * Calc damage. */ if ( IS_NPC(ch) ) { dam = number_range( ch->level / 2, ch->level * 3 ); if ( ch->level >= 25 ) dam += dam; if ( ch->level >= 50 ) dam += dam; if ( ch->level >= 75 ) dam += dam; if ( ch->level > 95 ) dam += dam * ( ch->level - 94 ); if ( wield != NULL ) dam += dam / 2; } else { if ( IS_CLASS(ch,CLASS_SORCERER) && ch->pcdata->powers[SORC_PREP] > 0 ) { i = ch->pcdata->powers[ch->pcdata->powers[SORC_PREP]]; dam = number_range(i*(UMIN(ch->pcdata->powers[SORC_MYSTIC],i)/15),i*15); } else if ( wield != NULL ) { if ( dt < TYPE_HIT ) dam = number_range(ch->pcdata->weapons[0]/8+1,ch->pcdata->weapons[0]/5+5); else dam = number_range( (ch->pcdata->weapons[dt-1000]/8)+(wield->value[1]*2), (ch->pcdata->weapons[dt-1000]/5)+(wield->value[2]*2) ); } /* for mazoku, essentially */ else if ( IS_CLASS(ch,CLASS_MAZOKU) && dt >= TYPE_HIT ) { dam = number_range( ch->pcdata->weapons[dt-TYPE_HIT] / 4, ch->pcdata->weapons[dt-TYPE_HIT] / 3 ); } /* unarmed combat */ else { weapon = ch->pcdata->weapons[0]; if ( ch->level < 2 ) weapon = UMIN( 200, weapon ); if ( ch->class == CLASS_FIST ) dam = number_range(weapon/8+1,weapon/3+5); else if ( ch->class == CLASS_SAIYAN && ch->pcdata->powers[S_AEGIS] > 0 ) dam = number_range((weapon/8)+20,(weapon/5)+45); else if ( ch->class == CLASS_SORCERER && IS_AFFECTED(ch,AFF_VISFARANK) ) { i = UMAX( 0, (ch->pcdata->powers[SCHOOL_WHITE]-20)*2 ); dam = number_range((weapon/2)+i,(weapon*2)+40+i); } else dam = number_range(weapon/10+1,weapon/5+5); } } if ( !IS_NPC(ch) ) { int max = 200; if ( ch->class == CLASS_FIST && dt == TYPE_HIT && ch->pcdata->powers[F_DISC] >= 2 ) max = 500; chance = number_percent(); if ( ch->pcdata->weapons[dt-1000] < max ) if ( chance < UMAX( 5, 100 - ch->pcdata->weapons[dt-1000] ) ) ch->pcdata->weapons[dt-1000]++; stance = stanced(ch); max = 200; if ( ch->class == CLASS_FIST && ch->pcdata->powers[F_DISC] >= 3 ) max = 300; if ( stance > 0 && stance <= 10 ) { roll = number_percent(); if ( ch->pcdata->stances[stance] < max ) if ( roll > ch->pcdata->stances[stance] || roll > 95 ) ch->pcdata->stances[stance]++; } } /* * Bonuses. */ if ( !IS_NPC(ch) ) cdam = UMIN( ch->damroll, ch->pcdata->extras2[EVAL]*3 ); else cdam = ch->damroll; if ( !IS_NPC(victim) ) vdam = UMIN( victim->damroll, victim->pcdata->extras2[EVAL]*3 ); else vdam = victim->damroll; /* dam += dam * isquare(UMAX( 0, cdam - vdam )) / 33; */ dam += dam * URANGE(0,cdam-vdam, 40) / 100; if ( IS_CLASS(ch,CLASS_SAIYAN) && ch->level >= 2 ) { if ( ch->pcdata->powers[S_STRENGTH] > 0 ) dam += ( dam * ch->pcdata->powers[S_STRENGTH] / 175 ); if ( is_affected(ch,gsn_kaiouken) ) dam += dam * ch->pcdata->powers[S_STRENGTH_MAX] / 1000; } if ( IS_CLASS(ch,CLASS_FIST) && ch->level >= 2 ) if ( ch->pcdata->powers[F_HANDS] > 0 ) dam += dam * ch->pcdata->powers[F_HANDS] / 33; if ( IS_CLASS(ch,CLASS_PATRYN) && ch->level >= 2 ) dam += dam * (50 + ch->pcdata->powers[P_FIRE] / 2) * (get_runes(ch,RUNE_FIRE,LEFTARM) + get_runes(ch,RUNE_FIRE,RIGHTARM)) / 100; if ( IS_CLASS(ch,CLASS_MAZOKU) && ch->level >= 2 ) { if ( IS_SET(ch->pcdata->powers[M_SET],M_CLAWS) ) dam += dam * 3 * (50+ch->pcdata->powers[M_MATTER]+ch->pcdata->powers[M_FOCUS]) / 120; else if ( IS_SET(ch->pcdata->powers[M_SET],M_SPIKES) ) dam += dam * 3 * (ch->pcdata->powers[M_MATTER]+ch->pcdata->powers[M_FOCUS]) / 150; else if ( IS_SET(ch->pcdata->powers[M_SET],M_BLADES) ) dam += dam * 4 * (ch->pcdata->powers[M_MATTER]+ch->pcdata->powers[M_FOCUS]) / 120; else if ( IS_SET(ch->pcdata->powers[M_SET],M_TENTACLES) ) dam += dam * 3 * (ch->pcdata->powers[M_MATTER]+ch->pcdata->powers[M_FOCUS]) / 170; else dam += dam * 3 * ch->pcdata->powers[M_MATTER] / 100; if ( IS_SET(ch->pcdata->powers[M_SET],M_ASTRIKE) ) { if ( IS_NPC(victim) ) dam += dice( 3, dam/2 ); else dam += dice( 3, dam ) / 3; } if ( IS_SUIT(victim) ) dam /= 2; } if ( !IS_AWAKE(victim) ) dam *= 2; if ( dt == gsn_backstab ) { dam *= dice( 2, 4 ); if ( IS_CLASS(victim,CLASS_FIST) && !IS_CLASS(ch,CLASS_FIST) ) dam *= 3; else if ( IS_CLASS(victim,CLASS_MAZOKU) && !IS_CLASS(ch,CLASS_FIST) ) dam *= 2; } if ( !IS_NPC(ch) ) { stance = stanced( ch ); if ( stance ) { if ( IS_CLASS(ch,CLASS_SORCERER) && ch->pcdata->powers[SORC_PREP] > 0 ) dam += dam * ch->pcdata->stances[stance] * stance_table[stance].damage[0] / 5000; else dam += dam * ch->pcdata->stances[stance] * stance_table[stance].damage[0] / 2000 ; } } if ( !IS_NPC(victim) ) { stance = stanced( victim ); if ( stance > 0 && stance <= 10 ) dam -= dam * victim->pcdata->stances[stance] * stance_table[stance].redux / 3000; } /* AC damage reduction for pcs */ if ( !IS_NPC(victim) ) { if ( victim->armor < 0 ) dam -= dam * -1 * victim->armor / 1000; } if ( !IS_NPC(ch) && ch->class == CLASS_SAIYAN ) if ( is_affected(ch,gsn_kaiouken) ) { kai = dice( 10, 20 ); if ( ch->move < kai ) { affect_strip(ch,gsn_kaiouken); act( "Exhausted, you cease using the Kaiouken attack.", ch, NULL, NULL, TO_CHAR ); act( "The crimson flame encasing $n flickers and vanishes.", ch, NULL, NULL, TO_ROOM ); } else ch->move -= kai; } if ( dam <= 0 ) dam = 1; damage( ch, victim, dam, dt ); /* Lightning Ball runeweave check */ if ( IS_CLASS(ch,CLASS_MAZOKU) && IS_SET(ch->pcdata->powers[M_SET],M_ASTRIKE) && victim != NULL && !IS_NPC(victim) && victim->level >= 2 && IS_SET(victim->pcdata->actnew,NEW_BALL_LIGHTNING) ) { damage( victim, ch, dice(18,65), DAM_SHOCKSHIELD ); } tail_chain( ); return; } /* * Inflict damage from a hit. */ int damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) { sh_int mod; char log_buf[MAX_STRING_LENGTH]; int i; if ( victim->position == POS_DEAD ) return -1; /* * Stop up any residual loopholes. */ if ( dam > 30000 && !IS_IMMORTAL(ch) ) { bug( "Damage: %d: more than 30000 points!", dam ); dam = 30000; } if ( victim != ch ) { /* * Certain attacks are forbidden. * Most other attacks are returned. */ if ( is_safe( ch, victim ) ) return -1; if ( victim->position > POS_STUNNED ) { if ( victim->fighting == NULL ) set_fighting( victim, ch ); victim->position = POS_FIGHTING; } if ( victim->position > POS_STUNNED ) { if ( ch->fighting == NULL ) set_fighting( ch, victim ); /* * If victim is charmed, ch might attack victim's master. */ if ( IS_NPC(ch) && IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL && victim->master->in_room == ch->in_room && number_bits( 3 ) == 0 ) { stop_fighting( ch, FALSE ); multi_hit( ch, victim->master, TYPE_UNDEFINED ); return -1; } } /* * More charm stuff. */ if ( victim->master == ch ) stop_follower( victim ); /* * Inviso attacks ... not. */ if ( IS_AFFECTED(ch, AFF_INVISIBLE) ) { affect_strip( ch, gsn_invis ); affect_strip( ch, gsn_mass_invis ); REMOVE_BIT( ch->affected_by, AFF_INVISIBLE ); act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM ); } if ( is_affected(ch,gsn_sneak) ) affect_strip( ch, gsn_sneak ); /* * Damage modifiers. */ if ( IS_AFFECTED(victim, AFF_SANCTUARY) && !IS_SUIT(victim) ) dam /= 2; if ( IS_AFFECTED(victim,AFF_STEELY) ) dam /= 2; if ( dam < 0 ) dam = 0; /* No lowbies fucking with maxed char fights */ if ( !IS_NPC(ch) && (!IS_NPC(victim) || victim->level >= 96) && ch->pcdata->extras2[EVAL] < 50 ) { dam = dam * (1 + ch->pcdata->extras2[EVAL]/10) / 6; } /* * Check for disarm, trip, parry, and dodge. */ /* if ( IS_NPC(ch) && number_percent( ) < ch->level / 10 ) disarm( ch, victim ); if ( IS_NPC(ch) && number_percent( ) < ch->level / 2 ) trip( ch, victim ); */ /* Mystic melee can be dodged - removed if ( (dt >= TYPE_HIT && dt < TYPE_HIT+15) || (dt >= 1400 && dt < 1480) ) { if ( check_dodge( ch, victim ) ) return -1; } */ if ( dt >= TYPE_HIT && dt < TYPE_HIT+15 ) { if ( check_parry( ch, victim ) ) return -1; if ( check_dodge( ch, victim ) ) return -1; if ( check_block( ch, victim ) ) return -1; if ( check_shields( ch, victim ) ) return -1; } if ( dt >= F_SHINKICK && dt <= F_JUMPKICK ) { if ( is_affected(victim,gsn_defense) ) { act( "Your defense barrier blocks $n's blow.", ch, NULL, victim, TO_VICT ); act( "$N's defense barrier blocks your blow.", ch, NULL, victim, TO_CHAR ); return TRUE; } if ( !IS_NPC(ch) && stanced(ch) > 0 ) { if ( stance_table[stanced(ch)].redux > 2 ) dam -= dam * stance_table[stanced(ch)].redux / 20; } } /* special damage mods */ if ( dt == DAM_SHELLS || dt == DAM_BEAMSABRE || dt == DAM_BEAMRIFLE || dt == DAM_BEAMSWORD || dt == DAM_BULLETS) { if ( IS_NPC(victim) && victim->level < 97 ) dam*= 2; else if ( IS_NPC(victim) && victim->level >= 97 ) dam /= 3; } if ( dt == DAM_KIFLAME ) { if ( IS_NPC(victim) ) dam *= 2; else if ( victim->class == CLASS_SAIYAN && victim->pcdata->powers[S_AEGIS] > 0 ) dam -= dam * victim->pcdata->powers[S_AEGIS] / 2100; else if ( is_affected(victim,gsn_balus_wall) ) { dam = 0; act( "Your attack is sucked into a flourescent wall.", ch, NULL, victim,TO_CHAR); act( "Your Balus Wall absorbs $n's attack and vanishes!",ch,NULL,victim,TO_VICT ); act( "$n's attack is absorbed by a flourescent wall.",ch,NULL,victim,TO_NOTVICT); affect_strip(victim,gsn_balus_wall); } } /* can turtle against melee component of fist combos */ if ( dt >= 1020 && dt <= 1027 ) { if ( !IS_NPC(victim) && stanced(victim) > 0 ) dam -= dam * victim->pcdata->stances[stanced(victim)] * stance_table[stanced(victim)].redux / 5000; } if ( IS_SUIT(victim) ) { if ( dt == DAM_LIGHTNING ) dam *= 2; dam -= dam * (suit_table[victim->pcdata->suit[SUIT_NUMBER]].armor - 60) / 140; } /* damage reduction from toughness */ else if (!IS_NPC(victim) && victim->level >= 2) { if ( IS_CLASS(victim,CLASS_SAIYAN) ) { /* Resist to mystickal damage */ if ( dt >= 1400 && dt < 1480 ) dam -= dam * victim->pcdata->powers[S_AEGIS] / 3000; if ( victim->pcdata->powers[S_AEGIS] > 0 ) { dam -= dam * ( victim->pcdata->powers[S_AEGIS] + number_range(1,300) ) / 1500; if ( dt != DAM_MISSILES || dt != DAM_FIRE || dt != DAM_LIGHTNING ) { victim->pcdata->powers[S_AEGIS] = UMAX( victim->pcdata->powers[S_AEGIS_MAX]/2, victim->pcdata->powers[S_AEGIS] - isquare(dam) ); } } if ( is_affected(victim,gsn_kiwall) ) { if ( dt == F_DEATHTOUCH ) dam /= 2; else if ( dt != DAM_CERULEAN ) dam /= 3; } if ( dt == DAM_OBSIDIAN ) { victim->pcdata->powers[S_STRENGTH] = UMAX( victim->pcdata->powers[S_STRENGTH] - dam/5, victim->pcdata->powers[S_STRENGTH_MAX]/2 ); victim->pcdata->powers[S_SPEED] = UMAX( victim->pcdata->powers[S_SPEED] - dam/5, victim->pcdata->powers[S_SPEED_MAX]/2 ); victim->pcdata->powers[S_AEGIS] = UMAX( victim->pcdata->powers[S_AEGIS] - dam/5, victim->pcdata->powers[S_AEGIS_MAX]/2 ); } } if ( victim->class == CLASS_FIST ) { if ( IS_SET(victim->pcdata->actnew,NEW_FIGUREEIGHT) ) dam /= 3; dam -= dam * ((number_range(1,15))+(25+victim->pcdata->powers[F_TORSO] / 2)) / 100; /* Kaiouken effect on Ki */ if ( IS_CLASS(ch,CLASS_SAIYAN) && is_affected(ch,gsn_kaiouken) ) { if ( victim->pcdata->powers[F_KI] > 0 && !IS_SET(victim->pcdata->actnew,NEW_FIGUREEIGHT) ) victim->pcdata->powers[F_KI]--; } } if ( victim->class == CLASS_PATRYN ) { if ( dt == DAM_KIFLAME || dt == DAM_CRIMSON ) { if ( get_runes(victim,RUNE_FIRE,TORSO) > 0 ) mod = get_runes(victim,RUNE_EARTH,TORSO) + (get_runes(victim,RUNE_FIRE,TORSO)*3/2); else mod = UMAX( 0, get_runes(victim,RUNE_EARTH,TORSO)/2 ); } else if ( dt == DAM_LIGHTNING || dt == F_DEATHTOUCH ) { mod = get_runes(victim,RUNE_EARTH,TORSO); if ( get_runes(victim,RUNE_AIR,TORSO) <= 0 ) mod /= 2; } else if ( dt == DAM_FIRE ) { mod = get_runes(victim,RUNE_EARTH,TORSO); if ( get_runes(victim,RUNE_FIRE,TORSO) <= 0 ) mod /= 2; } else mod = get_runes(victim,RUNE_EARTH,TORSO); dam -= ( dam * mod * (4+victim->pcdata->powers[P_EARTH]/20) ) / ( mod * 10 + ( 35 - (mod * 2) ) + dice(1,20) ); switch ( dt ) { default: break; case DAM_SHOCKWAVE: if ( is_affected( victim, gsn_wind_ward ) ) { dam -= 500; dec_duration( victim, gsn_wind_ward, 500 ); } break; case DAM_EMERALD: if ( is_affected( victim, gsn_earth_ward ) ) { dam -= 200; dec_duration( victim, gsn_earth_ward, 200 ); } break; case F_SHINKICK: case F_JAB: case F_SPINKICK: case F_KNEE: case F_ELBOW: case F_UPPERCUT: if ( is_affected( victim, gsn_earth_ward ) ) { dam -= 15; dec_duration( victim, gsn_earth_ward, 60 ); } break; /* all melee attack types */ case 1000: case 1001: case 1002: case 1003: case 1004: case 1005: case 1006: case 1007: case 1008: case 1009: case 1010: case 1011: case 1012: if ( is_affected( victim, gsn_earth_ward ) ) { dam -= 15; dec_duration( victim, gsn_earth_ward, 15 ); } break; case DAM_KIFLAME: case DAM_CRIMSON: if ( is_affected( victim, gsn_flame_ward ) ) { dam -= 400; dec_duration( victim, gsn_flame_ward, 400 ); } break; case DAM_CERULEAN: if ( is_affected( victim, gsn_water_ward ) ) { dam -= 400; dec_duration( victim, gsn_water_ward, 400 ); } break; case F_DEATHTOUCH: case DAM_OBSIDIAN: if ( is_affected( victim, gsn_negative_ward ) ) { dam -= 200; dec_duration( victim, gsn_negative_ward, 200 ); } break; }; } if ( IS_CLASS(victim,CLASS_SORCERER) ) { if ( IS_CLASS(ch,CLASS_FIST) ) { if ( IS_AFFECTED(ch,AFF_CHAOS_STRING) ) { if ( (dt >= TYPE_HIT && dt < TYPE_HIT+15 ) || (dt >= F_SHINKICK && dt <= F_JUMPKICK) ) { dam /= 2; } } } if ( IS_AFFECTED(victim,AFF_HOLY_RESIST) ) { if ( dt == DAM_FIRE || dt == DAM_LIGHTNING || dt == DAM_NEGATIVE ) dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE]) / 150; if ( dt == DAM_OBSIDIAN || dt == DAM_CRIMSON || dt == DAM_EMERALD ) dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE]) / 100; if ( dt == DAM_CERULEAN ) dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE]) / 150; if ( dt == F_DEATHTOUCH ) dam -= dam / 2; } if ( is_affected(victim,gsn_mos_varim) ) { if ( dt == DAM_KIFLAME || dt == DAM_FIRE ) dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE]-20) / 35; /* resistance to mobile suit attacks */ if ( dt == DAM_BEAMRIFLE || dt == DAM_BEAMSABRE ) { dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE]-25) / 50; if ( dam <= 0 ) dam = 1; } } if ( IS_AFFECTED(victim,AFF_VAS_GLUUDO) ) { if ( dt == DAM_KIFLAME || (dt >= 130 && dt < 140) || dt == DAM_SHOCKWAVE ) dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE]-20) / 35; if ( dt == DAM_BEAMRIFLE || dt == DAM_BEAMSABRE || dt == DAM_BEAMSWORD ) dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE] - 10) / 60; if ( dt == DAM_SHOCKSHIELD ) dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE]-20) / 60; } } if ( IS_CLASS(victim,CLASS_MAZOKU) ) { if ( dt == DAM_KIFLAME ) { dam += dam / 3; dam -= dam * victim->pcdata->powers[M_NIHILISM] / 400; } if ( IS_SET(victim->pcdata->powers[M_SET],M_HUMAN) ) dam -= dam * victim->pcdata->powers[M_MATTER] / 130; else if ( IS_SET(victim->pcdata->powers[M_SET],M_BATTLE) ) dam -= dam * (victim->pcdata->powers[M_MATTER] + 15) / 135; else if ( IS_SET(victim->pcdata->powers[M_SET],M_TRUE) ) dam -= dam * victim->pcdata->powers[M_ASTRAL] / 140; } } /* NPC's get damage reduction by level */ else { dam -= dam * victim->level / 200; if ( victim->level > 95 ) dam -= dam * (victim->level - 95) * 10 / 100; /* No shelling down boss mobs */ if ( IS_SET(victim->act,ACT_NO_RANGED) && ch->in_room != victim->in_room ) dam = 0; } /* dam_message( ch, victim, dam, dt ); */ } if ( dam < 0 ) dam = 0; timer_check( ch, victim ); dam_message( ch, victim, dam, dt ); essense_gain( ch, victim, dam, dt ); if ( victim->position >= POS_STUNNED ) add_inf( ch, victim, dam ); if ( IS_SUIT(victim) && dt != DAM_EXPLOSION ) return suit_damage( victim, dam ); /* * Hurt the victim. * Inform the victim of his new state. */ victim->hit -= dam; if ( !IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL && victim->hit < 1 ) victim->hit = 1; update_pos( victim ); /* Mazoku nihilism gain */ if ( IS_CLASS(victim,CLASS_MAZOKU) && dam > victim->max_hit/10 && victim != ch ) { if ( victim->pcdata->powers[M_NIHILISM] < 100 ) victim->pcdata->powers[M_NIHILISM]++; } switch( victim->position ) { case POS_MORTAL: act( "$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are mortally wounded, and will die soon, if not aided.\n\r", victim ); if ( IS_CLASS(victim,CLASS_SAIYAN) ) { if ( IS_SET(victim->pcdata->actnew,NEW_KAME_1) ) REMOVE_BIT(victim->pcdata->actnew,NEW_KAME_1); if ( IS_SET(victim->pcdata->actnew,NEW_KAME_2) ) REMOVE_BIT(victim->pcdata->actnew,NEW_KAME_2); if ( IS_SET(victim->pcdata->actnew,NEW_MASENKOUHA) ) REMOVE_BIT(victim->pcdata->actnew,NEW_MASENKOUHA); } else if ( IS_CLASS(victim,CLASS_SORCERER) ) { while ( victim->pcdata->chant != NULL ) lose_chant( victim ); } break; if ( IS_NPC(ch) && !IS_NPC(victim) && IS_SET(ch->act,ACT_FINISH) ) do_finish( ch, victim->name ); case POS_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are incapacitated and will slowly die, if not aided.\n\r", victim ); break; case POS_STUNNED: act( "$n is stunned, but will probably recover.", victim, NULL, NULL, TO_ROOM ); send_to_char("You are stunned, but will probably recover.\n\r", victim ); break; case POS_DEAD: act( "$n is DEAD!!", victim, 0, 0, TO_ROOM ); send_to_char( "You have been KILLED!!\n\r\n\r", victim ); break; default: if ( dam > victim->max_hit / 4 ) send_to_char( "That really did HURT!\n\r", victim ); break; } /* * Sleep spells and extremely wounded folks. */ if ( !IS_AWAKE(victim) ) stop_fighting( victim, FALSE ); if ( !IS_NPC(victim) && victim->position < POS_STUNNED ) { stop_fighting( ch, FALSE ); stop_fighting( victim, TRUE ); if ( !IS_NPC(ch) ) { sprintf( log_buf, "%s morted by %s at %d from %d.", victim->name, ch->name, victim->in_room->vnum, ch->in_room->vnum ); log_string( log_buf ); } if ( IS_NPC(ch) && victim->position == POS_MORTAL && IS_SET(ch->act,ACT_FINISH) ) do_finish( ch, victim->name ); } /* * Payoff for killing things. */ if ( victim->position == POS_DEAD ) { if ( !IS_NPC(ch) ) { ch->pcdata->kills[MK]++; clan_table[ch->pcdata->clan[CLAN]].mobkills++; } if ( !IS_NPC(victim) ) { victim->pcdata->kills[MD]++; clan_table[victim->pcdata->clan[CLAN]].mobdeaths++; } group_gain( ch, victim ); if ( !IS_NPC(victim) ) { sprintf( log_buf, "%s killed by %s at %d", victim->name, (IS_NPC(ch) ? ch->short_descr : ch->name), victim->in_room->vnum ); log_string( log_buf ); /* * Dying penalty: * 1/2 way back to previous level. * taken out if ( victim->exp > 1000 * victim->level ) gain_exp( victim, (1000 * victim->level - victim->exp)/2 ); */ } check_quest( ch, victim ); if ( IS_NPC(victim) && victim->level >= 50 ) rand_obj( victim ); raw_kill( victim, FALSE ); if ( !IS_NPC(ch) && IS_NPC(victim) ) { if ( IS_SET(ch->act, PLR_AUTOLOOT) ) do_get( ch, "all corpse" ); else do_look( ch, "in corpse" ); if ( IS_SET(ch->act, PLR_AUTOSAC) ) do_sacrifice( ch, "corpse" ); } return dam; } if ( victim == ch ) return -1; /* * Take care of link dead people. * Fucking abusable if ( !IS_NPC(victim) && victim->desc == NULL ) { if ( number_range( 0, victim->wait ) == 0 ) { do_recall( victim, "" ); return; } } fuckin' pansies */ /* * Wimp out? */ if ( IS_NPC(victim) && dam > 0 ) { if ( ( IS_SET(victim->act, ACT_WIMPY) && number_bits( 1 ) == 0 && victim->hit < victim->max_hit / 2 ) || ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL && victim->master->in_room != victim->in_room ) ) do_flee( victim, "" ); } if ( !IS_NPC(victim) && victim->hit > 0 && victim->hit <= victim->wimpy && victim->wait == 0 ) send_to_char( "You're a fucking PANSY ASS BITCH!!", victim ); /* Clumsy positioning necessary because of parry/dodge */ if ( dam > 0 && dt == TYPE_HIT && ch && victim && IS_CLASS(ch,CLASS_FIST) && IS_NPC(victim) ) { if ( is_affected(ch,gsn_golden_blaze) ) damage( ch, victim, 400 + number_percent(), DAM_KIFLAME ); if ( is_affected(ch,gsn_judicators_ire) && victim ) damage( ch, victim, 400 + number_percent(), DAM_SHOCKWAVE ); if ( is_affected(ch,gsn_dark_blaze) && number_percent() < 50 && victim ) { i = victim->hit; damage( ch, victim, 200 + number_percent(), DAM_NEGATIVE ); if ( victim && victim->position > POS_STUNNED ) { i -= victim->hit; ch->hit = UMIN(ch->max_hit,ch->hit+i); ch->move = UMIN(ch->max_move,ch->move+i); } } } tail_chain( ); return dam; } /* * Damage function for sorcerer chants */ void chant_damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) { int mod, rank, school; if ( victim->position == POS_DEAD ) return; /* * Stop up any residual loopholes. */ if ( dam > 30000 ) { bug( "Damage: %d: more than 30000 points!", dam ); dam = 30000; } if ( victim != ch ) { /* * Certain attacks are forbidden. * Most other attacks are returned. */ if ( is_safe( ch, victim ) ) return; if ( victim->position > POS_STUNNED ) { if ( victim->fighting == NULL ) set_fighting( victim, ch ); victim->position = POS_FIGHTING; } if ( victim->position > POS_STUNNED ) { if ( ch->fighting == NULL ) set_fighting( ch, victim ); /* * If victim is charmed, ch might attack victim's master. */ if ( IS_NPC(ch) && IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL && victim->master->in_room == ch->in_room && number_bits( 3 ) == 0 ) { stop_fighting( ch, FALSE ); multi_hit( ch, victim->master, TYPE_UNDEFINED ); return; } } /* * More charm stuff. */ if ( victim->master == ch ) stop_follower( victim ); /* * Inviso attacks ... not. */ if ( IS_AFFECTED(ch, AFF_INVISIBLE) ) { affect_strip( ch, gsn_invis ); affect_strip( ch, gsn_mass_invis ); REMOVE_BIT( ch->affected_by, AFF_INVISIBLE ); act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM ); } /* no attacking avatars, bitch */ if ( !IS_NPC(victim) && victim->level < 2 ) { send_to_char( "Don't fuck with mortals.\n\r", ch ); return; } /* I am no longer willing to tolerate this pussy trash. */ if ( !str_cmp( ch->name, "Karth" ) ) dam -= dam / 15; rank = chant_table[dt].rank; school = chant_table[dt].school; /* * Check for curses being removed. */ if ( school == SCHOOL_WIND ) { if ( is_affected(ch,gsn_wind_curse) ) affect_strip(ch,gsn_wind_curse); if ( is_affected(ch,gsn_earth_curse) && is_affected(ch,gsn_flame_curse) ) { act( "Your spell fizzles and dies!", ch, NULL, NULL, TO_CHAR ); act( "$n's spell fizzles and dies.", ch, NULL, NULL, TO_ROOM ); return; } } if ( school == SCHOOL_EARTH ) { if ( is_affected(ch,gsn_earth_curse) ) affect_strip(ch,gsn_earth_curse); if ( is_affected(ch,gsn_wind_curse) && is_affected(ch,gsn_water_curse) ) { act( "Your spell fizzles and dies!", ch, NULL, NULL, TO_CHAR ); act( "$n's spell fizzles and dies.", ch, NULL, NULL, TO_ROOM ); return; } } if ( school == SCHOOL_FIRE ) { if ( is_affected(ch,gsn_flame_curse) ) affect_strip(ch,gsn_flame_curse); if ( is_affected(ch,gsn_water_curse) && is_affected(ch,gsn_earth_curse) ) { act( "Your spell fizzles and dies!", ch, NULL, NULL, TO_CHAR ); act( "$n's spell fizzles and dies.", ch, NULL, NULL, TO_ROOM ); return; } } if ( school == SCHOOL_WATER ) { if ( is_affected(ch,gsn_water_curse) ) affect_strip(ch,gsn_water_curse); if ( is_affected(ch,gsn_flame_curse) && is_affected(ch,gsn_wind_curse) ) { act( "Your spell fizzles and dies!", ch, NULL, NULL, TO_CHAR ); act( "$n's spell fizzles and dies.", ch, NULL, NULL, TO_ROOM ); return; } } if ( school == SCHOOL_BLACK ) { if ( is_affected(ch,gsn_flame_curse) && is_affected(ch,gsn_water_curse) ) { act( "Your spell fizzles and dies!", ch, NULL, NULL, TO_CHAR ); act( "$n's spell fizzles and dies.", ch, NULL, NULL, TO_ROOM ); return; } } if ( school == SCHOOL_ASTRAL ) { if ( is_affected(ch,gsn_earth_curse) && is_affected(ch,gsn_wind_curse) ) { act( "Your spell fizzles and dies!", ch, NULL, NULL, TO_CHAR ); act( "$n's spell fizzles and dies.", ch, NULL, NULL, TO_ROOM ); return; } } /* * Damage modifiers. */ if ( IS_AFFECTED(victim, AFF_SANCTUARY) && !IS_SUIT(victim) ) dam /= 2; /* No lowbies fucking with maxed char fights */ if ( !IS_NPC(ch) && (!IS_NPC(victim) || victim->level >= 96) && ch->pcdata->extras2[EVAL] < 50 ) { dam = dam * (1 + ch->pcdata->extras2[EVAL]/10) / 6; } /* damage reduction from toughness */ if ( IS_AFFECTED(victim,AFF_STEELY) ) dam = dam / 5; if ( IS_NPC(victim) ) { dam -= dam * victim->level / (300 + rank*2); if ( victim->level > 95 ) dam -= dam * (victim->level - 95) * 10 / 100; } else if (IS_SUIT(victim) ) { if ( school == SCHOOL_WIND ) dam *= 2; dam -= dam * (suit_table[victim->pcdata->suit[SUIT_NUMBER]].armor - 60) / 160; } else { if ( victim->class == CLASS_SAIYAN ) { if ( is_affected(victim,gsn_kiwall) ) dam /= 2; if ( victim->pcdata->powers[S_AEGIS] > 0 ) { dam -= (dam * victim->pcdata->powers[S_AEGIS]+dice(1,300)) / (1200+rank*4); victim->pcdata->powers[S_AEGIS] = UMAX( victim->pcdata->powers[S_AEGIS_MAX] / 2, victim->pcdata->powers[S_AEGIS] - isquare(dam) ); } } else if ( victim->class == CLASS_FIST ) { if ( IS_SET(victim->pcdata->actnew,NEW_FIGUREEIGHT) ) dam /= 2; if ( victim->pcdata->powers[F_TORSO] > 0 ) dam -= dam * ( dice(1,10) + victim->pcdata->powers[F_TORSO] ) / 127; } else if ( IS_CLASS(victim,CLASS_PATRYN) ) { if ( get_runes(victim,RUNE_FIRE,TORSO) > 0 ) mod = get_runes(victim,RUNE_EARTH,TORSO); else mod = get_runes(victim,RUNE_EARTH,TORSO)/2; dam -= (dam * mod * victim->pcdata->powers[P_AIR]) / ((mod+4) * 100+(rank*5)); switch( school ) { case SCHOOL_WIND: if ( is_affected( victim, gsn_water_ward ) ) { dam = UMAX( dam - 100, 1 ); dec_duration( victim, gsn_water_ward, 100 ); } if ((mod = get_runes(victim,RUNE_WATER,TORSO)) > 0 ) { if ( is_affected( victim, gsn_water_ward ) ) dam += dam * mod / 6; else dam += dam * mod / 3; } break; case SCHOOL_EARTH: if ( is_affected( victim, gsn_earth_ward ) ) { dam = UMAX( dam - 100, 1 ); dec_duration( victim, gsn_earth_ward, 100 ); } break; case SCHOOL_FIRE: if ( is_affected( victim, gsn_flame_ward ) ) { dam = UMAX( dam - 100, 1 ); dec_duration( victim, gsn_flame_ward, 100 ); } break; case SCHOOL_WATER: if ( is_affected( victim, gsn_water_ward ) ) { dam = UMAX( dam - 100, 1 ); dec_duration( victim, gsn_water_ward, 100 ); } break; case SCHOOL_ASTRAL: if ( is_affected( victim, gsn_spirit_ward ) ) { dam = UMAX( dam - 100, 1 ); dec_duration( victim, gsn_spirit_ward, 100 ); } break; case 2: if ( is_affected( victim, gsn_negative_ward ) ) { dam = UMAX( dam - 100, 1 ); dec_duration( victim, gsn_negative_ward, 100 ); } break; default: break; }; } if ( victim->class == CLASS_SORCERER ) { if ( IS_AFFECTED(victim,AFF_HOLY_RESIST) ) dam -= dam * 2 * (victim->pcdata->powers[SCHOOL_WHITE]-20) / 100; if ( is_affected(victim,gsn_mos_varim) && chant_table[dt].school == SCHOOL_FIRE) dam -= dam * (victim->pcdata->powers[SCHOOL_WHITE]-20) / 35; if ( is_affected(victim,gsn_balus_wall) && school == SCHOOL_FIRE ) { dam = 0; act( "Your attack is sucked into a flourescent wall.", ch, NULL, victim, TO_CHAR ); act( "Your Balus Wall absorbs $n's attack and vanishes!",ch,NULL,victim,TO_VICT ); act( "$n's attack is absorbed by a flourescent wall.",ch,NULL,victim,TO_NOTVICT); affect_strip(victim,gsn_balus_wall); } } if ( IS_CLASS(victim,CLASS_MAZOKU) ) { if ( school == SCHOOL_WHITE ) dam += dam / 2; if ( IS_SET(victim->pcdata->powers[M_SET],M_HUMAN) ) dam -= dam * (victim->pcdata->powers[M_MATTER]+12) / 135; else if ( IS_SET(victim->pcdata->powers[M_SET],M_BATTLE) ) dam -= dam * victim->pcdata->powers[M_MATTER] / 135; else dam -= dam * victim->pcdata->powers[M_ASTRAL] / 150; if ( victim->pcdata->powers[M_NIHILISM] > 0 ) dam -= dam * victim->pcdata->powers[M_NIHILISM] / 400; if ( victim->pcdata->powers[M_CTIME] >= 10 ) victim->pcdata->powers[M_CTIME] -= dam/250; } } } if ( dam < 0 ) dam = 0; timer_check( ch, victim ); add_inf( ch, victim, dam ); dam_message( ch, victim, dam, (dt+1400) ); if ( IS_SUIT(victim) ) { suit_damage( victim, dam ); return; } /* * Hurt the victim. * Inform the victim of his new state. */ victim->hit -= dam; if ( !IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL && victim->hit < 1 ) victim->hit = 1; update_pos( victim ); if ( IS_CLASS(victim,CLASS_MAZOKU) && dam > victim->max_hit/10 ) { if ( victim->pcdata->powers[M_NIHILISM] < 100 ) victim->pcdata->powers[M_NIHILISM]++; } /* End combat on morting or killing */ if ( victim->position <= POS_STUNNED ) stop_fighting(ch,FALSE); switch( victim->position ) { case POS_MORTAL: act( "$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are mortally wounded, and will die soon, if not aided.\n\r", victim ); if ( IS_CLASS(victim,CLASS_SAIYAN) ) { if ( IS_SET(victim->pcdata->actnew,NEW_KAME_1) ) REMOVE_BIT(victim->pcdata->actnew,NEW_KAME_1); if ( IS_SET(victim->pcdata->actnew,NEW_KAME_2) ) REMOVE_BIT(victim->pcdata->actnew,NEW_KAME_2); if ( IS_SET(victim->pcdata->actnew,NEW_MASENKOUHA) ) REMOVE_BIT(victim->pcdata->actnew,NEW_MASENKOUHA); } else if ( IS_CLASS(victim,CLASS_SORCERER) ) { while ( victim->pcdata->chant != NULL ) lose_chant( victim ); } break; case POS_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are incapacitated and will slowly die, if not aided.\n\r", victim ); break; case POS_STUNNED: act( "$n is stunned, but will probably recover.", victim, NULL, NULL, TO_ROOM ); send_to_char("You are stunned, but will probably recover.\n\r", victim ); break; case POS_DEAD: act( "$n is DEAD!!", victim, 0, 0, TO_ROOM ); send_to_char( "You have been KILLED!!\n\r\n\r", victim ); break; default: if ( dam > victim->max_hit / 4 ) send_to_char( "That really did HURT!\n\r", victim ); break; } /* * Sleep spells and extremely wounded folks. */ if ( !IS_AWAKE(victim) ) stop_fighting( victim, FALSE ); /* if ( IS_NPC(victim) || !morted ) stop_fighting( ch, FALSE ); */ /* * Payoff for killing things. */ if ( victim->position == POS_DEAD ) { if ( !IS_NPC(ch) ) { ch->pcdata->kills[MK]++; clan_table[ch->pcdata->clan[CLAN]].mobkills++; } if ( !IS_NPC(victim) ) { victim->pcdata->kills[MD]++; clan_table[victim->pcdata->clan[CLAN]].mobdeaths++; } group_gain( ch, victim ); if ( !IS_NPC(victim) ) { sprintf( log_buf, "%s killed by %s at %d", victim->name, (IS_NPC(ch) ? ch->short_descr : ch->name), victim->in_room->vnum ); log_string( log_buf ); } check_quest( ch, victim ); raw_kill( victim, FALSE ); if ( !IS_NPC(ch) && IS_NPC(victim) ) { if ( IS_SET(ch->act, PLR_AUTOLOOT) ) do_get( ch, "all corpse" ); else do_look( ch, "in corpse" ); if ( IS_SET(ch->act, PLR_AUTOSAC) ) do_sacrifice( ch, "corpse" ); } return; } if ( victim == ch ) return; /* * Wimp out? */ if ( IS_NPC(victim) && dam > 0 ) { if ( ( IS_SET(victim->act, ACT_WIMPY) && number_bits( 1 ) == 0 && victim->hit < victim->max_hit / 4 ) || ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL && victim->master->in_room != victim->in_room ) ) do_flee( victim, "" ); } /* no pussy assed wimpy if ( !IS_NPC(victim) && victim->hit > 0 && victim->hit <= victim->wimpy && victim->wait == 0 ) do_flee( victim, "" ); */ tail_chain( ); return; } bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim ) { if ( IS_NPC(ch) || IS_NPC(victim) ) return FALSE; if ( IS_SET( victim->act, PLR_KILLER ) ) return FALSE; if ( ch->level < 2 ) { send_to_char( "Only avatars can kill players.\n\r", ch ); return TRUE; } if ( victim->level < 2 ) { send_to_char( "But they're not an avatar!", ch ); return TRUE; } return FALSE; } /* * Check for parry. */ bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim ) { OBJ_DATA *chw; int stance, chdt, suit, reflex; int chance = 0; int chstance = 0; int runes = 0; if ( !IS_AWAKE(victim) ) return FALSE; chw = get_eq_char( ch, WEAR_WIELD ); if ( chw == NULL ) chdt = 0; else chdt = chw->value[3]; chstance = stanced( ch ); if ( IS_NPC(victim) ) { chance += victim->level * 3 / 2; if ( IS_AFFECTED(ch,AFF_VISFARANK) ) return FALSE; } else if ( IS_SUIT(victim) ) { if ( !IS_SET(victim->pcdata->suit[SUIT_EQ],MS_BUCKLER) && !IS_SET(victim->pcdata->suit[SUIT_EQ],MS_HEATER) && !IS_SET(victim->pcdata->suit[SUIT_EQ],MS_BEAM_SABRE) && !IS_SET(victim->pcdata->suit[SUIT_EQ],MS_CRASHER) && !IS_SET(victim->pcdata->suit[SUIT_EQ],MS_BEAM_SCYTHE)&& !IS_SET(victim->pcdata->suit[SUIT_EQ],MS_BEAM_GLAIVE)&& !IS_SET(victim->pcdata->suit[SUIT_EQ],MS_HEAT_SHOTELS)&& !IS_SET(victim->pcdata->suit[SUIT_EQ],MS_BEAM_SWORD) ) return FALSE; suit = victim->pcdata->suit[SUIT_NUMBER]; reflex = victim->pcdata->suit[SUIT_REFLEX]; chance += ((suit_table[suit].power -80)*2/3) + isquare(reflex); if ( IS_SET(victim->pcdata->suit[SUIT_EQ],MS_BUCKLER) || IS_SET(victim->pcdata->suit[SUIT_EQ],MS_CRASHER) ) chance += 15; else if ( IS_SET(victim->pcdata->suit[SUIT_EQ],MS_HEATER) ) chance += 30; if ( dice(1, 1+reflex+isquare(reflex)) > reflex ) if ( reflex < 2500 && reflex < (victim->pcdata->extras2[EVAL]*45) ) victim->pcdata->suit[SUIT_REFLEX]++; } else { stance = stanced( victim ); if ( stance ) chance += ( victim->pcdata->stances[stance] / 40 ) * ( stance_table[stance].parry[chstance] ); if ( get_eq_char( victim, WEAR_WIELD ) == NULL && ( !(IS_CLASS(victim,CLASS_SAIYAN) && victim->pcdata->powers[S_AEGIS] >= 250) && !IS_CLASS(victim,CLASS_MAZOKU) ) ) return FALSE; chance += victim->pcdata->weapons[chdt] / 5; if ( victim->class == CLASS_PATRYN ) { runes = get_runes(victim,RUNE_EARTH,LEFTARM)+get_runes(victim,RUNE_EARTH,RIGHTARM); chance += runes * 8; chance += victim->pcdata->powers[P_EARTH] * 2 / 5; } if ( victim->class == CLASS_FIST ) chance /= 2; if ( IS_CLASS(victim,CLASS_MAZOKU) ) { if ( IS_SET(victim->pcdata->powers[M_SET],M_THIRD) ) chance += 5; if ( IS_SET(victim->pcdata->powers[M_SET],M_FOURTH) ) chance += 5; if ( IS_SET(victim->pcdata->powers[M_SET],M_FIFTH) ) chance += 5; if ( IS_SET(victim->pcdata->powers[M_SET],M_SIXTH) ) chance += 5; else if ( IS_SET(victim->pcdata->powers[M_SET],M_HUMAN) ) chance += 20; if ( IS_SET(victim->pcdata->powers[M_SET],M_BLADES) ) chance += 20; else if ( IS_SET(victim->pcdata->powers[M_SET],M_TENTACLES) ) chance += 30; else if ( IS_SET(victim->pcdata->powers[M_SET],M_SPIKES) ) chance += 15; else if ( IS_SET(victim->pcdata->powers[M_SET],M_CLAWS) ) chance += 10; chance -= victim->pcdata->powers[M_NIHILISM]/2; chance += UMIN(100,victim->pcdata->powers[M_EGO]) / 2; } } if ( IS_NPC(ch) ) { chance -= victim->level * 3 / 2; } else { chance -= ch->pcdata->weapons[chdt] / 5; if ( ch->class == CLASS_SAIYAN ) { chance -= isquare( ch->pcdata->powers[S_SPEED] ); if ( is_affected(ch,gsn_kaiouken) ) return FALSE; } if ( ch->class == CLASS_PATRYN ) { runes = get_runes(ch,RUNE_EARTH,LEFTLEG) + get_runes(ch,RUNE_EARTH,RIGHTLEG); chance -= runes * UMIN(13,21-runes); } if ( IS_CLASS(ch,CLASS_MAZOKU) ) { chance -= ch->pcdata->powers[M_NIHILISM]/3; if ( IS_SET(ch->pcdata->powers[M_SET],M_SPIKES) ) chance -= ch->pcdata->powers[M_FOCUS]/2+20; if ( IS_SET(ch->pcdata->powers[M_SET],M_CLAWS) ) chance -= ch->pcdata->powers[M_FOCUS]/3; if ( IS_SET(ch->pcdata->powers[M_SET],M_BLADES) ) chance -= ch->pcdata->powers[M_FOCUS]/3; if ( IS_SET(ch->pcdata->powers[M_SET],M_ASTRIKE) ) chance /= 2; } if ( IS_WIELDING(ch,LAGUNA_BLADE) ) return FALSE; if ( IS_SUIT(ch) ) return FALSE; } chance = URANGE( 20, chance, 80 ); if ( IS_NPC(ch) && ch->level > 95 ) chance -= (ch->level - 95) * 5; if ( number_percent( ) >= chance ) return FALSE; if ( !IS_SET( victim->act, PLR_BRIEF ) && !IS_NPC(victim) ) act( "You parry $n's attack.", ch, NULL, victim, TO_VICT ); if ( !IS_SET( ch->act, PLR_BRIEF ) && !IS_NPC(ch) ) act( "$N parries your attack.", ch, NULL, victim, TO_CHAR ); return TRUE; } /* * Check for dodge. */ bool check_dodge( CHAR_DATA *ch, CHAR_DATA *victim ) { int chance = 0; int suit, reflex, runes; if ( !IS_AWAKE(victim) ) return FALSE; if ( IS_NPC(victim) ) { chance += victim->level * 3 / 2; if ( IS_AFFECTED(ch,AFF_VISFARANK) ) chance /= 2; } else if ( IS_SUIT(victim) ) { suit = victim->pcdata->suit[SUIT_NUMBER]; reflex = victim->pcdata->suit[SUIT_REFLEX]; chance += (suit_table[suit].speed - 80) + isquare(reflex); if ( dice(1, 1+reflex+isquare(reflex)) > reflex ) if ( reflex < 2500 && reflex < (victim->pcdata->extras2[EVAL]*45) ) victim->pcdata->suit[SUIT_REFLEX]++; } else { if ( ch->level >= 2 ) chance += victim->pcdata->weapons[0] / 5; else chance += UMIN( victim->pcdata->weapons[0], 200 ) / 5; if ( victim->class == CLASS_SAIYAN ) { chance += victim->pcdata->powers[S_SPEED] / 7; if ( is_affected(victim,gsn_kaiouken) ) chance *= 2; } if ( victim->class == CLASS_PATRYN ) { runes = get_runes(victim,RUNE_WATER,LEFTLEG); runes += get_runes(victim,RUNE_WATER,RIGHTLEG); if ( runes >= 8 ) chance += 90; else chance += runes*12; chance += UMAX(runes-8,1) * 5; } if ( victim->class == CLASS_SORCERER ) if ( IS_AFFECTED(victim,AFF_RAYWING) ) chance += (victim->pcdata->powers[SCHOOL_WIND]-7)*2; if ( IS_CLASS(victim,CLASS_MAZOKU) ) { if ( IS_SET(victim->pcdata->powers[M_SET],M_BATTLE) ) chance += victim->pcdata->powers[M_MATTER]*3/4; if ( IS_SET(victim->pcdata->powers[M_SET],M_HUMAN) ) chance += victim->pcdata->powers[M_MATTER]/2; } } if ( IS_NPC(ch) ) chance -= ch->level * 3 / 2; else { chance -= ch->pcdata->weapons[0] / 5; if ( ch->class == CLASS_SAIYAN ) { if ( is_affected(ch,gsn_kaiouken) ) chance -= ch->pcdata->powers[S_SPEED] / 10; else chance -= ch->pcdata->powers[S_SPEED] / 15; } if ( ch->class == CLASS_PATRYN ) { runes = get_runes(ch,RUNE_EARTH,LEFTLEG); runes += get_runes(ch,RUNE_EARTH,RIGHTLEG); if ( runes <= 9 ) chance -= runes * 9; else chance -= runes * 7; } if ( IS_CLASS(ch,CLASS_MAZOKU) ) { chance -= ch->pcdata->powers[M_NIHILISM]/3; if ( IS_SET(ch->pcdata->powers[M_SET],M_CLAWS) ) chance -= ch->pcdata->powers[M_FOCUS]/2; if ( IS_SET(ch->pcdata->powers[M_SET],M_SPIKES) ) chance -= ch->pcdata->powers[M_FOCUS]/2+20; if ( IS_SET(ch->pcdata->powers[M_SET],M_BLADES) ) chance -= ch->pcdata->powers[M_FOCUS]/3; if ( IS_SET(ch->pcdata->powers[M_SET],M_TENTACLES) ) chance -= (ch->pcdata->powers[M_FOCUS]+ch->pcdata->powers[M_MATTER])/3; if ( IS_SET(ch->pcdata->powers[M_SET],M_ASTRIKE) ) { if ( IS_CLASS(victim,CLASS_MAZOKU) && IS_SET(victim->pcdata->powers[M_SET],M_TRUE) ) { chance = 80; } else chance -= chance/4; } } if ( IS_WIELDING(ch,LAGUNA_BLADE) ) chance /= 2; if ( IS_SUIT(ch) ) return FALSE; } chance = URANGE( 20, chance, 80 ); if ( IS_NPC(ch) && ch->level > 95 ) chance -= (ch->level - 95 ) * 5; if ( number_percent( ) >= chance ) return FALSE; if ( !IS_SET( victim->act, PLR_BRIEF ) && !IS_NPC(victim) ) act( "You dodge $n's attack.", ch, NULL, victim, TO_VICT ); if ( !IS_SET( ch->act, PLR_BRIEF ) && !IS_NPC(ch) ) act( "$N dodges your attack.", ch, NULL, victim, TO_CHAR ); return TRUE; } /* * Monk defensive skill */ bool check_block( CHAR_DATA *ch, CHAR_DATA *victim ) { int chance = 0; if ( IS_NPC(victim) ) return FALSE; if ( victim->class != CLASS_FIST ) return FALSE; if ( victim->level < 2 ) return FALSE; if ( victim->position < POS_STUNNED ) return FALSE; if ( IS_SUIT(victim) ) return FALSE; if ( get_eq_char( victim, WEAR_WIELD ) != NULL ) return FALSE; chance += (victim->pcdata->powers[F_ARMS] / 2) + (victim->pcdata->weapons[0] / 10); if ( IS_NPC(ch) ) chance -= ch->level / 2; else { if ( ch->class == CLASS_SAIYAN ) { chance -= ch->pcdata->powers[S_SPEED] / 40; if ( is_affected(ch,gsn_kaiouken) ) return FALSE; } if ( ch->class == CLASS_FIST ) chance -= ch->pcdata->powers[F_ARMS] * 3 / 8; if ( ch->class == CLASS_PATRYN ) chance -= 8 * (get_runes(ch,RUNE_EARTH,LEFTLEG)+get_runes(ch,RUNE_EARTH,RIGHTLEG)); if ( IS_CLASS(ch,CLASS_MAZOKU) ) { if ( IS_SET(ch->pcdata->powers[M_SET],M_SPIKES) ) chance -= ch->pcdata->powers[M_MATTER]*2/3; if ( IS_SET(ch->pcdata->powers[M_SET],M_BLADES) || IS_SET(ch->pcdata->powers[M_SET],M_CLAWS) ) chance -= ch->pcdata->powers[M_MATTER]/2; if ( IS_SET(ch->pcdata->powers[M_SET],M_ASTRIKE) ) chance /= 2; } if( IS_WIELDING(ch,LAGUNA_BLADE) ) chance /= 3; if ( IS_SUIT(ch) ) return FALSE; } if (IS_SET(victim->pcdata->actnew,NEW_NOBLOCK) ) return FALSE; chance = URANGE( 25, chance, 85 ); if ( IS_NPC(ch) && ch->level > 95 ) chance -= (ch->level - 95) * 5; if ( number_percent() >= chance ) return FALSE; if ( !IS_SET( victim->act, PLR_BRIEF ) && !IS_NPC(victim) ) act( "You block $n's attack.", ch, NULL, victim, TO_VICT ); if ( !IS_SET( ch->act, PLR_BRIEF ) && !IS_NPC(ch) ) act( "$N blocks your attack.", ch, NULL, victim, TO_CHAR ); return TRUE; } bool check_shields( CHAR_DATA *ch, CHAR_DATA *victim ) { int num; if ( IS_AFFECTED(victim,AFF_STEELY) && number_percent() > 20 ) { if ( !IS_SET(ch->act,PLR_BRIEF) ) act( "Your blow skitters off $N's incredible battle aura.", ch, NULL, victim, TO_CHAR ); if ( !IS_SET(victim->act,PLR_BRIEF) ) act( "$n's blow skitters off your battle aura.", ch, NULL, victim, TO_VICT ); return TRUE; } if ( IS_NPC(victim) ) return FALSE; if ( IS_SUIT(victim) ) { if ( IS_SET(victim->pcdata->suit[SUIT_EQ],MS_SHIELDS) ) { if ( number_percent() < 50 && victim->pcdata->suit[SUIT_PLASMA] > 0 ) { victim->pcdata->suit[SUIT_PLASMA]--; if ( !IS_SET(ch->act,PLR_BRIEF) ) act( "$N's planet shields block your attack.", ch, NULL, victim, TO_CHAR ); if ( !IS_SET(victim->act,PLR_BRIEF) ) act( "Your planet shields block $n's attack.", ch, NULL, victim, TO_VICT ); return TRUE; } } return FALSE; } if ( IS_SET(victim->pcdata->actnew,NEW_VAN_REHL) ) { if ( number_percent() < 50 ) { if ( !IS_SET(ch->act,PLR_BRIEF) ) act( "Your attack slides off an icy barrier.", ch, NULL, victim, TO_CHAR ); if ( !IS_SET(victim->act,PLR_BRIEF) ) act( "$n's attack slides off your icy barrier.", ch, NULL, victim, TO_VICT ); } } if ( IS_AFFECTED(victim,AFF_WINDY_SHIELD) ) { num = 30 + (victim->pcdata->powers[SCHOOL_WIND]-40); if ( IS_CLASS(ch,CLASS_SAIYAN) && is_affected(ch,gsn_kaiouken) ) num -= num / 4; if ( number_percent() < num ) { act( "Your windy shield deflects $n's attack.", ch, NULL, victim, TO_VICT ); act( "$N's windy shield deflects your attack.", ch, NULL, victim, TO_CHAR ); return TRUE; } } if ( is_affected(victim,gsn_defense) ) { if ( IS_NPC(ch) && ch->level >= 95 ) { act( "Your defense barrier shatters!", ch, NULL, victim, TO_VICT ); act( "$N's defense barrier shatters!", ch, NULL, victim, TO_CHAR ); affect_strip(victim,gsn_defense); return FALSE; } act( "Your defense barrier blocks $n's blow.", ch, NULL, victim, TO_VICT ); act( "$N's defense barrier blocks your blow.", ch, NULL, victim, TO_CHAR ); return TRUE; } return FALSE; } /* * Set position of a victim. */ void update_pos( CHAR_DATA *victim ) { if ( victim->hit > 0 ) { if ( victim->position <= POS_STUNNED ) victim->position = POS_STANDING; return; } if ( IS_NPC(victim) || (victim->hit <= -10 && victim->level < 2) ) { victim->position = POS_DEAD; return; } if ( victim->hit < -10 ) victim->hit = -10; if ( victim->hit <= -6 ) victim->position = POS_MORTAL; else if ( victim->hit <= -3 ) victim->position = POS_INCAP; else victim->position = POS_STUNNED; return; } /* * Start fights. */ void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim ) { if ( ch->fighting != NULL ) { bug( "Set_fighting: already fighting", 0 ); return; } if ( IS_AFFECTED(ch, AFF_SLEEP) ) affect_strip( ch, gsn_sleep ); ch->fighting = victim; ch->position = POS_FIGHTING; return; } /* * Stop fights. */ void stop_fighting( CHAR_DATA *ch, bool fBoth ) { CHAR_DATA *fch; for ( fch = char_list; fch != NULL; fch = fch->next ) { if ( fch == ch || ( fBoth && fch->fighting == ch ) ) { fch->fighting = NULL; fch->position = POS_STANDING; update_pos( fch ); } } return; } /* * Make a corpse out of a character. */ void make_corpse( CHAR_DATA *ch, bool pdox ) { char buf[MAX_STRING_LENGTH]; OBJ_DATA *corpse; OBJ_DATA *obj; OBJ_DATA *obj_next; char *name; if ( IS_NPC(ch) ) { name = ch->short_descr; corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0); corpse->timer = number_range( 2, 4 ); if ( ch->gold > 0 ) { obj_to_obj( create_money( ch->gold ), corpse ); ch->gold = 0; } } else { name = ch->name; corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0); corpse->timer = number_range( 50, 80 ); corpse->pIndexData->value[0] = 0; } sprintf( buf, corpse->short_descr, name ); free_string( corpse->short_descr ); corpse->short_descr = str_dup( buf ); sprintf( buf, corpse->description, name ); free_string( corpse->description ); corpse->description = str_dup( buf ); for ( obj = ch->carrying; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; /* * If item is claimed, or is non-unique on a pdox cap, * item stays with the char, unequipped. Otherwise, * send item to corpse. */ if ( (!IS_NPC(ch) && is_name( obj->owner, ch->name )) || (pdox && !IS_OBJ_STAT(obj,ITEM_UNIQUE)) ) { if ( obj->wear_loc != -1 ) unequip_char( ch, obj ); } else { obj_from_char( obj ); if ( IS_SET(obj->extra_flags,ITEM_INVENTORY) ) extract_obj( obj ); else obj_to_obj( obj, corpse ); } } obj_to_room( corpse, ch->in_room ); return; } /* * Improved Death_cry contributed by Diavolo. */ void death_cry( CHAR_DATA *ch ) { ROOM_INDEX_DATA *was_in_room; char *msg; int door; int vnum; vnum = 0; switch ( number_bits( 4 ) ) { default: msg = "You hear $n's death cry."; break; case 0: msg = "$n hits the ground ... DEAD."; break; case 1: msg = "$n splatters blood on your armor."; break; case 2: msg = "You smell $n's sphincter releasing in death."; vnum = OBJ_VNUM_FINAL_TURD; break; case 3: msg = "$n's severed head plops on the ground."; vnum = OBJ_VNUM_SEVERED_HEAD; break; case 4: msg = "$n's heart is torn from $s chest."; vnum = OBJ_VNUM_TORN_HEART; break; case 5: msg = "$n's arm is sliced from $s dead body."; vnum = OBJ_VNUM_SLICED_ARM; break; case 6: msg = "$n's leg is sliced from $s dead body."; vnum = OBJ_VNUM_SLICED_LEG; break; } act( msg, ch, NULL, NULL, TO_ROOM ); if ( vnum != 0 ) { char buf[MAX_STRING_LENGTH]; OBJ_DATA *obj; char *name; name = IS_NPC(ch) ? ch->short_descr : ch->name; obj = create_object( get_obj_index( vnum ), 0 ); obj->timer = number_range( 4, 7 ); sprintf( buf, obj->short_descr, name ); free_string( obj->short_descr ); obj->short_descr = str_dup( buf ); sprintf( buf, obj->description, name ); free_string( obj->description ); obj->description = str_dup( buf ); obj_to_room( obj, ch->in_room ); } if ( IS_NPC(ch) ) msg = "You hear something's death cry."; else msg = "You hear someone's death cry."; was_in_room = ch->in_room; for ( door = 0; door <= 5; door++ ) { EXIT_DATA *pexit; if ( ( pexit = was_in_room->exit[door] ) != NULL && pexit->to_room != NULL && pexit->to_room != was_in_room ) { ch->in_room = pexit->to_room; act( msg, ch, NULL, NULL, TO_ROOM ); } } ch->in_room = was_in_room; return; } void raw_kill( CHAR_DATA *victim, bool pdox ) { stop_fighting( victim, TRUE ); mprog_death_trigger( victim ); make_corpse( victim, pdox ); if ( IS_NPC(victim) ) { victim->pIndexData->killed++; kill_table[URANGE(0, victim->level, MAX_LEVEL-1)].killed++; extract_char( victim, TRUE ); return; } extract_char( victim, FALSE ); while ( victim->affected ) affect_remove( victim, victim->affected ); victim->affected_by = 0; victim->armor = 100; victim->position = POS_RESTING; /* not sure whats up with this victim->hit = UMAX( 1, victim->hit ); victim->mana = UMAX( 1, victim->mana ); victim->move = UMAX( 1, victim->move ); */ victim->hit = 1; victim->mana = 1; victim->move = 1; if ( !IS_NPC(victim) && victim->class == CLASS_SAIYAN ) { victim->pcdata->powers[S_POWER] = 5; victim->pcdata->powers[S_SPEED] = victim->pcdata->powers[S_SPEED_MAX]/2; victim->pcdata->powers[S_STRENGTH] = victim->pcdata->powers[S_STRENGTH_MAX]/2; victim->pcdata->powers[S_AEGIS] = victim->pcdata->powers[S_AEGIS_MAX]/2; } if ( IS_NPC(victim) && IS_SET(victim->pcdata->actnew,NEW_DRAGON_SLAVE) ) REMOVE_BIT(victim->pcdata->actnew,NEW_DRAGON_SLAVE); save_char_obj( victim ); return; } void group_gain( CHAR_DATA *ch, CHAR_DATA *victim ) { char buf[MAX_STRING_LENGTH]; CHAR_DATA *gch; CHAR_DATA *lch; int xp; int members; /* * Monsters don't get kill xp's. * P-killing doesn't help either. * Dying of mortal wounds or poison doesn't give xp to anyone! */ if ( IS_NPC(ch) || !IS_NPC(victim) || victim == ch ) return; members = 0; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( is_same_group( gch, ch ) ) members++; } if ( members == 0 ) { bug( "Group_gain: members.", members ); members = 1; } lch = (ch->leader != NULL) ? ch->leader : ch; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( !is_same_group( gch, ch ) ) continue; /* unnecessary in levelless system if ( gch->level - lch->level >= 6 ) { send_to_char( "You are too high for this group.\n\r", gch ); continue; } if ( gch->level - lch->level <= -6 ) { send_to_char( "You are too low for this group.\n\r", gch ); continue; } */ xp = xp_compute( gch, victim ) * 4 / (3+members); if ( ch == gch ) { xp += xp * UMAX( 0, (1200 - ch->played) ) / 1200; if ( IS_CLASS(gch,CLASS_MAZOKU) ) if ( victim->level > gch->pcdata->extras2[EVAL]/2 ) { act( "You bask in $N's dying agony.", gch, NULL, victim, TO_CHAR ); gch->pcdata->powers[M_EGO] = UMIN( 200, gch->pcdata->powers[M_EGO]+1 ); } } if ( ch->in_room != victim->in_room ) xp /= 10; else if ( IS_SUIT(ch) ) xp /= 2; sprintf( buf, "You receive %d experience points.\n\r", xp ); send_to_char( buf, gch ); gain_exp( gch, xp ); } return; } /* * Compute xp for a kill. * Edit this function to change xp computations. */ int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim ) { int xp; xp = 1000 + victim->level * 1000 + victim->max_hit; if ( victim->level > 50 ) xp += victim->level * 250; if ( victim->level > 75 ) xp += victim->level * 500; if ( victim->level > 90 ) xp += victim->level * 1000; if ( victim->level > 95 ) xp += ( victim->level - 95 ) * 200000; /* * Adjust for popularity of target: * -1/8 for each target over 'par' (down to -100%) * +1/8 for each target under 'par' ( up to + 25%) * I don't really like this, so it's coming out level = URANGE( 0, victim->level, MAX_LEVEL - 1 ); number = UMAX( 1, kill_table[level].number ); extra = victim->pIndexData->killed - kill_table[level].killed / number; xp -= xp * URANGE( -2, extra, 8 ) / 8; */ xp = number_range( xp * 3 / 4, xp * 5 / 4 ); if ( !IS_NPC(gch) && gch->pcdata->clan[CLAN] > 0 ) { if ( (IS_SET(victim->act,ACT_VALHERU) && gch->pcdata->clan[CLAN] == 1) || (IS_SET(victim->act,ACT_CITHDEUX) && gch->pcdata->clan[CLAN] == 2) || (IS_SET(victim->act,ACT_SYNDICATE) && gch->pcdata->clan[CLAN] == 3) || (IS_SET(victim->act,ACT_BROTHERHOOD) && gch->pcdata->clan[CLAN] == 4) || (IS_SET(victim->act,ACT_EXODUS) && gch->pcdata->clan[CLAN] == 5) || (IS_SET(victim->act,ACT_MERCENARY) && gch->pcdata->clan[CLAN] == 6) ) xp = 0; } if ( !IS_NPC(gch) && gch->pcdata->extras2[EVAL] > 35 && victim->level < 50 ) xp /= 5; /* sanity check */ if ( xp > 3000000 ) xp = 1; xp = UMAX( 0, xp ); return xp; } void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt ) { static char * const attack_a[] = { "punch", "slice", "stab", "slash", "whip", "claw", "blast", "pound", "crush", "grep", "bite", "pierce", "blow" }; static char * const attack_b[] = { "punches", "slices", "stabs", "slashes", "whips", "claws", "blasts", "pounds", "crushes", "greps", "bites", "pierces", "blows" }; char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char buf3[MAX_STRING_LENGTH]; char buf4[MAX_STRING_LENGTH]; const char *vp; const char *attack; const char *attack2; char cdam[10]; char vdam[10]; char punct; /* april fools joke if ( dt == F_JUMPKICK ) dam *= 5; */ /* check for numeric damage being shown */ sprintf( cdam, " " ); sprintf( vdam, " " ); if ( !IS_NPC(ch) ) if ( dam != 0 ) if ( ch->pcdata->extras[LEGEND] >= 1 ) sprintf( cdam, "(%d)", dam ); if ( !IS_NPC(victim) ) if ( dam != 0 ) if ( victim->pcdata->extras[LEGEND] >= 1 ) sprintf( vdam, "[%d]", dam ); if ( dam == 0 ) { vp = "and miss"; } else if ( dam <= 5 ) { vp = "`bbarely`n"; } else if ( dam <= 20 ) { vp = "`bslightly`n"; } else if ( dam <= 35 ) { vp = "`bmoderately`n"; } else if ( dam <= 50 ) { vp = "`bfairly well`n"; } else if ( dam <= 75 ) { vp = "`gsomewhat hard`n"; } else if ( dam <= 100 ) { vp = "`ghard`n"; } else if ( dam <= 125 ) { vp = "`gvery hard`n"; } else if ( dam <= 150 ) { vp = "`gamazingly hard`n"; } else if ( dam <= 200 ) { vp = "`ginsanely hard`n"; } else if ( dam <= 250 ) { vp = "`Yskillfully`n"; } else if ( dam <= 350 ) { vp = "`Yvery skillfully`n"; } else if ( dam <= 500 ) { vp = "`Yamazingly skillfully`n"; } else if ( dam <= 750 ) { vp = "`rpowerfully`n"; } else if ( dam <= 1000 ) { vp = "`rvery powerfully`n"; } else if ( dam <= 1500 ) { vp = "`ramazingly powerfully`n"; } else if ( dam <= 2000 ) { vp = "`Rwith AWESOME force`n"; } else if ( dam <= 2500 ) { vp = "`Rwith GODLIKE force`n"; } else if ( dam <= 3500 ) { vp = "`Rwith UNHOLY force`n"; } else if ( dam <= 5000 ) { vp = "`WLIKE A BITCH`n!"; } else if ( dam <= 10000) { vp = "`WMACK TRUCK HARD`n!"; } else if ( dam <= 15000) { vp = "`WWITH FURIOUS ANGER`n!!"; } else if ( dam <= 30000) { vp = "`WLIKE A `RRED HEADED STEPCHILD`n!!";} else { vp = "`dWR`nAT`WHF`nUL`dLY`n"; } punct = (dam <= 500) ? '.' : '!'; /* * Buf4 added to show damage to room when ranged attacks * are used, so they are reversed in damage message so the * act function may be used. */ switch( dt ) { case TYPE_HIT: sprintf( buf1, "$n punches $N %s%c", vp, punct ); sprintf( buf2, "You punch $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n punches you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N punches $n %s%c", vp, punct ); break; case TYPE_LSLASH: sprintf( buf1, "$n leaps and strikes down at $N %s%c", vp, punct ); sprintf( buf2, "You leap and strike down at $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n leaps and strikes down at you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N leaps and strikes down at $n %s%c", vp, punct ); break; case TYPE_USTROKE: sprintf( buf1, "$n's upward stroke cuts $N %s%c", vp, punct ); sprintf( buf2, "Your upward stroke cuts $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's upward stroke cuts you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's upward stroke cuts $n %s%c", vp, punct ); break; case F_PALMTHRUST: sprintf( buf1, "The explosion blasts $N %s%c", vp, punct ); sprintf( buf2, "The explosion blasts $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "The explosion blasts you %s%c %s", vp, punct, vdam ); sprintf( buf4, "The explosion blasts $n %s%c", vp, punct ); break; case F_SHINKICK: sprintf( buf1, "$n kicks $N in the shins %s%c", vp, punct ); sprintf( buf2, "You kick $N in the shins %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n kicks you in the shin %s%c That smarts! %s", vp, punct, vdam ); sprintf( buf4, "$N kicks $n in the shins %s%c", vp, punct ); break; case F_JAB: sprintf( buf1, "$n lands a quick jab on $N %s%c", vp, punct ); sprintf( buf2, "You land a quick jab on $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n lands a quick jab on you %s %c %s", vp, punct, vdam ); sprintf( buf4, "$N lands a quick jab on $n %s%c", vp, punct ); break; case F_SPINKICK: sprintf( buf1, "$n spins and kicks $N %s%c", vp, punct ); sprintf( buf2, "You spin and kick $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n spins quickly and kicks you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N spins and kicks $n %s%c", vp, punct ); break; case F_KNEE: sprintf( buf1, "$n drives $s knee into $Ns gut %s%c", vp, punct ); sprintf( buf2, "You drive your knee into $Ns gut %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n drives $s knee into your gut %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N drives $s knee into $ns gut %s%c", vp, punct ); break; case F_ELBOW: sprintf( buf1, "$n jams $s elbow into $Ns face %s%c", vp, punct ); sprintf( buf2, "You jam your elbow into $Ns face %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n rams $s elbow into your face %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N jams $s elbow into $ns face %s%c", vp, punct ); break; case F_UPPERCUT: sprintf( buf1, "$n slams $s fist into $Ns jaw %s%c", vp, punct ); sprintf( buf2, "You slam your fist into $Ns jaw %s%c %s", vp, punct, cdam ); sprintf( buf3, "$ns fist connects with your jaw %s%c You see stars! %s", vp, punct, vdam ); sprintf( buf4, "$N slams $s fist into $ns jaw %s%c", vp, punct ); break; case F_STOMP: sprintf( buf1, "$n toestomps $N %s%c", vp, punct ); sprintf( buf2, "You toestomp $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n toestomps you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N toestomps $n %s%c", vp, punct ); break; case F_JUMPKICK: sprintf( buf1, "$n boots $N in the head %s%c", vp, punct ); sprintf( buf2, "You boot $N in the head %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n boots you in the head %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N boots $n in the head %s%c", vp, punct ); break; case F_DEATHTOUCH: sprintf( buf1, "$ns death touch strikes $N %s%c", vp, punct ); sprintf( buf2, "Your death touch strikes $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$ns death touch strikes you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$Ns death touch strikes $n %s%c", vp, punct ); break; case DAM_KIFLAME: sprintf( buf1, "$ns burst of Ki flame burns $N %s%c", vp, punct ); sprintf( buf2, "Your burst of Ki flame burns $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$ns burst of Ki flame burns you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$Ns burst of Ki flame burns $n %s%c", vp, punct ); break; case DAM_SHOCKSHIELD: sprintf( buf1, "`Y$n's defenses flare to life, shocking $N%c`n", punct ); sprintf( buf2, "`YYour defenses flare to life, shocking $N%c `n%s", punct, cdam ); sprintf( buf3, "`Y$n's defenses flare to life, shocking you%c `n%s", punct, vdam ); sprintf( buf4, "`Y$N's defenses flare to life, shocking $n%c`n", punct ); break; case DAM_LIGHTNING: sprintf( buf1, "$n's lightning bolt shocks $N %s%c", vp, punct ); sprintf( buf2, "Your lightning bolt shocks $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's lightning bolt shocks $N %s%c %s", vp, punct, cdam ); sprintf( buf4, "$N's lightning bolt shocks $n %s%c", vp, punct ); break; case DAM_FIRE: sprintf( buf1, "$n's firey blast burns $N %s%c", vp, punct ); sprintf( buf2, "Your firey blast burns $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's firey blast burns you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's firey blast burns $n %s%c", vp, punct ); break; case DAM_NEGATIVE: sprintf( buf1, "$n drains $N %s%c", vp, punct ); sprintf( buf2, "You drain $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n drains you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N drains $n %s%c", vp, punct ); break; case DAM_BULLETS: sprintf( buf1, "$n's bullets pierce $N %s%c", vp, punct ); sprintf( buf2, "Your bullets pierce $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's bullets pierce you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's bullets pierce $n %s%c", vp, punct ); break; case DAM_BEAMRIFLE: sprintf( buf1, "$n's beams burn $N %s%c", vp, punct ); sprintf( buf2, "Your beams burn $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's beams burn you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's beams burn $n %s%c", vp, punct ); break; case DAM_BEAMSABRE: sprintf( buf1, "$n's beam blade sears $N %s%c", vp, punct ); sprintf( buf2, "Your beam blade sears $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's beam blade sears you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's beam blade sears $n %s%c", vp, punct ); break; case DAM_BEAMSWORD: sprintf( buf1, "$n's beamsword incinerates $N %s%c", vp, punct ); sprintf( buf2, "Your beamsword incinerates $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's beamsword incinerates you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's beamsword incinerates $n %s%c", vp, punct ); break; case DAM_SHELLS: sprintf( buf1, "$n's shells explode on $N %s%c", vp, punct ); sprintf( buf2, "Your shells explode on $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's shells explode on you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's shells explode on $n %s%c", vp, punct ); break; case DAM_HEATROD: sprintf( buf1, "$'n heat rod rips $N %s%c", vp, punct ); sprintf( buf2, "Your heat rod rips $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's heat rod rips you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's heat rod rips $n %s%c", vp, punct ); break; case DAM_MISSILES: sprintf( buf1, "$n's missiles explode on $N %s%c", vp, punct ); sprintf( buf2, "Your missiles explode on $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's missiles explode on you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's missiles explode on $n %s%c", vp, punct ); break; case DAM_SHOCKWAVE: sprintf( buf1, "$n's shockwave attack blasts $N %s%c", vp, punct ); sprintf( buf2, "Your shockwave attack blasts $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's shockwave attack blasts you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's shockwave attack blasts $n %s%c", vp, punct ); break; case DAM_EXPLOSION: sprintf( buf1, "$N is hurt by the explosion." ); sprintf( buf2, "You are hurt by the explosion! %s", cdam ); sprintf( buf3, "$N is hurt by the explosion! %s", vdam ); sprintf( buf4, "$N is hurt by the explosion!" ); break; case DAM_FLAME_BREATH: sprintf( buf1, "$N's skin smolders." ); sprintf( buf2, "Your skin smolders! %s", cdam ); sprintf( buf3, "$N's skin smolders! %s", vdam ); sprintf( buf4, "$N's skins molders." ); break; case DAM_CRIMSON: sprintf( buf1, "$n's crimson flames scorch $N %s%c", vp, punct ); sprintf( buf2, "Your crimson flames scorch $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's crimson flames scorch you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's crimson flames scorch $n %s%c", vp, punct ); break; case DAM_EMERALD: sprintf( buf1, "$n's emerald rays sear $N %s%c", vp, punct ); sprintf( buf2, "Your emerald rays sear $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's emerald rays sear you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's emerald rays sear $n %s%c", vp, punct ); break; case DAM_CERULEAN: sprintf( buf1, "$n's cerulean storm tears at $N %s%c", vp, punct ); sprintf( buf2, "Your cerulean storm tears at $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's cerulean storm tears at you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's cerulean storm tears at $n %s%c", vp, punct ); break; case DAM_OBSIDIAN: sprintf( buf1, "$n's demonic energies wither $N %s%c", vp, punct ); sprintf( buf2, "Your demonic energies wither $N %s%c %s", vp, punct, cdam ); sprintf( buf3, "$n's demonic energies wither you %s%c %s", vp, punct, vdam ); sprintf( buf4, "$N's demonic energies wither $n %s%c", vp, punct ); break; default: if ( dt >= 1400 && dt <= 1480 ) { sprintf(buf1, "$n's %s strikes $N %s%c", chant_table[dt-1400].name, vp, punct ); sprintf(buf2,"Your %s strikes $N %s%c %s",chant_table[dt-1400].name,vp,punct,cdam ); sprintf(buf3,"$n's %s strikes you %s%c %s",chant_table[dt-1400].name,vp,punct,vdam); sprintf(buf4,"$N's %s strikes $n %s%c", chant_table[dt-1400].name, vp, punct ); break; } else if ( dt >= 0 && dt < MAX_SKILL ) { attack = skill_table[dt].noun_damage; attack2 = skill_table[dt].noun_damage; } else if ( dt >= TYPE_HIT && dt < TYPE_HIT + sizeof(attack_a)/sizeof(attack_a[0]) ) { attack = attack_a[dt - TYPE_HIT]; attack2 = attack_b[dt-TYPE_HIT]; } else { bug( "Dam_message: bad dt %d.", dt ); dt = TYPE_HIT; attack = attack_a[0]; attack2 = attack_b[0]; } sprintf( buf1, "$n %s $N %s%c", attack2, vp, punct ); sprintf( buf2, "You %s $N %s%c %s", attack, vp, punct, cdam ); sprintf( buf3, "$n %s you %s%c %s", attack2, vp, punct, vdam ); sprintf( buf4, "$N %s $n %s%c", attack2, vp, punct ); break; } act( buf1, ch, NULL, victim, TO_NOTVICT ); act( buf2, ch, NULL, victim, TO_CHAR ); act( buf3, ch, NULL, victim, TO_VICT ); /* show ranged attacks to victims room */ if ( ch->in_room != victim->in_room ) act( buf4, victim, NULL, ch, TO_NOTVICT ); return; } /* * Disarm a creature. * Caller must check for successful attack. */ void disarm( CHAR_DATA *ch, CHAR_DATA *victim ) { OBJ_DATA *obj; if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL ) return; if ( get_eq_char( ch, WEAR_WIELD ) == NULL && number_bits( 1 ) == 0 ) return; act( "$n DISARMS you!", ch, NULL, victim, TO_VICT ); act( "You disarm $N!", ch, NULL, victim, TO_CHAR ); act( "$n DISARMS $N!", ch, NULL, victim, TO_NOTVICT ); obj_from_char( obj ); if ( IS_NPC(victim) ) obj_to_char( obj, victim ); else obj_to_room( obj, victim->in_room ); return; } /* * Trip a creature. * Caller must check for successful attack. */ void trip( CHAR_DATA *ch, CHAR_DATA *victim ) { if ( victim->wait == 0 ) { act( "$n trips you and you go down!", ch, NULL, victim, TO_VICT ); act( "You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR ); act( "$n trips $N and $N goes down!", ch, NULL, victim, TO_NOTVICT ); WAIT_STATE( ch, 2 * PULSE_VIOLENCE ); WAIT_STATE( victim, 2 * PULSE_VIOLENCE ); victim->position = POS_RESTING; } return; } void do_kill( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Kill whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); WAIT_STATE( ch, 4 ); return; } if ( victim == ch ) { send_to_char( "You hit yourself. Ouch!\n\r", ch ); multi_hit( ch, ch, TYPE_UNDEFINED ); return; } if ( is_safe( ch, victim ) ) return; if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim ) { act( "$N is your beloved master.", ch, NULL, victim, TO_CHAR ); return; } if ( ch->position == POS_FIGHTING ) { send_to_char( "You attempt to double your efforts, but fail!\n\r", ch ); return; } stancecheck( ch, victim ); WAIT_STATE( ch, 1 * PULSE_VIOLENCE ); multi_hit( ch, victim, TYPE_UNDEFINED ); return; } void do_murde( CHAR_DATA *ch, char *argument ) { send_to_char( "If you want to MURDER, spell it out.\n\r", ch ); return; } void do_murder( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Murder whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( victim == ch ) { send_to_char( "Suicide is a mortal sin.\n\r", ch ); return; } if ( is_safe( ch, victim ) ) return; if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim ) { act( "$N is your beloved master.", ch, NULL, victim, TO_CHAR ); return; } if ( ch->position == POS_FIGHTING ) { send_to_char( "You do the best you can!\n\r", ch ); return; } WAIT_STATE( ch, 1 * PULSE_VIOLENCE ); sprintf( buf, "Help! I am being attacked by %s!", ch->name ); do_shout( victim, buf ); multi_hit( ch, victim, TYPE_UNDEFINED ); return; } void do_backstab( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; if ( IS_NPC(ch) ) return; one_argument( argument, arg ); if ( arg[0] == '\0' ) { if ( ch->fighting == NULL ) { send_to_char( "Backstab whom?\n\r", ch ); return; } else victim = ch->fighting; } else if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( victim == ch ) { send_to_char( "How can you sneak up on yourself?\n\r", ch ); return; } if ( is_safe( ch, victim ) ) return; if ( IS_NPC(victim) || !IS_SET(victim->pcdata->actnew,NEW_FLEEING) ) { send_to_char( "Their back isn't turned.\n\r", ch ); return; } stancecheck( ch, victim ); WAIT_STATE( ch, skill_table[gsn_backstab].beats ); if ( !IS_AWAKE(victim) || IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_backstab] ) multi_hit( ch, victim, gsn_backstab ); else damage( ch, victim, 0, gsn_backstab ); return; } void do_flee( CHAR_DATA *ch, char *argument ) { ROOM_INDEX_DATA *was_in; ROOM_INDEX_DATA *now_in; CHAR_DATA *victim; CHAR_DATA *vch; CHAR_DATA *vch_next; char buf[MAX_STRING_LENGTH]; int attackers = 0, attempt, mod = 0; if ( ( victim = ch->fighting ) == NULL ) { if ( ch->position == POS_FIGHTING ) ch->position = POS_STANDING; send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } was_in = ch->in_room; for ( attempt = 0; attempt < 6; attempt++ ) { EXIT_DATA *pexit; int door; door = dice(1,6)-1; if ( ( pexit = was_in->exit[door] ) == 0 || pexit->to_room == NULL || IS_SET(pexit->exit_info, EX_CLOSED) || ( !IS_NPC(ch) && ch->in_room->area != pexit->to_room->area && pexit->to_room->clan > 0 && pexit->to_room->clan != ch->pcdata->clan[CLAN] ) || ( IS_NPC(ch) && ( IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB) || ( IS_SET(ch->act, ACT_STAY_AREA) && pexit->to_room->area != ch->in_room->area ) ) ) ) continue; if ( IS_NPC(ch) && IS_CLASS(victim,CLASS_FIST) && victim->pcdata->powers[F_DISC] >= 6 ) if ( victim->pcdata->powers[F_DISC] >= 6 && number_percent() > 50 ) { act( "You attempt to flee, but $N tackles you!", ch, NULL, victim, TO_CHAR ); act( "$n attempts to flee and you tackle $m.", ch, NULL, victim, TO_VICT ); act( "$n attempts to flee and $N tackles $m.", ch, NULL, victim, TO_NOTVICT ); WAIT_STATE( ch, 8 ); return; } if ( IS_AFFECTED(ch,AFF_NO_FLEE) && IS_NPC(ch) ) { act( "You attempt to flee but are restrained!", ch, NULL, victim, TO_CHAR ); act( "$n attempts to flee but is restrained!", ch, NULL, victim, TO_VICT ); act( "$n attempts to flee from $N but is restrained.", ch,NULL,victim,TO_NOTVICT); return; } for ( vch = ch->in_room->people; vch != NULL; vch = vch_next ) { vch_next = vch->next_in_room; if ( vch->fighting == ch ) attackers++; } attackers = UMAX(0,attackers-1); if ( IS_NPC(ch->fighting) ) attackers++; if ( IS_SUIT(ch->fighting) ) mod = 20; /* Karma disabled if ( !IS_NPC(ch) ) mod += ch->pcdata->extras[PUSSY]; */ if ( number_percent() > (15 + mod + attackers*40 ) ) { act( "You fail!", ch, NULL, victim, TO_CHAR ); act( "$n turns $s back in an attempt to flee.", ch, NULL, victim, TO_VICT ); act( "$n turns $s back on $N in an attempt to flee.", ch, NULL, victim,TO_NOTVICT); WAIT_STATE(ch,12); if ( !IS_NPC(ch) && !IS_SET(ch->pcdata->actnew,NEW_FLEEING) ) SET_BIT(ch->pcdata->actnew,NEW_FLEEING ); return; } if ( !IS_NPC(ch) && !IS_NPC(victim) ) { switch( attackers ) { case 0: sprintf( buf, "%s is fleeing in terror from %s.", ch->name, victim->name ); break; case 1: sprintf( buf, "%s is on the run from %s's group.", ch->name, victim->name ); break; case 2: sprintf( buf, "%s is running for their life from %s's posse.", ch->name, victim->name ); break; default: sprintf( buf, "%s has successfully evaded %s's gangbang.", ch->name, victim->name ); break; } do_info( ch, buf ); } 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( "You flee from combat! You lose 25 exps.\n\r", ch ); gain_exp( ch, -25 ); } stop_fighting( ch, TRUE ); return; } send_to_char( "You failed! You lose 10 exps.\n\r", ch ); gain_exp( ch, -10 ); return; } void do_rescue( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; CHAR_DATA *vch; CHAR_DATA *fch = NULL; bool match = FALSE; if ( !IS_NPC(ch) && ch->level < skill_table[gsn_rescue].skill_level[ch->class] ) { send_to_char( "You better leave the heroic acts to warriors.\n\r", ch ); return; } one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Rescue whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { 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( "Doesn't need your help!\n\r", ch ); return; } if ( ch->fighting == victim ) { send_to_char( "Too late.\n\r", ch ); return; } for ( vch = ch->in_room->people; vch != NULL && !match; vch = vch->next_in_room ) { if ( vch != ch && vch != victim && vch->fighting == victim ) { match = TRUE; fch = vch; } } if ( !match || fch == NULL ) { send_to_char( "They don't need to be rescued.\n\r", ch ); return; } WAIT_STATE( ch, skill_table[gsn_rescue].beats ); if ( !IS_NPC(ch) && number_percent( ) > ch->pcdata->learned[gsn_rescue] ) { send_to_char( "You fail the rescue.\n\r", ch ); return; } act( "You rescue $N!", ch, NULL, victim, TO_CHAR ); act( "$n rescues you!", ch, NULL, victim, TO_VICT ); act( "$n rescues $N!", ch, NULL, victim, TO_NOTVICT ); if ( fch != ch ) fch->fighting = ch; if ( ch != fch ) ch->fighting = fch; return; } void do_kick( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; int dam; if ( !IS_NPC(ch) && ch->level < skill_table[gsn_kick].skill_level[ch->class] ) { send_to_char( "You better leave the martial arts to fighters.\n\r", ch ); return; } if ( ( victim = ch->fighting ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if ( IS_NPC(ch) ) dam = dice( 10, ch->level ); else if ( ch->class == CLASS_FIST && ch->level >= 2 ) dam = number_range( ch->pcdata->weapons[0] * 2, ch->pcdata->weapons[0] * 4 + ch->pcdata->powers[F_LEGS] * 15 ); else if ( ch->class == CLASS_FIST ) dam = number_range( UMIN(ch->pcdata->weapons[0], 200), UMIN( ch->pcdata->weapons[0], 200 )*5 ); else dam = number_range( ch->pcdata->weapons[0], ch->pcdata->weapons[0] * 5 ); if ( !IS_NPC(victim) || victim->level > 95 ) dam /= 15; WAIT_STATE( ch, skill_table[gsn_kick].beats ); if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_kick] ) damage( ch, victim, dam, gsn_kick ); else damage( ch, victim, 0, gsn_kick ); return; } void do_disarm( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; OBJ_DATA *obj; int percent, defense; if ( !IS_NPC(ch) && ch->level < skill_table[gsn_disarm].skill_level[ch->class] ) { send_to_char( "You don't know how to disarm opponents.\n\r", ch ); return; } if ( get_eq_char( ch, WEAR_WIELD ) == NULL ) { send_to_char( "You must wield a weapon to disarm.\n\r", ch ); return; } if ( ( victim = ch->fighting ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL ) { send_to_char( "Your opponent is not wielding a weapon.\n\r", ch ); return; } if ( !IS_NPC(victim) ) defense = 50 + ch->pcdata->body; else defense = victim->level; WAIT_STATE( ch, skill_table[gsn_disarm].beats ); percent = number_percent( ) + defense - ch->level; if ( IS_NPC(ch) || percent < ch->pcdata->learned[gsn_disarm] * 2 / 3 ) disarm( ch, victim ); else send_to_char( "You failed.\n\r", ch ); return; } void do_sla( CHAR_DATA *ch, char *argument ) { send_to_char( "If you want to SLAY, spell it out.\n\r", ch ); return; } void do_slay( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Slay whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { 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; } act( "You slay $M in cold blood!", ch, NULL, victim, TO_CHAR ); act( "$n slays you in cold blood!", ch, NULL, victim, TO_VICT ); act( "$n slays $N in cold blood!", ch, NULL, victim, TO_NOTVICT ); raw_kill( victim, FALSE ); return; } int stanced( CHAR_DATA *ch ) { if ( IS_NPC(ch) ) return 0; return ch->pcdata->stances[MAX_STANCES+1]; } void stancecheck( CHAR_DATA *ch, CHAR_DATA *victim ) { int autostance; if (!IS_NPC(ch)) { autostance = ch->pcdata->stances[0]; if ( autostance > MAX_STANCES ) autostance = 0; if ( autostance > 0 && ch->pcdata->stances[MAX_STANCES+1] == 0 ) do_stance( ch, stance_table[autostance].name ); } if (!IS_NPC(victim)) { autostance = victim->pcdata->stances[0]; if ( autostance > MAX_STANCES ) autostance = 0; if ( autostance > 0 && victim->pcdata->stances[MAX_STANCES+1] == 0 ) do_stance( victim, stance_table[autostance].name ); } return; } int calc_attacks( CHAR_DATA *ch, CHAR_DATA *victim ) { int atk, stance, chit, vhit; if (IS_NPC(ch)) { atk = 1; atk += ch->level / 25; if ( ch->level > 95 ) atk += ( ch->level - 95 ); if ( IS_AFFECTED(ch,AFF_CHAOS_STRING) ) atk = UMAX( 1, atk * 2 / 3 ); return atk; } atk = 1; stance = stanced( ch ); if ( stance > 0 ) atk += stance_table[stance].attacks; if ( !IS_NPC(ch) && !IS_NPC(victim) ) { chit = UMIN( ch->hitroll, ch->pcdata->extras2[EVAL]*3 ); vhit = UMIN( victim->hitroll, victim->pcdata->extras2[EVAL]*3 ); if ( !IS_CLASS(ch,CLASS_SORCERER) || ch->pcdata->powers[SORC_PREP] <= 0 ) atk += URANGE( 0, (chit - vhit)/10, 3 ); } if ( ch->class == CLASS_SAIYAN ) { if ( ch->pcdata->powers[S_SPEED] > 50 ) atk++; if ( ch->pcdata->powers[S_SPEED] >= 150 ) atk += (ch->pcdata->powers[S_SPEED] / 150 ); if ( IS_SET(ch->pcdata->powers[S_TECH],S_ZANZOUKEN) ) atk += 2; } else if ( ch->class == CLASS_PATRYN ) { atk += get_runes(ch,RUNE_AIR,LEFTARM) + get_runes(ch,RUNE_AIR,RIGHTARM); // atk += ( get_runes(ch,RUNE_AIR,LEFTLEG) + get_runes(ch,RUNE_AIR,RIGHTLEG) ) / 2; } else if ( IS_CLASS(ch,CLASS_MAZOKU) ) { if ( IS_SET(ch->pcdata->powers[M_SET],M_BATTLE) ) { if ( IS_SET(ch->pcdata->powers[M_SET],M_THIRD) ) atk++; if ( IS_SET(ch->pcdata->powers[M_SET],M_FOURTH) ) atk++; if ( IS_SET(ch->pcdata->powers[M_SET],M_FIFTH) ) atk++; if ( IS_SET(ch->pcdata->powers[M_SET],M_SIXTH) ) atk++; } if ( IS_SET(ch->pcdata->powers[M_SET],M_SPIKES) ) atk++; if ( IS_SET(ch->pcdata->powers[M_SET],M_BLADES) ) atk += 2; if ( IS_SET(ch->pcdata->powers[M_SET],M_TENTACLES) ) atk += 7; } if ( IS_AFFECTED(victim,AFF_RAYWING) ) atk = UMAX( 1, atk * 2 / 3 ); return atk; } void do_whirl( CHAR_DATA *ch, char *argument ) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam, weapon, cost, mod, suit; int type = DAM_BEAMSABRE; int ammo = SUIT_BEAM; /* whirling for suits only */ if ( IS_SUIT(ch) ) { weapon = ch->pcdata->suit[SUIT_WEAPON]; suit = ch->pcdata->suit[SUIT_NUMBER]; switch( ch->pcdata->suit[SUIT_READY] ) { case MS_BEAM_SABRE: case MS_CRASHER: cost = 1; mod = 2; break; case MS_HEAT_SHOTELS: cost = 1; mod = 1; ammo = SUIT_PLASMA; break; case MS_BEAM_SCYTHE: case MS_BEAM_GLAIVE: cost = 1; mod = 3; break; case MS_BEAM_SWORD: cost = 10; mod = 4; break; default: send_to_char( "You can't whirl without a melee weapon.\n\r", ch ); return; break; } for ( vch = char_list; vch != NULL; vch = vch_next ) { vch_next = vch->next; if ( vch == ch || vch->in_room == NULL ) continue; if ( vch->in_room == ch->in_room ) { dam = isquare( weapon ) * dice(5,5) + (suit_table[suit].fight-90)*30; dam *= mod; if ( IS_SUIT(vch) && ch->pcdata->suit[SUIT_READY] == MS_HEAT_SHOTELS ) dam *= 3; if ( ch->pcdata->suit[ammo] < cost ) send_to_char( "You are out of ammunition.\n\r", ch ); else { damage( ch, vch, dam, type ); ch->pcdata->suit[ammo] -= cost; } } } WAIT_STATE(ch, 16-((suit_table[suit].speed-80)/10) ); return; } /* return to normal whirl function */ if ( ch->position < POS_FIGHTING || IS_TIED(ch) ) { send_to_char( "Nah... You feel too relaxed...\n\r", ch ); return; } for ( vch = char_list; vch != NULL; vch = vch_next ) { vch_next = vch->next; if ( vch == ch || vch->in_room == NULL ) continue; /* whirls by mortals skip avatars, no free autostance */ if ( !IS_NPC(ch) && !IS_NPC(vch) && ch->level < 2 ) continue; if ( vch->in_room == ch->in_room ) { stancecheck( ch, vch ); one_hit( ch, vch, gsn_whirl ); } } WAIT_STATE( ch, 24 ); return; } void check_quest( CHAR_DATA *ch, CHAR_DATA *victim ) { if ( IS_NPC(ch) || !IS_NPC(victim) ) return; if ( ch->pcdata->extras2[QUEST_TYPE] != QUEST_MOB ) return; if ( ch->pcdata->extras2[QUEST_INFO] == victim->pIndexData->vnum ) { send_to_char( "`WYou have completed your quest, return to your quest master!`n\n\r",ch); ch->pcdata->extras2[QUEST_TYPE] = QUEST_FINISHED; ch->pcdata->extras2[QUEST_INFO] = victim->level; } return; } int suit_damage( CHAR_DATA *victim, int dam ) { int suit, part, i, j; bool match = FALSE; char *buf; char buf2[MAX_STRING_LENGTH]; if ( IS_NPC(victim) ) return -1; if ( !IS_SUIT(victim) ) return -1; suit = victim->pcdata->suit[SUIT_NUMBER]; victim->pcdata->suit[SUIT_ARMOR] -= dam; if ( victim->pcdata->suit[SUIT_ARMOR] > 0 ) return dam; victim->pcdata->suit[SUIT_ARMOR] = suit_table[suit].armor * 15; part = 1; if ( victim->pcdata->suit[SUIT_COND] < 4095 ) { while ( !match ) { i = dice(1,12) - 1; part = 1; for ( j = 0; j < i; j++ ) part *= 2; if ( !IS_SET(victim->pcdata->suit[SUIT_COND],part) ) match = TRUE; } SET_BIT(victim->pcdata->suit[SUIT_COND],part); } switch( part ) { case 1: buf = "torso has been damaged"; break; case 2: buf = "guidance package has been damaged"; break; case 4: buf = "head has been damaged"; break; case 8: buf = "camera has been damaged"; break; case 16: buf = "left leg has been damaged"; break; case 32: buf = "right hand has been damaged"; break; case 64: buf = "right leg has been damaged"; break; case 128: buf = "left hand has been damaged"; break; case 256: buf = "left arm has been damaged"; break; case 512: buf = "radar system has been damaged"; break; case 1024: buf = "right arm has been damaged"; break; case 2048: buf = "propulsion system has been damaged"; break; default: buf = "This is a bug"; sprintf( buf2, "part %d cond %d", part, victim->pcdata->suit[SUIT_COND]); send_to_char( buf2, victim ); break; }; act( ".. Your $T.", victim, NULL, buf, TO_CHAR ); act( ".. $n's $T.", victim, NULL, buf, TO_ROOM ); if ( victim->pcdata->suit[SUIT_COND] >= 4095 ) { act( "Your mobile suit explodes, throwing you from the cockpit!", victim, NULL, NULL, TO_CHAR ); act( "$n's mobile suit explodes!", victim, NULL, NULL, TO_ROOM ); for ( i = 0; i < 10; i++ ) victim->pcdata->suit[i] = 0; victim->hit = dice( 1, UMAX(1,victim->hit)/5 ); } else damage( victim, victim, dice(5,400), DAM_EXPLOSION ); return dam; } void essense_gain( CHAR_DATA *ch, CHAR_DATA *victim, int gain, int dt ) { if ( !IS_CLASS(ch,CLASS_MAZOKU) ) return; if ( ch == victim ) { ch->pcdata->powers[M_NIHILISM] = UMIN( 100, ch->pcdata->powers[M_NIHILISM]+1 ); return; } if ( dt != DAM_OBSIDIAN ) gain /= 10; gain -= gain * ch->pcdata->powers[M_ESSENSE] / 100000; if ( (ch->pcdata->powers[M_ESSENSE] + gain) < 100000 ) ch->pcdata->powers[M_ESSENSE] += gain; return; } void do_retarget( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; if ( ch->fighting == NULL ) { stc( "Why bother?\n\r", ch ); return; } argument = one_argument( argument, arg ); if ( (victim = get_char_room( ch, arg )) == NULL ) { stc( "They aren't here.\n\r", ch ); return; } act( "You focus your attacks on $N.", ch, NULL, victim, TO_CHAR ); act( "$n focuses $s attacks on you!", ch, NULL, victim, TO_VICT ); act( "$n focuses $s attacks on $N.", ch, NULL, victim, TO_NOTVICT ); ch->fighting = victim; return; } void do_sap( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; OBJ_DATA *obj; AFFECT_DATA af; char arg[MAX_INPUT_LENGTH]; if ( (obj = get_eq_char(ch,WEAR_HOLD)) == NULL ) { stc( "Huh?\n\r", ch ); return; } if ( obj->pIndexData->vnum != 35 ) { stc( "Huh?\n\r", ch ); return; } if ( !IS_NPC(ch) && ch->pcdata->extras2[EVAL] < 10 ) { stc( "You're too young to play with one of those.\n\r", ch ); return; } argument = one_argument( argument, arg ); if ( arg[0] == '\0' ) { stc( "Sap who?\n\r", ch ); return; } if ( (victim = get_char_room(ch,arg)) == NULL ) { stc( "They aren't here.\n\r", ch ); return; } if ( victim->position <= POS_SLEEPING ) { stc( "Why bother?\n\r", ch ); return; } if ( victim->hit < victim->max_hit ) { act( "$N is hurt and suspicious.", ch, NULL, victim, TO_CHAR ); act( "You avoid a vicious attack with $p by $n!", ch, obj, victim, TO_VICT ); return; } af.type = skill_lookup( "sleep" ); af.duration = 15 + dice(1,5); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SLEEP; act( "You slam $p against $N's temple!", ch, obj, victim, TO_CHAR ); act( "$N slumps to the ground.", ch, NULL, victim, TO_CHAR ); act( "Unnnnnngh.... zzzzzzzz.......", ch, NULL, victim, TO_VICT ); act( "$N slumps to the ground.", ch, NULL, victim, TO_NOTVICT ); victim->position = POS_SLEEPING; affect_to_char( victim, &af ); if ( !IS_NPC(ch) && ch->pcdata->extras[TIMER] < 15 ) ch->pcdata->extras[TIMER] = 15; WAIT_STATE( ch, 12 ); return; } void add_inf( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) { INF_DATA *inf = NULL; if ( ch == NULL || IS_NPC(ch) || victim == NULL || dam <= 0 ) return; for ( inf = ch->pcdata->inf; inf != NULL; inf = inf->next ) { if ( !str_cmp( inf->victim, victim->name ) ) break; } if ( inf == NULL ) { inf = new_inf(); inf->pc = !IS_NPC(victim); inf->victim = str_dup( victim->name ); inf->next = ch->pcdata->inf; ch->pcdata->inf = inf; } inf->damage += dam; inf->time = current_time; return; } /* * Remove all inf records of damage from a character */ void clear_inf( CHAR_DATA *ch ) { INF_DATA *inf; INF_DATA *inf_last; if ( ch == NULL || IS_NPC(ch) || ch->pcdata->inf == NULL ) return; inf_last = ch->pcdata->inf; for ( inf = ch->pcdata->inf; inf != NULL; inf = inf->next ) { free_string( inf->victim ); inf_last = inf; } inf_last->next = inf_free; inf_free = ch->pcdata->inf; ch->pcdata->inf = NULL; return; } void inf_update() { CHAR_DATA *vch; INF_DATA *inf; INF_DATA *inf_next; INF_DATA *inf_prev; for ( vch = char_list; vch != NULL; vch = vch->next ) { if ( IS_NPC(vch) ) continue; if ( vch->pcdata->inf == NULL ) continue; inf_prev = NULL; for ( inf = vch->pcdata->inf; inf != NULL; inf = inf_next ) { inf_next = inf->next; if ( inf->time + 30 < current_time ) /* infs expire after 30 seconds */ { free_string( inf->victim ); if ( inf == vch->pcdata->inf ) vch->pcdata->inf = inf_next; else inf_prev->next = inf_next; inf->next = inf_free; inf_free = inf; } else inf_prev = inf; } } return; } int get_inf_dam( CHAR_DATA *ch, char *name ) { INF_DATA *inf; if ( ch == NULL || IS_NPC(ch) || ch->pcdata->inf == NULL ) return 0; inf = ch->pcdata->inf; while ( inf != NULL && str_cmp( inf->victim, name ) ) inf = inf->next; if ( inf == NULL ) return 0; return inf->damage; }