From 48e858988f16109b81ce1c3b3e4d63c3565f25b3 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Fri, 21 Oct 2011 20:03:31 +0000 Subject: Add -statdump command line parameter, to generate the same output as statdump.exe does with Vanilla Doom. Subversion-branch: /branches/v2-branch Subversion-revision: 2450 --- src/doom/Makefile.am | 1 + src/doom/d_main.c | 7 + src/doom/g_game.c | 3 + src/doom/statdump.c | 355 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/doom/statdump.h | 29 +++++ 5 files changed, 395 insertions(+) create mode 100644 src/doom/statdump.c create mode 100644 src/doom/statdump.h (limited to 'src/doom') diff --git a/src/doom/Makefile.am b/src/doom/Makefile.am index f0938c7e..eb229acb 100644 --- a/src/doom/Makefile.am +++ b/src/doom/Makefile.am @@ -56,6 +56,7 @@ r_sky.c r_sky.h \ r_things.c r_things.h \ s_sound.c s_sound.h \ sounds.c sounds.h \ +statdump.c statdump.h \ st_lib.c st_lib.h \ st_stuff.c st_stuff.h \ wi_stuff.c wi_stuff.h diff --git a/src/doom/d_main.c b/src/doom/d_main.c index e59802dd..ddc0c7f7 100644 --- a/src/doom/d_main.c +++ b/src/doom/d_main.c @@ -78,6 +78,7 @@ #include "p_setup.h" #include "r_local.h" +#include "statdump.h" #include "d_main.h" @@ -1546,6 +1547,12 @@ void D_DoomMain (void) if (gamemode == commercial && W_CheckNumForName("map01") < 0) storedemo = true; + if (M_CheckParmWithArgs("-statdump", 1)) + { + I_AtExit(StatDump, true); + DEH_printf("External statistics registered.\n"); + } + //! // @arg // @category demo diff --git a/src/doom/g_game.c b/src/doom/g_game.c index 3c9eba62..b698d465 100644 --- a/src/doom/g_game.c +++ b/src/doom/g_game.c @@ -57,6 +57,7 @@ #include "hu_stuff.h" #include "st_stuff.h" #include "am_map.h" +#include "statdump.h" // Needs access to LFB. #include "v_video.h" @@ -1395,6 +1396,8 @@ void G_DoCompleted (void) gamestate = GS_INTERMISSION; viewactive = false; automapactive = false; + + StatCopy(&wminfo); WI_Start (&wminfo); } diff --git a/src/doom/statdump.c b/src/doom/statdump.c new file mode 100644 index 00000000..0e83df8d --- /dev/null +++ b/src/doom/statdump.c @@ -0,0 +1,355 @@ + + /* + + Copyright(C) 2007,2011 Simon Howard + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + + -- + + Functions for presenting the information captured from the statistics + buffer to a file. + + */ + +#include +#include +#include + +#include "d_player.h" +#include "d_mode.h" +#include "m_argv.h" + +#include "statdump.h" + +/* Par times for E1M1-E1M9. */ +static const int doom1_par_times[] = +{ + 30, 75, 120, 90, 165, 180, 180, 30, 165, +}; + +/* Par times for MAP01-MAP09. */ +static const int doom2_par_times[] = +{ + 30, 90, 120, 120, 90, 150, 120, 120, 270, +}; + +/* Player colors. */ +static const char *player_colors[] = +{ + "Green", "Indigo", "Brown", "Red" +}; + +// Array of end-of-level statistics that have been captured. + +#define MAX_CAPTURES 32 +static wbstartstruct_t captured_stats[MAX_CAPTURES]; +static int num_captured_stats = 0; + +static GameMode_t discovered_gamemode = indetermined; + +/* Try to work out whether this is a Doom 1 or Doom 2 game, by looking + * at the episode and map, and the par times. This is used to decide + * how to format the level name. Unfortunately, in some cases it is + * impossible to determine whether this is Doom 1 or Doom 2. */ + +static void DiscoverGamemode(wbstartstruct_t *stats, int num_stats) +{ + int partime; + int level; + int i; + + if (discovered_gamemode != indetermined) + { + return; + } + + for (i=0; i 0) + { + discovered_gamemode = doom; + return; + } + + /* This is episode 1. If this is level 10 or higher, + it must be Doom 2. */ + + if (level >= 9) + { + discovered_gamemode = doom2; + return; + } + + /* Try to work out if this is Doom 1 or Doom 2 by looking + at the par time. */ + + partime = stats[i].partime; + + if (partime == doom1_par_times[level] * TICRATE + && partime != doom2_par_times[level] * TICRATE) + { + discovered_gamemode = doom; + return; + } + + if (partime != doom1_par_times[level] * TICRATE + && partime == doom2_par_times[level] * TICRATE) + { + discovered_gamemode = doom2; + return; + } + } +} + +/* Returns the number of players active in the given stats buffer. */ + +static int GetNumPlayers(wbstartstruct_t *stats) +{ + int i; + int num_players = 0; + + for (i=0; iplyr[i].in) + { + ++num_players; + } + } + + return num_players; +} + +static void PrintBanner(FILE *stream) +{ + fprintf(stream, "===========================================\n"); +} + +static void PrintPercentage(FILE *stream, int amount, int total) +{ + if (total == 0) + { + fprintf(stream, "0"); + } + else + { + fprintf(stream, "%i / %i", amount, total); + + fprintf(stream, " (%i%%)", (amount * 100) / total); + } +} + +/* Display statistics for a single player. */ + +static void PrintPlayerStats(FILE *stream, wbstartstruct_t *stats, + int player_num) +{ + wbplayerstruct_t *player = &stats->plyr[player_num]; + + fprintf(stream, "Player %i (%s):\n", player_num + 1, + player_colors[player_num]); + + /* Kills percentage */ + + fprintf(stream, "\tKills: "); + PrintPercentage(stream, player->skills, stats->maxkills); + fprintf(stream, "\n"); + + /* Items percentage */ + + fprintf(stream, "\tItems: "); + PrintPercentage(stream, player->sitems, stats->maxitems); + fprintf(stream, "\n"); + + /* Secrets percentage */ + + fprintf(stream, "\tSecrets: "); + PrintPercentage(stream, player->ssecret, stats->maxsecret); + fprintf(stream, "\n"); +} + +/* Frags table for multiplayer games. */ + +static void PrintFragsTable(FILE *stream, wbstartstruct_t *stats) +{ + int x, y; + + fprintf(stream, "Frags:\n"); + + /* Print header */ + + fprintf(stream, "\t\t"); + + for (x=0; xplyr[x].in) + { + continue; + } + + fprintf(stream, "%s\t", player_colors[x]); + } + + fprintf(stream, "\n"); + + fprintf(stream, "\t\t-------------------------------- VICTIMS\n"); + + /* Print table */ + + for (y=0; yplyr[y].in) + { + continue; + } + + fprintf(stream, "\t%s\t|", player_colors[y]); + + for (x=0; xplyr[x].in) + { + continue; + } + + fprintf(stream, "%i\t", stats->plyr[y].frags[x]); + } + + fprintf(stream, "\n"); + } + + fprintf(stream, "\t\t|\n"); + fprintf(stream, "\t KILLERS\n"); +} + +/* Displays the level name: MAPxy or ExMy, depending on game mode. */ + +static void PrintLevelName(FILE *stream, int episode, int level) +{ + PrintBanner(stream); + + switch (discovered_gamemode) + { + + case doom: + fprintf(stream, "E%iM%i\n", episode + 1, level + 1); + break; + case doom2: + fprintf(stream, "MAP%02i\n", level + 1); + break; + default: + case indetermined: + fprintf(stream, "E%iM%i / MAP%02i\n", + episode + 1, level + 1, level + 1); + break; + } + + PrintBanner(stream); +} + +/* Print details of a statistics buffer to the given file. */ + +static void PrintStats(FILE *stream, wbstartstruct_t *stats) +{ + int leveltime, partime; + int i; + + PrintLevelName(stream, stats->epsd, stats->last); + fprintf(stream, "\n"); + + leveltime = stats->plyr[0].stime / TICRATE; + partime = stats->partime / TICRATE; + fprintf(stream, "Time: %i:%02i", leveltime / 60, leveltime % 60); + fprintf(stream, " (par: %i:%02i)\n", partime / 60, partime % 60); + fprintf(stream, "\n"); + + for (i=0; iplyr[i].in) + { + PrintPlayerStats(stream, stats, i); + } + } + + if (GetNumPlayers(stats) >= 2) + { + PrintFragsTable(stream, stats); + } + + fprintf(stream, "\n"); +} + +void StatCopy(wbstartstruct_t *stats) +{ + if (M_ParmExists("-statdump") && num_captured_stats < MAX_CAPTURES) + { + memcpy(&captured_stats[num_captured_stats], stats, + sizeof(wbstartstruct_t)); + ++num_captured_stats; + } +} + +void StatDump(void) +{ + FILE *dumpfile; + int i; + + //! + // @category compat + // @arg + // + // Dump statistics information to the specified file on the levels + // that were played. The output from this option matches the output + // from statdump.exe (see ctrlapi.zip in the /idgames archive). + // + + i = M_CheckParmWithArgs("-statdump", 1); + + if (i > 0) + { + // We actually know what the real gamemode is, but this has + // to match the output from statdump.exe. + + DiscoverGamemode(captured_stats, num_captured_stats); + + // Allow "-" as output file, for stdout. + + if (strcmp(myargv[i + 1], "-") != 0) + { + dumpfile = fopen(myargv[i + 1], "w"); + } + else + { + dumpfile = NULL; + } + + for (i = 0; i < num_captured_stats; ++i) + { + PrintStats(dumpfile, &captured_stats[i]); + } + + if (dumpfile != NULL) + { + fclose(dumpfile); + } + } +} + diff --git a/src/doom/statdump.h b/src/doom/statdump.h new file mode 100644 index 00000000..511d945b --- /dev/null +++ b/src/doom/statdump.h @@ -0,0 +1,29 @@ + + /* + + Copyright(C) 2007 Simon Howard + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + + */ + +#ifndef DOOM_STATDUMP_H +#define DOOM_STATDUMP_H + +void StatCopy(wbstartstruct_t *stats); +void StatDump(void); + +#endif /* #ifndef DOOM_STATDUMP_H */ -- cgit v1.2.3