
Standard
Logging Support!
This tutorial will show you how to
implement support for the standard log, a system which all the programs like
Gibstats use to tally player statistics and put them on webpages.
First off, this code is
courtesy of Mark Davies, who runs the Statlogging site on PlanetQuake.
In order for
this tutorial to work properly, you must be using MSVC++ 5.0 or greater. It is also important that you
download this zip file with the standard log source files:
Standard Logging Files: stdlog.zip
After you unzip the
files, place the stdlog.obj in the release folder with the other object
files. You will need to add the stdlog.obj file to your project within
MSVC by clicking on Project->Add To Project->Files, specifying .obj
files, and selecting the stdlog.obj. The other files go with your source
code and also must be added to the project in the same manner as the
stdlog.obj, except they are not object files.
If all that has been done
you now have 3 new files and 1 new object file added to your project.
Now let's get started!
Add in the blue code and remove any pink code.
First open up
g_local.h. Add this new cvar as shown:
extern
cvar_t *sv_maplist;
// StdLog
extern cvar_t *stdlogfile;
Now go down to the very bottom of
the file and put this:
// StdLog
void StartGSLogFile(void);
Close the file. Next open up
g_main.c and place these #includes right near the top:
#include
"g_local.h"
#include
"stdlog.h" // StdLog
#include "g_statlog.h" // StdLog
Now go down until you find the
list of cvars and add in the new one:
cvar_t
*sv_maplist;
//StdLog
cvar_t *stdlogfile;
Go down to the ShutdownGame
function and add this:
void ShutdownGame (void)
{
gi.dprintf ("==== ShutdownGame ====\n");
sl_GameEnd( &gi, level ); // StdLog
gi.FreeTags (TAG_LEVEL);
gi.FreeTags (TAG_GAME);
}
Now go to the EndDMLevel
function and add this:
void EndDMLevel (void)
{
edict_t *ent;
char *s, *t, *f;
static const char *seps = " ,\n\r";
sl_GameEnd( &gi, level ); // StdLog - Mark Davies
// stay on same level flag
if ((int)dmflags->value & DF_SAME_LEVEL)
{
BeginIntermission
(CreateTargetChangeLevel (level.mapname) );
return;
}
Close the file.
Next open up g_save.c and add the #includes at the top:
#include
"g_local.h"
#include
"stdlog.h" // StdLog
#include "g_statlog.h" // StdLog
Next go the the InitGame
function and add the indicated lines:
void InitGame (void)
{
//StdLog Start
cvar_t *stdlogfile =
gi.cvar("stdlogfile","0",CVAR_LATCH);
if(stdlogfile->value)
StartGSLogFile();
sl_Logging( &gi, "My Mod's Name" );
//StdLog End
gi.dprintf ("==== InitGame ====\n");
Close the file. Now
open up g_spawn.c and add the #Includes at the top:
#include
"g_local.h"
#include
"stdlog.h" // StdLog
#include "g_statlog.h" // StdLog
Go to the spawnentities
function and add this to the end:
G_FindTeams ();
sl_GameStart( &gi, level ); // StdLog
}
Close the file.
Next open up p_client.c and add the #Includes at the top:
#include
"g_local.h"
#include "m_player.h"
#include
"stdlog.h" //StdLog
#include "g_statlog.h" //StdLog
Go to the player_die
function and add this:
if
(!self->deadflag)
{
self->client->respawn_time =
level.time + 1.0;
LookAtKiller (self, inflictor,
attacker);
self->client->ps.pmove.pm_type
= PM_DEAD;
ClientObituary (self, inflictor,
attacker);
sl_WriteStdLogDeath( &gi, level, self, inflictor,
attacker); // StdLog
TossClientWeapon (self);
if (deathmatch->value)
Cmd_Help_f
(self); // show scores
// clear inventory
// this is kind of ugly, but it's
how we want to handle keys in coop
for (n = 0; n < game.num_items;
n++)
{
self->client->pers.inventory[n] = 0;
}
}
Next go to the
clientbegindeathmatch function and add this to the end:
sl_WriteStdLogPlayerEntered( &gi, level, ent ); //
StdLog
// make sure all view stuff is valid
ClientEndServerFrame (ent);
}
Next go to the
clientdisconnect function and add this:
if
(!ent->client)
return;
gi.bprintf (PRINT_HIGH, "%s disconnected\n",
ent->client->pers.netname);
sl_LogPlayerDisconnect( &gi, level, ent ); // StdLog
Now you need to open up
g_statlog.c and go down to the StartGSLogfile function. Near the
beginning it points to where the file is opened and saved.
Change it to suit your
mod. (if your mod resides in quake2/mymod then you want the function to point
to mymod/stdlog.log)
You're done!
Explanation: All the calls made with the sl_whatever simply write to the
logging file about the player. More things can be added, but for now it
simply covers time connected, frags, and deaths. Make sure you turn it on
using the stdlogfile variable.
Tutorial by Willi