LONG: Mob skills & Guildmasters

From: Ryan A.J. Biggs (ae744@freenet.toronto.on.ca)
Date: 07/09/96


I am working on a major overhaul MUD based on Circle bpl 11, and I have a 
few questions.  Firstly, I am lkooking into  making it so that mobs can 
have skills (ie. A mob that can dodge or cast spells, or steal...without 
spec_procs for individual commands) and that use this skill definition to 
determine what level they can teach a skill up to if they are a 
guildmaster.  For example, a guildmaster in midgaard has fireball at 
50%.  He can only teach a PC up to 50%, then they must seek out a better 
master.  I am thinking of making this in mob as a sort of command like in 
objects for affects.  I got it working, BUT, because all mobs use the 
same skill settings (damn them pointers) all mobs will have the same 
lkevel of skills.  (A fido with 85% dodge?  I dunnot think so!)  Is there 
a way to give only certain mobs their own skills, and the rest can go to 
pointer heck.  (I'm still new in C, so be kind to a pointer fearing 
newbie coder)

Also, does anyone want SeeFu's weather code?  It was based on the weather 
code from NoMUD, and I have added a lot of interesting things (lightning 
and tornadoes that can hurt or kill, heat waves that make players need 
more water, severe storms that make more movement needed)  I am about to 
completely do an overhaul on the weather system to make it VERY detailed 
(wind speed/direction, humidty, temperature, seasons) and I don't mind 
giving out the old code.

Finally, I got LostLands missile weapon code and implemented it.  (A big 
hit I must say) and then I made a few alterations to have it so that you 
could aim it so that the weapon had to go a minimum distance before it 
would even check to see if it hits (like a torpedo, needs a distance to 
'arm' itself)  It worked great for missile hurling weapons (bows, 
crossbows, my arm mounted sidewinder missile launcher :) but thrown 
weapons stopped hitting (stuff like spears, boomerangs, etc.)  Here is 
the code I have.

(in act.offensive.c)
static char *fire_msg[] = {
  "You are not holding something to throw.\r\n",
  "You must wield the correct weapon.\r\n",
  "You are not holding the right missile type for that weapon.\r\n",
  "You must specify a correct direction.\r\n",
  "You pull back your arm and throw $p.",
  "You take aim and fire $p.",
  "With herculean might, $n throws $p.",
  "With skill equal to that of William Tell, $n fires $p.",
  "Losing it's momentum, $p falls to the ground.",
  "Miraculously, $p returns to $n.",
  "Miraculously, $p returns to you."
  "\n"
};

extern char *dirs[];

void fire_in_direction(struct char_data *ch, struct obj_data *obj, int 
look_type, int distance, int dist_set);

ACMD(do_fire)
{
  static char arg2[MAX_INPUT_LENGTH];
  struct obj_data * obj = GET_EQ(ch, WEAR_WIELD);
  int look_type, distance;
  int dist_set;

  half_chop(argument, arg, arg2);

  if (!*arg || (look_type = search_block(arg, dirs, FALSE)) < 0) {
    send_to_char(fire_msg[3], ch);
    return;
  }

  if (ROOM_FLAGGED(ch->in_room, ROOM_PEACEFUL)) {
    send_to_char("Divine intervention prevents you from doing that.\r\n", 
ch);
    return;
  }
  dist_set = 0;

  if (subcmd == 1) {
    obj = GET_EQ(ch, WEAR_DUALWIELD);
    if (!obj && !GET_EQ(ch, WEAR_WIELD)) {
      if (!GET_EQ(ch, WEAR_HOLD)) {
        send_to_char(fire_msg[0], ch);
        return;
      } else
        obj = unequip_char(ch, WEAR_HOLD);
    } else if (!obj) {
      obj = unequip_char(ch, WEAR_WIELD);
    } else {
      obj = unequip_char(ch, WEAR_DUALWIELD);
    }
    if (GET_OBJ_TYPE(obj) == ITEM_MISSILE)
      distance = 2;
    else
      distance = 1;
  } else {
    if (!obj || GET_OBJ_TYPE(obj) != ITEM_FIREWEAPON) {
      send_to_char(fire_msg[1], ch);
      return;
    }
    if (!GET_EQ(ch, WEAR_LOAD) || GET_OBJ_TYPE(GET_EQ(ch, WEAR_LOAD)) != 
ITEM_MISSILE ||
        GET_OBJ_VAL(obj, 3) != GET_OBJ_VAL(GET_EQ(ch, WEAR_LOAD), 3)) {
      send_to_char(fire_msg[2], ch);
      return;
    }
    obj = unequip_char(ch, WEAR_LOAD);
    distance = GET_OBJ_VAL(obj, 0);
    if (*arg2) {
      dist_set = MAX(1, MIN(atoi(arg2), distance));
      dist_set = MIN(dist_set, 10);
    }
    act(fire_msg[3 + subcmd], FALSE, ch, obj, 0, TO_CHAR);
    act(fire_msg[5 + subcmd], FALSE, ch, obj, 0, TO_ROOM);
    fire_in_direction(ch, obj, look_type, distance, dist_set);
    WAIT_STATE(ch, PULSE_VIOLENCE * 1); 
  }
}
  bool range_hit(struct char_data *ch, struct char_data * victim, struct 
obj_data *obj);

  bool fire_at_char(struct char_data *ch, struct char_data * list, struct 
obj_data * obj, int dir, bool do_hit);

  void fire_in_direction(struct char_data *ch, struct obj_data *obj, int 
dir, int distance, int dist_set)
  {
    int temp_room = ch->in_room;
    struct char_data *vict;
    bool contin = TRUE;

    while (contin && EXITN(temp_room, dir) && (distance-- > 0) &&
        !IS_SET(EXITN(temp_room, dir)->exit_info, EX_CLOSED)) {
      temp_room = EXITN(temp_room, dir)->to_room;
      if (dist_set-- < 2)
        contin = fire_at_char(ch, world[temp_room].people, obj, dir, TRUE);
      else
        contin = fire_at_char(ch, world[temp_room].people, obj, dir, 
FALSE);   
    }
    if (IS_OBJ_STAT(obj, ITEM_RETURNING)) {
      act(fire_msg[10], FALSE, ch, obj, 0, TO_CHAR);
      act(fire_msg[9], FALSE, ch, obj, 0, TO_ROOM);
      obj_to_char(obj, ch);
    } else {
      obj_to_room(obj, temp_room);
      if ((vict = world[temp_room].people)) {
        act(fire_msg[8], FALSE, vict, obj, 0, TO_CHAR);
        act(fire_msg[8], FALSE, vict, obj, 0, TO_ROOM);
      }
    }
/*  WAIT_STATE(ch, PULSE_VIOLENCE * 4); */
}


(in fight.c)
bool range_hit(struct char_data *ch, struct char_data * victim, struct 
obj_data *obj)
{
  int w_type = 315, victim_ac, calc_thaco, dam = 0, diceroll;
  extern int thaco[NUM_CLASSES][LVL_IMPL+1];
  extern struct str_app_type str_app[];
  extern struct dex_app_type dex_app[];

  if (!IS_NPC(ch))
    calc_thaco = thaco[(int) GET_CLASS(ch)][(int) GET_LEVEL(ch)];
  else
    calc_thaco = 20;

  calc_thaco -= dex_app[GET_DEX(ch)].miss_att;
  calc_thaco -= GET_HITROLL(ch);
  calc_thaco -= (int) ((GET_INT(ch) - 13) / 1.5);
  calc_thaco -= (int) ((GET_WIS(ch) - 13) / 1.5);
  diceroll = number(1, 20);

  victim_ac = GET_AC(victim) / 10;

  if (AWAKE(victim))
    victim_ac += dex_app[GET_DEX(victim)].defensive;
  if (GET_POS(victim) == POS_SITTING)
    victim_ac -= 1;
  if (GET_POS(victim) <= POS_RESTING)
    victim_ac -= 2;
  victim_ac = MAX(-10, victim_ac);

  if ((((diceroll < 20) && AWAKE(victim)) &
       ((diceroll == 1) || ((calc_thaco - diceroll) > victim_ac)))) {
    return FALSE;
  } else {
    dam = str_app[STRENGTH_APPLY_INDEX(ch)].todam;
    if (GET_OBJ_TYPE(obj) == ITEM_MISSILE) {
      dam += GET_DAMROLL(ch);
      dam += dice(GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 2));
    }
    if (GET_OBJ_TYPE(obj) == ITEM_WEAPON)
      dam += (GET_OBJ_VAL(obj, 0) + dice(GET_OBJ_VAL(obj, 1), 
GET_OBJ_VAL(obj, 2)) /2);
    else
      dam += number(0, (GET_OBJ_WEIGHT(obj) / 5));
    dam = MAX(1, dam);
    damage(ch, victim, dam, w_type);
    return TRUE;
  }
  return FALSE;
}

const char *opp_dir[] = {
  "south",
  "west",
  "north",
  "east",
  "area below you",
  "area above you",
  "\n"
};

bool fire_at_char(struct char_data *ch, struct char_data * list, struct 
obj_data * obj, int dir, bool do_hit) {
  struct char_data *vict = list;
  char msgbuf[256];

  while (vict) {
    sprintf(msgbuf, "$p just flew in from %s.", opp_dir[dir]);
    act(msgbuf, FALSE, vict, obj, 0, TO_CHAR);
    if (do_hit) {
      if (range_hit(ch, vict, obj)) {
        if (vict) {
          if (IS_NPC(vict) && !IS_NPC(ch) && GET_POS(ch) > POS_STUNNED) {
            SET_BIT(MOB_FLAGS(vict), MOB_MEMORY);
            remember(vict, ch);
            HUNTING(vict) = ch;
          }
        }
        return FALSE;
      }
    }
    send_to_char("It flies past you harmlessly.\r\n", vict);
    vict = vict->next_in_room;
  }
  return TRUE;
}



(end of snippet)

Can anyone help me find my bugs.

------------------------------------------------------------------
Ryan A.J. Biggs    email-ae744@freenet.toronto.on.ca
Doppleganger, Charon the Boatman and member of Dieties Anonymous
Owner of a 100% organic wibble and Plasma lamp, and rubber chicken
Keeper of the sacred butcher knife and the Cloak of Shadows
Compiler of the Net.Psionics.Handbook
------------------------------------------------------------------



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