FIGHT.C
上传用户:kesirui
上传日期:2007-01-07
资源大小:263k
文件大小:37k
源码类别:

Internet/网络编程

开发平台:

WINDOWS

  1. /***************************************************************************
  2.  *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
  3.  *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
  4.  *                                                                         *
  5.  *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
  6.  *  Chastain, Michael Quan, and Mitchell Tse.                              *
  7.  *                                                                         *
  8.  *  In order to use any part of this Merc Diku Mud, you must comply with   *
  9.  *  both the original Diku license in 'license.doc' as well the Merc       *
  10.  *  license in 'license.txt'.  In particular, you may not remove either of *
  11.  *  these copyright notices.                                               *
  12.  *                                                                         *
  13.  *  Much time and thought has gone into this software and you are          *
  14.  *  benefitting.  We hope that you share your changes too.  What goes      *
  15.  *  around, comes around.                                                  *
  16.  ***************************************************************************/
  17. #if defined(macintosh)
  18. #include <types.h>
  19. #else
  20. #include <sys/types.h>
  21. #endif
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <time.h>
  25. #include "merc.h"
  26. /*
  27.  * Local functions.
  28.  */
  29. bool check_dodge args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
  30. void check_killer args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
  31. bool check_parry args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
  32. void dam_message args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam,
  33.     int dt ) );
  34. void death_cry args( ( CHAR_DATA *ch ) );
  35. void group_gain args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
  36. int xp_compute args( ( CHAR_DATA *gch, CHAR_DATA *victim ) );
  37. bool is_safe args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
  38. void make_corpse args( ( CHAR_DATA *ch ) );
  39. void one_hit args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) );
  40. void raw_kill args( ( CHAR_DATA *victim ) );
  41. void set_fighting args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
  42. void disarm args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
  43. void trip args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );
  44. /*
  45.  * Control the fights going on.
  46.  * Called periodically by update_handler.
  47.  */
  48. void violence_update( void )
  49. {
  50.     CHAR_DATA *ch;
  51. //    CHAR_DATA *ch_next;
  52.     CHAR_DATA *victim;
  53.     CHAR_DATA *rch;
  54.     CHAR_DATA *rch_next;
  55.     for ( ch = char_list; ch != NULL; ch = ch->next )
  56.     {
  57. // ch_next = ch->next;
  58. if ( ( victim = ch->fighting ) == NULL || ch->in_room == NULL )
  59.     continue;
  60. if ( IS_AWAKE(ch) && ch->in_room == victim->in_room )
  61.     multi_hit( ch, victim, TYPE_UNDEFINED );
  62. else
  63.     stop_fighting( ch, FALSE );
  64. if ( ( victim = ch->fighting ) == NULL )
  65.     continue;
  66.         mprog_hitprcnt_trigger( ch, victim );
  67.         mprog_fight_trigger( ch, victim );
  68. /*
  69.  * Fun for the whole family!
  70.  */
  71. for ( rch = ch->in_room->people; rch != NULL; rch = rch_next )
  72. {
  73.     rch_next = rch->next_in_room;
  74.     if ( IS_AWAKE(rch) && rch->fighting == NULL )
  75.     {
  76. /*
  77.  * PC's auto-assist others in their group.
  78.  */
  79. if ( !IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM) )
  80. {
  81.     if ( ( !IS_NPC(rch) || IS_AFFECTED(rch, AFF_CHARM) )
  82.     &&   is_same_group(ch, rch) )
  83. multi_hit( rch, victim, TYPE_UNDEFINED );
  84.     continue;
  85. }
  86. /*
  87.  * NPC's assist NPC's of same type or 12.5% chance regardless.
  88.  */
  89. if ( IS_NPC(rch) && !IS_AFFECTED(rch, AFF_CHARM) )
  90. {
  91.     if ( rch->pIndexData == ch->pIndexData
  92.     ||   number_bits( 3 ) == 0 )
  93.     {
  94. CHAR_DATA *vch;
  95. CHAR_DATA *target;
  96. int number;
  97. target = NULL;
  98. number = 0;
  99. for ( vch = ch->in_room->people; vch; vch = vch->next )
  100. {
  101.     if ( can_see( rch, vch )
  102.     &&   is_same_group( vch, victim )
  103.     &&   number_range( 0, number ) == 0 )
  104.     {
  105. target = vch;
  106. number++;
  107.     }
  108. }
  109. if ( target != NULL )
  110. {
  111.    if ( ( ( ( target->level - rch->level <= 4 )
  112.            && ( target->level - rch->level >= -4 ) )
  113.       && !( IS_GOOD ( rch ) && IS_GOOD ( target ) ) )
  114.    || ( IS_EVIL ( rch ) || IS_EVIL ( target ) ) )
  115.      multi_hit( rch, target, TYPE_UNDEFINED );
  116. }
  117.     }
  118. }
  119.     }
  120. }
  121.     }
  122.     return;
  123. }
  124. /*
  125.  * Do one group of attacks.
  126.  */
  127. void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
  128. {
  129.     int     chance;
  130.     one_hit( ch, victim, dt );
  131.     if ( ch->fighting != victim || dt == gsn_backstab )
  132. return;
  133.     chance = IS_NPC(ch) ? ch->level : ch->pcdata->learned[gsn_second_attack]/2;
  134.     if ( number_percent( ) < chance )
  135.     {
  136. one_hit( ch, victim, dt );
  137. if ( ch->fighting != victim )
  138.     return;
  139.     }
  140.     chance = IS_NPC(ch) ? ch->level : ch->pcdata->learned[gsn_third_attack]/4;
  141.     if ( number_percent( ) < chance )
  142.     {
  143. one_hit( ch, victim, dt );
  144. if ( ch->fighting != victim )
  145.     return;
  146.     }
  147.     chance = IS_NPC(ch) ? ch->level / 2 : 0;
  148.     if ( number_percent( ) < chance )
  149. one_hit( ch, victim, dt );
  150.     
  151.     return;
  152. }
  153. /*
  154.  * Hit one guy once.
  155.  */
  156. void one_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
  157. {
  158.     OBJ_DATA *wield;
  159.     int victim_ac;
  160.     int thac0;
  161.     int thac0_00;
  162.     int thac0_32;
  163.     int dam;
  164.     int diceroll;
  165.     /*
  166.      * Can't beat a dead char!
  167.      * Guard against weird room-leavings.
  168.      */
  169.     if ( victim->position == POS_DEAD || ch->in_room != victim->in_room )
  170. return;
  171.     /*
  172.      * Figure out the type of damage message.
  173.      */
  174.     wield = get_eq_char( ch, WEAR_WIELD );
  175.     if ( dt == TYPE_UNDEFINED )
  176.     {
  177. dt = TYPE_HIT;
  178. if ( wield != NULL && wield->item_type == ITEM_WEAPON )
  179.     dt += wield->value[3];
  180.     }
  181.     /*
  182.      * Calculate to-hit-armor-class-0 versus armor.
  183.      */
  184.     if ( IS_NPC(ch) )
  185.     {
  186. thac0_00 = 20;
  187. thac0_32 =  0;
  188.     }
  189.     else
  190.     {
  191. thac0_00 = class_table[ch->class].thac0_00;
  192. thac0_32 = class_table[ch->class].thac0_32;
  193.     }
  194.     thac0     = interpolate( ch->level, thac0_00, thac0_32 ) - GET_HITROLL(ch);
  195.     victim_ac = UMAX( -15, GET_AC(victim) / 10 );
  196.     if ( !can_see( ch, victim ) )
  197. victim_ac -= 4;
  198.     /*
  199.      * The moment of excitement!
  200.      */
  201.     while ( ( diceroll = number_bits( 5 ) ) >= 20 )
  202. ;
  203.     if ( diceroll == 0
  204.     || ( diceroll != 19 && diceroll < thac0 - victim_ac ) )
  205.     {
  206. /* Miss. */
  207. damage( ch, victim, 0, dt );
  208. tail_chain( );
  209. return;
  210.     }
  211.     /*
  212.      * Hit.
  213.      * Calc damage.
  214.      */
  215.     if ( IS_NPC(ch) )
  216.     {
  217. dam = number_range( ch->level / 2, ch->level * 3 / 2 );
  218. if ( wield != NULL )
  219.     dam += dam / 2;
  220.     }
  221.     else
  222.     {
  223. if ( wield != NULL )
  224.     dam = number_range( wield->value[1], wield->value[2] );
  225. else
  226.     dam = number_range( 1, 4 );
  227.     }
  228.     /*
  229.      * Bonuses.
  230.      */
  231.     dam += GET_DAMROLL(ch);
  232.     if ( !IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0 )
  233. dam += dam * ch->pcdata->learned[gsn_enhanced_damage] / 150;
  234.     if ( !IS_AWAKE(victim) )
  235. dam *= 2;
  236.     if ( dt == gsn_backstab )
  237. dam *= 2 + ch->level / 8;
  238.     if ( dam <= 0 )
  239. dam = 1;
  240.     damage( ch, victim, dam, dt );
  241.     tail_chain( );
  242.     return;
  243. }
  244. /*
  245.  * Inflict damage from a hit.
  246.  */
  247. void damage( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
  248. {
  249.     if ( victim->position == POS_DEAD )
  250. return;
  251.     /*
  252.      * Stop up any residual loopholes.
  253.      */
  254.     if ( dam > 1000 )
  255.     {
  256. bug( "Damage: %d: more than 1000 points!", dam );
  257. dam = 1000;
  258.     }
  259.     if ( victim != ch )
  260.     {
  261. /*
  262.  * Certain attacks are forbidden.
  263.  * Most other attacks are returned.
  264.  */
  265. if ( is_safe( ch, victim ) )
  266.     return;
  267. check_killer( ch, victim );
  268. if ( victim->position > POS_STUNNED )
  269. {
  270.     if ( victim->fighting == NULL )
  271. set_fighting( victim, ch );
  272.     victim->position = POS_FIGHTING;
  273. }
  274. if ( victim->position > POS_STUNNED )
  275. {
  276.     if ( ch->fighting == NULL )
  277. set_fighting( ch, victim );
  278.     /*
  279.      * If victim is charmed, ch might attack victim's master.
  280.      */
  281.     if ( IS_NPC(ch)
  282.     &&   IS_NPC(victim)
  283.     &&   IS_AFFECTED(victim, AFF_CHARM)
  284.     &&   victim->master != NULL
  285.     &&   victim->master->in_room == ch->in_room
  286.     &&   number_bits( 3 ) == 0 )
  287.     {
  288. stop_fighting( ch, FALSE );
  289. multi_hit( ch, victim->master, TYPE_UNDEFINED );
  290. return;
  291.     }
  292. }
  293. /*
  294.  * More charm stuff.
  295.  */
  296. if ( victim->master == ch )
  297.     stop_follower( victim );
  298. /*
  299.  * Inviso attacks ... not.
  300.  */
  301. if ( IS_AFFECTED(ch, AFF_INVISIBLE) )
  302. {
  303.     affect_strip( ch, gsn_invis );
  304.     affect_strip( ch, gsn_mass_invis );
  305.     REMOVE_BIT( ch->affected_by, AFF_INVISIBLE );
  306.     act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM );
  307. }
  308. /*
  309.  * Damage modifiers.
  310.  */
  311. if ( IS_AFFECTED(victim, AFF_SANCTUARY) )
  312.     dam /= 2;
  313. if ( IS_AFFECTED(victim, AFF_PROTECT) && IS_EVIL(ch) )
  314.     dam -= dam / 4;
  315. if ( dam < 0 )
  316.     dam = 0;
  317. /*
  318.  * Check for disarm, trip, parry, and dodge.
  319.  */
  320. if ( dt >= TYPE_HIT )
  321. {
  322.     if ( IS_NPC(ch) && number_percent( ) < ch->level / 2 )
  323. disarm( ch, victim );
  324.     if ( IS_NPC(ch) && number_percent( ) < ch->level / 2 )
  325. trip( ch, victim );
  326.     if ( check_parry( ch, victim ) )
  327. return;
  328.     if ( check_dodge( ch, victim ) )
  329. return;
  330. }
  331. dam_message( ch, victim, dam, dt );
  332.     }
  333.     /*
  334.      * Hurt the victim.
  335.      * Inform the victim of his new state.
  336.      */
  337.     victim->hit -= dam;
  338.     if ( !IS_NPC(victim)
  339.     &&   victim->level >= LEVEL_IMMORTAL
  340.     &&   victim->hit < 1 )
  341. victim->hit = 1;
  342.     update_pos( victim );
  343.     switch( victim->position )
  344.     {
  345.     case POS_MORTAL:
  346. act( "$n is mortally wounded, and will die soon, if not aided.",
  347.     victim, NULL, NULL, TO_ROOM );
  348. send_to_char( 
  349.     "You are mortally wounded, and will die soon, if not aided.nr",
  350.     victim );
  351. break;
  352.     case POS_INCAP:
  353. act( "$n is incapacitated and will slowly die, if not aided.",
  354.     victim, NULL, NULL, TO_ROOM );
  355. send_to_char(
  356.     "You are incapacitated and will slowly die, if not aided.nr",
  357.     victim );
  358. break;
  359.     case POS_STUNNED:
  360. act( "$n is stunned, but will probably recover.",
  361.     victim, NULL, NULL, TO_ROOM );
  362. send_to_char("You are stunned, but will probably recover.nr",
  363.     victim );
  364. break;
  365.     case POS_DEAD:
  366. act( "$n is DEAD!!", victim, 0, 0, TO_ROOM );
  367. send_to_char( "You have been KILLED!!nrnr", victim );
  368. break;
  369.     default:
  370. if ( dam > victim->max_hit / 4 )
  371.     send_to_char( "That really did HURT!nr", victim );
  372. if ( victim->hit < victim->max_hit / 4 )
  373.     send_to_char( "You sure are BLEEDING!nr", victim );
  374. break;
  375.     }
  376.     /*
  377.      * Sleep spells and extremely wounded folks.
  378.      */
  379.     if ( !IS_AWAKE(victim) )
  380. stop_fighting( victim, FALSE );
  381.     /*
  382.      * Payoff for killing things.
  383.      */
  384.     if ( victim->position == POS_DEAD )
  385.     {
  386. group_gain( ch, victim );
  387. if ( !IS_NPC(victim) )
  388. {
  389.     sprintf( log_buf, "%s killed by %s at %d",
  390. victim->name,
  391. (IS_NPC(ch) ? ch->short_descr : ch->name),
  392. victim->in_room->vnum );
  393.     log_string( log_buf );
  394.     /*
  395.      * Dying penalty:
  396.      * 1/2 way back to previous level.
  397.      */
  398.     if ( victim->exp > 1000 * victim->level )
  399. gain_exp( victim, (1000 * victim->level - victim->exp)/2 );
  400. }
  401. raw_kill( victim );
  402. if ( !IS_NPC(ch) && IS_NPC(victim) )
  403. {
  404.     if ( IS_SET(ch->act, PLR_AUTOLOOT) )
  405. do_get( ch, "all corpse" );
  406.     else
  407. do_look( ch, "in corpse" );
  408.     if ( IS_SET(ch->act, PLR_AUTOSAC) )
  409. do_sacrifice( ch, "corpse" );
  410. }
  411. return;
  412.     }
  413.     if ( victim == ch )
  414. return;
  415.     /*
  416.      * Take care of link dead people.
  417.      */
  418.     if ( !IS_NPC(victim) && victim->desc == NULL )
  419.     {
  420. if ( number_range( 0, victim->wait ) == 0 )
  421. {
  422.     do_recall( victim, "" );
  423.     return;
  424. }
  425.     }
  426.     /*
  427.      * Wimp out?
  428.      */
  429.     if ( IS_NPC(victim) && dam > 0 )
  430.     {
  431. if ( ( IS_SET(victim->act, ACT_WIMPY) && number_bits( 1 ) == 0
  432. &&   victim->hit < victim->max_hit / 2 )
  433. ||   ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL
  434. &&     victim->master->in_room != victim->in_room ) )
  435.     do_flee( victim, "" );
  436.     }
  437.     if ( !IS_NPC(victim)
  438.     &&   victim->hit > 0
  439.     &&   victim->hit <= victim->wimpy
  440.     &&   victim->wait == 0 )
  441. do_flee( victim, "" );
  442.     tail_chain( );
  443.     return;
  444. }
  445. bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim )
  446. {
  447.     if ( IS_NPC(ch) || IS_NPC(victim) )
  448. return FALSE;
  449.     if ( get_age( ch ) < 21 )
  450.     {
  451. send_to_char( "You aren't old enough.nr", ch );
  452. return TRUE;
  453.     }
  454.     if ( IS_SET( victim->act, PLR_KILLER ) )
  455.         return FALSE;
  456.     if ( ch->level >= victim->level )
  457.     {
  458. send_to_char( "You may not attack a lower level player.nr", ch );
  459. return TRUE;
  460.     }
  461.     return FALSE;
  462. }
  463. /*
  464.  * See if an attack justifies a KILLER flag.
  465.  */
  466. void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
  467. {
  468.     /*
  469.      * Follow charm thread to responsible character.
  470.      * Attacking someone's charmed char is hostile!
  471.      */
  472.     while ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL )
  473. victim = victim->master;
  474.     /*
  475.      * NPC's are fair game.
  476.      * So are killers and thieves.
  477.      */
  478.     if ( IS_NPC(victim)
  479.     ||   IS_SET(victim->act, PLR_KILLER)
  480.     ||   IS_SET(victim->act, PLR_THIEF) )
  481. return;
  482.     /*
  483.      * Charm-o-rama.
  484.      */
  485.     if ( IS_SET(ch->affected_by, AFF_CHARM) )
  486.     {
  487. if ( ch->master == NULL )
  488. {
  489.     char buf[MAX_STRING_LENGTH];
  490.     sprintf( buf, "Check_killer: %s bad AFF_CHARM",
  491. IS_NPC(ch) ? ch->short_descr : ch->name );
  492.     bug( buf, 0 );
  493.     affect_strip( ch, gsn_charm_person );
  494.     REMOVE_BIT( ch->affected_by, AFF_CHARM );
  495.     return;
  496. }
  497. send_to_char( "*** You are now a KILLER!! ***nr", ch->master );
  498. SET_BIT(ch->master->act, PLR_KILLER);
  499. stop_follower( ch );
  500. return;
  501.     }
  502.     /*
  503.      * NPC's are cool of course (as long as not charmed).
  504.      * Hitting yourself is cool too (bleeding).
  505.      * So is being immortal (Alander's idea).
  506.      * And current killers stay as they are.
  507.      */
  508.     if ( IS_NPC(ch)
  509.     ||   ch == victim
  510.     ||   ch->level >= LEVEL_IMMORTAL
  511.     ||   IS_SET(ch->act, PLR_KILLER) )
  512. return;
  513.     send_to_char( "*** You are now a KILLER!! ***nr", ch );
  514.     SET_BIT(ch->act, PLR_KILLER);
  515.     save_char_obj( ch );
  516.     return;
  517. }
  518. /*
  519.  * Check for parry.
  520.  */
  521. bool check_parry( CHAR_DATA *ch, CHAR_DATA *victim )
  522. {
  523.     int chance;
  524.     if ( !IS_AWAKE(victim) )
  525. return FALSE;
  526.     if ( IS_NPC(victim) )
  527.     {
  528. /* Tuan was here.  :) */
  529. chance = UMIN( 60, 2 * victim->level );
  530.     }
  531.     else
  532.     {
  533. if ( get_eq_char( victim, WEAR_WIELD ) == NULL )
  534.     return FALSE;
  535. chance = victim->pcdata->learned[gsn_parry] / 2;
  536.     }
  537.     if ( number_percent( ) >= chance + victim->level - ch->level )
  538. return FALSE;
  539.     act( "You parry $n's attack.",  ch, NULL, victim, TO_VICT    );
  540.     act( "$N parries your attack.", ch, NULL, victim, TO_CHAR    );
  541.     return TRUE;
  542. }
  543. /*
  544.  * Check for dodge.
  545.  */
  546. bool check_dodge( CHAR_DATA *ch, CHAR_DATA *victim )
  547. {
  548.     int chance;
  549.     if ( !IS_AWAKE(victim) )
  550. return FALSE;
  551.     if ( IS_NPC(victim) )
  552. /* Tuan was here.  :) */
  553.         chance  = UMIN( 60, 2 * victim->level );
  554.     else
  555.         chance  = victim->pcdata->learned[gsn_dodge] / 2;
  556.     if ( number_percent( ) >= chance + victim->level - ch->level )
  557.         return FALSE;
  558.     act( "You dodge $n's attack.", ch, NULL, victim, TO_VICT    );
  559.     act( "$N dodges your attack.", ch, NULL, victim, TO_CHAR    );
  560.     return TRUE;
  561. }
  562. /*
  563.  * Set position of a victim.
  564.  */
  565. void update_pos( CHAR_DATA *victim )
  566. {
  567.     if ( victim->hit > 0 )
  568.     {
  569.      if ( victim->position <= POS_STUNNED )
  570.     victim->position = POS_STANDING;
  571. return;
  572.     }
  573.     if ( IS_NPC(victim) || victim->hit <= -11 )
  574.     {
  575. victim->position = POS_DEAD;
  576. return;
  577.     }
  578.          if ( victim->hit <= -6 ) victim->position = POS_MORTAL;
  579.     else if ( victim->hit <= -3 ) victim->position = POS_INCAP;
  580.     else                          victim->position = POS_STUNNED;
  581.     return;
  582. }
  583. /*
  584.  * Start fights.
  585.  */
  586. void set_fighting( CHAR_DATA *ch, CHAR_DATA *victim )
  587. {
  588.     if ( ch->fighting != NULL )
  589.     {
  590. bug( "Set_fighting: already fighting", 0 );
  591. return;
  592.     }
  593.     if ( IS_AFFECTED(ch, AFF_SLEEP) )
  594. affect_strip( ch, gsn_sleep );
  595.     ch->fighting = victim;
  596.     ch->position = POS_FIGHTING;
  597.     return;
  598. }
  599. /*
  600.  * Stop fights.
  601.  */
  602. void stop_fighting( CHAR_DATA *ch, bool fBoth )
  603. {
  604.     CHAR_DATA *fch;
  605.     for ( fch = char_list; fch != NULL; fch = fch->next )
  606.     {
  607. if ( fch == ch || ( fBoth && fch->fighting == ch ) )
  608. {
  609.     fch->fighting = NULL;
  610.     fch->position = POS_STANDING;
  611.     update_pos( fch );
  612. }
  613.     }
  614.     return;
  615. }
  616. /*
  617.  * Make a corpse out of a character.
  618.  */
  619. void make_corpse( CHAR_DATA *ch )
  620. {
  621.     char buf[MAX_STRING_LENGTH];
  622.     OBJ_DATA *corpse;
  623.     OBJ_DATA *obj;
  624.     OBJ_DATA *obj_next;
  625.     char *name;
  626.     if ( IS_NPC(ch) )
  627.     {
  628. name = ch->short_descr;
  629. corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_NPC), 0);
  630.    // @@@ ECS - Made all corpses have value 3 gp
  631.    corpse->cost   = 3;
  632. corpse->timer = number_range( 2, 4 );
  633. if ( ch->gold > 0 )
  634. {
  635.     obj_to_obj( create_money( ch->gold ), corpse );
  636.     ch->gold = 0;
  637. }
  638.     }
  639.     else
  640.     {
  641. name = ch->name;
  642. corpse = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0);
  643. corpse->timer = number_range( 25, 40 );
  644.     }
  645.     sprintf( buf, corpse->short_descr, name );
  646.     free_string( corpse->short_descr );
  647.     corpse->short_descr = str_dup( buf );
  648.     sprintf( buf, corpse->description, name );
  649.     free_string( corpse->description );
  650.     corpse->description = str_dup( buf );
  651.     for ( obj = ch->carrying; obj != NULL; obj = obj_next )
  652.     {
  653. obj_next = obj->next_content;
  654. obj_from_char( obj );
  655. if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
  656.     extract_obj( obj );
  657. else
  658.     obj_to_obj( obj, corpse );
  659.     }
  660.     obj_to_room( corpse, ch->in_room );
  661.     return;
  662. }
  663. /*
  664.  * Improved Death_cry contributed by Diavolo.
  665.  */
  666. void death_cry( CHAR_DATA *ch )
  667. {
  668.     ROOM_INDEX_DATA *was_in_room;
  669.     char *msg;
  670.     int door;
  671.     int vnum;
  672.     vnum = 0;
  673.     switch ( number_bits( 4 ) )
  674.     {
  675.     default: msg  = "You hear $n's death cry."; break;
  676.     case  0: msg  = "$n hits the ground ... DEAD."; break;
  677.     case  1: msg  = "$n splatters blood on your armor."; break;
  678.     case  2: msg  = "You smell $n's sphincter releasing in death.";
  679.      vnum = OBJ_VNUM_FINAL_TURD; break;
  680.     case  3: msg  = "$n's severed head plops on the ground.";
  681.      vnum = OBJ_VNUM_SEVERED_HEAD; break;
  682.     case  4: msg  = "$n's heart is torn from $s chest.";
  683.      vnum = OBJ_VNUM_TORN_HEART; break;
  684.     case  5: msg  = "$n's arm is sliced from $s dead body.";
  685.      vnum = OBJ_VNUM_SLICED_ARM; break;
  686.     case  6: msg  = "$n's leg is sliced from $s dead body.";
  687.      vnum = OBJ_VNUM_SLICED_LEG; break;
  688.     }
  689.     act( msg, ch, NULL, NULL, TO_ROOM );
  690.     if ( vnum != 0 )
  691.     {
  692. char buf[MAX_STRING_LENGTH];
  693. OBJ_DATA *obj;
  694. char *name;
  695. name = IS_NPC(ch) ? ch->short_descr : ch->name;
  696. obj = create_object( get_obj_index( vnum ), 0 );
  697. obj->timer = number_range( 4, 7 );
  698. sprintf( buf, obj->short_descr, name );
  699. free_string( obj->short_descr );
  700. obj->short_descr = str_dup( buf );
  701. sprintf( buf, obj->description, name );
  702. free_string( obj->description );
  703. obj->description = str_dup( buf );
  704. obj_to_room( obj, ch->in_room );
  705.     }
  706.     if ( IS_NPC(ch) )
  707. msg = "You hear something's death cry.";
  708.     else
  709. msg = "You hear someone's death cry.";
  710.     was_in_room = ch->in_room;
  711.     for ( door = 0; door <= 5; door++ )
  712.     {
  713. EXIT_DATA *pexit;
  714. if ( ( pexit = was_in_room->exit[door] ) != NULL
  715. &&   pexit->to_room != NULL
  716. &&   pexit->to_room != was_in_room )
  717. {
  718.     ch->in_room = pexit->to_room;
  719.     act( msg, ch, NULL, NULL, TO_ROOM );
  720. }
  721.     }
  722.     ch->in_room = was_in_room;
  723.     return;
  724. }
  725. void raw_kill( CHAR_DATA *victim )
  726. {
  727.     stop_fighting( victim, TRUE );
  728.     mprog_death_trigger( victim );
  729.     make_corpse( victim );
  730.     if ( IS_NPC(victim) )
  731.     {
  732. victim->pIndexData->killed++;
  733. kill_table[URANGE(0, victim->level, MAX_LEVEL-1)].killed++;
  734. extract_char( victim, TRUE );
  735. return;
  736.     }
  737.     extract_char( victim, FALSE );
  738.     while ( victim->affected )
  739. affect_remove( victim, victim->affected );
  740.     victim->affected_by = race_table[victim->race].bitvector; // ###
  741. //    victim->affected_by = 0;
  742.     victim->armor = 100;
  743.     victim->position = POS_RESTING;
  744.     victim->hit = UMAX( 1, victim->hit  );
  745.     victim->mana = UMAX( 1, victim->mana );
  746.     victim->move = UMAX( 1, victim->move );
  747.     save_char_obj( victim );
  748.     return;
  749. }
  750. void group_gain( CHAR_DATA *ch, CHAR_DATA *victim )
  751. {
  752.     char buf[MAX_STRING_LENGTH];
  753.     CHAR_DATA *gch;
  754.     CHAR_DATA *lch;
  755.     int xp;
  756.     int members;
  757.     /*
  758.      * Monsters don't get kill xp's or alignment changes.
  759.      * P-killing doesn't help either.
  760.      * Dying of mortal wounds or poison doesn't give xp to anyone!
  761.      */
  762.     if ( IS_NPC(ch) || !IS_NPC(victim) || victim == ch )
  763. return;
  764.     
  765.     members = 0;
  766.     for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room )
  767.     {
  768. if ( is_same_group( gch, ch ) )
  769.     members++;
  770.     }
  771.     if ( members == 0 )
  772.     {
  773. bug( "Group_gain: members.", members );
  774. members = 1;
  775.     }
  776.     lch = (ch->leader != NULL) ? ch->leader : ch;
  777.     for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room )
  778.     {
  779. OBJ_DATA *obj;
  780. OBJ_DATA *obj_next;
  781. if ( !is_same_group( gch, ch ) )
  782.     continue;
  783. if ( gch->level - lch->level >= 6 )
  784. {
  785.     send_to_char( "You are too high for this group.nr", gch );
  786.     continue;
  787. }
  788. if ( gch->level - lch->level <= -6 )
  789. {
  790.     send_to_char( "You are too low for this group.nr", gch );
  791.     continue;
  792. }
  793. xp = xp_compute( gch, victim ) / members;
  794. sprintf( buf, "You receive %d experience points.nr", xp );
  795. send_to_char( buf, gch );
  796. gain_exp( gch, xp );
  797. for ( obj = ch->carrying; obj != NULL; obj = obj_next )
  798. {
  799.     obj_next = obj->next_content;
  800.     if ( obj->wear_loc == WEAR_NONE )
  801. continue;
  802.     if ( ( IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)    && IS_EVIL(ch)    )
  803.     ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)    && IS_GOOD(ch)    )
  804.     ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch) ) )
  805.     {
  806. act( "You are zapped by $p.", ch, obj, NULL, TO_CHAR );
  807. act( "$n is zapped by $p.",   ch, obj, NULL, TO_ROOM );
  808. obj_from_char( obj );
  809. obj_to_room( obj, ch->in_room );
  810.     }
  811. }
  812.     }
  813.     return;
  814. }
  815. /*
  816.  * Compute xp for a kill.
  817.  * Also adjust alignment of killer.
  818.  * Edit this function to change xp computations.
  819.  */
  820. int xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
  821. {
  822.     int align;
  823.     int xp;
  824.     int extra;
  825.     int level;
  826.     int number;
  827.     xp    = 300 - URANGE( -3, gch->level - victim->level, 6 ) * 50;
  828.     align = gch->alignment - victim->alignment;
  829.     if ( align >  500 )
  830.     {
  831. gch->alignment  = UMIN( gch->alignment + (align-500)/4,  1000 );
  832. xp = 5 * xp / 4;
  833.     }
  834.     else if ( align < -500 )
  835.     {
  836. gch->alignment  = UMAX( gch->alignment + (align+500)/4, -1000 );
  837.     }
  838.     else
  839.     {
  840. gch->alignment -= gch->alignment / 4;
  841. xp = 3 * xp / 4;
  842.     }
  843.     /*
  844.      * Adjust for popularity of target:
  845.      *   -1/8 for each target over  'par' (down to -100%)
  846.      *   +1/8 for each target under 'par' (  up to + 25%)
  847.      */
  848.     level  = URANGE( 0, victim->level, MAX_LEVEL - 1 );
  849.     number = UMAX( 1, kill_table[level].number );
  850.     extra  = victim->pIndexData->killed - kill_table[level].killed / number;
  851.     xp    -= xp * URANGE( -2, extra, 8 ) / 8;
  852.     xp     = number_range( xp * 3 / 4, xp * 5 / 4 );
  853.     xp     = UMAX( 0, xp );
  854.     return xp;
  855. }
  856. void dam_message( CHAR_DATA *ch, CHAR_DATA *victim, int dam, int dt )
  857. {
  858.     static char * const attack_table[] =
  859.     {
  860. "hit",
  861. "slice",  "stab",  "slash", "whip", "claw",
  862. "blast",  "pound", "crush", "grep", "bite",
  863. "pierce", "suction", "chop" // @@@ Chop is from envy
  864.     };
  865.     char buf1[256], buf2[256], buf3[256];
  866.     const char *vs;
  867.     const char *vp;
  868.     const char *attack;
  869.     char punct;
  870.  if ( dam ==   0 ) { vs = "miss"; vp = "misses"; }
  871.     else if ( dam <=   4 ) { vs = "scratch"; vp = "scratches"; }
  872.     else if ( dam <=   8 ) { vs = "graze"; vp = "grazes"; }
  873.     else if ( dam <=  12 ) { vs = "hit"; vp = "hits"; }
  874.     else if ( dam <=  16 ) { vs = "injure"; vp = "injures"; }
  875.     else if ( dam <=  20 ) { vs = "wound"; vp = "wounds"; }
  876.     else if ( dam <=  24 ) { vs = "maul";       vp = "mauls"; }
  877.     else if ( dam <=  28 ) { vs = "decimate"; vp = "decimates"; }
  878.     else if ( dam <=  32 ) { vs = "devastate"; vp = "devastates"; }
  879.     else if ( dam <=  36 ) { vs = "maim"; vp = "maims"; }
  880.     else if ( dam <=  40 ) { vs = "MUTILATE"; vp = "MUTILATES"; }
  881.     else if ( dam <=  44 ) { vs = "DISEMBOWEL"; vp = "DISEMBOWELS"; }
  882.     else if ( dam <=  48 ) { vs = "EVISCERATE"; vp = "EVISCERATES"; }
  883.     else if ( dam <=  52 ) { vs = "MASSACRE"; vp = "MASSACRES"; }
  884.     else if ( dam <= 100 ) { vs = "*** DEMOLISH ***";
  885.      vp = "*** DEMOLISHES ***"; }
  886.     else                   { vs = "*** ANNIHILATE ***";
  887.      vp = "*** ANNIHILATES ***"; }
  888.     punct   = (dam <= 24) ? '.' : '!';
  889.     if ( dt == TYPE_HIT )
  890.     {
  891. sprintf( buf1, "$n %s $N%c",  vp, punct );
  892. sprintf( buf2, "You %s $N%c", vs, punct );
  893. sprintf( buf3, "$n %s you%c", vp, punct );
  894.     }
  895.     else
  896.     {
  897. if ( dt >= 0 && dt < MAX_SKILL )
  898.     attack = skill_table[dt].noun_damage;
  899. else if ( dt >= TYPE_HIT
  900. && dt < TYPE_HIT + sizeof(attack_table)/sizeof(attack_table[0]) )
  901.     attack = attack_table[dt - TYPE_HIT];
  902. else
  903. {
  904.     bug( "Dam_message: bad dt %d.", dt );
  905.     dt  = TYPE_HIT;
  906.     attack  = attack_table[0];
  907. }
  908. sprintf( buf1, "$n's %s %s $N%c",  attack, vp, punct );
  909. sprintf( buf2, "Your %s %s $N%c",  attack, vp, punct );
  910. sprintf( buf3, "$n's %s %s you%c", attack, vp, punct );
  911.     }
  912.     act( buf1, ch, NULL, victim, TO_NOTVICT );
  913.     act( buf2, ch, NULL, victim, TO_CHAR );
  914.     act( buf3, ch, NULL, victim, TO_VICT );
  915.     return;
  916. }
  917. /*
  918.  * Disarm a creature.
  919.  * Caller must check for successful attack.
  920.  */
  921. void disarm( CHAR_DATA *ch, CHAR_DATA *victim )
  922. {
  923.     OBJ_DATA *obj;
  924.     if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL )
  925. return;
  926.     if ( get_eq_char( ch, WEAR_WIELD ) == NULL /*&& number_bits( 1 ) == 0*/ )
  927. return;
  928.     act( "$n DISARMS you!", ch, NULL, victim, TO_VICT    );
  929.     act( "You disarm $N!",  ch, NULL, victim, TO_CHAR    );
  930.     act( "$n DISARMS $N!",  ch, NULL, victim, TO_NOTVICT );
  931.     obj_from_char( obj );
  932.     if ( IS_NPC(victim) )
  933. obj_to_char( obj, victim );
  934.     else
  935. obj_to_room( obj, victim->in_room );
  936.     return;
  937. }
  938. /*
  939.  * Trip a creature.
  940.  * Caller must check for successful attack.
  941.  */
  942. void trip( CHAR_DATA *ch, CHAR_DATA *victim )
  943. {
  944.     if ( victim->wait == 0 )
  945.     {
  946. act( "$n trips you and you go down!", ch, NULL, victim, TO_VICT    );
  947. act( "You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR    );
  948. act( "$n trips $N and $N goes down!", ch, NULL, victim, TO_NOTVICT );
  949. WAIT_STATE( ch,     2 * PULSE_VIOLENCE );
  950. WAIT_STATE( victim, 2 * PULSE_VIOLENCE );
  951. victim->position = POS_RESTING;
  952.     }
  953.     return;
  954. }
  955. void do_kill( CHAR_DATA *ch, char *argument )
  956. {
  957.     char arg[MAX_INPUT_LENGTH];
  958.     CHAR_DATA *victim;
  959.     one_argument( argument, arg );
  960.     if ( arg[0] == '' )
  961.     {
  962. send_to_char( "Kill whom?nr", ch );
  963. return;
  964.     }
  965.     if ( ( victim = get_char_room( ch, arg ) ) == NULL )
  966.     {
  967. send_to_char( "They aren't here.nr", ch );
  968. return;
  969.     }
  970.     if ( !IS_NPC(victim) )
  971.     {
  972. if ( !IS_SET(victim->act, PLR_KILLER)
  973. &&   !IS_SET(victim->act, PLR_THIEF) )
  974. {
  975.     send_to_char( "You must MURDER a player.nr", ch );
  976.     return;
  977. }
  978.     }
  979.     else
  980.     {
  981. if ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL )
  982. {
  983.     send_to_char( "You must MURDER a charmed creature.nr", ch );
  984.     return;
  985. }
  986.     }
  987.     if ( victim == ch )
  988.     {
  989. send_to_char( "You hit yourself.  Ouch!nr", ch );
  990. multi_hit( ch, ch, TYPE_UNDEFINED );
  991. return;
  992.     }
  993.     if ( is_safe( ch, victim ) )
  994. return;
  995.     if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
  996.     {
  997. act( "$N is your beloved master.", ch, NULL, victim, TO_CHAR );
  998. return;
  999.     }
  1000.     if ( ch->position == POS_FIGHTING )
  1001.     {
  1002. send_to_char( "You do the best you can!nr", ch );
  1003. return;
  1004.     }
  1005.     WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
  1006.     check_killer( ch, victim );
  1007.     multi_hit( ch, victim, TYPE_UNDEFINED );
  1008.     return;
  1009. }
  1010. void do_murde( CHAR_DATA *ch, char *argument )
  1011. {
  1012.     send_to_char( "If you want to MURDER, spell it out.nr", ch );
  1013.     return;
  1014. }
  1015. void do_murder( CHAR_DATA *ch, char *argument )
  1016. {
  1017.     char buf[MAX_STRING_LENGTH];
  1018.     char arg[MAX_INPUT_LENGTH];
  1019.     CHAR_DATA *victim;
  1020.     one_argument( argument, arg );
  1021.     if ( arg[0] == '' )
  1022.     {
  1023. send_to_char( "Murder whom?nr", ch );
  1024. return;
  1025.     }
  1026.     if ( ( victim = get_char_room( ch, arg ) ) == NULL )
  1027.     {
  1028. send_to_char( "They aren't here.nr", ch );
  1029. return;
  1030.     }
  1031.     if ( victim == ch )
  1032.     {
  1033. send_to_char( "Suicide is a mortal sin.nr", ch );
  1034. return;
  1035.     }
  1036.     if ( is_safe( ch, victim ) )
  1037. return;
  1038.     if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
  1039.     {
  1040. act( "$N is your beloved master.", ch, NULL, victim, TO_CHAR );
  1041. return;
  1042.     }
  1043.     if ( ch->position == POS_FIGHTING )
  1044.     {
  1045. send_to_char( "You do the best you can!nr", ch );
  1046. return;
  1047.     }
  1048.     WAIT_STATE( ch, 1 * PULSE_VIOLENCE );
  1049.     sprintf( buf, "Help!  I am being attacked by %s!", ch->name );
  1050.     do_shout( victim, buf );
  1051.     check_killer( ch, victim );
  1052.     multi_hit( ch, victim, TYPE_UNDEFINED );
  1053.     return;
  1054. }
  1055. void do_backstab( CHAR_DATA *ch, char *argument )
  1056. {
  1057.     char arg[MAX_INPUT_LENGTH];
  1058.     CHAR_DATA *victim;
  1059.     OBJ_DATA *obj;
  1060.     if ( !IS_NPC(ch)
  1061.     &&   ch->level < skill_table[gsn_backstab].skill_level[ch->class] )
  1062.     {
  1063. send_to_char(
  1064.     "You better leave the assassin trade to thieves.nr", ch );
  1065. return;
  1066.     }
  1067.     one_argument( argument, arg );
  1068.     
  1069.     if ( arg[0] == '' )
  1070.     {
  1071. send_to_char( "Backstab whom?nr", ch );
  1072. return;
  1073.     }
  1074.     if ( ( victim = get_char_room( ch, arg ) ) == NULL )
  1075.     {
  1076. send_to_char( "They aren't here.nr", ch );
  1077. return;
  1078.     }
  1079.     if ( victim == ch )
  1080.     {
  1081. send_to_char( "How can you sneak up on yourself?nr", ch );
  1082. return;
  1083.     }
  1084.     if ( is_safe( ch, victim ) )
  1085.       return;
  1086.     if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL
  1087.     ||   obj->value[3] != 11 )
  1088.     {
  1089. send_to_char( "You need to wield a piercing weapon.nr", ch );
  1090. return;
  1091.     }
  1092.     if ( victim->fighting != NULL )
  1093.     {
  1094. send_to_char( "You can't backstab a fighting person.nr", ch );
  1095. return;
  1096.     }
  1097.     if ( victim->hit < victim->max_hit )
  1098.     {
  1099. act( "$N is hurt and suspicious ... you can't sneak up.",
  1100.     ch, NULL, victim, TO_CHAR );
  1101. return;
  1102.     }
  1103.     check_killer( ch, victim );
  1104.     WAIT_STATE( ch, skill_table[gsn_backstab].beats );
  1105.     if ( !IS_AWAKE(victim)
  1106.     ||   IS_NPC(ch)
  1107.     ||   number_percent( ) < ch->pcdata->learned[gsn_backstab] )
  1108. multi_hit( ch, victim, gsn_backstab );
  1109.     else
  1110. damage( ch, victim, 0, gsn_backstab );
  1111.     return;
  1112. }
  1113. void do_flee( CHAR_DATA *ch, char *argument )
  1114. {
  1115.     ROOM_INDEX_DATA *was_in;
  1116.     ROOM_INDEX_DATA *now_in;
  1117.     CHAR_DATA *victim;
  1118.     int attempt;
  1119.     if ( ( victim = ch->fighting ) == NULL )
  1120.     {
  1121. if ( ch->position == POS_FIGHTING )
  1122.     ch->position = POS_STANDING;
  1123. send_to_char( "You aren't fighting anyone.nr", ch );
  1124. return;
  1125.     }
  1126.     was_in = ch->in_room;
  1127.     for ( attempt = 0; attempt < 6; attempt++ )
  1128.     {
  1129. EXIT_DATA *pexit;
  1130. int door;
  1131. door = number_door( );
  1132. if ( ( pexit = was_in->exit[door] ) == 0
  1133.     ||   pexit->to_room == NULL
  1134.     ||   IS_SET(pexit->exit_info, EX_CLOSED)
  1135.     || ( IS_NPC(ch)
  1136. && ( IS_SET(pexit->to_room->room_flags, ROOM_NO_MOB)
  1137.     || ( IS_SET(ch->act, ACT_STAY_AREA)
  1138. && pexit->to_room->area != ch->in_room->area ) ) ) )
  1139.     continue;
  1140. move_char( ch, door );
  1141. if ( ( now_in = ch->in_room ) == was_in )
  1142.     continue;
  1143. ch->in_room = was_in;
  1144. act( "$n has fled!", ch, NULL, NULL, TO_ROOM );
  1145. ch->in_room = now_in;
  1146. if ( !IS_NPC(ch) )
  1147. {
  1148.     send_to_char( "You flee from combat!  You lose 25 exps.nr", ch );
  1149.     gain_exp( ch, -25 );
  1150. }
  1151. stop_fighting( ch, TRUE );
  1152. return;
  1153.     }
  1154.     send_to_char( "You failed!  You lose 10 exps.nr", ch );
  1155.     gain_exp( ch, -10 );
  1156.     return;
  1157. }
  1158. void do_rescue( CHAR_DATA *ch, char *argument )
  1159. {
  1160.     char arg[MAX_INPUT_LENGTH];
  1161.     CHAR_DATA *victim;
  1162.     CHAR_DATA *fch;
  1163.     if ( !IS_NPC(ch)
  1164.     &&   ch->level < skill_table[gsn_rescue].skill_level[ch->class] )
  1165.     {
  1166. send_to_char(
  1167.     "You better leave the heroic acts to warriors.nr", ch );
  1168. return;
  1169.     }
  1170.     one_argument( argument, arg );
  1171.     if ( arg[0] == '' )
  1172.     {
  1173. send_to_char( "Rescue whom?nr", ch );
  1174. return;
  1175.     }
  1176.     if ( ( victim = get_char_room( ch, arg ) ) == NULL )
  1177.     {
  1178. send_to_char( "They aren't here.nr", ch );
  1179. return;
  1180.     }
  1181.     if ( victim == ch )
  1182.     {
  1183. send_to_char( "What about fleeing instead?nr", ch );
  1184. return;
  1185.     }
  1186.     if ( !IS_NPC(ch) && IS_NPC(victim) )
  1187.     {
  1188. send_to_char( "Doesn't need your help!nr", ch );
  1189. return;
  1190.     }
  1191.     if ( ch->fighting == victim )
  1192.     {
  1193. send_to_char( "Too late.nr", ch );
  1194. return;
  1195.     }
  1196.     if ( ( fch = victim->fighting ) == NULL )
  1197.     {
  1198. send_to_char( "That person is not fighting right now.nr", ch );
  1199. return;
  1200.     }
  1201.     WAIT_STATE( ch, skill_table[gsn_rescue].beats );
  1202.     if ( !IS_NPC(ch) && number_percent( ) > ch->pcdata->learned[gsn_rescue] )
  1203.     {
  1204. send_to_char( "You fail the rescue.nr", ch );
  1205. return;
  1206.     }
  1207.     act( "You rescue $N!",  ch, NULL, victim, TO_CHAR    );
  1208.     act( "$n rescues you!", ch, NULL, victim, TO_VICT    );
  1209.     act( "$n rescues $N!",  ch, NULL, victim, TO_NOTVICT );
  1210.     stop_fighting( fch, FALSE );
  1211.     stop_fighting( victim, FALSE );
  1212.     check_killer( ch, fch );
  1213.     set_fighting( ch, fch );
  1214.     set_fighting( fch, ch );
  1215.     return;
  1216. }
  1217. void do_kick( CHAR_DATA *ch, char *argument )
  1218. {
  1219.     CHAR_DATA *victim;
  1220.     if ( !IS_NPC(ch)
  1221.     &&   ch->level < skill_table[gsn_kick].skill_level[ch->class] )
  1222.     {
  1223. send_to_char(
  1224.     "You better leave the martial arts to fighters.nr", ch );
  1225. return;
  1226.     }
  1227.     if ( ( victim = ch->fighting ) == NULL )
  1228.     {
  1229. send_to_char( "You aren't fighting anyone.nr", ch );
  1230. return;
  1231.     }
  1232.     WAIT_STATE( ch, skill_table[gsn_kick].beats );
  1233.     if ( IS_NPC(ch) || number_percent( ) < ch->pcdata->learned[gsn_kick] )
  1234. damage( ch, victim, number_range( 1, ch->level ), gsn_kick );
  1235.     else
  1236. damage( ch, victim, 0, gsn_kick );
  1237.     return;
  1238. }
  1239. void do_disarm( CHAR_DATA *ch, char *argument )
  1240. {
  1241.     CHAR_DATA *victim;
  1242.     OBJ_DATA *obj;
  1243.     int percent;
  1244.     if ( !IS_NPC(ch)
  1245.     &&   ch->level < skill_table[gsn_disarm].skill_level[ch->class] )
  1246.     {
  1247. send_to_char( "You don't know how to disarm opponents.nr", ch );
  1248. return;
  1249.     }
  1250.     if ( get_eq_char( ch, WEAR_WIELD ) == NULL )
  1251.     {
  1252. send_to_char( "You must wield a weapon to disarm.nr", ch );
  1253. return;
  1254.     }
  1255.     if ( ( victim = ch->fighting ) == NULL )
  1256.     {
  1257. send_to_char( "You aren't fighting anyone.nr", ch );
  1258. return;
  1259.     }
  1260.     if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL )
  1261.     {
  1262. send_to_char( "Your opponent is not wielding a weapon.nr", ch );
  1263. return;
  1264.     }
  1265.     WAIT_STATE( ch, skill_table[gsn_disarm].beats );
  1266.     percent = number_percent( ) + victim->level - ch->level;
  1267.     if ( IS_NPC(ch) || percent < ch->pcdata->learned[gsn_disarm] * 2 / 3 )
  1268. disarm( ch, victim );
  1269.     else
  1270. send_to_char( "You failed.nr", ch );
  1271.     return;
  1272. }
  1273. void do_sla( CHAR_DATA *ch, char *argument )
  1274. {
  1275.     send_to_char( "If you want to SLAY, spell it out.nr", ch );
  1276.     return;
  1277. }
  1278. void do_slay( CHAR_DATA *ch, char *argument )
  1279. {
  1280.     CHAR_DATA *victim;
  1281.     char arg[MAX_INPUT_LENGTH];
  1282.     one_argument( argument, arg );
  1283.     if ( arg[0] == '' )
  1284.     {
  1285. send_to_char( "Slay whom?nr", ch );
  1286. return;
  1287.     }
  1288.     if ( ( victim = get_char_room( ch, arg ) ) == NULL )
  1289.     {
  1290. send_to_char( "They aren't here.nr", ch );
  1291. return;
  1292.     }
  1293.     if ( ch == victim )
  1294.     {
  1295. send_to_char( "Suicide is a mortal sin.nr", ch );
  1296. return;
  1297.     }
  1298.     if ( !IS_NPC(victim) && victim->level >= ch->level )
  1299.     {
  1300. send_to_char( "You failed.nr", ch );
  1301. return;
  1302.     }
  1303.     act( "You slay $M in cold blood!",  ch, NULL, victim, TO_CHAR    );
  1304.     act( "$n slays you in cold blood!", ch, NULL, victim, TO_VICT    );
  1305.     act( "$n slays $N in cold blood!",  ch, NULL, victim, TO_NOTVICT );
  1306.     raw_kill( victim );
  1307.     return;
  1308. }