Is there any reason that mobs AREN'T using their weapons?

Login to reply  Page: « < 1 of 1 > »
09 Jul 2010 - 17:112819
Is there any reason that mobs AREN'T using their weapons?
Is there a particular reason why mobs aren't using their weapons as mentioned here? In my MUD I have them using both wielded, and if they have dual-wield skill, held weapons. Via the do_hit function in fight.c

Works fine, and it's much more realistic.

I also have mobs casting spells assigned to them in the enhanced mobiles portion of the mob files during combat too. Without spec_procs, and they must actually "know" the spell.

My perform_violence() with multiple attacks, dual wield, weapon spells, and mob spells and mob skills:
(Yes I realize that many people just do mob spells via DG Scripts... however the way I've done them they actually make the mob use mana, which is set per mob in my MUD, plus they're very easy to set from OLC)

/* control the fights going on.  Called every 2 seconds from comm.c. */
void perform_violence(void)
{
  struct char_data *ch;
  struct obj_data *wielded, *held;
  int i;
  int spell_num[50], num_spells = 0, to_cast;


  for (ch = combat_list; ch; ch = next_combat_list) {
    next_combat_list = ch->next_fighting;

    if (FIGHTING(ch) == NULL || IN_ROOM(ch) != IN_ROOM(FIGHTING(ch))) {
      stop_fighting(ch);
      continue;
    }

	if ((IS_NPC(FIGHTING(ch)) && MOB_FLAGGED(FIGHTING(ch), MOB_NOKILL)) ||
		(IS_NPC(ch) && MOB_FLAGGED(ch, MOB_NOKILL))) {
			if (!IS_NPC(ch))
				send_to_char(ch, "Dunno how you were fighting them... but this has to stop!\r\n");
			stop_fighting(ch);
			continue;
	}

    if (IS_NPC(ch)) {
      if (GET_MOB_WAIT(ch) > 0) {
		  GET_MOB_WAIT(ch) -= PULSE_VIOLENCE;
		  if (TMP_FLAGGED(ch, TMP_BASHED | TMP_SPELL_STUN)) {
			  send_to_char(ch, "You stagger around stunned!!\r\n");
			  continue;
		  }
      } else {
      GET_MOB_WAIT(ch) = 0;
      if (GET_POS(ch) < POS_FIGHTING)
		  GET_POS(ch) = POS_FIGHTING;
        if (TMP_FLAGGED(ch, TMP_BASHED | TMP_SPELL_STUN)) {
          REMOVE_BIT(TMP_FLAGS(ch), TMP_BASHED);
          REMOVE_BIT(TMP_FLAGS(ch), TMP_SPELL_STUN);
          act("$n regains $s senses!", TRUE, ch, 0, 0, TO_ROOM);
        }
	  }
    }

    if (TMP_FLAGGED(ch, TMP_BASHED) ||  TMP_FLAGGED(ch, TMP_SPELL_STUN)) {
      send_to_char(ch, "You stagger around stunned!!\r\n");
      continue;
    }

	if (GET_POS(ch) < POS_FIGHTING) {
      send_to_char(ch, "You can't fight while sitting!!\r\n");
      continue;
    }

	for (k = ch->followers; k; k=k->next) {
      if (PRF_FLAGGED(k->follower, PRF_AUTOASSIST) &&
        (k->follower->in_room == ch->in_room))
       do_assist(k->follower, GET_NAME(ch), 0, 0);
    }

	hit(ch, FIGHTING(ch), TYPE_WEAPON);
	if ((GET_EQ(ch, WEAR_WIELD) !=NULL && GET_OBJ_TYPE(GET_EQ(ch, WEAR_WIELD)) == ITEM_WEAPON) ||  GET_SKILL(ch, SKILL_UNARMED_COMBAT)) {
		if (rand_number(0, 100) <= GET_SKILL(ch, SKILL_SECOND_ATK))
			hit(ch, FIGHTING(ch), TYPE_WEAPON);
		if (rand_number(0, 100) <= GET_SKILL(ch, SKILL_THIRD_ATK))
			hit(ch, FIGHTING(ch), TYPE_WEAPON);
		if (rand_number(0, 100) <= GET_SKILL(ch, SKILL_FOURTH_ATK))
			hit(ch, FIGHTING(ch), TYPE_WEAPON);
	}
	if ((GET_EQ(ch, WEAR_HOLD) != NULL && GET_OBJ_TYPE(GET_EQ(ch, WEAR_HOLD)) == ITEM_WEAPON) || GET_SKILL(ch, SKILL_UNARMED_COMBAT)) {
		if (rand_number(0, 100) <= GET_SKILL(ch, SKILL_DUAL_WIELD))
			hit(ch, FIGHTING(ch), TYPE_DUAL);
		if (rand_number(0, 100) <= GET_SKILL(ch, SKILL_DUAL_WIELD) && rand_number(0, 100) <= GET_SKILL(ch, SKILL_SECOND_ATK))
			hit(ch, FIGHTING(ch), TYPE_DUAL);
		if (rand_number(0, 100) <= GET_SKILL(ch, SKILL_DUAL_WIELD) && rand_number(0, 100) <= GET_SKILL(ch, SKILL_THIRD_ATK))
			hit(ch, FIGHTING(ch), TYPE_DUAL);
		if (rand_number(0, 100) <= GET_SKILL(ch, SKILL_DUAL_WIELD) && rand_number(0, 100) <= GET_SKILL(ch, SKILL_FOURTH_ATK))
			hit(ch, FIGHTING(ch), TYPE_DUAL);
	}
	if (GET_EQ(ch, WEAR_WIELD) != NULL) {
		wielded = GET_EQ(ch, WEAR_WIELD);
       if (wielded->obj_spell.spellnum > 0) {
          if (dice(0,100) <= (wielded->obj_spell.percent)){
			  call_magic(ch, FIGHTING(ch), NULL,
			  wielded->obj_spell.spellnum,
			  GET_LEVEL(ch), CAST_SPELL);
          }
       }
    }
	if (GET_EQ(ch, WEAR_HOLD) != NULL && GET_OBJ_TYPE(GET_EQ(ch, WEAR_HOLD)) == ITEM_WEAPON && GET_SKILL(ch, SKILL_DUAL_WIELD)) {
		held = GET_EQ(ch, WEAR_HOLD);
		if (held != NULL) {
			if (held->obj_spell.spellnum > 0) {
				if (dice(0, 100) <= (held->obj_spell.percent)) {
					call_magic(ch, FIGHTING(ch), NULL,
					held->obj_spell.spellnum,
					GET_LEVEL(ch), CAST_SPELL);
				}
			}
		}
	}
	if(IS_NPC(ch) && ch->mob_specials.has_spells == TRUE && !(GET_MOB_WAIT(ch) > 0)) {
		for (i = 1; i <= MAX_SKILLS; i++) {
			if (GET_SKILL(ch, i) > 0 && i <= 1900) {
				num_spells++;
				spell_num[num_spells] = i;
			}
		}
		to_cast = rand_number(1, num_spells);
		if (spell_num[to_cast] <= MAX_SPELLS) {
			if (rand_number(0, 100) <= GET_SKILL(ch, spell_num[to_cast])) {
				char buf[255];
				sprintf(buf, " '%s'", spell_info[spell_num[to_cast]].name);
				if(spell_info[spell_num[to_cast]].violent)
					do_cast(ch, buf, find_command("cast"), 0);
			}
		} else {
			perform_mob_skill(ch, FIGHTING(ch), spell_num[to_cast]);
		}
    }
	if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_AUTODIAG) && FIGHTING(ch) && GET_POS(FIGHTING(ch)) != POS_DEAD)
       diag_char_to_char(FIGHTING(ch), ch);

    if (MOB_FLAGGED(ch, MOB_SPEC) && GET_MOB_SPEC(ch) && !MOB_FLAGGED(ch, MOB_NOTDEADYET)) {
      char actbuf[MAX_INPUT_LENGTH] = "";
      (GET_MOB_SPEC(ch)) (ch, ch, 0, actbuf);
    }
  }
}

If anyone is interested in the full code for any of that, let me know. Some is based on other people's work off the CircleMUD ftp site, but some is my own ideas too... like how I did mob spells and skills.

And here is my hit() function so you can see I don't stop mobs from using weapons once it gets here either:
void hit(struct char_data *ch, struct char_data *victim, int type)
{
  struct obj_data *wielded, *held;
  int w_type, victim_ac, calc_thaco, dam, diceroll;

  wielded = GET_EQ(ch, WEAR_WIELD);
  held = GET_EQ(ch, WEAR_HOLD);
  /* check if the character has a fight trigger */
  fight_mtrigger(ch);

  /* Do some sanity checking, in case someone flees, etc. */
  if (IN_ROOM(ch) != IN_ROOM(victim)) {
    if (FIGHTING(ch) && FIGHTING(ch) == victim)
      stop_fighting(ch);
    return;
  }

  /* Find the weapon type (for display purposes only) */
  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;
  }

  if (type == TYPE_DUAL) {
	  /* Find the weapon type (for display purposes only) */
	  if (held && GET_OBJ_TYPE(held) == ITEM_WEAPON)
		  w_type = GET_OBJ_VAL(held, 3) + TYPE_HIT;
  }

  /* Calculate chance of hit. Lower THAC0 is better for attacker. */
  calc_thaco = compute_thaco(ch, victim);

  /* Calculate the raw armor including magic armor.  Lower AC is better for defender. */
  victim_ac = compute_armor_class(victim) / 10;

  /* roll the die and take your chances... */
  diceroll = rand_number(1, 100);

  /*
   * Decide whether this is a hit or a miss.
   *
   *  Victim asleep = hit, otherwise:
   *     1   = Automatic miss.
   *   2..19 = Checked vs. AC.
   *    20   = Automatic hit.
   */
  if (diceroll >= 20 || !AWAKE(victim))
    dam = TRUE;
  else if (diceroll == 1)
    dam = FALSE;
  else
    dam = (calc_thaco - diceroll <= victim_ac);

  if (!dam)
    /* the attacker missed the victim */
    damage(ch, victim, 0, type == SKILL_BACKSTAB ? SKILL_BACKSTAB : w_type);
  else {
    /* okay, we know the guy has been hit.  now calculate damage. */

    /* Start with the damage bonuses: the damroll and strength apply */
    dam = str_app[STRENGTH_APPLY_INDEX(ch)].todam;
    dam += GET_DAMROLL(ch);

    /* Maybe holding arrow? */
    if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON && type == TYPE_WEAPON) {
      /* Add weapon-based damage if a weapon is being wielded */
      dam += dice(GET_OBJ_VAL(wielded, 1), GET_OBJ_VAL(wielded, 2));
	} else if (held && GET_OBJ_TYPE(held) == ITEM_WEAPON && type == TYPE_DUAL) {
		/* Add weapon-based damage if a weapon is being held */
		dam += dice(GET_OBJ_VAL(held, 1), GET_OBJ_VAL(held, 2));
    } else {
      /* If no weapon, add bare hand damage instead */
      if (IS_NPC(ch))
		  dam += dice(ch->mob_specials.damnodice, ch->mob_specials.damsizedice);
      else
		  dam += rand_number(0, 2);	/* Max 2 bare hand damage for players */
    }

    /*
     * Include a damage multiplier if victim isn't ready to fight:
     *
     * Position sitting  1.33 x normal
     * Position resting  1.66 x normal
     * Position sleeping 2.00 x normal
     * Position stunned  2.33 x normal
     * Position incap    2.66 x normal
     * Position mortally 3.00 x normal
     *
     * Note, this is a hack because it depends on the particular
     * values of the POSITION_XXX constants.
     */
    if (GET_POS(victim) < POS_FIGHTING)
      dam *= 1 + (POS_FIGHTING - GET_POS(victim)) / 3;

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

    if (type == SKILL_BACKSTAB)
      damage(ch, victim, dam * backstab_mult(GET_LEVEL(ch)), SKILL_BACKSTAB);
    else
      damage(ch, victim, dam, w_type);
  }

  /* check if the victim has a hitprcnt trigger */
  hitprcnt_mtrigger(victim);
}


__________________
Owner/Coder/Head Admin
Caer Dubrin

Last edited by ralgith (09 Jul 2010 - 17:13) Reason: Messed up the code tags
09 Jul 2010 - 19:372822
One thing to watch for is that some mobiles might do more BHD than they do with a weapon. I added fumbles to my code and noticed that sometimes damage went up rather than down when they dropped or broke a weapon. I fixed it by using BHD if greater than the weapon damage.


09 Jul 2010 - 20:592823
Ahhh, good thing to point out... not an issue for me
While that is an issue if you let your builders get away with it, I don't. No mob should ever be wielding a weapon with LOWER damage output than their BHA. If they are, it isn't an appropriate weapon for their level and power. At least that is what I enforce on my own MUD. Also, on my MUD, the majority of the damage comes from a mob's damroll anyways. Due to the way my MUD is set up it isn't amiss to see high end mobs having damrolls in excess of 10k. One has a damroll of 75k, and one is planned (one of my own zones) for a damroll of 200k.

Now, you may wonder why so high? The 200k damroll mob is meant to be fought from vehicles, which only take damage at 1% the rate a player does. However, Vehicles arent implemented yet, so neither is that mob :)


__________________
Owner/Coder/Head Admin
Caer Dubrin
10 Jul 2010 - 03:342825
any idea

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



10 Jul 2010 - 14:062826
Quote drefs:
any idea

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




If that's supposed to say "an idea" instead of "any idea" I get it ;)
Otherwise I'm confused lol.

There are a lot of places where I could streamline the code like that, but I wont be doing it until I get everything new implemented. Then I'll be returning to my older less experienced code like this and streamlining it. However, since you brought it up and pointed it out... I suppose I could do it now :)

It also has to be done for the weapon hit message type farther down too.


__________________
Owner/Coder/Head Admin
Caer Dubrin
10 Jul 2010 - 14:302827
Also did that in a few places in perform violence too, for example the weapon spell casting.


__________________
Owner/Coder/Head Admin
Caer Dubrin
Login to reply  Page: « < 1 of 1 > »