home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / d / d-linux.zip / dm-dist / fight.c < prev    next >
C/C++ Source or Header  |  1991-03-01  |  22KB  |  800 lines

  1. /* ************************************************************************
  2. *  File: fight.c , Combat module.                         Part of DIKUMUD *
  3. *  Usage: Combat system and messages.                                     *
  4. *  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
  5. ************************************************************************* */
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <assert.h>
  10.  
  11. #include "structs.h"
  12. #include "utils.h"
  13. #include "comm.h"
  14. #include "handler.h"
  15. #include "interpreter.h"
  16. #include "db.h"
  17. #include "spells.h"
  18.  
  19. /* Structures */
  20.  
  21. struct char_data *combat_list = 0;        /* head of l-list of fighting chars    */
  22. struct char_data *combat_next_dude = 0; /* Next dude global trick           */
  23.  
  24.  
  25. /* External structures */
  26.  
  27. extern struct room_data *world;
  28. extern struct message_list fight_messages[MAX_MESSAGES];
  29. extern struct obj_data  *object_list;
  30.  
  31. /* External procedures */
  32.  
  33. char *fread_string(FILE *f1);
  34. void stop_follower(struct char_data *ch);
  35. void do_flee(struct char_data *ch, char *argument, int cmd);
  36. void hit(struct char_data *ch, struct char_data *victim, int type);
  37.  
  38.  
  39. /* Weapon attack texts */
  40. struct attack_hit_type attack_hit_text[] =
  41. {
  42.   {"hit",   "hits"},             /* TYPE_HIT      */
  43.   {"pound", "pounds"},           /* TYPE_BLUDGEON */
  44.   {"pierce", "pierces"},         /* TYPE_PIERCE   */
  45.   {"slash", "slashes"},          /* TYPE_SLASH    */
  46.   {"whip", "whips"},             /* TYPE_WHIP     */
  47.   {"claw", "claws"},             /* TYPE_CLAW     */
  48.   {"bite", "bites"},             /* TYPE_BITE     */
  49.   {"sting", "stings"},           /* TYPE_STING    */
  50.   {"crush", "crushes"}           /* TYPE_CRUSH    */
  51. };
  52.  
  53.  
  54.  
  55.  
  56. /* The Fight related routines */
  57.  
  58.  
  59. void appear(struct char_data *ch)
  60. {
  61.   act("$n slowly fade into existence.", FALSE, ch,0,0,TO_ROOM);
  62.  
  63.   if (affected_by_spell(ch, SPELL_INVISIBLE))
  64.     affect_from_char(ch, SPELL_INVISIBLE);
  65.  
  66.   REMOVE_BIT(ch->specials.affected_by, AFF_INVISIBLE);
  67. }
  68.  
  69.  
  70.  
  71. void load_messages(void)
  72. {
  73.     FILE *f1;
  74.     int i,type;
  75.     struct message_type *messages;
  76.     char chk[100];
  77.  
  78.     if (!(f1 = fopen(MESS_FILE, "r"))){
  79.         perror("read messages");
  80.         exit(0);
  81.     }
  82.  
  83.     for (i = 0; i < MAX_MESSAGES; i++)
  84.     { 
  85.         fight_messages[i].a_type = 0;
  86.         fight_messages[i].number_of_attacks=0;
  87.         fight_messages[i].msg = 0;
  88.     }
  89.  
  90.     fscanf(f1, " %s \n", chk);
  91.  
  92.     while(*chk == 'M')
  93.     {
  94.         fscanf(f1," %d\n", &type);
  95.         for (i = 0; (i < MAX_MESSAGES) && (fight_messages[i].a_type!=type) &&
  96.             (fight_messages[i].a_type); i++);
  97.         if(i>=MAX_MESSAGES){
  98.             log("Too many combat messages.");
  99.             exit(0);
  100.         }
  101.  
  102.         CREATE(messages,struct message_type,1);
  103.         fight_messages[i].number_of_attacks++;
  104.         fight_messages[i].a_type=type;
  105.         messages->next=fight_messages[i].msg;
  106.         fight_messages[i].msg=messages;
  107.  
  108.         messages->die_msg.attacker_msg      = fread_string(f1);
  109.         messages->die_msg.victim_msg        = fread_string(f1);
  110.         messages->die_msg.room_msg          = fread_string(f1);
  111.         messages->miss_msg.attacker_msg     = fread_string(f1);
  112.         messages->miss_msg.victim_msg       = fread_string(f1);
  113.         messages->miss_msg.room_msg         = fread_string(f1);
  114.         messages->hit_msg.attacker_msg      = fread_string(f1);
  115.         messages->hit_msg.victim_msg        = fread_string(f1);
  116.         messages->hit_msg.room_msg          = fread_string(f1);
  117.         messages->god_msg.attacker_msg      = fread_string(f1);
  118.         messages->god_msg.victim_msg        = fread_string(f1);
  119.         messages->god_msg.room_msg          = fread_string(f1);
  120.         fscanf(f1, " %s \n", chk);
  121.     }
  122.  
  123.     fclose(f1);
  124. }
  125.  
  126.  
  127. void update_pos( struct char_data *victim )
  128. {
  129.  
  130.     if ((GET_HIT(victim) > 0) && (GET_POS(victim) > POSITION_STUNNED)) return;
  131.     else if (GET_HIT(victim) > 0 ) GET_POS(victim) = POSITION_STANDING;
  132.     else if (GET_HIT(victim) <= -11) GET_POS(victim) = POSITION_DEAD;
  133.     else if (GET_HIT(victim) <= -6) GET_POS(victim) = POSITION_MORTALLYW;
  134.     else if (GET_HIT(victim) <= -3) GET_POS(victim) = POSITION_INCAP;
  135.     else GET_POS(victim) = POSITION_STUNNED;
  136.  
  137. }
  138.  
  139.  
  140. /* start one char fighting another (yes, it is horrible, I know... )  */
  141. void set_fighting(struct char_data *ch, struct char_data *vict)
  142. {
  143.     assert(!ch->specials.fighting);
  144.  
  145.     ch->next_fighting = combat_list;
  146.     combat_list = ch;
  147.  
  148.     if(IS_AFFECTED(ch,AFF_SLEEP))
  149.         affect_from_char(ch,SPELL_SLEEP);
  150.  
  151.     ch->specials.fighting = vict;
  152.     GET_POS(ch) = POSITION_FIGHTING;
  153. }
  154.  
  155.  
  156.  
  157. /* remove a char from the list of fighting chars */
  158. void stop_fighting(struct char_data *ch)
  159. {
  160.     struct char_data *tmp;
  161.  
  162.     assert(ch->specials.fighting);
  163.  
  164.     if (ch == combat_next_dude)
  165.         combat_next_dude = ch->next_fighting;
  166.  
  167.     if (combat_list == ch)
  168.        combat_list = ch->next_fighting;
  169.     else
  170.     {
  171.         for (tmp = combat_list; tmp && (tmp->next_fighting != ch); 
  172.             tmp = tmp->next_fighting);
  173.         if (!tmp) {
  174.             log("Char fighting not found Error (fight.c, stop_fighting)");
  175.             abort();
  176.         }
  177.         tmp->next_fighting = ch->next_fighting;
  178.     }
  179.  
  180.     ch->next_fighting = 0;
  181.     ch->specials.fighting = 0;
  182.     GET_POS(ch) = POSITION_STANDING;
  183.     update_pos(ch);
  184. }
  185.  
  186.  
  187.  
  188. #define MAX_NPC_CORPSE_TIME 5
  189. #define MAX_PC_CORPSE_TIME 10
  190.  
  191. void make_corpse(struct char_data *ch)
  192. {
  193.     struct obj_data *corpse, *o;
  194.     struct obj_data *money;    
  195.     char buf[MAX_STRING_LENGTH];
  196.     int i;
  197.  
  198.     char *strdup(char *source);
  199.     struct obj_data *create_money( int amount );
  200.  
  201.     CREATE(corpse, struct obj_data, 1);
  202.     clear_object(corpse);
  203.  
  204.     
  205.     corpse->item_number = NOWHERE;
  206.     corpse->in_room = NOWHERE;
  207.     corpse->name = strdup("corpse");
  208.  
  209.     sprintf(buf, "Corpse of %s is lying here.", 
  210.       (IS_NPC(ch) ? ch->player.short_descr : GET_NAME(ch)));
  211.     corpse->description = strdup(buf);
  212.  
  213.     sprintf(buf, "Corpse of %s",
  214.       (IS_NPC(ch) ? ch->player.short_descr : GET_NAME(ch)));
  215.     corpse->short_description = strdup(buf);
  216.  
  217.     corpse->contains = ch->carrying;
  218.     if(GET_GOLD(ch)>0)
  219.     {
  220.         money = create_money(GET_GOLD(ch));
  221.         GET_GOLD(ch)=0;
  222.         obj_to_obj(money,corpse);
  223.     }
  224.  
  225.     corpse->obj_flags.type_flag = ITEM_CONTAINER;
  226.     corpse->obj_flags.wear_flags = ITEM_TAKE;
  227.     corpse->obj_flags.value[0] = 0; /* You can't store stuff in a corpse */
  228.   corpse->obj_flags.value[3] = 1; /* corpse identifyer */
  229.     corpse->obj_flags.weight = GET_WEIGHT(ch)+IS_CARRYING_W(ch);
  230.     corpse->obj_flags.cost_per_day = 100000;
  231.     if (IS_NPC(ch))
  232.         corpse->obj_flags.timer = MAX_NPC_CORPSE_TIME;
  233.     else
  234.         corpse->obj_flags.timer = MAX_PC_CORPSE_TIME;
  235.  
  236.     for (i=0; i<MAX_WEAR; i++)
  237.         if (ch->equipment[i])
  238.             obj_to_obj(unequip_char(ch, i), corpse);
  239.  
  240.     ch->carrying = 0;
  241.     IS_CARRYING_N(ch) = 0;
  242.     IS_CARRYING_W(ch) = 0;
  243.  
  244.     corpse->next = object_list;
  245.     object_list = corpse;
  246.  
  247.     for(o = corpse->contains; o; o->in_obj = corpse, o = o->next_content);
  248.     object_list_new_owner(corpse, 0);
  249.  
  250.     obj_to_room(corpse, ch->in_room);
  251. }
  252.  
  253.  
  254. /* When ch kills victim */
  255. void change_alignment(struct char_data *ch, struct char_data *victim)
  256. {
  257.     int align;
  258.  
  259.     if ((align = GET_ALIGNMENT(ch)-GET_ALIGNMENT(victim)) > 0) {
  260.         if (align > 650)
  261.             GET_ALIGNMENT(ch) = MIN(1000,GET_ALIGNMENT(ch) + ((align-650) >> 3));
  262.         else
  263.             GET_ALIGNMENT(ch) >>= 1;
  264.     } else {
  265.         if (align < -650)
  266.             GET_ALIGNMENT(ch) = MAX(-1000, GET_ALIGNMENT(ch) + ((align+650) >> 3));
  267.         else
  268.             GET_ALIGNMENT(ch) >>= 1;
  269.     }
  270. }
  271.  
  272.  
  273.  
  274. void death_cry(struct char_data *ch)
  275. {
  276.     struct char_data *victim;
  277.     int door, was_in;
  278.  
  279.     act("Your blood freezes as you hear $ns death cry.", FALSE, ch,0,0,TO_ROOM);
  280.     was_in = ch->in_room;
  281.  
  282.     for (door = 0; door <= 5; door++) {
  283.         if (CAN_GO(ch, door))    {
  284.             ch->in_room = world[was_in].dir_option[door]->to_room;
  285.             act("Your blood freezes as you hear someones death cry.",FALSE,ch,0,0,TO_ROOM);
  286.             ch->in_room = was_in;
  287.         }
  288.     }
  289. }
  290.  
  291.  
  292.  
  293. void raw_kill(struct char_data *ch)
  294. {
  295.     if (ch->specials.fighting)
  296.         stop_fighting(ch);
  297.  
  298.     death_cry(ch);
  299.  
  300.     make_corpse(ch);
  301.     extract_char(ch);
  302. }
  303.  
  304.  
  305.  
  306. void die(struct char_data *ch)
  307. {
  308.     gain_exp(ch, -(GET_EXP(ch)/2));
  309.     raw_kill(ch);
  310. }
  311.  
  312.  
  313.  
  314. void group_gain(struct char_data *ch, struct char_data *victim)
  315. {
  316.     char buf[256];
  317.     int no_members, share;
  318.     struct char_data *k;
  319.     struct follow_type *f;
  320.  
  321.     if (!(k=ch->master))
  322.         k = ch;
  323.  
  324.  
  325.     if (IS_AFFECTED(k, AFF_GROUP) &&
  326.        (k->in_room == ch->in_room))
  327.         no_members = 1;
  328.     else
  329.         no_members = 0;
  330.  
  331.     for (f=k->followers; f; f=f->next)
  332.         if (IS_AFFECTED(f->follower, AFF_GROUP) &&
  333.            (f->follower->in_room == ch->in_room))
  334.             no_members++;
  335.  
  336.     if (no_members >= 1)
  337.         share = MIN(450000/no_members, (GET_EXP(victim)/3)/no_members);
  338.     else
  339.         share = 0;
  340.  
  341.     if (IS_AFFECTED(k, AFF_GROUP) &&
  342.        (k->in_room == ch->in_room)) {
  343.         act("You receive your share of experience.", FALSE, k, 0, 0, TO_CHAR);
  344.         gain_exp(k, share);
  345.         change_alignment(k, victim);
  346.     }
  347.  
  348.     for (f=k->followers; f; f=f->next) {
  349.         if (IS_AFFECTED(f->follower, AFF_GROUP) &&
  350.            (f->follower->in_room == ch->in_room)) {
  351.             act("You receive your share of experience.", FALSE, f->follower,0,0,TO_CHAR);
  352.             gain_exp(f->follower, share);
  353.             change_alignment(f->follower, victim);
  354.         }
  355.     }
  356. }
  357.  
  358. char *replace_string(char *str, char *weapon)
  359. {
  360.     static char buf[256];
  361.     char *cp;
  362.  
  363.     cp = buf;
  364.  
  365.     for (; *str; str++) {
  366.         if (*str == '#') {
  367.             switch(*(++str)) {
  368.                 case 'W' : 
  369.                     for (; *weapon; *(cp++) = *(weapon++));
  370.                     break;
  371.                 default :
  372.                     *(cp++) = '#';
  373.                     break;
  374.             }
  375.         } else {
  376.             *(cp++) = *str;
  377.         }
  378.  
  379.         *cp = 0;
  380.     } /* For */
  381.  
  382.     return(buf);
  383. }
  384.  
  385.  
  386.  
  387. void dam_message(int dam, struct char_data *ch, struct char_data *victim,
  388.                  int w_type)
  389. {
  390.     struct obj_data *wield;
  391.     char *buf;
  392.  
  393.     static struct dam_weapon_type {
  394.         char *to_room;
  395.         char *to_char;
  396.         char *to_victim;
  397.     } dam_weapons[] = {
  398.  
  399.      {"$n misses $N with $s #W.",                           /*    0    */
  400.       "You miss $N with your #W.",
  401.       "$n miss you with $s #W." },
  402.  
  403.    {"$n tickles $N with $s #W.",                          /*  1.. 2  */
  404.     "You tickle $N as you #W $M.",
  405.     "$n tickle you as $e #W you." },
  406.  
  407.    {"$n barely #W $N.",                                   /*  3.. 4  */
  408.     "You barely #W $N.",
  409.     "$n barely #W you."},
  410.  
  411.      {"$n #W $N.",                                          /*  5.. 6  */
  412.     "You #W $N.",
  413.     "$n #W you."}, 
  414.  
  415.      {"$n #W $N hard.",                                     /*  7..10  */
  416.       "You #W $N hard.",
  417.     "$n #W you hard."},
  418.  
  419.      {"$n #W $N very hard.",                                /* 11..14  */
  420.       "You #W $N very hard.",
  421.       "$n #W you very hard."},
  422.  
  423.      {"$n #W $N extremely hard.",                          /* 15..20  */
  424.       "You #W $N extremely hard.",
  425.       "$n #W you extremely hard."},
  426.  
  427.      {"$n massacre $N to small fragments with $s #W.",     /* > 20    */
  428.       "You massacre $N to small fragments with your #W.",
  429.       "$n massacre you to small fragments with $s #W."}
  430.     };
  431.  
  432.     w_type -= TYPE_HIT;   /* Change to base of table with text */
  433.  
  434.     wield = ch->equipment[WIELD];
  435.  
  436.     if (dam == 0) {
  437.         buf = replace_string(dam_weapons[0].to_room, attack_hit_text[w_type].singular);
  438.         act(buf, FALSE, ch, wield, victim, TO_NOTVICT);
  439.         buf = replace_string(dam_weapons[0].to_char, attack_hit_text[w_type].singular);
  440.         act(buf, FALSE, ch, wield, victim, TO_CHAR);
  441.         buf = replace_string(dam_weapons[0].to_victim, attack_hit_text[w_type].singular);
  442.         act(buf, FALSE, ch, wield, victim, TO_VICT);
  443.     } else if (dam <= 2) {
  444.         buf = replace_string(dam_weapons[1].to_room, attack_hit_text[w_type].singular);
  445.         act(buf, FALSE, ch, wield, victim, TO_NOTVICT);
  446.         buf = replace_string(dam_weapons[1].to_char, attack_hit_text[w_type].singular);
  447.         act(buf, FALSE, ch, wield, victim, TO_CHAR);
  448.         buf = replace_string(dam_weapons[1].to_victim, attack_hit_text[w_type].plural);
  449.         act(buf, FALSE, ch, wield, victim, TO_VICT);
  450.     } else if (dam <= 4) {
  451.         buf = replace_string(dam_weapons[2].to_room, attack_hit_text[w_type].singular);
  452.         act(buf, FALSE, ch, wield, victim, TO_NOTVICT);
  453.         buf = replace_string(dam_weapons[2].to_char, attack_hit_text[w_type].singular);
  454.         act(buf, FALSE, ch, wield, victim, TO_CHAR);
  455.         buf = replace_string(dam_weapons[2].to_victim, attack_hit_text[w_type].plural);
  456.         act(buf, FALSE, ch, wield, victim, TO_VICT);
  457.     } else if (dam <= 6) {
  458.         buf = replace_string(dam_weapons[3].to_room, attack_hit_text[w_type].plural);
  459.         act(buf, FALSE, ch, wield, victim, TO_NOTVICT);
  460.         buf = replace_string(dam_weapons[3].to_char, attack_hit_text[w_type].singular);
  461.         act(buf, FALSE, ch, wield, victim, TO_CHAR);
  462.         buf = replace_string(dam_weapons[3].to_victim, attack_hit_text[w_type].plural);
  463.         act(buf, FALSE, ch, wield, victim, TO_VICT);
  464.     } else if (dam <= 10) {
  465.         buf = replace_string(dam_weapons[4].to_room, attack_hit_text[w_type].plural);
  466.         act(buf, FALSE, ch, wield, victim, TO_NOTVICT);
  467.         buf = replace_string(dam_weapons[4].to_char, attack_hit_text[w_type].singular);
  468.         act(buf, FALSE, ch, wield, victim, TO_CHAR);
  469.         buf = replace_string(dam_weapons[4].to_victim, attack_hit_text[w_type].singular);
  470.         act(buf, FALSE, ch, wield, victim, TO_VICT);
  471.     } else if (dam <= 15) {
  472.         buf = replace_string(dam_weapons[5].to_room, attack_hit_text[w_type].plural);
  473.         act(buf, FALSE, ch, wield, victim, TO_NOTVICT);
  474.         buf = replace_string(dam_weapons[5].to_char, attack_hit_text[w_type].singular);
  475.         act(buf, FALSE, ch, wield, victim, TO_CHAR);
  476.         buf = replace_string(dam_weapons[5].to_victim, attack_hit_text[w_type].plural);
  477.         act(buf, FALSE, ch, wield, victim, TO_VICT);
  478.     } else if (dam <= 20) {
  479.         buf = replace_string(dam_weapons[6].to_room, attack_hit_text[w_type].singular);
  480.         act(buf, FALSE, ch, wield, victim, TO_NOTVICT);
  481.         buf = replace_string(dam_weapons[6].to_char, attack_hit_text[w_type].singular);
  482.         act(buf, FALSE, ch, wield, victim, TO_CHAR);
  483.         buf = replace_string(dam_weapons[6].to_victim, attack_hit_text[w_type].singular);
  484.         act(buf, FALSE, ch, wield, victim, TO_VICT);
  485.     } else {
  486.         buf = replace_string(dam_weapons[7].to_room, attack_hit_text[w_type].singular);
  487.         act(buf, FALSE, ch, wield, victim, TO_NOTVICT);
  488.         buf = replace_string(dam_weapons[7].to_char, attack_hit_text[w_type].singular);
  489.         act(buf, FALSE, ch, wield, victim, TO_CHAR);
  490.         buf = replace_string(dam_weapons[7].to_victim, attack_hit_text[w_type].singular);
  491.         act(buf, FALSE, ch, wield, victim, TO_VICT);
  492.     }
  493. }
  494.  
  495.  
  496.  
  497. void damage(struct char_data *ch, struct char_data *victim,
  498.             int dam, int attacktype)
  499. {
  500.     char buf[MAX_STRING_LENGTH];
  501.     struct message_type *messages;
  502.     int i,j,nr,max_hit,exp;
  503.  
  504.     int hit_limit(struct char_data *ch);
  505.  
  506.     assert(GET_POS(victim) > POSITION_DEAD);
  507.  
  508.     if ((GET_LEVEL(victim)>20) && !IS_NPC(victim)) /* You can't damage an immortal! */
  509.         dam=0;
  510.         
  511.     if (victim != ch) {
  512.         if (GET_POS(victim) > POSITION_STUNNED) {
  513.             if (!(victim->specials.fighting))
  514.                 set_fighting(victim, ch);
  515.             GET_POS(victim) = POSITION_FIGHTING;
  516.         }
  517.  
  518.         if (GET_POS(ch) > POSITION_STUNNED) {
  519.             if (!(ch->specials.fighting))
  520.                 set_fighting(ch, victim);
  521.  
  522.             if (IS_NPC(ch) && IS_NPC(victim) &&
  523.           victim->master &&
  524.                 !number(0,10) && IS_AFFECTED(victim, AFF_CHARM) &&
  525.                 (victim->master->in_room == ch->in_room)) {
  526.                 if (ch->specials.fighting)
  527.                     stop_fighting(ch);
  528.                 hit(ch, victim->master, TYPE_UNDEFINED);
  529.                 return;
  530.             }
  531.         }
  532.     }
  533.  
  534.     if (victim->master == ch)
  535.         stop_follower(victim);
  536.             
  537.     if (IS_AFFECTED(ch, AFF_INVISIBLE))
  538.         appear(ch);
  539.  
  540.     if (IS_AFFECTED(victim, AFF_SANCTUARY))
  541.         dam = MIN(dam, 18);  /* Max 18 damage when sanctuary */
  542.  
  543.     dam=MIN(dam,100);
  544.  
  545.     dam=MAX(dam,0);
  546.  
  547.     GET_HIT(victim)-=dam;
  548.  
  549.     if (ch != victim)
  550.         gain_exp(ch,GET_LEVEL(victim)*dam);
  551.  
  552.     update_pos(victim);
  553.  
  554.  
  555.     if ((attacktype >= TYPE_HIT) && (attacktype <= TYPE_SLASH)) {
  556.         if (!ch->equipment[WIELD]) {
  557.             dam_message(dam, ch, victim, TYPE_HIT);
  558.         } else {
  559.             dam_message(dam, ch, victim, attacktype);
  560.         }
  561.     } else {
  562.  
  563.     for(i = 0; i < MAX_MESSAGES; i++) {
  564.         if (fight_messages[i].a_type == attacktype) {
  565.             nr=dice(1,fight_messages[i].number_of_attacks);
  566.             for(j=1,messages=fight_messages[i].msg;(j<nr)&&(messages);j++)
  567.                 messages=messages->next;
  568.  
  569.             if (!IS_NPC(victim) && (GET_LEVEL(victim) > 20)) {
  570.                 act(messages->god_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR);
  571.                 act(messages->god_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT);
  572.                 act(messages->god_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT);
  573.             } else if (dam != 0) {
  574.                 if (GET_POS(victim) == POSITION_DEAD) {
  575.                     act(messages->die_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR);
  576.                     act(messages->die_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT);
  577.                     act(messages->die_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT);
  578.                 } else {
  579.                     act(messages->hit_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR);
  580.                     act(messages->hit_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT);
  581.                     act(messages->hit_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT);
  582.                 }
  583.             } else { /* Dam == 0 */
  584.                 act(messages->miss_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR);
  585.                 act(messages->miss_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT);
  586.                 act(messages->miss_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT);
  587.             }
  588.         }
  589.     }
  590.     }
  591.     switch (GET_POS(victim)) {
  592.         case POSITION_MORTALLYW:
  593.             act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, TO_ROOM);
  594.             act("You are mortally wounded, and will die soon, if not aided.", FALSE, victim, 0, 0, TO_CHAR);
  595.             break;
  596.         case POSITION_INCAP:
  597.             act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, TO_ROOM);
  598.             act("You are incapacitated an will slowly die, if not aided.", FALSE, victim, 0, 0, TO_CHAR);
  599.             break;
  600.         case POSITION_STUNNED:
  601.             act("$n is stunned, but will probably regain conscience again.", TRUE, victim, 0, 0, TO_ROOM);
  602.             act("You're stunned, but will probably regain conscience again.", FALSE, victim, 0, 0, TO_CHAR);
  603.             break;
  604.         case POSITION_DEAD:
  605.             act("$n is dead! R.I.P.", TRUE, victim, 0, 0, TO_ROOM);
  606.             act("You are dead!  Sorry...", FALSE, victim, 0, 0, TO_CHAR);
  607.             break;
  608.  
  609.         default:  /* >= POSITION SLEEPING */
  610.  
  611.             max_hit=hit_limit(victim);
  612.  
  613.             if (dam > (max_hit/5))
  614.                 act("That Really did HURT!",FALSE, victim, 0, 0, TO_CHAR);
  615.  
  616.             if (GET_HIT(victim) < (max_hit/5)) {
  617.  
  618.                 act("You wish that your wounds would stop BLEEDING that much!",FALSE,victim,0,0,TO_CHAR);
  619.                 if (IS_NPC(victim))
  620.                     if (IS_SET(victim->specials.act, ACT_WIMPY))
  621.                         do_flee(victim, "", 0);
  622.             }
  623.             break;        
  624.     }
  625.  
  626.     if (!IS_NPC(victim) && !(victim->desc)) {
  627.         do_flee(victim, "", 0);
  628.         if (!victim->specials.fighting) {
  629.             act("$n is rescued by divine forces.", FALSE, victim, 0, 0, TO_ROOM);
  630.             victim->specials.was_in_room = victim->in_room;
  631.             char_from_room(victim);
  632.             char_to_room(victim, 0);
  633.         }
  634.     }
  635.  
  636.     if (GET_POS(victim) < POSITION_STUNNED)
  637.         if (ch->specials.fighting == victim)
  638.             stop_fighting(ch);
  639.  
  640.     if (!AWAKE(victim))
  641.         if (victim->specials.fighting)
  642.             stop_fighting(victim);
  643.  
  644.     if (GET_POS(victim) == POSITION_DEAD) {
  645.         if (IS_NPC(victim) || victim->desc)
  646.             if (IS_AFFECTED(ch, AFF_GROUP)) {
  647.                     group_gain(ch, victim);
  648.             } else {
  649.                 /* Calculate level-difference bonus */
  650.                 exp = GET_EXP(victim)/3;
  651.                 if (IS_NPC(ch))
  652.                     exp += (exp*MIN(4, (GET_LEVEL(victim) - GET_LEVEL(ch))))>>3;
  653.                 else
  654.                     exp += (exp*MIN(8, (GET_LEVEL(victim) - GET_LEVEL(ch))))>>3;
  655.                 exp = MAX(exp, 1);
  656.                 gain_exp(ch, exp);
  657.                 change_alignment(ch, victim);
  658.             }
  659.         if (!IS_NPC(victim)) {
  660.             sprintf(buf, "%s killed by %s at %s",
  661.                 GET_NAME(victim),
  662.                 (IS_NPC(ch) ? ch->player.short_descr : GET_NAME(ch)),
  663.                 world[victim->in_room].name);
  664.             log(buf);
  665.         }
  666.         die(victim);
  667.     }
  668. }
  669.  
  670.  
  671.  
  672. void hit(struct char_data *ch, struct char_data *victim, int type)
  673. {
  674.  
  675.     struct obj_data *wielded = 0;
  676.     struct obj_data *held = 0;
  677.     int w_type;
  678.     int victim_ac, calc_thaco;
  679.     int dam;
  680.     byte diceroll;
  681.  
  682.     extern int thaco[4][25];
  683.     extern byte backstab_mult[];
  684.     extern struct str_app_type str_app[];
  685.     extern struct dex_app_type dex_app[];
  686.  
  687.     if (ch->in_room != victim->in_room) {
  688.         log("NOT SAME ROOM WHEN FIGHTING!");
  689.         return;
  690.     }
  691.  
  692.     if (ch->equipment[HOLD])
  693.         held = ch->equipment[HOLD];
  694.  
  695.     if (ch->equipment[WIELD] &&
  696.        (ch->equipment[WIELD]->obj_flags.type_flag == ITEM_WEAPON)) {
  697.         wielded = ch->equipment[WIELD];
  698.         switch (wielded->obj_flags.value[3]) {
  699.             case 0  :
  700.             case 1  :
  701.             case 2  : w_type = TYPE_WHIP; break;
  702.             case 3  : w_type = TYPE_SLASH; break;
  703.             case 4  :
  704.             case 5  :
  705.             case 6  : w_type = TYPE_CRUSH; break;
  706.             case 7  : w_type = TYPE_BLUDGEON; break;
  707.             case 8  :
  708.             case 9  :
  709.             case 10 :
  710.             case 11 : w_type = TYPE_PIERCE; break;
  711.  
  712.             default : w_type = TYPE_HIT; break;
  713.         }
  714.     }    else {
  715.         if (IS_NPC(ch) && (ch->specials.attack_type >= TYPE_HIT))
  716.             w_type = ch->specials.attack_type;
  717.         else
  718.             w_type = TYPE_HIT;
  719.     }
  720.  
  721.     /* Calculate the raw armor including magic armor */
  722.     /* The lower AC, the better                      */
  723.  
  724.     if (!IS_NPC(ch))
  725.         calc_thaco  = thaco[GET_CLASS(ch)-1][GET_LEVEL(ch)];
  726.     else
  727.         /* THAC0 for monsters is set in the HitRoll */
  728.         calc_thaco = 20;
  729.  
  730.     calc_thaco -= str_app[STRENGTH_APPLY_INDEX(ch)].tohit;
  731.     calc_thaco -= GET_HITROLL(ch);
  732.  
  733.     diceroll = number(1,20);
  734.  
  735.     victim_ac  = GET_AC(victim)/10;
  736.  
  737.     if (AWAKE(victim))
  738.         victim_ac += dex_app[GET_DEX(victim)].defensive;
  739.  
  740.     victim_ac = MAX(-10, victim_ac);  /* -10 is lowest */
  741.  
  742.     if ((diceroll < 20) && AWAKE(victim) &&
  743.        ((diceroll==1) || ((calc_thaco-diceroll) > victim_ac))) {
  744.         if (type == SKILL_BACKSTAB)
  745.             damage(ch, victim, 0, SKILL_BACKSTAB);
  746.         else
  747.             damage(ch, victim, 0, w_type);
  748.     } else {
  749.  
  750.         dam  = str_app[STRENGTH_APPLY_INDEX(ch)].todam;
  751.         dam += GET_DAMROLL(ch);
  752.  
  753.         if (!wielded) {
  754.             if (IS_NPC(ch))
  755.                 dam += dice(ch->specials.damnodice, ch->specials.damsizedice);
  756.             else
  757.                 dam += number(0,2);  /* Max. 2 dam with bare hands */
  758.         } else {
  759.             dam += dice(wielded->obj_flags.value[1], wielded->obj_flags.value[2]);
  760.         }
  761.  
  762.         if (GET_POS(victim) < POSITION_FIGHTING)
  763.             dam *= 1+(POSITION_FIGHTING-GET_POS(victim))/3;
  764.         /* Position  sitting  x 1.33 */
  765.         /* Position  resting  x 1.66 */
  766.         /* Position  sleeping x 2.00 */
  767.         /* Position  stunned  x 2.33 */
  768.         /* Position  incap    x 2.66 */
  769.         /* Position  mortally x 3.00 */
  770.  
  771.         dam = MAX(1, dam);  /* Not less than 0 damage */
  772.  
  773.         if (type == SKILL_BACKSTAB) {
  774.             dam *= backstab_mult[GET_LEVEL(ch)];
  775.             damage(ch, victim, dam, SKILL_BACKSTAB);
  776.         } else
  777.             damage(ch, victim, dam, w_type);
  778.     }
  779. }
  780.  
  781.  
  782.  
  783. /* control the fights going on */
  784. void perform_violence(void)
  785. {
  786.     struct char_data *ch;
  787.  
  788.     for (ch = combat_list; ch; ch=combat_next_dude)
  789.     {
  790.         combat_next_dude = ch->next_fighting;
  791.         assert(ch->specials.fighting);
  792.  
  793.         if (AWAKE(ch) && (ch->in_room==ch->specials.fighting->in_room)) {
  794.             hit(ch, ch->specials.fighting, TYPE_UNDEFINED);
  795.         } else { /* Not in same room */
  796.             stop_fighting(ch);
  797.         }
  798.     }
  799. }
  800.