Player Stats Editor [By Karl N. Matthias]
Snippet Posted Thursday, March 4th @ 03:26:34 PM, by George Greer in the Players dept.
Karl N. Matthias writes "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

<< Do_Create & Do_Scare [By B. Brown] | Reply | View as text | Flattened | Database Parser 2 v0.1 >>

 


Related Links
  Intel
Karl N. Matthias
Related Articles
More by greerga
 
 

CircleMUD Snippets
 
Note: Not all of these snippets will work perfectly with your version of code, so be prepared to fix one or two bugs that may arise, and please let me know what you needed to do to fix it. Sending a corrected version is always welcome.
Finally, if you wish to use any of the snippets from this page, you are more than welcome, just mention the authors in your credits. If you wish to release any of these snippets to the public on another site, contact me FIRST.
 
 


Coredump?
by Terry Valladon (CybrRepr@yahoo.com) on Wednesday, August 29th @ 11:12:51 AM
http://
I am using this on bpl17 with oasis OLC(or trying to) but I get a core dump in statedit.c on the line that states:

switch(OLC_MODE(d)) {

can anyone help with this?

Thank you,
Terry
[ Reply to this comment ]