Race before Class Code. v1.0
----------------------------

Author: Lews
Webpage: www.sica.tzo.com/mud/
Email: lews00@yahoo.com
Telnet: sica.tzo.com:4000


TERMS OF USE:
-------------
Keep any comments of headers in place. 
If you use my code, send me an e-mail 
letting me know that you are using it.
Always make sure you back up your files
before making any changes. I will assume no responsibility
if something goes wrong.


What it is:
-----------
This code changes the character creation process. 
Instead of choosing a class first then a race,
the player will choose a race first, then a race. 
the setclass, showclass, setrace and showrace commands 
are also changed to reflect the new code.
This code will not affect any current users, they
can stll keep there current race and class.
Also included are the modified stock class and
race files. If there are differences in the stock
files to my own, please let me know.
This is my first code snippet to be released,
be kind.


Instructions:
-------------
Before you start, make sure you back up your mud. 
Also make sure you back up your class and race files.
The sections that are to be commented out, are to ease an 
uninstallation process, you can delete these sections of code 
if you feel the need to.


----------------------------------------------------------------
in mud.h 
================================================================

Find this:
/*
 * Per-class stuff.
 */
struct	class_type
{
    char *	who_name;		/* Name for 'who'		*/
    EXT_BV	affected;
    sh_int	attr_prime;		/* Prime attribute		*/
    sh_int	attr_second;		/* Second attribute		*/
    sh_int	attr_deficient;		/* Deficient attribute		*/

and ADD this:
    EXT_BV 	race_restriction;	/* Flags for illegal races	-Lews */


find this:
/* race dedicated stuff */
struct	race_type
{
    char 	race_name	[16];	/* Race name			*/
    EXT_BV	affected;		/* Default affect bitvectors	*/
    sh_int	str_plus;		/* Str bonus/penalty		*/
    sh_int	dex_plus;		/* Dex      "			*/
    sh_int	wis_plus;		/* Wis      "			*/
    sh_int	int_plus;		/* Int      "			*/
    sh_int	con_plus;		/* Con      "			*/
    sh_int	cha_plus;		/* Cha      "			*/
    sh_int	lck_plus;		/* Lck 	    "			*/
    sh_int      hit;
    sh_int      mana;
    int      	resist;
    int      	suscept;
    int		class_restriction;	/* Flags for illegal classes	*/

and CHANGE the last line above to:
 /* int		class_restriction;	*//* Flags for illegal classes  */

----------------------------------------------------------------
In act_wiz.c
================================================================

Find this:
/* from build.c */
int     get_risflag( char *flag );
int get_defenseflag( char *flag );
int  get_attackflag( char *flag );

and ADD:
int get_pc_race( char *type );



----------------------------------------------------------------
void do_showclass( CHAR_DATA *ch, char *argument )
----------------------------------------------------------------
Find this:
    int cl, low, hi;

and CHANGE to:
    int cl, low, hi, ct, i;

find this:
    pager_printf_color( ch, "&wSecond Attribute:  &W%-14s  &wDeficient Attribute:  &W%-14s\n\r",
    	affect_loc_name(class->attr_second), affect_loc_name(class->attr_deficient) );

and ADD:

   ct=0;
    pager_printf_color( ch, "&wAllowed Races: ");
    for(i=0;i<MAX_RACE;i++){
      if( !xIS_SET(class->race_restriction, i )
          &&   str_cmp(race_table[i]->race_name,"unused" )  )
      {
             ct++;
            pager_printf_color( ch, "&W%s ", race_table[i]->race_name);
	     if( ct%6==0) send_to_char("\n\r", ch);
      }
    }
    if( (ct%6!=0) || (ct==0)) send_to_char("\n\r", ch);

    ct=0;
    pager_printf_color( ch, "&wDisallowed Races: ");
    for(i=0;i<MAX_RACE;i++){
      if( xIS_SET(class->race_restriction, i )
          &&   str_cmp(race_table[i]->race_name,"unused" )  )
      {
             ct++;
            pager_printf_color( ch, "&r%s ", race_table[i]->race_name);
	     if( ct%6==0) send_to_char("\n\r", ch);
      }
    }
    if( (ct%6!=0) || (ct==0)) send_to_char("\n\r", ch);



----------------------------------------------------------------
in bool create_new_class( int index, char *argument )
----------------------------------------------------------------

find this:
  class_table[index]->attr_deficient = 0;
and add:
  xCLEAR_BITS(class_table[index]->race_restriction);

----------------------------------------------------------------
in void do_setclass( CHAR_DATA *ch, char *argument )
----------------------------------------------------------------
find this:
	send_to_char( "  name prime weapon guild thac0 thac32\n\r",	ch );

CHANGE to:
	send_to_char( "  name prime race weapon guild thac0 thac32\n\r",	ch );


find this:
    if ( !str_cmp( arg2, "name" ) )
    {
	STRFREE(class->who_name );
	class->who_name = STRALLOC( argument );
	send_to_char( "Done.\n\r", ch );
	return;
    }

and ADD below:
    /* Race Restriction -Lews */
    if ( !str_cmp( arg2, "race" ) )
    {
        if ( !argument || argument[0] == '\0' )
        {
            send_to_char( "Usage: setclass <class> <race> \n\r", ch );
            return;
        }
        while ( argument[0] != '\0' )
        {
            argument = one_argument( argument, arg2 );
            value = get_pc_race( arg2 );
            if ( value < 0 || value > MAX_BITS )
                ch_printf( ch, "Unknown Race: %s\n\r", arg2 );
            else
                xTOGGLE_BIT( class->race_restriction, value );
        }
        return;
     }

--------------------------------------------------------
in bool create_new_race( int index, char *argument ) 
--------------------------------------------------------
find this:
  race_table[index]->class_restriction = 0;

and COMMENT it out /* */

--------------------------------------------------------
in void do_setrace( CHAR_DATA *ch, char *argument )
--------------------------------------------------------
Find this:
        send_to_char( "  name classes strplus dexplus wisplus\n\r",     ch );

and CHANGE it to
        send_to_char( "  name strplus dexplus wisplus\n\r",     ch );

find this:

    if ( !str_cmp( arg2, "classes" ) )
    {
        for(i=0;i<MAX_CLASS;i++)
        {
           if( !str_cmp(argument,class_table[i]->who_name) )
           {   
              TOGGLE_BIT( race->class_restriction, 1 << i);   /* k, that's boggling */
              send_to_char( "Done.\n\r", ch );
              return;
           }   
        }
        send_to_char( "No such class.\n\r", ch );
        return;
    }

and COMMENT it out /* */

--------------------------------------------------------
in void do_showrace( CHAR_DATA *ch, char *argument )
--------------------------------------------------------
find:

    ct=0;
    sprintf( buf, "Disallowed Classes: ");
    send_to_char( buf, ch);
    for(i=0;i<MAX_CLASS;i++){
      if( IS_SET(race->class_restriction, 1 << i) )
      {
             ct++; 
             sprintf(buf,"%s ", class_table[i]->who_name);
             send_to_char( buf, ch);
	     if( ct%6==0) send_to_char("\n\r", ch);
      } 
    }
    if( (ct%6!=0) || (ct==0)) send_to_char("\n\r", ch);

    ct=0;
    sprintf( buf, "Allowed Classes: ");
    send_to_char( buf, ch);
    for(i=0;i<MAX_CLASS;i++){
      if( !IS_SET(race->class_restriction, 1 << i) )
      {
             ct++;
             sprintf(buf,"%s ", class_table[i]->who_name);
             send_to_char( buf, ch);
	     if( ct%6==0) send_to_char("\n\r", ch);
      } 
    }
    if( (ct%6!=0) || (ct==0)) send_to_char("\n\r", ch);


and COMMENT it out /* */

----------------------------------------------------------------
In comm.c (This is the big one )
================================================================

Find this:
	write_to_buffer( d, "\n\rSelect a class, or type help [class] to learn more about that class.\n\r[", 0 );
	buf[0] = '\0';

	/*
	 * Take this out SHADDAI
	 */
	for ( iClass = 0; iClass < MAX_PC_CLASS-2; iClass++ )
	{
	    if ( class_table[iClass]->who_name &&
	    	 class_table[iClass]->who_name[0] != '\0' )
	    {
	      if ( iClass > 0 )
	      {
		  if ( strlen(buf)+strlen(class_table[iClass]->who_name) > 77 )
		  {
		     strcat( buf, "\n\r" );
		     write_to_buffer( d, buf, 0 );
		     buf[0] = '\0';
		  }
		  else
		     strcat( buf, " " );
	      }
	    }
	    strcat( buf, class_table[iClass]->who_name );
	}
	strcat( buf, "]\n\r: " );
	write_to_buffer( d, buf, 0 );
	d->connected = CON_GET_NEW_CLASS;
	break;

    case CON_GET_NEW_CLASS:
	argument = one_argument(argument, arg);

        if (!str_cmp(arg, "help"))
        {
        
	for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ )
	{
	  if ( class_table[iClass]->who_name &&
	       class_table[iClass]->who_name[0] != '\0' )
	  {
            if (toupper(argument[0])==toupper(class_table[iClass]->who_name[0])
	    &&   !str_prefix( argument, class_table[iClass]->who_name ) )
	    {
	      do_help(ch, argument);
	      write_to_buffer( d, "Please choose a class: ", 0 );
              return;
	    }
	  }
        }  
	write_to_buffer( d, "No such help topic.  Please choose a class: ", 0 );
	return;
	}

	for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ )
	{
	  if ( class_table[iClass]->who_name &&
	       class_table[iClass]->who_name[0] != '\0' )
	  {
	    if ( toupper(arg[0]) == toupper(class_table[iClass]->who_name[0])
	    &&   !str_prefix( arg, class_table[iClass]->who_name ) )
	    {
		ch->class =  iClass;
		break;
	    }
	  }
	}

	if ( iClass == MAX_PC_CLASS
	||  !class_table[iClass]->who_name 
	|| class_table[iClass]->who_name[0] == '\0'
	|| !str_cmp(class_table[iClass]->who_name,"unused"))
	{
	  write_to_buffer( d, "That's not a class.\n\rWhat IS your class? ",0);
	  return;
	}


        if ( check_bans( ch, BAN_CLASS ) )
        {
         write_to_buffer (d,
             "That class is not currently avaiable.\n\rWhat IS your class? ",0);
         return;
        }

	write_to_buffer( d, "\n\rYou may choose from the following races, or type help [race] to learn more:\n\r[", 0 );
	buf[0] = '\0';
	for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
	{
	  if (iRace != RACE_VAMPIRE
	  && race_table[iRace]->race_name && race_table[iRace]->race_name[0] != '\0'
	  && !IS_SET(race_table[iRace]->class_restriction, 1 << ch->class) 
	  && str_cmp(race_table[iRace]->race_name,"unused") )
	  {
            if ( iRace > 0 )
	    {
		if ( strlen(buf)+strlen(race_table[iRace]->race_name) > 77 )
		{
		   strcat( buf, "\n\r" );
		   write_to_buffer( d, buf, 0 );
		   buf[0] = '\0';
		}
		else
		   strcat( buf, " " );
	    }
	    strcat( buf, race_table[iRace]->race_name );
          }
        }
	strcat( buf, "]\n\r: " );
	write_to_buffer( d, buf, 0 );
	d->connected = CON_GET_NEW_RACE;
	break;

    case CON_GET_NEW_RACE:
	argument = one_argument(argument, arg);
        if (!str_cmp( arg, "help") )
        {
          for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
	  {
	    if ( toupper(argument[0]) == toupper(race_table[iRace]->race_name[0])
	    &&  !str_prefix( argument, race_table[iRace]->race_name) )
	    {
	      do_help(ch, argument);
      	      write_to_buffer( d, "Please choose a race: ", 0);
	      return;
	    }
	  }
   	  write_to_buffer( d, "No help on that topic.  Please choose a race: ", 0 );
	  return;
	}
	

	for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
	{
	    if ( toupper(arg[0]) == toupper(race_table[iRace]->race_name[0])
	    &&   !str_prefix( arg, race_table[iRace]->race_name ) )
	    {
		ch->race = iRace;
		break;
	    }
	}

    if ( iRace == MAX_PC_RACE
    ||  !race_table[iRace]->race_name || race_table[iRace]->race_name[0] == '\0'
    ||   iRace == RACE_VAMPIRE
    ||   IS_SET(race_table[iRace]->class_restriction, 1 << ch->class )
    ||   !str_cmp(race_table[iRace]->race_name,"unused")
       )
	{
	    write_to_buffer( d,
		"That's not a race.\n\rWhat IS your race? ", 0 );
	    return;
	}
        if ( check_bans( ch, BAN_RACE ) )
        {
          write_to_buffer (d,
            "That race is not currently available.\n\rWhat is your race? ", 0);
          return;
        }

	write_to_buffer( d, "\n\rWould you like RIP, ANSI or no graphic/color support, (R/A/N)? ", 0 );
	d->connected = CON_GET_WANT_RIPANSI;
        break;


and CHANGE it to:

	write_to_buffer( d, "\n\rYou may choose from the following races, or type help [race] to learn more:\n\r[", 0 );
	buf[0] = '\0';
	for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
	{
	  if (iRace != RACE_VAMPIRE
	  && race_table[iRace]->race_name && race_table[iRace]->race_name[0] != '\0'
	  && str_cmp(race_table[iRace]->race_name,"unused") )
	  {
            if ( iRace > 0 )
	    {
		if ( strlen(buf)+strlen(race_table[iRace]->race_name) > 77 )
		{
		   strcat( buf, "\n\r" );
		   write_to_buffer( d, buf, 0 );
		   buf[0] = '\0';
		}
		else
		   strcat( buf, " " );
	    }
	    strcat( buf, race_table[iRace]->race_name );
          }
        }
	strcat( buf, "]\n\r: " );
	write_to_buffer( d, buf, 0 );
	d->connected = CON_GET_NEW_RACE;
	break;

    case CON_GET_NEW_RACE:
	argument = one_argument(argument, arg);
        if (!str_cmp( arg, "help") )
        {
          for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
	  {
	    if ( toupper(argument[0]) == toupper(race_table[iRace]->race_name[0])
	    &&  !str_prefix( argument, race_table[iRace]->race_name) )
	    {
	      do_help(ch, argument);
      	      write_to_buffer( d, "Please choose a race: ", 0);
	      return;
	    }
	  }
   	  write_to_buffer( d, "No help on that topic.  Please choose a race: ", 0 );
	  return;
	}


	for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
	{
	    if ( toupper(arg[0]) == toupper(race_table[iRace]->race_name[0])
	    &&   !str_prefix( arg, race_table[iRace]->race_name ) )
	    {
                ch->race =  iRace;
	        break;
	    }
	}

    if ( iRace == MAX_PC_RACE
    ||  !race_table[iRace]->race_name || race_table[iRace]->race_name[0] == '\0'
    ||   iRace == RACE_VAMPIRE
    ||   !str_cmp(race_table[iRace]->race_name,"unused")
       )
	{
	    write_to_buffer( d,
		"That's not a race.\n\rWhat IS your race? ", 0 );
	    return;
	}
        if ( check_bans( ch, BAN_RACE ) )
        {
          write_to_buffer (d,
            "That race is not currently available.\n\rWhat is your race? ", 0);
          return;
        }

	write_to_buffer( d, "\n\rYou may choose from the following classes, or type help [class] to learn more:\n\r[", 0 );
	buf[0] = '\0';
	for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ )
	{
	  if ( class_table[iClass]->who_name && class_table[iClass]->who_name[0] != '\0'
	  && !xIS_SET(class_table[iClass]->race_restriction, 1 << ch->race)
	  && str_cmp(class_table[iClass]->who_name,"unused") )
	  {
            if ( iClass > 0 )
	    {
		if ( strlen(buf)+strlen(class_table[iClass]->who_name ) > 77 )
		{
		   strcat( buf, "\n\r" );
		   write_to_buffer( d, buf, 0 );
		   buf[0] = '\0';
		}
		else
		   strcat( buf, " " );
	    }
	    strcat( buf, class_table[iClass]->who_name );
          }
        }
	strcat( buf, "]\n\r: " );
	write_to_buffer( d, buf, 0 );
	d->connected = CON_GET_NEW_CLASS;
	break;

    case CON_GET_NEW_CLASS:
	argument = one_argument(argument, arg);

        if (!str_cmp(arg, "help"))
        {
        
	for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ )
	{
	  if ( class_table[iClass]->who_name &&
	       class_table[iClass]->who_name[0] != '\0' )
	  {
            if (toupper(argument[0])==toupper(class_table[iClass]->who_name[0])
	    &&   !str_prefix( argument, class_table[iClass]->who_name ) )
	    {
	      do_help(ch, argument);
	      write_to_buffer( d, "Please choose a class: ", 0 );
              return;
	    }
	  }
        }  
	write_to_buffer( d, "No such help topic.  Please choose a class: ", 0 );
	return;
	}

	for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ )
	{
	  if ( class_table[iClass]->who_name &&
	       class_table[iClass]->who_name[0] != '\0' )
	  {
	    if ( toupper(arg[0]) == toupper(class_table[iClass]->who_name[0])
	    &&   !str_prefix( arg, class_table[iClass]->who_name ) )
	    {
		ch->class =  iClass;
		break;
	    }
	  }
	}

    if ( iClass == MAX_PC_CLASS
    ||  !class_table[iClass]->who_name || class_table[iClass]->who_name[0] == '\0'
    ||   xIS_SET(class_table[iClass]->race_restriction, 1 << ch->race )
    ||   !str_cmp(class_table[iClass]->who_name,"unused")
       )
	{
	    write_to_buffer( d,
		"That's not a class.\n\rWhat IS your class? ", 0 );
	    return;
	}


        if ( check_bans( ch, BAN_CLASS ) )
        {
         write_to_buffer (d,
             "That class is not currently avaiable.\n\rWhat IS your class? ",0);
         return;
        }

	write_to_buffer( d, "\n\rWould you like RIP, ANSI or no graphic/color support, (R/A/N)? ", 0 );
	d->connected = CON_GET_WANT_RIPANSI;
        break;

----------------------------------------------------------------
In tables.c 
================================================================

----------------------------------------------------------------
in bool load_class_file( char *fname )
----------------------------------------------------------------

Find this:
    /* Setup defaults for additions to class structure */
    class->attr_second = 0;
    class->attr_deficient = 0;
    xCLEAR_BITS(class->affected);

and ADD:
    xCLEAR_BITS(class->race_restriction);

Find this:
	    KEY( "Resist",	class->resist,		fread_number( fp ) );
and ADD above
	    KEY( "Races",	class->race_restriction,        fread_bitvector( fp )	);

----------------------------------------------------------------
in void write_class_file( int cl )
----------------------------------------------------------------
Find this:
    fprintf( fpout, "AttrSecond   %d\n",	class->attr_second	);
    fprintf( fpout, "AttrDeficient   %d\n",	class->attr_deficient	);

and ADD:
    fprintf( fpout, "Races       %s\n",		print_bitvector(&class->race_restriction ));

----------------------------------------------------------------
In void write_race_file( int ra )
----------------------------------------------------------------
Find this:
    fprintf( fpout, "Classes     %d\n",		race->class_restriction );

and COMMENT it out /* */

----------------------------------------------------------------
In bool load_race_file( char *fname )
----------------------------------------------------------------

Find this:
	    KEY( "Classes",	race->class_restriction,		fread_number( fp )	);

and COMMENT it out /* */


================================================================
================================================================
Now you just need to Recompile, and edit all your race and class files. 
I've included modified race and class files from stock smaug 1.4a