/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * 1stMud ROM Derivative (c) 2001-2004 by Markanth * * http://www.firstmud.com/ <markanth@firstmud.com> * * By using this code you have agreed to follow the term of * * the 1stMud license in ../doc/1stMud/LICENSE * ***************************************************************************/ #include "merc.h" #include "interp.h" #include "recycle.h" #include "data_table.h" DataTable stat_data_table[] = { {"name", FIELD_STRING, (void *) &stat_zero.name, NULL, NULL}, {"stats", FIELD_LONG_ARRAY, (void *) &stat_zero.gamestat, (const void *) MAX_GAMESTAT, (const void *) 0}, {"version", FIELD_INT, (void *) &stat_zero.version, NULL, NULL}, {NULL, (field_t) - 1, NULL, NULL, NULL} }; TableSave_Fun(rw_stat_data) { rw_list(type, STAT_FILE, StatData, stat); } void update_statlist(CharData * ch, bool pdelete) { StatData *prev; StatData *curr; int i; if (IsNPC(ch) || IsImmortal(ch)) return; prev = NULL; for (curr = stat_first; curr != NULL; curr = prev) { prev = curr->next; if (!str_cmp(ch->name, curr->name)) { if (curr->version < mud_info.stats.version) { memset(curr->gamestat, 0, MAX_GAMESTAT); memset(ch->pcdata->gamestat, 0, MAX_GAMESTAT); } UnLink(curr, stat, next, prev); free_stat(curr); } } if (pdelete || IsNPC(ch) || IsImmortal(ch)) { rw_stat_data(act_write); return; } curr = new_stat(); curr->name = str_dup(ch->name); curr->version = mud_info.stats.version; for (i = 0; i < MAX_GAMESTAT; i++) curr->gamestat[i] = GetStat(ch, i); Link(curr, stat, next, prev); rw_stat_data(act_write); return; } const char *print_stat(CharData * ch, const char *head, long value) { return FORMATF("{W%-19.19s {w[{R%10.10ld{w]", head, value); } Do_Fun(do_showstats) { int option; char arg[MIL]; argument = one_argument(argument, arg); if (NullStr(arg)) { chprintln(ch, " {ROPTIONS AVAILABLE:{x"); chprintln(ch, " {G0{x - Show general {n stats. (gstats)"); chprintln(ch, " {G1{x - Ranking of Player Killers (pkills)"); chprintln(ch, " {G2{x - Ranking of Player Deaths (pdeaths)"); chprintln(ch, " {G3{x - Ranking of Mob Kills (mkills)"); chprintln(ch, " {G4{x - Ranking of Mob Deaths (mdeaths)"); chprintln(ch, " {G5{x - Personal Rankings (personal)"); if (IsImmortal(ch)) chprintln(ch, " {Gdelete <name>{x - deletes from statlist"); return; } option = atoi(arg); if (!str_cmp(arg, "delete") && IsImmortal(ch)) { StatData *prev = NULL; StatData *curr = NULL; bool found = false; for (curr = stat_first; curr != NULL; curr = prev) { prev = curr->next; if (!str_cmp(argument, curr->name)) { UnLink(curr, stat, next, prev); free_stat(curr); rw_stat_data(act_write); found = true; } } if (!found) chprintlnf(ch, "Error deleting %s.", argument); } else if (option == 0 || !str_prefix(arg, "gstats")) { Column *Cd; Buffer *b; Cd = new_column(); b = new_buf(); set_cols(Cd, ch, 2, COLS_BUF, b); bprintln(b, stringf(ch, 0, Center, "{R-{r=", "{C[ %s Stats ]", mud_info.name)); print_cols(Cd, print_stat(ch, "Logins", mud_info.stats.logins)); print_cols(Cd, print_stat(ch, "Quests", mud_info.stats.quests)); print_cols(Cd, print_stat(ch, "Quests Complete", mud_info.stats.qcomplete)); print_cols(Cd, print_stat(ch, "Levels", mud_info.stats.levels)); print_cols(Cd, print_stat(ch, "Newbies", mud_info.stats.newbies)); print_cols(Cd, print_stat(ch, "Deletions", mud_info.stats.deletions)); print_cols(Cd, print_stat(ch, "Mob Deaths", mud_info.stats.mobdeaths)); print_cols(Cd, print_stat(ch, "Auctions", mud_info.stats.auctions)); print_cols(Cd, print_stat(ch, "Auctions Sold", mud_info.stats.aucsold)); print_cols(Cd, print_stat(ch, "Player Deaths", mud_info.stats.pdied)); print_cols(Cd, print_stat(ch, "Player Kills", mud_info.stats.pkill)); print_cols(Cd, print_stat(ch, "Notes", mud_info.stats.notes)); print_cols(Cd, print_stat(ch, "Remorts", mud_info.stats.remorts)); print_cols(Cd, print_stat(ch, "Wars", mud_info.stats.wars)); print_cols(Cd, print_stat(ch, "Global Quests", mud_info.stats.gquests)); print_cols(Cd, print_stat(ch, "Connections", mud_info.stats.connections)); print_cols(Cd, print_stat(ch, "Connects this Boot", mud_info.stats.boot_connects)); print_cols(Cd, print_stat(ch, "Online Record", mud_info.stats.online)); print_cols(Cd, print_stat(ch, "Web Hits", mud_info.stats.web_requests)); print_cols(Cd, print_stat(ch, "Channel Messages", mud_info.stats.chan_msgs)); cols_nl(Cd); bprintln(b, stringf(ch, 0, Center, "{R-{r=", "{C[ Stats since: %s ]", str_time(mud_info.stats.lastupdate, GetTzone(ch), NULL))); sendpage(ch, buf_string(b)); free_buf(b); free_column(Cd); return; } 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 if (option == 5 || !str_prefix(arg, "personal")) { StatData *curr; Column Cd; Buffer b; int i = 0; const char *stat_self[MAX_GAMESTAT] = { "PLAYER KILLS", "MOB KILLS", "PK DEATHS", "MOB DEATHS", }; update_statlist(ch, false); for (curr = stat_first; curr != NULL; curr = curr->next) if (!str_cmp(ch->name, curr->name)) break; if (!curr) { chprintln(ch, "You have no stats yet."); return; } set_cols(&Cd, ch, 2, COLS_BUF, &b); bprintln(&b, stringf(ch, 0, Center, "{r-{R=", "{C[ RANKING OF PERSONAL BESTS ]")); for (i = 0; i < MAX_GAMESTAT; i++) { print_cols(&Cd, "{G%2d{w){W %s{x", i + 1, print_stat(ch, stat_self[i], curr->gamestat[i])); } cols_nl(&Cd); bprintln(&b, draw_line(ch, "{r-{R=", 0)); sendpage(ch, buf_string(&b)); return; } else do_showstats(n_fun, ch, ""); return; } int compare_type; int compare_stats(const void *v1, const void *v2) { StatData *stat1 = *(StatData **) v1; StatData *stat2 = *(StatData **) v2; if (!stat2) return 1; if (!stat1) return 2; return stat2->gamestat[compare_type] - stat1->gamestat[compare_type]; } void show_game_stats(CharData * ch, int type) { StatData *curr; Buffer *output; StatData **top; Column *Cd, c; int count, loop; bool found = false; const char *stat_name[MAX_GAMESTAT] = { "PLAYER KILLERS", "MOB KILLERS", "PK DEATHS", "MOB DEATHS", }; output = new_buf(); Cd = &c; set_cols(Cd, ch, 2, COLS_BUF, output); count = 0; compare_type = type; alloc_mem(top, StatData *, top_stat); bprintln(output, stringf(ch, 0, Center, "{R-{r=", "{C[ RANKING OF %s ]", stat_name[type])); loop = 0; loop = 0; for (curr = stat_first; curr != NULL; curr = curr->next) { top[count] = curr; count++; found = true; } if (found) { qsort(top, count, sizeof(*top), compare_stats); for (loop = 0; loop < count; loop++) { if (loop >= 50) break; print_cols(Cd, "{G%2d{w){W %-20s {w[{R%8ld{W]{x", loop + 1, top[loop]->name, top[loop]->gamestat[type]); } } if (!found) bprintln(output, "No one found yet."); else cols_nl(Cd); bprintln(output, draw_line(ch, "{R-{r=", 0)); sendpage(ch, buf_string(output)); free_mem(top); free_buf(output); free_column(Cd); return; }