/******************************************************************************** * Stat List code copyright 1999-2001 * * Markanth : markanth@spaceservices.net * * Devil's Lament : spaceservices.net port 3778 * * Web Page : http://spaceservices.net/~markanth/ * * * * All I ask in return is that you give me credit on your mud somewhere * * or email me if you use it. * ********************************************************************************/ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #if !defined(WIN32) #include <unistd.h> #endif #include "merc.h" #include "interp.h" #include "recycle.h" STAT_DATA *stat_list; long TopGameStat[MAX_GAMESTAT]; void save_statlist ( void ) { STAT_DATA *pstat; FILE *fp; bool found = FALSE; int i; if ( ( fp = file_open ( STAT_FILE, "w" ) ) == NULL ) { perror ( STAT_FILE ); } fprintf ( fp, "TOPSTATS %d ", MAX_GAMESTAT ); for ( i = 0; i < MAX_GAMESTAT; i++ ) fprintf ( fp, "%ld ", TopGameStat[i] ); fprintf ( fp, "\n" ); for ( pstat = stat_list; pstat != NULL; pstat = pstat->next ) { found = TRUE; fprintf ( fp, "%s ", pstat->name ); for ( i = 0; i < MAX_GAMESTAT; i++ ) fprintf ( fp, "%ld ", pstat->gamestat[i] ); fprintf ( fp, "\n" ); } file_close ( fp ); if ( !found ) unlink ( STAT_FILE ); } void load_statlist ( void ) { FILE *fp; STAT_DATA *stat_last; int i, maxStat = 0; if ( ( fp = file_open ( STAT_FILE, "r" ) ) == NULL ) return; if ( !str_cmp ( fread_word ( fp ), "TOPSTATS" ) ); { maxStat = fread_number ( fp ); for ( i = 0; i < maxStat; i++ ) TopGameStat[i] = fread_number ( fp ); } stat_last = NULL; for ( ;; ) { STAT_DATA *pstat; if ( feof ( fp ) ) { file_close ( fp ); return; } pstat = new_stat_data ( ); pstat->name = str_dup ( fread_word ( fp ) ); for ( i = 0; i < maxStat; i++ ) pstat->gamestat[i] = fread_number ( fp ); fread_to_eol ( fp ); if ( stat_list == NULL ) stat_list = pstat; else stat_last->next = pstat; stat_last = pstat; } } void update_statlist ( CHAR_DATA * ch, bool pdelete ) { STAT_DATA *prev; STAT_DATA *curr; int i; if ( IS_NPC ( ch ) || IS_IMMORTAL ( ch ) ) return; prev = NULL; for ( curr = stat_list; curr != NULL; prev = curr, curr = curr->next ) { if ( !str_cmp ( ch->name, curr->name ) ) { if ( prev == NULL ) stat_list = stat_list->next; else prev->next = curr->next; free_stat_data ( curr ); save_statlist ( ); } } if ( pdelete ) { return; } curr = new_stat_data ( ); curr->name = str_dup ( ch->name ); for ( i = 0; i < MAX_GAMESTAT; i++ ) { curr->gamestat[i] = ch->pcdata->gamestat[i]; if ( curr->gamestat[i] > TopGameStat[i] ) TopGameStat[i] = curr->gamestat[i]; } curr->next = stat_list; stat_list = curr; save_statlist ( ); return; } CH_CMD ( do_showstats ) { int option; char arg[MIL]; argument = one_argument ( argument, arg ); if ( arg[0] == '\0' ) { chsend ( " {ROPTIONS AVAILABLE:{x\n\r", ch ); chsend ( " {G1{x - Ranking of Player Killers (pkills)\n\r", ch ); chsend ( " {G2{x - Ranking of Player Deaths (pdeaths)\n\r", ch ); chsend ( " {G3{x - Ranking of Mob Kills (mkills)\n\r", ch ); chsend ( " {G4{x - Ranking of Mob Deaths (mdeaths)\n\r", ch ); if ( IS_IMMORTAL ( ch ) ) chsend ( " {Gdelete <name>{x - deletes from statlist\n\r", ch ); return; } option = atoi ( arg ); if ( !str_cmp ( arg, "delete" ) && IS_IMMORTAL ( ch ) ) { STAT_DATA *prev = NULL; STAT_DATA *curr = NULL; bool found = FALSE; for ( curr = stat_list; curr != NULL; prev = curr, curr = curr->next ) { if ( !str_cmp ( argument, curr->name ) ) { if ( prev == NULL ) stat_list = stat_list->next; else prev->next = curr->next; free_stat_data ( curr ); save_statlist ( ); found = TRUE; } } if ( !found ) chprintf ( ch, "Error deleting %s.\n\r", argument ); } else if ( option == 1 || !str_prefix ( arg, "pkills" ) ) show_game_stats ( ch, PK_KILLS ); else if ( option == 3 || !str_prefix ( arg, "mkills" ) ) show_game_stats ( ch, MOB_KILLS ); else if ( option == 2 || !str_prefix ( arg, "pdeaths" ) ) show_game_stats ( ch, PK_DEATHS ); else if ( option == 4 || !str_prefix ( arg, "mdeaths" ) ) show_game_stats ( ch, MOB_DEATHS ); else do_showstats ( ch, "" ); return; } int compare_stats args ( ( const void *v1, const void *v2 ) ); int compare_stats ( const void *v1, const void *v2 ) { return *( long * ) v2 - *( long * ) v1; } void show_game_stats ( CHAR_DATA * ch, int type ) { STAT_DATA *curr; BUFFER *output; char buf[MSL]; /* max 2000 entries? old entries will be shoved to the end anyways */ long top[2000]; int count, pos, loop, dcount; bool found = FALSE; const char *stat_name[MAX_GAMESTAT] = { "PLAYER KILLERS", "MOB KILLERS", "PK DEATHS", "MOB DEATHS", }; output = new_buf ( ); count = 0; pos = 0; dcount = 0; sprintf ( buf, "{CRANKING OF %s{x", stat_name[type] ); add_buf ( output, buf ); add_buf ( output, "\n\r" ); loop = 0; for ( curr = stat_list; curr != NULL; curr = curr->next ) { if ( count >= 2000 ) break; if ( curr->gamestat[type] > 0 ) { top[count] = curr->gamestat[type]; count++; found = TRUE; } } qsort ( top, count, sizeof ( long ), compare_stats ); for ( loop = 0; loop < count; loop++ ) { if ( loop >= 49 ) break; for ( curr = stat_list; curr != NULL; curr = curr->next ) { if ( curr->gamestat[type] != top[loop] ) continue; if ( dcount++ >= 50 ) break; sprintf ( buf, "{G%2d{w){W %-20s {w[{R%8ld{W]{x ", dcount, curr->name, top[loop] ); add_buf ( output, buf ); if ( ++pos % 2 == 0 ) { add_buf ( output, "\n\r" ); pos = 0; } } } if ( !found ) add_buf ( output, "\n\rNo one found yet.\n\r" ); else if ( pos % 2 != 0 ) add_buf ( output, "\n\r" ); page_to_char ( buf_string ( output ), ch ); free_buf ( output ); return; }