Author: Kieren Johnstone a.k.a. -X'BuG-
Today, we are going to find out how to find out who wins at the end of each
match and log them to a file on the server! It's a real quickie, but it's great
for ranking the best and/or worst players on the server !!
Here we go then...Today, we are only going to be editing one function in
g_main.c.
As you may have guessed, this is the function that is executed when it's time for the
map to change - either the fraglimit or timelimit (or in CTF, caplimit) has been reached.
This site, and all content and graphics displayed
on it,
Difficulty: Easy
Find the EndDMLevel function. You should see something like this:
/*
=================
EndDMLevel
The timelimit or fraglimit has been exceeded
=================
*/
void EndDMLevel (void)
{
edict_t *ent;
char *s, *t, *f;
int its_a_draw;
static const char *seps = " ,\n\r";
// stay on same level flag
if ((int)dmflags->value & DF_SAME_LEVEL)
{
BeginIntermission (CreateTargetChangeLevel (level.mapname) );
return;
}
To enable us to display and/or log the winner, we need to change this...replace EndDMLevel with the code below.
/*
=================
EndDMLevel
The timelimit or fraglimit has been exceeded
=================
*/
void EndDMLevel (void)
{
//---------------------------//
// WINNER LOGGING BEGIN //
//---------------------------//
// | This code is pretty |
// | much self-explanitary, |
// | just read the comments |
// | or e-mail me if you |
// | don't understand. |
// \ /
// \_____________________/
edict_t *ent;
edict_t *joe_bloggs; // this is the entity to test (see if its a winner)
char *s, *t, *f;
int i; // this is a temporary counter
int winningfrags; // this is the frags of the winner
edict_t *winner; // this points to the winning person
file *logfile; // this is our file handle
static const char *seps = " ,\n\r";
winningfrags = 0; // reset winning frags - gotta get more than zero !!
winner = 0; // reset winner to nobody
for_each_player(joe_bloggs,i) // for every single player
{
// tell them their frags
gi.dprintf(joe_bloggs,PRINT_MEDIUM, "%s got %i frags.\n",joe_bloggs->client->pers.netname,joe_bloggs->client->resp.score);
// if they've got higher frags than the highest so far,
if (joe_bloggs->client->resp.score > winningfrags) {
// set the new winning frags
winningfrags = joe_bloggs->client->resp.score;
// and point to them as the winner
winner = joe_bloggs;
}
}
// say the winner to everybody
if (winner == 0) {
// nobody is in / got more than zero frags
gi.bprintf(PRINT_HIGH, "Nobody won\n");
} else {
// "winner" wins
gi.bprintf(PRINT_HIGH, "%s wins!!\n",winner->client->pers.netname);
}
// ---
// file logging
// ---
// open output to "winners.log" (wa = write, append)
logfile = fopen("wa","winners.log");
// write winner name
fputs(winner->client->pers.netname,logfile);
// and newline
fputs("\r\n",logfile);
// close file
fclose(logfile);
//---------------------------//
// WINNER LOGGING END //
//---------------------------//
// normal code again....
// stay on same level flag
if ((int)dmflags->value & DF_SAME_LEVEL)
{
BeginIntermission (CreateTargetChangeLevel (level.mapname) );
return;
}
// see if it's in the map list
if (*sv_maplist->string) {
s = strdup(sv_maplist->string);
f = NULL;
t = strtok(s, seps);
while (t != NULL) {
if (Q_stricmp(t, level.mapname) == 0) {
// it's in the list, go to the next one
t = strtok(NULL, seps);
if (t == NULL) { // end of list, go to first one
if (f == NULL) // there isn't a first one, same level
BeginIntermission (CreateTargetChangeLevel (level.mapname) );
else
BeginIntermission (CreateTargetChangeLevel (f) );
} else
BeginIntermission (CreateTargetChangeLevel (t) );
free(s);
return;
}
if (!f)
f = t;
t = strtok(NULL, seps);
}
free(s);
}
if (level.nextmap[0]) // go to a specific map
BeginIntermission (CreateTargetChangeLevel (level.nextmap) );
else { // search for a changelevel
ent = G_Find (NULL, FOFS(classname), "target_changelevel");
if (!ent)
{ // the map designer didn't include a changelevel,
// so create a fake ent that goes back to the same level
BeginIntermission (CreateTargetChangeLevel (level.mapname) );
return;
}
BeginIntermission (ent);
}
}
And that's all you need to do - I told you it's a quickie!
If you have any trouble compiling or understanding this code, please feel free to e-mail me.
Tutorial by Kieren Johnstone, author of forthcoming mod CLOT.
are ©opyrighted to the Quake DeveLS team.
All rights received.
Got a suggestion? Comment? Question? Hate mail? Send it to us!
Oh yeah, this site is best viewed in 16 Bit or higher, with the resolution on 800*600.
Thanks to Planet Quake for there great help and support with hosting.
Best viewed with Netscape 4 or IE 5