/**************************************************************************
* 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-2002 by Ryan Jennings *
* http://1stmud.dlmud.com/ <r-jenn@shaw.ca> *
***************************************************************************/
#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;
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];
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')
{
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_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_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_list; stat != NULL; stat = stat->next)
i++;
return i;
}
void show_game_stats (CHAR_DATA * ch, int type)
{
STAT_DATA *curr;
BUFFER *output;
char buf[MSL];
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);
sprintf (buf, "{CRANKING OF %s{x", stat_name[type]);
add_buf (output, buf);
add_buf (output, "\n\r");
loop = 0;
loop = 0;
for (curr = stat_list; 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;
sprintf (buf, "{G%2d{w){W %-20s {w[{R%8ld{W]{x ",
loop + 1, top[loop]->name, top[loop]->gamestat[type]);
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_mem (top);
free_buf (output);
return;
}