Author: SumFuka
Difficulty: Easy

Ok ok I lied about doing laser tag next... our quake2 server needs a MOTD (Message
Of The Day - the welcome message) ! Lets open up game.h and go to line 80.
Have a look at some of the game interface functions that John Carmack has made
for us to play with :
The function name bprintf appears next, enclosed in brackets with a *
in front. Don't worry about the brackets and the star, they are there because
the function is being listed in the game_import_t structure. In other words,
the bracket and star are there because of the way the function is being packaged
in neat little game interface (something that only a purely-brilliant(tm) programmer
like John Carmack would do !... it makes the code look hard here now, but it makes the
quake2 codebase more modularized and robust).
After the function name comes the
function parameters. bprint has at least 2 parameters,
the printlevel (which is an integer), the format string (fmt, which is a string)
and the ... means more parameters may be supplied to this function. A semi-colon
terminates the function description.
Lets SumUp some other functions :
Exercise 1:
(answer at bottom of page. DON'T LOOK YET ! Try it first, really).
Welcome, trooper !
Compile and install your gamex86.dll in your c:\quake2\test directory.
Run quake2 in deathmatch mode. You can do this from the command line with
//
// functions provided by the main engine
//
typedef struct
{
// special messages
void (*bprintf) (int printlevel, char *fmt, ...);
void (*dprintf) (char *fmt, ...);
void (*cprintf) (edict_t *ent, int printlevel, char *fmt, ...);
void (*centerprintf) (edict_t *ent, char *fmt, ...);
void (*sound) (edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs);
void (*positioned_sound) (vec3_t origin, edict_t *ent, int channel, int soundinedex, float volume, float attenuation, float timeofs);
...
...
...
Everything in the curly brackets after the 'typedef struct' is a function we can use in the game.
For example, lets look at the function bprintf:
void (*bprintf) (int printlevel, char *fmt, ...);
The void on the left simply says that the function does not return anything... in
C a function can return a string, an integer, something else, or nothing (void).
How do I use the game interface functions ? gi.bprintf (PRINT_MEDIUM, "Hi there people !\n");
...the line above will print a message to all players in the game saying "Hi there !".
The game interface (gi) is available to us at all times when we might need it.
gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
and add a line below it like this :
gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
gi.centerprintf (ent, "Welcome, trooper !\n\nGood luck, you'll need it\n");
The \n is a newline character. Notice how we used a double '\n\n' after the '!'...
the first \n terminates the "Welcome trooper !" line and the second \n leaves a blank
line. Always end your strings with a \n. c:\quake2\quake2.exe +set game "test" +set deathmatch 1 +map base1
(I have a shortcut on my desktop for this...)

Lets read the motd from a file
Go to p_client.c again and replace the WHOLE ClientBeginDeathmatch function with this one :
/*
=====================
ClientBeginDeathmatch
A client has just connected to the server in
deathmatch mode, so clear everything out before starting them.
=====================
*/
void ClientBeginDeathmatch (edict_t *ent)
{
// STEVE added these 3 local variables
FILE *motd_file;
char motd[500];
char line[80];
G_InitEdict (ent);
InitClientResp (ent->client);
// locate ent at a spawn point
PutClientInServer (ent);
// send effect
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_LOGIN);
gi.multicast (ent->s.origin, MULTICAST_PVS);
gi.bprintf (PRINT_HIGH, "%s entered the game\n", ent->client->pers.netname);
// STEVE changed this bit : read the motd from a file
if (motd_file = fopen("motd.txt", "r"))
{
// we successfully opened the file "motd.txt"
if ( fgets(motd, 500, motd_file) )
{
// we successfully read a line from "motd.txt" into motd
// ... read the remaining lines now
while ( fgets(line, 80, motd_file) )
{
// add each new line to motd, to create a BIG message string.
// we are using strcat: STRing conCATenation function here.
strcat(motd, line);
}
// print our message.
gi.centerprintf (ent, motd);
}
// be good now ! ... close the file
fclose(motd_file);
}
// make sure all view stuff is valid
ClientEndServerFrame (ent);
}
Now go and create a text file called motd.txt in your C:\QUAKE2 directory.
Mine looks like this :
Welcome to SumFuka's server ! This week Clan Manical have a match versus the BiPS (Bananas in pyjamas) Lock and Load, boys.Now you can run a quake2 server and change the motd whilst it is still running, just by modifying motd.txt. Cool huh ? Next week... Lets do different player classes...
Tutorial by SumFuka
|
This site, and all content and graphics displayed
on it, |