/**************************************************************************/ // laston.cpp - Laston command, see below for more /*************************************************************************** * 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 the dawn license * * in licenses.txt... In particular, you may not remove this copyright * * notice. * **************************************************************************/ /*************************************************************************** * LASTON records upto the last LASTON_ARRAY_SIZE times a character * * was on, and for how long. Stores the data in a linked list, to * * data across a reboot, it uses my GIO (generic IO) system * * * * Copyright 1997-2001 Michael Garratt * * check out http://www.dawnoftime.org/ for the latest version of dawn * ***************************************************************************/ char *dawnstat_generate_mud_client_stats(); void dawnstat_update(); #include "include.h" // dawn standard includes #include "clan.h" #include "laston.h" laston_data *laston_list; //last on list system laston_data *laston_rpers_list; // last on RPS list system time_t laston_since; // rough estimate of how current the last on data is time_t laston_next_save=0; char *flag_string( const struct flag_type *flag_table, int bits ); #define last_resave resave(ch, argument);laston_next_save /**************************************************************************/ // write the race name void lastondata_write_race(gio_type *gio_table, int tableIndex, void *data, FILE *fp) { laston_data * pld; pld= (laston_data*) data; fprintf(fp, "%s %s~\n", gio_table[tableIndex].heading, race_table[pld->race]->name); } /**************************************************************************/ // read the race name void lastondata_read_race(gio_type *, int, void *data, FILE *fp) { laston_data * pld; char *pstr; pld= (laston_data*) data; pstr=fread_string(fp); pld->race=race_lookup(pstr); if(pld->race<0){ bugf("Laston found unrecognised race '%s' for '%s'", pstr,pld->name); pld->race=0; } free_string(pstr); } /**************************************************************************/ // write the class name void lastondata_write_class(gio_type *gio_table, int tableIndex, void *data, FILE *fp) { laston_data * pld; pld= (laston_data*) data; fprintf(fp, "%s %s~\n", gio_table[tableIndex].heading, class_table[pld->clss].name); } /**************************************************************************/ // read the class name void lastondata_read_class(gio_type *, int, void *data, FILE *fp) { laston_data * pld; char *pstr; pld= (laston_data*) data; pstr=fread_string(fp); pld->clss=class_exact_lookup(pstr); if(pld->clss<0){ bugf("Laston found unrecognised class '%s' for '%s'", pstr,pld->name); pld->clss=0; } free_string(pstr); } /**************************************************************************/ // write the clan name void lastondata_write_clan(gio_type *gio_table, int tableIndex, void *data, FILE *fp) { laston_data * pld; pld= (laston_data*) data; if(pld->clan){ fprintf(fp, "%s %s~\n", gio_table[tableIndex].heading, pld->clan->savename()); } } /**************************************************************************/ // read the clan name void lastondata_read_clan(gio_type *, int, void *data, FILE *fp) { laston_data * pld; char *pstr; pld= (laston_data*) data; pstr=fread_string(fp); pld->clan=clan_slookup(pstr); // returns NULL if not found free_string(pstr); } /**************************************************************************/ // write the clanrank name void lastondata_write_clanrank(gio_type *gio_table, int tableIndex, void *data, FILE *fp) { laston_data * pld; pld= (laston_data*) data; if(pld->clan>0){ fprintf(fp, "%s %s~\n", gio_table[tableIndex].heading, pld->clan->clan_rank_title(pld->clanrank)); } } /**************************************************************************/ // read the clanrank name void lastondata_read_clanrank(gio_type *, int, void *data, FILE *fp) { laston_data * pld; char *pstr; pld= (laston_data*) data; pstr=fread_string(fp); pld->clanrank=pld->clan->rank_lookup(pstr); // returns 0/-1 if not found if(pld->clanrank<0){ bugf("Laston found unrecognised clanrank '%s' for '%s'", pstr,pld->name); pld->clanrank=0; } free_string(pstr); } /**************************************************************************/ // create race_type_old GIO lookup table GIO_START(laston_data) GIO_STR(name) GIO_INT(id) GIO_INT(know_index) GIO_WFLAGH(flags, "lastonflags ", laston_flags) GIO_WFLAGH(council, "council ", council_flags) GIO_SHWFLAGH(sex, "sex ", sex_types) GIO_INT(trust) GIO_INT(security) GIO_INT(played) GIO_INT(logout_room) GIO_INT(deleted_date) GIO_CUSTOM_WRITEH(race, "Race ", lastondata_write_race) GIO_CUSTOM_READH(race, "Race ", lastondata_read_race) GIO_CUSTOM_WRITEH(clss, "Class ", lastondata_write_class) GIO_CUSTOM_READH(clss, "Class ", lastondata_read_class) GIO_CUSTOM_WRITEH(clan, "Clan ", lastondata_write_clan) GIO_CUSTOM_READH(clan, "Clan ", lastondata_read_clan) GIO_CUSTOM_WRITEH(clanrank, "Clanrank ", lastondata_write_clanrank) GIO_CUSTOM_READH(clanrank, "Clanrank ", lastondata_read_clanrank) GIO_INT(rps) GIO_INT(xp) GIO_INT(alliance) GIO_INT(tendency) GIO_STR(short_descr) GIO_STR(email) GIO_STR(webpass) GIO_STR(mxp_client_version) GIO_STR(terminal_type) // arrays GIO_INT(index) GIO_STR_ARRAY(host,LASTON_ARRAY_SIZE) GIO_STR_ARRAY(ip,LASTON_ARRAY_SIZE) GIO_STR_ARRAY(ident,LASTON_ARRAY_SIZE) GIO_INT_ARRAY(level,LASTON_ARRAY_SIZE) GIO_INT_ARRAY(sublevel,LASTON_ARRAY_SIZE) GIO_LONG_ARRAY(on,LASTON_ARRAY_SIZE) GIO_LONG_ARRAY(off,LASTON_ARRAY_SIZE) GIO_SHINT_WITH_DEFAULT(wiznet_type, 0) // saved as a number, to save space GIO_FINISH /**************************************************************************/ // prototypes void laston_save(char_data *ch); void resort_top_roleplayers(); int get_sublevels_for_level(int level); /**************************************************************************/ // timediff() - written By Kalahn - June 97 char *timediff(time_t t1, time_t t2) { static char timebuf[3][MSL]; static int index; // used to rotate around 3 buffers, so timediff can // be used up to 3 times in one context without // overwriting a previous buffer ++index%=3; // rotate the index timebuf[index][0]='\0'; // clear the previous string // calculate the difference in time, and break it down long dsec, dmin, dhour, dday; long dweek, dmonth, dyear; dsec = abs((int)(t1-t2)); // difference between times in seconds dday = dsec/(60*60*24); dsec %= 60*60*24; dyear = dday/365; dday %= 365; dmonth= dday/(365/12); dday -= dmonth*(365/12); dweek = dday/7; dday %= 7; dhour = dsec/(60*60); dsec %= 60*60; dmin = dsec/60; dsec = dsec%60; // format the result up char working[MSL]; if (dyear!=0) { sprintf (working,"%ld year%s, ", dyear, ((dyear!=1)?"s":"")); strcat (timebuf[index], working); } if (dmonth!=0) { sprintf (working,"%ld month%s, ", dmonth, ((dmonth!=1)?"s":"")); strcat (timebuf[index], working); } if (dweek!=0) { sprintf (working,"%ld week%s, ", dweek, ((dweek!=1)?"s":"")); strcat (timebuf[index], working); } if (dday!=0) { sprintf (working,"%ld day%s, ", dday, ((dday!=1)?"s":"")); strcat (timebuf[index], working); } if (dhour!=0) { sprintf (working,"%ld hour%s, ", dhour, ((dhour!=1)?"s":"")); strcat (timebuf[index], working); } if (dmin!=0) { sprintf (working,"%ld minute%s, ", dmin, ((dmin!=1)?"s":"")); strcat (timebuf[index], working); } if (dsec!=0) { sprintf (working,"%ld second%s", dsec, ((dsec!=1)?"s":"")); strcat (timebuf[index], working); } // remove a space and comma that could be at the end of the line char *trim = &timebuf[index][str_len(timebuf[index])-1]; if (*trim==' ' || *trim==',') { *trim = '\0'; trim--; if (*trim==' ' || *trim==',') *trim = '\0'; } return(timebuf[index]); } /**************************************************************************/ // short_timediff() - written By Kalahn - Aug 97 char *condensed_timediff(time_t t1, time_t t2) { static char timebuf[3][MSL]; static int index; // used to rotate around 3 buffers, so timediff can // be used up to 3 times in one context without // overwriting a previous buffer ++index%=3; // rotate the index timebuf[index][0]='\0'; // clear the previous string // calculate the difference in time, and break it down long dsec, dmin, dhour, dday; long dweek, dmonth, dyear; dsec = abs((int)(t1-t2)); // difference between times in seconds dday = dsec/(60*60*24); dsec %= 60*60*24; dyear = dday/365; dday %= 365; dmonth= dday/(365/12); dday -= dmonth*(365/12); dweek = dday/7; dday %= 7; dhour = dsec/(60*60); dsec %= 60*60; dmin = dsec/60; dsec = dsec%60; // format the result up char working[MSL]; if (dyear!=0) { sprintf(working,"%ld year%s,", dyear, ((dyear!=1)?"s":"")); strcat(timebuf[index], working); } if (dmonth!=0) { sprintf (working,"%ld month%s,", dmonth, ((dmonth!=1)?"s":"")); strcat (timebuf[index], working); } if (dweek!=0) { sprintf (working,"%ld week%s, ", dweek, ((dweek!=1)?"s":"")); strcat (timebuf[index], working); } if (dday!=0) { sprintf (working,"%ldd,", dday); strcat (timebuf[index], working); } sprintf (working,"%2ld:%.2ld:%.2ld", dhour, dmin, dsec); strcat (timebuf[index], working); // remove a space and comma that could be at the end of the line char *trim = &timebuf[index][str_len(timebuf[index])-1]; if (*trim==' ' || *trim==',') { *trim = '\0'; trim--; if (*trim==' ' || *trim==','){ *trim = '\0'; } } return(timebuf[index]); } /**************************************************************************/ // short_timediff() - written By Kalahn - Aug 97 char *short_timediff(time_t t1, time_t t2) { static char timebuf[3][MSL]; static int index; // used to rotate around 3 buffers, so timediff can // be used up to 3 times in one context without // overwriting a previous buffer ++index%=3; // rotate the index timebuf[index][0]='\0'; // clear the previous string // calculate the difference in time, and break it down long dsec, dmin, dhour, dday; long dweek, dmonth, dyear; dsec = abs((int)(t1-t2)); // difference between times in seconds dday = dsec/(60*60*24); dsec %= 60*60*24; dyear = dday/365; dday %= 365; dmonth= dday/(365/12); dday -= dmonth*(365/12); dweek = dday/7; dday %= 7; dhour = dsec/(60*60); dsec %= 60*60; dmin = dsec/60; dsec = dsec%60; // format the result up char working[MSL]; if (dyear!=0) { sprintf(working,"%ld year%s,", dyear, ((dyear!=1)?"s":"")); strcat(timebuf[index], working); } if (dmonth!=0) { sprintf (working,"%ld month%s,", dmonth, ((dmonth!=1)?"s":"")); strcat (timebuf[index], working); } if (dweek!=0) { sprintf (working,"%ld week%s, ", dweek, ((dweek!=1)?"s":"")); strcat (timebuf[index], working); } if (dday!=0) { sprintf (working,"%ld day%s, ", dday, ((dday!=1)?"s":"")); strcat (timebuf[index], working); } if (str_len(timebuf[index])!=0) // put in a summary of the hrs,mins&secs { sprintf (working,"%2ld:%.2ld:%.2ld", dhour, dmin, dsec); strcat (timebuf[index], working); } else { if (dhour!=0) { sprintf (working,"%ld hr%s, ", dhour, ((dhour!=1)?"s":"")); strcat (timebuf[index], working); } if (dmin!=0) { sprintf (working,"%ld min%s, ", dmin, ((dmin!=1)?"s":"")); strcat (timebuf[index], working); } if (dsec!=0) { sprintf (working,"%ld sec%s", dsec, ((dsec!=1)?"s":"")); strcat (timebuf[index], working); } } // remove a space and comma that could be at the end of the line char *trim = &timebuf[index][str_len(timebuf[index])-1]; if (*trim==' ' || *trim==',') { *trim = '\0'; trim--; if (*trim==' ' || *trim==','){ *trim = '\0'; } } return(timebuf[index]); } /**************************************************************************/ // laston_remove_list - written by Kalahn - Sept 1997 // - removes someone from the laston list // - NOTE: it doesn't deallocate the memory for the node void laston_remove_list(laston_data *node) { // check to make sure they are marked as being in the list if (!node->in_list) return; if (node== laston_list) // we are the head of the list { laston_list = laston_list->next;// move the head if (laston_list) // if not empty list now laston_list->prev= NULL; // remove node from prev link node->in_list = false; // mark node as not in list return; } if (node->next) // we are in the middle of the list { node->prev->next = node->next; // remove node from next link node->next->prev = node->prev; // remove node from prev link node->in_list = false; // mark node as not in list } else // we must be at the tail of the list { node->prev->next = NULL; // remove node from next link node->in_list = false; // mark node as not in list } } /**************************************************************************/ // laston_add_list - written by Kalahn - Sept 1997 // - adds someone to the laston list above the given pointer void laston_add_list(laston_data *newnode, laston_data *where) { if (!newnode) // newnode can't be null return; // check to make sure we aren't trying to add above itself if (newnode == where) return; // remove from the list if we are already in there if (newnode->in_list) laston_remove_list(newnode); // *** check if we are starting a new list or adding to the head *** if (where == laston_list) // add to the head of the new list { newnode->next= laston_list; // put in next node in list if (newnode->next) // link back - if list isn't NULL newnode->next->prev= newnode; newnode->prev=NULL; // head of list - no prev pointer laston_list=newnode; // make newnode the head of laston_list newnode->in_list = true; // mark node as in list return; } if (!where) // you can't add newnode to a NULL pointer return; // end of checks - now add the newnode before where // code above tells us that 'where' is a not the head node newnode->next = where; newnode->prev = where->prev; where->prev = newnode; newnode->prev->next = newnode; newnode->in_list = true; // mark node as now in list } /**************************************************************************/ // laston_update_node - written by Kalahn // - updates a node record with the players info // - marks them as online // - does NOT affect the position in the laston list void laston_update_node(laston_data *node, char_data *ch) { assert(!IS_NPC(ch)); node->level[node->index] = ch->level; node->sublevel[node->index] = ch->pcdata->sublevel; // load their council from laston ch->pcdata->council= node->council; if(ch->desc){ replace_string(node->host[node->index], ch->desc->remote_hostname); replace_string(node->ip[node->index], ch->desc->remote_ip); } // ident if(ch->desc && !IS_NULLSTR(ch->desc->ident_username)){ replace_string(node->ident[node->index], ch->desc->ident_username); }else{ replace_string(node->ident[node->index],""); } // name replace_string(node->name,ch->name); // other details node->race = ch->race; node->clss = ch->clss; node->trust = ch->trust; node->clan = ch->clan; node->clanrank = ch->clanrank; node->security = ch->pcdata->security; // olc security node->sex = ch->pcdata->true_sex; node->rps = ch->pcdata->rp_points; node->xp = ch->exp; node->alliance = ch->alliance; node->tendency = ch->tendency; node->know_index= ch->know_index; if(ch->in_room){ node->logout_room=ch->in_room->vnum; }else{ node->logout_room=0; } //===+--- FLAGS ---+=== // CURRENTLY ONLINE SET_BIT(node->flags, LASTON_ONLINE); node->played=ch->played; // IRC PLAYER if (IS_IRC(ch)){ SET_BIT(node->flags, LASTON_IRC); SET_BIT(node->flags, LASTON_HASUSEDIRC); }else{ REMOVE_BIT(node->flags, LASTON_IRC); } // LOGGED PLAYER if (IS_SET(ch->act, PLR_LOG)){ SET_BIT(node->flags, LASTON_LOGGED); }else{ REMOVE_BIT(node->flags, LASTON_LOGGED); } // NOBLES if (IS_NOBLE(ch)){ SET_BIT(node->flags, LASTON_NOBLE); }else{ REMOVE_BIT(node->flags, LASTON_NOBLE); } // LETGAINED if ( IS_LETGAINED(ch) ){ SET_BIT(node->flags, LASTON_LETGAINED); }else{ REMOVE_BIT(node->flags, LASTON_LETGAINED); } // Automap if ( USING_AUTOMAP(ch) ){ SET_BIT(node->flags, LASTON_USING_AUTOMAP); }else{ REMOVE_BIT(node->flags, LASTON_USING_AUTOMAP); } // MSP if ( HAS_MSP( ch )){ SET_BIT(node->flags, LASTON_USING_MSP); }else{ REMOVE_BIT(node->flags, LASTON_USING_MSP); } // ACTIVE if ( IS_ACTIVE(ch)){ SET_BIT(node->flags, LASTON_ACTIVE); }else{ REMOVE_BIT(node->flags, LASTON_ACTIVE); } // Quester if ( IS_SET(ch->act, PLR_QUESTER)){ SET_BIT(node->flags, LASTON_QUESTER); }else{ REMOVE_BIT(node->flags, LASTON_QUESTER); } // Nsupport if ( IS_SET(ch->comm, COMM_NEWBIE_SUPPORT)){ SET_BIT(node->flags, LASTON_NSUPPORT); }else{ REMOVE_BIT(node->flags, LASTON_NSUPPORT); } // Allowimmtalk if ( ch->pcdata->immtalk_name){ SET_BIT(node->flags, LASTON_ALLOWIMMTALK); }else{ REMOVE_BIT(node->flags, LASTON_ALLOWIMMTALK); } // NO MAX KARN if ( IS_SET(ch->act, PLR_NOREDUCING_MAXKARN)){ SET_BIT(node->flags, LASTON_NOMAXKARN); }else{ REMOVE_BIT(node->flags, LASTON_NOMAXKARN); } if(ch->pcdata){ replace_string(node->email,ch->pcdata->email); replace_string(node->webpass, ch->pcdata->webpass); } replace_string(node->short_descr,ch->short_descr); if(ch->desc){ // mccp #ifdef MCCP_ENABLED if(ch->desc->out_compress){ SET_BIT(node->flags, LASTON_MCCP); }else{ REMOVE_BIT(node->flags, LASTON_MCCP); } #else REMOVE_BIT(node->flags, LASTON_MCCP); #endif // mxp version if(!IS_NULLSTR(ch->desc->mxp_version)){ replace_string(node->mxp_client_version,ch->desc->mxp_version); }else{ replace_string(node->mxp_client_version,""); } // terminal type if(!IS_NULLSTR(ch->desc->terminal_type)){ replace_string(node->terminal_type,ch->desc->terminal_type); }else{ replace_string(node->terminal_type,""); } } // save laston data if it hasn't been saved recently if (LASTON_SAVE_DATA && laston_next_save < current_time){ laston_save(NULL); }else{ // record system just started - set next save time laston_next_save = current_time + LASTON_SAVE_INTERVAL; } } /**************************************************************************/ // returns either a pointer to the node or NULL laston_data *find_node_from_id(int id) { laston_data *node; // find them in the list for (node= laston_list; node; node=node->next) { if (node->id==id) return node; } return NULL; } /**************************************************************************/ void laston_update_char(char_data *ch) { laston_data *node; char buf[MSL]; if(!ch){ bug("laston_update_char(): ch==NULL!!!"); return; } // ploaded players are not recorded in laston if(ch->pload){ return; } node=find_node_from_id(ch->id); if (node){ laston_update_node(node, ch); // update all the entries in the node }else{ sprintf(buf,"laston_update_char was passed a ch not in the laston_list (%s)\r\n" , ch->name); wiznet(buf,NULL,NULL,WIZ_BUGS,0,ADMIN); // put it on the bug channel log_string( buf ); } } /**************************************************************************/ // laston_login - written by Kalahn - July 1997 // - records time when someone logs on // - called from comm.c just before do_unread(ch,""); void laston_login(char_data *ch) { laston_data *node=NULL; int ti; // check if they are in the list for (node= laston_list; node; node=node->next){ if(node->id==ch->id){ // we have found our player already in list break; } } if (!node){ // we didn't find them - new addition to the laston database node = (laston_data *)malloc(sizeof(laston_data)); memset( node, 0, sizeof(laston_data) ); node->in_list = false; node->id=ch->id; node->index = 0; node->flags = 0; node->council=0; node->name=str_dup("(unknown)"); node->short_descr=str_dup(""); node->email= str_dup(""); node->webpass=str_dup(""); node->mxp_client_version=str_dup(""); node->terminal_type=str_dup(""); node->login_room=0; for (ti=0; ti<LASZ;ti++) // initialise on and off values { node->on[ti]=0; node->off[ti]=0; node->level[ti]=0; node->sublevel[ti]=0; node->host[ti]=str_dup(""); node->ident[ti]=str_dup(""); } // set if they are connecting from IRC first time if (IS_IRC(ch)){ SET_BIT(node->flags, LASTON_FIRSTIRC); } } else // we found them in the list { ++node->index%=LASZ; //get next index mod LASZ // remove from their current place in the list laston_remove_list(node); } node->deleted_date=0; node->on[node->index] = current_time; // record the logon time laston_add_list(node, laston_list); // add them to the head of the list laston_update_node(node,ch); // update all the entries in the node // load their council from laston ch->pcdata->council= node->council; } /**************************************************************************/ // laston_logout - written by Kalahn - July 1997 // - records logout time in the laston database // - called from handler.c in extract_char() void laston_logout(char_data *ch) { laston_data *node, *last_online=NULL, *found_node=NULL; if (IS_NPC(ch)) return; // find them in the list for (node= laston_list; node; node=node->next) { if (IS_SET(node->flags, LASTON_ONLINE)) // record the laston online last_online = node; if (ch->pcdata->karns<0){ SET_BIT(node->flags, LASTON_PERM_PKILLED); // permkilled }else{ REMOVE_BIT(node->flags, LASTON_PERM_PKILLED); // not permkilled } if (node->id==ch->id) // we have found our player in the list { found_node = node; node->off[node->index] = current_time; // record when they log off if (node->off[node->index]<=node->on[node->index]) node->off[node->index]++; // incase system clock is reset node->level[node->index] = ch->level; // record logoff level node->trust = ch->trust; node->clan = ch->clan; node->clanrank = ch->clanrank; node->security = ch->pcdata->security; // olc security REMOVE_BIT(node->flags, LASTON_ONLINE); // nolonger online node->council = ch->pcdata->council; // record their council } } // move them to the first offline place in the list if required if ( last_online && found_node && (last_online!=found_node) ) { laston_remove_list(found_node); if (last_online->next) laston_add_list(found_node, last_online->next); else { // shuffle around to get them at the bottom laston_add_list(found_node, last_online); laston_remove_list(last_online); laston_add_list(last_online, found_node); } }; // save laston data if it hasn't been saved recently if (laston_next_save < current_time){ laston_save(NULL); } } /**************************************************************************/ // laston_delete - written by Kalahn - July 1997 // - removes someone from the laston database void laston_id_delete(long id) { laston_data *node=NULL; int ti; // find them in the list for (node= laston_list; node; node=node->next ) { if (node->id==id) break; } if (node) // They are in the list { // create the deleters log { char buf[MIL], buf2[MIL]; int tempindex, newindex; sprintf ( buf, "DELETED CHARACTER REMOVAL: %s %s %s %s", node->name, (node->clss > -1?class_table[node->clss].short_name:""), (node->race > -1?race_table[node->race]->name:""), shortdate(NULL) ); append_datetimestring_to_file( LASTON_DELETE_LOGFILE, buf); // display clan info if (node->clan>0){ sprintf(buf,"`xclan: %s `xrank: %s (%d)`x", node->clan->cwho_name(), node->clan->clan_rank_title(node->clanrank), node->clanrank); append_datetimestring_to_file( LASTON_DELETE_LOGFILE, buf); } sprintf ( buf, "Noble: %s Created: %s", (IS_SET(node->flags, LASTON_NOBLE)?"`#`RYES`^":"no"), ctime( (time_t *) &node->id)); append_datetimestring_to_file( LASTON_DELETE_LOGFILE, buf); sprintf ( buf, "Email: %s\r\n", node->email); append_datetimestring_to_file( LASTON_DELETE_LOGFILE, buf); // characters times and levels for (tempindex=node->index+LASZ; tempindex > node->index; tempindex--) { newindex = tempindex % LASZ; if (node->on[newindex]!=0) // display only valid records { strcpy(buf2, ctime((time_t *) &node->on[newindex])); buf2[20] = '\0'; //remove year if (node->off[newindex]<=node->on[newindex]) { sprintf ( buf, "on: %s\nonline for %s (lvl %d) [%s]", buf2, short_timediff(node->on[newindex] , current_time), node->level[newindex], node->host[newindex] ); append_datetimestring_to_file( LASTON_DELETE_LOGFILE, buf); } else { sprintf ( buf, "on: %s %s\nwas on for %s (left level %d) [%s]", buf2, short_timediff(node->on[newindex], node->off[newindex]), short_timediff(node->on[newindex], current_time), node->level[newindex], node->host[newindex] ); append_datetimestring_to_file( LASTON_DELETE_LOGFILE, buf); } } // display valid data } // end of loop thru a characters LASZ times } // remove them from the list laston_remove_list(node); // deallocate memory for hosts for (ti=0; ti<LASZ;ti++){ if(!IS_NULLSTR(node->host[ti])){ free_string(node->host[ti]); } } // deallocate memory free(node); } // resort the laston toproleplayers list resort_top_roleplayers(); } /**************************************************************************/ void laston_delete(char_data * ch) { laston_id_delete(ch->id); laston_save(ch); } /**************************************************************************/ // Instead of deleting players, record the date they deleted on... then // laston can drop them out of the database depending on their level. // gamesettings record how long to keep deleted players in laston. void laston_player_deleting(char_data * ch) { // find them in the list laston_data *node=NULL; for (node= laston_list; node; node=node->next ) { if (node->id==ch->id) break; } if(!node){ bugf("laston_player_deleting(): Couldn't find player '%s' in the laston " "database to mark as deleted.", ch->name); return; } node->deleted_date=current_time; } /**************************************************************************/ // laston_mortal - written by Kalahn - Sept 1997 // - displays the basic laston data for a mortal. void laston_mortal( char_data *ch, char *argument ) { extern time_t boot_time; BUFFER *output; char buf[MSL]; char arg[MIL]; sh_int newindex=0, ntotal, displaycounter; bool buffer_overflow=false; laston_data *node; // Morts can't get a full listing // - so if they didn't specify a parameter, send them back if(GAMESETTING3(GAMESET3_MORTLASTON_REQUIRES_PART_OF_NAME) && IS_NULLSTR(argument)){ ch->println("You must type part of a characters name"); return; // exit with doing anything } argument = one_argument( argument, arg ); // Display a message telling roughly how current the data is ch->printlnf("%s has been up for %s", MUD_NAME, timediff(boot_time, current_time)); ch->printlnf("The current time is %sLaston records date back %s.", (char *) ctime( ¤t_time ), timediff(laston_since, current_time)); ch->println("Showing upto the ten most recent matches"); if(GAMESETTING3(GAMESET3_MORTLASTON_REQUIRES_FULL_IMM_NAME)){ ch->println("Note: Immortals do not show up on this list unless you spell their full name."); } // setup a buffer for info to be displayed output = new_buf(); // reset counters ntotal=0; // node total counter displaycounter=0; // counter of number about to displayed // loop thru all character records in linked list for (node= laston_list; node; node=node->next) { newindex= node->index; if (displaycounter>10) // display only last 10 characters continue; if (!str_prefix(arg, node->name)) { if (ch->id==node->id){ // check if lastoning themselves sprintf ( buf, "%-12s (you) have been online for %s.\r\n", node->name, timediff(node->on[newindex] , current_time)); }else{ // morts can't see deleted players in laston if(node->deleted_date){ continue; } // those that have abused laston can't see others within 2 days if (IS_SET(ch->comm,COMM_REDUCED_LASTON) && (IS_SET(node->flags, LASTON_ONLINE) || (node->off[newindex]> current_time-3600*48))) { sprintf ( buf, "%-12s is currently online or has been within the last 2 days.\r\n", node->name); } // those who have CONFIG2_ACCURATE_LASTON_TIMES set else if(HAS_CONFIG2(ch, CONFIG2_ACCURATE_LASTON_TIMES)){ if ( IS_SET(node->flags, LASTON_ONLINE) ){ sprintf ( buf, "%-12s is currently online.\r\n", node->name); }else{ sprintf ( buf, "%-12s laston %s ago.\r\n", node->name, timediff(node->off[newindex] , current_time)); } } // handle viewing of immortal characters else if(node->level[node->index]>=LEVEL_IMMORTAL) { // gotta do exact name match for an imm if(GAMESETTING3(GAMESET3_MORTLASTON_REQUIRES_FULL_IMM_NAME) && str_cmp(arg, node->name)){ continue; } if(GAMESETTING3(GAMESET3_MORTLASTON_REDUCED_LASTDAY_ON_IMMS) && (node->off[newindex]>current_time-3600*24 || IS_SET(node->flags, LASTON_ONLINE)) ) { sprintf ( buf, "%-12s is currently online or has been within the last day.\r\n", node->name); } // immortal is currently online else if ( IS_SET(node->flags, LASTON_ONLINE) ){ sprintf ( buf, "%-12s is currently online.\r\n", node->name); } // they aren't online else{ sprintf ( buf, "%-12s laston %s ago.\r\n", node->name, timediff(node->off[newindex] , current_time)); } } // if we have a 2 hour reduced view of mortals // and they are on or have been within the last 2 hours // show the reduced info else if ( GAMESETTING3(GAMESET3_MORTLASTON_REDUCED_TO2HOURS_ON_MORTS) && ( node->off[newindex]> current_time-7200 || IS_SET(node->flags, LASTON_ONLINE) ) ) { sprintf ( buf, "%-12s is currently online or has been within the last 2 hours.\r\n", node->name); } // they are currently online else if ( IS_SET(node->flags, LASTON_ONLINE) ){ sprintf ( buf, "%-12s is currently online.\r\n", node->name); } // they aren't online else { sprintf ( buf, "%-12s laston %s ago.\r\n", node->name, timediff(node->off[newindex] , current_time)); } } if (!add_buf( output, buf)){ buffer_overflow=true; }else{ displaycounter++; } } } // tell mortal that they couldn't find anyone with that name if (displaycounter==0) ch->println("Noone found with that name."); if (buffer_overflow){ ch->println("Unable to display all laston data, due to the amount requested."); } ch->sendpage(buf_string(output)); free_buf(output); return; } /**************************************************************************/ void do_councillist( char_data *ch, char *argument ) { laston_data *node; BUFFER *output; char buf[MSL]; int count=0; char arg[MIL]; argument = one_argument( argument, arg ); output = new_buf(); sprintf( buf,"`?`#`^%s`x", makef_titlebar("COUNCIL LIST`^")); add_buf( output, buf); for (node= laston_list; node; node=node->next) { if (node->level[node->index]<LEVEL_IMMORTAL && node->trust<LEVEL_IMMORTAL) continue; if (node->level[node->index]>=ADMIN || node->trust>=ADMIN) continue; sprintf( buf, "`%c %-13s `G-`Y %s`x\r\n", node->council?'W':'x', node->name, node->council?flag_string( council_flags, node->council):"`cnone"); if (!is_name( arg, buf)){ continue; } add_buf( output, buf ); count++; } sprintf( buf, "%d immortal record%s displayed.\r\n", count, count==1?"":"s"); add_buf( output, buf ); ch->sendpage(buf_string(output)); free_buf(output); } /**************************************************************************/ void do_lastoncouncil( char_data *ch, char *argument ) { laston_data *node; BUFFER *output; char buf[MSL]; int count=0; if(IS_NULLSTR(argument)){ output = new_buf(); add_buf( output, "name. [`Mlevel, `Btrust, `Rsecurity`x]- councils\r\n"); for (node= laston_list; node; node=node->next) { if((node->level[node->index]<LEVEL_IMMORTAL && node->trust<LEVEL_IMMORTAL) || node->deleted_date){ continue; } sprintf( buf, "`%c%-13s `S[`M%3d`S,`%c%3d`S,`R%d`S]`G- `Y%s`x\r\n", node->council?'W':'x', node->name, node->level[node->index], node->level[node->index]<node->trust?'C':'B', node->trust, node->security, node->council?flag_string( council_flags, node->council):"`cnone"); add_buf( output, buf ); count++; } sprintf( buf, "%d immortal record%s displayed.\r\n", count, count==1?"":"s"); add_buf( output, buf ); ch->sendpage(buf_string(output)); free_buf(output); }else{ // modify a councils settings on a player int council; char name[MIL]; // split and check the parameters argument=one_argument(argument, name); council = flag_lookup(argument,council_flags); if ( council == NO_FLAG) { ch->printlnf("'%s' is not a valid council.",argument); ch->println("syntax: lastoncouncil - shows the council info for imms"); ch->println("syntax: lastoncouncil <immname> <council> - toggles the council flag for immname"); ch->printlnf(" Valid councils are: %s", flag_string( council_flags, -1)); return; } // find the player for (node= laston_list; node; node=node->next) { // immortals only if (node->level[node->index]<LEVEL_IMMORTAL && node->trust<LEVEL_IMMORTAL) continue; if(!str_cmp(name,node->name)){ TOGGLE_BIT( node->council, council); ch->printlnf("Council toggled on %s.", node->name ); ch->printlnf("now are: %s", flag_string( council_flags, node->council )); // update the player's council if they are online { char_data *wch; for ( wch = player_list; wch; wch = wch->next_player ) { // must have an exactly matching name if (str_cmp(name, wch->name)) continue; // corruption check if(wch->id!=node->id){ ch->println("do_lastoncouncil(): BUG!!! victim->id!=node->id"); bugf("do_lastoncouncil(): BUG!!! victim->id!=node->id, name=%s\r\n", wch->name); }else{ wch->pcdata->council=node->council; wch->println("`?YOUR COUNCILS HAVE BEEN UPDATED!!!`x"); wch->println("`?YOUR COUNCILS HAVE BEEN UPDATED!!!`x"); wch->println("`?YOUR COUNCILS HAVE BEEN UPDATED!!!`x"); wch->printlnf("They are now: %s", flag_string( council_flags, wch->pcdata->council )); } } } return; } } ch->printlnf("Couldn't find any immortal character called '%s'", name); ch->println("syntax: lastoncouncil - shows the council info for imms"); ch->println("syntax: lastoncouncil <immname> <council> - toggles the council flag for immname"); ch->printlnf(" Valid councils are: %s", flag_string( council_flags, -1)); } } /**************************************************************************/ int wild_match(register unsigned char *m, register unsigned char *n); /**************************************************************************/ // return false on a match bool do_host_filter(laston_data *node, char* host_filter_substring) { int i; for (i=0; i<LASZ;i++) { if(IS_NULLSTR(node->host[i])) continue; // check the hostname if (wild_match((unsigned char*)host_filter_substring, (unsigned char*)node->host[i]) || !str_infix(host_filter_substring,node->host[i])) { return false; } // check the ip if (wild_match((unsigned char*)host_filter_substring, (unsigned char*)node->ip[i]) || !str_infix(host_filter_substring,node->ip[i])) { return false; } } return true; } /**************************************************************************** * do_laston_level_one_pwipe - written by Kalahn - Sept 1997 * * - wipes all level 1 pfiles older than 1 week old * ***************************************************************************/ void do_laston_level_one_pwipe(char_data *ch) { laston_data *node; laston_data *node_next; char buf[MSL]; int ni; int count=0; for (node= laston_list; node; node=node_next) { node_next=node->next; ni= node->index; if (node->level[ni]==1 && !node->deleted_date && ((node->off[ni]+(60*60* 24 *7)) < current_time )) { count++; ch->printlnf("%3d) LASTON - Deleting old newbie file %s ", count, node->name); // find the pfile and remove it PFILE_TYPE pt=find_pfiletype(node->name); if(pt==PFILE_NONE){ ch->printlnf("ERROR: a pfile for %s wasnt found!", node->name); logf("do_laston_level_one_pwipe(): ERROR - a pfile for %s wasnt found!", node->name); continue; } if(pt==PFILE_MULTIPLE){ ch->printlnf("ERROR: Multiple pfiles for %s were found!", node->name); logf("do_laston_level_one_pwipe(): ERROR - Multiple pfiles for %s were found!", node->name); continue; } sprintf( buf, pfilename(node->name, pt)); logf("do_laston_level_one_pwipe():[%3d] removing level 1 pfile %s from %s", count, node->name, buf); unlink(buf); laston_id_delete(node->id); // remove them from the laston list } } // next node in list } /***************************************************************************/ void show_immortal_laston_help( char_data *ch) { ch->printf("LASTON: Immortal options:\r\n" " -? - display this help\r\n" " -a - all laston records\r\n" " -b - brief format\r\n" " -c - display class in short listing\r\n" " -clan=<clan_name> - for members of a specific clan\r\n" " -clan=all - show all players in a clan\r\n" " -class=<class_name> - for players of a specific class\r\n" " -d - show deleted players.\r\n"); ch->println(" -l=<id> - lower ID"); ch->println(" -m=<id> - max ID"); if(IS_TRUSTED(ch,ADMIN-1)){ ch->println(" -e - display players email address, if we know it."); ch->println(" -e=email_filter - display all players that match the email filter."); ch->println(" -ip - show ip address as well as hostname"); } ch->println( " -f - full logins info on players (all recorded logins)\r\n" " -i - immortal/trusted characters only\r\n" " -irc - player has used irc\r\n" " -n - noble characters only\r\n" " -o - olc builder\r\n" " -r - race" " -race=<race_name> - for players of a specific race\r\n" " -t - times, instead of time differences\r\n" " -w - wide format\r\n" " -x - number entries\r\n" "====- restrict query by level -====\r\n" " <upperlevel - less than upperlevel\r\n" " >lowerlevel - greater than lowerlevel\r\n" " (e.g. laston >10 <20)"); if (IS_TRUSTED(ch,GUARDIAN)){ ch->println(" -h=<host_mask_filter> (search on their login host)."); } if (IS_TRUSTED(ch,IMPLEMENTOR)){ ch->println(" -z!!! - wipe all level 1 pfiles older than one week old."); } return; } /**************************************************************************** * laston_immortal - written by Kalahn - Sept 1997 * * - process immortal laston request * ***************************************************************************/ void laston_immortal( char_data *ch, char *argument ) { extern time_t boot_time; BUFFER *output; laston_data *node= NULL; char buf[MSL]; char working_arg[MIL]; char buf2[MSL]; char buf3[MIL]; char host_filter_substring[MIL]; char email_filter_substring[MIL]; char *parse=NULL; sh_int newindex=0, ntotal, displaycounter, linenum; int tempindex; bool buffer_overflow=false; int count; int greater_than_level=0; int less_than_level=MAX_LEVEL+2; char name_prefix[MIL]; bool laston_summary=true; bool laston_summary_specified=false; // default parameters bool laston_show_first_x=true; int laston_show_first_x_amount=ch->lines-4; /* default to one page */ bool laston_email=false; bool laston_email_filter= false; bool laston_imm_only= false; bool laston_host_filter= false; bool laston_show_deleted=false; bool laston_wide=false; // show the seconds online, wide time, and ip bool laston_show_ip=false; // show the ip address bool laston_show_race= false; bool laston_show_class= false; bool laston_show_times=false; bool laston_clan_filter= false; bool laston_number_entries= false; bool laston_show_allclans_only= false; bool laston_olc_builder= false; bool laston_irc_only=false; bool laston_no_args; short laston_class_filter=-1; short laston_race_filter=-1; bool laston_noble_only= false; CClanType *clan_filter=NULL; // filter on creation id's time_t laston_lower_id_value=0; bool laston_lower_id= false; time_t laston_max_id_value=0; bool laston_max_id= false; if (laston_show_first_x_amount<1){ laston_show_first_x_amount=25; } name_prefix[0]='\0'; if (IS_NULLSTR(argument)){ laston_no_args = true; }else{ laston_no_args = false; } // parse all parameters for (;;) { argument = one_argument( argument, working_arg ); if (working_arg[0] == 0) break; switch (working_arg[0]) { case '>': parse = &working_arg[0]; parse++; if (is_number(parse)) { greater_than_level = atoi(parse); } else ch->printlnf("Invalid parameter '%s' (should be numeric)", working_arg); break; case '<': parse = &working_arg[0]; parse++; if (is_number(parse)) { less_than_level = atoi(parse); } else ch->printlnf("Invalid parameter '%s' (should be numeric)", working_arg); break; case '-': parse = &working_arg[0]; parse++; switch (parse[0]) { case '?': show_immortal_laston_help(ch); return; break; case '!': GIOSAVE_LIST(laston_list, laston_data, LASTON_BACKFILE, true); ch->printlnf("laston data saved to %s", LASTON_BACKFILE); logf("laston data manually saved by %s to %s\r\n", ch->name, LASTON_BACKFILE); return; break; case 'a': laston_show_first_x= false; break; case 'b': laston_summary= true; laston_summary_specified=true; break; case 'c': if (parse[1]=='\0') // show classes in brief search { laston_show_class=true; break; }else if (!str_prefix("clan=", parse)){ // support -clan= clan searches if (laston_clan_filter) { ch->println("You can't filter 2 clans at the same time."); } parse+=str_len("clan="); if (!str_cmp(parse, "all")) { laston_show_allclans_only= true; }else{ // do a specific clan filter clan_filter= clan_nlookup(parse); if(!clan_filter){ ch->printlnf("Laston -clan= filter error: No such clan '%s' exists.",parse); return; } } laston_clan_filter= true; }else if (!str_prefix("class=", parse)){ // support -class= class searches if (laston_class_filter>-1) { ch->println("You can't filter 2 classes at the same time."); } parse+=str_len("class="); laston_class_filter=class_lookup(parse); if(laston_class_filter<0){ ch->printlnf("Laston -class= filter error: No such class '%s' exists.",parse); return; } }else{ ch->printlnf("LASTON SYNTAX ERROR: Unrecognised option '-%s'",parse); ch->printf("To do a clan search use `=C-clan=`S<clanname>`x for a specfic clan\r\n" " or `=C-clan=all`x for all clans.\r\n"); ch->println("To do a class search use `=C-class=`S<classname>`x for a specfic class"); return; } break; case 'd': laston_show_deleted=true; break; case 'e': if (IS_TRUSTED(ch,ADMIN-1)) { parse++; if (parse[0]!='='){ if(parse[0]!='\0'){ ch->println("LASTON SYNTAX ERROR: incorrect email filter syntax! " "(Should be like -e=someone@somewhere.com or -e=*@*aol.net, or just -e to show all chars with emails)"); return; }else{ laston_email= true; } }else{ // an email search if (laston_email_filter) { ch->println("You can't filter 2 email addresses at the same time."); return; } parse++; strcpy(email_filter_substring,parse); laston_email_filter= true; laston_email= true; } } break; case 'f': laston_summary= false; laston_summary_specified=true; break; case 'h': if (IS_TRUSTED(ch,GUARDIAN)) { laston_show_first_x= false; parse++; if (parse[0]!='=') { ch->println("LASTON SYNTAX ERROR: incorrect host filter syntax! " "(Should be like -h=ipx.com or -h=*cust??.*col*.uu.net)"); return; } if (laston_host_filter) { ch->println("You can't filter 2 hosts at the same time."); } parse++; strcpy(host_filter_substring,parse); laston_host_filter= true; } break; case 'i': if (parse[1]=='\0') // show classes in brief search { laston_imm_only= true; laston_show_first_x= false; break; }else if (!str_cmp("irc", parse)){ laston_irc_only=true; break; }else if (!str_cmp("ip", parse)){ laston_show_ip= true; break; }else{ ch->printlnf("LASTON SYNTAX ERROR: Unrecognised option '-%s'",parse); ch->wrapln("To do search for irc players use `=C-irc`x, " "use `=C-ip`x to show ip addresses and `=C-i`x to " "show only imms."); return; } break; case 'l': parse++; if (parse[0]!='=') { ch->println("LASTON SYNTAX ERROR: incorrect lower ID filter syntax! " "(Should be like -l=957420642)"); ch->println("The ID relates to when they created - seconds past 1Jan1970 - see the memory command)"); return; } if (laston_lower_id) { ch->println("You can't have two lower filters"); return; } parse++; if(!is_number(parse)){ ch->println("LASTON SYNTAX ERROR: incorrect lower ID filter number! " "(Should be like -l=957420642)\r\n" "The ID relates to when they created - seconds past 1Jan1970 - see the memory command)"); return; } laston_lower_id_value=(time_t)atoi(parse); laston_lower_id= true; break; case 'm': parse++; if (parse[0]!='=') { ch->println("LASTON SYNTAX ERROR: incorrect max ID filter syntax! " "(Should be like -m=987420642)\r\n" "The ID relates to when they created - seconds past 1Jan1970 - see the memory command)"); return; } if (laston_max_id) { ch->println("You can't have two max filters"); return; } parse++; if(!is_number(parse)){ ch->println("LASTON SYNTAX ERROR: incorrect max ID filter number! " "(Should be like -l=987420642)\r\n" "The ID relates to when they created - seconds past 1Jan1970 - see the memory command)"); return; } laston_max_id_value=(time_t)atoi(parse); laston_max_id= true; break; case 'n': laston_noble_only= true; break; case 'o': laston_summary= true; laston_olc_builder= true; break; case 'r': if (parse[1]=='\0') // show races in brief search { laston_show_race=true; break; }else if (!str_prefix("race=", parse)){ // support -race= race searches if (laston_race_filter>-1) { ch->println("You can't filter 2 races at the same time."); } parse+=str_len("race="); laston_race_filter=pcrace_lookup(parse); if(laston_race_filter<0){ ch->printlnf("Laston -race= filter error: No such pc race '%s' exists.",parse); return; } }else{ ch->printlnf("LASTON SYNTAX ERROR: Unrecognised option '-%s'",parse); ch->println("To do a race search use `=C-race=`S<racename>`x for a specfic race"); return; } break; case 't': laston_show_times=true; break; case 'w': laston_wide=true; laston_show_ip=true; break; case 'x': laston_number_entries= true; break; case 'z': if (IS_TRUSTED(ch,IMPLEMENTOR)) { if (parse[1]=='!' && parse[2]=='!' && parse[3]=='!') { ch->println("LASTON LEVEL 1 - 1 week old pfile wipe!!!"); do_laston_level_one_pwipe(ch); } return; } break; } break; case '?': show_immortal_laston_help(ch); return; break; default: strcpy (name_prefix, working_arg); laston_show_first_x= false; break; } if(IS_SET(ch->dyn,DYN_IMMLASTON)){ if(working_arg[0]=='`'){ last_resave=laston_next_save; return; } } } // if there is no name prefix default to brief if (!laston_summary_specified) { if (IS_NULLSTR(name_prefix)){ laston_summary= true; }else{ laston_summary= false; laston_show_class=true; laston_show_race=true; } } // Display a message telling how current the data is ch->printlnf("%s has been up for %s", MUD_NAME, timediff(boot_time, current_time)); ch->printlnf("The current time is %sLaston records date back %s.", (char *) ctime( ¤t_time ), timediff(laston_since, current_time)); // setup a buffer for info to be displayed output = new_buf(); displaycounter=0; // counter of amount of matches displayed linenum= 0; count=0; char clanname_buffer[MIL]; if (laston_no_args){ ch->printlnf("No filter parameters specified, showing the last %d logins.", laston_show_first_x_amount); }else{ sprintf(buf,"Laston records being filtered with the following settings:\r\n"); add_buf( output, buf ); if (laston_show_first_x) { sprintf(buf,"- Show the most recent %d matching characters.\r\n", laston_show_first_x_amount); add_buf( output, buf ); linenum++; }else{ sprintf(buf,"- Search thru and display all the matching laston records.\r\n"); add_buf( output, buf ); linenum++; } if (name_prefix[0] != 0) { sprintf(buf,"- Where the characters name starts with '%s'.\r\n", name_prefix); add_buf( output, buf ); linenum++; } if (greater_than_level) { sprintf(buf,"- Characters with level greater than %d.\r\n", greater_than_level); add_buf( output, buf ); linenum++; } if (less_than_level<MAX_LEVEL+2) { sprintf(buf,"- Characters with level less than %d.\r\n", less_than_level); add_buf( output, buf ); linenum++; } if(laston_class_filter>-1){ add_buf( output, "- Where characters class is "); add_buf( output, class_table[laston_class_filter].name); add_buf( output, "\r\n"); linenum++; laston_show_class=true; } if(laston_lower_id){ sprintf(buf,"- ID is greater or equal to %d.\r\n", (int)laston_lower_id_value); add_buf( output, buf ); linenum++; } if(laston_max_id){ sprintf(buf,"- ID is less than or equal to %d.\r\n", (int)laston_max_id_value); add_buf( output, buf ); linenum++; } if(laston_race_filter>-1){ add_buf( output, "- Where characters race is "); add_buf( output, race_table[laston_race_filter]->name); add_buf( output, "\r\n"); linenum++; laston_show_race=true; } if (laston_olc_builder) { add_buf( output, "- Where the characters has OLC access.\r\n"); linenum++; } if (laston_noble_only) { add_buf( output, "- Where the characters is a noble\r\n"); linenum++; } if (laston_imm_only) { sprintf(buf,"- Immortal characters only.\r\n"); add_buf( output, buf ); linenum++; } if (laston_wide) { sprintf(buf,"- Wide format.\r\n"); add_buf( output, buf ); linenum++; } if (laston_show_ip) { sprintf(buf,"- Show IP address in addition to hostname.\r\n"); add_buf( output, buf ); linenum++; } if (laston_irc_only) { sprintf(buf,"- Where character has logged on via the irc port at least once.\r\n"); add_buf( output, buf ); linenum++; } if(laston_number_entries){ add_buf( output, "- Numbering each character entry.\r\n"); linenum++; } if(laston_show_deleted){ add_buf( output, "- Showing deleted players.\r\n"); linenum++; } if(laston_host_filter){ sprintf(buf,"- Where the players login host or ip matches or contains the mask '%s'.\r\n", host_filter_substring); add_buf( output, buf ); linenum++; } if (laston_email_filter){ sprintf(buf,"- Where the players email address matches or contains the mask '%s'.\r\n", email_filter_substring); add_buf( output, buf ); linenum++; } if ( laston_clan_filter) { if (laston_show_allclans_only) { sprintf(buf,"- Where the character is a member of a clan.\r\n"); add_buf( output, buf ); linenum++; } else { sprintf(buf,"- Where the character is a member of the clan %s`x.\r\n", clan_filter->cname()); add_buf( output, buf ); linenum++; } } } sprintf(buf,"\r\n"); add_buf( output, buf ); // reset counters ntotal=0; // node total counter clanname_buffer[0]='\0'; // loop thru all laston records in linked list for (node= laston_list; node; node=node->next) { ntotal++; if (output->state == BUFFER_OVERFLOW) { buffer_overflow=true; } if (laston_show_first_x && (laston_show_first_x_amount<linenum)) continue; if (node->level[node->index]<=greater_than_level) continue; if (laston_olc_builder && node->security==0) continue; if (node->level[node->index]>=less_than_level) continue; if(laston_class_filter>-1 && laston_class_filter!=node->clss) continue; if(laston_race_filter>-1 && laston_race_filter!=node->race) continue; if(laston_lower_id && node->id<laston_lower_id_value){ continue; } if(laston_max_id && node->id>laston_max_id_value){ continue; } if(laston_irc_only && !IS_SET(node->flags, LASTON_IRC) && !IS_SET(node->flags, LASTON_HASUSEDIRC)){ continue; } if (laston_imm_only && node->level[node->index]<LEVEL_IMMORTAL && node->trust<LEVEL_IMMORTAL) continue; if (laston_noble_only && !IS_SET(node->flags, LASTON_NOBLE)) continue; if ( laston_host_filter){ if (do_host_filter(node,host_filter_substring)){ continue; } } if(node->deleted_date && !laston_show_deleted){ continue; } if ( laston_email_filter ){ if(IS_NULLSTR(node->email)){ continue; } if (!wild_match((unsigned char*)email_filter_substring, (unsigned char*)node->email) && str_infix(email_filter_substring, node->email)){ continue; } } if ( laston_clan_filter) { if (laston_show_allclans_only) { if (!node->clan) continue; } else { if (node->clan!=clan_filter) continue; } } // email only check if ( laston_email && IS_NULLSTR(node->email)){ continue; } // the name match check if (name_prefix[0] != 0 && str_prefix(name_prefix, node->name)){ continue; } if (laston_show_allclans_only){ sprintf(clanname_buffer,"%s[%d]`x ", node->clan->cwho_name(), node->clanrank); } // get the colour of the entries name char name_colour[3]; if(node->deleted_date){ strcpy(name_colour, "`S"); }else if (IS_SET(node->flags, LASTON_IRC)){ strcpy(name_colour, "`M"); }else if (IS_SET(node->flags, LASTON_HASUSEDIRC)){ strcpy(name_colour, "`g"); }else{ strcpy(name_colour, "`x"); } if (laston_summary){ // show summary list newindex= node->index; if (IS_SET(node->flags, LASTON_ONLINE)) { sprintf(buf, "%s%-12s %s %s%s[%2d.%d] %sonline for %s.%s`Y%s`x\r\n", name_colour, node->name, (laston_show_class && (node->clss>-1)?class_table[node->clss].short_name:""), (laston_show_race && (node->race>-1)?race_table[node->race]->short_name:""), (IS_TRUSTED(ch,ANGEL) && node->level[newindex]>=100?"":" "), (IS_TRUSTED(ch,ANGEL)?node->level[newindex]:0), (IS_TRUSTED(ch,ANGEL)?node->sublevel[newindex]:0), clanname_buffer, laston_wide?short_timediff(node->on[newindex] , current_time) :condensed_timediff(node->on[newindex] , current_time), (IS_TRUSTED(ch,GUARDIAN) ?(!IS_NULLSTR(node->ip[newindex]) && laston_show_ip ?FORMATF(" (%s)[%s] ", node->host[newindex], node->ip[newindex]) :FORMATF(" (%s) ", node->host[newindex])) :""), (IS_TRUSTED(ch,ADMIN-1) && laston_email && !IS_NULLSTR(node->email))?node->email:"" ); }else{ sprintf(buf, "%s%-12s %s %s%s[%2d.%d] %s%s %s ago.%s`Y%s`x\r\n", name_colour, node->name, (laston_show_class && (node->clss>-1)?class_table[node->clss].short_name:""), (laston_show_race && (node->race>-1)?race_table[node->race]->short_name:""), (IS_TRUSTED(ch,ANGEL) && node->level[newindex]>=100?"":" "), (IS_TRUSTED(ch,ANGEL)?node->level[newindex]:0), (IS_TRUSTED(ch,ANGEL)?node->sublevel[newindex]:0), clanname_buffer, node->deleted_date?"deleted":"on", laston_wide?short_timediff(node->off[newindex] , current_time) :condensed_timediff(node->off[newindex] , current_time), (IS_TRUSTED(ch,GUARDIAN) ?(!IS_NULLSTR(node->ip[newindex]) && laston_show_ip ?FORMATF(" (%s)[%s] ", node->host[newindex], node->ip[newindex]) :FORMATF(" (%s) ", node->host[newindex])) :""), (IS_TRUSTED(ch,ADMIN-1) && laston_email && !IS_NULLSTR(node->email))?node->email:"" ); } if (laston_olc_builder) { sprintf(buf3,"OLC=%d ", node->security); if (!add_buf( output, buf3 )){ buffer_overflow=true; }else{ linenum++; } } if (IS_SET(node->flags, LASTON_PERM_PKILLED)) { if (!add_buf( output, "`#`RPERMKILLED`& ")){ buffer_overflow=true; }else{ linenum++; } } // prepend the laston entry with the line counter if (laston_number_entries && !buffer_overflow) { sprintf(buf3,"`x%3d ", displaycounter+1); if (!add_buf( output, buf3 )){ buffer_overflow=true; } } // add the info to display to the page buffer if (!add_buf( output, buf )){ buffer_overflow=true; }else{ displaycounter++; linenum++; } } else // show full listing { char trust_buf[MIL]; sprintf(trust_buf,"Trust: %d, Sec: %d",node->trust, node->security); sprintf ( buf, "CHARACTER: %s%s`x %s %s %s%s- %s%s %s\r\n", name_colour, node->name, (laston_show_class && (node->clss>-1)?class_table[node->clss].short_name:""), (laston_show_race && (node->race>-1)?race_table[node->race]->short_name:""), capitalize(flag_string(sex_types, node->sex)), clanname_buffer, (IS_SET(node->flags, LASTON_ONLINE)?"": (node->deleted_date?"`Sdeleted ":"laston ")), (IS_SET(node->flags, LASTON_ONLINE)? "online":timediff(node->off[node->index] , current_time)), IS_ADMIN(ch)?trust_buf:"" ); // tack on the deleted date if(node->deleted_date){ char delbuf[MIL]; sprintf(delbuf, "Deleted: %s", ctime(&node->deleted_date)); strcat(buf, delbuf); } // prepend the laston entry with the line counter if (laston_number_entries && !buffer_overflow) { sprintf(buf3,"%3d ", displaycounter+1); if (!add_buf( output, buf3 )){ buffer_overflow=true; } } if (IS_SET(node->flags, LASTON_PERM_PKILLED)) { if (!add_buf( output, "`#`RPERMKILLED`& ")){ buffer_overflow=true; }else{ linenum++; } } // add the info to display to the page buffer if (!add_buf( output, buf )) buffer_overflow=true; else{ displaycounter++; linenum++; } // display clan info if (node->clan>0){ sprintf(buf,"`xclan: %s `xrank: %s (%d)`x\r\n", node->clan->cwho_name(), node->clan->clan_rank_title(node->clanrank), node->clanrank); if (!add_buf( output, buf )){ buffer_overflow=true; }else{ linenum++; } } sprintf ( buf, "Noble: %s Letgained: %s KnowIndex=%d, ID=%d - Created: %s ", (IS_SET(node->flags, LASTON_NOBLE)?"`#`RYES`^":"no"), (IS_SET(node->flags, LASTON_LETGAINED)?"`#`BYES`^":"no"), (int)node->know_index, (int)node->id, ctime( (time_t *) &node->id)); if (!add_buf( output, buf )) buffer_overflow=true; else{ linenum++; } if(IS_ADMIN(ch) && !IS_NULLSTR(node->email)){ sprintf ( buf, "Email: %s\r\n", node->email); if (!add_buf( output, buf )) buffer_overflow=true; else{ linenum++; } } double played_percent=0.0; time_t last_on_time; if(IS_SET(node->flags, LASTON_ONLINE)){ last_on_time=current_time; }else{ last_on_time=node->off[node->index]; } if( (last_on_time-node->id)!=0 ){// prevent divide by zero's played_percent= node->played/(double)(last_on_time-node->id); played_percent*=100; } sprintf ( buf, "Played:%d.%02d(%0.03f%%) LogoutRoom:%d Short: %s`x\r\n", (int) node->played/ 3600, ((int) (node->played /36)%100), played_percent, node->logout_room, node->short_descr); if (!add_buf( output, buf )){ buffer_overflow=true; }else{ linenum++; } // alliance/tendency if(IS_TRUSTED(ch,ANGEL)){ sprintf ( buf, "Alliance: %d Tendency: %d\r\n", node->alliance, node->tendency); if (!add_buf( output, buf )) buffer_overflow=true; else{ linenum++; } } // characters times and levels for (tempindex=node->index+LASZ; tempindex > node->index; tempindex--) { char identbuf[MIL]; newindex = tempindex % LASZ; if (node->on[newindex]==0){// display only valid records continue; } strcpy(buf2, ctime((time_t *) &node->on[newindex])); if(laston_wide){ buf2[20] = '\0'; //remove year }else{ buf2[17] = '\0'; //remove year and seconds } sprintf ( buf, " on: %s", buf2); add_buf( output, buf ); if(!IS_NULLSTR(node->ident[newindex])){ sprintf(identbuf, "(ident=%s)",node->ident[newindex]); }else{ identbuf[0]='\0'; } if (node->off[newindex]<=node->on[newindex]) { sprintf ( buf, "(lvl %d.%d/%d) online for %s %s%s\r\n", (IS_TRUSTED(ch,ANGEL)?node->level[newindex]:0), (IS_TRUSTED(ch,ANGEL)?node->sublevel[newindex]:0), (IS_TRUSTED(ch,ANGEL)?get_sublevels_for_level(node->level[newindex]):0), short_timediff(node->on[newindex] , current_time), (IS_TRUSTED(ch,GUARDIAN) ?(!IS_NULLSTR(node->ip[newindex]) && laston_show_ip ?FORMATF(" (%s)[%s] ", node->host[newindex], node->ip[newindex]) :FORMATF(" (%s) ", node->host[newindex])) :""), identbuf ); } else { if(laston_show_times){ sprintf ( buf, "[%d.%d] off %-20.20s %s%s\r\n", (IS_TRUSTED(ch,ANGEL)?node->level[newindex]:0), (IS_TRUSTED(ch,ANGEL)?node->sublevel[newindex]:0), ctime((time_t *) &node->off[newindex]), (IS_TRUSTED(ch,GUARDIAN) ?(!IS_NULLSTR(node->ip[newindex]) && laston_show_ip ?FORMATF(" (%s)[%s] ", node->host[newindex], node->ip[newindex]) :FORMATF(" (%s) ", node->host[newindex])) :""), identbuf ); }else{ sprintf ( buf, "[%d.%d] on %s %s%s\r\n", (IS_TRUSTED(ch,ANGEL)?node->level[newindex]:0), (IS_TRUSTED(ch,ANGEL)?node->sublevel[newindex]:0), short_timediff(node->on[newindex] , node->off[newindex]), (IS_TRUSTED(ch,GUARDIAN) ?(!IS_NULLSTR(node->ip[newindex]) && laston_show_ip ?FORMATF(" (%s)[%s] ", node->host[newindex], node->ip[newindex]) :FORMATF(" (%s) ", node->host[newindex])) :""), identbuf ); } } if (!add_buf( output, buf )) { buffer_overflow=true; }; } // end of loop thru a characters LASZ times if (!add_buf( output, "`x\r\n")) { buffer_overflow=true; }; } } // next node in list ch->printlnf("%d character%s total, displaying %d\r\n", ntotal, (ntotal==1?"":"s"), displaycounter); if(name_prefix[0] != '\0') { sprintf( buf,"\r\n%d character%s total, displayed %d\r\n", ntotal, (ntotal==1?"":"s"), displaycounter); if (!add_buf( output, buf )) buffer_overflow= true; } if(buffer_overflow){ ch->println("Unable to display all laston data, due to the amount requested."); } ch->sendpage(buf_string(output)); free_buf(output); return; } /**************************************************************************** * do_laston_remove - written by Kalahn - Jan 1998 * * - removes the last occurance of a name in the last database * * - doesn't delete the pfile though * ***************************************************************************/ void do_lastonremove( char_data *ch, char *argument ) { char pname[MIL]; laston_data *node; int count; if (IS_NULLSTR(argument)) { ch->println("Syntax: lastonremove <playername>"); ch->println(" note: if there are duplicates, it will remove the tail entry."); } argument = one_argument( argument, pname ); // loop thru all laston records in linked list count=0; // count the number of matching occurances for (node= laston_list; node; node=node->next){ if(!str_cmp(pname, node->name)){ count++; } }; if(count>0){ int removenum=0; for (node= laston_list; node; node=node->next){ if(!str_cmp(pname, node->name)){ if(++removenum==count){ if (node) { ch->printlnf("Removed %s from laston database, there were %d total found.", node->name, count); laston_id_delete(node->id); // remove them from the laston list }; break; }; } }; }else{ ch->printlnf("No name matching '%s' was found to remove.", pname); } return; } /**************************************************************************** * do_laston - written by Kalahn - July 1997 * * - selects how to process the laston request (immortal vs mortal) * ***************************************************************************/ void do_laston( char_data *ch, char *argument ) { // command not valid for npcs if ( IS_NPC(ch) ){ ch->println("Players only"); return; } if(HAS_CONFIG2(ch, CONFIG2_HIGHIMMORTAL_LASTON_ACCESS)){ chImmortal->level=ch->level; ch->level=ABSOLUTE_MAX_LEVEL; } if(IS_SET(ch->dyn,DYN_IMMLASTON)){ chImmortal->level=ch->level; ch->level=ABSOLUTE_MAX_LEVEL; } if(!GAMESETTING2(GAMESET2_USE_LASTON_IMM_VALUE)){ if (IS_IMMORTAL(ch)){ laston_immortal(ch, argument); }else{ laston_mortal(ch, argument); } }else{ if (ch->level>=game_settings->laston_level_for_immortal_version){ laston_immortal(ch, argument); }else{ laston_mortal(ch, argument); } } if(IS_SET(ch->dyn,DYN_IMMLASTON)){ ch->level=chImmortal->level; } } /*************************************************************************** * laston_save - written by Kalahn - July 1997 * * - saves all players * * - called by laston_login and laston_logout if we haven't saved * * for a the LASTON_SAVE_INTERVAL (in seconds) * * - also called from in act_wiz.c by do_reboot and do_save, * * maintence_saves() in update.c * ***************************************************************************/ void laston_save(char_data *) { laston_data *node; if (LASTON_SAVE_DATA){ // update times on characters for (node= laston_list; node; node=node->next){ if (IS_SET(node->flags, LASTON_ONLINE)){ node->off[node->index] = current_time; // record when the data is uptil } } logf("===Saving in laston records to %s.", LASTON_FILE); GIOSAVE_LIST(laston_list, laston_data, LASTON_FILE, true); logf("Laston save completed"); }else{ logf("Laston save disabled - records not saved."); } // record next autosave time laston_next_save = current_time + LASTON_SAVE_INTERVAL; } /*************************************************************************** * laston_load - written by Kalahn - July 1997 * - reads in all laston records ***************************************************************************/ void laston_load() // saves the laston data { laston_data *node, *prev; laston_list = NULL; int count=0; log_string ("===Reading in laston records."); GIOLOAD_LIST(laston_list, laston_data, LASTON_FILE); // now mark as offline and link the previous node pointers laston_since = current_time; prev=NULL; for(node=laston_list; node; node=node->next) { REMOVE_BIT(node->flags, LASTON_ONLINE); // nolonger online node->in_list = true; // mark as a member of the list node->prev= prev; prev = node; count++; // figure out when the laston data relates back to if(node->on[node->index]>100 && node->on[node->index]<laston_since){ laston_since = node->on[node->index]; // a rough estimate } } logf("%d laston record%s %s been read.", count, count==1?"":"s", count==1?"has":"have"); // now remove player records of those long since deleted laston_data *next_node; for(node=laston_list; node; node=next_node){ next_node=node->next; if(!node->deleted_date){ continue; } int level=node->level[node->index]; int days_to_keep=0; if(level<5){ days_to_keep=game_settings->laston_remove_deleted_players_0_4; }else if(level<35){ days_to_keep=game_settings->laston_remove_deleted_players_5_34; }else if(level<65){ days_to_keep=game_settings->laston_remove_deleted_players_35_64; }else if(level<92){ days_to_keep=game_settings->laston_remove_deleted_players_65_91; }else{ days_to_keep=game_settings->laston_remove_deleted_players_92; } if( (node->deleted_date + (days_to_keep* 60*60*24))<current_time){ logf("Removing old laston record of deleted player '%s'<%d>", node->name, level); laston_id_delete(node->id); } } return; } /*************************************************************************** * lastonreload - reloads the laston list from disk * * - allows manual editing of laston file. * * - calls laston_load * ***************************************************************************/ void do_lastonreload(char_data *ch, char *) { ch->println("Reloading laston records."); laston_load(); ch->println("Laston records have been reloaded."); } /**************************************************************************/ void add_top_roleplayers(laston_data *pnode) { laston_data *node, *prev; if (!laston_rpers_list) { laston_rpers_list=pnode; return; } // go down the list till we find the place they are less than prev=NULL; for (node= laston_rpers_list; node; node=node->next_rper) { if (node->rps < pnode->rps){ if (!prev) { pnode->next_rper=laston_rpers_list; laston_rpers_list=pnode; return; } pnode->next_rper = node; prev->next_rper =pnode; return; } prev=node; } pnode->next_rper = node; prev->next_rper =pnode; } /**************************************************************************/ void resort_top_roleplayers() { laston_data *node; log_string("resorting top roleplayers list..."); // first wipe the old settings laston_rpers_list=NULL; for (node= laston_list; node; node=node->next) { node->next_rper=NULL; } // now readd to the list if their rps is over 10000 for (node= laston_list; node; node=node->next) { if (node->rps>=10000 // nonimms on in the last 8 weeks && (node->level[node->index]<LEVEL_IMMORTAL) && node->off[node->index]> current_time-(60*60*24*7*8)) add_top_roleplayers(node); } log_string("resort complete."); } /**************************************************************************/ void do_toprp(char_data *ch, char *) { laston_data *node; BUFFER *output; char buf[MSL]; int col=0; int line=3; int lines_to_show=ch->lines; int count=1; if (lines_to_show==0) lines_to_show=9999; output= new_buf(); sprintf( buf,"`?%s`x\r\n", makef_titlebar("HIGHEST RPS SCORES")); add_buf(output,buf); for (node= laston_rpers_list; node; node=node->next_rper) { // sprintf(buf, " %-13s%6d ", node->name, node->rps); sprintf(buf, "`W%3d `w%-13s%6d ", count, node->name, node->rps); add_buf(output,buf); if (++col%3==0) { add_buf(output,"\r\n"); if (++line>lines_to_show) break; } count++; } if (col%3!=0) add_buf(output,"\r\n"); ch->sendpage(buf_string(output)); free_buf(output); } /**************************************************************************/ int count_active_players(void) { laston_data *node; int active=0; for (node= laston_list; node; node=node->next) { if (node->level[node->index]<6) continue; if (node->level[node->index]>LEVEL_IMMORTAL) continue; if (node->off[node->index]+ (60*60*24*7)<current_time) continue; if(node->deleted_date) continue; if(!race_table[node->race]->creation_selectable()) continue; active++; } return active; } /**************************************************************************/ // laston accuracy reduced for those that abuse laston info // Written by Kalahn at the request of Rathern void do_reducelaston( char_data *ch, char *argument ) { char arg[MIL], buf[MSL]; char_data *victim; // can only be used by imms if ( !IS_IMMORTAL(ch) ) { do_huh(ch,""); return; } one_argument( argument, arg ); if ( arg[0] == '\0' ){ ch->println("Reduce laston accuracy on whom?"); return; } if ( ( victim = get_whovis_player_world( ch, arg ) ) == NULL ) { ch->println("They aren't here."); return; } // can't reduce laston on high level imms than yourself if ( get_trust( victim ) >= LEVEL_IMMORTAL && get_trust( victim ) >= get_trust( ch ) ) { ch->println("You failed."); return; } if ( IS_SET(victim->comm, COMM_REDUCED_LASTON) ) { REMOVE_BIT(victim->comm, COMM_REDUCED_LASTON); logf("reducelaston removed on %s by %s", victim->name, ch->name); victim->println("The gods have restored your ability to get detailed info from laston."); ch->println("Reduced laston removed."); sprintf(buf,"$N regives full laston details to %s",victim->name); wiznet(buf,ch,NULL,WIZ_PENALTIES,WIZ_SECURE,0); } else { SET_BIT(victim->comm, COMM_REDUCED_LASTON); logf("reduced laston set on %s by %s", victim->name, ch->name); victim->println("The gods have revoked your ability to get detailed info on imms from laston."); ch->printf("%s can no longer tell with laston if an imm has been on within the last 2 days.", victim->name); sprintf(buf,"$N reduces %s's ability to get laston login times more accurate that 2 days regarding imms.",victim->name); wiznet(buf,ch,NULL,WIZ_PENALTIES,WIZ_SECURE,0); } return; } /**************************************************************************/ // mud client statistics code, Kal, Feb 2002 char *laston_generate_mud_client_stats() { char *client_version="-"; char buf[MSL]; char num[MSL]; int val; bool buffer_full; name_linkedlist_type *plist, *plist_next; // used for going thru the list etc name_linkedlist_type *list=NULL; // all players name_linkedlist_type *alist=NULL; // active players name_linkedlist_type *clist=NULL; // condensed list name_linkedlist_type *slist=NULL; // sort list laston_data *node; int total=0; int atotal=0; int ctotal=0; static char result[32000]; char all_buf[16000]; char active_buf[8000]; char condensed_buf[8000]; // loop thru the list getting all mxp client versions for (node= laston_list; node; node=node->next) { if(!IS_NULLSTR(node->mxp_client_version)){ client_version=node->mxp_client_version; }else if(!IS_NULLSTR(node->terminal_type)){ client_version=FORMATF(" termtype=%s", node->terminal_type); }else{ client_version=" unknown"; } total++; addlist(&list, client_version, 0, false, false); if (node->level[node->index]<6) continue; if (node->level[node->index]>LEVEL_IMMORTAL) continue; if (node->off[node->index]+ (60*60*24*7)<current_time) continue; if(node->deleted_date) continue; if(!race_table[node->race]->creation_selectable()) continue; addlist(&alist, client_version, 0, false, false); // condensed list sprintf(buf, "%d #%s%s", str_len(client_version), client_version, node->host[node->index]); client_version=buf; addlist(&clist, client_version, 0, false, false); atotal++; } // sort the all player total list by quantity of clients, highest first for(plist=list;plist; plist=plist_next){ plist_next=plist->next; addlist(&slist, FORMATF("%5d=%s", plist->count, plist->name), 0, true, true); free_string(plist->name); delete plist; } sprintf(all_buf,"-=all player total:%d\r\n", total); buffer_full=false; for(plist=slist;plist; plist=plist_next){ plist_next=plist->next; if(!buffer_full){ if(str_len(all_buf)>15350){ buffer_full=true; strcat(all_buf, " -1= buffer too full to display remaining text"); }else{ // we assume plist->name is less than 600 bytes in length // because the code limits the mxp version string to 512 bytes strcat(all_buf,plist->name); strcat(all_buf,"\n\r"); } } free_string(plist->name); delete plist; } slist=NULL; // sort the active player list by quantity of clients, highest first for(plist=alist;plist; plist=plist_next){ plist_next=plist->next; addlist(&slist, FORMATF("%5d=%s", plist->count, plist->name), 0, true, true); free_string(plist->name); delete plist; } sprintf(active_buf,"-=active player total:%d\r\n", atotal); buffer_full=false; for(plist=slist;plist; plist=plist_next){ plist_next=plist->next; if(!buffer_full){ if(str_len(active_buf)>7350){ buffer_full=true; strcat(active_buf, " -1= buffer too full to display remaining text"); }else{ // we assume plist->name is less than 600 bytes in length // because the code limits the mxp version string to 512 bytes strcat(active_buf,plist->name); strcat(active_buf,"\n\r"); } } free_string(plist->name); delete plist; } slist=NULL; // loop thru the results, generating a condensed version of the list list=NULL; ctotal=0; for(plist=clist;plist; plist=plist_next){ plist_next=plist->next; client_version=one_argument(plist->name, num); val=atoi(num); strcpy(buf,client_version+1); buf[val]='\0'; addlist(&list, buf, 0, false, false); ctotal++; free_string(plist->name); delete plist; } // sort the condensed list by quantity of clients, highest first for(plist=list;plist; plist=plist_next){ plist_next=plist->next; addlist(&slist, FORMATF("%5d=%s", plist->count, plist->name), 0, true, true); free_string(plist->name); delete plist; } sprintf(condensed_buf,"-=condensed player total:%d\r\n", ctotal); buffer_full=false; for(plist=slist;plist; plist=plist_next){ plist_next=plist->next; if(!buffer_full){ if(str_len(condensed_buf)>7350){ buffer_full=true; strcat(condensed_buf, " -1= buffer too full to display remaining text"); }else{ // we assume plist->name is less than 600 bytes in length // because the code limits the mxp version string to 512 bytes strcat(condensed_buf,plist->name); strcat(condensed_buf,"\n\r"); } } free_string(plist->name); delete plist; } slist=NULL; strcpy(result,condensed_buf); strcat(result, "\r\n"); strcat(result,active_buf); strcat(result, "\r\n"); strcat(result,all_buf); strcat(result, "=-\r\n"); return result; } /**************************************************************************** * do_lastonstats - written by Kalahn - Sept 1998 * ***************************************************************************/ void do_lastonstats( char_data *ch, char *argument) { int i, class_count[MAX_CLASS]; int race_count[MAX_RACE]; int bit_table[32]; int total; int colcount=0; int alignment_matrix[8][8]; memset(alignment_matrix, 0, sizeof(alignment_matrix)); laston_data *node; /* * Display a message telling how current the data is */ ch->printlnf("%s has been up for %s", MUD_NAME, timediff(boot_time, current_time)); ch->printlnf("The current time is %sLaston records date back %s.", (char *) ctime( ¤t_time ), timediff(laston_since, current_time)); // reset counters total=0; for (i=0; i<MAX_CLASS; i++){ class_count[i]=0; } for (i=0; i<MAX_RACE; i++){ race_count[i]=0; } for (i=0; i<32; i++){ bit_table[i]=0; } int gender[3]; for (i=0; i<3; i++){ gender[i]=0; } // loop thru all character records in linked list for (node= laston_list; node; node=node->next) { if (node->level[node->index]<6) continue; if (node->level[node->index]>LEVEL_IMMORTAL) continue; if (node->off[node->index]+ (60*60*24*7)<current_time) // active only players continue; if(node->deleted_date) continue; if(!race_table[node->race]->creation_selectable()) continue; class_count[node->clss]++; race_count[node->race]++; total++; for (int bit_index=0; bit_index<32; bit_index++) { int bit_value = 1<<bit_index; if (!IS_SET(bit_value, node->flags)) continue; bit_table[bit_index]++; } gender[URANGE(0, node->sex,3)]++; // record alignment matrix details alignment_matrix[node->alliance+3][node->tendency+3]++; alignment_matrix[7][node->tendency+3]++; alignment_matrix[node->alliance+3][7]++; } if (total<1){ ch->printlnf("There are no active players. (>5 <%d)", LEVEL_IMMORTAL); return; } ch->print("`?`#"); // get the random colour if(!str_cmp(argument,"class")|| IS_NULLSTR(argument)) { colcount=0; ch->titlebar("LASTON CLASS STATS"); for (i=0; !IS_NULLSTR(class_table[i].name) && i<MAX_CLASS; i++) { if (class_table[i].creation_selectable==false) continue; ch->printf("`x %-14s %3d (%5.1f%%)", capitalize(class_table[i].name), class_count[i], ((float)(class_count[i]*100)/(float)total)); if(++colcount%2==0){ ch->println("`x"); }else{ ch->print(" "); }; } if(colcount%2==1){ ch->println("`x"); }; } if(!str_cmp(argument,"race") || IS_NULLSTR(argument)) { colcount=0; ch->titlebar("LASTON RACE STATS"); for (i=1; race_table[i]; i++) { if(!race_table[i]->creation_selectable()) continue; ch->printf("`x %-14s %3d (%5.1f%%)", capitalize(race_table[i]->name), race_count[i], ((float)(race_count[i]*100)/(float)total)); if(++colcount%2==0){ ch->println("`x"); }else{ ch->print(" "); }; } if(colcount%2==1){ ch->println("`x"); }; } if(IS_NULLSTR(argument) && IS_ADMIN(ch)) { colcount=0; ch->titlebar("LASTON FLAG STATS"); for (int bit_index=0; bit_index<32; bit_index++) { if (bit_table[bit_index]==0) continue; int bit_value = 1<<bit_index; ch->printf("`x %-14s %3d (%5.1f%%)", capitalize(flag_string(laston_flags, bit_value)), bit_table[bit_index], ((float)(bit_table[bit_index]*100)/(float)total)); if(++colcount%2==0){ ch->println("`x"); }else{ ch->print(" "); }; } if(++colcount%2==0){ ch->println("`x"); }; ch->titlebar("LASTON GENDER STATS"); colcount=0; for(i=0; i<3; i++) { ch->printf("`x %-14s %3d (%5.1f%%)", capitalize(flag_string(sex_types, i)), gender[i], ((float)(gender[i]*100)/(float)total)); if(++colcount%2==0){ ch->println("`x"); }else{ ch->print(" "); }; } if(++colcount%2==0){ ch->println("`x"); }; } // Alignment Matrix if(!str_cmp(argument,"align") || IS_NULLSTR(argument)) { char buf[MIL], grid[MSL]; colcount=0; ch->titlebar("LASTON ALIGNMENT MATRIX"); int ali, ten; ch->printf(" `^TENDENCY: `YLawful <----> Neutral <----> Chaotic\r\n"); ch->printf(" `S+===`Y3"); for(ten=5; ten>=3; ten--){ ch->printf( "`S====`Y%-d", ten-3); } for(ten=2; ten>=0; ten--){ ch->printf( "`S===`Y%d", ten-3); } ch->println("`S==`gTotal`S=="); grid[0]='\0'; for(ali=6; ali>=0; ali--){ strcat(grid, " "); switch (ali){ case 6: strcat(grid, "`^ ALLIANCE:`B Good ");break; case 5: strcat(grid, "`B ");break; case 4: strcat(grid, "`B ");break; case 3: strcat(grid, "`B Neutral ");break; case 2: strcat(grid, "`B ");break; case 1: strcat(grid, "`B ");break; case 0: strcat(grid, "`B Evil ");break; default:break; } sprintf(buf," %2d `S|`x", ali-3); strcat(grid, buf); for(ten=6; ten>=0; ten--){ sprintf(buf,"%4d ", alignment_matrix[ali][ten]); strcat(grid, buf); } sprintf(buf," `g%4d\r\n", alignment_matrix[ali][7]); strcat(grid, buf); } // bottom totals strcat(grid, " `g Totals `S|`g"); for(ten=6; ten>=0; ten--){ sprintf(buf,"%4d ", alignment_matrix[7][ten]); strcat(grid, buf); } ch->print(grid); ch->printlnf(" `G%4d`x\r\n", total); } if(++colcount%2==0){ ch->println("`x"); }; ch->printlnf( "NOTE: active players (%d) are " "only in these stats.", total); } /**************************************************************************/ void do_classstats( char_data *ch, char *) { do_lastonstats(ch,"class"); } /**************************************************************************/ void do_racestats( char_data *ch, char *) { do_lastonstats(ch,"race"); } /**************************************************************************/ void do_alignstats( char_data *ch, char *) { do_lastonstats(ch,"align"); } /**************************************************************************/ void do_mudclientstats( char_data *ch, char *) { ch->titlebar("MUD CLIENT STATISTICS"); ch->println(laston_generate_mud_client_stats()); ch->titlebar(""); } /**************************************************************************/ // return -1 if immortal not setup for weblevel // return 0 if failed access // return the level/trust of the immortal if password and username correct int laston_web_level(char *username, char *password) { laston_data *node; // find the username for (node= laston_list; node; node=node->next){ if(!str_cmp(username, node->name)){ // check if it is an imm if(node->level[node->index]>=LEVEL_IMMORTAL || node->trust>LEVEL_IMMORTAL) { if(IS_NULLSTR(node->webpass)){ return -1; } char *crypted_pass=dot_crypt(password, node->webpass); if(!strcmp(crypted_pass, node->webpass)){ return UMAX(node->level[node->index], node->trust); }else{ return 0; } } } }; return 0; } /**************************************************************************/ /**************************************************************************/