Here's another little cooperative play mod, or a pretty sinister
deathmatch mod. Since you guys are space marines, you ought to be able
to keep tabs on each other, right? This little patch adds a command to
check the health and range of all players.

All of the editing for this patch takes place in g_cmds.c. In
Clientcommand(), I've added the following ('+' signs indicate lines
added)

 		Cmd_PutAway_f (ent);
 	else if (Q_stricmp (cmd, "wave") == 0)
 		Cmd_Wave_f (ent);
+
+	// CCH: new command 'checkstats'
+	else if (Q_stricmp (cmd, "checkstats") == 0)
+		Cmd_CheckStats_f (ent);
+
 	else if (Q_stricmp (cmd, "gameversion") == 0)
 	{
 		gi.cprintf (ent, PRINT_HIGH, "%s : %s\n", GAMEVERSION, __DATE__);

This allows us to call a new function Cmd_CheckStats_f() from the
console by typing 'cmd checkstats'. I recommend binding that to a key
for easy access.

Now for what Cmd_CheckStats_f() will do. I've added the new function
just before ClientCommand(), like so

+/*
+=================
+Cmd_CheckStats_f
+CCH: New function to print all players' stats
+=================
+*/
+void Cmd_CheckStats_f (edict_t *ent)
+{
+	int		i, j;
+	edict_t	*player;
+	char	stats[500];
+	vec3_t	v;
+	float	len;
+
+	// use in coop mode only
+//	if (!coop->value)
+//		return;
+
+	j = sprintf(stats, "            Name Health Range\n=============================\n");
+	for (i=0 ; i<maxclients->value ; i++)
+	{
+		player = g_edicts + 1 + i;
+		if (!player->inuse || !player->client)
+			continue; 
+		VectorSubtract (ent->s.origin, player->s.origin, v);
+		len = VectorLength (v);
+		j += sprintf(stats + j, "%16s %6d %5.0f\n", player->client->pers.netname, player->health, len);
+		if (j > 450)
+			break;
+	}
+	gi.centerprintf(ent, "%s", stats);
+}
+
 /*
 =================
 ClientCommand
 =================
 */

Normally, I would think you want this to be a coop only command, but
since coop mode hasn't been implemented yet, I've commented that bit of
the code out. stats is the buffer we'll store the information in and j
will keep track of where we are in the buffer. First, we put some column
headings in our buffer, then we run through the player edicts. If the
edict has a current player, we calculate its range from this player
and then add the name, health, and range information to the buffer. The
printf specification makes sure these values all line up with the column
headings appropriately, with 16 spaces for the name, 6 spaces for
health, and 5 spaces for the range with no digits after the decimal
point. If we've written more than 450 characters to the buffer, we're
getting near the end of the buffer so we go ahead and break out before
we have a buffer overrun. Finally, we centerprint all this info we've
gathered to the player.

Feel free to make changes on the info presented, like shortening the
columns (health will never be more than 3 digits, but the column heading
takes 6 spaces) or presenting new info (delta x,y,z values maybe). Also,
you might want to skip the current player, since they probably know all
this info already. Full source and patch file at
http://www.jump.net/~dctank.

Chris Hilton
chilton@scci-ad.com