I will also note that I will be taking a different approach to my tutorials from here on in. Most of the teaching will be done through the use of comments in the code. I have colored them green to make it easier for you.
First things first open up cg_draw.c and head over to line number 517. We will be adding all new code from here on.
Add the following code :
/*
==============
CG_DrawSmallField
Draws small numbers for status bar and powerups.
==============
*/
static void CG_DrawSmallField (int x, int y, int width, int value)
{
char num[16], *ptr;
int l;
int frame;
if ( width < 1 ) {
return;
}
// draw number string
if ( width > 5 ) {
width = 5;
}
switch ( width ) {
case 1:
value = value > 9 ? 9 : value;
value = value < 0 ? 0 : value;
break;
case 2:
value = value > 99 ? 99 : value;
value = value < -9 ? -9 : value;
break;
case 3:
value = value > 999 ? 999 : value;
value = value < -99 ? -99 : value;
break;
case 4:
value = value > 9999 ? 9999 : value;
value = value < -999 ? -999 : value;
break;
}
Com_sprintf (num, sizeof(num), "%i", value);
l = strlen(num);
if (l > width)
l = width;
x += 2 + CHAR_WIDTH/3*(width - l);
ptr = num;
while (*ptr && l)
{
if (*ptr == '-')
frame = STAT_MINUS;
else
frame = *ptr -'0';
CG_DrawPic( x,y, CHAR_WIDTH/3, CHAR_HEIGHT/3, cgs.media.numberShaders[frame] );
x += CHAR_WIDTH/3;
ptr++;
l--;
}
}
WHAT WE DID
We made a copy of the DrawField function from cg_drawtools.c, and added some new code to make the numbers display a little bit smaller. The code we added is colored green.
Underneath our new function paste this :
/*
==============
CG_DrawFrameRect
This draws a rectangular frame with a border.
==============
*/
static void CG_DrawFrameRect(int x, int y, int w, int h, int size, const float *color1, const float *color2)
{
// trap our first color
trap_R_SetColor(color1);
// draw back layer first
CG_FillRect(x, y, w, h, color1);
// reset colors
trap_R_SetColor(NULL);
// trap our second color
trap_R_SetColor(color2);
// draw borders
CG_DrawRect(x, y, w, h, size, color2);
// reset colors
trap_R_SetColor(NULL);
}
WHAT WE DID
We made a function that will draw a box of any given height and width, and color it, and position it where we specify.
Now for the heart of the beast, add this below what we just added :
// MAIN DRAWING FUNCTIONS
// CG_DrawAmmoBar : Draws our ammo bar
/*
==============
CG_DrawAmmoBar
This draws our nice ammo bar
==============
*/
static void CG_DrawAmmoBar( void )
{
/*-------------------------------------------------------------
// Setting it all up
//-----------------------------------------------------------*/
qhandle_t icon[8]; // Create an array for our icons
playerState_t *ps; // Create a playerstate
int i = 0; // we will use these in our loop
int iconNum = 0; // this will be used for icon numbers
int y = 105; // this will be used for our y location for our icons
int value[8]; // this is our array for our ammo amounts
int valueNum = 0; // this will be used for our ammo amounts
// set up our color array
static float colors[2][4] = {
{ 1.0f, 1.0f, 1.0f, 1.0f }, // White
{ 0.0f, 0.0f, 0.0f, 0.5f } // Black
};
ps = &cg.snap->ps; // initialize our player state
// Set up our icon array
icon[0] = cg_weapons[WP_MACHINEGUN].ammoIcon;
icon[1] = cg_weapons[WP_SHOTGUN].ammoIcon;
icon[2] = cg_weapons[WP_GRENADE_LAUNCHER].ammoIcon;
icon[3] = cg_weapons[WP_ROCKET_LAUNCHER].ammoIcon;
icon[4] = cg_weapons[WP_LIGHTNING].ammoIcon;
icon[5] = cg_weapons[WP_RAILGUN].ammoIcon;
icon[6] = cg_weapons[WP_PLASMAGUN].ammoIcon;
icon[7] = cg_weapons[WP_BFG].ammoIcon;
// set up our ammo amount array
value[0] = ps->ammo[WP_MACHINEGUN];
value[1] = ps->ammo[WP_SHOTGUN];
value[2] = ps->ammo[WP_GRENADE_LAUNCHER];
value[3] = ps->ammo[WP_ROCKET_LAUNCHER];
value[4] = ps->ammo[WP_LIGHTNING];
value[5] = ps->ammo[WP_RAILGUN];
value[6] = ps->ammo[WP_PLASMAGUN];
value[7] = ps->ammo[WP_BFG];
/*-------------------------------------------------------------
// Draw It All
//-----------------------------------------------------------*/
// Draw Ammo String Container
CG_DrawFrameRect(0, 75, 100, 20, 1, colors[1], colors[0]);
// Draw Ammo Icon and Ammo Amounts container
CG_DrawFrameRect(0, 96, 100, 175, 1, colors[1], colors[0]);
// OK our basic layout is set up, lets add some content :)
// Lets add some text to our little box up top
CG_DrawStringExt(10, 80, "Ammo", colors[0], qfalse, qfalse, 10, 10, 8);
// Ok lets go ahead and add the ammo icons and the ammounts.
// Here we use a for loop to draw the icons to the screen
for(i = 0; i < 8; i++) // for i = 0, i is less than 8, and increment i by 1 each pass
{
CG_DrawPic( 10, y, 16, 16, icon[iconNum] ); // draw our icons
CG_DrawSmallField ( 50, y, 3, value[valueNum] ); // draw our ammo ammounts
y += 20; // increment y by 20
iconNum++; // increment iconNum by 1
valueNum++; // increment valueNum by 1
} // when the loop realizes that it has reached 8, it will exit out.
}
Whew, that was hefty.
Dont worry, the next peice of code is only one line.
Scroll down to CG_DrawStatusBar:
/*
================
CG_DrawStatusBar
================
*/
#ifndef MISSIONPACK
static void CG_DrawStatusBar( void )
Now paste this after the first If statement :
CG_DrawAmmoBar(); // Draw our ammo bar
And there we have it. Compile the source, and run the mod. You should have a nifty frame on the left hand side displaying all our ammo.
Stay tuned for Chapter B of this two part epic, we will be adding a cvar that allows us to toggle our ammo box. I will also be introducing you to the UI project, and how to add custom controls.
Happy Fragging.
PSYKoR3
