[Circle] My combat bug again...

From: WarRat (warrat@erinet.com)
Date: 08/02/96


I'm still having major problems with a cute thiss crash bug that only occurs
while in a player is in combat without a weapon.
I've gone through the messages file, everything looks right for type HIT.

Here's some info on how it looks from runtime:

Player starts fight without a weapon and hits the mob

Mob hits player
Player hits mob

(continue until mob is one hit from being stunned)

Since the mob is hitting first, he should have a hit message on the player,
but there is none...There is never a mob hit message nor a "Mob is stunned
(incap, etc)"  after the player gets the stunning hit.  It just crashes at
this point.

Again, any and all help is greatly appreciatied.

If the player is wielding a weapon it works fine...
I've gone through damage() and skill_message() (attached to bottom of
message with hit() ) several times and can find nothing that I believe would
be causing this.

R-
(who is quickly going bald after pulling his hair out for the past 2 months
trying to figure this this out)

I'm really sorry to be spamming the list with this much code, but I'm at my
wits end and really need help

int skill_message(int dam, struct char_data * ch, struct char_data * vict,
                      int attacktype)
{
  int i, j, nr;
  struct message_type *msg;
  struct obj_data *weap;

  weap = GET_EQ(ch, WEAR_WIELD);

  for (i = 0; i < MAX_MESSAGES; i++) {
    if (fight_messages[i].a_type == attacktype) {
      nr = dice(1, fight_messages[i].number_of_attacks);
      for (j = 1, msg = fight_messages[i].msg; (j < nr) && msg; j++)
     msg = msg->next;

      if (!IS_NPC(vict) && (GET_LEVEL(vict) >= LVL_IMMORT)) {
     act(msg->god_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
     act(msg->god_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT);
     act(msg->god_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
      } else if (dam != 0) {
     if (GET_POS(vict) == POS_DEAD) {
       send_to_char(CCYEL(ch, C_CMP), ch);
       act(msg->die_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
       send_to_char(CCNRM(ch, C_CMP), ch);

       send_to_char(CCRED(vict, C_CMP), vict);
       act(msg->die_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
       send_to_char(CCNRM(vict, C_CMP), vict);

       act(msg->die_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
     } else {
       send_to_char(CCYEL(ch, C_CMP), ch);
       act(msg->hit_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
       send_to_char(CCNRM(ch, C_CMP), ch);

       send_to_char(CCRED(vict, C_CMP), vict);
       act(msg->hit_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
       send_to_char(CCNRM(vict, C_CMP), vict);

       act(msg->hit_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
     }
      } else if (ch != vict) {     /* Dam == 0 */
     send_to_char(CCYEL(ch, C_CMP), ch);
     act(msg->miss_msg.attacker_msg, FALSE, ch, weap, vict, TO_CHAR);
     send_to_char(CCNRM(ch, C_CMP), ch);

     send_to_char(CCRED(vict, C_CMP), vict);
     act(msg->miss_msg.victim_msg, FALSE, ch, weap, vict, TO_VICT | TO_SLEEP);
     send_to_char(CCNRM(vict, C_CMP), vict);

     act(msg->miss_msg.room_msg, FALSE, ch, weap, vict, TO_NOTVICT);
      }
      return 1;
    }
  }
  return 0;
}


void damage(struct char_data * ch, struct char_data * victim, int dam, int
attacktype)
{
  int exp;
  long local_gold = 0;
  char *spl;

  if (GET_POS(victim) <= POS_DEAD) {
    log("SYSERR: Attempt to damage a corpse.");
    return;              /* -je, 7/7/92 */
  }
  /* peaceful rooms */
  if ((ch != victim) && (ROOM_FLAGGED(ch->in_room, ROOM_PEACEFUL))) {
    send_to_char("This room just has such a peaceful, easy feeling...\r\n", ch);
    stop_fighting(ch);
    return;
  }

  if(PLR_FLAGGED(victim, PLR_BLOCKING)) {
    REMOVE_BIT(PLR_FLAGS(victim), PLR_BLOCKING);
    act("$n blocks a blow by $N.", FALSE, victim, 0, ch, TO_ROOM);
    send_to_char("You successfully block the blow.\r\n", victim);
    return;
  }

  if (PLR_FLAGGED(victim, PLR_RIPOST)) {
    REMOVE_BIT(PLR_FLAGS(victim), PLR_RIPOST);
    if(IS_AFFECTED(ch, AFF_SANCTUARY)) 
      dam >>= 1;
    dam = MAX(dam, 0);
    GET_HIT(ch) -= dam;
    act("$n reflects a blow by $N.", FALSE, victim, 0, ch, TO_ROOM);
    send_to_char("You successfully reflect the blow.\r\n", victim);
    update_pos(ch);
    return;
  }

   /* shopkeeper protection */
  if (!ok_damage_shopkeeper(ch, victim))
    return;

  /* You can't damage an immortal! */
  if (!IS_NPC(victim) && (GET_LEVEL(victim) >= LVL_IMMORT))
    dam = 0;

  if (victim != ch) {
    if (GET_POS(ch) > POS_STUNNED) {
      if (!FIGHTING(ch))
        set_fighting(ch, victim);

      if (IS_NPC(ch) && IS_NPC(victim) && victim->master &&
        !number(0, 10) && IS_AFFECTED(victim, AFF_CHARM) &&
        (victim->master->in_room == ch->in_room)) {
      if (FIGHTING(ch))
        stop_fighting(ch);
     hit(ch, victim->master, TYPE_UNDEFINED);
     return;
      }
    }
    if (GET_POS(victim) > POS_STUNNED && !FIGHTING(victim)) {
      set_fighting(victim, ch);
      if (MOB_FLAGGED(victim, MOB_MEMORY) && !IS_NPC(ch) &&
       (GET_LEVEL(ch) < LVL_IMMORT))
     remember(victim, ch);
    }
  }

  if (victim->master == ch)
    stop_follower(victim);

  if (IS_AFFECTED(ch, AFF_INVISIBLE | AFF_HIDE))
    appear(ch);

  if (IS_AFFECTED(victim, AFF_SANCTUARY))
    dam >>= 1;      /* 1/2 damage when sanctuary */

  if (!pk_allowed) {
    check_killer(ch, victim);
    if (PLR_FLAGGED(ch, PLR_KILLER) && (ch != victim))
      dam = 0;
  }

  dam = MAX(dam, 0);
  GET_HIT(victim) -= dam;

  if (ch != victim)
    gain_exp(ch, GET_LEVEL(victim) * dam);

  update_pos(victim);

  if (!IS_WEAPON(attacktype))
     skill_message(dam, ch, victim, attacktype);
   else {
     if (GET_POS(victim) == POS_DEAD || dam == 0) {
       if (!skill_message(dam, ch, victim, attacktype))
         dam_message(dam, ch, victim, attacktype);
     } else
       dam_message(dam, ch, victim, attacktype);
  }

   /* Use send_to_char -- act() doesn't send message if you are DEAD. */
   switch (GET_POS(victim)) {
    case POS_MORTALLYW:
      act("$n is mortally wounded, and will die soon, if not aided.", TRUE,
victim, 0, 0, TO_ROOM);
      send_to_char("You are mortally wounded, and will die soon, if not
aided.\r\n", victim);
      break;
    case POS_INCAP:
      act("$n is incapacitated and will slowly die, if not aided.", TRUE,
victim, 0, 0, TO_ROOM);
      send_to_char("You are incapacitated an will slowly die, if not
aided.\r\n", victim);
      break;
    case POS_STUNNED:
      if (GET_HIT(victim) <= 0) {
        act("$n is stunned, but will probably regain consciousness again.",
TRUE, victim, 0, 0, TO_ROOM);
        send_to_char("You're stunned, but will probably regain consciousness
again.\r\n", victim);
      }
      break;
    case POS_DEAD:
      act("$n is dead!  R.I.P.", FALSE, victim, 0, 0, TO_ROOM);
      send_to_char("You are dead!  Sorry...\r\n", victim);
      break;

   default:               /* >= POSITION SLEEPING */
     if (dam > (GET_MAX_HIT(victim) >> 2))
       act("That really did HURT!", FALSE, victim, 0, 0, TO_CHAR);

     if (GET_HIT(victim) < (GET_MAX_HIT(victim) >> 2)) {
       sprintf(buf2, "%sYou wish that your wounds would stop BLEEDING so
much!%s\r\n",
            CCRED(victim, C_SPR), CCNRM(victim, C_SPR));
       send_to_char(buf2, victim);
       if (IS_NPC(victim) && MOB_FLAGGED(victim, MOB_WIMPY))
         do_flee(victim, "", 0, 0);
     }
     if (!IS_NPC(victim) && GET_WIMP_LEV(victim) && (victim != ch) &&
      GET_HIT(victim) < GET_WIMP_LEV(victim) &&
         GET_CLASS(victim) != CLASS_BERSERKER) {
       send_to_char("You wimp out, and attempt to flee!\r\n", victim);
       do_flee(victim, "", 0, 0);
     }
     break;
  }

  if (!IS_NPC(victim) && !(victim->desc)) {
     do_flee(victim, "", 0, 0);
     if (!FIGHTING(victim)) {
       act("$n is rescued by divine forces.", FALSE, victim, 0, 0, TO_ROOM);
       GET_WAS_IN(victim) = victim->in_room;
       char_from_room(victim);
       char_to_room(victim, 0);
     }
  }
  if (!AWAKE(victim))
    if (FIGHTING(victim))
      stop_fighting(victim);

  if (GET_POS(victim) == POS_DEAD) {
    if (IS_NPC(victim) || victim->desc)
      if (IS_AFFECTED(ch, AFF_GROUP))
        group_gain(ch, victim);
      else {
        exp = MIN(max_exp_gain, GET_EXP(victim));

         /* Calculate level-difference bonus */
        if (IS_NPC(ch))
          exp += MAX(0, (exp * MIN(4, (GET_LEVEL(victim) - GET_LEVEL(ch))))
>> 3);
        else
          exp += MAX(0, (exp * MIN(8, (GET_LEVEL(victim) - GET_LEVEL(ch))))
>> 3);
        exp = MAX(exp, 1);
        if (exp > 1) {
          sprintf(buf2, "You receive %d experience points.\r\n", exp);
          send_to_char(buf2, ch);
        } else
           send_to_char("You receive one lousy experience point.\r\n", ch);
        gain_exp(ch, exp);
        change_alignment(ch, victim);
      }

  if (!IS_NPC(victim)) {
    sprintf(buf2, "%s killed by %s at %s", GET_NAME(victim), GET_NAME(ch),
      world[victim->in_room].name);
    mudlog(buf2, BRF, LVL_IMMORT, TRUE);
    if (MOB_FLAGGED(ch, MOB_MEMORY))
       forget(ch, victim);
  }
  if (IS_NPC(victim)) {
     local_gold = GET_GOLD(victim);
     sprintf(spl, "split %ld", (long) local_gold);
  }
  die(victim);
  if (PRF_FLAGGED(ch, PRF_AUTOSPLIT)) {
    ACMD(do_get);
    do_get(ch, "gold corpse", 0, 0);
     if (IS_AFFECTED(ch, AFF_GROUP) && local_gold > 0) {
       command_interpreter(ch, spl);
     }
  }
  if (IS_NPC(victim) && !IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTOLOOT)) {
    ACMD(do_get);
    do_get(ch, "all corpse", 0, 0);
  }   
 } 
} 

void hit(struct char_data * ch, struct char_data * victim, int type)
 {
   struct obj_data *wielded = GET_EQ(ch, WEAR_WIELD);
   int w_type, victim_ac, calc_thaco, dam, diceroll;

   extern int thaco[NUM_CLASSES][LVL_IMPL+1];
   extern struct str_app_type str_app[];
   extern struct dex_app_type dex_app[];

   int backstab_mult(int level);

   if (ch->in_room != victim->in_room) {
     if (FIGHTING(ch) == victim)
       stop_fighting(ch);
     return;
   }

   if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON)
     w_type = GET_OBJ_VAL(wielded, 3) + TYPE_HIT;
   else {
     if (IS_NPC(ch) && (ch->mob_specials.attack_type != 0))
       w_type = ch->mob_specials.attack_type + TYPE_HIT;
     else
       w_type = TYPE_HIT;
   }

   /* Calculate the raw armor including magic armor.  Lower AC is better. */

   if (!IS_NPC(ch))
     calc_thaco = thaco[(int) GET_CLASS(ch)][(int) GET_LEVEL(ch)];
   else         /* THAC0 for monsters is set in the HitRoll */
     calc_thaco = 20;

   calc_thaco -= str_app[STRENGTH_APPLY_INDEX(ch)].tohit;
   calc_thaco -= GET_HITROLL(ch);
   calc_thaco -= (int) ((GET_INT(ch) - 13) / 1.5); /* Intelligence helps! */
   calc_thaco -= (int) ((GET_WIS(ch) - 13) / 1.5); /* So does wisdom */
   calc_thaco += GET_COND(ch, DRUNK);              /* being drunk don't */
   diceroll = number(1, 20);

   victim_ac = GET_AC(victim) / 10;

   if (AWAKE(victim))
     victim_ac += dex_app[GET_DEX(victim)].defensive;

   victim_ac = MAX(-10, victim_ac); /* -10 is lowest */

   /* decide whether this is a hit or a miss */
   if ((((diceroll < 20) && AWAKE(victim)) &&
        ((diceroll == 1) || ((calc_thaco - diceroll) > victim_ac)))) {
     if (type == SKILL_BACKSTAB)
       damage(ch, victim, 0, SKILL_BACKSTAB);
     else if (type == SKILL_CIRCLE)
       damage(ch, victim, 0, SKILL_CIRCLE);
     else
       damage(ch, victim, 0, w_type);
     } else if (IS_AFFECTED(victim, AFF_MIRROR_IMAGE) && (number(1, 100) <
26)) {
       act("You destroy one of $Ns false images.", FALSE, ch, 0, victim,
TO_CHAR);
       act("One of $Ns false images takes the blow from $n.", FALSE, ch, 0,
victim, TO_NOTVICT);
       act("How lucky, $n hits one of your false images instead of you.",
FALSE, ch, 0, victim, TO_VICT);
       return;
     } else if (!IS_NPC(ch) && (int)(GET_SKILL(victim, SKILL_DODGE)*15/100)
> number(1, 100)) { 
       act("$N dodges your attack.", FALSE, ch, 0, victim, TO_CHAR);
       act("$N dodges out of $n's way.", FALSE, ch, 0, victim, TO_NOTVICT);
       act("You dodge an attack by $n.", FALSE, ch, 0, victim, TO_VICT);
       return;
     } else {
     /* okay, the guy has been hit.  now calculate damage. */
     dam = str_app[STRENGTH_APPLY_INDEX(ch)].todam;
     dam += GET_DAMROLL(ch);

     if (wielded)
       dam += dice(GET_OBJ_VAL(wielded, 1), GET_OBJ_VAL(wielded, 2));
     else {
       if (IS_NPC(ch)) {
      dam += dice(ch->mob_specials.damnodice, ch->mob_specials.damsizedice);
       } else if (GET_CLASS(ch) == CLASS_MONK) {
            dam += dice(MIN(1, GET_LEVEL(ch)/3), 2);
           } else {
           dam += number(1, 2);     /* Max. 2 dam with bare hands */
       }
     }

     if (GET_POS(victim) < POS_FIGHTING)
       dam *= 1 + (POS_FIGHTING - GET_POS(victim)) / 3;
     /* Position  sitting  x 1.33 */
     /* Position  resting  x 1.66 */
     /* Position  sleeping x 2.00 */
     /* Position  stunned  x 2.33 */
     /* Position  incap    x 2.66 */
     /* Position  mortally x 3.00 */

     dam = MAX(1, dam);        /* at least 1 hp damage min per hit */

     if (type == SKILL_BACKSTAB) {
       dam *= backstab_mult(GET_LEVEL(ch));
       damage(ch, victim, dam, SKILL_BACKSTAB);
     } else if (type == SKILL_CIRCLE) {
       dam = (dam * backstab_mult(GET_LEVEL(ch)) * 2 / 3);
       damage(ch, victim, dam, SKILL_CIRCLE);
     } else
       damage(ch, victim, dam, w_type);
   }
 }

  ^"^'^"^"^'^"^'^"^"^"#
                            #  \O/
10,000 lemmings#    |
can't all be wrong#   / \    
                            #  .. .     warrat@erinet.com
                            #  . . .
                            # #..# .
                               ^^^^^^^^^^^^^^^^^^^^

       Happy shall he be, that taketh and dasheth thy little ones 
       against the stones.
                                  Psalms 137:9 



+-----------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
|   http://cspo.queensu.ca/~fletcher/Circle/list_faq.html   |
+-----------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/07/00 PST