/**************************************************************************
* 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-2003 by Ryan Jennings *
* http://1stmud.dlmud.com/ <r-jenn@shaw.ca> *
***************************************************************************/
#include "merc.h"
#include "interp.h"
#include "recycle.h"
#include "tablesave.h"
STAT_DATA xStat;
const struct savetable_type statsavetable[] = {
{"name", FIELD_STRING, (void *) &xStat.name, NULL, NULL},
{"stats", FIELD_LONG_ARRAY, (void *) &xStat.gamestat,
(const void *) MAX_GAMESTAT, (const void *) 0},
{NULL, 0, NULL, NULL, NULL}
};
TABLESAVE(rw_stats)
{
rw_list(type, STAT_FILE, STAT_DATA, stat_first, stat_last, next, prev,
new_stat_data, "STAT", xStat, statsavetable);
}
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_first; curr != NULL; curr = prev)
{
prev = curr->next;
if (!str_cmp(ch->name, curr->name))
{
UNLINK(curr, stat_first, stat_last, next, prev);
free_stat_data(curr);
rw_stats(action_write);
}
}
if (pdelete)
{
return;
}
curr = new_stat_data();
curr->name = str_dup(ch->name);
for (i = 0; i < MAX_GAMESTAT; i++)
curr->gamestat[i] = GET_STAT(ch, i);
LINK(curr, stat_first, stat_last, next, prev);
rw_stats(action_write);
return;
}
CH_CMD(do_showstats)
{
int option;
char arg[MIL];
argument = one_argument(argument, arg);
if (IS_NULLSTR(arg))
{
chprintln(ch, " {ROPTIONS AVAILABLE:{x");
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)");
if (IS_IMMORTAL(ch))
chprintln(ch, " {Gdelete <name>{x - deletes from statlist");
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_first; curr != NULL; curr = prev)
{
prev = curr->next;
if (!str_cmp(argument, curr->name))
{
UNLINK(curr, stat_first, stat_last, next, prev);
free_stat_data(curr);
rw_stats(action_write);
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_type;
int compare_stats(const void *v1, const void *v2)
{
STAT_DATA *stat1 = *(STAT_DATA **) v1;
STAT_DATA *stat2 = *(STAT_DATA **) v2;
if (!stat2)
return 1;
if (!stat1)
return 2;
return stat2->gamestat[compare_type] - stat1->gamestat[compare_type];
}
int count_statlist()
{
STAT_DATA *stat;
int i = 0;
for (stat = stat_first; stat != NULL; stat = stat->next)
i++;
return i;
}
void show_game_stats(CHAR_DATA * ch, int type)
{
STAT_DATA *curr;
BUFFER *output;
STAT_DATA **top;
int count, pos, loop;
bool found = FALSE;
int topstat = count_statlist();
const char *stat_name[MAX_GAMESTAT] = {
"PLAYER KILLERS",
"MOB KILLERS",
"PK DEATHS",
"MOB DEATHS",
};
output = new_buf();
count = 0;
pos = 0;
compare_type = type;
alloc_mem(top, STAT_DATA *, topstat);
bprintlnf(output, "{CRANKING OF %s{x", 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;
bprintf(output, "{G%2d{w){W %-20s {w[{R%8ld{W]{x ",
loop + 1, top[loop]->name, top[loop]->gamestat[type]);
if (++pos % 2 == 0)
{
bprintln(output, "");
pos = 0;
}
}
}
if (!found)
bprintln(output, "\n\rNo one found yet.");
else if (pos % 2 != 0)
bprintln(output, "");
sendpage(ch, buf_string(output));
free_mem(top);
free_buf(output);
return;
}