Menu Addon

A modification for the Menu tutorial; This allows you to update a single line of the menu and not worry about the others. This tut means you have to remember to do slightly more with the selection function which is why I havn't just intergrated it into the original.

I got this idea while considering ways to get angles from the player for cameras and such. You can use it to create menus which change a value, and do it repeatedly.

You MUST have done the menu tut before doing this. If you have implemented any menus before doing this tut, you MUST have converted them to the new format before running the mod. It should compile without a problem if you don't but it will not work properly. I just don't want emails saying 'this doesn't work' when the person sending it didn't read this paragraph


The first change you need to do is to modify menuselect function in menu.c. We no longer want the menu cleared when an option is selected. so change the function to read as below

void menuselect(edict_t *ent)
{
ent->client->menustorage.optionselected(ent,ent->client->menustorage.messages[ent->client->menustorage.currentline].option);
 // call the select function with the value that has been alocated for that selection.
}

What these means is that the clean up functions are going to have to be called in the option selected code for each menu. as we have a function for closing menus, we may as well put the code in that so we only need a single function call

find close menu in menu.c; Modify it to read

void closemenu(edict_t *ent)
{
 
ent->client->menustorage.optionselected=NULL;
clearmenu(ent);
ent->client->showscores = false;
ent->client->menustorage.menu_active = false;
ent->client->menustorage.displaymsg = false;
ent->client->showinventory = false;
 
 
}

now, when you are finished with the menu (the user selects a finishing option [or any option depending on the menu]) call closemenu from the selected-option function


Now down to the meat of the tutorial. Add the function below to menu.c; position isn't important as long as you don't get stupid and stick it within one of the other functions :)

void changeline(edict_t *ent,int linenum ,char *line,int option)
{
if (linenum>(ent->client->menustorage.num_of_lines))
               return; // no changing lines that don't exist :)
 
sprintf(ent->client->menustorage.messages[linenum].msg,"%-21s",line); // copies the first 21 characters to the storage string. the 22nd character is for the delimiting '/0'
ent->client->menustorage.messages[linenum].option=option;
 
}

remember to call showmenu after redefining the menu to show the results.

add the line below to menu.h it's just a prototype of the function above, so you can use it anywhere

void changeline(edict_t *ent,int linenum ,char *line,int option);

And thats us done. Here is an example of what I am doing. replace the functions in menu.c with the same names as these two to see how it works.

void testmenuhandler(edict_t *ent,int option)
{
char *line;
switch (option)
{
case 1:
ent->health+=5;
break;
case 2:
ent->health-=5;
break;
case 3:
closemenu(ent);
return;
break;
default:
gi.centerprintf(ent,"fuckup\n");
}
sprintf(line,"%d",ent->health); // just copies the players health
changeline(ent,4,line,0);
showmenu(ent);
 
}
 
 
 
 
 
void Menu_test(edict_t *ent)
{
char *line;
 
 
   if (ent->client->showscores || ent->client->showinventory || ent->client->menustorage.menu_active)
        return;
 
sprintf(line,"%d",ent->health); // just copies the players health
 
clearmenu(ent);
addlinetomenu(ent,"This is a test menu,",0);
addlinetomenu(ent,"for setting your health",0);
 
addlinetomenu(ent,"Health Up 5",1);
addlinetomenu(ent,line,0);
addlinetomenu(ent,"Health Down 5",2);
addlinetomenu(ent,"Exit",3);
setmenuhandler(ent,testmenuhandler);
ent->client->menustorage.currentline=3;
showmenu(ent);
 
}

Try it :)


Skunkworks Tutorial