Adding items to the Controls Menu
by Gum-Lass
In this tutorial we will:
- Add a new subsection to the controls menu.
- Add a binding for the grappling hook to it.
The finished
product will be something like this:
First,
all the modifications will be made in ui_controls2.c
- Red indicates lines that have been added or
changed.
- Blue indicates lines from the original code.
Now first we are going to add a new sub-section to the menu.
Because I'm doing the Running Man mod, I'll call it "RUN". So the new controls
menu will go:
Then we are going to add a bindable action to the RUN section
of the menu.
Firstly, we must change the #defines :
This may seem like
a waste of time, but it will help if you want to add other sub-sections.
Add
this near the top of the file.
// GLs : This is the
centre of the menu. I defined it so I could add more menus later. ;)
#define
RM_CONTROLS_MENUMIDDLE 240
where it says "control sections", add the
C_RUN #define and change the C_MAX #define
//
control sections
#define C_MOVEMENT 0
#define C_LOOKING 1
#define
C_WEAPONS 2
#define C_MISC 3
#define C_RUN 4 // GLs : The
Running Man menu.
#define C_MAX 5
Then in the next
section:
Notice how you have to add 1 to each of the #defines below ID_RUN.
#define ID_MOVEMENT 100
#define ID_LOOKING
101
#define ID_WEAPONS 102
#define ID_MISC 103
#define
ID_RUN 104 // GLs : The Running Man Menu.
#define ID_DEFAULTS 105
#define
ID_BACK 106
#define ID_SAVEANDEXIT 107
#define ID_EXIT
108
Then below ID_CHAT4, we will define our grapple as
ID_WEAPON10.
#define ID_CHAT2 31
#define ID_CHAT3
32
#define ID_CHAT4 33
#define ID_WEAPON10 34 // GLs :
Next bindable action.
Again in the next section you
must add 1 to all of the #defines
// all others GLs : +1
added to all due to Grappling hook.
#define ID_FREELOOK 35
#define
ID_INVERTMOUSE 36
#define ID_ALWAYSRUN 37
#define ID_AUTOSWITCH
38
#define ID_MOUSESPEED 39
#define ID_JOYENABLE 40
#define
ID_JOYTHRESHOLD 41
#define ID_SMOOTHMOUSE 42
Now in the
struct that follows add a line for the runningman sub-menu.
menutext_s weapons;
menutext_s misc;
menutext_s
runningman; // GLs : The Running Man submenu
menuaction_s
walkforward;
. . . and another like this . . .
menuaction_s chat3;
menuaction_s chat4;
menuradiobutton_s
joyenable;
menuslider_s joythreshold;
menuaction_s
grap_hook; // GLs : The Grappling Hook.
int section;
qboolean
waitingforkey;
char playerModel[64];
Now we'll add the
binding data in the bind_t array, g_bindings[]
Add a line like this at the
bottom of the declaration . . .
{"messagemode2","chat -
team", ID_CHAT2, ANIM_CHAT,-1,-1,-1,-1},
{"messagemode3","chat - target",
ID_CHAT3, ANIM_CHAT,-1,-1,-1, -1},
{"messagemode4","chat - attacker",
ID_CHAT4, ANIM_CHAT,-1,-1,-1,-1},
//GLs : Grappling Hook
Added as weapon 10.
{"weapon 10", "Grappling Hook", ID_WEAPON10,
ANIM_WEAPON10, '0',-1,-1,-1},
{(char*)NULL, (char*)NULL, 0, 0,
-1,-1,-1,-1},
Note: the first field is the command you want to
bind, the second is the name you want to show up in the menu, the third is the
#define of the weapon (we added that at the start of this tut), the fourth is
the #define of the animation you want to play while selected. The fifth is the
default key you want it to be bound to. The sixth is the default alternate key
you would like the command to be bound to. The last 2 you should leave as -1
because this is where the menu system will store the keys users will
bind.
Next, we want to add our binding to a group. The static
menucommon_s arrays are these groups. Because we want to add our binding to a
new group (the "run" sub-menu) we must declare a new group.
Add these lines
after the declaration of static menucommon_s *g_misc_controls[]
// GLs : The Running Man Menu.
static menucommon_s *g_rm_controls[]
= {
(menucommon_s
*)&s_controls.grap_hook,
NULL,
};
Then just below it add
this line to the next group.
static menucommon_s
**g_controls[] =
{
g_movement_controls,
g_looking_controls,
g_weapons_controls,
g_misc_controls,
g_rm_controls, // GLs : Adding it to the main
menu.
};
Add these lines in the Controls_Update(
void ) function.
// makes sure flags are right on the
group selection controls
s_controls.looking.generic.flags &=
~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
s_controls.movement.generic.flags
&=
~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
s_controls.weapons.generic.flags
&=
~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
s_controls.misc.generic.flags
&= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
//
GLs : Don't forget Running Man
s_controls.runningman.generic.flags &=
~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
s_controls.looking.generic.flags
|= QMF_PULSEIFFOCUS;
s_controls.movement.generic.flags |=
QMF_PULSEIFFOCUS;
s_controls.weapons.generic.flags |=
QMF_PULSEIFFOCUS;
s_controls.misc.generic.flags |= QMF_PULSEIFFOCUS;
// GLs : Don't forget Running Man here
either.
s_controls.runningman.generic.flags |=
QMF_PULSEIFFOCUS;
That sets the right flags so that
your new item will pulse if the mouse moves over it.
Now, go down to
about line 645 and add a section like this below case C_MISC like so:
case C_MISC:
s_controls.misc.generic.flags &=
~QMF_PULSEIFFOCUS;
s_controls.misc.generic.flags |=
(QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
break;
case
C_RUN:
s_controls.runningman.generic.flags &=
~QMF_PULSEIFFOCUS;
s_controls.runningman.generic.flags |=
(QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
break;
}
Now
we must change something in the void Controls_MenuEvent( void* ptr, int event )
function.
This is about line 1090.
As usual, add the lines in Red
case ID_MISC:
if (event ==
QM_ACTIVATED)
{
s_controls.section = C_MISC;
Controls_Update();
}
break;
// GLs : The
Running Man Menu
case ID_RUN:
if (event ==
QM_ACTIVATED)
{
s_controls.section = C_RUN;
Controls_Update();
}
break;
case ID_DEFAULTS:
if
(event == QM_ACTIVATED)
{
UI_ConfirmMenu( "SET TO DEFAULTS?",
Controls_ResetDefaults_Draw, Controls_ResetDefaults_Action
);
}
break;
Now you should be able to switch to your
menu when you click on it.
Now comes the bit where we actually add all
these things to the menu.
In the function void
Controls_MenuInit( void ) from about line 1245 change all the lines like
so.
s_controls.looking.generic.type =
MTYPE_PTEXT;
s_controls.looking.generic.flags =
QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
s_controls.looking.generic.id =
ID_LOOKING;
s_controls.looking.generic.callback =
Controls_MenuEvent;
s_controls.looking.generic.x = 152;
s_controls.looking.generic.y = RM_CONTROLS_MENUMIDDLE - 2 *
PROP_HEIGHT;
s_controls.looking.string =
"LOOK";
s_controls.looking.style = UI_RIGHT;
s_controls.looking.color =
color_red;
s_controls.movement.generic.type =
MTYPE_PTEXT;
s_controls.movement.generic.flags =
QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
s_controls.movement.generic.id =
ID_MOVEMENT;
s_controls.movement.generic.callback =
Controls_MenuEvent;
s_controls.movement.generic.x = 152;
s_controls.movement.generic.y = RM_CONTROLS_MENUMIDDLE -
PROP_HEIGHT;
s_controls.movement.string =
"MOVE";
s_controls.movement.style = UI_RIGHT;
s_controls.movement.color =
color_red;
s_controls.weapons.generic.type =
MTYPE_PTEXT;
s_controls.weapons.generic.flags =
QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
s_controls.weapons.generic.id =
ID_WEAPONS;
s_controls.weapons.generic.callback =
Controls_MenuEvent;
s_controls.weapons.generic.x = 152;
s_controls.weapons.generic.y =
RM_CONTROLS_MENUMIDDLE;
s_controls.weapons.string =
"SHOOT";
s_controls.weapons.style = UI_RIGHT;
s_controls.weapons.color =
color_red;
s_controls.misc.generic.type =
MTYPE_PTEXT;
s_controls.misc.generic.flags =
QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
s_controls.misc.generic.id =
ID_MISC;
s_controls.misc.generic.callback =
Controls_MenuEvent;
s_controls.misc.generic.x = 152;
s_controls.misc.generic.y = RM_CONTROLS_MENUMIDDLE +
PROP_HEIGHT;
s_controls.misc.string = "MISC";
s_controls.misc.style
= UI_RIGHT;
s_controls.misc.color = color_red;
// GLs
: Initializing the Running Man Menu.
s_controls.runningman.generic.type =
MTYPE_PTEXT;
s_controls.runningman.generic.flags =
QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
s_controls.runningman.generic.id =
ID_RUN;
s_controls.runningman.generic.callback =
Controls_MenuEvent;
s_controls.runningman.generic.x =
152;
s_controls.runningman.generic.y = RM_CONTROLS_MENUMIDDLE + 2 *
PROP_HEIGHT; // so it's below misc
s_controls.runningman.string = "RUN"; //
GLs : Maybe try "RUNNING MAN" later?
s_controls.runningman.style =
UI_RIGHT;
s_controls.runningman.color =
color_blue;
Then further down at about line 1430, do
like this.
s_controls.bfg.generic.type =
MTYPE_ACTION;
s_controls.bfg.generic.flags =
QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_GRAYED|QMF_HIDDEN;
s_controls.bfg.generic.callback
= Controls_ActionEvent;
s_controls.bfg.generic.ownerdraw =
Controls_DrawKeyBinding;
s_controls.bfg.generic.id = ID_WEAPON9;
// GLs : Running Man's Grappling
Hook
s_controls.grap_hook.generic.type =
MTYPE_ACTION;
s_controls.grap_hook.generic.flags =
QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_GRAYED|QMF_HIDDEN;
s_controls.grap_hook.generic.callback
= Controls_ActionEvent;
s_controls.grap_hook.generic.ownerdraw =
Controls_DrawKeyBinding;
s_controls.grap_hook.generic.id =
ID_WEAPON10;
s_controls.attack.generic.type =
MTYPE_ACTION;
s_controls.attack.generic.flags =
QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_GRAYED|QMF_HIDDEN;
s_controls.attack.generic.callback
= Controls_ActionEvent;
s_controls.attack.generic.ownerdraw =
Controls_DrawKeyBinding;
s_controls.attack.generic.id =
ID_ATTACK;
We're almost done, I know it's been long, but we're
getting close.
At about line 1610 add the following
Menu_AddItem( &s_controls.menu, &s_controls.looking
);
Menu_AddItem( &s_controls.menu, &s_controls.movement
);
Menu_AddItem( &s_controls.menu, &s_controls.weapons
);
Menu_AddItem( &s_controls.menu, &s_controls.misc );
// GLs : The Running Man sub-menu
Menu_AddItem(
&s_controls.menu, &s_controls.runningman
);
Then this at about line 1660
Menu_AddItem( &s_controls.menu, &s_controls.chat2
);
Menu_AddItem( &s_controls.menu, &s_controls.chat3
);
Menu_AddItem( &s_controls.menu, &s_controls.chat4 );
// GLs : Now Stuff on the Running Man Menu
Menu_AddItem(
&s_controls.menu, &s_controls.grap_hook );
Menu_AddItem(
&s_controls.menu, &s_controls.back );
And then we're
finished. Phew. That took a while.
Anyway, I hope this was helpful for
everyone. I know it had me buggered for quite some time. I was beginning to
think there was an engine limited number of items one could have on a menu.
Luckily, Barry (SoWat!) helped me out and so did DrooG. It turned out all I had wrong was that I just added
the grapple define after the last defined thing. BIG MISTAKE. You actually have
to add it after the bindable actions and add 1 to all the other defines. That is
:
DO NOT JUST ADD #define ID_WEAPON10 42
We'll anyway, I hope this has
been helpful.
If you have any questions (or if I've buggered up this
tutorial.), e-mail me (Gum-Lass) at benjamin.horn@studentmail.newcastle.edu.au
and let me know what you think. Also, please check out my mod, "The Running
Man", at http://www.geocites.com/gumlass.