Hi,
a little remark : it is NOT necessary to convert your playerfile!!!!
In structs.h, you can put the byte of the races in one of the spare bytes
in player_special_data...Search for them in structs.h!!!
You don't need to ruin your playerfile...
Hymy, The Wacko P-Imp <Power-Imp>
On Sat, 20 May 1995, Steve wrote:
> Date: Sat, 20 May 1995 13:30:09 -0700 (PDT)
> From: Steve <quickey@cyberverse.com>
> To: Ricky David Gibson <rdgibson@mailhost.ecn.uoknor.edu>
> Cc: circle@pvv.unit.no
> Subject: Re: races
>
> Races aren't really that hard, here is a sample of the changes needed for
> bpl4 i think. I haven't tested it with 7 but i dont think there should be
> too many problems, (you will have to convert your playerfile though)
>
> ------------------------------------------------------------------------------
> Race Modification for CircleMUD 3.0
> -by hash@cyberverse.com-
> This mod is VERY bare, just the core for a good race system; it will be
> improved VERY soon.... so don't be mad this isn't the spiffiest thing!
> Basically this mod is search and add, search and replace, etc... dont
> get too scared by the file size! :)
> ~~
>
> First, let's open up the header (.h) files, as they are very important to
> the functioning of the program (.c) files.
>
> *************************
> OPEN EDIT FILE: structs.h
> *************************
>
> Search for
> ---
> /* NPC classes (currently unused - feel free to implement!) */
> #define CLASS_OTHER 0
> #define CLASS_UNDEAD 1
> #define CLASS_HUMANOID 2
> #define CLASS_ANIMAL 3
> #define CLASS_DRAGON 4
> #define CLASS_GIANT 5
> ---
> Right below it, put the following
> ---
> /* PC races */
> #define RACE_UNDEFINED -1
> #define RACE_HUMAN 0
> #define RACE_ELF 1
> #define RACE_GNOME 2
> #define RACE_FAIRY 3
>
> #define NUM_RACES 4
> ---
> Now search for
> ---
> #define CON_DELCNF1 15 /* Delete confirmation 1 */
> #define CON_DELCNF2 16 /* Delete confirmation 2 */
> ---
> Right below it, put the following
> ---
> #define CON_QRACE 17 /* Race? */
> ---
> Now search for
> ---
> #define ITEM_ANTI_WARRIOR (1 << 15) /* Not usable by warriors */
> #define ITEM_NOSELL (1 << 16) /* Shopkeepers won't touch it */
> ---
> Right below it, put the following
> ---
> #define ITEM_ANTI_HUMAN (1 << 17) /* Not usable by Humans */
> #define ITEM_ANTI_ELF (1 << 18) /* Not usable by Elves */
> #define ITEM_ANTI_GNOME (1 << 19) /* Not usable by Gnomes */
> #define ITEM_ANTI_FAIRY (1 << 20) /* Not usable by Fairies */
> ---
> Now search for
> ---
> #define APPLY_SAVING_BREATH 23 /* Apply to save throw: breath */
> #define APPLY_SAVING_SPELL 24 /* Apply to save throw: spells */
> ---
> Right below it, put the following
> ---
> #define APPLY_RACE 25 /* Reserved */
> ---
> Now search for
> ---
> /* general player-related info, usually PC's and NPC's */
> struct char_player_data {
> char *name; /* PC / NPC s name (kill ... ) */
> char *short_descr; /* for NPC 'actions' */
> char *long_descr; /* for 'look' */
> char *description; /* Extra descriptions */
> char *title; /* PC / NPC's title */
> byte sex; /* PC / NPC's sex */
> byte class; /* PC / NPC's class */
> ---
> Right below it, between byte class and the next variable, put the following
> ---
> byte race; /* PC / NPC's race */
> ---
> Lastly search for
> ---
> struct char_file_u {
> /* char_player_data */
> char name[MAX_NAME_LENGTH+1];
> char description[EXDSCR_LENGTH];
> char title[MAX_TITLE_LENGTH+1];
> byte sex;
> byte class;
> ---
> Right below it, between byte class and the next variable, put the following
> ---
> byte race;
> ---
>
> **************************
> CLOSE EDIT FILE: structs.h
> **************************
>
> ***********************
> OPEN EDIT FILE: utils.h
> ***********************
>
> Search for
> ---
> #define GET_REAL_LEVEL(ch) \
> (ch->desc && ch->desc->original ? GET_LEVEL(ch->desc->original) : \
> GET_LEVEL(ch))
>
> #define GET_CLASS(ch) ((ch)->player.class)
> ---
> Right below it, put the following
> ---
> #define GET_RACE(ch) ((ch)->player.race)
> ---
> Lastly search for
> ---
> #define IS_THIEF(ch) (!IS_NPC(ch) && \
> (GET_CLASS(ch) == CLASS_THIEF))
> #define IS_WARRIOR(ch) (!IS_NPC(ch) && \
> (GET_CLASS(ch) == CLASS_WARRIOR))
> ---
> Right below it, put the following
> ---
> #define IS_HUMAN(ch) (!IS_NPC(ch) && \
> (GET_RACE(ch) == RACE_HUMAN))
>
> #define IS_ELF(ch) (!IS_NPC(ch) && \
> (GET_RACE(ch) == RACE_ELF))
>
> #define IS_GNOME(ch) (!IS_NPC(ch) && \
> (GET_RACE(ch) == RACE_GNOME))
>
> #define IS_FAIRY(ch) (!IS_NPC(ch) && \
> (GET_RACE(ch) == RACE_FAIRY))
> ---
>
> ************************
> CLOSE EDIT FILE: utils.h
> ************************
>
> Now, lets go on to the .C files, the core of it all.
>
> ***********************
> OPEN EDIT FILE: class.c
> ***********************
>
> Search for
> ---
> const char *pc_class_types[] = {
> "Magic User",
> "Cleric",
> "Thief",
> "Warrior",
> "\n"
> };
> ---
> Then put the following below it
> ---
> const char *race_abbrevs[] = {
> "Hum",
> "Elf",
> "Gno",
> "Fai",
> "\n"
> };
>
> const char *pc_race_types[] = {
> "Human",
> "Elf",
> "Gnome",
> "Fairy",
> "\n"
> };
> ---
> Now search for
> ---
> "Select a class:\r\n"
> " [C]leric\r\n"
> " [T]hief\r\n"
> " [W]arrior\r\n"
> " [M]agic-user\r\n";
> ---
> And put the following right below it
> ---
> /* The menu for choosing a race in interpreter.c: */
> const char *race_menu =
> "\r\n"
> "Select a race:\r\n"
> " [H]uman\r\n"
> " [E]lf\r\n"
> " [G]nome\r\n"
> " [F]airy\r\n";
> ---
> Now search for
> ---
> case 'w':
> return CLASS_WARRIOR;
> break;
> case 't':
> return CLASS_THIEF;
> break;
> default:
> return CLASS_UNDEFINED;
> break;
> }
> }
> ---
> And block copy the following below it
> ---
> /*
> * The code to interpret a race letter (used in interpreter.c when a
> * new character is selecting a race).
> */
> int parse_race(char arg)
> {
> arg = LOWER(arg);
>
> switch (arg) {
> case 'h':
> return RACE_HUMAN;
> break;
> case 'e':
> return RACE_ELF;
> break;
> case 'g':
> return RACE_GNOME;
> break;
> case 'f':
> return RACE_FAIRY;
> break;
> default:
> return RACE_UNDEFINED;
> break;
> }
> }
> ---
> Now search for
> ---
> case 't':
> return 4;
> break;
> case 'w':
> return 8;
> break;
> default:
> return 0;
> break;
> }
> }
> ---
> Then place the following below it
> ---
> long find_race_bitvector(char arg)
> {
> arg = LOWER(arg);
>
> switch (arg) {
> case 'h':
> return 1;
> break;
> case 'e':
> return 2;
> break;
> case 'g':
> return 4;
> break;
> case 'f':
> return 8;
> break;
> default:
> return 0;
> break;
> }
> }
> ---
> Now replace the description of void roll_real_abils(...) with this one
> ---
> /*
> * Roll the 6 stats for a character... each stat is made of the sum of
> * the best 3 out of 4 rolls of a 6-sided die. Each class then decides
> * which priority will be given for the best to worst stats. Race also
> * affects stats.
> */
> ---
> Now search for
> ---
> case CLASS_WARRIOR:
> ch->real_abils.str = table[0];
> ch->real_abils.dex = table[1];
> ch->real_abils.con = table[2];
> ch->real_abils.wis = table[3];
> ch->real_abils.intel = table[4];
> ch->real_abils.cha = table[5];
> if (ch->real_abils.str == 18)
> ch->real_abils.str_add = number(0, 100);
> break;
> }
> ---
> And directly<!> below it, put this
> ---
> switch (GET_RACE(ch)) {
> case RACE_HUMAN:
> ++ch->real_abils.con;
> break;
> case RACE_ELF:
> ++ch->real_abils.dex;
> ++ch->real_abils.intel;
> --ch->real_abils.con;
> --ch->real_abils.str;
> break;
> case RACE_GNOME:
> ch->real_abils.str+=3;
> --ch->real_abils.dex;
> --ch->real_abils.intel;
> --ch->real_abils.cha;
> break;
> case RACE_FAIRY:
> ch->real_abils.dex+=2;
> ++ch->real_abils.wis;
> ++ch->real_abils.cha;
> ch->real_abils.str-=2;
> --ch->real_abils.con;
> break;
> }
> ---
> You should have still left the end of the function the same though, like:
> ---
> ch->aff_abils = ch->real_abils;
> }
> ---
> Okay, now, at the very END of the file, add this function
> ---
> int invalid_race(struct char_data *ch, struct obj_data *obj) {
> if ((IS_OBJ_STAT(obj, ITEM_ANTI_HUMAN) && IS_HUMAN(ch)) ||
> (IS_OBJ_STAT(obj, ITEM_ANTI_ELF) && IS_ELF(ch)) ||
> (IS_OBJ_STAT(obj, ITEM_ANTI_GNOME) && IS_GNOME(ch)) ||
> (IS_OBJ_STAT(obj, ITEM_ANTI_FAIRY) && IS_FAIRY(ch)))
> return 1;
> else
> return 0;
> }
> ---
>
> ************************
> CLOSE EDIT FILE: class.c
> ************************
>
> ***************************
> OPEN EDIT FILE: constants.c
> ***************************
>
> Search for
> ---
> /* CON_x */
> const char *connected_types[] = {
> "Playing",
> "Disconnecting",
> "Get name",
> "Confirm name",
> "Get password",
> "Get new PW",
> "Confirm new PW",
> "Select sex",
> "Select class",
> "Reading MOTD",
> "Main Menu",
> "Get descript.",
> "Changing PW 1",
> "Changing PW 2",
> "Changing PW 3",
> "Self-Delete 1",
> "Self-Delete 2",
> ---
> And add the following below it
> ---
> "Select race",
> ---
> Lastly search for
> ---
> /* APPLY_x */
> const char *apply_types[] = {
> "NONE",
> "STR",
> "DEX",
> "INT",
> "WIS",
> "CON",
> "CHA",
> "CLASS",
> "LEVEL",
> "AGE",
> "CHAR_WEIGHT",
> "CHAR_HEIGHT",
> "MAXMANA",
> "MAXHIT",
> "MAXMOVE",
> "GOLD",
> "EXP",
> "ARMOR",
> "HITROLL",
> "DAMROLL",
> "SAVING_PARA",
> "SAVING_ROD",
> "SAVING_PETRI",
> "SAVING_BREATH",
> "SAVING_SPELL",
> ---
> And add the following below it
> ---
> "RACE",
> ---
>
> ***************************
> CLOSE EDIT FILE: constant.c
> ***************************
>
> ********************
> OPEN EDIT FILE: db.c
> ********************
>
> Search for
> ---
> mob_proto[i].player.sex = t[2];
>
> mob_proto[i].player.class = 0;
> ---
> Then put this after it
> ---
> mob_proto[i].player.race = 0;
> ---
> Now search for
> ---
> GET_SEX(ch) = st->sex;
> GET_CLASS(ch) = st->class;
> ---
> Then add the following below it
> ---
> GET_RACE(ch) = st->race;
> ---
> Lastly search for
> ---
> st->sex = GET_SEX(ch);
> st->class = GET_CLASS(ch);
> ---
> Then put this below it
> ---
> st->race = GET_RACE(ch);
> ---
>
> *********************
> CLOSE EDIT FILE: db.c
> *********************
>
> *************************
> OPEN EDIT FILE: handler.c
> *************************
>
> Search for
> ---
> case APPLY_SAVING_SPELL:
> GET_SAVE(ch, SAVING_SPELL) += mod;
> break;
> ---
> Put the following below it
> ---
> case APPLY_RACE:
> /* ??? GET_RACE(ch) += mod; */
> break;
> ---
> Now search for
> ---
> void equip_char(struct char_data * ch, struct obj_data * obj, int pos)
> {
> int j;
> int invalid_class(struct char_data *ch, struct obj_data *obj);
> ---
> And add this below it
> ---
> int invalid_race(struct char_data *ch, struct obj_data *obj);
> ---
> Lastly search for the following
> ---
> if ((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) ||
> (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) ||
> (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)) ||
> invalid_class(ch, obj)) {
> ---
> and REPLACE the entire thing with the following:
> ---
> if ((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) ||
> (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) ||
> (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)) ||
> invalid_class(ch, obj) || invalid_race(ch, obj)) {
> ---
>
> **************************
> CLOSE EDIT FILE: handler.c
> **************************
>
> *****************************
> OPEN EDIT FILE: interpreter.c
> *****************************
>
> Search for
> ---
> extern const char *class_menu;
> ---
> Then add this below it
> ---
> extern const char *race_menu;
> ---
> Now, search for (its right below it)
> ---
> sh_int load_room;
>
> int load_char(char *name, struct char_file_u * char_element);
> int parse_class(char arg);
> ---
> And add this...
> ---
> int parse_race(char arg);
> ---
> Now replace the following two CASE statements for the ones that already exist
> <THIS IS VERY IMPORTANT!> completely erase old case CON_QCLASS, and add
> this one plus the additional <new> case CON_QRACE at the end of it...
> ---
> case CON_QCLASS:
> if ((GET_CLASS(d->character) = parse_class(*arg)) == CLASS_UNDEFINED) {
> SEND_TO_Q("\r\nThat's not a class.\r\nClass: ", d);
> return;
> }
> SEND_TO_Q(race_menu, d);
> SEND_TO_Q("\r\nRace: ", d);
> STATE(d) = CON_QRACE;
> break;
>
> case CON_QRACE:
> if ((GET_RACE(d->character) = parse_race(*arg)) == CLASS_UNDEFINED) {
> SEND_TO_Q("\r\nThat's not a race.\r\nRace: ", d);
> return;
> }
>
> if (d->pos < 0)
> d->pos = create_entry(GET_NAME(d->character));
> init_char(d->character);
> save_char(d->character, NOWHERE);
> SEND_TO_Q(motd, d);
> SEND_TO_Q("\r\n\n*** PRESS RETURN: ", d);
> STATE(d) = CON_RMOTD;
>
> sprintf(buf, "%s [%s] new player.", GET_NAME(d->character), d->host);
> mudlog(buf, NRM, LVL_IMMORT, TRUE);
> break;
> ---
>
> ***************************
> CLOSE EDIT FILE: interpre.c
> ***************************
>
>
> *******YOU'RE DONE!*******
>
.-----------------------------------------------------------------------.
| I t ' s n o t a b u g , i t ' s a f e a t u r e ! ! ! |
| BUG Mud - Belgian UnderGround @@@@@@@@. @@@. @@@. .@@@@@@@. |
| Imps: @@@@ `@@@ @@@@ @@@@ !@@@@' `@@! |
| Gekke, Charlotte, Hymy, @@@@..:@@@ @@@@ @@@! !@@@@ ' |
| Mentat and Wodan @@!@@@@@@ @@@! !@@! !@!@@ .@@@. |
| !@!! `!@@@. @@!! !@!! !@!!@ `@@@ |
| Thanx to SunGoku... :!!: .!!@@; !!!:. !@!! `!!!@. :@!@ |
| `!!::!!:!' `!!!:::!!' :!!!!!!!!! |
| If you can't connect, .!: `:: : `::' `:: :!:' `!' |
| email tvergote@eduserv.rug.ac.be :; : . :; : :: : |
| with subject "frontdoor" : . : . . . |
`-----------------------------------------------------------------------'
This archive was generated by hypermail 2b30 : 12/07/00 PST