Karl N. Matthias Stats editor which allows new players to assign a pool of points to their stats in order that they can configure which are most important to them. By: Karl N. Matthias (Relistan on Urath) E-mail: karl@matthias.org Urath: urath.razors-edge.net 4000 ------------------------------------ NOTE: You can do whatever you want with this code as long as my copyright notice remains in place. Giving me credit on your mud would be nice, but is not necessary if you don''t. If you use it, drop me a note to let me know. The code isn''t the cleanest, so if you find bugs or nasties, let me know that, too! But you are on your own in installing this. If it completely junks your Mud, it''s not my fault. You have been warned. If you''re not a coder, get one to add this for you: it''s simple, but not THAT simple. On Urath we were looking at ways to let players configure their characters more than just by selecting race and class. I looked around and couldn''t find an editor of any kind for stats. What we really wanted was for people to be able to assign a randomly rolled pool of points to scores. The implementation I wrote sets a minimum of 8 for each score and a maximum of 18, but you can easily change this in the code. So, now for the implementation. The way Circle does input makes it a little hard to write things which require state between calls. A perfect example of code which does this, though, is OasisOLC. Rather than writing all of this again myself(which wouldn''t be that difficult, actually, now that I see how it all works), I used OasisOLC''s variables. What this means to you is that YOU MUST HAVE OASISOLC installed to use this code. Otherwise, you can create the support code yourself. [Basically you need to add a variable to the descriptor or character which lets you store a variable across calls to a function (you could use character alignment for this if pressed). And you need somewhere to store a second set of connection states.] If you have OasisOLC, you can ignore the stuff in brackets. Okay, so you need a new piece of code, statedit.c which follows: ------------------------------------------------------------------------------- /************************************************************************ * --Statedit Part of UrathMud v1.0 * * Copyright 1999 Karl N. Matthias. All rights Reserved. * * You may freely distribute, modify, or sell this code * * as long as this copyright remains intact. * * * * Based on code by Jeremy Elson, Harvey Gilpin, and George Greer. * ************************************************************************/ /* --relistan 2/22/99 - 2/24/99 */ #include "conf.h" #include "sysdep.h" #include "structs.h" #include "interpreter.h" #include "comm.h" #include "utils.h" #include "db.h" #include "olc.h" int parse_stat_menu(struct descriptor_data *d, char *arg); int parse_stats(struct descriptor_data *d, char *arg); int stats_disp_menu(struct descriptor_data *d); void init_stats(struct descriptor_data *d); int stats_assign_stat(int abil, char *arg, struct descriptor_data *d); /* --relistan 2/22/99 for player configurable stats */ int parse_stats(struct descriptor_data *d, char *arg) { struct char_data *ch; ch = d->character; switch(OLC_MODE(d)) { case STAT_QUIT: return 1; case STAT_PARSE_MENU: if(parse_stat_menu(d, arg)) return 1; break; case STAT_GET_STR: ch->real_abils.str = stats_assign_stat(ch->real_abils.str, arg, d); stats_disp_menu(d); break; case STAT_GET_INT: ch->real_abils.intel = stats_assign_stat(ch->real_abils.intel, arg, d); stats_disp_menu(d); break; case STAT_GET_WIS: ch->real_abils.wis = stats_assign_stat(ch->real_abils.wis, arg, d); stats_disp_menu(d); break; case STAT_GET_DEX: ch->real_abils.dex = stats_assign_stat(ch->real_abils.dex, arg, d); stats_disp_menu(d); break; case STAT_GET_CON: ch->real_abils.con = stats_assign_stat(ch->real_abils.con, arg, d); stats_disp_menu(d); break; case STAT_GET_CHA: ch->real_abils.cha = stats_assign_stat(ch->real_abils.cha, arg, d); stats_disp_menu(d); break; default: OLC_MODE(d) = stats_disp_menu(d); break; } return 0; } /* Roll up the initial stats and assign them to OLC_VAL(d) This isn''t nearly as efficient as it could be, but this code is horked from the original roll_real_abils() code */ void init_stats(struct descriptor_data *d) { int i, j, k, temp; ubyte table[6]; ubyte rolls[4]; for (i = 0; i < 6; i++) table[i] = 0; for (i = 0; i < 6; i++) { for (j = 0; j < 4; j++) rolls[j] = number(1, 6); temp = rolls[0] + rolls[1] + rolls[2] + rolls[3] - MIN(rolls[0], MIN(rolls[1], MIN(rolls[2], rolls[3]))); for (k = 0; k < 6; k++) if (table[k] < temp) { temp ^= table[k]; table[k] ^= temp; temp ^= table[k]; } } OLC_VAL(d) = table[0] + table[1] + table[2] + table[3] + table[4] + table[5]; d->character->real_abils.str_add = 0; /* Minimum stats 8 */ d->character->real_abils.str = 8; d->character->real_abils.intel = 8; d->character->real_abils.cha = 8; d->character->real_abils.dex = 8; d->character->real_abils.con = 8; d->character->real_abils.wis = 8; OLC_VAL(d) -= 48; stats_disp_menu(d); } int stats_disp_menu(struct descriptor_data *d) { sprintf(buf, "\r\n" "-<[========[ Urath ]=======]>-\r\n" " <| Total Points Left: %3d |> You should select the letter of\r\n" " <| |> the score you wish to adjust.\r\n" " <| = Select a stat: |> When prompted, enter the new\r\n" " <| S) Strength : %2d |> score, NOT the amount to add.\r\n" " <| I) Intelligence : %2d |> NOTE: If you quit before you\r\n" " <| W) Wisdom : %2d |> assign all the points, you\r\n" " <| D) Dexterity : %2d |> will lose them forever.\r\n" " <| N) Constitution : %2d |>\r\n" " <| C) Charisma : %2d |>\r\n" " <| Q) Quit |>\r\n" "-<[========================]>-\r\n" "\r\n", OLC_VAL(d), d->character->real_abils.str, d->character->real_abils.intel, d->character->real_abils.wis, d->character->real_abils.dex, d->character->real_abils.con, d->character->real_abils.cha); send_to_char(buf, d->character); send_to_char("Enter Letter to Change: ", d->character); OLC_MODE(d) = STAT_PARSE_MENU; return 1; } int parse_stat_menu(struct descriptor_data *d, char *arg) { /* Main parse loop */ *arg = LOWER(*arg); switch (*arg) { case ''s'': OLC_MODE(d) = STAT_GET_STR; send_to_char("Enter New value: ", d->character); break; case ''i'': OLC_MODE(d) = STAT_GET_INT; send_to_char("Enter New value: ", d->character); break; case ''w'': OLC_MODE(d) = STAT_GET_WIS; send_to_char("Enter New value: ", d->character); break; case ''d'': OLC_MODE(d) = STAT_GET_DEX; send_to_char("Enter New value: ", d->character); break; case ''n'': OLC_MODE(d) = STAT_GET_CON; send_to_char("Enter New value: ", d->character); break; case ''c'': OLC_MODE(d) = STAT_GET_CHA; send_to_char("Enter New value: ", d->character); break; case ''q'': OLC_MODE(d) = STAT_QUIT; return 1; default: stats_disp_menu(d); } return 0; } int stats_assign_stat(int abil, char *arg, struct descriptor_data *d) { int temp; if (abil > 0) { OLC_VAL(d) = OLC_VAL(d) + abil; abil = 0; } if (atoi(arg) > OLC_VAL(d)) temp = OLC_VAL(d); else temp = atoi(arg); if (temp > 18) { if (OLC_VAL(d) < 18) temp = OLC_VAL(d); else temp = 18; } if (temp < 8) { temp = 8; } /* This should throw an error! */ if (OLC_VAL(d) <= 0) { temp = 0; OLC_VAL(d) = 0; sprintf(buf, "Stat total below 0: possible code error"); mudlog(buf, NRM, LVL_IMMORT, TRUE); } abil = temp; OLC_VAL(d) -= temp; return abil; } ------------------------------------------------------------------------------- Okay, Now you need to modify a few files. First, get into olc.h and add the following lines: /* * Statedit Connectedness * --relistan 2/23/99 */ #define STAT_GET_STR 0 #define STAT_GET_INT 1 #define STAT_GET_WIS 2 #define STAT_GET_DEX 3 #define STAT_GET_CON 4 #define STAT_GET_CHA 5 #define STAT_QUIT 6 #define STAT_PARSE_MENU 7 I put these just above ''Limit Information'' in the code. Once you''ve done that, you need to add a connection state in structs.h. On Urath, we had 24 previous states of connectedness but stock Circle has like 16 or so. Add one to the end of the list that looks something like: #define CON_QSTATS 25 /* In-game disconnection */ You should change the number to be the next available in the list. I usually keep CON_DISCONNECT at the end and move it each time, but I''m not sure you need to do this (probably not). Now you need to edit the nanny function in interpreter.c so that this code will get called when a new player logs in. I have installed Race support on Urath, so this code may be a little different from stock Circle, but the end of the code here is really what''s important. You should modify the code under CON_QCLASS to look something like this: case CON_QCLASS: load_result = parse_class(*arg); if (load_result == CLASS_UNDEFINED) { SEND_TO_Q("\r\nThat''s not a class.\r\nClass: ", d); return; } else GET_CLASS(d->character) = load_result; if (GET_PFILEPOS(d->character) < 0) GET_PFILEPOS(d->character) = create_entry(GET_NAME(d->character)); init_char(d->character); /* --relistan for statedit -- Some code moved into CON_QSTATS See below for details */ if (!d->olc) CREATE(d->olc, struct olc_data, 1); STATE(d) = CON_QSTATS; init_stats(d); break; Now, right after that code, you should add the new connectedness entry for the stats editor. It should look like this: /* --relistan 2/22/99 for configurable stats */ case CON_QSTATS: if (parse_stats(d, arg)) { if(d->olc) free(d->olc); 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; Notice that I''ve moved some of the code from CON_QCLASS down into CON_QSTATS. That''s so that you enter your stats before getting the motd/imotd. You can change this if you want, but then you need to modify CON_RMOTD. One last file needs to be modified. You need to keep it from re-rolling your stats when you log in. Edit class.c and goto the roll_real_abils() function. It looks something like this: void roll_real_abils(struct char_data * ch) It begins with a switch() statement. What you need to do is comment out or delete this entire switch statement. On Urath I didn''t get rid of the entire function because Race support uses it to assign special stats to races. If you aren''t using race support and you want to stop this from being called at all, you can remove it from do_start() in class.c. It follows the set_title() call. Okay, I don''t think I left anything out. That should do it! If you have any problems, try to figure them out yourself. If everything else fails, mail me and I''ll try to help, but I''m not guaranteeing any support. If you want to see how it works, come visit Urath at urath.razors-edge.net 4000. ENHANCEMENTS: You might want to have a fixed point pool. Just replace the statements in statedit.c which do the rolling for the pool with a fixed assign. This is done in init_stats(). --relistan