Index | FAQ | Search | Memberlist | Usergroups | Profile | Log in to check your private messages | Log in | Register

Tutorial: Fixing annoying -alias keypress in standard Quake

| Inside3d Forums Forum Index -> Programming Tutorials

View previous topic :: View next topic
Author | Message
--- | ---
Baker Joined: 14 Mar 2006 Posts: 1538 |

Posted: Sun Nov 23, 2008 5:16 am Post subject: Tutorial: Fixing annoying -alias keypress in standard Quake |

I think Inside3d should serve as the central depot for engine code now that Quakesrc.org is dead and it is clear it won't ever be back. Here is a tutorial I made a while back @ QuakeOne.com (original thread) and I think this is needs to be here:
Summary:
This short tutorial fixes a couple of really annoying problems in Quake that have to do with all sorts of aliases and keybinds being triggered inappropriately in situations in-game, in the console and when using ALT-TAB or changing video mode (if you are using an engine that supports that).
Walkthrough:
This part fixes the ALT-TAB and video mode changing issues. Later on, the console and messagemode fixes are addressed.
For starters, some of the code is not really in the right place in Quake.
I moved Key_ClearAllStates from gl_vidnt.c/vid_win.c into keys.c. There is no Windows-only code in Key_ClearAllStates, so it is just a more sensible location.
Here is the ClearAllStates from GLQuake:

Quote:
/* ================ ClearAllStates ================ */
void ClearAllStates (void)
{
int i;
// send an up event for each key, to make sure the server clears them all
for (i=0 ; i<256 ; i++)
{
Key_Event (i, false);
}
Key_ClearStates ();
IN_ClearStates ();
}

And the Key_ClearStates from GLQuake:

Quote:
/* =================== Key_ClearStates =================== */
void Key_ClearStates (void)
{
int i;
for (i=0 ; i<256 ; i++)
{
keydown[i] = false;
key_repeats[i] = 0;
}
}

Note that the above is setting the down state to false.
And here is the IN_ClearStates from GLQuake in in_win.c:

Quote:
/* =================== IN_ClearStates =================== */
void IN_ClearStates (void)
{
if (mouseactive)
{
mx_accum = 0;
my_accum = 0;
mouse_oldbuttonstate = 0;
}
}

This is reseting the mouse coordinates.
What is wrong with the way GLQuake does it
First, it is triggering -aliases FOR all keys. It doesn't matter if the key was depressed or not. This can have undesirable effects when ALT-TAB is done or if the client supports video mode changing.
Second, only ClearAllStates in gl_vidnt.c/vid_win.c calls Key_ClearStates. Why have 2 procedures separate and 1 of them in clearly the wrong source file.
What I did to fix this ...
Only ClearAllStates calls Key_ClearStates and it's in the wrong place. I deleted ClearAllStates from gl_vidnt.c and vid_win.c. Then renamed Key_ClearStates to Key_ClearAllStates.
And instead of triggering every key with a release event, it only triggers key events for keys that were actually down.

Code:
/* ================== Key_ClearAllStates ================== */
void Key_ClearAllStates (void)
{
int i;
for (i=0 ; i<256 ; i++)
{
// If the key is down, trigger the up action if, say, +showscores or another +bind is activated
if (keydown[i])
Key_Event (i, false);
}
IN_ClearStates ();
}

The Key_Event with the down=false is going to set keydown[key] to false and keyrepeats[key] to 0 anyway.
Extra Credit
The above doesn't address another issue. Minus -aliases are triggered in the console or even in messagemode! This is annoying.
My console, for instance, gets spammed with "-hook isn't a valid alias" and weird impulses gets trigger when I'm in message mode because I have a weapon changing binds with both +aliases and -aliases. I've had other oddball things happen while typing, I even ruined a tournament game once when logged in as admin from this because all sorts of things can get triggered by -aliases being executed while chatting.
The Fix For That
First, we are going to mark whether a key was depressed while in-game.

Quote:
//At the top of keys.c qboolean keygamedown[256];

Second, in Key_Event we need a temp variable to store this value. This is because Key_Event will need to set the down state to false if exiting.

Quote:
//keys.c in Key_Event qboolean wasgamekey = false;

And we need to set this variable immediately after "keydown[key] = down;"

Code:
//keys.c in Key_Event wasgamekey = keygamedown[key]; // Baker: to prevent -aliases being triggered in-console needlessly if (!down) { keygamedown[key] = false; }

Now we need to find this to make it only execute the -alias if the key was triggered in the game:

Quote:
if (!down) { // Baker: we only want to trigger -alias if appropriate // but we ALWAYS want to exit if key is up if (wasgamekey) {
kb = keybindings[key];
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-%s %i\n", kb+1, key);
Cbuf_AddText (cmd);
}
if (keyshift[key] != key)
{
kb = keybindings[keyshift[key]];
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-%s %i\n", kb+1, key);
Cbuf_AddText (cmd);
}
}
}
return;
}

And finally, we need to have it set the keygamedown ONLY when the +alias is executed:

Quote:
if ((kb = keybindings[key])) { // Baker: if we are here, the key is down // and if it is retrigger a bind // it must be allowed to trigger the -bind
//
keygamedown[key]=true; // Let it be untriggered anytime
if (kb[0] == '+')
{ // button commands add keynum as a parm
Q_snprintfz (cmd, sizeof(cmd), "%s %i\n", kb, key);
Cbuf_AddText (cmd);
}
else
{
Cbuf_AddText (kb);
Cbuf_AddText ("\n");
}
}
return;

Back to top |

Display posts from previous:

| Inside3d Forums Forum Index -> Programming Tutorials | All times are GMT
Page 1 of 1

Jump to:

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2004 phpBB Group