/**************************************************************************/
// 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
laston_data *laston_celeb_list; //most famous characters
laston_data *laston_next_celeb_list; //fame 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 (fame)
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->fame = ch->pcdata->fame;
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,CODER)){
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,CODER))
{
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,CODER)
?(!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,CODER)
?(!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,CODER)
?(!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,CODER)
?(!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,CODER)
?(!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);
}
/**************************************************************************/
void add_top_celeb(laston_data *pnode)
{
laston_data *node, *prev;
if (!laston_celeb_list)
{
laston_celeb_list=pnode;
return;
}
// go down the list till we find the place they are less than
prev=NULL;
for (node= laston_celeb_list; node; node=node->next_celeb)
{
if (node->fame < pnode->fame){
if (!prev)
{
pnode->next_celeb=laston_celeb_list;
laston_celeb_list=pnode;
return;
}
pnode->next_celeb = node;
prev->next_celeb =pnode;
return;
}
prev=node;
}
pnode->next_celeb = node;
prev->next_celeb =pnode;
}
/**************************************************************************/
void resort_top_celeb()
{
laston_data *node;
log_string("resorting most famous list...");
// first wipe the old settings
laston_celeb_list=NULL;
for (node= laston_list; node; node=node->next)
{
node->next_celeb=NULL;
}
// now readd to the list if their fame is over 100
for (node= laston_list; node; node=node->next)
{
if (node->fame>=100 // 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_celeb(node);
}
log_string("resort complete.");
}
/**************************************************************************/
void do_topceleb(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("MOST FAMOUS PEOPLE"));
add_buf(output,buf);
for (node= laston_celeb_list; node; node=node->next_celeb)
{
// sprintf(buf, " %-13s%6d ", node->name, node->fame);
sprintf(buf, "`W%3d `w%-13s%6d ", count, node->name, node->fame);
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;
}
/**************************************************************************/
/**************************************************************************/