Another code dump for my editable hud. It’s now A LOT easier to add/remove hud elements. Also you’ll need to create a cvar for the default hud as seen in CG_LoadHud2(). You’ll have to update all occurances of the previous hud code (and there’s a lot) in cgame.
cg_hud.c
#include "cg_local.h"
#define DEFAULTHUD "hud/default.dat"
// name elementid params dimensions
helements_t hude[MAX_ELEMENTS] = {
{ "", H_NULL, 0, 0 },
{ "healthbar", H_HEALTHBAR, 3, 1 },
{ "staminabar", H_STAMINABAR, 3, 1 },
{ "chargebar", H_CHARGEBAR, 3, 1 },
{ "compass", H_COMPASS, 4, 1 },
{ "healthtext", H_HP, 3, 1 },
{ "xptext", H_XP, 3, 1 },
{ "upperright", H_UPPERRIGHT, 2, 1 },
{ "skillpic", H_SKILLPICS, 3, 2 },
{ "skilltext", H_SKILLTEXTS, 3, 2 },
{ "skillbox", H_SKILLBOXES, 3, 2 },
{ "overheat", H_OVERHEAT, 4, 1 },
{ "weaponcard", H_WEAPONCARD, 3, 1 },
{ "ammocount", H_AMMO, 3, 1 },
{ "fireteam", H_FIRETEAM, 3, 1 },
{ "cptext", H_CP, 2, 1 },
{ "bptext", H_BP, 2, 1 },
{ "stance", H_STANCE, 4, 1 },
{ "flag", H_FLAG, 3, 1 },
{ "treasure", H_TREASURE, 3, 1 },
{ "pmitems", H_PM, 3, 1 },
{ "bigpmitems", H_PMBIG, 3, 1 },
{ "head", H_HEAD, 4, 1 },
{ "cash", H_CASH, 3, 1 },
};
void CG_LoadHud2(char *filename) {
int handle;
int x, y, z;
pc_token_t token;
pc_token_t saved;
float version;
memset(&cg.hud2, 0, sizeof(cg.hud2));
handle = trap_PC_LoadSource( filename );
if (!handle) {
// inform the user that this hud does not exist
CG_Printf("CG_LoadHud: file '%s' does not exist, attempting to load default hud.
", filename);
// see if we can load from the cvar
filename = va("hud/%s.dat", cb_defaulthud.string);
handle = trap_PC_LoadSource( filename );
if (!handle) {
// return a warning
CG_Printf("CG_LoadHud: Failed to load default hud.
");
// now try the hardcoded hud, this *SHOULD* exist for all clients...
handle = trap_PC_LoadSource( DEFAULTHUD );
if (!handle) {
CG_Printf("CG_LoadHud: (^1CRITICAL ERROR^7) ^3NO HUD FOUND!^7
");
return;
}
}
}
// now let's read the elements
while (1) {
if ( !trap_PC_ReadToken( handle, &token ) ) {
break;
}
// find the version (this is incompatible with version 1 files)
if (!Q_stricmp( token.string, "version") ) {
saved = token;
// read the next token
if ( !trap_PC_ReadToken( handle, &token ) ) {
CG_Printf("Error reading after token '%s'
", saved.string);
break;
}
version = token.floatvalue;
if (version < 2) {
CG_Printf("Hud contains invalid or empty version.
");
return;
}
}
if ( !Q_stricmp( token.string, "elements") ) {
// first we *MUST* have a version (version 1 breaks our parsing)
if (version == 0) {
CG_Printf("Hud contains invalid or empty version.
");
return;
}
saved = token;
// read the next token
if ( !trap_PC_ReadToken( handle, &token ) ) {
CG_Printf("Error reading after token '%s'
", saved.string);
return;
}
// bracket
if ( !Q_stricmp(token.string, "{") ) {
while ( 1 ) {
// read a token
saved = token;
if ( !trap_PC_ReadToken( handle, &token ) ) {
CG_Printf("Error reading after token '%s'
", saved.string);
return;
}
// end bracket
if ( !Q_stricmp( token.string, "}") ) {
break;
}
// see if this element exists
for (x = 0; x < MAX_ELEMENTS; x++) {
// force compass to load anyways
if ( !Q_stricmp( token.string, hude[x].name ) ) {
//if ( !Q_stricmp( token.string, hude[x].name ) ) {
// first check to see if we have only 1 param!
if ( hude[x].params == 1 ) {
cg.hud2[hude[x].element][0][0] = token.intvalue;
} else if ( hude[x].dimensions == 1 ) {
for (y = 0; y < hude[x].params; y++) {
saved = token;
if ( !trap_PC_ReadToken( handle, &token ) ) {
CG_Printf("Error reading after token '%s'
", saved.string);
return;
}
cg.hud2[hude[x].element][0][y] = token.intvalue;
}
} else {
for ( y = 0; y <= hude[x].dimensions; y++ ) {
for (z = 0; z < hude[x].params; z++ ) {
saved = token;
if ( !trap_PC_ReadToken( handle, &token ) ) {
CG_Printf("Error reading after token '%s'
", saved.string);
return;
}
cg.hud2[hude[x].element][y][z] = token.intvalue;
}
}
}
}
}
}
}
}
}
trap_PC_FreeSource( handle );
}
In cg_local.h add the following code before the cg_t struct.
#define HUDPARAMS 4
#define HUDDEPTH 3
typedef enum hud_s {
H_NULL,
H_HEALTHBAR,
H_STAMINABAR,
H_CHARGEBAR,
H_COMPASS,
H_HP,
H_XP,
H_SKILLPICS,
H_SKILLTEXTS,
H_SKILLBOXES,
H_OVERHEAT,
H_WEAPONCARD,
H_FIRETEAM,
H_AMMO,
H_CP,
H_BP,
H_HEAD,
H_STANCE,
H_FLAG,
H_TREASURE,
H_PM,
H_PMBIG,
H_UPPERRIGHT,
H_CASH,
MAX_ELEMENTS
} hud_e;
typedef struct helements_s {
char *name;
int element;
int params;
int dimensions;
} helements_t;
EDIT: I forgot the sample hud 
hud/default.dat
// HUD ELEMENTS
version 2.0
elements {
"staminabar" 4 403 12 // x y size
"chargebar" 622 360 16 // x y size
"healthtext" 606 474 22 // x y scale
"xptext" 153 465 22 // x y scale
"compass" 275 383 90 90 // x y width height
"upperright" 25 20 // y
"skillpic" 180 460 14 200 460 14 220 460 14
"skilltext" 183 453 20 203 453 20 223 453 20
"overheat" 285 254 70 14 // x y width height
"weaponcard" 558 424 60 // x y size
"ammocount" 618 420 25 // x y scale
"fireteam" 10 20 180 // x y size
"cptext" 640 300 // x y
"bptext" 5 15 // x y
"stance" 615 65 56 56 // x y width height
"flag" 20 405 16 // x y size
"treasure" 580 370 36 // x y size
"pmitems" 4 360 20 // x y scale
"bigpmitems" 636 270 22 // x y scale
"head" 666 666 666 666
"healthbar" 666 666 666
"cash" 510 470 45
}