How to load different control configs

Locked
Herr W
Posts: 90
Joined: Tue May 16, 2006 8:53 am

How to load different control configs

Post by Herr W »

Hi, me again, this time with a probably more challenging question! :D

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

#define ID_DEFAULTS				17

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! :)
[color=#FF0000]Visit MONKEYS of DOOM at [url]http://www.monkeysofdoom.org[/url][/color]
^misantropia^
Posts: 4022
Joined: Sat Mar 12, 2005 6:24 pm

Re: How to load different control configs

Post 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
Herr W
Posts: 90
Joined: Tue May 16, 2006 8:53 am

Re: How to load different control configs

Post by Herr W »

Okay, lots of radio buttons in there! Let's see what I need for a new one in ui_controls...

1.

Code: Select all

#define ID_ADVANCEDCFG	128
2.

Code: Select all

	menuradiobutton_s     advancedcfg;
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. :dork:

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...
[color=#FF0000]Visit MONKEYS of DOOM at [url]http://www.monkeysofdoom.org[/url][/color]
^misantropia^
Posts: 4022
Joined: Sat Mar 12, 2005 6:24 pm

Re: How to load different control configs

Post 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. :dork:
But there is (in the stock and ioquake3 source, at least) - SETUP -> DEFAULTS - and the executed action is Setup_ResetDefaults_Action().
^misantropia^
Posts: 4022
Joined: Sat Mar 12, 2005 6:24 pm

Re: How to load different control configs

Post by ^misantropia^ »

Oh, and the case is around line 138 in q3_ui/ui_setup.c, look for ID_DEFAULTS.
Herr W
Posts: 90
Joined: Tue May 16, 2006 8:53 am

Re: How to load different control configs

Post 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. :confused:

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... :paranoid:
[color=#FF0000]Visit MONKEYS of DOOM at [url]http://www.monkeysofdoom.org[/url][/color]
Herr W
Posts: 90
Joined: Tue May 16, 2006 8:53 am

Re: How to load different control configs

Post 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!
[color=#FF0000]Visit MONKEYS of DOOM at [url]http://www.monkeysofdoom.org[/url][/color]
^misantropia^
Posts: 4022
Joined: Sat Mar 12, 2005 6:24 pm

Re: How to load different control configs

Post 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 );
^misantropia^
Posts: 4022
Joined: Sat Mar 12, 2005 6:24 pm

Re: How to load different control configs

Post 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.
Herr W
Posts: 90
Joined: Tue May 16, 2006 8:53 am

Re: How to load different control configs

Post by Herr W »

^misantropia^ wrote:I'm not a cruel guy.
I'll never say so again ;) - Thanks a lot friend!
[color=#FF0000]Visit MONKEYS of DOOM at [url]http://www.monkeysofdoom.org[/url][/color]
Herr W
Posts: 90
Joined: Tue May 16, 2006 8:53 am

Re: How to load different control configs

Post 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

	menuslider_s		sensitivity;

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? :confused:
[color=#FF0000]Visit MONKEYS of DOOM at [url]http://www.monkeysofdoom.org[/url][/color]
Herr W
Posts: 90
Joined: Tue May 16, 2006 8:53 am

Re: How to load different control configs

Post by Herr W »

Oops... Another code-puzzling error. Just missed this line: :rolleyes:

Code: Select all

	s_controls.sensitivity.generic.id          = ID_MOUSESPEED;
[color=#FF0000]Visit MONKEYS of DOOM at [url]http://www.monkeysofdoom.org[/url][/color]
Locked