Inside3D!
     

Tutorial: Fixing annoying -alias keypress in standard Quake

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials
View previous topic :: View next topic  
Author Message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Sun Nov 23, 2008 5:16 am    Post subject: Tutorial: Fixing annoying -alias keypress in standard Quake Reply with quote

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. Wink

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    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