#include <ctype.h> #include <sys/types.h> #include <stdio.h> #include <syslog.h> #include "define.h" #include "struct.h" void use_start_table ( char_data*, int ); /* * CHARACTER CREATION ROUTINES */ void wrong_choice( link_data* link ) { send( link, "\n\rWhat you entered was unintelligible. Please press\ return and then select\n\rone of the choices given between the left\ and right brackets.\n\r" ); press_return( link ); return; } /* * NAME */ bool check_parse_name( link_data* link, char* name ) { species_data* species; char* letter; int length = strlen( name ); int capitals = 0; /* ALPHA AND PUNCTUATION */ if( ispunct( *name ) || ispunct( name[length] ) ) { send( link, "\n\rThe first and last letters of a name may not be\ punctuation to stop the\n\rsegment of the population who insist on the\ name --Starbright--.\n\r" ); return FALSE; } for( letter = name; *letter != '\0'; letter++ ) { if( isdigit( *letter ) ) { send( link, "\n\rNames are not allowed to contain numbers.\n\r" ); return FALSE; } if( ispunct( *letter ) && *letter != '-' && *letter != '\'' ) { send( link, "\n\rNames are not allowed to contain punctuation other\ than dashes and\n\rapostrophes.\n\r" ); return FALSE; } if( isupper( *letter ) && ++capitals > 2 ) { send( link, "\n\rNames can contain at most 3 capital letters.\n\r" ); return FALSE; } } if( length < 3 || length > 12 ) { send( link, "Names must be greater than 2 and less than 13 letters.\n\r" ); return FALSE; } /* WORDS USED IN GAME */ for( int i = 0; i < MAX_SPECIES; i++ ) { if( ( species = species_list[i] ) == NULL ) continue; if( is_name( name, species->descr->name ) ) { send( link, "\n\rThat is the name of monster in the game and thus\ unallowed.\n\r" ); return FALSE; } } if( find_pfile_exact( name ) != NULL ) { send( link, "\n\rA player already exists with that name.\n\r" ); return FALSE; } if( find_pfile( name ) != NULL || find_pfile_substring( name ) != NULL ) { help_link( link, "Name_Similiar" ); return FALSE; } if( pntr_search( badname_array, max_badname, name ) >= 0 ) { help_link( link, "Bad_Name" ); return FALSE; } return TRUE; } void nanny_new_name( link_data* link, char* argument ) { player_data* ch; pfile_data* pfile; if( no_input( link, argument ) ) return; *argument = toupper( *argument ); if( !check_parse_name( link, argument ) ) { send( link, "\n\rSelect another name: " ); return; } pfile = new pfile_data( argument ); ch = new player_data( pfile->name ); ch->pcdata->pfile = pfile; ch->link = link; link->player = ch; link->character = ch; link->connected = CON_GET_NEW_PASSWORD; link->pfile = pfile; modify_pfile( ch ); help_link( link, "Login_password" ); send( link, "Password: " ); } void nanny_new_password( link_data* link, char* argument ) { char_data* ch = link->character; char* p; if( strlen( argument ) < 5 ) { send( link, "\n\rPassword must be at least five characters long.\n\rPassword: " ); return; } for( p = argument; *p != '\0'; p++ ) { if( *p == '~' ) { send( link, "\n\rNew password not acceptable, try again.\n\rPassword: " ); return; } } free_string( ch->pcdata->pfile->pwd, MEM_PLAYER ); ch->pcdata->pfile->pwd = alloc_string( argument, MEM_PLAYER ); send( link, "Please retype password: " ); link->connected = CON_CONFIRM_PASSWORD; } void nanny_confirm_password( link_data* link, char* argument ) { char_data* ch = link->character; send( link, "\n\r" ); if( strcmp( argument, ch->pcdata->pfile->pwd ) ) { send( link, "Passwords don't match.\n\rRetype password: " ); link->connected = CON_GET_NEW_PASSWORD; return; } help_link( link, "Login.Display" ); send( link, "Display type? [ None Ansi VT52 ]: " ); link->connected = CON_SET_TERM; return; } /* * TERMINAL TYPE */ void nanny_set_term( link_data* link, char* argument ) { char_data* ch = link->character; int i; switch( toupper( *argument ) ) { case 'V' : ch->pcdata->terminal = TERM_VT100; break; case 'A' : ch->pcdata->terminal = TERM_ANSI; break; default : ch->pcdata->terminal = TERM_DUMB; break; } if( ch->pcdata->terminal != TERM_DUMB ) for( i = 0; i < MAX_COLOR; i++ ) ch->pcdata->color[i] = term_table[ ch->pcdata->terminal ].defaults[i]; setup_screen( ch ); help_link( link, "Gamedesc_1" ); press_return( link ); link->connected = CON_READ_GAME_RULES; } /* * GAME RULES */ void nanny_show_rules( link_data* link, char* ) { char_data* ch = link->character; clear_screen( ch ); do_help( ch, "GAMEDESC_2" ); send( link, "\r\nDo you wish to continue (Y/N)? " ); link->connected = CON_AGREE_GAME_RULES; return; } void nanny_agree_rules( link_data* link, char* argument ) { if( toupper( *argument ) == 'N' ) { send( link, "Good bye.\r\n" ); close_socket( link ); return; } if( toupper( *argument ) != 'Y' ) { send( link, "Please answer Y or N. " ); return; } nanny_help_sex( link, "" ); return; } /* * SEX */ void nanny_help_sex( link_data* link, char* ) { char_data* ch = link->character; clear_screen( ch ); do_help( ch, "login_sex" ); send( link, "\n\rPlease enter your sex [Male Female]: " ); link->connected = CON_GET_NEW_SEX; return; } void nanny_sex( link_data* link, char* argument ) { char_data* ch = link->character; switch( toupper( *argument ) ) { case 'M': ch->sex = SEX_MALE; break; case 'F': ch->sex = SEX_FEMALE; break; default: wrong_choice( link ); link->connected = CON_HELP_SEX; return; } nanny_help_class( link, argument ); return; } void nanny_help_class( link_data* link, char* ) { char tmp [ TWO_LINES ]; int i; char_data* ch = link->character; clear_screen( ch ); do_help( ch, "login_classes" ); strcpy( tmp, "\n\rSelect a class [" ); for( i = 0; i < MAX_CLSS; i++ ) { if( clss_table[i].open ) { if( i > 0 ) strcat( tmp, " " ); strcat( tmp, clss_table[i].abbrev ); } } strcat( tmp, "]: " ); send( link, tmp ); link->connected = CON_GET_NEW_CLSS; return; } void nanny_class( link_data* link, char* argument ) { char_data* ch = link->character; int i; bool help = FALSE; link->connected = CON_HELP_CLSS; if( *argument == '\0' ) { wrong_choice( link ); return; } if( *argument == '?' ) { argument++; help = TRUE; } for( i = 0; i < MAX_CLSS; i++ ) if( clss_table[i].open && fmatches( argument, clss_table[i].name ) ) break; if( help ) { clear_screen( ch ); help_link( link, clss_table[i].name ); press_return( link ); return; } if( i == MAX_CLSS ) { wrong_choice( link ); return; } ch->pcdata->clss = i; nanny_help_race( link, argument ); return; } /* * RACES */ bool allowed_race( char_data* ch, int race ) { int i; if( !plyr_race_table[race].open ) return FALSE; for( i = 0; i < MAX_ENTRY_ALIGNMENT; i++ ) if( is_set( &clss_table[ ch->pcdata->clss ].alignments, i ) && is_set( &plyr_race_table[ race ].alignments, i ) ) return TRUE; return FALSE; } void nanny_help_race( link_data* link, char* ) { char tmp [ TWO_LINES ]; char_data* ch = link->character; bool first = TRUE; int i; clear_screen( ch ); do_help( ch, "login_races" ); strcpy( tmp, "\n\rSelect a race [" ); for( i = 0; i < MAX_PLYR_RACE; i++ ) { if( allowed_race( ch, i ) ) { if( !first ) strcat( tmp, " " ); strcat( tmp, race_table[i].abbrev ); first = FALSE; } } strcat( tmp, "]: " ); send( link, tmp ); link->connected = CON_GET_NEW_RACE; return; } void nanny_race( link_data* link, char* argument ) { char_data* ch = link->character; int i; bool help = FALSE; link->connected = CON_HELP_RACE; if( *argument == '?' ) { argument++; help = TRUE; } if( *argument == '\0' ) { wrong_choice( link ); return; } for( i = 0; i < MAX_PLYR_RACE; i++ ) if( plyr_race_table[i].open && ( fmatches( argument, race_table[i].name ) || fmatches( argument, race_table[i].abbrev ) ) ) break; if( i == MAX_PLYR_RACE ) { wrong_choice( link ); return; } if( help ) { clear_screen( ch ); help_link( link, plyr_race_table[i].plural ); press_return( link ); return; } ch->shdata->race = i; ch->pcdata->speaking = LANG_HUMANIC+i; ch->shdata->skill[ LANG_HUMANIC+i ] = 10; ch->shdata->skill[ LANG_PRIMAL ] = 10; link->connected = CON_DECIDE_STATS; nanny_stats( link, "" ); } /* * STATS */ void nanny_stats( link_data* link, char* argument ) { char_data* ch = link->character; share_data* shdata = ch->shdata; int* bonus = plyr_race_table[ch->shdata->race].stat_bonus; int points; int number; int i,j; char c; int *stat[] = { &shdata->strength, &shdata->intelligence, &shdata->wisdom, &shdata->dexterity, &shdata->constitution }; char letter[] = { 'S', 'I', 'W', 'D', 'C' }; char *name[] = { "Strength", "Intelligence", "Wisdom", "Dexterity", "Constitution" }; if( !strcasecmp( "done", argument ) ) { nanny_help_alignment( link, "" ); return; } clear_screen( ch ); if( strlen( argument ) < 2 || ( strlen( argument ) < 3 && isdigit( argument[1] ) ) ) { do_help( ch, "login_stats" ); send( ch, "\n\r" ); } else { for( j = 0, points = 500; j < 5; j++ ) points -= (*stat[j]-bonus[j])*(*stat[j]-bonus[j]+1)/2; if( isdigit( argument[1] ) ) { c = toupper( argument[2] ); number = argument[1]-'0'; } else { c = toupper( argument[1] ); number = 1; } for( i = 0; i < 5; i++ ) if( c == letter[ i ] ) break; if( i != 5 ) { switch( argument[0] ) { case '+' : if( *stat[i]+number > 18+bonus[ i ] ) send( link, "\n\rYou can not raise a stat over its racial maximum.\n\r" ); else *stat[i] += number; break; case '-' : if( *stat[i]-number < 3 ) send( link, "\n\rYou can not lower a stat below 3.\n\r" ); else *stat[i] -= number; break; default: i = 5; break; } } if( i == 5 ) { do_help( ch, "login_stats" ); send( ch, "\n\r" ); } else { for( j = 0, points = 500; j < 5; j++ ) points -= (*stat[j]-bonus[j])*(*stat[j]-bonus[j]+1)/2; if( points < 0 ) { send( link, "\n\rYou don't have enough points for that.\n\r" ); *stat[i] -= number; } } } for( j = 0, points = 500; j < 5; j++ ) points -= (*stat[j]-bonus[j])*(*stat[j]-bonus[j]+1)/2; send( link, "Points Left: %d\n\r\n\r", points ); send( link, "Ability Character Racial Max Cost to inc.\n\r" ); send( link, "------- --------- ---------- ------------\n\r" ); for( i = 0; i < 5; i++ ) { send( link, "%-15s%10d%13d%15d\n\r", name[i], *stat[i], 18+bonus[i],*stat[i]-bonus[i]+1 ); } send( link, "\n\rEnter choice: " ); } /* * ALIGNMENT */ bool allowed_alignment( char_data* ch, int align ) { return( is_set( &clss_table[ ch->pcdata->clss ].alignments, align ) && is_set( &plyr_race_table[ ch->shdata->race ].alignments, align ) ); } void nanny_help_alignment( link_data* link, char* ) { char tmp [ TWO_LINES ]; char_data* ch = link->character; bool first = TRUE; int i; clear_screen( ch ); do_help( ch, "login_alignment" ); strcpy( tmp, "\n\rEnter an alignment [" ); for( i = 0; i < MAX_ENTRY_ALIGNMENT; i++ ) { if( allowed_alignment( ch, i ) ) { if( !first ) strcat( tmp, " " ); strcat( tmp, alignment_table[i].abbrev ); first = FALSE; } } strcat( tmp, "]: " ); send( link, tmp ); link->connected = CON_GET_NEW_ALIGNMENT; } void nanny_alignment( link_data* link, char* argument ) { char_data* ch = link->player; int i; const char* word = empty_string; bool help = FALSE; link->connected = CON_HELP_ALIGNMENT; if( *argument == '?' ) { argument++; help = TRUE; } if( *argument == '\0' ) { wrong_choice( link ); return; } for( i = 0; i < MAX_ENTRY_ALIGNMENT; i++ ) if( !strcasecmp( argument, alignment_table[i].abbrev ) || fmatches( argument, alignment_table[i].name, 3 ) ) break; if( i == MAX_ENTRY_ALIGNMENT ) { wrong_choice( link ); return; } if( help ) { clear_screen( ch ); help_link( link, alignment_table[i].name ); press_return( link ); return; } if( !is_set( &clss_table[ ch->pcdata->clss ].alignments, i ) ) { word = clss_table[ ch->pcdata->clss ].name; } else if( !is_set( &plyr_race_table[ ch->shdata->race ].alignments, i ) ) { word = race_table[ ch->shdata->race ].name; } else { ch->shdata->alignment = i; clear_screen( ch ); help_link( link, "Introduction" ); press_return( link ); link->connected = CON_READ_IMOTD; return; } send( link, "\n\rA%c %s would not choose to be %s.\n\r", isvowel( *word ), word, alignment_table[i].name ); press_return( link ); } /* * INITIALIZE NEW PLAYER */ void new_player( player_data* ch ) { char tmp [ MAX_STRING_LENGTH ]; int clss = ch->pcdata->clss; int i; ch->shdata->level = 1; ch->exp = 0; ch->pcdata->practice = 25; ch->base_hit = 20; ch->base_mana = 50; ch->base_move = 100; ch->base_age = plyr_race_table[ ch->shdata->race ].start_age; update_max_hit( ch ); update_max_mana( ch ); ch->hit = ch->max_hit; ch->mana = ch->max_mana; update_max_move( ch ); ch->move = ch->max_move; /* OPTIONS */ set_bit( ch->pcdata->pfile->flags, PLR_PROMPT ); set_bit( ch->pcdata->pfile->flags, PLR_GOSSIP ); set_bit( ch->pcdata->pfile->flags, PLR_SAY_REPEAT ); set_bit( ch->pcdata->pfile->flags, PLR_AUTO_EXIT ); set_bit( ch->pcdata->pfile->flags, PLR_SAFE_KILL ); set_bit( ch->pcdata->pfile->flags, PLR_PORTAL ); set_bit( ch->pcdata->pfile->flags, PLR_IDLE ); set_bit( ch->pcdata->pfile->flags, PLR_INFO ); set_bit( ch->pcdata->pfile->flags, PLR_LANG_ID ); set_bit( ch->pcdata->pfile->flags, PLR_OOC ); set_level( &ch->pcdata->pfile->settings, SET_ROOM_INFO, 3 ); set_level( &ch->pcdata->pfile->settings, SET_AUTOLOOT, 1 ); /* IFLAGS */ for( i = 0; i < MAX_IFLAG; i++ ) set_level( ch->iflag, i, 3 ); set_level( ch->iflag, IFLAG_AUCTION, 1 ); set_level( ch->iflag, IFLAG_LOGINS, 1 ); set_level( ch->iflag, MAX_IFLAG+NOTE_ANNOUNCEMENTS, 1 ); set_level( ch->iflag, MAX_IFLAG+NOTE_GENERAL, 1 ); /* MESSAGES */ remove_bit( &ch->pcdata->message, MSG_MAX_MOVE ); modify_pfile( ch ); ch->pcdata->pfile->account = ch->link->account; free_string( ch->descr->singular, MEM_DESCR ); sprintf( tmp, "%s %s", race_table[ ch->shdata->race ].name, clss_table[ clss ].name ); ch->descr->singular = alloc_string( tmp, MEM_DESCR ); free_string( ch->descr->long_s, MEM_DESCR ); sprintf( tmp, "%s is standing here.", ch->descr->singular ); tmp[0] = toupper( tmp[0] ); ch->descr->long_s = alloc_string( tmp, MEM_DESCR ); free_string( ch->pcdata->title, MEM_PLAYER ); sprintf( tmp, " the %s %s", race_table[ ch->shdata->race ].name, clss_table[ clss ].name ); ch->pcdata->title = alloc_string( tmp, MEM_PLAYER ); free_string( ch->descr->keywords, MEM_DESCR ); sprintf( tmp, "%s %s", race_table[ch->shdata->race].name, clss_table[clss].name ); ch->descr->keywords = alloc_string( tmp, MEM_DESCR ); /* SET STANDARD EQUIP/SKILLS */ use_start_table( ch, 0 ); use_start_table( ch, clss+1 ); use_start_table( ch, MAX_CLSS+ch->shdata->race+1 ); ch->To( get_temple( ch ) ); } void use_start_table( char_data* ch, int entry ) { obj_clss_data* index; obj_data* obj; int skill; for( int i = 0; i < 5; i++ ) if( ( skill = starting_table[entry].skill[i] ) >= 0 ) ch->shdata->skill[skill] = starting_table[entry].level[i]; for( int i = 0; i < 5; i++ ) if( ( index = get_obj_index( starting_table[entry].object[2*i] ) ) != NULL ) { obj = create( index, starting_table[ entry ].object[ 2*i+1 ] ); obj->To( ch ); switch( obj->pIndexData->item_type ) { case ITEM_ARMOR : case ITEM_WEAPON : needremove( obj, ch, NULL ); } } } bool newbie_abuse( char_data* ch ) { if( ch->species != NULL || ch->played+current_time-ch->logon > 50 ) return FALSE; send( ch, "To stop abuse you cannot drop or give anything for the\ first 5 minutes\n\rof play. To get rid of an item use junk.\n\r" ); return TRUE; }