Main  |  Maps  |  Programming | Links |  Files |  Demos |  Forums

This tut shows how to make an in-game keypress menu( it's a menu that pops up and asks you what team you want to join in spectator mode, easily modified for use while actually playing ). The code is WELL documented, so I am just gonna tell you where to paste it, then you read it :) The best thing about this menu format is that it is SO easy to add new commands and such. I have had this code done for quite some time, but it had 1 bug. Thanks to RR2D02 for showing me the nice little CG_Weapon_f hack :) Here we go!

First off, go into cg_local.h and lets declare our functions and add a variable. Go to about line 613 and find:

	// development tool
refEntity_t testModelEntity;
char testModelName[MAX_QPATH];
qboolean testGun;

Add right under it:

	// inolen
// is spec menu on?
qboolean specMenu;

Now go to about line 1261 and find:

qhandle_t CG_StatusHandle(int task);

Add this up under it:

// inolen
// Declare our functions
void CG_DrawSpecMenu( void );
void CG_SpecMenuCmd( int num );

Now go into cg_weapons.c and at about line 1393 find:

	num = atoi( CG_Argv( 1 ) );

Up under it add:

	// inolen
// Leech user's input key
if( cg.specMenu == qtrue ) {
CG_SpecMenuCmd( num );
return;
}

Now its onto cg_draw.c to add in the last 2 bits of code, first lets add the little bit, then the huge bit :) So find:

if ( cg.snap->ps.persistant[PERS_TEAM] == TEAM_SPECTATOR ) {
CG_DrawSpectator();
CG_DrawCrosshair();
CG_DrawCrosshairNames();

And up under it add:

		CG_DrawSpecMenu();

Now, for the core code! Go find:

/*
=================
CG_DrawVote
=================
*/

And directly ABOVE it add:

/*
=========================================================
inolen's in-game menu system
If you are a newbie to programming,
this is quite a bit of code to take in.
I have documented this code pretty well,
so I would suggest reading it.
As always if you have any problems, e-mail me at:
admin@inolen.com
http://www.inolen.com
And remember, if you use this code in your mod,
credit me for it!
=========================================================
*/
// the text's height
#define TEXT_HEIGHT 10
// the struct to hold our menu information
// hence the name of it, menuInfo :)
typedef struct
{
int number;
char *string;
vec4_t *color;
char *command;
} menuInfo;
// this array holds what    will be in the specMenu
    menuInfo specMenu[] = { 
    // Edit this to add new choices in your menu
    // here are what the fields do:
    // 1. This is the number the choice
    // is in the menu
    // 2. The text to appear for the choice
    // 3. What color it is
    // 4. What command to execute when the user
    // selects it.
    { 1, "Team Red", &colorWhite, "team r" },
    { 2, "Team Blue", &colorWhite, "team b" },
    { 3, "Team Free", &colorWhite, "team f" },
    // This lets the CG_DrawSpecMenu know
    // there is no more to draw
    {0, NULL}
    };
// Function we use to    make drawing any text for the menu easier
    void CG_DrawMenuText( int x, int y, const char *s, vec4_t color ) {
    CG_DrawStringExt( x, y, s, color, qfalse, qfalse, TEXT_HEIGHT, 12, 0 );
    }
/*
    =================
    CG_DrawSpecMenu
    Draws the spec menu
    =================
    */
    void CG_DrawSpecMenu( void ) {
    vec4_t color;
    char *menuString;
    int n;
    int w = 125;
    // Amount of items in the menu
    int count = 3;
    int h = 230 - (( count * TEXT_HEIGHT+1 )/2);
    int y = 240 - (( count * TEXT_HEIGHT+1 )/2);
 // lets CG_Weapon_f    know to
    // use the users keys to make a selection
    cg.specMenu = qtrue;
    
    // color of the menu's background
    color[0] = 0.00f;
    color[1] = 0.75f;
    color[2] = 0.25f;
    color[3] = 0.33f;
    
    // draw the rectangular background
    CG_FillRect( 0, h, w, 480-( h * 2 ), color );
 // goes through all    the choices in our menu
    // and draws them
    for(n = 0; specMenu[n].string; n++) {
    // tells it to stop when it reaches
    // the choice with the text of NULL
    if(specMenu[n].string == NULL) { 
    return;
    }
    // Combines the selection's # and
    // it't text string into a string to draw
    menuString = va("%i.%s", specMenu[n].number, specMenu[n].string );
    // Draws it with our above function
    CG_DrawMenuText(0, y, menuString, *specMenu[n].color );
    // add to the y number so next time it draws
    // a selection, it is below the first one
    y += TEXT_HEIGHT+1;
    }
    }
/*
    =================
    CG_SpecMenuCmd
    =================
    */
    void CG_SpecMenuCmd( int num ) {
    int n;
   // goes through all the choices in our menu
// and matches the incoming choice to
// the choice's command for(n = 0; specMenu[n].command; n++) { // tells it to stop when it reaches // the choice with the text of NULL if(specMenu[n].command == NULL) { return; } // found the right choice if( num == specMenu[n].number ) { // Execute the command trap_SendClientCommand( specMenu[n].command ); // Tells CG_Weapon_f to not monitor keys anymore cg.specMenu = qfalse; } } }

Thats it, compile and enjoy!

I spend my time programming and writing these tutorials, so please feel free to use this code in your mod as long as www.inolen.com and the author receive credit.

Design Copyright inolen 2000