NPC Classes and Races
Documentation Posted Saturday, March 13th @ 11:36:59 PM, by George Greer.
"John Hines" updated his NPC class and race document a bit. Hit the link below to read it.
This is intended to be used not as a direct snippet but as a guideline
for adding npc class and race to a CircleMUD. I am using CircleMUD 3.0
bpl 14 along with OLC+ 2.1a and DG Scripts pl 6. If you do not use any
form of OLC more than likely you can ignore most of this document.
To use this document as a guide you MUST have allready implemented races
and classes for players on your MUD. I wont be held responsible for any 
screw up to your MUD. Do these changes on a COPY of your mud. Also as 
a referral tool you can follow one of the many Race and Class documents 
available on the CircleMUD snippet sites.

WARNING: YOU MUST FOLLOW THE DIRECTIONS CAREFULLY. THIS CHANGE OF CODE
         WILL ALTER THE FORMAT OF MOBILE FILES!

While we cannot be responsible for any damage done to your code
we will however offer some help if you are in need. This document is 
very easy to follow and you really shouldn't have problems. If you
do, send email to John Hines (jahweb@grnco.net) or Julian Buckley 
(caniffe@cyberdude.com). We will be happy to help.


open medit.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In medit.c around line 49ish look for:

extern const char *position_types[];
extern const char *genders[];
extern int top_shop;
extern struct shop_data *shop_index;
extern struct descriptor_data *descriptor_list;

right below
extern const char *genders[];
add in:
extern const char *class_types[];
extern const char *race_types[];

then move down to about line 93 and look for:
void medit_disp_attack_types(struct descriptor_data *d);

below it add in
void medit_disp_class(struct descriptor_data *d);
void medit_disp_race(struct descriptor_data *d); 

go down to about line 522 where the medit menu functions are displayed
it should look like this:

                        "%ld %ld %d E\n"
                        "%d %d %d %dd%d+%d %dd%d+%d\n"
                        "%d %d\n"
                        "%d %d %d\n",

change the last line in this to add in the new information for the 
mob files. It should look like this:

                        "%ld %ld %d E\n"
                        "%d %d %d %dd%d+%d %dd%d+%d\n"
                        "%d %d\n"
                        "%d %d %d %d %d\n",

now a little lower in the same area are the definitors if you will.
(what all those little %d's mean :) )

         GET_AC(mob) / 10, GET_HIT(mob), GET_MANA(mob), GET_MOVE(mob),
              GET_NDD(mob), GET_SDD(mob), GET_DAMROLL(mob), GET_GOLD(mob),
              GET_EXP(mob), GET_POS(mob), GET_DEFAULT_POS(mob), GET_SEX(mob));

after GET_SEX(mob) add in the new definitions for race and class and 
make it look like so:

         GET_AC(mob) / 10, GET_HIT(mob), GET_MANA(mob), GET_MOVE(mob),
              GET_NDD(mob), GET_SDD(mob), GET_DAMROLL(mob), GET_GOLD(mob),
              GET_EXP(mob), GET_POS(mob), GET_DEFAULT_POS(mob), GET_SEX(mob),
              GET_CLASS(mob), GET_RACE(mob));

from here move down to about line 702 and look for a statement
void medit_disp_mprog_types
below it add in the 2 following statements:

void medit_disp_class(struct descriptor_data *d)
{
  int i;
      
  get_char_cols(d->character);
    
#if defined(CLEAR_SCREEN)
  send_to_char("^[[H^[[J", d->character);
#endif
  for (i = 0; i < NUM_CLASSES; i++) {
    sprintf(buf, "%s%2d%s) %s\r\n", grn, i, nrm, class_types[i]);
    send_to_char(buf, d->character);
  }      
  send_to_char("Enter new Class : ", d->character);
}
/*------------------------------------------------------------------*/
void medit_disp_race(struct descriptor_data *d)
{      
  int i;
        
  get_char_cols(d->character);
  
#if defined(CLEAR_SCREEN)
  send_to_char("^[[H^[[J", d->character);
#endif
  for (i = 0; i < NUM_RACES; i++) { 
    sprintf(buf, "%s%2d%s) %s\r\n", grn, i, nrm, race_types[i]);
    send_to_char(buf, d->character);
  }
  send_to_char("Enter new Race : ", d->character);
}

now jump down to line 890 in the main menu display and look for
          "%sJ%s) Default   : %s%s\r\n"
          "%sK%s) Attack    : %s%s\r\n"
          "%sL%s) NPC Flags : %s%s\r\n"
          "%sM%s) AFF Flags : %s%s\r\n"
just below these lines add this:
          "%sO%s) NPC Class : %s%s\r\n"
          "%sR%s) NPC Race  : %s%s\r\n"

skip down to line 903ish and add in definitions for the above:
          grn, nrm, yel, position_types[(int)GET_POS(mob)],
          grn, nrm, yel, position_types[(int)GET_DEFAULT_POS(mob)],
          grn, nrm, yel, attack_hit_text[GET_ATTACK(mob)].singular,
          grn, nrm, cyn, buf1,
          grn, nrm, cyn, buf2,

add in this:
          grn, nrm, cyn, class_types[(int)GET_CLASS(mob)],
          grn, nrm, cyn, race_types[(int)GET_RACE(mob)],

move down around line 1077 and look for
    case 'm':
    case 'M':
      OLC_MODE(d) = MEDIT_AFF_FLAGS;
      medit_disp_aff_flags(d);
      return;

below it add in this:
    case 'o':
    case 'O':
      OLC_MODE(d) = MEDIT_CLASS;
      medit_disp_class(d);
      return;
    case 'r':
    case 'R':
      OLC_MODE(d) = MEDIT_RACE;
      medit_disp_race(d);
      return;

now down around line 1300 look for
      
  case MEDIT_SEX:
    GET_SEX(OLC_MOB(d)) = MAX(0, MIN(NUM_GENDERS - 1, atoi(arg)));
    break;   

just below this add in:
    
  case MEDIT_CLASS:
    GET_CLASS(OLC_MOB(d)) = MAX(0, MIN(NUM_CLASSES - 1, 
atoi(arg)));
    break;   
    
  case MEDIT_RACE:
    GET_RACE(OLC_MOB(d)) = MAX(0, MIN(NUM_RACES - 1, atoi(arg)));
    break;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
now close medit.c and open up db.c:
      down around line 1025 there is a statement that looks like this:

  if (sscanf(line, " %d %d %d ", t, t + 1, t + 2) != 3) {
    log("SYSERR: Format error in last line of mob #%d\n"
        "...expecting line of form '# # #'", nr);
    exit(1);
  }

  mob_proto[i].char_specials.position = t[0];
  mob_proto[i].mob_specials.default_pos = t[1];
  mob_proto[i].player.sex = t[2];

  mob_proto[i].player.chclass = 0;
  mob_proto[i].player.weight = 200;
  mob_proto[i].player.height = 198;

take note of all of the above:
first change the line if(sscanf(line, ladedede
to this:

  if (sscanf(line, " %d %d %d %d %d ", t, t + 1, t + 2, t + 3, t + 4) < 3) {
    log("SYSERR: Format error in last line of mob #%d\n"
        "...expecting line of form '# # # # #'", nr);
    exit(1);
  }

then in the mob_proto's remove the line   mob_proto[i].player.chclass = 0;
and add in the 2 new protos pointed below

  mob_proto[i].char_specials.position = t[0];
  mob_proto[i].mob_specials.default_pos = t[1];
  mob_proto[i].player.sex = t[2];
  mob_proto[i].player.chclass = t[3];<-----this
  mob_proto[i].player.race = t[4];<----------and this

  mob_proto[i].player.weight = 200;
  mob_proto[i].player.height = 198;

now close db.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
open structs.h and go to around line 130

in there should be your race defines
#define RACE_UNDEFINED  -1
#define RACE_HUMAN      0
#define RACE_DWARF      1
#define RACE_ELF        2
#define RACE_HOBBIT     3
#define RACE_GNOME      4
#define RACE_OGRE       5

below this is you havent allready done so add

#define NUM_RACES     6

NUM_RACES must be the total number of races on the game
you can add in special races for npc's that wont be available to 
players at your own discretion. To do so use one of the Race 
documents available at ftp.circlemud.org

close structs.h
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
open utils.h

around line 460 look for

#define IS_MAGIC_USER(ch)       (!IS_NPC / &&
                                (GET_CLASS(ch) == CLASS_MAGIC_USER)
or something similar looking to that
change it to
#define IS_MAGIC_USER(ch)       (GET_CLASS(ch) == CLASS_MAGIC_USER)
#define IS_CLERIC(ch)                 (GET_CLASS(ch) == CLASS_CLERIC)
#define IS_THIEF(ch)                   (GET_CLASS(ch) == CLASS_THIEF)  
#define IS_WARRIOR(ch)             (GET_CLASS(ch) == CLASS_WARRIOR)

all you do is drop the !IS_NPC and leave it open
and follow suit for all your classes and races
#define IS_HUMAN(ch)            (GET_RACE(ch) == RACE_HUMAN)   
#define IS_DWARF(ch)            (GET_RACE(ch) == RACE_DWARF)
#define IS_ELF(ch)                 (GET_RACE(ch) == RACE_ELF)
#define IS_HOBBIT(ch)           (GET_RACE(ch) == RACE_HOBBIT)

close utils.h
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Now that you have changed the source files to include the 
you will have to either delete your .mob files or change them to 
correspond with the new format defined in db.c.
To change them, from the circle30bpl14/lib/world/obj/ directory
open each one of your .mob files and for each mob look for:

0 0 0 0d0+0 0d0+0
0 0
0 0 0 

Of course all your numbers defining the fields of the mob are not 0's
but you can see the format plainly. That is what you need to look for.

On the last line in the format example above you MUST add in two 
extra 0's to format for your new NPC race and class. (see below)

0 0 0 0d0+0 0d0+0
0 0
0 0 0 0 0 <---notice the 2 new fields for Race and Class

If you do not choose to add in the extra fields you will need to 
delete ALL of your mob files and make new mobs in your editor.
Either by deleting or changing the format of the .mob files by hand or by 
script this step must be completed in order for this change in code
to work.
 
That should give you the basic shell for an endless ammount
of possibilities for your MUD. You can go as far as adding
statements and checks to enable npc's to use the skills and
spells available to players. The more like the players the mobs can 
be the more realistic (in my opinion) your mud will become.



John Hines
Weefcraft Custom Tiedyed Apparel
mailto:tiedye@tiedye.org
http://www.tiedye.org

<< mteach and mskillset [by Xual] | Reply | Flattened | CircleMUD 3.0 bpl15 >>

 


Related Links
  CircleMUD
"John Hines"
Related Articles
More by greerga