/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( * * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~* * Tricops and Fireblade | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Low-level communication module * ****************************************************************************/ #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <ctype.h> #include <errno.h> #include <stdio.h> #include <time.h> #include <string.h> #include <fcntl.h> #include <signal.h> #include <stdarg.h> #include "mud.h" #include "md5.h" #ifdef USE_IMC #include "imc.h" #include "icec.h" #endif /* * Socket and TCP/IP stuff. */ #ifdef WIN32 #include <io.h> #undef EINTR #undef EMFILE #define EINTR WSAEINTR #define EMFILE WSAEMFILE #define EWOULDBLOCK WSAEWOULDBLOCK #define MAXHOSTNAMELEN 32 #define TELOPT_ECHO '\x01' #define GA '\xF9' #define SB '\xFA' #define WILL '\xFB' #define WONT '\xFC' #define DO '\xFD' #define DONT '\xFE' #define IAC '\xFF' void bailout( void ); void shutdown_checkpoint( void ); #else #include <sys/socket.h> #include <netinet/in.h> // #include <netinet/in_systm.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <arpa/telnet.h> #include <netdb.h> #define closesocket close #endif #ifdef sun int gethostname( char *name, int namelen ); #endif const char echo_off_str[] = { IAC, WILL, TELOPT_ECHO, '\0' }; const char echo_on_str[] = { IAC, WONT, TELOPT_ECHO, '\0' }; const char go_ahead_str[] = { IAC, GA, '\0' }; #ifdef MCCP #define TELOPT_COMPRESS 85 #define TELOPT_COMPRESS2 86 const char eor_on_str[] = { IAC, WILL, TELOPT_EOR, '\0' }; const char compress_on_str[] = { IAC, WILL, TELOPT_COMPRESS2, '\0' }; const char compress2_on_str[] = { IAC, WILL, TELOPT_COMPRESS2, '\0' }; bool compressStart args( ( DESCRIPTOR_DATA * d, unsigned char telopt ) ); bool compressEnd args( ( DESCRIPTOR_DATA * d ) ); #endif void auth_maxdesc args( ( int *md, fd_set * ins, fd_set * outs, fd_set * excs ) ); void auth_check args( ( fd_set * ins, fd_set * outs, fd_set * excs ) ); void set_auth args( ( DESCRIPTOR_DATA * d ) ); void kill_auth args( ( DESCRIPTOR_DATA * d ) ); //void save_sysdata args( ( SYSTEM_DATA sys ) ); /* * External Functions */ void shutdown_mud args( ( char *reason ) ); void save_auth_list args( ( void ) ); /* * Global variables. */ IMMORTAL_HOST *immortal_host_start; /* Start of Immortal legal domains */ IMMORTAL_HOST *immortal_host_end; /* End of Immortal legal domains */ DESCRIPTOR_DATA *first_descriptor; /* First descriptor */ DESCRIPTOR_DATA *last_descriptor; /* Last descriptor */ DESCRIPTOR_DATA *d_next; /* Next descriptor in loop */ int num_descriptors; FILE *fpReserve; /* Reserved file handle */ bool mud_down; /* Shutdown */ bool service_shut_down; /* Shutdown by operator closing down service */ bool wizlock; int locklev; time_t boot_time; HOUR_MIN_SEC set_boot_time_struct; HOUR_MIN_SEC *set_boot_time; struct tm *new_boot_time; struct tm new_boot_struct; char str_boot_time[MAX_INPUT_LENGTH]; char lastplayercmd[MAX_INPUT_LENGTH * 2]; time_t current_time; /* Time of this pulse */ int control; /* Controlling descriptor */ int newdesc; /* New descriptor */ fd_set in_set; /* Set of desc's for reading */ fd_set out_set; /* Set of desc's for writing */ fd_set exc_set; /* Set of desc's with errors */ int maxdesc; char *alarm_section = "(unknown)"; /* * OS-dependent local functions. */ void game_loop args( ( ) ); int init_socket args( ( int port ) ); void new_descriptor args( ( int new_desc ) ); bool read_from_descriptor args( ( DESCRIPTOR_DATA * d ) ); bool write_to_descriptor args( ( int desc, char *txt, int length ) ); /* * Other local functions (OS-independent). */ bool check_parse_name args( ( char *name, bool newchar ) ); bool check_reconnect args( ( DESCRIPTOR_DATA * d, char *name, bool fConn ) ); bool check_playing args( ( DESCRIPTOR_DATA * d, char *name, bool kick ) ); int main args( ( int argc, char **argv ) ); void nanny args( ( DESCRIPTOR_DATA * d, char *argument ) ); bool flush_buffer args( ( DESCRIPTOR_DATA * d, bool fPrompt ) ); void read_from_buffer args( ( DESCRIPTOR_DATA * d ) ); void stop_idling args( ( CHAR_DATA * ch ) ); void free_desc args( ( DESCRIPTOR_DATA * d ) ); void display_prompt args( ( DESCRIPTOR_DATA * d ) ); int make_color_sequence args( ( const char *col, char *buf, DESCRIPTOR_DATA * d ) ); void set_pager_input args( ( DESCRIPTOR_DATA * d, char *argument ) ); bool pager_output args( ( DESCRIPTOR_DATA * d ) ); void mail_count args( ( CHAR_DATA * ch ) ); void tax_player args( ( CHAR_DATA * ch ) ); void mccp_interest args( ( CHAR_DATA * ch ) ); bool check_total_ip args( ( DESCRIPTOR_DATA * dnew ) ); int port; char capitalizeString( char *text ) { int i; if( text[0] == '\0' ) return *text; text[0] = UPPER( text[0] ); for( i = 1; text[i] != '\0'; i++ ) { text[i] = LOWER( text[i] ); } return *text; } /* ==================== send color to a desc -Nopey ==================== */ void send_to_desc_color( const char *txt, DESCRIPTOR_DATA * d ) { char *colstr; const char *prevstr = txt; char colbuf[20]; int ln; if( !d ) { bug( "send_to_desc_color: NULL *d" ); return; } if( !txt || !d->descriptor ) return; while( ( colstr = strpbrk( prevstr, "&^}" ) ) != NULL ) { if( colstr > prevstr ) write_to_buffer( d, prevstr, ( colstr - prevstr ) ); ln = make_color_sequence( colstr, colbuf, d ); if( ln < 0 ) { prevstr = colstr + 1; break; } else if( ln > 0 ) write_to_buffer( d, colbuf, ln ); prevstr = colstr + 2; } if( *prevstr ) write_to_buffer( d, prevstr, 0 ); return; } #ifdef WIN32 int mainthread( int argc, char **argv ) #else int main( int argc, char **argv ) #endif { struct timeval now_time; char hostn[128]; bool fCopyOver = !TRUE; /* * Memory debugging if needed. */ #if defined(MALLOC_DEBUG) malloc_debug( 2 ); #endif DONT_UPPER = FALSE; num_descriptors = 0; first_descriptor = NULL; last_descriptor = NULL; sysdata.NO_NAME_RESOLVING = TRUE; sysdata.WAIT_FOR_AUTH = TRUE; /* * Init time. */ gettimeofday( &now_time, NULL ); current_time = ( time_t ) now_time.tv_sec; /* gettimeofday( &boot_time, NULL); okay, so it's kludgy, sue me :) */ boot_time = time( 0 ); /* <-- I think this is what you wanted */ strcpy( str_boot_time, ctime( ¤t_time ) ); /* * Init boot time. */ set_boot_time = &set_boot_time_struct; set_boot_time->manual = 0; new_boot_time = update_time( localtime( ¤t_time ) ); /* * Copies *new_boot_time to new_boot_struct, and then points * new_boot_time to new_boot_struct again. -- Alty */ new_boot_struct = *new_boot_time; new_boot_time = &new_boot_struct; if( new_boot_time->tm_hour > 3 ) new_boot_time->tm_mday += 1; new_boot_time->tm_sec = 0; new_boot_time->tm_min = 0; new_boot_time->tm_hour = 4; /* * Update new_boot_time (due to day increment) */ new_boot_time = update_time( new_boot_time ); new_boot_struct = *new_boot_time; new_boot_time = &new_boot_struct; /* * Bug fix submitted by Gabe Yoder */ new_boot_time_t = mktime( new_boot_time ); reboot_check( mktime( new_boot_time ) ); /* * Set reboot time string for do_time */ get_reboot_string( ); init_pfile_scan_time( ); /* Pfile autocleanup initializer - Samson 5-8-99 */ /* * Reserve two channels for our use. */ if( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL ) { perror( NULL_FILE ); exit( 1 ); } if( ( fpLOG = fopen( NULL_FILE, "r" ) ) == NULL ) { perror( NULL_FILE ); exit( 1 ); } /* * Get the port number. */ port = 3000; if( argc > 1 ) { if( !is_number( argv[1] ) ) { fprintf( stderr, "Usage: %s [port #]\n", argv[0] ); exit( 1 ); } else if( ( port = atoi( argv[1] ) ) <= 1024 ) { fprintf( stderr, "Port number must be above 1024.\n" ); exit( 1 ); } if( argv[2] && argv[2][0] ) { fCopyOver = TRUE; control = atoi( argv[3] ); } else fCopyOver = FALSE; } /* * Run the game. */ #ifdef WIN32 { /* * Initialise Windows sockets library */ unsigned short wVersionRequested = MAKEWORD( 1, 1 ); WSADATA wsadata; int err; /* * Need to include library: wsock32.lib for Windows Sockets */ err = WSAStartup( wVersionRequested, &wsadata ); if( err ) { fprintf( stderr, "Error %i on WSAStartup\n", err ); exit( 1 ); } /* * standard termination signals */ signal( SIGINT, ( void * )bailout ); signal( SIGTERM, ( void * )bailout ); } #endif /* WIN32 */ /* Disabled -Goku 10.14.03 log_string("Booting Chat Robot"); startchat(CHAT_FILE); */ log_string( "Booting Database" ); boot_db( fCopyOver ); log_string( "Initializing socket" ); if( !fCopyOver ) /* We have already the port if copyover'ed */ { control = init_socket( port ); } #ifdef OLD_IMC /* * Be sure to change RoD to your mud's name! */ if( port == 3000 ) imc_startup( "RoD", port + 5, "imc/" ); else imc_startup( "RoDBLD", port + 5, "imc/" ); #else #ifdef USE_IMC imc_startup( "imc/" ); icec_init( ); #endif #endif /* * I don't know how well this will work on an unnamed machine as I don't * have one handy, and the man pages are ever-so-helpful.. -- Alty */ if( gethostname( hostn, sizeof( hostn ) ) < 0 ) { perror( "main: gethostname" ); strcpy( hostn, "unresolved" ); } sprintf( log_buf, "%s ready at address %s on port %d.", sysdata.mud_name, hostn, port ); /* sprintf( log_buf, "Realms of Despair ready at address %s on port %d.", hostn, port ); */ log_string( log_buf ); game_loop( ); #ifdef USE_IMC imc_shutdown( ); /* shut down IMC */ #endif closesocket( control ); #ifdef WIN32 if( service_shut_down ) { CHAR_DATA *vch; /* * Save all characters before booting. */ for( vch = first_char; vch; vch = vch->next ) if( !IS_NPC( vch ) ) { shutdown_checkpoint( ); save_char_obj( vch ); } } /* * Save MUD time */ save_timedata( ); /* * Shut down Windows sockets */ WSACleanup( ); /* clean up */ kill_timer( ); /* stop timer thread */ #endif /* * That's all, folks. */ log_string( "Normal termination of game." ); exit( 0 ); return 0; } int init_socket( int port ) { char hostname[64]; struct sockaddr_in sa; int x = 1; int fd; gethostname( hostname, sizeof( hostname ) ); if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { perror( "Init_socket: socket" ); exit( 1 ); } if( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, ( void * )&x, sizeof( x ) ) < 0 ) { perror( "Init_socket: SO_REUSEADDR" ); closesocket( fd ); exit( 1 ); } #if defined(SO_DONTLINGER) && !defined(SYSV) { struct linger ld; ld.l_onoff = 1; ld.l_linger = 1000; if( setsockopt( fd, SOL_SOCKET, SO_DONTLINGER, ( void * )&ld, sizeof( ld ) ) < 0 ) { perror( "Init_socket: SO_DONTLINGER" ); closesocket( fd ); exit( 1 ); } } #endif memset( &sa, '\0', sizeof( sa ) ); sa.sin_family = AF_INET; sa.sin_port = htons( port ); if( bind( fd, ( struct sockaddr * )&sa, sizeof( sa ) ) == -1 ) { perror( "Init_socket: bind" ); closesocket( fd ); exit( 1 ); } if( listen( fd, 50 ) < 0 ) { perror( "Init_socket: listen" ); closesocket( fd ); exit( 1 ); } return fd; } static void SegVio( ) { CHAR_DATA *ch; for( ch = first_char; ch; ch = ch->next ) { if( !IS_NPC( ch ) ) save_char_obj( ch ); } if( fork( ) == 0 ) abort( ); exit( 1 ); /* char buf[MAX_STRING_LENGTH]; log_string( "SEGMENTATION VIOLATION" ); log_string( lastplayercmd ); for ( ch = first_char; ch; ch = ch->next ) { sprintf( buf, "%cPC: %-20s room: %d", IS_NPC(ch) ? 'N' : ' ', ch->name, ch->in_room->vnum ); log_string( buf ); } exit(0); */ } static void SigTerm( int signum ) { CHAR_DATA *vch; char buf[MAX_STRING_LENGTH]; sprintf( log_buf, "&RATTENTION!! Message from game server: &YEmergency shutdown called.\a" ); echo_to_all( AT_RED, log_buf, ECHOTAR_ALL ); sprintf( log_buf, "Executing emergency shutdown proceedure." ); echo_to_all( AT_YELLOW, log_buf, ECHOTAR_ALL ); log_string( "Message from server: Executing emergency shutdown proceedure." ); shutdown_mud( log_buf ); strcat( buf, "\n\r" ); if( auction->item ) do_auction( supermob, "stop" ); log_string( "Saving players...." ); for( vch = first_char; vch; vch = vch->next ) { if( !IS_NPC( vch ) ) { save_char_obj( vch ); sprintf( log_buf, "%s saved.", vch->name ); log_string( log_buf ); if( vch->desc ) { write_to_descriptor( vch->desc->descriptor, buf, 0 ); write_to_descriptor( vch->desc->descriptor, "You have been saved to disk.\n\r", 0 ); } } } /* * Save morphs so can sort later. --Shaddai */ if( sysdata.morph_opt ) save_morphs( ); fflush( stderr ); /* make sure strerr is flushed */ close( control ); /* * Extra ports disabled - Samson 12-1-98 : uncomment * this section if you still use them * close( control2 ); * close( conclient); * close( conjava ); */ #ifdef IMC imc_shutdown( ); /* shut down IMC */ #endif #ifdef I3 I3_shutdown( 0 ); #endif log_string( "Emergency shutdown complete." ); /* * Using exit here instead of mud_down because the * thing sometimes failed to kill when asked!! */ exit( 0 ); } /* * LAG alarm! -Thoric */ void caught_alarm( ) { char buf[MAX_STRING_LENGTH]; sprintf( buf, "ALARM CLOCK! In section %s", alarm_section ); bug( buf ); strcpy( buf, "Alas, the hideous malevolent entity known only as 'Lag' rises once more!\n\r" ); echo_to_all( AT_IMMORT, buf, ECHOTAR_ALL ); if( newdesc ) { FD_CLR( newdesc, &in_set ); FD_CLR( newdesc, &out_set ); FD_CLR( newdesc, &exc_set ); log_string( "clearing newdesc" ); } } bool check_bad_desc( int desc ) { if( FD_ISSET( desc, &exc_set ) ) { FD_CLR( desc, &in_set ); FD_CLR( desc, &out_set ); log_string( "Bad FD caught and disposed." ); return TRUE; } return FALSE; } /* * Determine whether this player is to be watched --Gorog */ bool chk_watch( sh_int player_level, char *player_name, char *player_site ) { WATCH_DATA *pw; /* char buf[MAX_INPUT_LENGTH]; sprintf( buf, "che_watch entry: plev=%d pname=%s psite=%s", player_level, player_name, player_site); log_string(buf); */ if( !first_watch ) return FALSE; for( pw = first_watch; pw; pw = pw->next ) { if( pw->target_name ) { if( !str_cmp( pw->target_name, player_name ) && player_level < pw->imm_level ) return TRUE; } else if( pw->player_site ) { if( !str_prefix( pw->player_site, player_site ) && player_level < pw->imm_level ) return TRUE; } } return FALSE; } void accept_new( int ctrl ) { static struct timeval null_time; DESCRIPTOR_DATA *d; /* * int maxdesc; Moved up for use with id.c as extern */ #if defined(MALLOC_DEBUG) if( malloc_verify( ) != 1 ) abort( ); #endif /* * Poll all active descriptors. */ FD_ZERO( &in_set ); FD_ZERO( &out_set ); FD_ZERO( &exc_set ); FD_SET( ctrl, &in_set ); maxdesc = ctrl; newdesc = 0; for( d = first_descriptor; d; d = d->next ) { maxdesc = UMAX( maxdesc, d->descriptor ); FD_SET( d->descriptor, &in_set ); FD_SET( d->descriptor, &out_set ); FD_SET( d->descriptor, &exc_set ); if( d->ifd != -1 && d->ipid != -1 ) { maxdesc = UMAX( maxdesc, d->ifd ); FD_SET( d->ifd, &in_set ); } if( d == last_descriptor ) break; } auth_maxdesc( &maxdesc, &in_set, &out_set, &exc_set ); #ifdef USE_IMC maxdesc = imc_fill_fdsets( maxdesc, &in_set, &out_set, &exc_set ); #endif if( select( maxdesc + 1, &in_set, &out_set, &exc_set, &null_time ) < 0 ) { perror( "accept_new: select: poll" ); exit( 1 ); } if( FD_ISSET( ctrl, &exc_set ) ) { bug( "Exception raise on controlling descriptor %d", ctrl ); FD_CLR( ctrl, &in_set ); FD_CLR( ctrl, &out_set ); } else if( FD_ISSET( ctrl, &in_set ) ) { newdesc = ctrl; new_descriptor( newdesc ); } } void game_loop( ) { struct timeval last_time; char cmdline[MAX_INPUT_LENGTH]; DESCRIPTOR_DATA *d; /* time_t last_check = 0; */ #ifndef WIN32 signal( SIGPIPE, SIG_IGN ); signal( SIGALRM, caught_alarm ); #endif signal( SIGSEGV, SegVio ); signal( SIGTERM, SigTerm ); /* Catch kill signals */ gettimeofday( &last_time, NULL ); current_time = ( time_t ) last_time.tv_sec; /* * Main loop */ while( !mud_down ) { accept_new( control ); auth_check( &in_set, &out_set, &exc_set ); /* * Kick out descriptors with raised exceptions * or have been idle, then check for input. */ for( d = first_descriptor; d; d = d_next ) { if( d == d->next ) { bug( "descriptor_loop: loop found & fixed" ); d->next = NULL; } d_next = d->next; d->idle++; /* make it so a descriptor can idle out */ if( d->idle > 2 ) d->prev_idle = d->idle; if( FD_ISSET( d->descriptor, &exc_set ) ) { FD_CLR( d->descriptor, &in_set ); FD_CLR( d->descriptor, &out_set ); if( d->character && ( d->connected == CON_PLAYING || d->connected == CON_EDITING ) ) save_char_obj( d->character ); d->outtop = 0; close_socket( d, TRUE ); continue; } else if( ( !d->character && d->idle > 480 ) /* 2 mins */ || ( d->connected != CON_PLAYING && d->idle > 1200 ) /* 5 mins */ || d->idle > 28800 ) /* 2 hrs */ { write_to_descriptor( d->descriptor, "Idle timeout... disconnecting.\n\r", 0 ); d->outtop = 0; close_socket( d, TRUE ); continue; } else { d->fcommand = FALSE; if( FD_ISSET( d->descriptor, &in_set ) ) { if( d->character ) { d->character->timer = 0; if( d->character->pcdata && d->character->level < 51 ) { if( d->idle >= 180 ) { if( d->character->pcdata->iIdle < 0 ) d->character->pcdata->iIdle = 0; if( d->character->pcdata->iIdle > 4 ) d->character->pcdata->iIdle = 0; d->character->pcdata->pIdle[d->character->pcdata->iIdle] = ( d->idle / 4 ); d->character->pcdata->bot_warn[0]++; d->character->pcdata->iIdle++; } } } if( d->prev_idle < 2 ) d->psuppress_cmdspam = TRUE; else d->psuppress_cmdspam = FALSE; d->psuppress_channel = 0; d->prev_idle = d->idle; d->idle = 0; if( !read_from_descriptor( d ) ) { FD_CLR( d->descriptor, &out_set ); if( d->character && ( d->connected == CON_PLAYING || d->connected == CON_EDITING ) ) save_char_obj( d->character ); d->outtop = 0; close_socket( d, FALSE ); continue; } } /* * check for input from the dns */ if( ( d->connected == CON_PLAYING || d->character != NULL ) && d->ifd != -1 && FD_ISSET( d->ifd, &in_set ) ) process_dns( d ); if( d->character && d->character->wait > 0 ) { --d->character->wait; continue; } read_from_buffer( d ); if( d->incomm[0] != '\0' ) { d->fcommand = TRUE; stop_idling( d->character ); strcpy( cmdline, d->incomm ); d->incomm[0] = '\0'; if( d->character ) set_cur_char( d->character ); if( d->pagepoint ) set_pager_input( d, cmdline ); else switch ( d->connected ) { default: nanny( d, cmdline ); break; case CON_PLAYING: interpret( d->character, cmdline ); break; case CON_EDITING: edit_buffer( d->character, cmdline ); break; /* case CON_NOTE_TEXT: // handle_con_note_text (d, argument); edit_buffer( d->character, cmdline ); break; */ } } } if( d == last_descriptor ) break; } #ifdef USE_IMC /* * kick IMC */ imc_idle_select( &in_set, &out_set, &exc_set, current_time ); #endif /* * Autonomous game motion. */ update_handler( ); /* * Check REQUESTS pipe */ check_requests( ); /* * Output. */ for( d = first_descriptor; d; d = d_next ) { d_next = d->next; if( ( d->fcommand || d->outtop > 0 ) && FD_ISSET( d->descriptor, &out_set ) ) { if( d->pagepoint ) { if( !pager_output( d ) ) { if( d->character && ( d->connected == CON_PLAYING || d->connected == CON_EDITING ) ) save_char_obj( d->character ); d->outtop = 0; close_socket( d, FALSE ); } } else if( !flush_buffer( d, TRUE ) ) { if( d->character && ( d->connected == CON_PLAYING || d->connected == CON_EDITING ) ) save_char_obj( d->character ); d->outtop = 0; close_socket( d, FALSE ); } } if( d == last_descriptor ) break; } /* * Synchronize to a clock. * Sleep( last_time + 1/PULSE_PER_SECOND - now ). * Careful here of signed versus unsigned arithmetic. */ { struct timeval now_time; long secDelta; long usecDelta; gettimeofday( &now_time, NULL ); usecDelta = ( ( int )last_time.tv_usec ) - ( ( int )now_time.tv_usec ) + 1000000 / PULSE_PER_SECOND; secDelta = ( ( int )last_time.tv_sec ) - ( ( int )now_time.tv_sec ); while( usecDelta < 0 ) { usecDelta += 1000000; secDelta -= 1; } while( usecDelta >= 1000000 ) { usecDelta -= 1000000; secDelta += 1; } if( secDelta > 0 || ( secDelta == 0 && usecDelta > 0 ) ) { struct timeval stall_time; stall_time.tv_usec = usecDelta; stall_time.tv_sec = secDelta; #ifdef WIN32 Sleep( ( stall_time.tv_sec * 1000L ) + ( stall_time.tv_usec / 1000L ) ); #else if( select( 0, NULL, NULL, NULL, &stall_time ) < 0 && errno != EINTR ) { perror( "game_loop: select: stall" ); exit( 1 ); } #endif } } gettimeofday( &last_time, NULL ); current_time = ( time_t ) last_time.tv_sec; /* * Check every 5 seconds... (don't need it right now) * if ( last_check+5 < current_time ) * { * CHECK_LINKS(first_descriptor, last_descriptor, next, prev, * DESCRIPTOR_DATA); * last_check = current_time; * } */ } /* * Save morphs so can sort later. --Shaddai */ if( sysdata.morph_opt ) save_morphs( ); fflush( stderr ); /* make sure strerr is flushed */ return; } void new_descriptor( int new_desc ) { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *dnew; struct sockaddr_in sock; struct hostent *from; int desc; int size; char bugbuf[MAX_STRING_LENGTH]; #ifdef WIN32 unsigned long arg = 1; #endif size = sizeof( sock ); if( check_bad_desc( new_desc ) ) { set_alarm( 0 ); return; } set_alarm( 20 ); alarm_section = "new_descriptor::accept"; if( ( desc = accept( new_desc, ( struct sockaddr * )&sock, &size ) ) < 0 ) { perror( "New_descriptor: accept" ); sprintf( bugbuf, "[*****] BUG: New_descriptor: accept" ); log_string_plus( bugbuf, LOG_COMM, sysdata.log_level ); set_alarm( 0 ); return; } if( check_bad_desc( new_desc ) ) { set_alarm( 0 ); return; } #if !defined(FNDELAY) #define FNDELAY O_NDELAY #endif set_alarm( 20 ); alarm_section = "new_descriptor: after accept"; #ifdef WIN32 if( ioctlsocket( desc, FIONBIO, &arg ) == -1 ) #else if( fcntl( desc, F_SETFL, FNDELAY ) == -1 ) #endif { perror( "New_descriptor: fcntl: FNDELAY" ); set_alarm( 0 ); return; } if( check_bad_desc( new_desc ) ) return; CREATE( dnew, DESCRIPTOR_DATA, 1 ); dnew->next = NULL; dnew->descriptor = desc; dnew->connected = CON_GET_NAME; dnew->ansi = TRUE; /* force ansi */ dnew->outsize = 2000; dnew->idle = 0; dnew->lines = 0; dnew->scrlen = 24; dnew->port = ntohs( sock.sin_port ); dnew->user = STRALLOC( "(unknown)" ); dnew->newstate = 0; dnew->prevcolor = 0x07; dnew->ifd = -1; /* Descriptor pipes, used for DNS resolution and such */ dnew->ipid = -1; CREATE( dnew->outbuf, char, dnew->outsize ); strcpy( log_buf, inet_ntoa( sock.sin_addr ) ); dnew->host = STRALLOC( log_buf ); /* if ( !sysdata.NO_NAME_RESOLVING ) { strcpy( buf, in_dns_cache( log_buf ) ); if( buf[0] == '\0' ) resolve_dns( dnew, sock.sin_addr.s_addr ); else { STRFREE( dnew->host2 ); dnew->host = STRALLOC( buf ); } } */ // OLD DNS CODE --Saiyr // else // { from = gethostbyaddr( ( char * )&sock.sin_addr, sizeof( sock.sin_addr ), AF_INET ); dnew->host2 = STRALLOC( ( char * )( from ? from->h_name : buf ) ); // } if( check_total_bans( dnew ) ) { write_to_descriptor( desc, "Your site has been banned from this Mud.\n\r", 0 ); free_desc( dnew ); set_alarm( 0 ); return; } /* * Init descriptor data. */ if( !last_descriptor && first_descriptor ) { DESCRIPTOR_DATA *d; bug( "New_descriptor: last_desc is NULL, but first_desc is not! ...fixing" ); for( d = first_descriptor; d; d = d->next ) if( !d->next ) last_descriptor = d; } LINK( dnew, first_descriptor, last_descriptor, next, prev ); #ifdef MCCP write_to_buffer( dnew, eor_on_str, 0 ); write_to_buffer( dnew, compress2_on_str, 0 ); write_to_buffer( dnew, compress_on_str, 0 ); #endif /* * Send the greeting. */ { extern char *help_greeting; if( help_greeting[0] == '.' ) send_to_desc_color( help_greeting + 1, dnew ); else send_to_desc_color( help_greeting, dnew ); } send_to_desc_color( "&wEnter your character's name, or type &Wnew&w: &D", dnew ); alarm_section = "new_descriptor: set_auth"; set_auth( dnew ); alarm_section = "new_descriptor: after set_auth"; if( ++num_descriptors > sysdata.maxplayers ) sysdata.maxplayers = num_descriptors; if( sysdata.maxplayers > sysdata.alltimemax ) { if( sysdata.time_of_max ) DISPOSE( sysdata.time_of_max ); sprintf( buf, "%24.24s", ctime( ¤t_time ) ); sysdata.time_of_max = str_dup( buf ); sysdata.alltimemax = sysdata.maxplayers; sprintf( log_buf, "Broke all-time maximum player record: %d", sysdata.alltimemax ); log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); to_channel( log_buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL ); save_sysdata( sysdata ); } set_alarm( 0 ); return; } void free_desc( DESCRIPTOR_DATA * d ) { kill_auth( d ); closesocket( d->descriptor ); DISPOSE( d->outbuf ); STRFREE( d->user ); /* identd */ if( d->pagebuf ) DISPOSE( d->pagebuf ); #ifdef MCCP compressEnd( d ); #endif DISPOSE( d ); /* --num_descriptors; This is called from more than close_socket -- Alty */ return; } void close_socket( DESCRIPTOR_DATA * dclose, bool force ) { AUTH_LIST *old_auth; CHAR_DATA *ch; DESCRIPTOR_DATA *d; bool DoNotUnlink = FALSE; OBJ_DATA *o; if( dclose->ipid != -1 ) { int status; kill( dclose->ipid, SIGKILL ); waitpid( dclose->ipid, &status, 0 ); } if( dclose->ifd != -1 ) close( dclose->ifd ); /* * flush outbuf */ if( !force && dclose->outtop > 0 ) flush_buffer( dclose, FALSE ); /* * say bye to whoever's snooping this descriptor */ if( dclose->snoop_by ) write_to_buffer( dclose->snoop_by, "Your victim has left the game.\n\r", 0 ); /* * stop snooping everyone else */ for( d = first_descriptor; d; d = d->next ) if( d->snoop_by == dclose ) d->snoop_by = NULL; /* * Check for switched people who go link-dead. -- Altrag */ if( dclose->original ) { if( ( ch = dclose->character ) != NULL ) do_return( ch, "" ); else { bug( "Close_socket: dclose->original without character %s", ( dclose->original->name ? dclose->original->name : "unknown" ) ); dclose->character = dclose->original; dclose->original = NULL; } } ch = dclose->character; /* * sanity check :( */ if( !dclose->prev && dclose != first_descriptor ) { DESCRIPTOR_DATA *dp, *dn; bug( "Close_socket: %s desc:%p != first_desc:%p and desc->prev = NULL!", ch ? ch->name : d->host, dclose, first_descriptor ); dp = NULL; for( d = first_descriptor; d; d = dn ) { dn = d->next; if( d == dclose ) { bug( "Close_socket: %s desc:%p found, prev should be:%p, fixing.", ch ? ch->name : d->host, dclose, dp ); dclose->prev = dp; break; } dp = d; } if( !dclose->prev ) { bug( "Close_socket: %s desc:%p could not be found!.", ch ? ch->name : dclose->host, dclose ); DoNotUnlink = TRUE; } } if( !dclose->next && dclose != last_descriptor ) { DESCRIPTOR_DATA *dp, *dn; bug( "Close_socket: %s desc:%p != last_desc:%p and desc->next = NULL!", ch ? ch->name : d->host, dclose, last_descriptor ); dn = NULL; for( d = last_descriptor; d; d = dp ) { dp = d->prev; if( d == dclose ) { bug( "Close_socket: %s desc:%p found, next should be:%p, fixing.", ch ? ch->name : d->host, dclose, dn ); dclose->next = dn; break; } dn = d; } if( !dclose->next ) { bug( "Close_socket: %s desc:%p could not be found!.", ch ? ch->name : dclose->host, dclose ); DoNotUnlink = TRUE; } } if( dclose->character ) { sprintf( log_buf, "Closing link to %s.", ch->pcdata->filename ); log_string_plus( log_buf, LOG_COMM, UMAX( sysdata.log_level, ch->level ) ); /* if ( ch->level < LEVEL_DEMI ) to_channel( log_buf, CHANNEL_MONITOR, "Monitor", ch->level ); */ /* * Link dead auth -- Rantic */ old_auth = get_auth_name( ch->name ); if( old_auth != NULL && old_auth->state == AUTH_ONLINE ) { old_auth->state = AUTH_LINK_DEAD; save_auth_list( ); } if( ( dclose->connected == CON_PLAYING || dclose->connected == CON_EDITING ) || ( dclose->connected >= CON_NOTE_TO && dclose->connected <= CON_NOTE_FINISH ) ) { char ldbuf[MAX_STRING_LENGTH]; act( AT_ACTION, "$n has lost $s link.", ch, NULL, NULL, TO_CANSEE ); sprintf( ldbuf, "%s has gone linkdead", ch->name ); while( ( o = carrying_noquit( ch ) ) != NULL ) { obj_from_char( o ); obj_to_room( o, ch->in_room ); } if( !IS_IMMORTAL( ch ) ) do_info( ch, ldbuf ); else do_ainfo( ch, ldbuf ); ch->desc = NULL; } else { /* * clear descriptor pointer to get rid of bug message in log */ dclose->character->desc = NULL; free_char( dclose->character ); } } if( !DoNotUnlink ) { /* * make sure loop doesn't get messed up */ if( d_next == dclose ) d_next = d_next->next; UNLINK( dclose, first_descriptor, last_descriptor, next, prev ); } #ifdef MCCP compressEnd( dclose ); #endif if( dclose->descriptor == maxdesc ) --maxdesc; free_desc( dclose ); --num_descriptors; return; } bool read_from_descriptor( DESCRIPTOR_DATA * d ) { int iStart, iErr; /* * Hold horses if pending command already. */ if( d->incomm[0] != '\0' ) return TRUE; /* * Check for overflow. */ iStart = strlen( d->inbuf ); if( iStart >= sizeof( d->inbuf ) - 10 ) { sprintf( log_buf, "%s input overflow!", d->host ); log_string( log_buf ); write_to_descriptor( d->descriptor, "\n\r*** PUT A LID ON IT!!! ***\n\rYou cannot enter the same command more than 20 consecutive times!\n\r", 0 ); return FALSE; } for( ;; ) { int nRead; nRead = recv( d->descriptor, d->inbuf + iStart, sizeof( d->inbuf ) - 10 - iStart, 0 ); #ifdef WIN32 iErr = WSAGetLastError( ); #else iErr = errno; #endif if( nRead > 0 ) { iStart += nRead; if( d->inbuf[iStart - 1] == '\n' || d->inbuf[iStart - 1] == '\r' ) break; } else if( nRead == 0 ) { log_string_plus( "EOF encountered on read.", LOG_COMM, sysdata.log_level ); return FALSE; } else if( iErr == EWOULDBLOCK ) break; else { perror( "Read_from_descriptor" ); return FALSE; } } d->inbuf[iStart] = '\0'; return TRUE; } /* * Transfer one line from input buffer to input line. */ void read_from_buffer( DESCRIPTOR_DATA * d ) { int i, j, k; #ifdef MCCP int iac = 0; #endif /* * Hold horses if pending command already. */ if( d->incomm[0] != '\0' ) return; /* * Look for at least one new line. */ for( i = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r' && i < MAX_INBUF_SIZE; i++ ) { if( d->inbuf[i] == '\0' ) return; } /* * Canonical input processing. */ for( i = 0, k = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++ ) { int z = 0; if( d->connected == CON_EDITING ) z = 254; else z = 762; // if ( k >= 254 ) -- This was the old buffer size, new is above. if( k >= z ) { write_to_descriptor( d->descriptor, "Line too long.\n\r", 0 ); /* * skip the rest of the line */ /* * for ( ; d->inbuf[i] != '\0' || i>= MAX_INBUF_SIZE ; i++ ) * { * if ( d->inbuf[i] == '\n' || d->inbuf[i] == '\r' ) * break; * } */ d->inbuf[i] = '\n'; d->inbuf[i + 1] = '\0'; break; } #ifdef MCCP if( d->inbuf[i] == ( signed char )IAC ) iac = 1; else if( iac == 1 && ( d->inbuf[i] == ( signed char )DO || d->inbuf[i] == ( signed char )DONT ) ) iac = 2; else if( iac == 2 ) { iac = 0; if( d->inbuf[i] == ( signed char )TELOPT_COMPRESS ) { if( d->inbuf[i - 1] == ( signed char )DO ) compressStart( d, TELOPT_COMPRESS ); else if( d->inbuf[i - 1] == ( signed char )DONT ) compressEnd( d ); } else if( d->inbuf[i] == ( signed char )TELOPT_COMPRESS2 ) { if( d->inbuf[i - 1] == ( signed char )DO ) compressStart( d, TELOPT_COMPRESS2 ); else if( d->inbuf[i - 1] == ( signed char )DONT ) compressEnd( d ); } } else #endif if( d->inbuf[i] == '\b' && k > 0 ) --k; else if( isascii( d->inbuf[i] ) && isprint( d->inbuf[i] ) ) d->incomm[k++] = d->inbuf[i]; } /* * Finish off the line. */ if( k == 0 ) d->incomm[k++] = ' '; d->incomm[k] = '\0'; /* * Deal with bozos with #repeat 1000 ... */ if( k > 1 || d->incomm[0] == '!' ) { if( d->incomm[0] != '!' && strcmp( d->incomm, d->inlast ) ) { d->repeat = 0; } else { if( ++d->repeat >= 20 ) { /* sprintf( log_buf, "%s input spamming!", d->host ); log_string( log_buf ); */ write_to_descriptor( d->descriptor, "\n\r*** PUT A LID ON IT!!! ***\n\rYou cannot enter the same command more than 20 consecutive times!\n\r", 0 ); strcpy( d->incomm, "quit" ); } } } /* * Do '!' substitution. */ if( d->incomm[0] == '!' ) strcpy( d->incomm, d->inlast ); else strcpy( d->inlast, d->incomm ); /* * Shift the input buffer. */ while( d->inbuf[i] == '\n' || d->inbuf[i] == '\r' ) i++; for( j = 0; ( d->inbuf[j] = d->inbuf[i + j] ) != '\0'; j++ ) ; return; } /* * Low level output function. */ bool flush_buffer( DESCRIPTOR_DATA * d, bool fPrompt ) { char buf[MAX_INPUT_LENGTH]; // char promptbuf[MAX_STRING_LENGTH]; extern bool mud_down; /* * If buffer has more than 4K inside, spit out .5K at a time -Thoric */ if( !mud_down && d->outtop > 4096 ) { memcpy( buf, d->outbuf, 512 ); d->outtop -= 512; memmove( d->outbuf, d->outbuf + 512, d->outtop ); if( d->snoop_by ) { char snoopbuf[MAX_INPUT_LENGTH]; buf[512] = '\0'; if( d->character && d->character->name ) { if( d->original && d->original->name ) sprintf( snoopbuf, "%s (%s)", d->character->name, d->original->name ); else sprintf( snoopbuf, "%s", d->character->name ); write_to_buffer( d->snoop_by, snoopbuf, 0 ); } write_to_buffer( d->snoop_by, "% ", 2 ); write_to_buffer( d->snoop_by, buf, 0 ); } if( !write_to_descriptor( d->descriptor, buf, 512 ) ) { d->outtop = 0; return FALSE; } return TRUE; } /* * Bust a prompt. */ if( fPrompt && !mud_down && d->connected == CON_PLAYING ) { CHAR_DATA *ch; ch = d->original ? d->original : d->character; if( xIS_SET( ch->act, PLR_BLANK ) ) write_to_buffer( d, "\n\r", 2 ); if( ch->fighting ) { d->psuppress_cmdspam = FALSE; d->psuppress_channel = 0; } if( d->psuppress_channel >= 5 ) d->psuppress_channel = 0; if( xIS_SET( ch->act, PLR_PROMPT ) ) { sysdata.outBytesFlag = LOGBOUTPROMPT; // if( !d->psuppress_cmdspam && !d->psuppress_channel ) // { display_prompt( d ); // d->psuppress_cmdspam = FALSE; /* } else if( d->psuppress_channel && ch->pcdata ) { switch ( ch->pcdata->normalPromptConfig ) { default: if( is_android( ch ) ) sprintf( promptbuf, "&D<D:%d E:%s T:%s> ", ch->hit, num_punct( ch->mana ), abbNumLD( ch->pl ) ); else sprintf( promptbuf, "&D<L:%d K:%s P:%s> ", ch->hit, num_punct( ch->mana ), abbNumLD( ch->pl ) ); break; case 1: if( is_android( ch ) ) sprintf( promptbuf, "&D<D:%d E:%s T:%s> ", ch->hit, num_punct( ch->mana ), abbNumLD( ch->pl ) ); else sprintf( promptbuf, "&D<L:%d K:%s P:%s> ", ch->hit, num_punct( ch->mana ), abbNumLD( ch->pl ) ); break; } send_to_char( promptbuf, ch ); if( get_true_rank( ch ) >= 11 ) pager_printf( ch, "(KRT:%d) ", sysdata.kaiRestoreTimer ); } else send_to_char( "&D> ", ch ); sysdata.outBytesFlag = LOGBOUTNORM; */ } if( !IS_NPC( ch ) ) if( xIS_SET( ch->act, PLR_TELNET_GA ) ) write_to_buffer( d, go_ahead_str, 0 ); } /* * Short-circuit if nothing to write. */ if( d->outtop == 0 ) return TRUE; /* * Snoop-o-rama. */ if( d->snoop_by ) { /* * without check, 'force mortal quit' while snooped caused crash, -h */ if( d->character && d->character->name ) { /* * Show original snooped names. -- Altrag */ if( d->original && d->original->name ) sprintf( buf, "%s (%s)", d->character->name, d->original->name ); else sprintf( buf, "%s", d->character->name ); write_to_buffer( d->snoop_by, buf, 0 ); } write_to_buffer( d->snoop_by, "% ", 2 ); write_to_buffer( d->snoop_by, d->outbuf, d->outtop ); } /* * OS-dependent output. */ if( !write_to_descriptor( d->descriptor, d->outbuf, d->outtop ) ) { d->outtop = 0; return FALSE; } else { d->outtop = 0; return TRUE; } } /* * Append onto an output buffer. */ void write_to_buffer( DESCRIPTOR_DATA * d, const char *txt, int length ) { if( !d ) { bug( "Write_to_buffer: NULL descriptor" ); return; } /* * Normally a bug... but can happen if loadup is used. */ if( !d->outbuf ) return; /* * Find length in case caller didn't. */ if( length <= 0 ) length = strlen( txt ); /* Uncomment if debugging or something if ( length != strlen(txt) ) { bug( "Write_to_buffer: length(%d) != strlen(txt)!", length ); length = strlen(txt); } */ /* * Initial \n\r if needed. */ if( d->outtop == 0 && !d->fcommand ) { d->outbuf[0] = '\n'; d->outbuf[1] = '\r'; d->outtop = 2; } /* * Expand the buffer as needed. */ while( d->outtop + length >= d->outsize ) { if( d->outsize > 32000 ) { /* * empty buffer */ d->outtop = 0; bug( "Buffer overflow. Closing (%s).", d->character ? d->character->name : "???" ); close_socket( d, TRUE ); return; } d->outsize *= 2; RECREATE( d->outbuf, char, d->outsize ); } /* * Copy. */ strncpy( d->outbuf + d->outtop, txt, length ); d->outtop += length; d->outbuf[d->outtop] = '\0'; return; } #ifdef MCCP #define COMPRESS_BUF_SIZE 1024 bool write_to_descriptor( int desc, char *txt, int length ) { DESCRIPTOR_DATA *d; int iStart = 0; int nWrite = 0; int nBlock; int len; if( length <= 0 ) length = strlen( txt ); for( d = first_descriptor; d; d = d->next ) if( d->descriptor == desc ) break; if( d && d->descriptor != desc ) d = NULL; if( d && d->out_compress ) { d->out_compress->next_in = ( unsigned char * )txt; d->out_compress->avail_in = length; while( d->out_compress->avail_in ) { d->out_compress->avail_out = COMPRESS_BUF_SIZE - ( d->out_compress->next_out - d->out_compress_buf ); if( d->out_compress->avail_out ) { int status = deflate( d->out_compress, Z_SYNC_FLUSH ); if( status != Z_OK ) return FALSE; } len = d->out_compress->next_out - d->out_compress_buf; if( len > 0 ) { for( iStart = 0; iStart < len; iStart += nWrite ) { nBlock = UMIN( len - iStart, 4096 ); if( ( nWrite = write( d->descriptor, d->out_compress_buf + iStart, nBlock ) ) < 0 ) { perror( "Write_to_descriptor: compressed" ); return FALSE; } if( !nWrite ) break; } if( !iStart ) break; if( iStart < len ) memmove( d->out_compress_buf, d->out_compress_buf + iStart, len - iStart ); d->out_compress->next_out = d->out_compress_buf + len - iStart; } } return TRUE; } for( iStart = 0; iStart < length; iStart += nWrite ) { nBlock = UMIN( length - iStart, 4096 ); if( ( nWrite = write( desc, txt + iStart, nBlock ) ) < 0 ) { perror( "Write_to_descriptor" ); return FALSE; } } return TRUE; } #else /* * Lowest level output function. * Write a block of text to the file descriptor. * If this gives errors on very long blocks (like 'ofind all'), * try lowering the max block size. */ bool write_to_descriptor( int desc, char *txt, int length ) { int iStart; int nWrite; int nBlock; if( length <= 0 ) length = strlen( txt ); for( iStart = 0; iStart < length; iStart += nWrite ) { nBlock = UMIN( length - iStart, 4096 ); if( ( nWrite = send( desc, txt + iStart, nBlock, 0 ) ) < 0 ) { perror( "Write_to_descriptor" ); return FALSE; } } return TRUE; } #endif /* Added to try to fix hotboot issue */ bool write_to_descriptor_old( int desc, char *txt, int length ) { int iStart; int nWrite; int nBlock; if( length <= 0 ) length = strlen( txt ); for( iStart = 0; iStart < length; iStart += nWrite ) { nBlock = UMIN( length - iStart, 4096 ); if( ( nWrite = send( desc, txt + iStart, nBlock, 0 ) ) < 0 ) { perror( "Write_to_descriptor" ); return FALSE; } } return TRUE; } /* End added */ void show_title( DESCRIPTOR_DATA * d ) { CHAR_DATA *ch; ch = d->character; if( !IS_SET( ch->pcdata->flags, PCFLAG_NOINTRO ) ) { if( xIS_SET( ch->act, PLR_RIP ) ) send_rip_title( ch ); else if( xIS_SET( ch->act, PLR_ANSI ) ) send_ansi_title( ch ); else send_ascii_title( ch ); } else { write_to_buffer( d, "Press enter...\n\r", 0 ); } d->connected = CON_PRESS_ENTER; } char *smaug_crypt( const char *pwd ) { md5_state_t state; md5_byte_t digest[16]; static char passwd[16]; unsigned int x; md5_init( &state ); md5_append( &state, ( const md5_byte_t * )pwd, strlen( pwd ) ); md5_finish( &state, digest ); strncpy( passwd, ( const char * )digest, 15 ); passwd[15] = '\0'; /* * The listed exceptions below will fubar the MD5 authentication packets, so change them */ for( x = 0; x < strlen( passwd ); x++ ) { if( passwd[x] == '\n' ) passwd[x] = 'n'; if( passwd[x] == '\r' ) passwd[x] = 'r'; if( passwd[x] == '\t' ) passwd[x] = 't'; if( passwd[x] == ' ' ) passwd[x] = 's'; if( ( int )passwd[x] == 11 ) passwd[x] = 'x'; if( ( int )passwd[x] == 12 ) passwd[x] = 'X'; if( passwd[x] == '~' ) passwd[x] = '+'; if( passwd[x] == EOF ) passwd[x] = 'E'; } return ( passwd ); } /* * Deal with sockets that haven't logged in yet. */ void nanny( DESCRIPTOR_DATA * d, char *argument ) { /* extern int lang_array[]; extern char *lang_names[];*/ char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char buf3[MAX_STRING_LENGTH]; char buf4[MAX_STRING_LENGTH]; char arg[MAX_STRING_LENGTH]; CHAR_DATA *ch; char *pwdnew; char *p; int b = 0; int iClass; // int iRace; bool fOld, chk; NOTE_DATA *catchup_notes; int i = 0; // these were making compile warnings making it look ugly :) -Goku // FILE *ipFp; // char ipBuf[MAX_STRING_LENGTH]; if( d->connected != CON_NOTE_TEXT ) { while( isspace( *argument ) ) argument++; } ch = d->character; switch ( d->connected ) { default: bug( "Nanny: bad d->connected %d.", d->connected ); close_socket( d, TRUE ); return; case CON_GET_NAME: if( argument[0] == '\0' ) { close_socket( d, FALSE ); return; } // argument[0] = UPPER(argument[0]); *argument = capitalizeString( argument ); /* * Old players can keep their characters. -- Alty */ if( !check_parse_name( argument, ( d->newstate != 0 ) ) ) { send_to_desc_color( "&wIllegal name, try another.\n\rName: &D", d ); return; } bool blocked = FALSE; // Added for more convenient disabling // of newbie creation. -Karma if( !str_cmp( argument, "New" ) && !blocked ) { if( d->newstate == 0 ) { /* * New player */ /* * Don't allow new players if DENY_NEW_PLAYERS is true */ if( sysdata.DENY_NEW_PLAYERS == TRUE ) { sprintf( buf, "The mud is currently preparing for a reboot.\n\r" ); send_to_desc_color( buf, d ); sprintf( buf, "New players are not accepted during this time.\n\r" ); send_to_desc_color( buf, d ); sprintf( buf, "Please try again in a few minutes.\n\r" ); send_to_desc_color( buf, d ); close_socket( d, FALSE ); } sprintf( buf, "\n\r&gChoosing a name is one of the most important parts of this game...\n\r" "Make sure to pick a name appropriate to the character you are going\n\r" "to role play, and be sure that it fits into the DragonBall Z world.\n\r" "Please type '&WHELP&g' to read what restirictions we have for naming your\n\r" "character.\n\r\n\r&wPlease choose a name for your character: &D" ); send_to_desc_color( buf, d ); d->newstate++; d->connected = CON_GET_NAME; return; } else { send_to_desc_color( "&wIllegal name, try another.\n\rName: &D", d ); return; } } if( !str_cmp( argument, "help" ) ) { HELP_DATA *pHelp; for( pHelp = first_help; pHelp; pHelp = pHelp->next ) { if( !str_cmp( pHelp->keyword, "dbznames" ) ) break; } if( !pHelp ) { send_to_desc_color( "No help on that word.\n\rName: ", d ); return; } send_to_desc_color( "\n\r", d ); send_to_desc_color( pHelp->text, d ); send_to_desc_color( "\n\r\n\r&wName: ", d ); return; } if( check_playing( d, argument, FALSE ) == BERR ) { write_to_buffer( d, "Name: ", 0 ); return; } fOld = load_char_obj( d, argument, TRUE ); if( !d->character ) { sprintf( log_buf, "Bad player file %s@%s.", argument, d->host ); log_string( log_buf ); send_to_desc_color( "Your playerfile is corrupt...Please notify wav3master@hotmail.com.\n\r", d ); close_socket( d, FALSE ); return; } ch = d->character; if( check_bans( ch, BAN_SITE ) ) { send_to_desc_color( "Your site has been banned from this Mud.\n\r", d ); close_socket( d, FALSE ); return; } if( fOld ) { if( check_bans( ch, BAN_CLASS ) ) { send_to_desc_color( "Your class has been banned from this Mud.\n\r", d ); close_socket( d, FALSE ); return; } if( check_bans( ch, BAN_RACE ) ) { send_to_desc_color( "Your race has been banned from this Mud.\n\r", d ); close_socket( d, FALSE ); return; } } if( get_trust( ch ) > MAX_LEVEL && !xIS_SET( ch->act, PLR_DENY ) ) xSET_BIT( ch->act, PLR_DENY ); if( xIS_SET( ch->act, PLR_DENY ) ) { sprintf( log_buf, "Denying access to %s@%s.", argument, d->host ); log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); if( d->newstate != 0 ) { send_to_desc_color( "That name is already taken. Please choose another: ", d ); d->connected = CON_GET_NAME; d->character->desc = NULL; free_char( d->character ); /* Big Memory Leak before --Shaddai */ d->character = NULL; return; } send_to_desc_color( "You are denied access.\n\r", d ); close_socket( d, FALSE ); return; } /* * Make sure the immortal host is from the correct place. * Shaddai */ if( check_total_ip( d ) ) { send_to_desc_color( "Your maximum amount of players you can have online has been reached.\n\r", d ); close_socket( d, FALSE ); return; } if( IS_IMMORTAL( ch ) && sysdata.check_imm_host && !check_immortal_domain( ch, d->host ) ) { sprintf( log_buf, "%s's char being hacked from %s.", argument, d->host ); log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); sprintf( log_buf, "&R%s's char being hacked from %s.", argument, d->host ); ch->level = 51; do_ainfo( ch, log_buf ); send_to_desc_color( "This hacking attempt has been logged.\n\r", d ); close_socket( d, FALSE ); return; } chk = check_reconnect( d, argument, FALSE ); if( chk == BERR ) return; if( chk ) { fOld = TRUE; } else { // if ( wizlock && !IS_IMMORTAL(ch) ) if( wizlock && ch->level < locklev ) { send_to_desc_color( "The game is wizlocked. Only immortals can connect now.\n\r", d ); send_to_desc_color( "Please try back later.\n\r", d ); close_socket( d, FALSE ); return; } } if( fOld ) { if( d->newstate != 0 ) { send_to_desc_color( "&wThat name is already taken. Please choose another: &D", d ); d->connected = CON_GET_NAME; d->character->desc = NULL; free_char( d->character ); /* Big Memory Leak before --Shaddai */ d->character = NULL; return; } /* * Old player */ send_to_desc_color( "&wPassword: &D", d ); write_to_buffer( d, echo_off_str, 0 ); d->connected = CON_GET_OLD_PASSWORD; return; } else { /* * if ( !check_parse_name( argument ) ) * { * write_to_buffer( d, "Illegal name, try another.\n\rName: ", 0 ); * return; * } */ if( d->newstate == 0 ) { /* * No such player */ send_to_desc_color ( "\n\r&wNo such player exists.\n\rPlease check your spelling, or type new to start a new player.\n\r\n\rName: &D", d ); d->connected = CON_GET_NAME; d->character->desc = NULL; free_char( d->character ); /* Big Memory Leak before --Shaddai */ d->character = NULL; return; } sprintf( buf, "&wDid I get that right, %s (&WY&w/&WN&w)? &D", argument ); send_to_desc_color( buf, d ); d->connected = CON_CONFIRM_NEW_NAME; return; } break; case CON_GET_OLD_PASSWORD: write_to_buffer( d, "\n\r", 2 ); if( ch->pcdata->version < 4 ) { if( str_cmp( crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) ) { write_to_buffer( d, "Wrong password, disconnecting.\n\r", 0 ); /* * clear descriptor pointer to get rid of bug message in log */ d->character->desc = NULL; close_socket( d, FALSE ); return; } } else { /* * This if check is what you will want to keep once it is no longer necessary to convert pfiles */ if( str_cmp( smaug_crypt( argument ), ch->pcdata->pwd ) ) { write_to_buffer( d, "Wrong password, disconnecting.\n\r", 0 ); /* * clear descriptor pointer to get rid of bug message in log */ d->character->desc = NULL; close_socket( d, FALSE ); return; } } if( ch->pcdata->version < 4 ) { DISPOSE( ch->pcdata->pwd ); ch->pcdata->pwd = str_dup( smaug_crypt( argument ) ); } write_to_buffer( d, echo_on_str, 0 ); if( check_playing( d, ch->pcdata->filename, TRUE ) ) return; chk = check_reconnect( d, ch->pcdata->filename, TRUE ); if( chk == BERR ) { if( d->character && d->character->desc ) d->character->desc = NULL; close_socket( d, FALSE ); return; } if( chk == TRUE ) return; strncpy( buf, ch->pcdata->filename, MAX_STRING_LENGTH ); d->character->desc = NULL; free_char( d->character ); d->character = NULL; fOld = load_char_obj( d, buf, FALSE ); ch = d->character; if( ch->position > POS_SITTING && ch->position < POS_STANDING ) ch->position = POS_STANDING; sprintf( log_buf, "%s@%s(%s) has connected.", ch->pcdata->filename, d->host, d->user ); if( ch->level == 2 ) { xSET_BIT( ch->deaf, CHANNEL_FOS ); ch->level = 1; } sprintf( buf3, "%s has logged on", ch->name ); if( !IS_IMMORTAL( ch ) ) do_info( ch, buf3 ); else do_ainfo( ch, buf3 ); if( !IS_IMMORTAL( ch ) && IS_AFFECTED( ch, AFF_DEAD ) ) { sprintf( buf4, "%s has a halo", ch->name ); log_string_plus( buf4, LOG_HIGH, LEVEL_LESSER ); } /* * player data update checks */ pager_printf( ch, "Checking for player data updates...\n\r" ); if( ch->pcdata->upgradeL > CURRENT_UPGRADE_LEVEL ) ch->pcdata->upgradeL = CURRENT_UPGRADE_LEVEL - 1; if( upgrade_player( ch ) ) pager_printf( ch, "Updated player data successfully.\n\r" ); else pager_printf( ch, "No updates to make.\n\r" ); adjust_hiscore( "pkill", ch, ch->pcdata->pkills ); /* cronel hiscore */ adjust_hiscore( "sparwins", ch, ch->pcdata->spar_wins ); adjust_hiscore( "sparloss", ch, ch->pcdata->spar_loss ); adjust_hiscore( "mkills", ch, ch->pcdata->mkills ); adjust_hiscore( "deaths", ch, ( ch->pcdata->pdeaths + ch->pcdata->mdeaths ) ); update_plHiscore( ch ); adjust_hiscore( "played", ch, ( get_age( ch ) - 4 ) ); adjust_hiscore( "zeni", ch, ch->gold ); adjust_hiscore( "bounty", ch, ch->pcdata->bkills ); update_member( ch ); if( !str_cmp( ch->name, "normed" )) log_string_plus( log_buf, LOG_COMM, LEVEL_SUPREME ); else log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); if( ch->pcdata->version < 4 ) { DISPOSE( ch->pcdata->pwd ); ch->pcdata->pwd = str_dup( smaug_crypt( argument ) ); } show_title( d ); break; case CON_CONFIRM_NEW_NAME: switch ( *argument ) { case 'y': case 'Y': sprintf( buf, "\n\r&wMake sure to use a password that won't be easily guessed by someone else." "\n\rPick a good password for %s: %s&D", ch->name, echo_off_str ); send_to_desc_color( buf, d ); xSET_BIT( ch->act, PLR_ANSI ); d->connected = CON_GET_NEW_PASSWORD; break; case 'n': case 'N': send_to_desc_color( "&wOk, what IS it, then? &D", d ); /* * clear descriptor pointer to get rid of bug message in log */ d->character->desc = NULL; free_char( d->character ); d->character = NULL; d->connected = CON_GET_NAME; break; default: send_to_desc_color( "&wPlease type &WY&wes or &WN&wo. &D", d ); break; } break; case CON_GET_NEW_PASSWORD: send_to_desc_color( "\n\r", d ); if( strlen( argument ) < 5 ) { send_to_desc_color( "&wPassword must be at least five characters long.\n\rPassword: &D", d ); return; } pwdnew = smaug_crypt( argument ); /* MD5 Encryption */ for( p = pwdnew; *p != '\0'; p++ ) { if( *p == '~' || *p == '\'' || *p == '\"' ) { send_to_desc_color( "&wNew password not acceptable, try again.\n\rPassword: &D", d ); return; } } DISPOSE( ch->pcdata->pwd ); ch->pcdata->pwd = str_dup( pwdnew ); send_to_desc_color( "\n\r&wPlease retype the password to confirm: &D", d ); d->connected = CON_CONFIRM_NEW_PASSWORD; break; case CON_CONFIRM_NEW_PASSWORD: send_to_desc_color( "\n\r", d ); if( str_cmp( smaug_crypt( argument ), ch->pcdata->pwd ) ) { write_to_buffer( d, "Passwords don't match.\n\rRetype password: ", 0 ); d->connected = CON_GET_NEW_PASSWORD; return; } write_to_buffer( d, echo_on_str, 0 ); send_to_desc_color( "\n\r&wWhat do you want your last name to be? [press enter for none] &D\n\r", d ); d->connected = CON_GET_LAST_NAME; break; case CON_GET_LAST_NAME: if( argument[0] == '\0' ) { write_to_buffer( d, echo_on_str, 0 ); send_to_desc_color ( "\n\rDo you wish to be a &RHARDCORE&w character? (&WY&w/&WN&w)\n\rType &WHELP&w for more information.", d ); d->connected = CON_GET_HC; return; } // argument[0] = UPPER(argument[0]); *argument = capitalizeString( argument ); /* * Old players can keep their characters. -- Alty */ if( !check_parse_name( argument, TRUE ) ) { send_to_desc_color( "&wIllegal name, try another.\n\rLast name: &D", d ); return; } sprintf( buf, "&wDid I get that right, %s (&WY&w/&WN&w)? &D", argument ); send_to_desc_color( buf, d ); if( ch->pcdata->last_name ) DISPOSE( ch->pcdata->last_name ); buf[0] = ' '; strcpy( buf + 1, argument ); ch->pcdata->last_name = str_dup( buf ); d->connected = CON_CONFIRM_LAST_NAME; return; break; case CON_CONFIRM_LAST_NAME: switch ( *argument ) { case 'y': case 'Y': write_to_buffer( d, echo_on_str, 0 ); send_to_desc_color ( "\n\rDo you wish to be a &RHARDCORE&w character? (&WY&w/&WN&w)\n\rType &WHELP&w for more information.", d ); d->connected = CON_GET_HC; break; case 'n': case 'N': send_to_desc_color( "&wOk, what IS it, then? &D", d ); d->connected = CON_GET_LAST_NAME; break; default: send_to_desc_color( "&wPlease type &WY&wes or &WN&wo. &D", d ); break; } break; case CON_GET_HC: if( !str_cmp( argument, "help" ) ) { HELP_DATA *pHelp; for( pHelp = first_help; pHelp; pHelp = pHelp->next ) { if( !str_cmp( pHelp->keyword, "HC HARDCORE UNKNOWN" ) ) break; } if( !pHelp ) { send_to_desc_color( "No help on that word.\n\rDo you wish to be a &RHARDCORE&w character? (&WY&w/&WN&w): ", d ); return; } send_to_desc_color( "\n\r", d ); send_to_desc_color( pHelp->text, d ); send_to_desc_color( "&wDo you wish to be a &RHARDCORE&w character? (&WY&w/&WN&w): ", d ); return; } switch ( *argument ) { case 'y': case 'Y': sprintf( buf, "\n\r&wOkay, you are now &RHARDCORE&w!&D\n\r" ); send_to_desc_color( buf, d ); xSET_BIT( ch->act, PLR_HC ); write_to_buffer( d, echo_on_str, 0 ); break; case 'n': case 'N': send_to_desc_color( "\n\r&wOkay, you are a normal character.&D\n\r", d ); write_to_buffer( d, echo_on_str, 0 ); break; default: send_to_desc_color( "&wPlease type Yes or No. &D", d ); return; } /* whoever put this in...--Saiyr*/ send_to_desc_color( "\n\r&wWhat do you want your alignment set to(can be changed later)? (&REvil&w/&WNeutral&w/&CGood&w)? &D\n\r", d ); send_to_desc_color( "&RNOTE: &wThis will determain your clan if you choose to be in one. \n\r", d ); // d->connected = CON_GET_NEW_SEX; // break; d->connected = CON_GET_ALIGN; break; case CON_GET_ALIGN: if( !str_cmp( argument, "help" ) ) { HELP_DATA *pHelp; for( pHelp = first_help; pHelp; pHelp = pHelp->next ) { if( !str_cmp( pHelp->keyword, "ALIGN" ) ) break; } if( !pHelp ) { send_to_desc_color( "No help on that word.\n\rWhat do you want your alignment set to(can be changed later)? (&REvil&w/&WNeutral&w/&CGood&w): ", d ); // send_to_desc_color( "&RNOTE: &wThis will determain your clan if you choose to be in one. \n\r", d ); return; } send_to_desc_color( "\n\r", d ); send_to_desc_color( pHelp->text, d ); send_to_desc_color( "\n\r&wWhat do you want your alignment set to(can be changed later)? (&REvil&w/&WNeutral&w/&CGood&w): \n\r", d ); // send_to_desc_color( "&RNOTE: &wThis will determain your clan if you choose to be in one. \n\r", d ); return; } switch ( *argument ) { case 'e': case 'E': sprintf( buf, "\n\r&wOkay, you are now &REVIL&w!&D\n\r" ); send_to_desc_color( buf, d ); ch->alignment = -1000; write_to_buffer( d, echo_on_str, 0 ); break; case 'n': case 'N': send_to_desc_color( "\n\r&wOkay, you are NEUTRAL!.&D\n\r", d ); ch->alignment = 0; write_to_buffer( d, echo_on_str, 0 ); break; case 'g': case 'G': send_to_desc_color( "\n\r&wOkay, you are &CGOOD&w!.&D\n\r", d ); ch->alignment = 1000; write_to_buffer( d, echo_on_str, 0 ); break; default: send_to_desc_color( "\n\r&wPlease type Evil, Neutral, or Good. &D\n\r", d ); return; } send_to_desc_color( "\n\r&wWhat is your sex (&CM&w/&PF&w/&WN&w)? &D\n\r", d ); d->connected = CON_GET_NEW_SEX; break; case CON_GET_NEW_SEX: switch ( argument[0] ) { case 'm': case 'M': ch->sex = SEX_MALE; break; case 'f': case 'F': ch->sex = SEX_FEMALE; break; case 'n': case 'N': ch->sex = SEX_NEUTRAL; break; default: send_to_desc_color( "&wThat's not a sex.\n\rWhat IS your sex? &D", d ); return; } /* Uncomment here to add clans into creation -Karn 06.08.06 * Okgo -Karn 06.20.06 * send_to_desc_color( "\n\r&wDo you want to be in a clan? (Y/N)? &D", d ); send_to_desc_color( "\n\r&wNote: Only way to advance, join, or leave", d ); send_to_desc_color( "\n\r&w a clan after this is through RolePlay.&D\n\r", d ); d->connected = CON_GET_CLAN_STATUS; break; case CON_GET_CLAN_STATUS: if( !str_cmp( argument, "help" ) ) { HELP_DATA *pHelp; for( pHelp = first_help; pHelp; pHelp = pHelp->next ) { if( !str_cmp( pHelp->keyword, "CLANS" ) ) break; } if( !pHelp ) { send_to_desc_color( "No help on that word.\n\rWhat do you want your alignment set to? (&RE&w/&WN&w/&CG&w): ", d ); return; } send_to_desc_color( "\n\r", d ); send_to_desc_color( pHelp->text, d ); send_to_desc_color( "\n\r&wDo you want to be in a clan? (Y/N)\n\r", d ); return; } switch ( *argument ) { case 'n': case 'N': send_to_desc_color( "\n\r&wOkay, you are not in a clan!.&D\n\r", d ); write_to_buffer( d, echo_on_str, 0 ); break; case 'y': case 'Y': send_to_desc_color( "\n\r&wOkay, your in a clan!.&D\n\r", d ); send_to_desc_color( "\n\r&wPlease type: 'joinclan' once your inside the game.&D\n\r", d ); if ( IS_GOOD(ch) ) { ch->pcdata->clan = get_clan( "Alliance of Hope" ); ch->pcdata->clanRank = 7; ch->pcdata->clanZeniDonated = 0; ch->pcdata->clanZeniClanTax = 0; ch->pcdata->clanItemsDonated = 0; if( ch->sex == SEX_FEMALE ) get_clan( "Alliance of Hope" )->fRank7Count++; else get_clan( "Alliance of Hope" )->mRank7Count++; write_to_buffer( d, echo_on_str, 0 ); break; } if ( IS_NEUTRAL(ch) ) { ch->pcdata->clan = get_clan( "Crimson Steel" ); ch->pcdata->clanRank = 7; ch->pcdata->clanZeniDonated = 0; ch->pcdata->clanZeniClanTax = 0; ch->pcdata->clanItemsDonated = 0; if( ch->sex == SEX_FEMALE ) get_clan( "Crimson Steel" )->fRank7Count++; else get_clan( "Crimson Steel" )->mRank7Count++; write_to_buffer( d, echo_on_str, 0 ); break; } if ( IS_EVIL(ch) ) { ch->pcdata->clan = get_clan( "Dark Horizon" ); ch->pcdata->clanRank = 7; ch->pcdata->clanZeniDonated = 0; ch->pcdata->clanZeniClanTax = 0; ch->pcdata->clanItemsDonated = 0; if( ch->sex == SEX_FEMALE ) get_clan( "Dark Horizon" )->fRank7Count++; else get_clan( "Dark Horizon" )->mRank7Count++; write_to_buffer( d, echo_on_str, 0 ); break; } default: send_to_desc_color( "\n\r&wPlease type [&WY&w]es or [&WN&w].&D\n\r", d ); return; }*/ /* * Added for when I need to close down char creation to do * work on this section. Leaving the commented code in for * future use, if the need arises. -Karma * if(!(!str_cmp(d->character->name,"lemming")) ) { send_to_desc_color( "Character creation is currently disabled.\n\r",d); return; } */ send_to_desc_color( "\n\r&wThe following Races are Available to You:&D\n\r", d ); send_to_desc_color( "&c==============================================================================&D", d ); buf[0] = '\0'; /* * Take this out SHADDAI */ i = 0; /* * for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ ) */ send_to_desc_color( "\n\r", d ); //for ( iClass = 0; iClass < 9; iClass++ ) for( iClass = 0; iClass < 31; iClass++ ) { if( iClass == 4 ) { //i++; continue; } if( iClass > 8 && iClass < 27 ) continue; //char letters[12] = "abcdefghijk"; //char letters[14] = "abcdefghijklmn"; char letters[15] = "abcdefghijklmno"; if( class_table[iClass]->who_name && class_table[iClass]->who_name[0] != '\0' ) { sprintf( buf, "&w (&W%2d&w) &c%-12s&w ('&R%c&w' for help)&D\n\r", i, class_table[iClass]->who_name, letters[i] ); send_to_desc_color( buf, d ); i++; } } send_to_desc_color( "&c==============================================================================&D", d ); sprintf( buf, "\n\r&wChoose the number of your race: &D" ); send_to_desc_color( buf, d ); d->connected = CON_GET_NEW_CLASS; break; case CON_GET_NEW_CLASS: argument = one_argument( argument, arg ); if( is_number( arg ) ) { i = atoi( arg ); int c = 0; if( i == 0 ) c = 0; // saian if( i == 1 ) c = 1; // human if( i == 2 ) c = 2; // halfbreed if( i == 3 ) c = 3; // namek if( i == 4 ) c = 5; // icer if( i == 5 ) c = 6; // bio if( i == 6 ) c = 7; // kaio if( i == 7 ) c = 8; // demon if( i == 8 ) c = 27; // genie if( i == 9 ) c = 28; // android-h if( i == 10 ) c = 29; // android-e if( i == 11 ) c = 30; // android-fm /* * for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ ) */ //for ( iClass = 0; iClass < 9; iClass++ ) for( iClass = 0; iClass < 31; iClass++ ) { if( iClass > 8 && iClass < 27 ) continue; if( class_table[iClass]->who_name && class_table[iClass]->who_name[0] != '\0' ) { //if ( i == iClass ) if( c == iClass ) { ch->class = iClass; ch->race = iClass; break; } } } } else { //char letters[12] = "abcdefghijk"; //char letters[14] = "abcdefghijklmn"; char letters[15] = "abcdefghijklmno"; for( i = 0; i < 14; i++ ) { if( arg[0] == letters[i] ) { int c = i; if( i == 0 ) c = 0; // saian if( i == 1 ) c = 1; // human if( i == 2 ) c = 2; // halfbreed if( i == 3 ) c = 3; // namek if( i == 4 ) c = 5; // icer if( i == 5 ) c = 6; // bio if( i == 6 ) c = 7; // kaio if( i == 7 ) c = 8; // demon if( i == 8 ) c = 27; // genie if( i == 9 ) c = 28; // android-h if( i == 10 ) c = 29; // android-e if( i == 11 ) c = 30; // android-fm if( !str_cmp( class_table[c]->who_name, "android-h" ) ) sprintf( buf, "androidh" ); else if( !str_cmp( class_table[c]->who_name, "android-e" ) ) sprintf( buf, "androide" ); else if( !str_cmp( class_table[c]->who_name, "android-fm" ) ) sprintf( buf, "androidfm" ); else sprintf( buf, "%s", class_table[c]->who_name ); do_help( ch, buf ); return; } } i = 0; send_to_desc_color( "\n\r&c==============================================================================&D", d ); /* * for ( iClass = 0; iClass < MAX_PC_CLASS; iClass++ ) */ //for ( iClass = 0; iClass < 9; iClass++ ) for( iClass = 0; iClass < 31; iClass++ ) { if( iClass == 4 ) { //i++; continue; } if( iClass > 8 && iClass < 27 ) continue; //char letters[14] = "abcdefghijklmn"; char letters[15] = "abcdefghijklmno"; if( class_table[iClass]->who_name && class_table[iClass]->who_name[0] != '\0' ) { sprintf( buf, "\n\r&w (&W%2d&w) &c%-12s&w ('&R%c&w' for help)&D", i, class_table[iClass]->who_name, letters[i] ); send_to_desc_color( buf, d ); i++; } } send_to_desc_color( "\n\r&c==============================================================================&D", d ); sprintf( buf, "\n\r&wChoose the number of your race: &D" ); send_to_desc_color( buf, d ); return; } /* * if ( iClass == MAX_PC_CLASS */ if( iClass != 27 && iClass != 28 && iClass != 29 && iClass != 30 ) if( iClass > 8 || !class_table[iClass]->who_name || class_table[iClass]->who_name[0] == '\0' || !str_cmp( class_table[iClass]->who_name, "unused" ) ) { send_to_desc_color( "&wThat's not a race.\n\rWhat IS your race? &D", d ); return; } if( check_bans( ch, BAN_CLASS ) ) { send_to_desc_color( "&wThat race is not currently avaiable.\n\rWhat IS your race? &D", d ); return; } if( ch->race == 3 || ch->race == 5 || ch->race == 6 || ch->race == 27 ) { ch->pcdata->haircolor = 24; ch->pcdata->orignalhaircolor = 24; } else { send_to_desc_color( "\n\r&wPlease choose a hair color from the following list:&D\n\r", d ); buf[0] = '\0'; for( iClass = 0; iClass < ( MAX_HAIR - 2 ); iClass++ ) { sprintf( buf2, "&w[&W%2d&w] &g%-18.18s ", iClass, hair_color[iClass] ); b++; strcat( buf, buf2 ); if( ( b % 3 ) == 0 ) strcat( buf, "&D\n\r" ); } strcat( buf, "\n\r: " ); strcat( buf, "\r\r" ); send_to_desc_color( buf, d ); d->connected = CON_GET_NEW_HAIR; break; } case CON_GET_NEW_HAIR: argument = one_argument( argument, arg ); if( ch->race != 3 && ch->race != 5 && ch->race != 6 && ch->race != 27 ) { if( !str_cmp( arg, "help" ) ) { do_help( ch, argument ); send_to_desc_color( "&wPlease choose a hair color: &D", d ); return; } for( iClass = 0; iClass < ( MAX_HAIR - 2 ); iClass++ ) { if( toupper( arg[0] ) == toupper( hair_color[iClass][0] ) && !str_prefix( arg, hair_color[iClass] ) ) { ch->pcdata->haircolor = iClass; ch->pcdata->orignalhaircolor = iClass; break; } if( is_number( arg ) && atoi( arg ) == iClass ) { ch->pcdata->haircolor = iClass; ch->pcdata->orignalhaircolor = iClass; break; } } if( iClass == ( MAX_HAIR - 2 ) || !hair_color[iClass] || hair_color[iClass][0] == '\0' ) { send_to_desc_color( "&wThat's not a hair color.\n\rWhat IS it going to be? &D", d ); return; } } if( ch->race == 3 || ch->race == 6 ) { send_to_desc_color( "\n\r&wPlease choose a main body color from the following list:&D\n\r", d ); buf[0] = '\0'; buf2[0] = '\0'; b = 0; for( iClass = ( MAX_COMPLEXION - 17 ); iClass < ( MAX_COMPLEXION - 14 ); iClass++ ) { sprintf( buf2, "&w[&W%2d&W] &g%-15s&D", iClass, complexion[iClass] ); b++; strcat( buf, buf2 ); if( ( b % 4 ) == 0 ) strcat( buf, "\n\r" ); } strcat( buf, "\n\r: " ); strcat( buf, "\r\r\r\r" ); send_to_desc_color( buf, d ); d->connected = CON_GET_NEW_COMPLEXION; break; } else if( ch->race == 5 || ch->race == 27 ) { send_to_desc_color( "\n\r&wPlease choose a main body color from the following list:&D\n\r", d ); buf[0] = '\0'; buf2[0] = '\0'; b = 0; for( iClass = ( MAX_COMPLEXION - 14 ); iClass < ( MAX_COMPLEXION ); iClass++ ) { sprintf( buf2, "&w[&W%2d&w] &g%-15s&D", iClass, complexion[iClass] ); b++; strcat( buf, buf2 ); if( ( b % 4 ) == 0 ) strcat( buf, "\n\r" ); } strcat( buf, "\n\r: " ); strcat( buf, "\r\r\r\r" ); send_to_desc_color( buf, d ); d->connected = CON_GET_NEW_COMPLEXION; break; } else { send_to_desc_color( "\n\r&wPlease choose a complexion from the following list:&D\n\r", d ); buf[0] = '\0'; buf2[0] = '\0'; b = 0; for( iClass = 0; iClass < ( MAX_COMPLEXION - 17 ); iClass++ ) { sprintf( buf2, "&w[&W%2d&w] &g%-15s&D", iClass, complexion[iClass] ); b++; strcat( buf, buf2 ); if( ( b % 4 ) == 0 ) strcat( buf, "\n\r" ); } strcat( buf, "\n\r: " ); strcat( buf, "\r\r\r\r" ); send_to_desc_color( buf, d ); d->connected = CON_GET_NEW_COMPLEXION; break; } case CON_GET_NEW_COMPLEXION: argument = one_argument( argument, arg ); if( ch->race == 5 || ch->race == 27 ) { if( !str_cmp( arg, "help" ) ) { do_help( ch, argument ); send_to_desc_color( "&wPlease choose a main body color: &D", d ); return; } for( iClass = ( MAX_COMPLEXION - 14 ); iClass < ( MAX_COMPLEXION ); iClass++ ) { if( toupper( arg[0] ) == toupper( complexion[iClass][0] ) && !str_prefix( arg, complexion[iClass] ) ) { ch->pcdata->complexion = iClass; break; } if( is_number( arg ) && atoi( arg ) == iClass ) { ch->pcdata->complexion = iClass; break; } } if( iClass == ( MAX_COMPLEXION ) || !complexion[iClass] || complexion[iClass][0] == '\0' ) { send_to_desc_color( "&wThat's not a choice.\n\rWhat IS it going to be? &D", d ); return; } } else if( ch->race == 3 || ch->race == 6 ) { if( !str_cmp( arg, "help" ) ) { do_help( ch, argument ); send_to_desc_color( "&wPlease choose a main body color: &D", d ); return; } for( iClass = ( MAX_COMPLEXION - 17 ); iClass < ( MAX_COMPLEXION - 13 ); iClass++ ) { if( toupper( arg[0] ) == toupper( complexion[iClass][0] ) && !str_prefix( arg, complexion[iClass] ) ) { ch->pcdata->complexion = iClass; break; } if( is_number( arg ) && atoi( arg ) == iClass ) { ch->pcdata->complexion = iClass; break; } } if( iClass == ( MAX_COMPLEXION - 14 ) || !complexion[iClass] || complexion[iClass][0] == '\0' ) { send_to_desc_color( "&wThat's not a choice.\n\rWhat IS it going to be? &D", d ); return; } } else { if( !str_cmp( arg, "help" ) ) { do_help( ch, argument ); send_to_desc_color( "&wPlease choose complexion: &D", d ); return; } for( iClass = 0; iClass < ( MAX_COMPLEXION - 17 ); iClass++ ) { if( toupper( arg[0] ) == toupper( complexion[iClass][0] ) && !str_prefix( arg, complexion[iClass] ) ) { ch->pcdata->complexion = iClass; break; } if( is_number( arg ) && atoi( arg ) == iClass ) { ch->pcdata->complexion = iClass; break; } } if( iClass == ( MAX_COMPLEXION - 17 ) || !complexion[iClass] || complexion[iClass][0] == '\0' ) { send_to_desc_color( "&wThat's not a complexion.\n\rWhat IS it going to be? &D", d ); return; } } /* ------------------------------------------------------------------------------------- */ if( ch->race == 5 || ch->race == 27 ) { send_to_desc_color( "\n\r&wPlease choose a secondary body color from the following list:&D\n\r", d ); buf[0] = '\0'; buf2[0] = '\0'; b = 0; for( iClass = 0; iClass < ( MAX_SECONDARYCOLOR - 1 ); iClass++ ) { sprintf( buf2, "&w[&W%2d&w] &g%-15s&D", iClass, secondary_color[iClass] ); b++; strcat( buf, buf2 ); if( ( b % 4 ) == 0 ) strcat( buf, "\n\r" ); } strcat( buf, "\n\r: " ); strcat( buf, "\r\r\r\r" ); send_to_desc_color( buf, d ); d->connected = CON_GET_NEW_SECONDARYCOLOR; break; case CON_GET_NEW_SECONDARYCOLOR: /* * Black, Brown, Red, Blonde, Strawberry Blonde, Argent, Golden Blonde, Platinum Blonde, Light Brown */ argument = one_argument( argument, arg ); if( !str_cmp( arg, "help" ) ) { do_help( ch, argument ); send_to_desc_color( "&wPlease choose a secondary body color: &D", d ); return; } for( iClass = 0; iClass < ( MAX_SECONDARYCOLOR - 1 ); iClass++ ) { if( toupper( arg[0] ) == toupper( secondary_color[iClass][0] ) && !str_prefix( arg, secondary_color[iClass] ) ) { ch->pcdata->secondarycolor = iClass; break; } if( is_number( arg ) && atoi( arg ) == iClass ) { ch->pcdata->secondarycolor = iClass; break; } } if( iClass == ( MAX_SECONDARYCOLOR - 1 ) || !secondary_color[iClass] || secondary_color[iClass][0] == '\0' ) { send_to_desc_color( "&wThat's not a choice.\n\rWhat IS it going to be? &D", d ); return; } } /* ------------------------------------------------------------------------------------- */ send_to_desc_color( "\n\r&wPlease choose a eye color from the following list:&D\n\r", d ); buf[0] = '\0'; buf2[0] = '\0'; b = 0; for( iClass = 0; iClass < ( MAX_EYE - 3 ); iClass++ ) { sprintf( buf2, "&w[&W%2d&w] &g%-15s&D", iClass, eye_color[iClass] ); b++; strcat( buf, buf2 ); if( ( b % 4 ) == 0 ) strcat( buf, "\n\r" ); } strcat( buf, "\n\r: " ); strcat( buf, "\r\r\r\r" ); send_to_desc_color( buf, d ); d->connected = CON_GET_NEW_EYE; break; case CON_GET_NEW_EYE: /* * Black, Brown, Red, Blonde, Strawberry Blonde, Argent, Golden Blonde, Platinum Blonde, Light Brown */ argument = one_argument( argument, arg ); if( !str_cmp( arg, "help" ) ) { do_help( ch, argument ); send_to_desc_color( "&wPlease choose a hair color: &D", d ); return; } for( iClass = 0; iClass < ( MAX_EYE - 3 ); iClass++ ) { if( toupper( arg[0] ) == toupper( eye_color[iClass][0] ) && !str_prefix( arg, eye_color[iClass] ) ) { ch->pcdata->eyes = iClass; ch->pcdata->orignaleyes = iClass; break; } if( is_number( arg ) && atoi( arg ) == iClass ) { ch->pcdata->eyes = iClass; ch->pcdata->orignaleyes = iClass; break; } } if( iClass == ( MAX_EYE - 3 ) || !eye_color[iClass] || eye_color[iClass][0] == '\0' ) { send_to_desc_color( "&wThat's not a eye color.\n\rWhat IS it going to be? &D", d ); return; } /* ------------------------------------------------------------------------------------- */ send_to_desc_color( "\n\r&wPlease choose a build type from the following list:&D\n\r", d ); buf[0] = '\0'; buf2[0] = '\0'; b = 0; for( iClass = 0; iClass < ( MAX_BUILD ); iClass++ ) { sprintf( buf2, "&w[&W%2d&w] &g%-15s&D", iClass, build_type[iClass] ); b++; strcat( buf, buf2 ); if( ( b % 4 ) == 0 ) strcat( buf, "\n\r" ); } strcat( buf, "\n\r: " ); strcat( buf, "\r\r\r\r" ); send_to_desc_color( buf, d ); d->connected = CON_GET_NEW_BUILD; break; case CON_GET_NEW_BUILD: /* * Black, Brown, Red, Blonde, Strawberry Blonde, Argent, Golden Blonde, Platinum Blonde, Light Brown */ argument = one_argument( argument, arg ); if( !str_cmp( arg, "help" ) ) { do_help( ch, argument ); send_to_desc_color( "&wPlease choose a build type: &D", d ); return; } for( iClass = 0; iClass < ( MAX_BUILD ); iClass++ ) { if( toupper( arg[0] ) == toupper( build_type[iClass][0] ) && !str_prefix( arg, build_type[iClass] ) ) { ch->pcdata->build = iClass; break; } if( is_number( arg ) && atoi( arg ) == iClass ) { ch->pcdata->build = iClass; break; } } if( iClass == ( MAX_BUILD ) || !build_type[iClass] || build_type[iClass][0] == '\0' ) { send_to_desc_color( "&wThat's not a build type.\n\rWhat IS it going to be? &D", d ); return; } /* send_to_desc_color( "\n\rWould you like RIP, ANSI or no graphic/color support, (R/A/N)? ", d ); d->connected = CON_GET_WANT_RIPANSI; break; case CON_GET_WANT_RIPANSI: switch ( argument[0] ) { case 'r': case 'R': xSET_BIT(ch->act,PLR_RIP); xSET_BIT(ch->act,PLR_ANSI); break; case 'a': case 'A': xSET_BIT(ch->act,PLR_ANSI); break; case 'n': case 'N': break; default: write_to_buffer( d, "Invalid selection.\n\rRIP, ANSI or NONE? ", 0 ); return; } */ sprintf( log_buf, "%s@%s new %s %s.", ch->name, d->host, race_table[ch->race]->race_name, class_table[ch->class]->who_name ); log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); to_channel( log_buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL ); send_to_desc_color( "&wPress [&RENTER&w] &D", d ); show_title( d ); ch->level = 0; ch->canmajin = FALSE; ch->position = POS_STANDING; d->connected = CON_PRESS_ENTER; set_pager_color( AT_PLAIN, ch ); adjust_hiscore( "pkill", ch, ch->pcdata->pkills ); /* cronel hiscore */ adjust_hiscore( "sparwins", ch, ch->pcdata->spar_wins ); adjust_hiscore( "sparloss", ch, ch->pcdata->spar_loss ); adjust_hiscore( "mkills", ch, ch->pcdata->mkills ); adjust_hiscore( "deaths", ch, ( ch->pcdata->pdeaths + ch->pcdata->mdeaths ) ); update_plHiscore( ch ); adjust_hiscore( "played", ch, ( get_age( ch ) - 4 ) ); adjust_hiscore( "zeni", ch, ch->gold ); return; break; case CON_PRESS_ENTER: if( chk_watch( get_trust( ch ), ch->name, d->host ) ) /* --Gorog */ SET_BIT( ch->pcdata->flags, PCFLAG_WATCH ); else REMOVE_BIT( ch->pcdata->flags, PCFLAG_WATCH ); if( ch->position == POS_MOUNTED ) ch->position = POS_STANDING; set_pager_color( AT_PLAIN, ch ); if( xIS_SET( ch->act, PLR_RIP ) ) send_rip_screen( ch ); if( xIS_SET( ch->act, PLR_ANSI ) ) send_to_pager( "\033[2J", ch ); else send_to_pager( "\014", ch ); if( IS_IMMORTAL( ch ) ) do_help( ch, "imotd" ); if( ch->level == 50 ) do_help( ch, "amotd" ); if( ch->level < 50 && ch->level > 0 ) do_help( ch, "motd" ); if( ch->level == 0 ) do_help( ch, "nmotd" ); send_to_pager( "\n\rPress [ENTER] ", ch ); d->connected = CON_READ_MOTD; break; case CON_READ_MOTD: { char motdbuf[MAX_STRING_LENGTH]; sprintf( motdbuf, "\n\rWelcome to %s&D...\n\r", sysdata.mud_name ); send_to_desc_color( motdbuf, d ); } add_char( ch ); d->connected = CON_PLAYING; /* * hopefully clear up some ansi changing issues -Nopey */ set_char_color( AT_DGREEN, ch ); if( !xIS_SET( ch->act, PLR_ANSI ) && d->ansi == TRUE ) d->ansi = FALSE; else if( xIS_SET( ch->act, PLR_ANSI ) && d->ansi == FALSE ) d->ansi = TRUE; if( ch->level == 0 ) { OBJ_DATA *obj; int iLang; ch->pcdata->upgradeL = CURRENT_UPGRADE_LEVEL; // Removed the next 2 lines as a test -Karn 06.08.06 /*ch->pcdata->clan_name = STRALLOC( "" ); ch->pcdata->clan = NULL;*/ switch ( class_table[ch->class]->attr_prime ) { case APPLY_STR: ch->perm_str = 10; break; case APPLY_INT: ch->perm_int = 10; break; case APPLY_DEX: ch->perm_dex = 10; break; case APPLY_CON: ch->perm_con = 10; break; case APPLY_LCK: ch->perm_lck = 10; break; } ch->perm_str += race_table[ch->race]->str_plus; ch->perm_int += race_table[ch->race]->int_plus; ch->perm_dex += race_table[ch->race]->dex_plus; ch->perm_con += race_table[ch->race]->con_plus; ch->affected_by = race_table[ch->race]->affected; ch->perm_lck = number_range( 0, 30 ); ch->pcdata->permTstr = ch->perm_str; ch->pcdata->permTspd = ch->perm_dex; ch->pcdata->permTint = ch->perm_int; ch->pcdata->permTcon = ch->perm_con; ch->armor += race_table[ch->race]->ac_plus; ch->alignment += race_table[ch->race]->alignment; ch->attacks = race_table[ch->race]->attacks; ch->defenses = race_table[ch->race]->defenses; ch->saving_poison_death = race_table[ch->race]->saving_poison_death; ch->saving_wand = race_table[ch->race]->saving_wand; ch->saving_para_petri = race_table[ch->race]->saving_para_petri; ch->saving_breath = race_table[ch->race]->saving_breath; ch->saving_spell_staff = race_table[ch->race]->saving_spell_staff; ch->height = number_range( race_table[ch->race]->height * .9, race_table[ch->race]->height * 1.1 ); ch->weight = number_range( race_table[ch->race]->weight * .9, race_table[ch->race]->weight * 1.1 ); if( ( iLang = skill_lookup( "common" ) ) < 0 ) bug( "Nanny: cannot find common language." ); else ch->pcdata->learned[iLang] = 100; for( iLang = 0; lang_array[iLang] != LANG_UNKNOWN; iLang++ ) if( lang_array[iLang] == race_table[ch->race]->language ) break; if( lang_array[iLang] == LANG_UNKNOWN ) ; /* * bug( "Nanny: invalid racial language." ); */ else { if( ( iLang = skill_lookup( lang_names[iLang] ) ) < 0 ) bug( "Nanny: cannot find racial language." ); else ch->pcdata->learned[iLang] = 100; } /* * ch->resist += race_table[ch->race]->resist; drats */ /* * ch->susceptible += race_table[ch->race]->suscept; drats */ name_stamp_stats( ch ); ch->level = 1; ch->exp = 100; ch->pl = 100; ch->heart_pl = 100; ch->max_hit += race_table[ch->race]->hit; ch->max_mana += race_table[ch->race]->mana; ch->max_move = 100; ch->hit = UMAX( 1, ch->max_hit ); ch->mana = UMAX( 1, ch->max_mana ); ch->move = UMAX( 1, ch->max_move ); ch->train = 5; ch->max_train = 1; ch->pcdata->xTrain = 0; ch->pcdata->total_xTrain = 0; ch->practice = 0; ch->max_prac = 0; ch->max_energy = 1; ch->pcdata->admintalk = 0; ch->pcdata->age = 18; ch->canmajin = FALSE; ch->pcdata->sparcount = 0; if( is_saiyan( ch ) || is_hb( ch ) || is_icer( ch ) || is_bio( ch ) ) ch->pcdata->tail = TRUE; else ch->pcdata->tail = FALSE; if( is_bio( ch ) ) ch->alignment = 0; if( is_android( ch ) ) ch->pcdata->natural_ac_max = 500; if( is_bio( ch ) ) ch->pcdata->absorb_pl_mod = 6; /* * To make it so that saiyans and halfies start out * with the Oozaru mouth cannon. -Karma */ if( is_saiyan( ch ) || is_hb( ch ) ) ch->pcdata->learned[gsn_monkey_gun] = 95; sprintf( buf, "the %s", title_table[ch->class][ch->level][ch->sex == SEX_FEMALE ? 1 : 0] ); set_title( ch, buf ); ch->pcdata->creation_date = current_time; /* * Added by Narn. Start new characters with autoexit and autgold * already turned on. Very few people don't use those. */ xSET_BIT( ch->act, PLR_AUTOGOLD ); xSET_BIT( ch->act, PLR_AUTOEXIT ); xSET_BIT( ch->act, PLR_AUTO_COMPASS ); xSET_BIT( ch->act, PLR_SPAR ); SET_BIT( ch->pcdata->flags, PCFLAG_DEADLY ); xSET_BIT( ch->deaf, CHANNEL_FOS ); /* * Don't display old notes as 'unread' except for the announcment board */ for( i = 1; i < MAX_BOARD; i++ ) { for( catchup_notes = ch->pcdata->board->note_first; catchup_notes && catchup_notes->next; catchup_notes = catchup_notes->next ); if( !catchup_notes ) ; else { ch->pcdata->last_note[i] = catchup_notes->date_stamp; } } /* * Added by Brittany, Nov 24/96. The object is the adventurer's guide * to the realms of despair, part of Academy.are. */ { OBJ_INDEX_DATA *obj_ind = get_obj_index( 10333 ); if( obj_ind != NULL ) { obj = create_object( obj_ind, 0 ); obj_to_char( obj, ch ); equip_char( ch, obj, WEAR_HOLD ); } } if( !sysdata.WAIT_FOR_AUTH ) char_to_room( ch, get_room_index( ROOM_VNUM_SCHOOL ) ); else { char_to_room( ch, get_room_index( ROOM_AUTH_START ) ); ch->pcdata->auth_state = 1; SET_BIT( ch->pcdata->flags, PCFLAG_UNAUTHED ); add_to_auth( ch ); /* new auth */ } /* * Display_prompt interprets blank as default */ ch->pcdata->prompt = STRALLOC( "" ); /* * Attempt to make "stealing" easier to catch */ // Put in code to write Created IP to file // sprintf( ipBuf, "%s%s", PLAYFROM_DIR, capitalize( ch->name ) ); // if( !( ipFp = fopen( ipBuf, "a" ) ) ) // { // bug( "Write playfrom: Cannot open file.", 0 ); // perror( ipBuf ); // } // else // { // fprintf( ipFp, "CREATED: %s\n\r", ch->desc->host ); // fclose( ipFp ); // } } else if( !IS_IMMORTAL( ch ) && ch->pcdata->release_date > 0 && ch->pcdata->release_date > current_time ) { if( ch->in_room->vnum == 6 || ch->in_room->vnum == 8 || ch->in_room->vnum == 1206 ) char_to_room( ch, ch->in_room ); else char_to_room( ch, get_room_index( 8 ) ); } else if( !IS_IMMORTAL( ch ) && ch->in_room && ch->in_room->vnum == 2060 ) { act( AT_GREEN, "A Strange Force rips you from the Hyperbolic Time Chamber.", ch, NULL, NULL, TO_CHAR ); char_to_room( ch, get_room_index( 2059 ) ); } else if( ch->in_room && ( IS_IMMORTAL( ch ) || !xIS_SET( ch->in_room->room_flags, ROOM_PROTOTYPE ) ) ) { char_to_room( ch, ch->in_room ); } else if( IS_IMMORTAL( ch ) ) { char_to_room( ch, get_room_index( ROOM_VNUM_CHAT ) ); } else { char_to_room( ch, get_room_index( ROOM_VNUM_TEMPLE ) ); } /* * Attempt to make "stealing" easier to catch */ // Put in code to write Connected IP to file // sprintf( ipBuf, "%s%s", PLAYFROM_DIR, capitalize( ch->name ) ); // if( !( ipFp = fopen( ipBuf, "a" ) ) ) // { // bug( "Write playfrom: Cannot open file.", 0 ); // perror( ipBuf ); // } // else // { // fprintf( ipFp, "%s\n\r", ch->desc->host ); // fclose( ipFp ); // } /* * if ( get_timer( ch, TIMER_SHOVEDRAG ) > 0 ) * remove_timer( ch, TIMER_SHOVEDRAG ); * * if ( get_timer( ch, TIMER_PKILLED ) > 0 ) * remove_timer( ch, TIMER_PKILLED ); */ act( AT_ACTION, "$n has entered the game.", ch, NULL, NULL, TO_CANSEE ); if( ch->pcdata->pet ) { act( AT_ACTION, "$n returns to $s master from the Void.", ch->pcdata->pet, NULL, ch, TO_NOTVICT ); act( AT_ACTION, "$N returns with you to the realms.", ch, NULL, ch->pcdata->pet, TO_CHAR ); } ch->tmystic = 0; ch->mysticlearn = 0; ch->teaching = NULL; if( is_kaio( ch ) && ch->alignment < 0 ) ch->alignment = 0; if( is_demon( ch ) && ch->alignment > 0 ) ch->alignment = 0; remove_member( ch ); if( ch->pcdata->clan ) update_member( ch ); /* * For the logon pl tracker */ ch->logon_start = ch->exp; /* -Temporarily removed due to this possibly being bugged -Karma */ if( is_kaio( ch ) && ch->rank > 0 ) { int a = 0; bool found = FALSE; for( a = 0; a < 6; a++ ) if( !str_cmp( kaioshin[a], ch->name ) ) found = TRUE; if( !found ) { //bug("%s has a kaio rank but is not on the global list. Removing rank.",ch->name); ch_printf( ch, "&RYou have a kaio rank, but are not on the global list. Removing kaio rank.\n\r" ); ch->rank = 0; } found = FALSE; } if( is_demon( ch ) && ch->rank > 0 ) { int a = 0; bool found = FALSE; for( a = 0; a < 6; a++ ) if( !str_cmp( greaterdemon[a], ch->name ) ) found = TRUE; if( !found ) for( a = 0; a < 3; a++ ) if( !str_cmp( demonwarlord[a], ch->name ) ) found = TRUE; if( !found ) if( !str_cmp( demonking, ch->name ) ) found = TRUE; if( !found ) { //bug("%s has demon rank but is not on the global list. Removing rank.",ch->name); ch_printf( ch, "&RYou have a demon rank, but are not on the global list. Removing demon rank.\n\r" ); ch->rank = 0; } found = FALSE; } if( is_saiyan( ch ) && ch->rank > 0 ) { int a = 0; bool found = FALSE; for( a = 0; a < 4; a++ ) if( !str_cmp( saiyanelite[a], ch->name ) ) found = TRUE; if( !found ) for( a = 0; a < 2; a++ ) if( !str_cmp( saiyanprince[a], ch->name ) ) found = TRUE; if( !found ) if( !str_cmp( saiyanking, ch->name ) ) found = TRUE; if( !found ) { //bug("%s has saiyan rank but is not on the global list. Removing rank.",ch->name); ch_printf( ch, "&RYou have a saiyan rank, but are not on the global list. Removing saiyan rank.\n\r" ); ch->rank = 0; ch->pcdata->learned[gsn_lssj] = 0; if( IS_SET( ch->pcdata->flags, PCFLAG_KNOWSLSSJ ) ) REMOVE_BIT( ch->pcdata->flags, PCFLAG_KNOWSLSSJ ); } found = FALSE; } do_global_boards( ch, "" ); ch->dodge = FALSE; ch->block = FALSE; ch->ki_dodge = FALSE; ch->ki_cancel = FALSE; ch->ki_deflect = FALSE; do_look( ch, "auto" ); tax_player( ch ); /* Here we go, let's tax players to lower the gold * pool -- TRI */ mccp_interest( ch ); mail_count( ch ); check_loginmsg( ch ); check_auth_state( ch ); /* new auth */ if( !ch->was_in_room && ch->in_room == get_room_index( ROOM_VNUM_TEMPLE ) ) ch->was_in_room = get_room_index( ROOM_VNUM_TEMPLE ); else if( ch->was_in_room == get_room_index( ROOM_VNUM_TEMPLE ) ) ch->was_in_room = get_room_index( ROOM_VNUM_TEMPLE ); else if( !ch->was_in_room ) ch->was_in_room = ch->in_room; break; case CON_NOTE_TO: handle_con_note_to( d, argument ); break; case CON_NOTE_SUBJECT: handle_con_note_subject( d, argument ); break; /* subject */ case CON_NOTE_EXPIRE: handle_con_note_expire( d, argument ); break; case CON_NOTE_TEXT: handle_con_note_text( d, argument ); break; case CON_NOTE_FINISH: handle_con_note_finish( d, argument ); break; } return; } bool is_reserved_name( char *name ) { RESERVE_DATA *res; for( res = first_reserved; res; res = res->next ) if( ( *res->name == '*' && !str_infix( res->name + 1, name ) ) || !str_cmp( res->name, name ) ) return TRUE; return FALSE; } /* * Parse a name for acceptability. */ bool check_parse_name( char *name, bool newchar ) { /* * Names checking should really only be done on new characters, otherwise * we could end up with people who can't access their characters. Would * have also provided for that new area havoc mentioned below, while still * disallowing current area mobnames. I personally think that if we can * have more than one mob with the same keyword, then may as well have * players too though, so I don't mind that removal. -- Alty */ if( is_reserved_name( name ) && newchar ) return FALSE; /* * Outdated stuff -- Alty */ /* if ( is_name( name, "all auto immortal self someone god supreme demigod dog guard cityguard cat cornholio spock hicaine hithoric death ass fuck shit piss crap quit" ) ) return FALSE;*/ /* * Length restrictions. */ if( strlen( name ) < 3 ) return FALSE; if( strlen( name ) > 12 ) return FALSE; /* * Alphanumerics only. * Lock out IllIll twits. */ { char *pc; bool fIll; fIll = TRUE; for( pc = name; *pc != '\0'; pc++ ) { if( !isalpha( *pc ) ) return FALSE; if( LOWER( *pc ) != 'i' && LOWER( *pc ) != 'l' ) fIll = FALSE; } if( fIll ) return FALSE; } /* * Code that followed here used to prevent players from naming * themselves after mobs... this caused much havoc when new areas * would go in... */ return TRUE; } /* * Look for link-dead player to reconnect. */ bool check_reconnect( DESCRIPTOR_DATA * d, char *name, bool fConn ) { CHAR_DATA *ch; for( ch = first_char; ch; ch = ch->next ) { if( !IS_NPC( ch ) && ( !fConn || !ch->desc ) && ch->pcdata->filename && !str_cmp( name, ch->pcdata->filename ) ) { if( fConn && ch->switched ) { write_to_buffer( d, "Already playing.\n\rName: ", 0 ); d->connected = CON_GET_NAME; if( d->character ) { /* * clear descriptor pointer to get rid of bug message in log */ d->character->desc = NULL; free_char( d->character ); d->character = NULL; } return BERR; } if( fConn == FALSE ) { DISPOSE( d->character->pcdata->pwd ); d->character->pcdata->pwd = str_dup( ch->pcdata->pwd ); } else { /* * clear descriptor pointer to get rid of bug message in log */ d->character->desc = NULL; free_char( d->character ); d->character = ch; ch->desc = d; ch->timer = 0; send_to_char( "Reconnecting.\n\r", ch ); do_look( ch, "auto" ); act( AT_ACTION, "$n has reconnected.", ch, NULL, NULL, TO_CANSEE ); sprintf( log_buf, "%s@%s(%s) reconnected.", ch->pcdata->filename, d->host, d->user ); log_string_plus( log_buf, LOG_COMM, UMAX( sysdata.log_level, ch->level ) ); /* if ( ch->level < LEVEL_SAVIOR ) to_channel( log_buf, CHANNEL_MONITOR, "Monitor", ch->level ); */ d->connected = CON_PLAYING; check_auth_state( ch ); /* Link dead support -- Rantic */ /* * Inform the character of a note in progress and the possbility of continuation! */ if( ch->pcdata->in_progress ) send_to_char( "You have a note in progress. Type \"note write\" to continue it.\n\r", ch ); } return TRUE; } } return FALSE; } /* * Check if already playing. */ bool check_playing( DESCRIPTOR_DATA * d, char *name, bool kick ) { CHAR_DATA *ch; DESCRIPTOR_DATA *dold; int cstate; for( dold = first_descriptor; dold; dold = dold->next ) { if( dold != d && ( dold->character || dold->original ) && !str_cmp( name, dold->original ? dold->original->pcdata->filename : dold->character->pcdata->filename ) ) { cstate = dold->connected; ch = dold->original ? dold->original : dold->character; if( !ch->name || ( cstate != CON_PLAYING && cstate != CON_EDITING ) ) { write_to_buffer( d, "Already connected - try again.\n\r", 0 ); sprintf( log_buf, "%s already connected.", ch->pcdata->filename ); log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); return BERR; } if( !kick ) return TRUE; write_to_buffer( d, "Already playing... Kicking off old connection.\n\r", 0 ); write_to_buffer( dold, "Kicking off old connection... bye!\n\r", 0 ); close_socket( dold, FALSE ); /* * clear descriptor pointer to get rid of bug message in log */ d->character->desc = NULL; free_char( d->character ); d->character = ch; ch->desc = d; ch->timer = 0; if( ch->switched ) do_return( ch->switched, "" ); ch->switched = NULL; send_to_char( "Reconnecting.\n\r", ch ); do_look( ch, "auto" ); act( AT_ACTION, "$n has reconnected, kicking off old link.", ch, NULL, NULL, TO_CANSEE ); sprintf( log_buf, "%s@%s reconnected, kicking off old link.", ch->pcdata->filename, d->host ); log_string_plus( log_buf, LOG_COMM, UMAX( sysdata.log_level, ch->level ) ); /* if ( ch->level < LEVEL_SAVIOR ) to_channel( log_buf, CHANNEL_MONITOR, "Monitor", ch->level ); */ d->connected = cstate; return TRUE; } } return FALSE; } void stop_idling( CHAR_DATA * ch ) { ROOM_INDEX_DATA *was_in_room; /* * if ( !ch * || !ch->desc * || ch->desc->connected != CON_PLAYING * || !ch->was_in_room * || ch->in_room != get_room_index( ROOM_VNUM_LIMBO ) ) * return; */ if( !ch || !ch->desc || ch->desc->connected != CON_PLAYING || !IS_IDLE( ch ) ) return; /* * if ( IS_IMMORTAL(ch) ) * return; */ ch->timer = 0; was_in_room = ch->was_in_room; char_from_room( ch ); char_to_room( ch, was_in_room ); ch->was_in_room = ch->in_room; /* * ch->was_in_room = NULL; */ REMOVE_BIT( ch->pcdata->flags, PCFLAG_IDLE ); act( AT_ACTION, "$n has returned from the void.", ch, NULL, NULL, TO_ROOM ); return; } /* * Write to one char. (update for color -Goku) */ void send_to_char( const char *txt, CHAR_DATA * ch ) { if( !ch ) { bug( "Send_to_char: NULL *ch" ); return; } send_to_char_color( txt, ch ); return; } /* * Same as above, but converts &color codes to ANSI sequences.. */ void send_to_char_color( const char *txt, CHAR_DATA * ch ) { DESCRIPTOR_DATA *d; char *colstr; const char *prevstr = txt; char colbuf[20]; int ln; if( !ch ) { bug( "Send_to_char_color: NULL *ch" ); return; } if( !txt || !ch->desc ) return; d = ch->desc; switch ( sysdata.outBytesFlag ) { default: sysdata.outBytesOther += strlen( txt ); break; case LOGBOUTCHANNEL: sysdata.outBytesChannel += strlen( txt ); break; case LOGBOUTCOMBAT: sysdata.outBytesCombat += strlen( txt ); break; case LOGBOUTMOVEMENT: sysdata.outBytesMovement += strlen( txt ); break; case LOGBOUTINFORMATION: sysdata.outBytesInformation += strlen( txt ); break; case LOGBOUTPROMPT: sysdata.outBytesPrompt += strlen( txt ); break; case LOGBOUTINFOCHANNEL: sysdata.outBytesInfoChannel += strlen( txt ); break; } /* * Clear out old color stuff */ /* make_color_sequence(NULL, NULL, NULL);*/ while( ( colstr = strpbrk( prevstr, "&^}" ) ) != NULL ) { if( colstr > prevstr ) write_to_buffer( d, prevstr, ( colstr - prevstr ) ); ln = make_color_sequence( colstr, colbuf, d ); if( ln < 0 ) { prevstr = colstr + 1; break; } else if( ln > 0 ) write_to_buffer( d, colbuf, ln ); prevstr = colstr + 2; } if( *prevstr ) write_to_buffer( d, prevstr, 0 ); return; } void write_to_pager( DESCRIPTOR_DATA * d, const char *txt, int length ) { int pageroffset; /* Pager fix by thoric */ if( length <= 0 ) length = strlen( txt ); if( length == 0 ) return; if( !d->pagebuf ) { d->pagesize = MAX_STRING_LENGTH; CREATE( d->pagebuf, char, d->pagesize ); } if( !d->pagepoint ) { d->pagepoint = d->pagebuf; d->pagetop = 0; d->pagecmd = '\0'; } if( d->pagetop == 0 && !d->fcommand ) { d->pagebuf[0] = '\n'; d->pagebuf[1] = '\r'; d->pagetop = 2; } pageroffset = d->pagepoint - d->pagebuf; /* pager fix (goofup fixed 08/21/97) */ while( d->pagetop + length >= d->pagesize ) { if( d->pagesize > 32000 ) { bug( "Pager overflow. Ignoring.\n\r" ); d->pagetop = 0; d->pagepoint = NULL; DISPOSE( d->pagebuf ); d->pagesize = MAX_STRING_LENGTH; return; } d->pagesize *= 2; RECREATE( d->pagebuf, char, d->pagesize ); } d->pagepoint = d->pagebuf + pageroffset; /* pager fix (goofup fixed 08/21/97) */ strncpy( d->pagebuf + d->pagetop, txt, length ); d->pagetop += length; d->pagebuf[d->pagetop] = '\0'; return; } void send_to_pager( const char *txt, CHAR_DATA * ch ) { if( !ch ) { bug( "Send_to_pager: NULL *ch" ); return; } send_to_pager_color( txt, ch ); return; } void send_to_pager_color( const char *txt, CHAR_DATA * ch ) { DESCRIPTOR_DATA *d; char *colstr; const char *prevstr = txt; char colbuf[20]; int ln; if( !ch ) { bug( "Send_to_pager_color: NULL *ch" ); return; } if( !txt || !ch->desc ) return; d = ch->desc; ch = d->original ? d->original : d->character; if( IS_NPC( ch ) || !IS_SET( ch->pcdata->flags, PCFLAG_PAGERON ) ) { send_to_char_color( txt, d->character ); return; } switch ( sysdata.outBytesFlag ) { default: sysdata.outBytesOther += strlen( txt ); break; case LOGBOUTCHANNEL: sysdata.outBytesChannel += strlen( txt ); break; case LOGBOUTCOMBAT: sysdata.outBytesCombat += strlen( txt ); break; case LOGBOUTMOVEMENT: sysdata.outBytesMovement += strlen( txt ); break; case LOGBOUTINFORMATION: sysdata.outBytesInformation += strlen( txt ); break; case LOGBOUTPROMPT: sysdata.outBytesPrompt += strlen( txt ); break; case LOGBOUTINFOCHANNEL: sysdata.outBytesInfoChannel += strlen( txt ); break; } /* * Clear out old color stuff */ /* make_color_sequence(NULL, NULL, NULL);*/ while( ( colstr = strpbrk( prevstr, "&^}" ) ) != NULL ) { if( colstr > prevstr ) write_to_pager( d, prevstr, ( colstr - prevstr ) ); ln = make_color_sequence( colstr, colbuf, d ); if( ln < 0 ) { prevstr = colstr + 1; break; } else if( ln > 0 ) write_to_pager( d, colbuf, ln ); prevstr = colstr + 2; } if( *prevstr ) write_to_pager( d, prevstr, 0 ); return; } sh_int figure_color( sh_int AType, CHAR_DATA * ch ) { int at = AType; if( at >= AT_COLORBASE && at < AT_TOPCOLOR ) { at -= AT_COLORBASE; if( IS_NPC( ch ) || ch->pcdata->colorize[at] == -1 ) at = at_color_table[at].def_color; else at = ch->pcdata->colorize[at]; } if( at < 0 || at > AT_WHITE + AT_BLINK ) { //bug("Figure_color: color %d invalid.", at); at = AT_GREY; } return at; } void set_char_color( sh_int AType, CHAR_DATA * ch ) { char buf[16]; CHAR_DATA *och; if( !ch || !ch->desc ) return; och = ( ch->desc->original ? ch->desc->original : ch ); if( !IS_NPC( och ) && xIS_SET( och->act, PLR_ANSI ) ) { AType = figure_color( AType, och ); if( AType == 7 ) strcpy( buf, "\033[0;37m" ); else sprintf( buf, "\033[0;%d;%s%dm", ( AType & 8 ) == 8, ( AType > 15 ? "5;" : "" ), ( AType & 7 ) + 30 ); write_to_buffer( ch->desc, buf, strlen( buf ) ); } return; } void set_pager_color( sh_int AType, CHAR_DATA * ch ) { char buf[16]; CHAR_DATA *och; if( !ch || !ch->desc ) return; och = ( ch->desc->original ? ch->desc->original : ch ); if( !IS_NPC( och ) && xIS_SET( och->act, PLR_ANSI ) ) { AType = figure_color( AType, och ); if( AType == 7 ) strcpy( buf, "\033[0;37m" ); else sprintf( buf, "\033[0;%d;%s%dm", ( AType & 8 ) == 8, ( AType > 15 ? "5;" : "" ), ( AType & 7 ) + 30 ); send_to_pager( buf, ch ); ch->desc->pagecolor = AType; } return; } /* source: EOD, by John Booth <???> */ void ch_printf( CHAR_DATA * ch, char *fmt, ... ) { char buf[MAX_STRING_LENGTH * 2]; /* better safe than sorry */ va_list args; va_start( args, fmt ); vsprintf( buf, fmt, args ); va_end( args ); send_to_char( buf, ch ); } void pager_printf( CHAR_DATA * ch, char *fmt, ... ) { char buf[MAX_STRING_LENGTH * 2]; va_list args; va_start( args, fmt ); vsprintf( buf, fmt, args ); va_end( args ); send_to_pager( buf, ch ); } /* * Function to strip off the "a" or "an" or "the" or "some" from an object's * short description for the purpose of using it in a sentence sent to * the owner of the object. (Ie: an object with the short description * "a long dark blade" would return "long dark blade" for use in a sentence * like "Your long dark blade". The object name isn't always appropriate * since it contains keywords that may not look proper. -Thoric */ char *myobj( OBJ_DATA * obj ) { if( !str_prefix( "a ", obj->short_descr ) ) return obj->short_descr + 2; if( !str_prefix( "an ", obj->short_descr ) ) return obj->short_descr + 3; if( !str_prefix( "the ", obj->short_descr ) ) return obj->short_descr + 4; if( !str_prefix( "some ", obj->short_descr ) ) return obj->short_descr + 5; return obj->short_descr; } char *obj_short( OBJ_DATA * obj ) { static char buf[MAX_STRING_LENGTH]; if( obj->count > 1 ) { sprintf( buf, "%s (%d)", obj->short_descr, obj->count ); return buf; } return obj->short_descr; } /* * The primary output interface for formatted output. */ /* Major overhaul. -- Alty */ void ch_printf_color( CHAR_DATA * ch, char *fmt, ... ) { char buf[MAX_STRING_LENGTH * 2]; va_list args; va_start( args, fmt ); vsprintf( buf, fmt, args ); va_end( args ); send_to_char_color( buf, ch ); } void pager_printf_color( CHAR_DATA * ch, char *fmt, ... ) { char buf[MAX_STRING_LENGTH * 2]; va_list args; va_start( args, fmt ); vsprintf( buf, fmt, args ); va_end( args ); send_to_pager_color( buf, ch ); } #define MORPHNAME(ch) ((ch->morph&&ch->morph->morph)? \ ch->morph->morph->short_desc: \ IS_NPC(ch) ? ch->short_descr : ch->name) #define NAME(ch) (IS_NPC(ch) ? ch->short_descr : ch->name) char *act_string( const char *format, CHAR_DATA * to, CHAR_DATA * ch, const void *arg1, const void *arg2, int flags ) { static char *const he_she[] = { "it", "he", "she" }; static char *const him_her[] = { "it", "him", "her" }; static char *const his_her[] = { "its", "his", "her" }; static char *const che_she[] = { "It", "He", "She" }; static char *const chim_her[] = { "It", "Him", "Her" }; static char *const chis_her[] = { "Its", "His", "Her" }; static char buf[MAX_STRING_LENGTH]; char fname[MAX_INPUT_LENGTH]; char temp[MAX_STRING_LENGTH]; char *point = buf; const char *str = format; const char *i; CHAR_DATA *vch = ( CHAR_DATA * ) arg2; OBJ_DATA *obj1 = ( OBJ_DATA * ) arg1; OBJ_DATA *obj2 = ( OBJ_DATA * ) arg2; bool capitalize = FALSE; if( str[0] == '$' ) DONT_UPPER = FALSE; else DONT_UPPER = TRUE; while( *str != '\0' ) { capitalize = FALSE; if( *str != '$' ) { *point++ = *str++; continue; } ++str; if( !arg2 && *str >= 'A' && *str <= 'Z' ) { bug( "Act: missing arg2 for code %c:", *str ); bug( format ); i = " <@@@> "; } else { if( *str == '*' ) { capitalize = TRUE; str++; } switch ( *str ) { default: bug( "Act: bad code %c.", *str ); i = " <@@@> "; break; #ifdef I3 case '$': i = "$"; break; #endif case 't': i = ( char * )arg1; break; case 'T': i = ( char * )arg2; break; case 'n': if( ch->morph == NULL ) i = ( to ? PERS( ch, to ) : NAME( ch ) ); else if( !IS_SET( flags, STRING_IMM ) ) i = ( to ? MORPHPERS( ch, to ) : MORPHNAME( ch ) ); else { sprintf( temp, "(MORPH) %s", ( to ? PERS( ch, to ) : NAME( ch ) ) ); i = temp; } break; case 'N': if( vch->morph == NULL ) i = ( to ? PERS( vch, to ) : NAME( vch ) ); else if( !IS_SET( flags, STRING_IMM ) ) i = ( to ? MORPHPERS( vch, to ) : MORPHNAME( vch ) ); else { sprintf( temp, "(MORPH) %s", ( to ? PERS( vch, to ) : NAME( vch ) ) ); i = temp; } break; case 'e': if( ch->sex > 2 || ch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", ch->name, ch->sex ); i = "it"; } else i = capitalize ? che_she[URANGE( 0, ch->sex, 2 )] : he_she[URANGE( 0, ch->sex, 2 )]; break; case 'E': if( vch->sex > 2 || vch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", vch->name, vch->sex ); i = "it"; } else i = capitalize ? che_she[URANGE( 0, vch->sex, 2 )] : he_she[URANGE( 0, vch->sex, 2 )]; break; case 'm': if( ch->sex > 2 || ch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", ch->name, ch->sex ); i = "it"; } else i = capitalize ? chim_her[URANGE( 0, ch->sex, 2 )] : him_her[URANGE( 0, ch->sex, 2 )]; break; case 'M': if( vch->sex > 2 || vch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", vch->name, vch->sex ); i = "it"; } else i = capitalize ? chim_her[URANGE( 0, vch->sex, 2 )] : him_her[URANGE( 0, vch->sex, 2 )]; break; case 's': if( ch->sex > 2 || ch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", ch->name, ch->sex ); i = "its"; } else i = capitalize ? chis_her[URANGE( 0, ch->sex, 2 )] : his_her[URANGE( 0, ch->sex, 2 )]; break; case 'S': if( vch->sex > 2 || vch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", vch->name, vch->sex ); i = "its"; } else i = capitalize ? chis_her[URANGE( 0, vch->sex, 2 )] : his_her[URANGE( 0, vch->sex, 2 )]; break; case 'q': i = ( to == ch ) ? "" : "s"; break; case 'Q': i = ( to == ch ) ? "your" : his_her[URANGE( 0, ch->sex, 2 )]; break; case 'p': i = ( !to || can_see_obj( to, obj1 ) ? obj_short( obj1 ) : "something" ); break; case 'P': i = ( !to || can_see_obj( to, obj2 ) ? obj_short( obj2 ) : "something" ); break; case 'd': if( !arg2 || ( ( char * )arg2 )[0] == '\0' ) i = "door"; else { one_argument( ( char * )arg2, fname ); i = fname; } break; } } ++str; while( ( *point = *i ) != '\0' ) ++point, ++i; /* * #0 0x80c6c62 in act_string ( * format=0x81db42e "$n has reconnected, kicking off old link.", to=0x0, * ch=0x94fcc20, arg1=0x0, arg2=0x0, flags=2) at comm.c:2901 */ } strcpy( point, "\n\r" ); if( !DONT_UPPER ) buf[0] = UPPER( buf[0] ); DONT_UPPER = FALSE; return buf; } #undef NAME void act( sh_int AType, const char *format, CHAR_DATA * ch, const void *arg1, const void *arg2, int type ) { char *txt; CHAR_DATA *to; CHAR_DATA *vch = ( CHAR_DATA * ) arg2; /* * Discard null and zero-length messages. */ if( !format || format[0] == '\0' ) return; if( !ch ) { bug( "Act: null ch. (%s)", format ); return; } if( !ch->in_room ) to = NULL; else if( type == TO_CHAR ) to = ch; else to = ch->in_room->first_person; /* * ACT_SECRETIVE handling */ if( IS_NPC( ch ) && xIS_SET( ch->act, ACT_SECRETIVE ) && type != TO_CHAR ) return; if( type == TO_VICT ) { if( !vch ) { bug( "Act: null vch with TO_VICT." ); bug( "%s (%s)", ch->name, format ); return; } if( !vch->in_room ) { bug( "Act: vch in NULL room!" ); bug( "%s -> %s (%s)", ch->name, vch->name, format ); return; } to = vch; /* to = vch->in_room->first_person;*/ } if( MOBtrigger && type != TO_CHAR && type != TO_VICT && to ) { OBJ_DATA *to_obj; txt = act_string( format, NULL, ch, arg1, arg2, STRING_IMM ); if( HAS_PROG( to->in_room, ACT_PROG ) ) rprog_act_trigger( txt, to->in_room, ch, ( OBJ_DATA * ) arg1, ( void * )arg2 ); for( to_obj = to->in_room->first_content; to_obj; to_obj = to_obj->next_content ) if( HAS_PROG( to_obj->pIndexData, ACT_PROG ) ) oprog_act_trigger( txt, to_obj, ch, ( OBJ_DATA * ) arg1, ( void * )arg2 ); } /* * Anyone feel like telling me the point of looping through the whole * room when we're only sending to one char anyways..? -- Alty */ for( ; to; to = ( type == TO_CHAR || type == TO_VICT ) ? NULL : to->next_in_room ) { if( ( !to->desc && ( IS_NPC( to ) && !HAS_PROG( to->pIndexData, ACT_PROG ) ) ) || !IS_AWAKE( to ) ) continue; if( type == TO_CHAR && to != ch ) continue; if( type == TO_VICT && ( to != vch || to == ch ) ) continue; if( type == TO_ROOM && to == ch ) continue; if( type == TO_NOTVICT && ( to == ch || to == vch ) ) continue; if( type == TO_CANSEE && ( to == ch || ( !IS_IMMORTAL( to ) && !IS_NPC( ch ) && ( xIS_SET( ch->act, PLR_WIZINVIS ) && ( get_trust( to ) < ( ch->pcdata ? ch->pcdata-> wizinvis : 0 ) ) ) ) ) ) continue; if( IS_IMMORTAL( to ) ) txt = act_string( format, to, ch, arg1, arg2, STRING_IMM ); else txt = act_string( format, to, ch, arg1, arg2, STRING_NONE ); if( to->desc ) { set_char_color( AType, to ); send_to_char( txt, to ); } if( MOBtrigger ) { /* * Note: use original string, not string with ANSI. -- Alty */ mprog_act_trigger( txt, to, ch, ( OBJ_DATA * ) arg1, ( void * )arg2 ); } } MOBtrigger = TRUE; return; } /* char *default_fprompt( CHAR_DATA *ch ) { static char buf[60]; if (ch->race == race_lookup( "android" )) { strcpy(buf, "&D&z<&wDamage &w(&c%h&w) "); strcat(buf, "&wArmor &w(&c%z&w) "); strcat(buf, "&wEnergy &w(&c%m&w) "); strcat(buf, "&wFocus &w(&c%f&w)&z>"); if ( IS_NPC(ch) || IS_IMMORTAL(ch) ) strcat(buf, " %i%R&D\n\r"); else strcat(buf, " &D\n\r"); strcat(buf, "&D&z<&cTechlevel &c(&w%x&c/&w&W%P&c)&z>&w Enemy: &w(&R%y&w)&D&w "); } else { strcpy(buf, "&D&z<&wLifeforce &w(&c%h&w) "); strcat(buf, "&wArmor &w(&c%z&w) "); strcat(buf, "&wEnergy &w(&c%m&w) "); strcat(buf, "&wFocus &w(&c%f&w)&z>"); if ( IS_NPC(ch) || IS_IMMORTAL(ch) ) strcat(buf, " %i%R&D\n\r"); else strcat(buf, " &D\n\r"); strcat(buf, "&D&z<&cPowerlevel &c(&w%x&c/&w&W%P&c)&z>&w Enemy: &w(&R%y&w)&D&w "); } return buf; } */ char *default_fprompt( CHAR_DATA * ch ) { static char buf[60]; if( !IS_NPC( ch ) ) { switch ( ch->pcdata->battlePromptConfig ) { default: if( is_android( ch ) ) { strcpy( buf, "&D<Damage(&c%h&w) En(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "TL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "TL(%x/&B%P&w)>" ); else strcat( buf, "TL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } else { strcpy( buf, "&D<Life(&c%h&w) Ki(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "PL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "PL(%x/&B%P&w)>" ); else strcat( buf, "PL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } strcat( buf, "\n\r<Enemy(&R%y&w) Focus(&C%f&w) Armor(&c%z&w)> " ); break; case 1: if( is_android( ch ) ) { strcpy( buf, "&D<Damage(&c%h&w) En(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "TL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "TL(%x/&B%P&w)>" ); else strcat( buf, "TL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } else { strcpy( buf, "&D<Life(&c%h&w) Ki(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "PL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "PL(%x/&B%P&w)>" ); else strcat( buf, "PL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } strcat( buf, "\n\r<Enemy(&R%y&w) Focus(&C%f&w)> " ); break; case 2: if( is_android( ch ) ) { strcpy( buf, "&D<Damage(&c%h&w) En(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "TL(&Y%p&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "TL(&B%p&w)>" ); else strcat( buf, "TL(&W%p&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } else { strcpy( buf, "&D<Life(&c%h&w) Ki(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "PL(&Y%p&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "PL(&B%p&w)>" ); else strcat( buf, "PL(&W%p&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } strcat( buf, "\n\r<Enemy(&R%y&w) Focus(&C%f&w) Armor(&c%z&w)> " ); break; case 3: if( is_android( ch ) ) { strcpy( buf, "&D<Damage(&c%h&w) En(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "TL(&Y%p&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "TL(&B%p&w)>" ); else strcat( buf, "TL(&W%p&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } else { strcpy( buf, "&D<Life(&c%h&w) Ki(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "PL(&Y%p&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "PL(&B%p&w)>" ); else strcat( buf, "PL(&W%p&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } strcat( buf, "\n\r<Enemy(&R%y&w) Focus(&C%f&w)> " ); break; } } else { if( is_android( ch ) ) { strcpy( buf, "&D<Damage(&c%h&w) En(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "TL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "TL(%x/&B%P&w)>" ); else strcat( buf, "TL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } else { strcpy( buf, "&D<Life(&c%h&w) Ki(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "PL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "PL(%x/&B%P&w)>" ); else strcat( buf, "PL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } strcat( buf, "\n\r<Enemy(&R%y&w) Focus(&C%f&w) Armor(&c%z&w)> " ); } return buf; } char *default_prompt( CHAR_DATA * ch ) { static char buf[60]; /* if (ch->desc->psuppress_channel != 0); { if (ch->race == race_lookup("android")) strcpy(buf, "&D<D:%h E:%m> "); else strcpy(buf, "&D<L:%h K:%m> "); ch->desc->psuppress_channel = 0; return buf; } */ if( !IS_NPC( ch ) ) { switch ( ch->pcdata->normalPromptConfig ) { default: if( is_android( ch ) ) { strcpy( buf, "&D<Damage(&c%h&w) En(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "TL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "TL(%x/&B%P&w)>" ); else strcat( buf, "TL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); else strcat( buf, " " ); } else { strcpy( buf, "&D<Life(&c%h&w) Ki(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "PL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "PL(%x/&B%P&w)>" ); else strcat( buf, "PL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); else strcat( buf, " " ); } break; case 1: if( is_android( ch ) ) { strcpy( buf, "&D<Damage(&c%h&w) En(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "TL(&Y%p&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "TL(&B%p&w)>" ); else strcat( buf, "TL(&W%p&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); else strcat( buf, " " ); } else { strcpy( buf, "&D<Life(&c%h&w) Ki(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "PL(&Y%p&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "PL(&B%p&w)>" ); else strcat( buf, "PL(&W%p&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); else strcat( buf, " " ); } break; } } else { if( is_android( ch ) ) { strcpy( buf, "&D<Damage(&c%h&w) En(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "TL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "TL(%x/&B%P&w)>" ); else strcat( buf, "TL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); } else { strcpy( buf, "&D<Life(&c%h&w) Ki(&c%m&w) " ); if( ch->exp < ch->pl ) strcat( buf, "PL(%x/&Y%P&w)>" ); else if( ch->exp > ch->pl ) strcat( buf, "PL(%x/&B%P&w)>" ); else strcat( buf, "PL(%x/&W%P&w)>" ); if( IS_NPC( ch ) || IS_IMMORTAL( ch ) ) strcat( buf, " %i%R" ); else strcat( buf, " " ); } } return buf; } /* char *default_prompt( CHAR_DATA *ch ) { static char buf[60]; if (is_android(ch)) { strcpy(buf, "&D&z<&wDamage &w(&c%h&w) "); strcat(buf, "&wArmor &w(&c%z&w) "); strcat(buf, "&wEnergy &w(&c%m&w)&z>"); if ( IS_NPC(ch) || IS_IMMORTAL(ch) ) strcat(buf, " %i%R&D\n\r"); else strcat(buf, " &D\n\r"); strcat(buf, "&D&z<&cTechlevel &c(&w%x&c/&w&W%P&c)&z>&D&w "); } else { strcpy(buf, "&D&z<&wLifeforce &w(&c%h&w) "); strcat(buf, "&wArmor &w(&c%z&w) "); strcat(buf, "&wEnergy &w(&c%m&w)&z>"); if ( IS_NPC(ch) || IS_IMMORTAL(ch) ) strcat(buf, " %i%R&D\n\r"); else strcat(buf, " &D\n\r"); strcat(buf, "&D&z<&cPowerlevel &c(&w%x&c/&w&W%P&c)&z>&D&w "); } return buf; } */ int getcolor( char clr ) { static const char colors[16] = "xrgObpcwzRGYBPCW"; int r; for( r = 0; r < 16; r++ ) if( clr == colors[r] ) return r; return -1; } void display_prompt( DESCRIPTOR_DATA * d ) { CHAR_DATA *ch = d->character; CHAR_DATA *och = ( d->original ? d->original : d->character ); CHAR_DATA *victim; bool ansi = ( !IS_NPC( och ) && xIS_SET( och->act, PLR_ANSI ) ); const char *prompt; const char *helpstart = "<Type HELP START>"; char buf[MAX_STRING_LENGTH]; char *pbuf = buf; int stat, percent; long double stat_ld = -1; long double stat_ldLong = -1; if( !ch ) { bug( "display_prompt: NULL ch" ); return; } if( !IS_NPC( ch ) && !IS_SET( ch->pcdata->flags, PCFLAG_HELPSTART ) ) prompt = helpstart; else if( !IS_NPC( ch ) && ch->substate != SUB_NONE && ch->pcdata->subprompt && ch->pcdata->subprompt[0] != '\0' ) prompt = ch->pcdata->subprompt; else if( IS_NPC( ch ) || ( !ch->fighting && ( !ch->pcdata->prompt || !*ch->pcdata->prompt ) ) ) prompt = default_prompt( ch ); else if( ch->fighting ) { if( !ch->pcdata->fprompt || !*ch->pcdata->fprompt ) prompt = default_fprompt( ch ); else prompt = ch->pcdata->fprompt; } else prompt = ch->pcdata->prompt; if( ansi ) { strcpy( pbuf, "\033[0;37m" ); d->prevcolor = 0x07; pbuf += 7; } /* * Clear out old color stuff */ /* make_color_sequence(NULL, NULL, NULL);*/ for( ; *prompt; prompt++ ) { /* * '%' = prompt commands * Note: foreground changes will revert background to 0 (black) */ if( *prompt != '%' ) { *( pbuf++ ) = *prompt; continue; } ++prompt; if( !*prompt ) break; if( *prompt == *( prompt - 1 ) ) { *( pbuf++ ) = *prompt; continue; } switch ( *( prompt - 1 ) ) { default: bug( "Display_prompt: bad command char '%c'.", *( prompt - 1 ) ); break; case '%': *pbuf = '\0'; stat = 0x80000000; switch ( *prompt ) { case '%': *pbuf++ = '%'; *pbuf = '\0'; break; case 'a': if( ch->level >= 10 ) stat = ch->alignment; else if( IS_GOOD( ch ) ) strcpy( pbuf, "good" ); else if( IS_EVIL( ch ) ) strcpy( pbuf, "evil" ); else strcpy( pbuf, "neutral" ); break; case 'A': sprintf( pbuf, "%s%s%s", IS_AFFECTED( ch, AFF_INVISIBLE ) ? "I" : "", IS_AFFECTED( ch, AFF_HIDE ) ? "H" : "", IS_AFFECTED( ch, AFF_SNEAK ) ? "S" : "" ); break; case 'C': /* Tank */ if( !IS_IMMORTAL( ch ) ) break; if( !ch->fighting || ( victim = ch->fighting->who ) == NULL ) strcpy( pbuf, "N/A" ); else if( !victim->fighting || ( victim = victim->fighting->who ) == NULL ) strcpy( pbuf, "N/A" ); else { if( victim->max_hit > 0 ) percent = ( 100 * victim->hit ) / victim->max_hit; else percent = -1; if( percent >= 100 ) strcpy( pbuf, "perfect health" ); else if( percent >= 90 ) strcpy( pbuf, "slightly scratched" ); else if( percent >= 80 ) strcpy( pbuf, "few bruises" ); else if( percent >= 70 ) strcpy( pbuf, "some cuts" ); else if( percent >= 60 ) strcpy( pbuf, "several wounds" ); else if( percent >= 50 ) strcpy( pbuf, "nasty wounds" ); else if( percent >= 40 ) strcpy( pbuf, "bleeding freely" ); else if( percent >= 30 ) strcpy( pbuf, "covered in blood" ); else if( percent >= 20 ) strcpy( pbuf, "leaking guts" ); else if( percent >= 10 ) strcpy( pbuf, "almost dead" ); else strcpy( pbuf, "DYING" ); } break; case 'c': if( !IS_IMMORTAL( ch ) ) break; if( !ch->fighting || ( victim = ch->fighting->who ) == NULL ) strcpy( pbuf, "N/A" ); else { if( victim->max_hit > 0 ) percent = ( 100 * victim->hit ) / victim->max_hit; else percent = -1; if( percent >= 100 ) strcpy( pbuf, "perfect health" ); else if( percent >= 90 ) strcpy( pbuf, "slightly scratched" ); else if( percent >= 80 ) strcpy( pbuf, "few bruises" ); else if( percent >= 70 ) strcpy( pbuf, "some cuts" ); else if( percent >= 60 ) strcpy( pbuf, "several wounds" ); else if( percent >= 50 ) strcpy( pbuf, "nasty wounds" ); else if( percent >= 40 ) strcpy( pbuf, "bleeding freely" ); else if( percent >= 30 ) strcpy( pbuf, "covered in blood" ); else if( percent >= 20 ) strcpy( pbuf, "leaking guts" ); else if( percent >= 10 ) strcpy( pbuf, "almost dead" ); else strcpy( pbuf, "DYING" ); } break; case 'h': stat = ch->hit; break; case 'H': stat = ch->max_hit; break; case 'm': stat = ch->mana; break; case 'M': stat = ch->max_mana; break; case 'P': stat_ld = ch->pl; break; case 'p': stat_ldLong = ch->pl; break; case 'N': /* Tank */ if( !IS_IMMORTAL( ch ) ) break; if( !ch->fighting || ( victim = ch->fighting->who ) == NULL ) strcpy( pbuf, "N/A" ); else if( !victim->fighting || ( victim = victim->fighting->who ) == NULL ) strcpy( pbuf, "N/A" ); else { if( ch == victim ) strcpy( pbuf, "You" ); else if( IS_NPC( victim ) ) strcpy( pbuf, victim->short_descr ); else strcpy( pbuf, victim->name ); pbuf[0] = UPPER( pbuf[0] ); } break; case 'n': if( !IS_IMMORTAL( ch ) ) break; if( !ch->fighting || ( victim = ch->fighting->who ) == NULL ) strcpy( pbuf, "N/A" ); else { if( ch == victim ) strcpy( pbuf, "You" ); else if( IS_NPC( victim ) ) strcpy( pbuf, victim->short_descr ); else strcpy( pbuf, victim->name ); pbuf[0] = UPPER( pbuf[0] ); } break; case 'T': if( time_info.hour < 5 ) strcpy( pbuf, "night" ); else if( time_info.hour < 6 ) strcpy( pbuf, "dawn" ); else if( time_info.hour < 19 ) strcpy( pbuf, "day" ); else if( time_info.hour < 21 ) strcpy( pbuf, "dusk" ); else strcpy( pbuf, "night" ); break; case 'b': stat = 0; break; case 'B': stat = 0; break; case 'u': stat = num_descriptors; break; case 'U': stat = sysdata.maxplayers; break; case 'v': stat = ch->move; break; case 'V': stat = ch->max_move; break; case 'g': stat = ch->gold; break; case 'r': if( IS_IMMORTAL( och ) ) stat = ch->in_room->vnum; break; case 'F': if( IS_IMMORTAL( och ) ) sprintf( pbuf, "%s", ext_flag_string( &ch->in_room->room_flags, r_flags ) ); break; case 'R': if( xIS_SET( och->act, PLR_ROOMVNUM ) ) sprintf( pbuf, "<#%d> ", ch->in_room->vnum ); break; case 'x': stat_ld = ch->exp; break; case 'X': stat = exp_level( ch, ch->level + 1 ) - ch->exp; case 'y': if( !ch->fighting || ( victim = ch->fighting->who ) == NULL ) strcpy( pbuf, "N/A" ); else { stat = victim->hit; /* if ( victim->max_hit > 0 ) percent = (victim->hit); else percent = -1; if (percent >= 100) strcpy (pbuf, "|||\x1b[1;33m|||\x1b[1;32m||||"); else if (percent >= 90) strcpy (pbuf, "|||\x1b[1;33m|||\x1b[1;32m|||\x1b[1;31m-"); else if (percent >= 80) strcpy (pbuf, "|||\x1b[1;33m|||\x1b[1;32m||\x1b[1;31m--"); else if (percent >= 70) strcpy (pbuf, "|||\x1b[1;33m|||\x1b[1;32m|\x1b[1;31m---"); else if (percent >= 60) strcpy (pbuf, "|||\x1b[1;33m|||\x1b[1;31m----"); else if (percent >= 50) strcpy (pbuf, "|||\x1b[1;33m||\x1b[1;31m-----"); else if (percent >= 40) strcpy (pbuf, "|||\x1b[1;33m|\x1b[1;31m------"); else if (percent >= 30) strcpy (pbuf, "|||-------"); else if (percent >= 20) strcpy (pbuf, "||--------"); else if (percent >= 10) strcpy (pbuf, "|---------"); else strcpy (pbuf, "----------"); */ } break; case 'o': /* display name of object on auction */ if( auction->item ) strcpy( pbuf, auction->item->name ); break; case 'S': if( ch->style == STYLE_BERSERK ) strcpy( pbuf, "B" ); else if( ch->style == STYLE_AGGRESSIVE ) strcpy( pbuf, "A" ); else if( ch->style == STYLE_DEFENSIVE ) strcpy( pbuf, "D" ); else if( ch->style == STYLE_EVASIVE ) strcpy( pbuf, "E" ); else strcpy( pbuf, "S" ); break; case 'i': if( ( !IS_NPC( ch ) && xIS_SET( ch->act, PLR_WIZINVIS ) ) || ( IS_NPC( ch ) && xIS_SET( ch->act, ACT_MOBINVIS ) ) ) sprintf( pbuf, "(Invis %d) ", ( IS_NPC( ch ) ? ch->mobinvis : ch->pcdata->wizinvis ) ); else if( IS_AFFECTED( ch, AFF_INVISIBLE ) ) sprintf( pbuf, "(Invis) " ); break; case 'I': stat = ( IS_NPC( ch ) ? ( xIS_SET( ch->act, ACT_MOBINVIS ) ? ch->mobinvis : 0 ) : ( xIS_SET( ch->act, PLR_WIZINVIS ) ? ch->pcdata->wizinvis : 0 ) ); break; case 'z': stat = get_armor( ch ); break; case 'Z': stat = get_maxarmor( ch ); break; case 'f': stat = ch->focus; break; } if( stat != 0x80000000 ) { if( stat >= 1000 ) sprintf( pbuf, "%s", num_punct( stat ) ); else sprintf( pbuf, "%d", stat ); } if( stat_ld != -1 ) { sprintf( pbuf, "%s", abbNumLD( stat_ld ) ); stat_ld = -1; } else if( stat_ldLong != -1 ) { sprintf( pbuf, "%s", num_punct_ld( stat_ldLong ) ); stat_ldLong = -1; } // sprintf(pbuf, "%s", abbNumLD(stat_ld)); // sprintf(pbuf, "%s", num_punct_ld(stat_ld)); pbuf += strlen( pbuf ); break; } } *pbuf = '\0'; send_to_char( buf, ch ); return; } int make_color_sequence( const char *col, char *code, DESCRIPTOR_DATA * d ) { // CHAR_DATA *ch = (d->original ? d->original : d->character); const char *ctype = col; int ln; // bool ansi = ( !IS_NPC(ch) && xIS_SET( ch->act, PLR_ANSI ) ); col++; if( !*col ) ln = -1; else if( *ctype != '&' && *ctype != '^' && *ctype != '}' ) { bug( "colorcode: command '%c' not '&', '^' or '}'", *ctype ); ln = -1; } else if( *col == *ctype ) { code[0] = *col; code[1] = '\0'; ln = 1; } else if( !d->ansi ) ln = 0; else { /* * Foreground text - non-blinking */ if( *ctype == '&' ) { switch ( *col ) { default: code[0] = *ctype; code[1] = *col; code[2] = '\0'; return 2; case 'i': /* Italic text */ case 'I': strcpy( code, ANSI_ITALIC ); break; case 'v': /* Reverse colors */ case 'V': strcpy( code, ANSI_REVERSE ); break; case 'u': /* Underline */ case 'U': strcpy( code, ANSI_UNDERLINE ); break; case 'd': /* Player's client default color */ strcpy( code, ANSI_RESET ); break; case 'D': /* Reset to custom color for whatever is being displayed */ strcpy( code, ANSI_RESET ); /* Yes, this reset here is quite necessary to cancel out other things */ strcat( code, ANSI_GREY ); // strcat( code, color_str( ch->desc->pagecolor, ch ) ); break; case 'x': /* Black */ strcpy( code, ANSI_BLACK ); break; case 'O': /* Orange/Brown */ strcpy( code, ANSI_ORANGE ); break; case 'c': /* Cyan */ strcpy( code, ANSI_CYAN ); break; case 'z': /* Dark Grey */ strcpy( code, ANSI_DGREY ); break; case 'g': /* Dark Green */ strcpy( code, ANSI_DGREEN ); break; case 'G': /* Light Green */ strcpy( code, ANSI_GREEN ); break; case 'P': /* Pink/Light Purple */ strcpy( code, ANSI_PINK ); break; case 'r': /* Dark Red */ strcpy( code, ANSI_DRED ); break; case 'b': /* Dark Blue */ strcpy( code, ANSI_DBLUE ); break; case 'w': /* Grey */ strcpy( code, ANSI_GREY ); break; case 'Y': /* Yellow */ strcpy( code, ANSI_YELLOW ); break; case 'C': /* Light Blue */ strcpy( code, ANSI_LBLUE ); break; case 'p': /* Purple */ strcpy( code, ANSI_PURPLE ); break; case 'R': /* Red */ strcpy( code, ANSI_RED ); break; case 'B': /* Blue */ strcpy( code, ANSI_BLUE ); break; case 'W': /* White */ strcpy( code, ANSI_WHITE ); break; } } /* * Foreground text - blinking */ if( *ctype == '}' ) { switch ( *col ) { default: code[0] = *ctype; code[1] = *col; code[2] = '\0'; return 2; case 'x': /* Black */ strcpy( code, BLINK_BLACK ); break; case 'O': /* Orange/Brown */ strcpy( code, BLINK_ORANGE ); break; case 'c': /* Cyan */ strcpy( code, BLINK_CYAN ); break; case 'z': /* Dark Grey */ strcpy( code, BLINK_DGREY ); break; case 'g': /* Dark Green */ strcpy( code, BLINK_DGREEN ); break; case 'G': /* Light Green */ strcpy( code, BLINK_GREEN ); break; case 'P': /* Pink/Light Purple */ strcpy( code, BLINK_PINK ); break; case 'r': /* Dark Red */ strcpy( code, BLINK_DRED ); break; case 'b': /* Dark Blue */ strcpy( code, BLINK_DBLUE ); break; case 'w': /* Grey */ strcpy( code, BLINK_GREY ); break; case 'Y': /* Yellow */ strcpy( code, BLINK_YELLOW ); break; case 'C': /* Light Blue */ strcpy( code, BLINK_LBLUE ); break; case 'p': /* Purple */ strcpy( code, BLINK_PURPLE ); break; case 'R': /* Red */ strcpy( code, BLINK_RED ); break; case 'B': /* Blue */ strcpy( code, BLINK_BLUE ); break; case 'W': /* White */ strcpy( code, BLINK_WHITE ); break; } } /* * Background color */ if( *ctype == '^' ) { switch ( *col ) { default: code[0] = *ctype; code[1] = *col; code[2] = '\0'; return 2; case 'x': /* Black */ strcpy( code, BACK_BLACK ); break; case 'r': /* Dark Red */ strcpy( code, BACK_DRED ); break; case 'g': /* Dark Green */ strcpy( code, BACK_DGREEN ); break; case 'O': /* Orange/Brown */ strcpy( code, BACK_ORANGE ); break; case 'b': /* Dark Blue */ strcpy( code, BACK_DBLUE ); break; case 'p': /* Purple */ strcpy( code, BACK_PURPLE ); break; case 'c': /* Cyan */ strcpy( code, BACK_CYAN ); break; case 'w': /* Grey */ strcpy( code, BACK_GREY ); break; } } ln = strlen( code ); } if( ln <= 0 ) *code = '\0'; return ln; } void set_pager_input( DESCRIPTOR_DATA * d, char *argument ) { while( isspace( *argument ) ) argument++; d->pagecmd = *argument; return; } bool pager_output( DESCRIPTOR_DATA * d ) { register char *last; CHAR_DATA *ch; int pclines; register int lines; bool ret; if( !d || !d->pagepoint || d->pagecmd == -1 ) return TRUE; ch = d->original ? d->original : d->character; pclines = UMAX( ch->pcdata->pagerlen, 5 ) - 1; switch ( LOWER( d->pagecmd ) ) { default: lines = 0; break; case 'b': lines = -1 - ( pclines * 2 ); break; case 'r': lines = -1 - pclines; break; case 'n': lines = 0; pclines = 0x7FFFFFFF; /* As many lines as possible */ break; case 'q': d->pagetop = 0; d->pagepoint = NULL; flush_buffer( d, TRUE ); DISPOSE( d->pagebuf ); d->pagesize = MAX_STRING_LENGTH; return TRUE; } while( lines < 0 && d->pagepoint >= d->pagebuf ) if( *( --d->pagepoint ) == '\n' ) ++lines; if( *d->pagepoint == '\n' && *( ++d->pagepoint ) == '\r' ) ++d->pagepoint; if( d->pagepoint < d->pagebuf ) d->pagepoint = d->pagebuf; for( lines = 0, last = d->pagepoint; lines < pclines; ++last ) if( !*last ) break; else if( *last == '\n' ) ++lines; if( *last == '\r' ) ++last; if( last != d->pagepoint ) { if( !write_to_descriptor( d->descriptor, d->pagepoint, ( last - d->pagepoint ) ) ) return FALSE; d->pagepoint = last; } while( isspace( *last ) ) ++last; if( !*last ) { d->pagetop = 0; d->pagepoint = NULL; flush_buffer( d, TRUE ); DISPOSE( d->pagebuf ); d->pagesize = MAX_STRING_LENGTH; return TRUE; } d->pagecmd = -1; if( xIS_SET( ch->act, PLR_ANSI ) ) if( write_to_descriptor( d->descriptor, ANSI_LBLUE, 0 ) == FALSE ) return FALSE; if( ( ret = write_to_descriptor( d->descriptor, "(C)ontinue, (N)on-stop, (R)efresh, (B)ack, (Q)uit: [C] ", 0 ) ) == FALSE ) return FALSE; if( xIS_SET( ch->act, PLR_ANSI ) ) { char buf[32]; sprintf( buf, "%s", color_str( d->pagecolor, ch ) ); } return ret; } #ifdef WIN32 void shutdown_mud( char *reason ); void bailout( void ) { echo_to_all( AT_IMMORT, "MUD shutting down by system operator NOW!!", ECHOTAR_ALL ); shutdown_mud( "MUD shutdown by system operator" ); log_string( "MUD shutdown by system operator" ); Sleep( 5000 ); /* give "echo_to_all" time to display */ mud_down = TRUE; /* This will cause game_loop to exit */ service_shut_down = TRUE; /* This will cause characters to be saved */ fflush( stderr ); return; } #endif bool check_total_ip( DESCRIPTOR_DATA * dnew ) { DESCRIPTOR_DATA *d; CHAR_DATA *vch; int ip_total = 0; bool ch = TRUE; bool is_nolimit = FALSE; bool linkdead = FALSE; if( !sysdata.check_plimit ) return FALSE; if( dnew->character->level >= sysdata.level_noplimit ) return FALSE; for( d = first_descriptor; d; d = d->next ) { if( d == dnew ) { continue; } vch = d->character; if( !vch ) ch = FALSE; if( ch ) { if( !vch->desc ) linkdead = TRUE; if( !linkdead && dnew->character ) { if( !str_cmp( dnew->character->name, vch->name ) ) return FALSE; } } #ifdef DNS_SLAVE if( ch && !str_cmp( d->host, dnew->host ) && vch->level >= sysdata.level_noplimit ) is_nolimit = TRUE; if( !linkdead && !str_cmp( d->host, dnew->host ) ) ip_total++; #else if( ch && !str_cmp( d->host, dnew->host ) && vch->level >= sysdata.level_noplimit ) is_nolimit = TRUE; if( !linkdead && !str_cmp( d->host, dnew->host ) ) ip_total++; #endif } if( is_nolimit ) return FALSE; if( ip_total >= sysdata.plimit ) return TRUE; return FALSE; } char *color_str( sh_int AType, CHAR_DATA * ch ) { if( !ch ) { bug( "color_str: NULL ch!", 0 ); return ( "" ); } if( IS_NPC( ch ) || !xIS_SET( ch->act, PLR_ANSI ) ) return ( "" ); switch ( AType ) { case 0: return ( ANSI_BLACK ); break; case 1: return ( ANSI_DRED ); break; case 2: return ( ANSI_DGREEN ); break; case 3: return ( ANSI_ORANGE ); break; case 4: return ( ANSI_DBLUE ); break; case 5: return ( ANSI_PURPLE ); break; case 6: return ( ANSI_CYAN ); break; case 7: return ( ANSI_GREY ); break; case 8: return ( ANSI_DGREY ); break; case 9: return ( ANSI_RED ); break; case 10: return ( ANSI_GREEN ); break; case 11: return ( ANSI_YELLOW ); break; case 12: return ( ANSI_BLUE ); break; case 13: return ( ANSI_PINK ); break; case 14: return ( ANSI_LBLUE ); break; case 15: return ( ANSI_WHITE ); break; default: return ( ANSI_RESET ); break; } } /* * Remove Colour Codes - By Komarosu * * Colour code removal function, removes color codes but wont remove * double instances of chars ( &&, }}. ^^ etc.). * Not sure about memleaks, but i doubt any. * Modified from a C++ Class for string modification. * */ char *remove_color( char *str ) { /* * List of chars to remove */ char *list = "&}^"; int ii, jj, kk; char *aa = ( char * )strdup( str ); for( ii = 0, jj = strlen( aa ); ii < jj; ii++ ) { for( kk = 0; kk < 3; kk++ ) { if( aa[ii] == list[kk] ) { if( aa[ii + 1] != list[kk] ) strcpy( &aa[ii], &aa[ii + 2] ); ii += 2; break; } } } return aa; } #define NAME(ch) (IS_NPC(ch) ? ch->short_descr : ch->name) char *act2_string( const char *format, CHAR_DATA * to, CHAR_DATA * ch, const void *arg1, const void *arg2, int flags, const void *arg3 ) { static char *const he_she[] = { "it", "he", "she" }; static char *const him_her[] = { "it", "him", "her" }; static char *const his_her[] = { "its", "his", "her" }; static char buf[MAX_STRING_LENGTH]; char fname[MAX_INPUT_LENGTH]; char temp[MAX_STRING_LENGTH]; char *point = buf; const char *str = format; const char *i; CHAR_DATA *vch = ( CHAR_DATA * ) arg2; OBJ_DATA *obj1 = ( OBJ_DATA * ) arg1; OBJ_DATA *obj2 = ( OBJ_DATA * ) arg2; if( str[0] == '$' ) DONT_UPPER = FALSE; while( *str != '\0' ) { if( *str != '$' ) { *point++ = *str++; continue; } ++str; if( !arg2 && *str >= 'A' && *str <= 'Z' ) { bug( "Act: missing arg2 for code %c:", *str ); bug( format ); i = " <@@@> "; } else { switch ( *str ) { default: bug( "Act: bad code %c.", *str ); i = " <@@@> "; break; case 't': i = ( char * )arg1; break; case 'T': i = ( char * )arg3; break; case 'n': if( ch->morph == NULL ) i = ( to ? PERS( ch, to ) : NAME( ch ) ); else if( !IS_SET( flags, STRING_IMM ) ) i = ( to ? MORPHPERS( ch, to ) : MORPHNAME( ch ) ); else { sprintf( temp, "(MORPH) %s", ( to ? PERS( ch, to ) : NAME( ch ) ) ); i = temp; } break; case 'N': if( vch->morph == NULL ) i = ( to ? PERS( vch, to ) : NAME( vch ) ); else if( !IS_SET( flags, STRING_IMM ) ) i = ( to ? MORPHPERS( vch, to ) : MORPHNAME( vch ) ); else { sprintf( temp, "(MORPH) %s", ( to ? PERS( vch, to ) : NAME( vch ) ) ); i = temp; } break; case 'e': if( ch->sex > 2 || ch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", ch->name, ch->sex ); i = "it"; } else i = he_she[URANGE( 0, ch->sex, 2 )]; break; case 'E': if( vch->sex > 2 || vch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", vch->name, vch->sex ); i = "it"; } else i = he_she[URANGE( 0, vch->sex, 2 )]; break; case 'm': if( ch->sex > 2 || ch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", ch->name, ch->sex ); i = "it"; } else i = him_her[URANGE( 0, ch->sex, 2 )]; break; case 'M': if( vch->sex > 2 || vch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", vch->name, vch->sex ); i = "it"; } else i = him_her[URANGE( 0, vch->sex, 2 )]; break; case 's': if( ch->sex > 2 || ch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", ch->name, ch->sex ); i = "its"; } else i = his_her[URANGE( 0, ch->sex, 2 )]; break; case 'S': if( vch->sex > 2 || vch->sex < 0 ) { bug( "act_string: player %s has sex set at %d!", vch->name, vch->sex ); i = "its"; } else i = his_her[URANGE( 0, vch->sex, 2 )]; break; case 'q': i = ( to == ch ) ? "" : "s"; break; case 'Q': i = ( to == ch ) ? "your" : his_her[URANGE( 0, ch->sex, 2 )]; break; case 'p': i = ( !to || can_see_obj( to, obj1 ) ? obj_short( obj1 ) : "something" ); break; case 'P': i = ( !to || can_see_obj( to, obj2 ) ? obj_short( obj2 ) : "something" ); break; case 'd': if( !arg2 || ( ( char * )arg2 )[0] == '\0' ) i = "door"; else { one_argument( ( char * )arg2, fname ); i = fname; } break; } } ++str; while( ( *point = *i ) != '\0' ) ++point, ++i; /* * #0 0x80c6c62 in act_string ( * format=0x81db42e "$n has reconnected, kicking off old link.", to=0x0, * ch=0x94fcc20, arg1=0x0, arg2=0x0, flags=2) at comm.c:2901 */ } strcpy( point, "\n\r" ); if( !DONT_UPPER ) buf[0] = UPPER( buf[0] ); return buf; } #undef NAME void act2( sh_int AType, const char *format, CHAR_DATA * ch, const void *arg1, const void *arg2, int type, const void *arg3 ) { char *txt; CHAR_DATA *to; CHAR_DATA *vch = ( CHAR_DATA * ) arg2; /* * Discard null and zero-length messages. */ if( !format || format[0] == '\0' ) return; if( !ch ) { bug( "Act: null ch. (%s)", format ); return; } if( !ch->in_room ) to = NULL; else if( type == TO_CHAR ) to = ch; else to = ch->in_room->first_person; /* * ACT_SECRETIVE handling */ if( IS_NPC( ch ) && xIS_SET( ch->act, ACT_SECRETIVE ) && type != TO_CHAR ) return; if( type == TO_VICT ) { if( !vch ) { bug( "Act: null vch with TO_VICT." ); bug( "%s (%s)", ch->name, format ); return; } if( !vch->in_room ) { bug( "Act: vch in NULL room!" ); bug( "%s -> %s (%s)", ch->name, vch->name, format ); return; } to = vch; /* to = vch->in_room->first_person;*/ } if( MOBtrigger && type != TO_CHAR && type != TO_VICT && to ) { OBJ_DATA *to_obj; txt = act2_string( format, NULL, ch, arg1, arg2, STRING_IMM, arg3 ); if( HAS_PROG( to->in_room, ACT_PROG ) ) rprog_act_trigger( txt, to->in_room, ch, ( OBJ_DATA * ) arg1, ( void * )arg2 ); for( to_obj = to->in_room->first_content; to_obj; to_obj = to_obj->next_content ) if( HAS_PROG( to_obj->pIndexData, ACT_PROG ) ) oprog_act_trigger( txt, to_obj, ch, ( OBJ_DATA * ) arg1, ( void * )arg2 ); } /* * Anyone feel like telling me the point of looping through the whole * room when we're only sending to one char anyways..? -- Alty */ for( ; to; to = ( type == TO_CHAR || type == TO_VICT ) ? NULL : to->next_in_room ) { if( ( !to->desc && ( IS_NPC( to ) && !HAS_PROG( to->pIndexData, ACT_PROG ) ) ) || !IS_AWAKE( to ) ) continue; if( type == TO_CHAR && to != ch ) continue; if( type == TO_VICT && ( to != vch || to == ch ) ) continue; if( type == TO_ROOM && to == ch ) continue; if( type == TO_NOTVICT && ( to == ch || to == vch ) ) continue; if( type == TO_CANSEE && ( to == ch || ( !IS_IMMORTAL( to ) && !IS_NPC( ch ) && ( xIS_SET( ch->act, PLR_WIZINVIS ) && ( get_trust( to ) < ( ch->pcdata ? ch->pcdata-> wizinvis : 0 ) ) ) ) ) ) continue; if( IS_IMMORTAL( to ) ) txt = act2_string( format, to, ch, arg1, arg2, STRING_IMM, arg3 ); else txt = act2_string( format, to, ch, arg1, arg2, STRING_NONE, arg3 ); if( to->desc ) { if( AType == AT_COLORIZE ) { if( txt[0] == '&' ) send_to_char_color( txt, to ); else { set_char_color( AT_MAGIC, to ); send_to_char_color( txt, to ); } } else { set_char_color( AType, to ); send_to_char_color( txt, to ); } } if( MOBtrigger ) { /* * Note: use original string, not string with ANSI. -- Alty */ mprog_act_trigger( txt, to, ch, ( OBJ_DATA * ) arg1, ( void * )arg2 ); } } MOBtrigger = TRUE; return; } #ifdef MCCP /* * Ported to SMAUG by Garil of DOTDII Mud * aka Jesse DeFer <dotd@dotd.com> http://www.dotd.com * * revision 1: MCCP v1 support * revision 2: MCCP v2 support * revision 3: Correct MMCP v2 support * revision 4: clean up of write_to_descriptor() suggested by Noplex@CB * * See the web site below for more info. */ /* * mccp.c - support functions for mccp (the Mud Client Compression Protocol) * * see http://homepages.ihug.co.nz/~icecube/compress/ and README.Rom24-mccp * * Copyright (c) 1999, Oliver Jowett <icecube@ihug.co.nz>. * * This code may be freely distributed and used if this copyright notice is * retained intact. */ void *zlib_alloc( void *opaque, unsigned int items, unsigned int size ) { return calloc( items, size ); } void zlib_free( void *opaque, void *address ) { DISPOSE( address ); } bool process_compressed( DESCRIPTOR_DATA * d ) { int iStart = 0, nBlock, nWrite, len; if( !d->out_compress ) return TRUE; // Try to write out some data.. len = d->out_compress->next_out - d->out_compress_buf; if( len > 0 ) { // we have some data to write for( iStart = 0; iStart < len; iStart += nWrite ) { nBlock = UMIN( len - iStart, 4096 ); if( ( nWrite = write( d->descriptor, d->out_compress_buf + iStart, nBlock ) ) < 0 ) { if( errno == EAGAIN || errno == ENOSR ) break; return FALSE; } if( !nWrite ) break; } if( iStart ) { // We wrote "iStart" bytes if( iStart < len ) memmove( d->out_compress_buf, d->out_compress_buf + iStart, len - iStart ); d->out_compress->next_out = d->out_compress_buf + len - iStart; } } return TRUE; } char enable_compress[] = { IAC, SB, TELOPT_COMPRESS, WILL, SE, 0 }; char enable_compress2[] = { IAC, SB, TELOPT_COMPRESS2, IAC, SE, 0 }; bool compressStart( DESCRIPTOR_DATA * d, unsigned char telopt ) { z_stream *s; char buf[MAX_INPUT_LENGTH]; if( d->out_compress ) return TRUE; sprintf( buf, "Starting compression for descriptor %d", d->descriptor ); log_string_plus( buf, LOG_COMM, LEVEL_SUPREME ); // bug("Starting compression for descriptor %d", d->descriptor); CREATE( s, z_stream, 1 ); CREATE( d->out_compress_buf, unsigned char, COMPRESS_BUF_SIZE ); s->next_in = NULL; s->avail_in = 0; s->next_out = d->out_compress_buf; s->avail_out = COMPRESS_BUF_SIZE; s->zalloc = zlib_alloc; s->zfree = zlib_free; s->opaque = NULL; if( deflateInit( s, 9 ) != Z_OK ) { DISPOSE( d->out_compress_buf ); DISPOSE( s ); return FALSE; } if( telopt == TELOPT_COMPRESS ) write_to_descriptor( d->descriptor, enable_compress, 0 ); else if( telopt == TELOPT_COMPRESS2 ) write_to_descriptor( d->descriptor, enable_compress2, 0 ); else bug( "compressStart: bad TELOPT passed" ); d->compressing = telopt; d->out_compress = s; return TRUE; } bool compressEnd( DESCRIPTOR_DATA * d ) { unsigned char dummy[1]; char buf[MAX_INPUT_LENGTH]; if( !d->out_compress ) return TRUE; sprintf( buf, "Stopping compression for descriptor %d", d->descriptor ); log_string_plus( buf, LOG_COMM, LEVEL_SUPREME ); // bug("Stopping compression for descriptor %d", d->descriptor); d->out_compress->avail_in = 0; d->out_compress->next_in = dummy; if( deflate( d->out_compress, Z_FINISH ) != Z_STREAM_END ) return FALSE; if( !process_compressed( d ) ) /* try to send any residual data */ return FALSE; deflateEnd( d->out_compress ); DISPOSE( d->out_compress_buf ); DISPOSE( d->out_compress ); d->compressing = 0; return TRUE; } void do_compress( CHAR_DATA * ch, char *argument ) { char arg[MAX_STRING_LENGTH]; if( !ch->desc ) { send_to_char( "What descriptor?!\n", ch ); return; } argument = one_argument( argument, arg ); if( !str_cmp( arg, "on" ) ) { send_to_char( "Initiating compression....", ch ); compressStart( ch->desc, TELOPT_COMPRESS2 ); if( !ch->desc->out_compress ) send_to_char( "failure\n\r", ch ); else send_to_char( "success\n\r", ch ); } else if( !str_cmp( arg, "off" ) ) { send_to_char( "Terminating compression...", ch ); compressEnd( ch->desc ); if( !ch->desc->out_compress ) send_to_char( "success\n\r", ch ); else send_to_char( "failure\n\r", ch ); } else { send_to_char( "Syntax: compression <on/off>\n\r", ch ); send_to_char( "MCCP compression is currently: ", ch ); if( !ch->desc->out_compress ) send_to_char( "Off\n\r", ch ); else send_to_char( "On\n\r", ch ); } return; } #endif bool debug_what( char *file, int line, bool isastr ) { bug( "Bad str_cmp: %s, line %d, null %s", file, line, isastr ? "astr" : "bstr" ); \ return TRUE; }