w/**************************************************************************/ // nanny.cpp - Deal with sockets that haven't logged in yet /*************************************************************************** * The Dawn of Time v1.69r (c)1997-2004 Michael Garratt * * >> A number of people have contributed to the Dawn codebase, with the * * majority of code written by Michael Garratt - www.dawnoftime.org * * >> To use this source code, you must fully comply with all the licenses * * in licenses.txt... In particular, you may not remove this copyright * * notice. * *************************************************************************** * >> Original Diku Mud copyright (c)1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, & Katja Nyboe. * * >> Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * >> ROM 2.4 is copyright 1993-1995 Russ Taylor and has been brought to * * you by the ROM consortium: Russ Taylor(rtaylor@pacinfo.com), * * Gabrielle Taylor(gtaylor@pacinfo.com) & Brian Moore(rom@rom.efn.org) * * >> Oblivion 1.2 is copyright 1996 Wes Wagner * **************************************************************************/ #include "comm.h" #include "clan.h" #include "nanny.h" #include "roles.h" #include "intro.h" #include "offmoot.h" #include "namegen.h" #include "security.h" #include "channels.h" #include "msp.h" #include "pload.h" void roll_stats(connection_data *d); int count_creation_connections_per_hour(connection_data *d); bool check_connection(connection_data *d); void add_connection(connection_data *d); void nanny_read_motd(connection_data *d, char *); void nannysup_past_email_check(connection_data *d, const char *); void nannysup_setprime_stats( char_data *ch ); void mp_login_trigger( char_data *ch); void nsupport_newbie_alert( char_data *ch, bool created ); int name_confirmed; DECLARE_DO_FUN( do_doublexp ); #ifdef unix 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' }; #else const char echo_off_str [] = { '\0', '\0', '\0' }; const char echo_on_str [] = { '\0' }; const char go_ahead_str [] = { '\0' }; #endif // locals typedef struct creation_counter_data { struct creation_counter_data* next; char *ip; time_t time; } CREATION_COUNTER_DATA; static CREATION_COUNTER_DATA* creation_counter; DECLARE_DO_FUN( do_unread ); DECLARE_DO_FUN( do_raceinfo ); DECLARE_DO_FUN( do_classinfo ); void check_offline_letgain(char_data *ch); void check_death_update(void); void display_legal_message(char_data *ch); /**************************************************************************/ char * creation_titlebar(char *fmt, ...) { char buf [MSL]; char line[MSL]; static char returnbuf[MSL]; int spaces; // format all the text into buf va_list args; va_start(args, fmt); vsnprintf(buf, MSL, fmt, args); va_end(args); //=============================================================================\r\n", ch); if(c_str_len(buf)<1 || (c_str_len(buf)==1 && (buf[0]=='-' || buf[0]=='=') )) { return("\r\n"); } if(c_str_len(buf)>78) { sprintf(returnbuf,"%s\r\n",buf); return returnbuf; } spaces= (74-c_str_len(buf))/2; for(int j=0;j<spaces; j++) { line[j]='='; } line[spaces]='\0'; sprintf(returnbuf,"-%s`# `=c%s `&%s-\r\n",line, buf, line); return returnbuf; } /**************************************************************************/ void connected_to_CON_REROLL_STATS(connection_data *d) { roll_stats(d); add_connection(d); write_to_buffer(d,"If this is your first character here we recommending\r\n",0); write_to_buffer(d,"accepting these stats till you know what they all mean.\r\n",0); write_to_buffer(d,"(read the newbie doc on the web page for a light explaination)\r\n",0); d->connected_state = CON_REROLL_STATS; } /**************************************************************************/ // this is run when a player chooses to not customise, // if customisation is disabled in the gamesettings // or they have choosen a class which has customising disabled void nanny_new_player_not_customizing(connection_data *d) { char_data *ch=d->character; group_add(ch,class_table[ch->clss].default_group,true, 1); write_to_buffer( d, "\r\n", 2 ); if(IS_IRCCON(d)){ do_help( ch, "irc-motd" ); }else{ do_help( ch, "motd" ); } ch->hit_return_to_continue(); d->connected_state = CON_READ_MOTD; } /**************************************************************************/ void connected_to_CON_GET_ALLIANCE(connection_data *d) { write_to_buffer(d, "`cYou must now choose your alignment, alignment is very important as it \r\n" "`eaffects how you are expected to roleplay your character, and acting in a \r\n" "`cmanner out-of-alignment can invite penalties from the gods/goddesses of\r\n" "`cthe realm. Only pick an extreme alignment if you can and will live up\r\n" "`cto it, otherwise you might do yourself great harm.\r\n\r\n",0); if(GAMESETTING(GAMESET_MAX_ALIGN_RANGE22)){ write_to_buffer(d, "`cThe first half of you alignment is your ALLIANCE towards good and evil,\r\n" "`cthis value can be from -2 to 2 (including 0 being neutral) 2 being good\r\n" "`cand -2 being evil. \r\n`cWhat value do you want for your alliance?`c ",0); }else{ write_to_buffer(d, "`cThe first half of you alignment is your ALLIANCE towards good and evil,\r\n" "`cthis value can be from -3 to 3 (including 0 being neutral) 3 being extreme\r\n" "`cgood and -3 being extreme evil. \r\n`cWhat value do you want for your alliance?`c ",0); } if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } d->connected_state = CON_GET_ALLIANCE; } /**************************************************************************/ void connected_to_CON_GET_NEW_CLASS(connection_data *d) { int iClass; char buf[MSL]; strcpy( buf, "[" ); for( iClass = 0; !IS_NULLSTR(class_table[iClass].name); iClass++ ) { if(!class_table[iClass].creation_selectable || class_table[iClass].remort_number > d->creation_remort_number) continue; if(race_table[CH(d)->race]->class_exp[iClass]<1000) continue; if(iClass > 0 ){ strcat( buf, " " ); } strcat( buf, class_table[iClass].name ); if(!GAMESETTING(GAMESET_CLASS_CREATION_NO_STAR)){ if(IS_SET(class_table[iClass].flags, CLASSFLAG_MAGIC_ANTIPATHY)){ strcat( buf, "`Y*`c" ); } } } strcat( buf, "]"); CH(d)->println("`cSelect a class:"); CH(d)->wrapln(buf); if(!GAMESETTING(GAMESET_CLASS_CREATION_NO_STAR)){ CH(d)->println("`cnote: only the slave class is available to new players."); } if(!GAMESETTING5(GAMESET5_CLASSINFO_DISABLED_IN_CREATION)){ CH(d)->wraplnf( "Note: You can use `=Cclassinfo`c to obtain information about " "the prime attributes of classes, and base xp values for your " "choosen city (%s).", lowercase(race_table[CH(d)->race]->name)); } CH(d)->println("--> " ); if(IS_IRCCON(d)){ CH(d)->println(""); } d->connected_state = CON_GET_NEW_CLASS; } /**************************************************************************/ void nanny_char_version_updates(char_data *ch) { char tempbuf[MSL]; if(ch->version<8) { ch->practice+=3; ch->train+=2; int langsn=race_table[ch->race]->language->gsn; if(langsn>0){ ch->pcdata->learned[langsn]=100; } ch->language=race_table[ch->race]->language; } if(ch->version==0) { ch->practice=9; ch->train=5; } // reset players default short description if(ch->short_descr[0]=='\0') { sprintf(tempbuf,"a %s %s", (ch->sex==0 ? "sexless" : ch->sex==1 ? "male" : "female"), race_table[ch->race]->name); ch->short_descr= str_dup(tempbuf); } if(ch->version<9){ ch->printf("There is a problem with your character, version number is less than 9!\r\n" "Talk to the admin about it.\r\n"); } // end of stat rolling } /**************************************************************************/ void nanny_get_email(connection_data *c, const char *argument) { int result; char logbuf[MSL]; if(IS_NULLSTR(argument)){ write_to_buffer(c,"An email address is required for all characters.\r\n",0); write_to_buffer(c,"This information is kept private and not distributed.\r\n",0); write_to_buffer(c,"Please type in your email address now:\r\n",0); return; } CH(c)->printf("`=j%s`c", creation_titlebar("=")); logf("Checking for email ban with check_email_ban(%d, %s)", c->connected_socket, argument); result=check_email_ban(c, (char*)argument); logf("check_email_ban returned = %d", result); switch(result){ default: bugf("handle_get_email(): unknown result of %d from check_email_ban()!",result); do_abort(); // get a coredump and debug it break; case 0: // 0 accepted email, email an id code to them { char unlockbuf[20]; sprintf(unlockbuf,"%X", number_range(0x100000,0xFFFFFF)); // Log the email addy and details to file sprintf(logbuf,"%-13s from '%s' accepted email '%s', unlock = %s", CH(c)->name, c->remote_hostname, argument, unlockbuf); append_datetimestring_to_file( EMAILADDRESSES_FILE, logbuf); replace_string(CH(c)->pcdata->unlock_id, unlockbuf); email_descriptor_unlock_id(c); CH(c)->wraplnf("An email has been sent to '%s' " "with an unlock id", CH(c)->pcdata->email); } nannysup_past_email_check(c,argument); // finished handling the email checks break; case 1: // 1 email rejected, they need another attempt. // do nothing sprintf(logbuf,"%-13s from '%s' rejected email '%s'", CH(c)->name, c->remote_hostname, argument); append_datetimestring_to_file( EMAILADDRESSES_FILE, logbuf); break; case 2: // 2 if they should be disconnected connection_close(c); break; } } /**************************************************************************/ // run when waiting for the IP addy to resolve on a newbie void nanny_resolve_ip(connection_data *c, const char *argument) { if(c->resolved){ write_to_buffer( c,"\r\n",0); nannysup_email_check(c,argument); }else{ if(c->outtop==0){ c->write(".", 1); if(c->connected_state_pulse_counter%30==0){ c->write("\r\n",2); } } if(++c->connected_state_pulse_counter>PULSE_PER_SECOND*60){ // skip the whole process. c->resolved=true; write_to_buffer( c,"\r\nResolving timed out.",0); #ifdef WIN32 bugf("Resolver timed out for %s - if this happens all the " "time disable resolving in game settings or turn " "on local resolving. (note: the resolver hasnt' been " "fully developed for win9x)", c->remote_hostname); #else bugf("Resolver timed out for %s", c->remote_hostname); #endif } } } /**************************************************************************/ // called when someone has an id code they have to key in void nanny_enter_unlock_id(connection_data *d, const char *argument) { char buf[MSL]; if(IS_NULLSTR(argument)){ CH(d)->printf("Enter the unlock code for '%s' or type `=Cquit`c:`1", CH(d)->name); return; } if(!str_cmp("quit",argument)){ CH(d)->printf("Disconnecting you now, come back when you have the code.`1"); connection_close( d ); return; } if(!str_cmp("resend",argument)){ email_descriptor_unlock_id(d); CH(d)->wraplnf("An email has been sent to '%s' " "with an unlock id", CH(d)->pcdata->email); CH(d)->println("Download the email and type in the code."); return; } if(!str_cmp("change",argument)){ replace_string(CH(d)->pcdata->email,""); CH(d)->printf("`=j%s`c", creation_titlebar("CHANGE EMAIL ADDRESS")); CH(d)->wrapln( " You need to key in a new email address for your character. Then the mud " "will email you an unlock key, with which you can unlock your character a single time " "during the logon process."); CH(d)->wrapln( " The email address 9 times of out 10 will have to be a valid email accout " "as part of either the isps domain or an email account on the server you " "are connecting through... e.g. if you are connecting from " "`c207-112-146.ipt.aol.com`c it is most likely that the email " "address you enter must be something like `cusername@aol.com`c" "`1 The email address you type in will not be publically available... " "only being able to be seen by those who administer the mud.`1" "Please type in your email address now:"); d->connected_state = CON_RECHECK_EMAIL; return; } if(!str_cmp("delete",argument)){ sprintf(buf,"mv %s %s &", pfilename( CH(d)->name, CH(d)->pcdata->pfiletype), LOCKED_PFILES_DIR); system(buf); CH(d)->printf("%s has been deleted, disconnecting you now.`1", CH(d)->name); connection_close( d ); return; } if(!str_cmp(CH(d)->pcdata->unlock_id,argument)){ // correct code :) sprintf(buf, "%s - unlocked by %s", CH(d)->pcdata->unlock_id, d->remote_hostname); #define validatedhost ch->act&W?"..": // move the pfile if required { PFILE_TYPE pt=get_pfiletype(CH(d)); replace_string(CH(d)->pcdata->unlock_id, buf); PFILE_TYPE newpt=get_pfiletype(CH(d)); if(pt!=newpt){ rename(pfilename(CH(d)->name,pt), pfilename(CH(d)->name,newpt)); // move the file } CH(d)->pcdata->pfiletype=newpt; save_char_obj(CH(d)); // resave pfile } CH(d)->wraplnf( "`1%s has been unlocked and saved!!! well done, `1" "[press Y to continue]`1 :)",CH(d)->name); d->connected_state = CON_READ_MOTD; return; }else{ // incorrect code CH(d)->wraplnf( "`1`1The code '%s' is incorrect...`1" "This character '%s' can only be accessed with the unlock code that was " "automatically emailed to '%s'.`1`1If you have that unlock code enter it now, " "otherwise there are a few options - type:`1" "`=Cquit`c to be disconnected`1" "`=Cdelete`c to remove %s`1" "`=Cresend`c to have the unlock resent to '%s'`1" "`=Cchange`c to change your email address.", argument, CH(d)->name, CH(d)->pcdata->email, CH(d)->name, CH(d)->pcdata->email); return; } } /**************************************************************************/ void nannysup_email_check(connection_data *d, const char *argument) { if(!d->resolved && resolver_running){ write_to_buffer( d,"Resolving ip address, this can take up to 60 seconds... please wait.", 0); d->connected_state = CON_RESOLVE_IP; d->connected_state_pulse_counter=0; return; } replace_string(CH(d)->pcdata->created_from, FORMATF("%s(%s)", d->remote_ip,d->remote_hostname)); if(check_ban(d,BAN_EMAIL_REQ)){ CH(d)->printf("`=j%s`c", creation_titlebar("EMAIL VERFICATION REQUIRED")); CH(d)->wrapln( " It appears we have had problems at some stage with people that connect " "from the isp or server you are connecting to us from. In the past the " "only way to deal with these types of problem players was to ban all " "connections from the ISP or server involved. This was obviously " "not a long term solution to the problem so we have developed a system " "that allows you to enter your email address in, and the mud will email " "you an unlock key, with which you can unlock the character you are " "creating either at the end of the creation process, or you will be " "prompted for the unlock key when you next logon."); CH(d)->wrapln( " The email address 9 times of out 10 will have to be a valid email accout " "as part of either the isps domain or an email account on the server you " "are connecting through... e.g. if you are connecting from " "`c207-112-146.ipt.aol.com`c it is most likely that the email " "address you enter must be something like `cusername@aol.com`c" "`1 The email address you type in will not be publically available... " "only being able to be seen by those who administer the mud.`1" "Please type in your email address now:"); d->connected_state = CON_GET_EMAIL; }else{ nannysup_past_email_check(d,argument); } } /**************************************************************************/ void nanny_recheck_email(connection_data *d, const char *argument) { int result; char logbuf[MSL]; logf("Start handle_recheck_email"); if(IS_NULLSTR(argument)){ write_to_buffer(d,"An email address is required sorry.\r\n",0); write_to_buffer(d,"Please type in your email address now:\r\n",0); return; } CH(d)->printf("`=j%s`c", creation_titlebar("=")); logf("Going into check_recheck_email argument='%s'", argument); result=check_email_ban(d, (char*)argument); logf("Result = %d", result); switch(result){ default: bugf("handle_get_email(): unknown result of %d from check_email_ban()!",result); do_abort(); // get a coredump and debug it break; case 0: // 0 accepted email, and id code emailed to them. { char unlockbuf[20]; sprintf(unlockbuf,"%X", number_range(0x100000,0xFFFFFF)); // Log the email addy and details to file sprintf(logbuf,"%-13s from '%s' accepted email '%s', unlock = %s", CH(d)->name, d->remote_hostname, argument, unlockbuf); append_datetimestring_to_file( EMAILADDRESSES_FILE, logbuf); // move the pfile if required { save_char_obj(CH(d)); PFILE_TYPE oldpt=get_pfiletype(CH(d)); replace_string(CH(d)->pcdata->unlock_id, unlockbuf); email_descriptor_unlock_id(d); PFILE_TYPE pt=get_pfiletype(CH(d)); if(oldpt!=pt){ rename(pfilename(CH(d)->name,oldpt), pfilename(CH(d)->name,pt)); // move the file CH(d)->pcdata->pfiletype=pt; } save_char_obj(CH(d)); // update the lock key in the pfile } CH(d)->wraplnf("An email has been sent to '%s' " "with an unlock id.", CH(d)->pcdata->email); } nanny_read_motd(d,""); break; case 1: // 1 email rejected, they need another attempt. // do nothing sprintf(logbuf,"%-13s from '%s' rejected email '%s'", CH(d)->name, d->remote_hostname, argument); append_datetimestring_to_file( EMAILADDRESSES_FILE, logbuf); break; case 2: // 2 if they should be disconnected connection_close(d); break; } logf("End of handle_get_email()"); } /**************************************************************************/ // find the vnum players start in int get_startvnum(char_data *ch) { if(IS_IRC(ch) && get_room_index(ROOM_VNUM_STARTIRC)){ return ROOM_VNUM_STARTIRC; } if(get_room_index(ROOM_VNUM_STARTTELNET)){ return ROOM_VNUM_STARTTELNET; } return ROOM_VNUM_OOC; }; /**************************************************************************/ void do_save_gamesettings(char_data *ch, char *); //void do_outfit( char_data *ch, char *); /**************************************************************************/ void nanny_read_motd(connection_data *d, char *) { char_data *ch = d->character; char buf[MSL]; char automaticbuf[MSL]; BAN_DATA *pban; int sn; if(ch->pcdata == NULL || ch->pcdata->pwd[0] == '\0') { write_to_buffer( d, "Warning! Null password!\r\n",0 ); write_to_buffer( d, "Please report old password with bug.\r\n",0); write_to_buffer( d, "Type 'password null <new password>' to fix.\r\n",0); } reset_char(ch); if(!IS_NULLSTR(ch->pcdata->unlock_id) && str_len(ch->pcdata->unlock_id)==6){ CH(d)->printf("`1`=j%s`c", creation_titlebar("UNLOCK CODE REQUIRED")); if(d->newbie_creating){ save_char_obj(ch); ch->wraplnf( "An unlock code for %s was automatically emailed to %s earlier during " "the character creation process. This code is now " "required for the one time unlocking of %s. " "Your characters file has been saved, so if the email has not arrived yet " "you can type `=Cquit`c now to disconnect, and then login later after you " "have the code for unlocking.`1`1Enter your unlock code or type `=Cquit`c:", ch->name, ch->pcdata->email, ch->name); }else{ ch->wraplnf( "This character '%s' can only be accessed with the unlock code that was " "automatically emailed to '%s'.`1`1If you have that unlock code enter it now, " "otherwise there are a few options, type `=Cquit`c to be disconnected, " "`=Cdelete`c to remove %s, `=Cresend`c to have the unlock resent to '%s'" "`=Cchange`c to change your email address.", ch->name, ch->pcdata->email, ch->name, ch->pcdata->email); } d->connected_state = CON_ENTER_UNLOCK_ID; return; } pban=check_ban(d,BAN_EMAIL_REQ); if(pban){ logf("quick check '%s'", ch->pcdata->email); if(IS_NULLSTR(ch->pcdata->email)){ CH(d)->printf("`=j%s`c", creation_titlebar("EMAIL VERFICATION REQUIRED")); CH(d)->wrapln( " Since you created your character it appears we have had problems with " "with players that that connect from the isp or server you are connecting to us from. " "In the past the only way to deal with these types of problem players was to ban all " "connections from the ISP or server involved. This was obviously " "not a long term solution to the problem so we have developed a system " "that allows you to enter your email address in, and the mud will email " "you an unlock key, with which you can unlock your character a single time " "during the logon process."); CH(d)->wrapln( " The email address 9 times of out 10 will have to be a valid email accout " "as part of either the isps domain or an email account on the server you " "are connecting through... e.g. if you are connecting from " "`c207-112-146.ipt.aol.com`c it is most likely that the email " "address you enter must be something like `cusername@aol.com`c" "`1 The email address you type in will not be publically available... " "only being able to be seen by those who administer the mud.`1" "Please type in your email address now:"); d->connected_state = CON_RECHECK_EMAIL; return; }else{ // they have already typed their email at some stage earlier // check that is it still valid int result=check_email_ban(d, ch->pcdata->email); switch(result){ default: bugf("nanny_read_motd(): unknown result of %d from check_email_ban()!",result); do_abort(); // get a coredump and debug it break; case 0: // 0 still accepted email, do nothing break; case 1: // 1 email rejected since they last logged on CH(d)->printf("`=j%s`c", creation_titlebar("EMAIL VERFICATION REQUIRED")); CH(d)->wraplnf( " It appears we have had problems with with players that that connect from " "the isp or server you are connecting to us from. " "Your email address that you typed in is no longer accepted because the restrictions " "on email addresses from your ISP has been increased. As a result you will need " "to enter a different email address than '%s'", ch->pcdata->email); CH(d)->wrapln( " The email address 9 times of out 10 will have to be a valid email accout " "as part of either the isps domain or an email account on the server you " "are connecting through... e.g. if you are connecting from " "`c207-112-146.ipt.aol.com`c it is most likely that the email " "address you enter must be something like `cusername@aol.com`c" "`1 The email address you type in will not be publically available... " "only being able to be seen by those who administer the mud.`1" "Please type in your email address now:"); d->connected_state = CON_RECHECK_EMAIL; return; case 2: // 2 if they should be disconnected - currently not used by check_email_ban() connection_close(d); return; } } } // do multilogging checks replace_string(ch->remote_ip_copy,d->remote_ip); if(!HAS_CONFIG(ch,CONFIG_IGNORE_MULTILOGINS)){ for(char_data* pch=player_list; pch; pch=pch->next) { if(!HAS_CONFIG(pch,CONFIG_IGNORE_MULTILOGINS)){ if(!strcmp(ch->remote_ip_copy, pch->remote_ip_copy)){ d->multiple_logins=true; if(TRUE_CH(pch)->desc){ TRUE_CH(pch)->desc->multiple_logins=true; } }; } }; if(d->multiple_logins){ // notify wiznet multilog_alertf(ch, "`YPossible multilog by `c%s `Y(%s)", ch->name, ch->remote_ip_copy); } } // add them to the player_list ch->next_player = player_list; player_list = ch; // add them to the character list ch->next = char_list; char_list = ch; // safety check they have at least 0 karns if(ch->pcdata->karns<0){ check_death_update(); return; } ch->wraplnf("`1Welcome to %s. Enjoy your stay and try to leave smiling.", MUD_NAME); if (double_exp) { ch->printlnf( "\n\r`mCurrently, a `MDOUBLE-XP BONUS`m is in affect!`x" ); //return; } if(d->newbie_creating){ info_broadcast(ch, "Welcome %s, the newest traveler to this realm!", ch->name); d->newbie_creating=false; } ch->beginning_remort=0; d->connected_state = CON_PLAYING; // newbie starting out if(ch->level == 0 ) { // setting recall_vnum to the race recall int start_room; ch->level = 1; ch->exp = exp_per_level(ch,ch->pcdata->points); ch->hit = ch->max_hit; ch->mana = ch->max_mana; ch->move = ch->max_move; // allocate a new players starting amounts - Daos, Oct03 ch->train = game_settings->newbie_start_train; // default 5 ch->practice = game_settings->newbie_start_practice; // default 10 ch->silver = game_settings->newbie_start_silver; // default 100 ch->gold = game_settings->newbie_start_gold; // default 0 // mark most of the notes and ideas etc as read ch->pcdata->last_note = current_time-21600; // 6 hours ch->pcdata->last_idea = current_time-21600; ch->pcdata->last_penalty= current_time; ch->pcdata->last_news = current_time-172800; // 2 days ch->pcdata->last_changes= current_time-172800; if(get_obj_index(OBJ_VNUM_WORLD_MAP)) // load world map if it exists obj_to_char(create_object(get_obj_index(OBJ_VNUM_WORLD_MAP)),ch); if(get_obj_index(OBJ_VNUM_NEWBIE_GUIDE )) // load newbie guide if it exists obj_to_char(create_object(get_obj_index(OBJ_VNUM_NEWBIE_GUIDE)),ch); /*if(!GAMESETTING2(GAMESET2_DONT_AUTOOUTFIT_ON_NEWBIE_LOGIN)){ do_outfit(ch,""); }*/ /* // not supported at this stage if(GAMESETTING2(GAMESET2_NEWBIES_GET_ALL_MAPS)){ if(get_obj_index(OBJ_VNUM_EVIL_CITY_MAP)){ // load main evil city map if it exists obj_to_char(create_object(get_obj_index(OBJ_VNUM_EVIL_CITY_MAP)),ch); } if(get_obj_index(OBJ_VNUM_GOOD_CITY_MAP)){ // load main good city map if it exists obj_to_char(create_object(get_obj_index(OBJ_VNUM_GOOD_CITY_MAP)),ch); } }else{ if(race_table[ch->race]->recall_room==ROOM_VNUM_EVIL_RECALL) { // evil city if(get_obj_index(OBJ_VNUM_EVIL_CITY_MAP)){ // load main evil city map if it exists obj_to_char(create_object(get_obj_index(OBJ_VNUM_EVIL_CITY_MAP)),ch); } } else // good city { if(get_obj_index(OBJ_VNUM_GOOD_CITY_MAP)){ // load main good city map if it exists obj_to_char(create_object(get_obj_index(OBJ_VNUM_GOOD_CITY_MAP)),ch); } } } */ // give them their races newbie map if(race_table[ch->race]->newbie_map_vnum){ if(get_obj_index(race_table[ch->race]->newbie_map_vnum)){ obj_to_char(create_object(get_obj_index(race_table[ch->race]->newbie_map_vnum)),ch); } } // sending newbies to different starting locations based on connection start_room = get_startvnum(ch); if(get_room_index(start_room)!=NULL){ char_to_room( ch, get_room_index(start_room)); }else{ ch->printf( "BUG: the starting room for you city " "doesn't exist (room number %d).\r\n", start_room); bugf("BUG: the starting room for you city " "doesn't exist (room number %d).\r\n", start_room); if(get_room_index(ROOM_VNUM_LIMBO)==NULL){ bugf("BUG: get_room_index(ROOM_VNUM_LIMBO)==NULL" "ROOM_VNUM_LIMBO = %d! Saving game settings, change it in there.\r\n", ROOM_VNUM_LIMBO); do_save_gamesettings(NULL, ""); exit_error( 1 , "nanny_read_motd", "missing limbo!"); } char_to_room( ch, get_room_index(ROOM_VNUM_LIMBO)); } ch->println("\r\n"); }else if(ch->in_room){ char_to_room( ch, ch->in_room ); }else{ ROOM_INDEX_DATA *target_room= get_room_index(race_table[ch->race]->recall_room); if(!target_room){ bugf("nanny_read_motd(): Couldn't find room %d to put player in " "(as per race_table[ch->race]->recall_room)... putting them in limbo instead.", race_table[ch->race]->recall_room); target_room= get_room_index( ROOM_VNUM_LIMBO ); } char_to_room(ch, target_room); } if(!GAMESETTING2(GAMESET2_NO_SECOND_SKILL_REQUIRED)){ if(get_eq_char(ch, WEAR_SECONDARY) && !IS_NPC(ch) && ch->get_skill(gsn_second)<1){ logf("removing second weapon from %s - doesn't have the skill to use it", ch->name); unequip_char( ch, get_eq_char(ch, WEAR_SECONDARY)); } } // automatically turn on their IC object restrictions SET_CONFIG(ch,CONFIG_NAMES_BEFORE_SHORT); SET_CONFIG(ch, CONFIG_OBJRESTRICT); if(IS_SET(ch->act,PLR_AUTOMAP)){ SET_CONFIG(ch,CONFIG_AUTOMAP); REMOVE_BIT(ch->act,PLR_AUTOMAP); } // conversion to comm field if(IS_SET(ch->act, PLR_SPECIFY_SELF)){ SET_BIT(ch->comm,COMM_AUTOSELF); REMOVE_BIT(ch->act, PLR_SPECIFY_SELF); } /********************************************* * turn on all their channels automatically * *********************************************/ automaticbuf[0]='\0'; // quiet channels - turn off if(HAS_CHANNELOFF(ch, CHANNEL_QUIET)) { sprintf(buf,"Quiet mode has been automatically removed.\r\n"); strcat(automaticbuf,buf); REMOVE_CHANNELOFF(ch, CHANNEL_QUIET); } // OOC channel turn on/off depending on nochannel status if(IS_SET(ch->comm, COMM_NOCHANNELS)) { sprintf(buf, "`COOC channel has been automatically turned OFF.\r\n"); strcat(automaticbuf,buf); SET_CHANNELOFF(ch, CHANNEL_OOC); } else{ if(HAS_CHANNELOFF(ch, CHANNEL_OOC)) { sprintf(buf, "`COOC channel has been automatically turned ON.\r\n"); strcat(automaticbuf,buf); REMOVE_CHANNELOFF(ch, CHANNEL_OOC); } if(HAS_CHANNELOFF(ch, CHANNEL_CHAT)) { sprintf(buf, "`CCHAT channel has been automatically turned ON.\r\n"); strcat(automaticbuf,buf); REMOVE_CHANNELOFF(ch, CHANNEL_CHAT); } } // Q/A channel turn on if(HAS_CHANNELOFF(ch, CHANNEL_QA)) { sprintf(buf, "`gQ/A channel has been automatically turned ON.\r\n"); strcat(automaticbuf,buf); REMOVE_CHANNELOFF(ch, CHANNEL_QA); } // Newbie channel turn on if(HAS_CONFIG( TRUE_CH(ch), CONFIG_NONEWBIE )) { sprintf(buf, "`SNewbie channel has been automatically turned ON.\r\n"); strcat(automaticbuf,buf); REMOVE_CONFIG( TRUE_CH(ch), CONFIG_NONEWBIE ); } // AFK turn off if(IS_SET(ch->comm,COMM_AFK)) { sprintf(buf, "`MAFK mode has been automatically turned OFF.\r\n"); strcat(automaticbuf,buf); REMOVE_BIT(ch->comm,COMM_AFK); } if(ch->level>=LEVEL_IMMORTAL && IS_SET(ch->comm, COMM_NEWBIE_SUPPORT)){ ch->println("Removed your newbie support status as immortals always helps newbies ;)"); REMOVE_BIT(ch->comm, COMM_NEWBIE_SUPPORT); } // dont allow levels or trust greater than ABSOLUTE_MAX_LEVEL if(ch->level>ABSOLUTE_MAX_LEVEL) { ch->level= LEVEL_IMMORTAL; } if(ch->trust>ABSOLUTE_MAX_LEVEL) { ch->trust= LEVEL_IMMORTAL; } // turn on imm things if(ch->level >= LEVEL_IMMORTAL ) { // turn wizi on if desired if(HAS_CONFIG2(ch, CONFIG2_AUTOWIZILOGIN) && !INVIS_LEVEL(ch)) { sprintf(buf, "`YYou have been made wizi %d automatically.\r\n", LEVEL_IMMORTAL ); strcat(automaticbuf,buf); ch->invis_level=LEVEL_IMMORTAL; } // turn whoinvis on if desired if(HAS_CONFIG2(ch, CONFIG2_AUTOWHOINVISLOGIN) && IS_SET(TRUE_CH(ch)->comm, COMM_WHOVIS)) { REMOVE_BIT(TRUE_CH(ch)->comm, COMM_WHOVIS); sprintf( buf,"`rYou have been made whoinvis automatically.\r\n"); strcat(automaticbuf,buf); } // IMMTALK turn on if(HAS_CHANNELOFF(ch, CHANNEL_IMMTALK)){ sprintf(buf,"`=IImmortal channel has been automatically turned ON.\r\n"); strcat(automaticbuf,buf); REMOVE_CHANNELOFF(ch, CHANNEL_IMMTALK); } { for(int ti=0; ti<4; ti++){ if(!IS_SET(ch->wiznet[ti],WIZ_ON) && IS_SET(ch->wiznet[ti],WIZ_AUTOON) ) { switch(ti){ case 0: sprintf(buf, "Immwiznet autoactivated.\r\n"); break; case 1: sprintf(buf, "Wiznet autoactivated.\r\n"); break; case 2: sprintf(buf, "Wiznet2 autoactivated.\r\n"); break; case 3: sprintf(buf, "Wiznet3 autoactivated.\r\n"); break; } strcat(automaticbuf,buf); SET_BIT(ch->wiznet[ti],WIZ_ON); } } } } strcat(automaticbuf,"`c"); /****************************************************** * end of turning on all their channels automatically * ******************************************************/ // tell them about ircwhite and irc colour modes if appropriate if(IS_NEWBIE(ch) && IS_IRC(ch)){ ch->println("NOTE: You can change between black and white backgrounds by typing:"); ch->println(" `=Ccolour mode ircwhite`c and `=Ccolour mode irc`c."); } attach_know(ch); // setups ch->know stuff assertp(ch->know); if(!GAMESETTING2(GAMESET2_DONT_DISPLAY_WHO_4_LOGIN)){ // give autowho to everyone // - doesn't show imms automatically though for morts do_who( ch, "-noimm4morts" ); } // update their msp settings msp_update_char(ch); ch->printf(automaticbuf); check_offline_letgain(ch); // Reset lastused on all everything for imms if(ch->level>=LEVEL_IMMORTAL){ for( sn = 0; sn < MAX_SKILL; sn++ ){ if(!IS_NULLSTR(skill_table[sn].name)){ ch->pcdata->last_used[sn] = 0; } } } if(ch->pet){ if(ch->pet->in_room){ char_to_room(ch->pet,ch->pet->in_room); // restore to room they left from }else{ char_to_room(ch->pet,ch->in_room); // restore to room the master } act("$n has entered the realm.",ch->pet,NULL,NULL,TO_ROOM); } if(GAMESETTING5(GAMESET5_DEDICATED_PKILL_STYLE_MUD)) { char_data *victim=ch; int newlevel=UMAX(number_range(LEVEL_HERO-10,LEVEL_HERO-1),ch->level); ch->pcdata->p9999kills=ch->pcdata->p9999defeats=0; if(ch->level<10){ ch->pksafe=10; } if(!IS_LETGAINED(ch)){ SET_BIT(ch->act,PLR_CAN_ADVANCE); ch->println("`GYOU HAVE BEEN AUTOMATICALLY LETGAINED!!!.`c\r\n"); }; if(ch->level<LEVEL_IMMORTAL ){ int iLevel; int temp_prac; ch->pknoquit=4; ch->pksafe=3; ch->printf("`BAUTOMATICALLY SETTING YOU TO LEVEL %d!!!`c", newlevel); if(victim->level<newlevel){ temp_prac = victim->practice; victim->level = 1; victim->exp = exp_per_level(victim,victim->pcdata->points); victim->max_hit = 10; victim->max_mana = 100; victim->max_move = 100; victim->practice = 0; victim->hit = victim->max_hit; victim->mana = victim->max_mana; victim->move = victim->max_move; advance_level( victim ); victim->practice = temp_prac; } for( iLevel = ch->level ; iLevel < newlevel; iLevel++ ) { ch->level += 1; advance_level( ch); } ch->exp = exp_per_level(ch,ch->pcdata->points) * UMAX( 1, ch->level ); } { ch->println("`GSETTING ALL MORTAL SKILLS TO 101%.`c\r\n"); for( sn = 0; !IS_NULLSTR(skill_table[sn].name); sn++ ) { if(IS_SET(skill_table[sn].flags,SKFLAGS_NO_GAIN)){ continue; } if(IS_SPELL(sn) && !IS_SET(skill_table[sn].flags, SKFLAGS_LEVEL_SPGAIN) && !IS_SET(skill_table[sn].flags, SKFLAGS_STUDY_SPGAIN)) { continue; } // check if no class can get it bool a_class_can_get=false; { int cl; for(cl=0; !IS_NULLSTR(class_table[cl].name); cl++){ if(class_table[cl].creation_selectable){ if(skill_table[sn].rating[cl] > 0 && skill_table[sn].skill_level[cl]< LEVEL_IMMORTAL && skill_table[sn].skill_level[cl]>0) { a_class_can_get=true; } } } } if(!a_class_can_get){ continue; } victim->pcdata->learned[sn] = 101; } } reset_char(victim); victim->max_hit+=number_range(40,200); victim->max_mana+=number_range(40,200); victim->max_move+=number_range(40,200); victim->gold+=number_range(40,400); // login restore victim->subdued = false; if(!IS_NPC(victim) && victim->pcdata->tired!=-1) { victim->pcdata->tired=0; } affect_strip(victim,gsn_plague); affect_strip(victim,gsn_poison); affect_strip(victim,gsn_blindness); affect_strip(victim,gsn_sleep); affect_strip(victim,gsn_curse); affect_strip(victim,gsn_cause_fear); affect_strip(victim,gsn_fear_magic); victim->hit = victim->max_hit; victim->mana = victim->max_mana; victim->move = victim->max_move; victim->pcdata->tired=0; update_pos( victim); ch->println( "`MYOU HAVE BEEN AUTOMATICALLY BOOSTED AND RESTORED!!!.`c"); ch->printlnf( "`YYOU ARE PK SAFE FOR %d MINUTES!!!.`c",ch->pksafe); // announce their arrival if(!IS_IMMORTAL(ch)){ pkill_broadcast("%s has entered the realm of death! [Pk=0.Pd=0,L=%d]", ch->name, ch->level); } } // automatically letgain remorted players if(ch->remort>0 && !IS_LETGAINED(ch)){ SET_BIT(ch->act,PLR_CAN_ADVANCE); ch->println("`GYOU HAVE BEEN AUTOMATICALLY LETGAINED!!!.`c\r\n"); } ch->mxp_send_init(); do_look( ch, "brief" ); act( "$n has entered the realm.", ch, NULL, NULL, TO_ROOM ); //info_broadcast(ch, "%s has entered the realm.", ch->name); if(IS_IRCCON(d)){ sprintf(buf, "`B%s has joined the game via IRC. [%s] (lvl %d, remort %d)`c", ch->name, ch->desc?ch->desc->remote_hostname:"no_descriptor", ch->level, ch->remort); }else{ sprintf(buf, "%s has joined the game via telnet. [%s] (lvl %d, remort %d)", ch->name, ch->desc?ch->desc->remote_hostname:"no_descriptor", ch->level, ch->remort); } wiznet(buf,ch,NULL, WIZ_LOGINS,0,UMIN(get_trust(ch), MAX_LEVEL)); if(ch->level <= 10 && !HAS_CONFIG( ch, CONFIG_NONEWBIE )) nsupport_newbie_alert( ch, true ); laston_login(ch); // record the time the character logged on do_unread(ch,""); // display a legal notice about olc creation if(HAS_SECURITY(ch, 1) && !HAS_CONFIG2(ch, CONFIG2_READ_BUILDER_LEGAL)){ display_legal_message(ch); } // tell MAX_LEVEL to set up their security. if(IS_TRUSTED(ch, MAX_LEVEL) && GET_SECURITY(ch)<1){ ch->titlebar("INCREASE YOUR OLC SECURITY?"); ch->wraplnf("`cYour olc security is currently set to 0, you need a security " "of %d to edit the game settings (by typing `=Cgameedit confirm`c). " "You can increase your olc security to 9 (the maximum) by typing " "`=Cset char self security 9`c", GAMEEDIT_MINSECURITY); ch->wraplnf("`cHint: to list all the olc editors available, type `=Ccommand edit`c " "for the ones commonly used by builders and `=Cwiz edit`c for the " "immortal/administrative editors."); ch->titlebar("`S[The above message disappears once you have a security higher than 0]"); } // tell users to upgrade their mud client if they have one with known issues if(!GAMESETTING2(GAMESET2_NO_MSG_ABOUT_OLD_MUDCLIENTS)){ if(ch->desc && IS_SET(ch->desc->flags, CONNECTFLAG_MXP_SECURE_PREFIX_EACH_LINE) ){ ch->titlebar("THERE ARE KNOWN MXP ISSUES WITH YOUR CURRENT MUD CLIENT"); ch->wrapln("`cThis mud makes heavy use of MXP... there are known " "bugs in your particular mud client (MXP and MCCP). It is " "recommended that you update your mud client if an update " "is available, or try another " "client - such as `cMuClient`c (available from " "`Bhttp://www.muclient.com`c)`1`1Alternatively if you notice " "unexpected output on your screen while using this client you may " "disable MXP and MCCP (view menu -> preferences -> " "general -> mxp) then restart the client."); ch->titlebar(""); } } // message to tell mushclient users to turn off the forced link colour if(ch->desc && !IS_NULLSTR(ch->desc->mxp_options) && strstr(ch->desc->mxp_options, "use_custom_link_colour=1")){ ch->titlebar("MXP RECOMMENDATION"); ch->println("Turn 'use custom link colour' mxp option off in your mud client!"); ch->wrapln("`cThis mud makes heavy use of colours in MXP links (especially in olc)... " "currently your mud client is configured to ignore the muds " "colour for links and has the 'use custom link colour' mxp option on..." " It is strongly recommended that you turn this option off for a better " "mudding experience. (Try Ctrl+Alt+U to do this)."); ch->titlebar(""); } // mobprog login trigger mp_login_trigger( ch); // offline moot kickin check_pending_moot(ch); // record their entry into the game into their plog if they have one if (!IS_NPC(ch) && IS_SET(ch->act, PLR_LOG)){ append_playerlog( ch, FORMATF("%s has entered the game. (left level %d), room=%d, lasticroom=%d", ch->name, ch->level, ch->in_room?ch->in_room->vnum:0, ch->last_ic_room?ch->last_ic_room->vnum:0)); } } /**************************************************************************/ void nanny_get_name(connection_data *d, char *argument) { char_data *ch; bool pfile_loaded_okay; char buf[MSL]; if(IS_NULLSTR(argument)){ write_to_buffer( d, "You can't have a blank name, type 'new' to create a new character,\r\n" "'quit' to disconnect, or type your characters name - try again.\r\n", 0); write_to_buffer(d, LOGIN_PROMPT, 0); return; } if(!str_cmp(argument,"quit")){ connection_close( d ); return; } if(!str_cmp(argument,"dawnftp") || !str_cmp(argument,"mudftp")){ logf("DawnFTP connection %d starting.", d->connected_socket); // 00 code indicates unsupported // 01 code indicates continue write_to_buffer(d, "\n:DAWNFTP:01 v1:transfering to mudftp authentication state.\n", 0); d->connected_state=CON_FTP_AUTH; return; } // check for invalid characters if(strstr(".", argument) || strstr("\\", argument) || strstr("/", argument)){ write_to_buffer( d, "Invalid characters in name, " "try again.\r\nName:", 0); return; } argument=capitalize(argument); pfile_loaded_okay= load_char_obj( d, argument ); ch = d->character; d->newbie_creating = false; // do checks on what was read in // check for multiple pfiles found if(ch->pcdata->pfiletype==PFILE_MULTIPLE){ ch->wraplnf("For some reason multiple copies of pfiles " "for '%s' found... to avoid loading the incorrect copy, your pfile " "can not be loaded. Create a new character and then write a note to " "admin once in the game.", ch->name); ch->print("Name:"); return; } // check for levels/trust/security etc if(pfile_loaded_okay) { int maxsecurity=0; int maxtrust=0; int maxlevel=LEVEL_HERO; switch(ch->pcdata->pfiletype){ case PFILE_LOCKED: break; case PFILE_NORMAL: break; case PFILE_BUILDER: maxsecurity=9; break; case PFILE_TRUSTED: maxsecurity=9; maxtrust=MAX_LEVEL; break; case PFILE_IMMORTAL: maxsecurity=9; maxtrust=ABSOLUTE_MAX_LEVEL; maxlevel=ABSOLUTE_MAX_LEVEL; break; default: break; } if(ch->pcdata->security>maxsecurity){ if(maxsecurity==9){ maxsecurity=8; } ch->wraplnf("`RNOTICE: Your player file was loaded from a directory that " "limits olc security. Your olc security was read in being higher than allowed, " "therefore your security has been changed from %d to %d!`c", ch->pcdata->security, maxsecurity); ch->pcdata->security=maxsecurity; } if(ch->trust>maxtrust){ if(maxtrust==ABSOLUTE_MAX_LEVEL){ maxtrust=MAX_LEVEL; } ch->wraplnf("`RNOTICE: Your player file was loaded from a directory that " "limits trust level. Your trust was read in being higher than allowed, " "therefore your trust has been changed from %d to %d!`c", ch->trust, maxtrust); ch->trust=maxtrust; } if(ch->level>maxlevel){ if(maxlevel==ABSOLUTE_MAX_LEVEL){ maxlevel=MAX_LEVEL; } ch->wraplnf("`RNOTICE: Your player file was loaded from a directory that " "limits your level to that of a mortal. Your level was read in as being higher " "than allowed, therefore your level has been changed from %d to %d!`c", ch->level, maxlevel); ch->level=maxlevel; } } if(IS_SET(ch->act, PLR_DENY)){ sprintf( log_buf, "Denying access to %s@%s.", argument, d->remote_hostname ); log_string( log_buf ); wiznet(log_buf,NULL,NULL,WIZ_SECURE,0,get_trust(ch)); d->write("You are denied access!\r\n", 0 ); if(d){ if(IS_IRCCON(d)){ sprintf( log_buf, "DENIED PLAYER DROPPED (nanny)\r\n" "was %s@%s (connected via IRC). (socket = %d)", ch->name, d->remote_hostname, d->connected_socket ); }else{ sprintf( log_buf, "DENIED PLAYER DROPPED (nanny)\r\n" "was %s@%s (socket = %d)", ch->name, d->remote_hostname, d->connected_socket); } wiznet(log_buf,NULL,NULL,WIZ_SECURE,0,get_trust(ch)); log_string(log_buf); } connection_close(d); return; } ch->mxp_send_init(); if(check_connection_ban(d)){ return; } if(check_reconnect( d, argument, false )){ pfile_loaded_okay= true; }else{ if(GAMESETTING(GAMESET_PLAYER_LOCKED)){ write_to_buffer( d, "\r\nThe game is playerlocked, only the administration can currently connect.\r\n", 0 ); if(!IS_IMMORTAL(ch) && !ch->host_validated && !d->ident_confirmed){ connection_close( d ); return; } write_to_buffer( d, "\r\n\r\nIF THE ADMIN ARE WANTING PLAYERS TO LOG INTO THE GAME, THEY NEED TO UNPLAYERLOCK THE GAME!\r\n\r\n", 0 ); } } if(pfile_loaded_okay){ if(ch->pcdata && ch->pcdata->colourmode){ d->colour_mode=ch->pcdata->colourmode; }else{ d->colour_mode=CT_NOCOLOUR; } if(!str_cmp( "-", ch->pcdata->pwd )) { write_to_buffer( d, "Your password has been wiped...\r\n", 0 ); write_to_buffer( d, "Please set your password using the password command, then relogin.\r\n", 0 ); write_to_buffer( d, "Syntax: password - <new password>.\r\n", 0 ); d->connected_state = CON_READ_MOTD; } else { // Old player if(HAS_MXPDESC(d)){ write_to_buffer( d, mxp_tagify("`cCharacter Password:`c <PASSWORD>"), 0 ); }else{ write_to_buffer( d, "`cCharacter Password:`c ", 0 ); } if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); }else{ write_to_buffer( d, echo_off_str, 0 ); } d->connected_state = CON_GET_OLD_PASSWORD; } return; } else { if(!str_cmp("new", argument)){ if(!d->ident_confirmed){ if(GAMESETTING(GAMESET_PLAYER_LOCKED)){ write_to_buffer( d, "Sorry, the game is currently playerlocked, no new players can be created at this point in time.\r\n", 0 ); connection_close( d ); return; } if(GAMESETTING(GAMESET_NEWBIE_LOCKED)){ write_to_buffer( d, "Athens is only available for building, coding and light player testing.\r\n", 0 ); write_to_buffer( d, " contact the owner at: hera_of_athens@yahoo.com \r\n", 0); write_to_buffer( d, LOGIN_PROMPT, 0); if(IS_IRCCON(d)){ write_to_buffer(d,"\r\n", 2); } return; } logf("Socket %d (%s) is considering making a new character", d->connected_socket, d->remote_hostname); } write_to_buffer( d, "Do you really want to create a new character? (Y or N)", 0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0); } d->connected_state = CON_CONFIRM_CREATING_NEW; return; } // pfile not found for playername sprintf( buf, "I don't recognise the name '%s', if you wish to create a \r\n" "character called '%s' type 'new' (without the quotes).\r\n", argument, argument); write_to_buffer( d, buf, 0); write_to_buffer( d, LOGIN_PROMPT, 0); if(IS_IRCCON(d)){ write_to_buffer(d,"\r\n", 2); } // recycle the memory we just allocated free_char(d->character); d->character = NULL; return; } } /**************************************************************************/ void nanny_get_automap(connection_data *d, char *argument) { switch( *argument ) { default: write_to_buffer(d,"Please type Yes or No ",0); return; case 'y' : case 'Y': SET_BIT(d->character->act,PLR_AUTOMAP); d->character->println("Automap activated!\r\n"); break; case 'n' : case 'N': REMOVE_BIT(d->character->act,PLR_AUTOMAP); d->character->println("Automap not activated.\r\n"); break; } // start class selection connected_to_CON_REROLL_STATS(d); return; } /**************************************************************************/ void begin_remort( char_data *oc); /**************************************************************************/ void nannysup_process_correct_connect_password(connection_data *d) { char_data *ch = d->character; // remort patch in here if(ch->beginning_remort){ begin_remort(ch); return; } if(IS_IRCCON(d)){ sprintf( log_buf, "%s@%s has connected via IRC. (socket=%d, lvl=%d)", ch->name, d->remote_hostname, ch->desc->connected_socket, ch->level ); }else{ sprintf( log_buf, "%s@%s has connected. (socket=%d, lvl=%d)", ch->name, d->remote_hostname, ch->desc->connected_socket, ch->level ); } log_string( log_buf ); wiznet(log_buf,ch,NULL,WIZ_SITES,0, UMIN(get_trust(ch), MAX_LEVEL)); nanny_char_version_updates(ch); if(ch->version>5 && ch->version!=0) { if(IS_IMMORTAL(ch) ) { do_help( ch, "imotd" ); ch->hit_return_to_continue(); d->connected_state = CON_READ_IMOTD; } else { if(IS_IRCCON(d)){ do_help( ch, "irc-motd" ); }else{ do_help( ch, "motd" ); } ch->hit_return_to_continue(); d->connected_state = CON_READ_MOTD; } } else { if(ch->version==0) { int langsn=race_table[ch->race]->language->gsn; if(langsn>0){ ch->pcdata->learned[langsn]=100; } ch->language=race_table[ch->race]->language; ch->gen_data = new_gen_data(); ch->gen_data->points_chosen = ch->pcdata->points; do_help(ch,"group-header"); list_group_costs(ch); write_to_buffer(d,"You already have the following skills:\r\n",0); do_skills(ch,""); do_help(ch,"menu-choice"); d->connected_state = CON_GEN_GROUPS; return; } ch->version=6; connected_to_CON_GET_ALLIANCE(d); return; } } /**************************************************************************/ void nanny_get_old_password(connection_data *d, char *argument) { char_data *ch = d->character; write_to_buffer( d, "\r\n", 2 ); if(ch->pcdata->overwrite_pwd){ write_to_buffer( d, "Your password has been wiped...\r\n", 0 ); write_to_buffer( d, "Please set your password using the password command, then relogin.\r\n", 0 ); write_to_buffer( d, "Syntax: password - <new password>.\r\n", 0 ); }else{ if(!is_valid_password(argument, ch->pcdata->pwd, d)) { logf( "Socket %d (%s) got the password wrong for %s!", ch->desc->connected_socket, ch->desc->remote_hostname, ch->name); write_to_buffer( d, "Wrong password", 0 ); if(++d->wrong_password_count<3){ write_to_buffer( d, " - try again.\r\n", 0 ); write_to_buffer( d, "`cCharacter Password:`c ", 0 ); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); }else{ write_to_buffer( d, echo_off_str, 0 ); } return; }else{ write_to_buffer( d, ".\r\n", 0 ); } connection_close( d ); return; } } logf("Socket %d (%s) got the password correct for %s", ch->desc->connected_socket, ch->desc->remote_hostname, ch->name); // automatically extract a ploaded player if they login while ploaded { char_data *t=pload_find_player_by_name(ch->name); if(t){ logf("automatically extracting the ploaded player '%s' due to login.", ch->name); pload_extract(NULL, t); } } if(ch->version==0) { logf("Socket %d - char version = 0", ch->desc->connected_socket); write_to_buffer( d, "Please remember to set your password when you finish creating.\r\n", 0 ); } if(!IS_IRCCON(d)){ write_to_buffer( d, echo_on_str, 0 ); } write_to_buffer( d, "\r\n", 0 ); // display the codebase advert if(!GAMESETTING2(GAMESET2_DONT_DISPLAY_CODEBASE_4_LOGIN)){ ch->println(" `GThis mud is based on the Dawn of Time codebase`c"); } // display last login info if(!IS_NULLSTR(ch->pcdata->last_logout_site)){ char lastbuf[MSL]; sprintf(lastbuf, " You last logged in from %s\r\n" " and logged out at %s", ch->pcdata->last_logout_site, (char *) ctime( &ch->pcdata->last_logout_time)); lastbuf[str_len(lastbuf)-1]='\0'; strcat(lastbuf, FORMATF("\r\n which was %s ago.\r\n\r\n", short_timediff(ch->pcdata->last_logout_time, current_time))); write_to_buffer( d, lastbuf, 0 ); } if(check_playing(d,ch->name)) return; if(check_reconnect( d, ch->name, true ) ) return; if(ch->host_validated){ ch->print(validatedhost"..."); }else{ // process a connection password - if there is one if(!IS_NULLSTR(game_settings->password_player_connect) && str_cmp(game_settings->password_player_connect, "-") && !IS_IMMORTAL(ch)){ ch->wrapln("There is currently a player connect password set which you must " "enter in now before you can connect to the game`1Please enter the connection password:"); d->connected_state=CON_GET_CONNECT_PASSWORD; return; } } nannysup_process_correct_connect_password(d); } /**************************************************************************/ void nanny_break_connect(connection_data *d, const char *argument) { connection_data *d_old, *c_next; char name[MIL]; strcpy(name, CH(d)?CH(d)->name:"???"); switch( *argument ) { case 'y' : case 'Y': logf("Socket %d (%s) to break connect (%s)", d->connected_socket, d->remote_hostname, name); for( d_old = connection_list; d_old != NULL; d_old = c_next ) { c_next = d_old->next; if(d_old == d || d_old->character == NULL) continue; if(str_cmp(name,d_old->original ? d_old->original->name : d_old->character->name)) continue; connection_close(d_old); } if(check_reconnect(d,name,true)){ return; } logf("Socket %d (%s) reconnect failed for %s", d->connected_socket, d->remote_hostname, name); write_to_buffer(d,"Reconnect attempt failed.\r\nName: ",0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } if(d->character != NULL ){ free_char( d->character ); d->character = NULL; } d->connected_state = CON_GET_NAME; break; case 'n' : case 'N': sprintf( log_buf, "Socket %d (%s) decided not to force another (%s) off.", d->connected_socket, d->remote_hostname, name); log_string(log_buf); write_to_buffer(d,"Name: ",0); if(d->character){ free_char( d->character ); d->character = NULL; } d->connected_state = CON_GET_NAME; break; default: write_to_buffer(d,"Please type Yes or No ",0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } break; } } /**************************************************************************/ // send the name selection prompt to the new player void nannysup_name_select_prompt(connection_data *d) { char_data *ch=d->character; // ch->printlnf("Name selector commands: <1-%d>, list, help, requirements\r\n" // "Enter your characters name or name selector command: ", profile_count); if(IS_IRCCON(d)){ ch->println(""); } } /**************************************************************************/ void nannysup_begin_name_select(connection_data *d) { char_data *ch=d->character; ch->lines += 15; if(!codehelp(CH(d), "creation_name_requirements", false)){ ch->wrapln( "\nThe first stage in creating a character is to come up with a name " "for it. There are many things to consider when naming your character, " "here are some requirement your character's name must meet:" "`1" "`1- Be creative. Do not give your character the name of another character" "`1 you like in a fantasy book." "`1- Do not give your char a descriptive name such as CoolGuy, SexyJane," "`1 WeaponMaster or GreatFighter." "`1- Dont put titles in your name such as EmperorCrosash or LadyElbriana" "`1- Do not put nouns, adjectives or adverbs. If a word has a meaning," "`1 keep it off your name. Examples: Slasher, TheShadow, RedDrac, Bloody." "`1- Swear words and names from earthly religions are not allowed." "`1- The administration reserve the right to change your name for any" "`1 reason what so ever, and will most likely do so if could be in" "`1 anyway disrespectful, or in violation of any of the above points." "`1" "`1Try to keep in mind the time period and theme for our mud. If you have " "questions about choosing a name or why it might have been suggested that " "change yours, any Newbie Support Technician can assist you." "`1" "`1Enter your character's name:`1"); } ch->lines -= 15; nannysup_name_select_prompt(d); d->connected_state=CON_NAME_SELECT; } /**************************************************************************/ void nanny_name_select(connection_data *d, char *argument) { char_data *ch=d->character; name_profile *nl; name_confirmed=0; // show help if(!str_cmp("help", argument)){ ch->wrapln( "The name selector gives you the option to type in a name you would " "like to give the character you are creating or can be used to suggest " "possible names you might like to consider." "`1The names the selector generates are randomized sequences of letters " "based on various naming profiles... these naming profiles give names of " "a certain 'style'." "`1" "`1Name selector commands:" "`1 '`=Chelp`c' shows this help screen." "`1 '`=Crequirements`c' shows you the requirements your name must meet." "`1 '`=Clist`c' will list the name profiles available." "`1" "`1The list command displays the title of a name profile and its number, " "to see names generated with that particular profile simply type the " "corresponding number and press enter. Because the system generates " "random names from a profile, you can use a profile numerous times " "with different names of simular style each time."); nannysup_name_select_prompt(d); return; } if(IS_NULLSTR(argument) || !str_prefix(argument, "requirements")){ nannysup_begin_name_select(d); return; } if(d && d->ident_confirmed){ name_confirmed=1; } // list profiles if(!str_cmp("list", argument)){ int count=0; ch->printf("`=j%s`c", creation_titlebar("NAME GENERATOR PROFILES")); for(nl=name_profiles_list; nl; nl=nl->next){ ch->printlnf("%2d> %s", ++count, nl->title); } ch->wrapln("`SNOTE: randomly generated names in some rare " "situations will not meet the naming requirements.`c"); nannysup_name_select_prompt(d); return; } // use a profile if(is_number(argument)){ int count=0; int profile_num=atoi(argument); if(profile_num<1 || profile_num>profile_count){ ch->printlnf("Invalid profile number %d.", profile_num); return; } for(nl=name_profiles_list; nl; nl=nl->next){ if(++count>=profile_num){ break; }; } int i; ch->printf("`cName Generator"); for(i=0; i<60; i++){ ch->printf(" %-18s", capitalize(genname(nl))); if(i%4==3){ ch->println(""); } } ch->println(""); ch->wrapln("`=cNOTE: randomly generated names in some rare situations " "will not meet the naming requirements.`c"); nannysup_name_select_prompt(d); return; } // *** A player has suggested a name - check it out // check for invalid characters in name if(strstr(".", argument) || strstr("\\", argument) || strstr(" ", argument) || strstr("/", argument)){ ch->wraplnf("Invalid letters name '%s' try another name (no spaces, fullstops " "or slashes in your please, try another single word name.", argument); nannysup_name_select_prompt(d); return; } argument=capitalize(argument); ch->wraplnf("Checking if the name '%s' is not currently used by another player " "or monster, please wait...", argument); // check for existing player with same name PFILE_TYPE pt=find_pfiletype(argument); ch->pcdata->pfiletype=pt; if(pt!=PFILE_NONE){ ch->printlnf("The name '%s' is already in use. Try another name.", argument); nannysup_name_select_prompt(d); return; } // check if we can reject the name for other reasons if(!check_parse_name( argument ) ) { ch->printlnf("Sorry the name '%s' is unable to be used, try another.", argument); nannysup_name_select_prompt(d); return; } { // dont allow duplicate names in creation connection_data *dc; for( dc = connection_list; dc; dc = dc->next ) { if(d!=dc && dc->character && !str_cmp(dc->character->name, argument) ) { logf("Socket %d (%s) had name %s rejected because another is creating with it", d->connected_socket, d->remote_hostname, CH(d)->name); ch->printlnf("Sorry someone else is currently creating using the name '%s', try another.", argument); nannysup_name_select_prompt(d); return; } } } replace_string(ch->name, argument); ch->wraplnf("The name '%s' appears to be available for you to use (assuming it meets " "the naming requirements listed earlier)." "`1Do you want to start creating a new character called '%s'?", argument, argument); d->connected_state=CON_CONFIRM_NEW_NAME; } /**************************************************************************/ void nanny_confirm_new_name(connection_data *d, const char *argument) { char_data *ch=d->character; switch( *argument ) { case 'y': case 'Y': if(count_creation_connections_per_hour(d)>2){ ch->wrapln("WARNING: We limit how many times you can create a character per hour!!!" "`1You can only create a few more times this hour!"); } ch->printlnf("`cWelcome %s! It is time for you to now pick a password.", ch->name); ch->printf("`cPlease enter a new password for %s:`c %s", ch->name, IS_IRCCON(d)?"\r\n":echo_off_str ); d->connected_state = CON_GET_NEW_PASSWORD; break; case 'n': case 'N': logf("Socket %d (%s) decided not to make a new player.", d->connected_socket, d->remote_hostname); write_to_buffer( d, "`cOk, lets start from the very start again...\r\n", 0 ); write_to_buffer( d, LOGIN_PROMPT, 0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } free_char(d->character); d->character = NULL; d->connected_state = CON_GET_NAME; break; default: write_to_buffer( d, "`cPlease type Yes or No ", 0 ); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } break; } } /**************************************************************************/ void nanny_confirm_creating_new(connection_data *d, const char *argument) { char_data *ch=d->character; switch( *argument ) { case 'y': case 'Y': d->newbie_creating= true; // check for newbie bans if(check_connection_ban(d)) break; if(check_connection(d)) break; // mark them as using the new colour code if(ch->pcdata){ ch->pcdata->colour_code=COLOURCODE; } // process a connection password - if there is one if(!IS_NULLSTR(game_settings->password_player_connect) && str_cmp(game_settings->password_player_connect, "-") && !IS_IMMORTAL(ch) && !ch->host_validated && !d->ident_confirmed){ ch->wrapln("There is currently a player connect password set which you must " "entered to play. Before you can create a new character you need to enter " "the connect password.`1Please enter the connection password:"); d->connected_state=CON_GET_CONNECT_PASS2CREATE; return; }else if(!IS_NULLSTR(game_settings->password_creation) && str_cmp(game_settings->password_creation, "-") && !ch->host_validated && !d->ident_confirmed){ ch->wrapln("There is currently a creation password set which you must " "enter in now before creating a new character`1Please enter the creation password:"); d->connected_state=CON_GET_CREATION_PASSWORD; }else{ nannysup_begin_name_select(d); } break; case 'n': case 'N': d->newbie_creating= false; logf("Socket %d (%s) decided not to make a new player.", d->connected_socket, d->remote_hostname); write_to_buffer( d, "Ok, lets try again...\r\n", 0 ); write_to_buffer( d, LOGIN_PROMPT, 0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } free_char( d->character ); d->character = NULL; d->connected_state = CON_GET_NAME; break; default: write_to_buffer( d, "Please type Yes or No ", 0 ); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } break; } } /**************************************************************************/ void nanny_get_connect_password_before_creating(connection_data *d, const char *argument) { char_data *ch=d->character; assertp(game_settings->password_player_connect); // correct creation password if(!str_cmp(game_settings->password_player_connect, argument)){ if(!IS_NULLSTR(game_settings->password_creation) && str_cmp(game_settings->password_creation, "-") && !ch->host_validated && !d->ident_confirmed){ ch->printf("`=j%s`c", creation_titlebar("CREATION PASSWORD REQUIRED")); ch->wrapln("There is also currently a creation password set which you must " "enter in now before creating a new character`1Please enter the creation password:"); d->connected_state=CON_GET_CREATION_PASSWORD; }else{ nannysup_begin_name_select(d); } return; } // wrong creation password ch->wraplnf("Sorry, '%s' is not the connect password... you can't create a new " "character at this point in time.", argument); write_to_buffer( d, LOGIN_PROMPT, 0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } free_char( ch ); d->character = NULL; d->connected_state = CON_GET_NAME; } /**************************************************************************/ void nanny_get_creation_password(connection_data *d, const char *argument) { char_data *ch=d->character; assertp(game_settings->password_creation); // correct creation password if(!str_cmp(game_settings->password_creation, argument)){ ch->println("great, now lets get on with creating a character."); nannysup_begin_name_select(d); return; } // wrong creation password ch->wraplnf("Sorry, '%s' is not the creation password... you can't create a new " "character at this point in time.", argument); write_to_buffer( d, LOGIN_PROMPT, 0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } free_char( ch ); d->character = NULL; d->connected_state = CON_GET_NAME; } /**************************************************************************/ void nanny_get_connect_password(connection_data *d, const char *argument) { char_data *ch=d->character; assertp(game_settings->password_player_connect); // correct connect password if(!str_cmp(game_settings->password_player_connect, argument)){ ch->println("great, now lets get on with creating a character."); nannysup_process_correct_connect_password(d); return; } // wrong creation password ch->wraplnf("Sorry, '%s' is not the connect password... you can't " "play this character at this point in time.", argument); write_to_buffer( d, LOGIN_PROMPT, 0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } free_char( ch ); d->character = NULL; d->connected_state = CON_GET_NAME; } /**************************************************************************/ void nanny_get_new_password(connection_data *d, const char *argument) { char_data *ch=d->character; write_to_buffer( d, "\r\n", 2 ); if(str_len(argument) < 5 ) { write_to_buffer( d, "`cPassword must be at least five characters long.\r\nPassword: ", 0 ); return; } char *p; char *pwdnew = dot_crypt( argument, CH(d)->name ); for( p = pwdnew; *p != '\0'; p++ ) { if(*p == '~' ) { write_to_buffer( d,"`cNew password not acceptable, try again.\r\nPassword: ",0 ); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } return; } } free_string( ch->pcdata->pwd ); ch->pcdata->pwd = str_dup( pwdnew ); write_to_buffer( d, "`cPlease retype password: ", 0 ); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } d->connected_state = CON_CONFIRM_NEW_PASSWORD; } /**************************************************************************/ void nanny_confirm_new_password(connection_data *d, const char *argument) { char_data *ch=d->character; #if defined(unix) write_to_buffer( d, "\r\n", 2 ); #endif if(strcmp( dot_crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) ) { write_to_buffer( d, "Passwords don't match.\r\nEnter a new password: ",0 ); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } d->connected_state = CON_GET_NEW_PASSWORD; return; } if(!IS_IRCCON(d)){ write_to_buffer( d, echo_on_str, 0 ); write_to_buffer( d, "`cDo you want to play with ansi colour?\r\n", 0 ); write_to_buffer( d, "`c(you can toggle at anytime once within the game by typing colour)\r\n", 0 ); d->connected_state = CON_GET_COLOUR; }else{ // automatically turn on colour for IRC connections - default them to irc white d->colour_mode=CT_IRCWHITE; ch->pcdata->colourmode=CT_IRCWHITE; nannysup_email_check(d,argument); } } /**************************************************************************/ void nanny_get_colour(connection_data *d, const char *argument) { char_data *ch=d->character; switch( *argument ) { default: write_to_buffer(d,"Please type Yes or No ",0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } return; break; case 'y' : case 'Y': ch->pcdata->colourmode=CT_ANSI; ch->println("`?C`?o`?l`?o`?u`?r`? `?i`?s `?n`?o`?w `?O`?N`?!`c"); break; case 'n' : case 'N': d->colour_mode=CT_NOCOLOUR; ch->pcdata->colourmode=CT_NOCOLOUR; write_to_buffer(d,"You now have colour disabled.\r\n",0); break; } nannysup_email_check(d,argument); } /**************************************************************************/ void nanny_get_new_race(connection_data *d, char *argument) { char arg[MIL]; char_data *ch=d->character; one_argument(argument,arg); if(!strcmp(arg,"help")) { argument = one_argument(argument,arg); if(argument[0] == '\0'){ do_help(ch,"race help"); }else{ do_help(ch,argument); } write_to_buffer(d, "What city do you want to come from?`1",0); return; } if(!GAMESETTING5(GAMESET5_RACEINFO_DISABLED_IN_CREATION) && !strcmp(arg,"raceinfo")) { CH(d)->wrapln("`cSee \"help `=_attributes`c\" and " "\"help `=_'creation points'`c\" for an explaination of " "what the following numbers relate to."); do_raceinfo(ch, ""); ch->print("`cEnter the name of the city you would like to come from: `c"); if(IS_IRCCON(d)){ ch->print_blank_lines(1); } return; } int race = race_lookup(argument); if(race == -1 || !race_table[race]->creation_selectable() || (race_table[race]->remort_number > d->creation_remort_number)) { if(IS_NULLSTR(argument)){ CH(d)->printf("You have to type something!`1"); }else{ CH(d)->printf("'%s' is not a valid city.`1", argument); } if(!codehelp(CH(d), "racial_option", false)){ CH(d)->printf("Please select your city from one of the following:`1 "); int count=0; for( race = 0; race_table[race]; race++ ) { // creation selectable pc races only if(!race_table[race]->creation_selectable() || (race_table[race]->remort_number > d->creation_remort_number)){ continue; } CH(d)->printf(" `S[`Y%12.12s`S]", race_table[race]->name); if(++count%5==0){ CH(d)->printf("`c\r\n "); } } CH(d)->printf("`1`cType in the name of the city you wish to come from:`1"); } return; } CH(d)->printf("Race '%s' selected.`1`1", race_table[race]->name); ch->race = race; ch->affected_by = ch->affected_by|race_table[race]->aff; REMOVE_BIT(ch->affected_by, AFF_FLYING); // new players dont start off flying affect_fly_update(ch); // set/remove DYN_MAGICAL_FLYING as required ch->affected_by2= ch->affected_by2|race_table[race]->aff2; ch->imm_flags = ch->imm_flags|race_table[race]->imm; ch->res_flags = ch->res_flags|race_table[race]->res; ch->vuln_flags = ch->vuln_flags|race_table[race]->vuln; ch->form = race_table[race]->form; ch->parts = race_table[race]->parts; // add racial skills for(int i = 0; i < MAX_RACIAL_SKILLS; i++){ if(race_table[race]->skills[i]==-1){ break; } group_add(ch,skill_table[race_table[race]->skills[i]].name,false, 1); // all racial skills are 1% } // add cost ch->pcdata->points = race_table[race]->points; ch->size = race_table[race]->size; write_to_buffer( d, "`cWhat gender is your character (M/F)? ", 0 ); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } d->connected_state = CON_GET_NEW_SEX; } /**************************************************************************/ void nanny_get_new_sex(connection_data *d, const char *argument) { char_data *ch=d->character; switch( argument[0] ) { case 'm': case 'M': ch->sex = SEX_MALE; ch->pcdata->true_sex = SEX_MALE; break; case 'f': case 'F': ch->sex = SEX_FEMALE; ch->pcdata->true_sex = SEX_FEMALE; break; default: write_to_buffer( d, "That's not a sex.\r\nWhat IS your sex? ", 0 ); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } return; } if(GAMESETTING5(GAMESET5_CREATION_ASK_IF_WANT_AUTOMAP_ON)){ ch->lines += 15; if(!codehelp(CH(d), "automap_option", CODEHELP_ALL_BUT_PLAYERS)){ ch->printf("Do you want the automap option enabled?\r\n"); } ch->lines -= 15; d->connected_state=CON_GET_AUTOMAP; }else{ // automap defaults to on automatically, // unless game is configured to ask in the gamesettings SET_BIT(d->character->act,PLR_AUTOMAP); // start class selection connected_to_CON_REROLL_STATS(d); } } /**************************************************************************/ void nanny_get_new_class(connection_data *c, char *argument) { char arg[MIL]; char tempbuf[MIL]; char_data *ch=c->character; one_argument(argument,arg); if(!strcmp(arg,"help")){ argument = one_argument(argument,arg); if(IS_NULLSTR(argument)){ do_help(ch,"classes"); }else{ do_help(ch,argument); } ch->println("What class do you wish to be? "); return; } if(!GAMESETTING5(GAMESET5_CLASSINFO_DISABLED_IN_CREATION) && !strcmp(arg,"classinfo")) { argument = one_argument(argument,arg); ch->print_blank_lines(1); ch->wrapln("`cSee \"help `=_basexp`c\", \"help `=_prime`c\" and " "\"help `=_attributes`c\" for an explaination of " "what the following values relate to."); if(!GAMESETTING5(GAMESET5_RACEINFO_DISABLED_IN_CREATION)){ ch->println("`=Craceinfo`c is also available at this stage in creation for reference purposes."); } if(IS_NULLSTR(argument)){ do_classinfo(ch, race_table[ch->race]->name); if(GAMESETTING5(GAMESET5_RACEINFO_DISABLED_IN_CREATION)){ ch->wrapln("You can also look at the base xp amounts for other cities " "(for comparision purposes), by typing 'RCLASSINFO <CITYNAME>`c'."); }else{ ch->wrapln("You can also look at the base xp amounts for other races " "(for comparision purposes), by typing 'classinfo <racename>'... " "use 'raceinfo' to get a list of races."); } }else{ do_classinfo(ch, argument); } ch->print("`cEnter the name of the class would you like to play: `c"); ch->print_blank_lines(IS_IRC(ch)?1:0); return; } if(!GAMESETTING5(GAMESET5_RACEINFO_DISABLED_IN_CREATION) && !strcmp(arg,"raceinfo")) { ch->wrapln("`cSee \"help `=_attributes`c\" and " "\"help `=_'creation points'`c\" for an explaination of " "what the following values relate to."); do_raceinfo(ch, ""); ch->print("`cEnter the name of the CLASS would you like to play: `c"); ch->print_blank_lines(IS_IRC(ch)?1:0); return; } int iClass= class_lookup(argument); if(iClass == -1 || !class_table[iClass].creation_selectable || (class_table[iClass].remort_number > c->creation_remort_number)) { ch->printlnf("'%s' is not a recognised class.", argument); ch->print("What is your class? "); ch->print_blank_lines(IS_IRC(ch)?1:0); return; } if(race_table[ch->race]->class_exp[iClass]<1000){ ch->printlnf("The %s class is not available for your city sorry.", class_table[iClass].name); ch->print("What IS your class? "); ch->print_blank_lines(IS_IRC(ch)?1:0); return; } ch->clss = iClass; ch->pcdata->perm_hit=race_table[ch->race]->start_hp; ch->max_hit=ch->pcdata->perm_hit; ch->hit=ch->max_hit; int langsn=race_table[ch->race]->language->gsn; if(langsn>0){ ch->pcdata->learned[langsn]=100; } ch->language=race_table[ch->race]->language; // set players default short description if(ch->short_descr[0]=='\0') { sprintf(tempbuf,"a %s %s", (ch->sex==0 ? "sexless" : ch->sex==1 ? "male" : "female"), race_table[ch->race]->name); ch->short_descr= str_dup(tempbuf); } // turn on players auto defaults SET_BIT(ch->act,PLR_AUTOREFORMAT); SET_BIT(ch->act,PLR_AUTOLOOT); SET_BIT(ch->act,PLR_AUTOASSIST); SET_BIT(ch->act,PLR_AUTOGOLD); SET_BIT(ch->act,PLR_AUTOEXIT); SET_BIT(ch->act,PLR_AUTOSPLIT); SET_BIT(ch->comm,COMM_SHOW_AFFECTS); SET_CONFIG(ch, CONFIG_AUTOLANDONREST); if(!GAMESETTING5(GAMESET5_AUTODAMAGE_DEFAULTS_OFF)){ SET_CONFIG2(ch,CONFIG2_AUTODAMAGE); } // log them if we autolog all new players if(GAMESETTING4(GAMESET4_AUTOLOG_ALL_NEW_PLAYERS)){ SET_BIT(ch->act,PLR_LOG); append_playerlog( ch, "Player log turned ON by GAMESET4_AUTOLOG_ALL_NEW_PLAYERS."); } ch->println("Applying primary stats for your class to your character..." ); nannysup_setprime_stats(ch); if(IS_IRC(ch)){ sprintf(log_buf,"%s@%s new IRC player!!! (socket = %d)", ch->name, c->remote_hostname, c->connected_socket); }else{ sprintf(log_buf,"%s@%s new player!!! (socket = %d)", ch->name, c->remote_hostname, c->connected_socket); } log_string(log_buf); wiznet("Newbie alert! Welcome $N.",ch,NULL,WIZ_NEWBIE,0,0); wiznet(log_buf,NULL,NULL,WIZ_SITES,0,get_trust(ch)); // alert newbie support of an incoming newbie nsupport_newbie_alert( ch, false ); connected_to_CON_GET_ALLIANCE(c); } /**************************************************************************/ void nanny_reroll_stats(connection_data *d, char *argument) { char_data *ch=d->character; char arg[MIL]; one_argument(argument,arg); switch( *arg) { case 'n' : case 'N': // dont let people reroll more than 100 times if(ch->pcdata->reroll_counter>20) { d->write("\r\n" "\r\n`cFind something better to do with your time!\r\n\r\n",0); logf("%s %s (%d) dropped due to rerolling over 20 times.", CH(d)->name, d->remote_hostname, d->connected_socket ); connection_close(d); return; } // reroll and show the stats write_to_buffer(d,"Rerolling please wait.\r\n",0); roll_stats(d); if(!ch->pcdata->reroll_counter) { write_to_buffer(d,"`cNote: Attributes are rolled with a bias in favour doing less rerolls.\r\n",0); write_to_buffer(d,"`cThe attributes rolling system has been changed since dawn1.1 and will NOT give\r\n" "`chigh attributes like it used to, also note that modifiers now start at 60 not 70!\r\n",0); } ch->pcdata->reroll_counter++; break; // player keeps stats case 'y' : case 'Y': connected_to_CON_GET_NEW_CLASS(d); break; default: { if(!strcmp(arg,"help")) { argument = one_argument(argument,arg); if(IS_NULLSTR(arg)){ do_help(ch,"attributes"); }else{ do_help(ch,argument); } ch->println("`cAre you happy with the attributes above the help entry? (Y, N): "); return; } write_to_buffer(d,"`cPlease type Y, N or HELP? ",0); if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } } break; } } /**************************************************************************/ void nanny_get_alliance(connection_data *d, const char *argument) { char_data *ch=d->character; if(is_number(argument)) { if(GAMESETTING(GAMESET_MAX_ALIGN_RANGE22)){ if(atoi(argument)<-2 || atoi(argument)>2) { write_to_buffer(d,"`cValue between -2 and 2 please:",0); return; } }else{ if(atoi(argument)<-3 || atoi(argument)>3) { write_to_buffer(d,"`cValue between -3 and 3 please:",0); return; } } ch->alliance=atoi(argument); { write_to_buffer(d, "`cThe second half of you alignment is your TENDENCY towards law and chaos,\r\n",0); if(GAMESETTING(GAMESET_MAX_ALIGN_RANGE22)){ write_to_buffer(d, "`cthis value can be from -2 to 2(including 0 being neutral) 2 being lawful,\r\n" "`clawful and -2 being chaotic. \r\nWhat is your choice? ",0); }else{ write_to_buffer(d, "`cthis value can be from -3 to 3(including 0 being neutral) 3 being extremely,\r\n" "`clawful and -3 being extremely chaotic. \r\nWhat is your choice? ",0); } if(IS_IRCCON(d)){ write_to_buffer( d, "\r\n", 0 ); } d->connected_state = CON_GET_TENDENCY; } }else{ if(GAMESETTING(GAMESET_MAX_ALIGN_RANGE22)){ write_to_buffer(d,"`cThat is not a number, try again(-2 through 2):",0); }else{ write_to_buffer(d,"`cThat is not a number, try again(-3 through 3):",0); } return; } } /**************************************************************************/ void nanny_get_tendency(connection_data *d, const char *argument) { char_data *ch=d->character; if(is_number(argument)) { if(GAMESETTING(GAMESET_MAX_ALIGN_RANGE22)){ if(atoi(argument)<-2 || atoi(argument)>2) { write_to_buffer(d,"Value between -2 and 2 please:",0); return; } }else{ if(atoi(argument)<-3 || atoi(argument)>3) { write_to_buffer(d,"Value between -3 and 3 please:",0); return; } } { ch->tendency=atoi(argument); if(d->ident_confirmed){ CH(d)->host_validated=1; } if(ch->version<6) { ch->version=6; write_to_buffer(d,"\r\n",0); // loop thru all the groups giving new character all the ones // his/her class can get for free and the free for all's for ( int lgn = 0; !IS_NULLSTR(skillgroup_table[lgn].name); lgn++ ) { if( skillgroup_table[lgn].rating[ch->clss]==0 || IS_SET(skillgroup_table[lgn].flags, SKILLGROUP_FREE_FOR_ALL)) { gn_add(ch, lgn); } } // give them some defaults ch->pcdata->learned[gsn_recall] = 50; /* if(GAMESETTING5(GAMESET5_CREATION_DISABLE_CUSTOMIZATION) || HAS_CLASSFLAG(ch, CLASSFLAG_NO_CUSTOMIZATION) || IS_SET(race_table[ch->race]->flags, RACEFLAG_NO_CUSTOMIZATION)) { */ nanny_new_player_not_customizing(d); return; // } /* CH(d)->printf("`cCustomization"); write_to_buffer(d,"Do you wish to customize this character?\r\n",0); write_to_buffer(d, "Customization takes time, but allows a wider range of skills and abilities.\r\n",0); write_to_buffer(d,"(we recommend choosing no, unless you have played here before as\r\n",0); write_to_buffer(d,"you can always gain skills at a later stage.)\r\n",0); write_to_buffer(d,"Customize (Y/N)? ",0); d->connected_state = CON_DEFAULT_CHOICE; return; */ } else { if(IS_IMMORTAL(ch) ) { do_help( ch, "imotd" ); ch->hit_return_to_continue(); d->connected_state = CON_READ_IMOTD; } else { if(IS_IRCCON(d)){ do_help( ch, "irc-motd" ); }else{ do_help( ch, "motd" ); } ch->hit_return_to_continue(); d->connected_state = CON_READ_MOTD; } } } } else { if(GAMESETTING(GAMESET_MAX_ALIGN_RANGE22)){ write_to_buffer(d,"That is not a number, try again(-2 through 2):",0); }else{ write_to_buffer(d,"That is not a number, try again(-3 through 3):",0); } return; } } /**************************************************************************/ void nanny_default_choice(connection_data *d, const char *argument) { char_data *ch=d->character; write_to_buffer(d,"\r\n",2); switch( argument[0] ) { case 'y': case 'Y': { int langsn=race_table[ch->race]->language->gsn; if(langsn>0){ ch->pcdata->learned[langsn]=100; } ch->language=race_table[ch->race]->language; ch->gen_data = new_gen_data(); ch->gen_data->points_chosen = ch->pcdata->points; do_help(ch,"group-header"); list_group_costs(ch); write_to_buffer(d,"You already have the following skills:\r\n",0); do_skills(ch,""); do_help(ch,"menu-choice"); d->connected_state = CON_GEN_GROUPS; } break; case 'n': case 'N': { nanny_new_player_not_customizing(d); // take some defaults, then d->connected_state -> CON_READ_MOTD } break; default: write_to_buffer( d, "Please answer (Y/N)? ", 0 ); return; } } /**************************************************************************/ void nanny_gen_groups(connection_data *d, char *argument) { char_data *ch=d->character; ch->println(""); if(!str_cmp(argument,"done") || !str_cmp(argument,"doneconfirm")) { if(ch->pcdata->points == race_table[ch->race]->points) { ch->println("You didn't pick anything.\r\n"); return; } if(str_cmp(argument,"doneconfirm")){ if(ch->pcdata->points < 40) { ch->wrapln("You haven't take at least 40 points of skills and groups... " "You can add more skills without affecting the amount of experience required to level. " "If you wish to continue without adding anymore skills/groups, type `=Cdoneconfirm`c"); return; } } ch->printf("Creation points: %d\r\n",ch->pcdata->points); ch->printf("Experience per level: %d\r\n", exp_per_level(ch,ch->pcdata->points)); if(ch->pcdata->points < 40) ch->train = (40 - ch->pcdata->points + 1) / 2; free_gen_data(ch->gen_data); ch->gen_data = NULL; write_to_buffer( d, "\r\n", 2 ); if(IS_IRCCON(d)){ do_help( ch, "irc-motd" ); }else{ do_help( ch, "motd" ); } ch->hit_return_to_continue(); d->connected_state = CON_READ_MOTD; return; } if(!parse_gen_groups(ch,argument)){ ch->println("That isn't a valid selection, (type help if you are stuck):\r\n"); } ch->println("\r\n"); do_help(ch,"menu-choice"); } /**************************************************************************/ void do_mobloglist( char_data *ch, char *argument); /**************************************************************************/ void nanny_read_imotd(connection_data *d, const char *) { char_data *ch=d->character; write_to_buffer(d,"\r\n",2); if(IS_IRCCON(d)){ do_help( ch, "irc-motd" ); }else{ do_help( ch, "motd" ); } ch->hit_return_to_continue(); if(IS_ADMIN(ch)){ // check the resolver version if(resolver_running && resolver_version<1400){ ch->titlebar("UPDATE THE DNS RESOLVER"); ch->wrapln("The dns resolver program (resolver) is an old version and " "needs to be updated. On a linux/bsd/unix platform this can be done by " "deleting the existing resolver program and recompile the code. " "On the Win32 platform you can " "download the latest version of the resolver.exe file from" " `1http://www.dawnoftime.org.`1This message is only displayed to the admin."); ch->titlebar(""); } // tell them about the moblogs on do_mobloglist(ch, "auto"); } d->connected_state = CON_READ_MOTD; } /**************************************************************************/ void visual_debug_flush( connection_data *d); /**************************************************************************/ // Deal with sockets that haven't logged in yet. void nanny( connection_data *d, char *argument ) { // logf("Nanny: d->connected_state %d, '%s' %d %d .", d->connected_state, // argument, *argument, *(argument+1) ); // debug testing code if(d->connected_state!= CON_FTP_DATA && d->connected_state!= CON_DETECT_CLIENT_SETTINGS){ while( is_space(*argument) ){ argument++; } logf("Start nanny state %2d (sock=%d)", d->connected_state, d->connected_socket); } if(d->visual_debugging_enabled && d->visual_debug_flush_before_prompt){ visual_debug_flush( d ); } switch( d->connected_state ) { default: bugf("Nanny: bad d->connected_state %d (sock=%d).", d->connected_state, d->connected_socket); connection_close( d ); break; // a new connection begins in state CON_DETECT_CLIENT_SETTINGS case CON_DETECT_CLIENT_SETTINGS: nanny_detect_client_settings(d, argument); break; case CON_GET_NAME: nanny_get_name(d, argument); break; case CON_CONFIRM_CREATING_NEW: nanny_confirm_creating_new(d, argument); break; case CON_GET_CONNECT_PASS2CREATE: nanny_get_connect_password_before_creating(d, argument); break; case CON_GET_CREATION_PASSWORD: nanny_get_creation_password(d, argument); break; case CON_GET_CONNECT_PASSWORD: nanny_get_connect_password(d, argument); break; case CON_NAME_SELECT: nanny_name_select(d, argument); break; case CON_CONFIRM_NEW_NAME: nanny_confirm_new_name(d, argument); break; case CON_RESOLVE_IP: nanny_resolve_ip(d, argument); break; case CON_GET_EMAIL: nanny_get_email(d, argument); break; case CON_RECHECK_EMAIL: nanny_recheck_email(d, argument); break; case CON_ENTER_UNLOCK_ID: nanny_enter_unlock_id(d, argument); break; case CON_GET_AUTOMAP: nanny_get_automap(d, argument); break; case CON_GET_OLD_PASSWORD: nanny_get_old_password(d, argument); break; case CON_BREAK_CONNECT: nanny_break_connect(d, argument); break; case CON_GET_NEW_PASSWORD: nanny_get_new_password(d, argument); break; case CON_CONFIRM_NEW_PASSWORD: nanny_confirm_new_password(d, argument); break; case CON_GET_COLOUR: nanny_get_colour(d, argument); break; case CON_GET_NEW_RACE: nanny_get_new_race(d, argument); break; case CON_GET_NEW_SEX: nanny_get_new_sex(d, argument); break; case CON_GET_NEW_CLASS: nanny_get_new_class(d, argument); break; case CON_REROLL_STATS: nanny_reroll_stats(d, argument); break; case CON_GET_ALLIANCE: nanny_get_alliance(d, argument); break; case CON_GET_TENDENCY: nanny_get_tendency(d, argument); break; case CON_DEFAULT_CHOICE: nanny_default_choice(d, argument); break; case CON_GEN_GROUPS: nanny_gen_groups(d, argument); break; case CON_READ_IMOTD: nanny_read_imotd(d, argument); break; case CON_READ_MOTD: nanny_read_motd(d, argument ); break; case CON_FTP_AUTH: handle_ftp_auth(d,argument); break; case CON_FTP_COMMAND: handle_ftp_command(d,argument); break; case CON_FTP_DATA: handle_ftp_data(d,argument); break; } } /**************************************************************************/ // Parse a name for acceptability. bool check_parse_name( char *name ) { // Reserved words. if(is_name( name, "auto someone something the you new self system dawnftp mudftp" )) return false; // some potentially offensive/inappropriate names in hex :) if(is_name_infix( name, "\x66\x75\x63\x6b \x70\x68\x75\x63\x6b \x66\x75\x6b \x70\x68\x75\x6b " "\x73\x68\x69\x74 \x64\x61\x6d\x6e \x63\x6f\x63\x6b \x63\x75\x6e\x74 " "\x62\x6c\x6f\x77\x6a\x6f\x62 \x61\x73\x73\x68\x6f\x6c\x65 " "\x70\x75\x73\x73\x79 \x6a\x65\x73\x75\x73 \x67\x6f\x64 " "\x61\x6e\x67\x65\x6c \x73\x61\x74\x61\x6e " "\x6c\x75\x63\x69\x66\x69\x65\x72 \x64\x65\x6d\x6f\x6e " "\x6f\x73\x61\x6d\x61 \x73\x61\x64\x61\x61\x6d")) { return false; } // just plain unoriginal/possibly intending to offend if(is_name( name, "merlin gandolf gandalf hero takhisis paladine majere morgion glarth " "trispringer chemosh zivilyn alexander belrak death angel bozo stupid " "beavis butthead mohammed mohammad buffy willow zander doom slayer rules rulez " "bauhaus lunitari solinari nuitari devil yugi anime penis assmunch " "kiri-jolith mishakal habbakuk branchala gilean sirrion reorx " "chislev shinare sargonnas zeboim hiddukel trinity morpheus " "blitz blytz budda buddah garlo blah blood buto cypher neo sliver " "alaric deity genocide freedalis gremlic hack hate king knight " "baron lord count prince princess darth vader lestat night zero " "victor viktor vashiva dashiva tinkle tanis sanctus rhuid rude")) return false; // reference names if(is_name( "none", name)) // none - used by olc return false; if(is_name( "self", name)) // self - used to reference self return false; if(is_name( "all", name)) // everyone in the game return false; if(is_name( "system", name)) return false; // council related names if(is_exact_name( "council", name )) return false; // next loop thru all the council names as defined in council_flags[] // admin can read all those notes { int index; for(index = 0; !IS_NULLSTR(council_flags[index].name); index++) { if(is_exact_name( council_flags[index].name, name )){ return false; } } } // next few are for allowing notes to certain groups if(is_name( "imm", name)) // immortals return false; if(is_name( "hero", name)) // heros return false; if(is_name( "heros", name)) // heros return false; if(is_name( "nsupport", name)) // newbie support return false; if(is_name( "head", name)) // head of departments return false; if(is_name( "noble", name)) // nobles return false; if(is_name( "admin", name)) // administrators return false; if(is_name( "imp", name)) // implementors return false; if(is_name( "rpsupport", name)) // role playing support return false; if(is_name( "olc", name)) // olc note group security >4 return false; if(is_name( "build", name)) // olc note group security >0 return false; if(is_name( "nsupport", name)) // newbie support return false; if(is_name( "bard", name )) // bards, for notes to bard return false; if(is_name( "karn", name)) // karns return false; // can't be named after clans if(clan_nlookup(name)>0) return false; // can't be named after a race if(race_exact_lookup(name)>=0){ return false; } // can't be named after a class if(class_exact_lookup(name)>=0){ return false; } // Length restrictions. if(str_len(name) <= 2 ) return false; if(str_len(name)>12) return false; if(name_confirmed) return true; // player specific if(is_name( "kal", name)) // kalahn return false; if(is_name_infix( name, "alahn elahn alehn elehn nhala")) // kalahn return false; if(is_name( "yle", name)) // ylerin return false; if(is_name( "quox", name)) // quoxatyl return false; if(is_name( "reav", name)) // reave return false; if(is_name( "imi", name)) // imidazole return false; // Alphanumerics only. // Lock out IllIll twits. { char *pc; bool fIll,adjcaps = false,cleancaps = false; int total_caps = 0; fIll = true; for( pc = name; *pc != '\0'; pc++ ) { if(!is_alpha(*pc) && *pc!='-') return false; if(is_upper(*pc)) // ugly anti-caps hack { if(adjcaps) cleancaps = true; total_caps++; adjcaps = true; } else adjcaps = false; if(LOWER(*pc) != 'i' && LOWER(*pc) != 'l' ) fIll = false; } if(fIll ) return false; if(cleancaps || (total_caps > (int) (str_len(name) / 2) && str_len(name) < 3)) return false; } // Prevent players from naming themselves after mobs. { extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH]; MOB_INDEX_DATA *pMobIndex; int iHash; for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) { for( pMobIndex = mob_index_hash[iHash]; pMobIndex != NULL; pMobIndex = pMobIndex->next ) { if(is_name( name, pMobIndex->player_name ) ) return false; } } } { // Prevent players from naming themselves after pkilled players FILE* file; char buf[MSL]; sprintf(buf, "%s%s", DEAD_DIR, name); fclose(fpReserve); // close the reserve file file = fopen (buf, "r"); // attempt to to open pkilled pfile if(file) { fclose(file); fpReserve = fopen( NULL_FILE, "r" ); return false; } fpReserve = fopen( NULL_FILE, "r" ); // reopen the reserve file } // Prevent players from naming themselves after deleted players if(file_exists("%s%s", DELETE_DIR, pfile_filename(name))){ return false; } // Prevent players from naming themselves after dead players if(file_exists("%s%s", DEAD_DIR, pfile_filename(name))){ return false; } return true; } /**************************************************************************/ // extremely ugly routine... needs a complete rewrite // if someone can be bothered. void roll_stats(connection_data *d) { char_data *ch, *v; int i; int total; int bias; char buf[MSL], sendbuf[MSL]; char * widthbuf=" "; bias = 0; sendbuf[0]='\0'; ch = d->character; total=0; v=ch; // generate the stats { attributes_set rm_stats_set; gen_rolemaster_stats(&rm_stats_set, ch->pcdata->reroll_counter); for(i=0; i<MAX_STATS; i++) { ch->perm_stats[i]= rm_stats_set.perm[i]; ch->potential_stats[i]=rm_stats_set.potential[i]; } } ch->pcdata->reroll_counter++; sprintf(buf," `cStrength (ST):`g%3d`c(`B%3d`c) Constitution (CO):`g%3d`c(`B%3d`c)\r\n", v->perm_stats[STAT_ST], v->potential_stats[STAT_ST], v->perm_stats[STAT_CO], v->potential_stats[STAT_CO]); strcat(sendbuf, widthbuf); strcat(sendbuf, buf); sprintf(buf," `cQuickness(QU):`g%3d`c(`B%3d`c) Agility (AG):`g%3d`c(`B%3d`c)\r\n", v->perm_stats[STAT_QU], v->potential_stats[STAT_QU], v->perm_stats[STAT_AG], v->potential_stats[STAT_AG]); strcat(sendbuf, widthbuf); strcat(sendbuf, buf); sprintf(buf," `cPresence (PR):`g%3d`c(`B%3d`c) Self-Discipline(SD):`g%3d`c(`B%3d`c)\r\n", v->perm_stats[STAT_PR], v->potential_stats[STAT_PR], v->perm_stats[STAT_SD], v->potential_stats[STAT_SD]); strcat(sendbuf, widthbuf); strcat(sendbuf, buf); sprintf(buf," `cEmpathy (EM):`g%3d`c(`B%3d`c) Memory (ME):`g%3d`c(`B%3d`c)\r\n", v->perm_stats[STAT_EM], v->potential_stats[STAT_EM], v->perm_stats[STAT_ME], v->potential_stats[STAT_ME]); strcat(sendbuf, widthbuf); strcat(sendbuf, buf); sprintf(buf," `cIntuition(IN):`g%3d`c(`B%3d`c) Reasoning (RE):`g%3d`c(`B%3d`c)\r\n", v->perm_stats[STAT_IN], v->potential_stats[STAT_IN], v->perm_stats[STAT_RE], v->potential_stats[STAT_RE]); strcat(sendbuf, widthbuf); strcat(sendbuf, buf); sprintf(buf," `ggreen is starting value, `B(blue) is potential with training`c.\r\n"); strcat(sendbuf, widthbuf); strcat(sendbuf, buf); if(GAMESETTING(GAMESET_SHOW_STAT_AVERAGES_IN_CREATION)){ int avpot=0, avperm=0; for(i=0; i<MAX_STATS; i++) { avperm+= ch->perm_stats[i]; avpot+= ch->potential_stats[i]; } sprintf(buf," `gaverage start %3d`B (average potential %3d)`c\r\n", avperm/MAX_STATS, avpot/MAX_STATS); strcat(sendbuf, widthbuf); strcat(sendbuf, buf); } strcat(sendbuf, "Are you happy with these attributes?\r\n"); ch->printf("`cAttributes Selection"); ch->print(sendbuf); } /**************************************************************************/ // returns true if the person was disconnected int count_creation_connections_per_hour(connection_data *d){ CREATION_COUNTER_DATA* tc; int count=0; // check them to the head of the linked list for(tc = creation_counter; tc; tc=tc->next) { if( !str_cmp(tc->ip, d->remote_ip) && (tc->time> current_time-60*60)) { count++; } } if(!GAMESETTING5(GAMESET5_RESTRICTED_CREATIONS_PER_HOUR) && count<40){ return 0; } return count; } /**************************************************************************/ // returns true if the person was disconnected bool check_connection(connection_data *d){ if(GAMESETTING5(GAMESET5_DEDICATED_PKILL_STYLE_MUD)){ return false; } if(count_creation_connections_per_hour(d)>5){ d->write(note_format_string(str_dup( "`1`1Due to abuse or potential abuse of the character creation system, " "we limit the number of characters that can be created within " "an hour or so from a single site. Try creating again an hour or so.`1`1")), 0); logf("%s %s (%d) dropped - creating too many times.", CH(d)->name, d->remote_hostname, d->connected_socket ); { char log_buf[MSL]; sprintf( log_buf, "%s %s (%d) dropped - creating to many times.\r\n", CH(d)->name, d->remote_hostname, d->connected_socket ); wiznet(log_buf,NULL,NULL,WIZ_SECURE,0,get_trust(CH(d)) ); } connection_close(d); return true; } return false; } /**************************************************************************/ void add_connection(connection_data *d) { CREATION_COUNTER_DATA* tc; tc = new CREATION_COUNTER_DATA; tc->ip = str_dup(d->remote_ip); tc->time = current_time; // add them to the head of the linked list tc->next=creation_counter; creation_counter=tc; } /**************************************************************************/ // go on to selecting the race void nannysup_past_email_check(connection_data *d, const char *) { int race; // display races CH(d)->wrapln( "It it now time to select a city... You can read online help on any " "city by simply typing `RHELP <CITYNAME>`c where `R<CITYNAME>`c is the " "name of the city you are interested in (e.g. `RHELP ATHENIAN`c). " "If you are unsure about which city to play, we recommend Athenian as " "they are good all round city, and start have the largest population.`1"); if(!GAMESETTING5(GAMESET5_RACEINFO_DISABLED_IN_CREATION)){ CH(d)->wraplnf( "Note: You can type `Rcityinfo`c for a list of cities, their " "citizenship attribute modifiers, creation point cost and " "maximum hitpoints.`1"); } if(!codehelp(CH(d), "racial_option", false)){ CH(d)->printf("Please select your city from one of the following:`1 "); int count=0; for( race = 0; race_table[race]; race++ ) { // creation selectable pc races only if(!race_table[race]->creation_selectable() || (race_table[race]->remort_number > d->creation_remort_number)){ continue; } CH(d)->printf(" `S[`Y%12.12s`S]", race_table[race]->name); if(++count%5==0){ CH(d)->printf("`c\r\n "); } } CH(d)->printf("`1`cType in the name of the city you wish to play now:`1"); } d->connected_state = CON_GET_NEW_RACE; } /**************************************************************************/ void nannysup_setprime_stats( char_data *ch ) { bool changed = false; // if character's prime stats are below 80 they get set to 80. // if character's prime stats are 90 + they get +5 to their prime to a max of 101 int old; // Do first primary stat if(ch->potential_stats[class_table[ch->clss].attr_prime[0]] < 80 ) { old=ch->potential_stats[class_table[ch->clss].attr_prime[0]]; ch->potential_stats[class_table[ch->clss].attr_prime[0]] = 80; ch->printlnf("Your %s has increased from %d to 80!", stat_flags[class_table[ch->clss].attr_prime[0]].name, old); changed = true; } else if(ch->potential_stats[class_table[ch->clss].attr_prime[0]] < 90 ) { old=ch->potential_stats[class_table[ch->clss].attr_prime[0]]; ch->potential_stats[class_table[ch->clss].attr_prime[0]] += (UMIN(ch->potential_stats[class_table[ch->clss].attr_prime[0]]-78, 10)/2); ch->printlnf("Your %s has increased from %d to %d!", stat_flags[class_table[ch->clss].attr_prime[0]].name, old, ch->potential_stats[class_table[ch->clss].attr_prime[0]]); changed = true; } else // if(ch->potential_stats[class_table[ch->clss].attr_prime[0]] => 90 ) { old=ch->potential_stats[class_table[ch->clss].attr_prime[0]]; ch->potential_stats[class_table[ch->clss].attr_prime[0]] += 5; if(ch->potential_stats[class_table[ch->clss].attr_prime[0]] > 101) { ch->potential_stats[class_table[ch->clss].attr_prime[0]] = 101; } ch->printlnf("Your %s has increased from %d to %d!", stat_flags[class_table[ch->clss].attr_prime[0]].name, old, ch->potential_stats[class_table[ch->clss].attr_prime[0]]); changed = true; } // Do second primary stat if(ch->potential_stats[class_table[ch->clss].attr_prime[1]] < 80 ) { old=ch->potential_stats[class_table[ch->clss].attr_prime[1]]; ch->potential_stats[class_table[ch->clss].attr_prime[1]] = 80; ch->printlnf("Your %s has increased from %d to 80!", stat_flags[class_table[ch->clss].attr_prime[1]].name, old); changed = true; } else if(ch->potential_stats[class_table[ch->clss].attr_prime[1]] < 90 ) { old=ch->potential_stats[class_table[ch->clss].attr_prime[1]]; ch->potential_stats[class_table[ch->clss].attr_prime[1]] += (UMIN(ch->potential_stats[class_table[ch->clss].attr_prime[1]]-78, 10)/2); ch->printlnf("Your %s has increased from %d to %d!", stat_flags[class_table[ch->clss].attr_prime[1]].name, old, ch->potential_stats[class_table[ch->clss].attr_prime[1]]); changed = true; } else // if(ch->potential_stats[class_table[ch->clss].attr_prime[1]] => 90 ) { old=ch->potential_stats[class_table[ch->clss].attr_prime[1]]; ch->potential_stats[class_table[ch->clss].attr_prime[1]] += 5; if(ch->potential_stats[class_table[ch->clss].attr_prime[1]] > 101) { ch->potential_stats[class_table[ch->clss].attr_prime[1]] = 101; } ch->printlnf("Your %s has increased from %d to %d!", stat_flags[class_table[ch->clss].attr_prime[1]].name, old, ch->potential_stats[class_table[ch->clss].attr_prime[1]]); changed = true; } if(!changed){ ch->println("Your stats have remained the same."); } return; } /**************************************************************************/ void do_clear_createcount( char_data *ch, char *argument ) { if(str_cmp("confirm", argument)) { ch->println("Syntax: clear_createcount confirm"); ch->println("notes: It clears the counter of who created in the last hour."); return; } ch->println("Creation counter cleared."); creation_counter=NULL; return; } /**************************************************************************/ void nsupport_newbie_alert( char_data *ch, bool created ) { connection_data *d; for( d = connection_list; d != NULL; d = d->next ) { if( d->connected_state == CON_PLAYING && CH(d) && d->character != ch && IS_NEWBIE_SUPPORT( d->character )) { // an existing newbie logging on, // if they have newbie channel off, then no warning is given if(created && !HAS_CONFIG( ch, CONFIG_NONEWBIE )) { d->character->printlnf( "`sNewbie '%s' has just logged on.`c", ch->name ); } if(!created ) { d->character->printlnf( "`sNew player '%s' is creating, please make them feel welcome when they arrive.", ch->name ); } } } } /**************************************************************************/ void greet_new_connection(connection_data *d); /**************************************************************************/ // give time for the telnet option negotiation to work void nanny_detect_client_settings(connection_data *c, char *argument) { bool t=c->fcommand; c->fcommand=true; #ifdef SHOW_CLIENT_DETECTION if(c->outtop==0){ write_to_buffer( c, ".", 1); if(c->connected_state_pulse_counter%42==0){ write_to_buffer( c, "\r\n", 2); } } #endif #ifdef SHOW_CLIENT_DETECTION if(!IS_NULLSTR(argument)){ write_to_buffer( c, "^", 1); } #endif if(!IS_NULLSTR(argument) || ++c->connected_state_pulse_counter>PULSE_PER_SECOND*4){ #ifdef SHOW_CLIENT_DETECTION { // write_to_buffer( c,".. detection completed.\033\133\062\113\r\n", 0); // the above esc code sequence was used to delete the detect line write_to_buffer( c,".. detection completed.\r\n", 0); } #endif c->fcommand=t; greet_new_connection(c); // jump straight into username input if detection was aborted // for any keystroke other than enter c->connected_state=CON_GET_NAME; if(!IS_NULLSTR(argument)){ if(*argument!=' ' && *(argument+1)!='\0'){ nanny(c, argument); } } return; } c->fcommand=t; } /**************************************************************************/ /**************************************************************************/ /**************************************************************************/