Page 1 of 1
How to load different control configs
Posted: Wed Apr 15, 2009 9:58 am
by Herr W
Hi, me again, this time with a probably more challenging question!
It's about the cellphone version of Quake3/Monkeys of Doom. I think it would be good to give the player the option to choose between easy controls (freelook "off", moving and aiming is bind to the accellerometer, mostly intuitive) and advanced controls, bringing the d-pad into game (for moving and strafing).
Maybe it could be bound to a radio button in the settings menu ("Advanced Controls On/Off"). My guess is, that it works like the "ResetDefaults_Action" in ui_setup:
Code: Select all
/*
=================
Setup_ResetDefaults_Action
=================
*/
static void Setup_ResetDefaults_Action( qboolean result ) {
if( !result ) {
return;
}
trap_Cmd_ExecuteText( EXEC_APPEND, "exec default.cfg\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
}
Probably like this...
Code: Select all
#define ID_ADVANCED 17
#define ID_EASY 18
Code: Select all
/*
=================
Controls_AdvancedConfig_Action
=================
*/
static void Setup_AdvancedConfig_Action( qboolean result ) {
if( !result ) {
return;
}
trap_Cmd_ExecuteText( EXEC_APPEND, "exec advanced.cfg\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
}
... and this...
Code: Select all
/*
=================
Controls_EasyConfig_Action
=================
*/
static void Setup_EasyConfig_Action( qboolean result ) {
if( !result ) {
return;
}
trap_Cmd_ExecuteText( EXEC_APPEND, "exec easy.cfg\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
}
... To load either "advanced.cfg" or "easy.cfg". Okay, doesn't involve a radio button so far, but that's not the most important thing.
Before I start messing up the code it would be good to know if this is generally the right way!

Re: How to load different control configs
Posted: Wed Apr 15, 2009 1:44 pm
by ^misantropia^
If you're going to use an actual radio button, you'll need to a somewhat different approach. Check out e.g. Preferences_Event() in q3_ui/ui_preferences.c
Re: How to load different control configs
Posted: Wed Apr 15, 2009 4:22 pm
by Herr W
Okay, lots of radio buttons in there! Let's see what I need for a new one in ui_controls...
1.
2.
3.
Code: Select all
s_controls.advancedcfg.curvalue = trap_Cvar_VariableValue( "cg_advancedcfg" ) != 0;
Hm... That part should probably look more like...
Code: Select all
trap_Cmd_ExecuteText( EXEC_APPEND, "exec advanced.cfg\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
... from Setup_ResetDefaults_Action (ui_setup).
4.
Code: Select all
case ID_ADVANCEDCFG:
UI_ConfirmMenu( "DOESNTMATTERWHAT TEXT", Controls_AdvancedCfg_Action );
break;
The confirm dialog is skipped, but after that nothing happens so far...
5. Hm... something like the following appeared already, so one of both must be too much:
Code: Select all
/*
=================
Controls_SetAdvanced_Action
=================
*/
static void Setup_SetAdvanced_Action( qboolean result ) {
if( !result ) {
return;
}
trap_Cmd_ExecuteText( EXEC_APPEND, "exec advance.cfg\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");
trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
}
What confuses me is that ui_controls2 already includes something similar...
Code: Select all
/*
=================
Controls_ResetDefaults_Action
=================
*/
static void Controls_ResetDefaults_Action( qboolean result ) {
if( !result ) {
return;
}
s_controls.changesmade = qtrue;
Controls_SetDefaults();
Controls_Update();
}
/*
=================
Controls_ResetDefaults_Draw
=================
*/
static void Controls_ResetDefaults_Draw( void ) {
UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 0, "WARNING: This will reset all", UI_CENTER|UI_SMALLFONT, color_yellow );
UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 1, "controls to their default values.", UI_CENTER|UI_SMALLFONT, color_yellow );
}
... But I can't find it which case the reset is executed, as there is no "Reset to Defaults" button or anything.
5.
Code: Select all
s_controls.advancedcfg.generic.type = MTYPE_RADIOBUTTON;
s_controls.advancedcfg.generic.flags = QMF_SMALLFONT;
s_controls.advancedcfg.generic.x = SCREEN_WIDTH/2;
s_controls.advancedcfg.generic.name = "Advanced Controls";
s_controls.advancedcfg.generic.id = ID_ADVANCEDCFG;
s_controls.advancedcfg.generic.callback = Controls_MenuEvent;
s_controls.advancedcfg.generic.statusbar = Controls_StatusBar;
6.
Code: Select all
Menu_AddItem( &s_controls.menu, &s_controls.advancedcfg );
I'm pretty sure that 3. and 5. won't work together. And I wonder if there isn't already something prepared in the code to set the controls to given keys...
Re: How to load different control configs
Posted: Wed Apr 15, 2009 6:46 pm
by ^misantropia^
Herr W wrote:... But I can't find it which case the reset is executed, as there is no "Reset to Defaults" button or anything.

But there is (in the stock and ioquake3 source, at least) - SETUP

DEFAULTS - and the executed action is Setup_ResetDefaults_Action().
Re: How to load different control configs
Posted: Wed Apr 15, 2009 6:48 pm
by ^misantropia^
Oh, and the case is around line 138 in q3_ui/ui_setup.c, look for ID_DEFAULTS.
Re: How to load different control configs
Posted: Thu Apr 16, 2009 8:14 am
by Herr W
I'd found that one already! Haven't tried it out, but the warning text says "This will reset *ALL* options".
The confusing thing - at least for me - is that the "controls" submenu has it's own ResetDefaults part...
Code: Select all
/*
=================
Controls_ResetDefaults_Action
=================
*/
static void Controls_ResetDefaults_Action( qboolean result ) {
if( !result ) {
return;
}
s_controls.changesmade = qtrue;
Controls_SetDefaults();
Controls_Update();
}
/*
=================
Controls_ResetDefaults_Draw
=================
*/
static void Controls_ResetDefaults_Draw( void ) {
UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 0, "WARNING: This will reset all", UI_CENTER|UI_SMALLFONT, color_yellow );
UI_DrawProportionalString( SCREEN_WIDTH/2, 356 + PROP_HEIGHT * 1, "controls to their default values.", UI_CENTER|UI_SMALLFONT, color_yellow );
}
... but lacks a button to execute it.
Some lines above is a table which seems to provide the default keybindings...
Code: Select all
static bind_t g_bindings[] =
{
{"+scores", "show scores", ID_SHOWSCORES, ANIM_IDLE, K_TAB, -1, -1, -1},
{"+button2", "use item", ID_USEITEM, ANIM_IDLE, K_ENTER, -1, -1, -1},
{"+speed", "run / walk", ID_SPEED, ANIM_RUN, K_SHIFT, -1, -1, -1},
...
... but I have no idea if or how it is connected with Controls_ResetDefaults_Action. (At least it makes me assume that there might be two ways to access preset configurations: from a table inside the code or an external .cfg file).
Still pretty mysterious...

Re: How to load different control configs
Posted: Mon Apr 20, 2009 9:37 am
by Herr W
This part looks promising (in ui_controls2):
Code: Select all
/*
=================
Controls_SetDefaults
=================
*/
static void Controls_SetDefaults( void )
{
int i;
bind_t* bindptr;
// set the bindings from the local store
bindptr = g_bindings;
// iterate each command, set its default binding
for (i=0; ;i++,bindptr++)
{
if (!bindptr->label)
break;
bindptr->bind1 = bindptr->defaultbind1;
bindptr->bind2 = bindptr->defaultbind2;
}
s_controls.invertmouse.curvalue = Controls_GetCvarDefault( "m_pitch" ) < 0;
s_controls.smoothmouse.curvalue = Controls_GetCvarDefault( "m_filter" );
s_controls.alwaysrun.curvalue = Controls_GetCvarDefault( "cl_run" );
s_controls.autoswitch.curvalue = Controls_GetCvarDefault( "cg_autoswitch" );
s_controls.sensitivity.curvalue = Controls_GetCvarDefault( "sensitivity" );
s_controls.joyenable.curvalue = Controls_GetCvarDefault( "in_joystick" );
s_controls.joythreshold.curvalue = Controls_GetCvarDefault( "joy_threshold" );
s_controls.freelook.curvalue = Controls_GetCvarDefault( "cl_freelook" );
}
I think I may need to create something similar with "Easy" and "Advanced" instead of "Default". But I'm still not sure where the related values are stored. Maybe in that table I mentioned above ("g_bindings")? And if so, can I simply create two new tables, for example "g_easybindings" and "g_advancedbindings"?
Hm... But getting the settings from external cfg-files might be more comfortable if something has to be altered afterwards... And there's still no radiobutton involved at all... Tough!
Re: How to load different control configs
Posted: Mon Apr 20, 2009 5:46 pm
by ^misantropia^
I'm not a cruel guy. The below diff (run against q3_ui/ui_preferences.c) should give you a nice handle.
Code: Select all
Index: ui_preferences.c
===================================================================
--- ui_preferences.c (revision 1528)
+++ ui_preferences.c (working copy)
@@ -39,6 +39,8 @@
#define PREFERENCES_X_POS 360
+#define MOD_ADVANCED_CONTROLS 1337
+
#define ID_CROSSHAIR 127
#define ID_SIMPLEITEMS 128
#define ID_HIGHQUALITYSKY 129
@@ -62,6 +64,8 @@
menubitmap_s framel;
menubitmap_s framer;
+ menuradiobutton_s mod_advanced_controls;
+
menulist_s crosshair;
menuradiobutton_s simpleitems;
menuradiobutton_s brass;
@@ -91,6 +95,7 @@
static void Preferences_SetMenuItems( void ) {
s_preferences.crosshair.curvalue = (int)trap_Cvar_VariableValue( "cg_drawCrosshair" ) % NUM_CROSSHAIRS;
+ s_preferences.mod_advanced_controls.curvalue = trap_Cvar_VariableValue( "mod_advanced_controls" ) != 0;
s_preferences.simpleitems.curvalue = trap_Cvar_VariableValue( "cg_simpleItems" ) != 0;
s_preferences.brass.curvalue = trap_Cvar_VariableValue( "cg_brassTime" ) != 0;
s_preferences.wallmarks.curvalue = trap_Cvar_VariableValue( "cg_marks" ) != 0;
@@ -165,6 +170,24 @@
case ID_BACK:
UI_PopMenu();
break;
+
+ case MOD_ADVANCED_CONTROLS:
+ {
+ const char *config;
+ if (s_preferences.mod_advanced_controls.curvalue)
+ {
+ config = "advanced.cfg";
+ }
+ else
+ {
+ config = "easy.cfg";
+ }
+ trap_Cvar_SetValue("mod_advanced_controls", s_preferences.mod_advanced_controls.curvalue);
+ trap_Cmd_ExecuteText(EXEC_APPEND, va("exec %s\n", config));
+ //trap_Cmd_ExecuteText(EXEC_APPEND, "cvar_restart\n");
+ trap_Cmd_ExecuteText(EXEC_APPEND, "vid_restart\n");
+ }
+ break;
}
}
@@ -265,6 +288,15 @@
s_preferences.crosshair.generic.left = PREFERENCES_X_POS - ( ( strlen(s_preferences.crosshair.generic.name) + 1 ) * SMALLCHAR_WIDTH );
s_preferences.crosshair.generic.right = PREFERENCES_X_POS + 48;
+ y += BIGCHAR_HEIGHT+2;
+ s_preferences.mod_advanced_controls.generic.type = MTYPE_RADIOBUTTON;
+ s_preferences.mod_advanced_controls.generic.name = "Advanced controls:";
+ s_preferences.mod_advanced_controls.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
+ s_preferences.mod_advanced_controls.generic.callback = Preferences_Event;
+ s_preferences.mod_advanced_controls.generic.id = MOD_ADVANCED_CONTROLS;
+ s_preferences.mod_advanced_controls.generic.x = PREFERENCES_X_POS;
+ s_preferences.mod_advanced_controls.generic.y = y;
+
y += BIGCHAR_HEIGHT+2+4;
s_preferences.simpleitems.generic.type = MTYPE_RADIOBUTTON;
s_preferences.simpleitems.generic.name = "Simple Items:";
@@ -373,6 +405,7 @@
Menu_AddItem( &s_preferences.menu, &s_preferences.framer );
Menu_AddItem( &s_preferences.menu, &s_preferences.crosshair );
+ Menu_AddItem( &s_preferences.menu, &s_preferences.mod_advanced_controls );
Menu_AddItem( &s_preferences.menu, &s_preferences.simpleitems );
Menu_AddItem( &s_preferences.menu, &s_preferences.wallmarks );
Menu_AddItem( &s_preferences.menu, &s_preferences.brass );
Re: How to load different control configs
Posted: Mon Apr 20, 2009 5:47 pm
by ^misantropia^
Note that I commented out the cvar_restart. The code uses mod_advanced_controls to track its current state, but of course cvar_restart nukes that.
Re: How to load different control configs
Posted: Wed Apr 22, 2009 2:25 pm
by Herr W
^misantropia^ wrote:I'm not a cruel guy.
I'll never say so again

- Thanks a lot friend!
Re: How to load different control configs
Posted: Mon May 04, 2009 8:08 am
by Herr W
Works perfectly now! Even without the "vid_restart\n"-line. (I guess, that one is only required for changes in system/video settings.)
Don't know if this is interesting for anybody, but that new config variable has to be added to "client.h", "cl_main.c" and "ui_shared.c", too.
Meanwhile - what a surprise! - a new problem appeared. Have no idea why, but mouse speed ("sensitivity") isn't saved. I tried to use code parts from another slider-button variable like "brightness"...
Code: Select all
case ID_MOUSESPEED:
trap_Cvar_SetValue( "sensitivity", s_controls.sensitivity.curvalue / 10 );
break;
Code: Select all
s_controls.sensitivity.generic.type = MTYPE_SLIDER;
s_controls.sensitivity.generic.flags = QMF_SMALLFONT;
s_controls.sensitivity.generic.x = SCREEN_WIDTH/2;
s_controls.sensitivity.generic.y = y;
s_controls.sensitivity.generic.name = "MOUSE SPEED:";
s_controls.sensitivity.generic.callback = Controls_Event;
s_controls.sensitivity.minvalue = 2;
s_controls.sensitivity.maxvalue = 30;
Code: Select all
Menu_AddItem( &s_controls.menu, &s_controls.sensitivity );
Code: Select all
s_controls.sensitivity.curvalue = trap_Cvar_VariableValue( "sensitivity" ) * 10;
... but this makes the slider always stick to the right. Did I miss something?

Re: How to load different control configs
Posted: Thu May 07, 2009 8:18 am
by Herr W
Oops... Another code-puzzling error. Just missed this line:
Code: Select all
s_controls.sensitivity.generic.id = ID_MOUSESPEED;