2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
32 #include "Session_local.h"
39 void usercmd_t::ByteSwap( void ) {
40 angles[0] = LittleShort( angles[0] );
41 angles[1] = LittleShort( angles[1] );
42 angles[2] = LittleShort( angles[2] );
43 sequence = LittleLong( sequence );
51 bool usercmd_t::operator==( const usercmd_t &rhs ) const {
52 return ( buttons == rhs.buttons &&
53 forwardmove == rhs.forwardmove &&
54 rightmove == rhs.rightmove &&
55 upmove == rhs.upmove &&
56 angles[0] == rhs.angles[0] &&
57 angles[1] == rhs.angles[1] &&
58 angles[2] == rhs.angles[2] &&
59 impulse == rhs.impulse &&
66 const int KEY_MOVESPEED = 127;
168 usercmdButton_t button;
171 userCmdString_t userCmdStrings[] = {
172 { "_moveUp", UB_UP },
173 { "_moveDown", UB_DOWN },
174 { "_left", UB_LEFT },
175 { "_right", UB_RIGHT },
176 { "_forward", UB_FORWARD },
177 { "_back", UB_BACK },
178 { "_lookUp", UB_LOOKUP },
179 { "_lookDown", UB_LOOKDOWN },
180 { "_strafe", UB_STRAFE },
181 { "_moveLeft", UB_MOVELEFT },
182 { "_moveRight", UB_MOVERIGHT },
184 { "_attack", UB_ATTACK },
185 { "_speed", UB_SPEED },
186 { "_zoom", UB_ZOOM },
187 { "_showScores", UB_SHOWSCORES },
188 { "_mlook", UB_MLOOK },
190 { "_button0", UB_BUTTON0 },
191 { "_button1", UB_BUTTON1 },
192 { "_button2", UB_BUTTON2 },
193 { "_button3", UB_BUTTON3 },
194 { "_button4", UB_BUTTON4 },
195 { "_button5", UB_BUTTON5 },
196 { "_button6", UB_BUTTON6 },
197 { "_button7", UB_BUTTON7 },
199 { "_impulse0", UB_IMPULSE0 },
200 { "_impulse1", UB_IMPULSE1 },
201 { "_impulse2", UB_IMPULSE2 },
202 { "_impulse3", UB_IMPULSE3 },
203 { "_impulse4", UB_IMPULSE4 },
204 { "_impulse5", UB_IMPULSE5 },
205 { "_impulse6", UB_IMPULSE6 },
206 { "_impulse7", UB_IMPULSE7 },
207 { "_impulse8", UB_IMPULSE8 },
208 { "_impulse9", UB_IMPULSE9 },
209 { "_impulse10", UB_IMPULSE10 },
210 { "_impulse11", UB_IMPULSE11 },
211 { "_impulse12", UB_IMPULSE12 },
212 { "_impulse13", UB_IMPULSE13 },
213 { "_impulse14", UB_IMPULSE14 },
214 { "_impulse15", UB_IMPULSE15 },
215 { "_impulse16", UB_IMPULSE16 },
216 { "_impulse17", UB_IMPULSE17 },
217 { "_impulse18", UB_IMPULSE18 },
218 { "_impulse19", UB_IMPULSE19 },
219 { "_impulse20", UB_IMPULSE20 },
220 { "_impulse21", UB_IMPULSE21 },
221 { "_impulse22", UB_IMPULSE22 },
222 { "_impulse23", UB_IMPULSE23 },
223 { "_impulse24", UB_IMPULSE24 },
224 { "_impulse25", UB_IMPULSE25 },
225 { "_impulse26", UB_IMPULSE26 },
226 { "_impulse27", UB_IMPULSE27 },
227 { "_impulse28", UB_IMPULSE28 },
228 { "_impulse29", UB_IMPULSE29 },
229 { "_impulse30", UB_IMPULSE30 },
230 { "_impulse31", UB_IMPULSE31 },
231 { "_impulse32", UB_IMPULSE32 },
232 { "_impulse33", UB_IMPULSE33 },
233 { "_impulse34", UB_IMPULSE34 },
234 { "_impulse35", UB_IMPULSE35 },
235 { "_impulse36", UB_IMPULSE36 },
236 { "_impulse37", UB_IMPULSE37 },
237 { "_impulse38", UB_IMPULSE38 },
238 { "_impulse39", UB_IMPULSE39 },
239 { "_impulse40", UB_IMPULSE40 },
240 { "_impulse41", UB_IMPULSE41 },
241 { "_impulse42", UB_IMPULSE42 },
242 { "_impulse43", UB_IMPULSE43 },
243 { "_impulse44", UB_IMPULSE44 },
244 { "_impulse45", UB_IMPULSE45 },
245 { "_impulse46", UB_IMPULSE46 },
246 { "_impulse47", UB_IMPULSE47 },
247 { "_impulse48", UB_IMPULSE48 },
248 { "_impulse49", UB_IMPULSE49 },
249 { "_impulse50", UB_IMPULSE50 },
250 { "_impulse51", UB_IMPULSE51 },
251 { "_impulse52", UB_IMPULSE52 },
252 { "_impulse53", UB_IMPULSE53 },
253 { "_impulse54", UB_IMPULSE54 },
254 { "_impulse55", UB_IMPULSE55 },
255 { "_impulse56", UB_IMPULSE56 },
256 { "_impulse57", UB_IMPULSE57 },
257 { "_impulse58", UB_IMPULSE58 },
258 { "_impulse59", UB_IMPULSE59 },
259 { "_impulse60", UB_IMPULSE60 },
260 { "_impulse61", UB_IMPULSE61 },
261 { "_impulse62", UB_IMPULSE62 },
262 { "_impulse63", UB_IMPULSE63 },
267 class buttonState_t {
272 buttonState_t() { Clear(); };
274 void SetKeyState( int keystate, bool toggle );
282 void buttonState_t::Clear( void ) {
289 buttonState_t::SetKeyState
292 void buttonState_t::SetKeyState( int keystate, bool toggle ) {
296 } else if ( !keystate ) {
298 } else if ( !held ) {
305 const int NUM_USER_COMMANDS = sizeof(userCmdStrings) / sizeof(userCmdString_t);
307 const int MAX_CHAT_BUFFER = 127;
309 class idUsercmdGenLocal : public idUsercmdGen {
311 idUsercmdGenLocal( void );
315 void InitForNewMap( void );
317 void Shutdown( void );
321 void ClearAngles( void );
323 usercmd_t TicCmd( int ticNumber );
325 void InhibitUsercmd( inhibit_t subsystem, bool inhibit );
327 void UsercmdInterrupt( void );
329 int CommandStringUsercmdData( const char *cmdString );
331 int GetNumUserCommands( void );
333 const char * GetUserCommandName( int index );
335 void MouseState( int *x, int *y, int *button, bool *down );
337 int ButtonState( int key );
338 int KeyState( int key );
340 usercmd_t GetDirectUsercmd( void );
343 void MakeCurrent( void );
344 void InitCurrent( void );
346 bool Inhibited( void );
347 void AdjustAngles( void );
348 void KeyMove( void );
349 void JoystickMove( void );
350 void MouseMove( void );
351 void CmdButtons( void );
354 void Keyboard( void );
355 void Joystick( void );
357 void Key( int keyNum, bool down );
363 buttonState_t toggled_crouch;
364 buttonState_t toggled_run;
365 buttonState_t toggled_zoom;
367 int buttonState[UB_MAX_BUTTONS];
368 bool keyState[K_LAST_KEY];
370 int inhibitCommands; // true when in console or menu locally
375 usercmd_t cmd; // the current cmd being built
376 usercmd_t buffered[MAX_BUFFERED_USERCMD];
378 int continuousMouseX, continuousMouseY; // for gui event generatioin, never zerod
379 int mouseButton; // for gui event generatioin
382 int mouseDx, mouseDy; // added to by mouse events
383 int joystickAxis[MAX_JOYSTICK_AXIS]; // set by joystick events
385 static idCVar in_yawSpeed;
386 static idCVar in_pitchSpeed;
387 static idCVar in_angleSpeedKey;
388 static idCVar in_freeLook;
389 static idCVar in_alwaysRun;
390 static idCVar in_toggleRun;
391 static idCVar in_toggleCrouch;
392 static idCVar in_toggleZoom;
393 static idCVar sensitivity;
394 static idCVar m_pitch;
396 static idCVar m_strafeScale;
397 static idCVar m_smooth;
398 static idCVar m_strafeSmooth;
399 static idCVar m_showMouseRate;
402 idCVar idUsercmdGenLocal::in_yawSpeed( "in_yawspeed", "140", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "yaw change speed when holding down _left or _right button" );
403 idCVar idUsercmdGenLocal::in_pitchSpeed( "in_pitchspeed", "140", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "pitch change speed when holding down look _lookUp or _lookDown button" );
404 idCVar idUsercmdGenLocal::in_angleSpeedKey( "in_anglespeedkey", "1.5", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "angle change scale when holding down _speed button" );
405 idCVar idUsercmdGenLocal::in_freeLook( "in_freeLook", "1", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "look around with mouse (reverse _mlook button)" );
406 idCVar idUsercmdGenLocal::in_alwaysRun( "in_alwaysRun", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "always run (reverse _speed button) - only in MP" );
407 idCVar idUsercmdGenLocal::in_toggleRun( "in_toggleRun", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "pressing _speed button toggles run on/off - only in MP" );
408 idCVar idUsercmdGenLocal::in_toggleCrouch( "in_toggleCrouch", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "pressing _movedown button toggles player crouching/standing" );
409 idCVar idUsercmdGenLocal::in_toggleZoom( "in_toggleZoom", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "pressing _zoom button toggles zoom on/off" );
410 idCVar idUsercmdGenLocal::sensitivity( "sensitivity", "5", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse view sensitivity" );
411 idCVar idUsercmdGenLocal::m_pitch( "m_pitch", "0.022", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse pitch scale" );
412 idCVar idUsercmdGenLocal::m_yaw( "m_yaw", "0.022", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse yaw scale" );
413 idCVar idUsercmdGenLocal::m_strafeScale( "m_strafeScale", "6.25", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse strafe movement scale" );
414 idCVar idUsercmdGenLocal::m_smooth( "m_smooth", "1", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_INTEGER, "number of samples blended for mouse viewing", 1, 8, idCmdSystem::ArgCompletion_Integer<1,8> );
415 idCVar idUsercmdGenLocal::m_strafeSmooth( "m_strafeSmooth", "4", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_INTEGER, "number of samples blended for mouse moving", 1, 8, idCmdSystem::ArgCompletion_Integer<1,8> );
416 idCVar idUsercmdGenLocal::m_showMouseRate( "m_showMouseRate", "0", CVAR_SYSTEM | CVAR_BOOL, "shows mouse movement" );
418 static idUsercmdGenLocal localUsercmdGen;
419 idUsercmdGen *usercmdGen = &localUsercmdGen;
423 idUsercmdGenLocal::idUsercmdGenLocal
426 idUsercmdGenLocal::idUsercmdGenLocal( void ) {
433 toggled_crouch.Clear();
435 toggled_zoom.Clear();
436 toggled_run.on = in_alwaysRun.GetBool();
444 idUsercmdGenLocal::InhibitUsercmd
447 void idUsercmdGenLocal::InhibitUsercmd( inhibit_t subsystem, bool inhibit ) {
449 inhibitCommands |= 1 << subsystem;
451 inhibitCommands &= ( 0xffffffff ^ ( 1 << subsystem ) );
457 idUsercmdGenLocal::ButtonState
459 Returns (the fraction of the frame) that the key was down
462 int idUsercmdGenLocal::ButtonState( int key ) {
463 if ( key<0 || key>=UB_MAX_BUTTONS ) {
466 return ( buttonState[key] > 0 ) ? 1 : 0;
471 idUsercmdGenLocal::KeyState
473 Returns (the fraction of the frame) that the key was down
477 int idUsercmdGenLocal::KeyState( int key ) {
478 if ( key<0 || key>=K_LAST_KEY ) {
481 return ( keyState[key] ) ? 1 : 0;
485 //=====================================================================
490 idUsercmdGenLocal::GetNumUserCommands
493 int idUsercmdGenLocal::GetNumUserCommands( void ) {
494 return NUM_USER_COMMANDS;
499 idUsercmdGenLocal::GetNumUserCommands
502 const char *idUsercmdGenLocal::GetUserCommandName( int index ) {
503 if (index >= 0 && index < NUM_USER_COMMANDS) {
504 return userCmdStrings[index].string;
511 idUsercmdGenLocal::Inhibited
513 is user cmd generation inhibited
516 bool idUsercmdGenLocal::Inhibited( void ) {
517 return ( inhibitCommands != 0);
522 idUsercmdGenLocal::AdjustAngles
524 Moves the local angle positions
527 void idUsercmdGenLocal::AdjustAngles( void ) {
530 if ( toggled_run.on ^ ( in_alwaysRun.GetBool() && idAsyncNetwork::IsActive() ) ) {
531 speed = idMath::M_MS2SEC * USERCMD_MSEC * in_angleSpeedKey.GetFloat();
533 speed = idMath::M_MS2SEC * USERCMD_MSEC;
536 if ( !ButtonState( UB_STRAFE ) ) {
537 viewangles[YAW] -= speed * in_yawSpeed.GetFloat() * ButtonState( UB_RIGHT );
538 viewangles[YAW] += speed * in_yawSpeed.GetFloat() * ButtonState( UB_LEFT );
541 viewangles[PITCH] -= speed * in_pitchSpeed.GetFloat() * ButtonState( UB_LOOKUP );
542 viewangles[PITCH] += speed * in_pitchSpeed.GetFloat() * ButtonState( UB_LOOKDOWN );
547 idUsercmdGenLocal::KeyMove
549 Sets the usercmd_t based on key states
552 void idUsercmdGenLocal::KeyMove( void ) {
553 int forward, side, up;
558 if ( ButtonState( UB_STRAFE ) ) {
559 side += KEY_MOVESPEED * ButtonState( UB_RIGHT );
560 side -= KEY_MOVESPEED * ButtonState( UB_LEFT );
563 side += KEY_MOVESPEED * ButtonState( UB_MOVERIGHT );
564 side -= KEY_MOVESPEED * ButtonState( UB_MOVELEFT );
566 up -= KEY_MOVESPEED * toggled_crouch.on;
567 up += KEY_MOVESPEED * ButtonState( UB_UP );
569 forward += KEY_MOVESPEED * ButtonState( UB_FORWARD );
570 forward -= KEY_MOVESPEED * ButtonState( UB_BACK );
572 cmd.forwardmove = idMath::ClampChar( forward );
573 cmd.rightmove = idMath::ClampChar( side );
574 cmd.upmove = idMath::ClampChar( up );
579 idUsercmdGenLocal::MouseMove
582 void idUsercmdGenLocal::MouseMove( void ) {
583 float mx, my, strafeMx, strafeMy;
584 static int history[8][2];
585 static int historyCounter;
588 history[historyCounter&7][0] = mouseDx;
589 history[historyCounter&7][1] = mouseDy;
591 // allow mouse movement to be smoothed together
592 int smooth = m_smooth.GetInteger();
601 for ( i = 0 ; i < smooth ; i++ ) {
602 mx += history[ ( historyCounter - i + 8 ) & 7 ][0];
603 my += history[ ( historyCounter - i + 8 ) & 7 ][1];
608 // use a larger smoothing for strafing
609 smooth = m_strafeSmooth.GetInteger();
618 for ( i = 0 ; i < smooth ; i++ ) {
619 strafeMx += history[ ( historyCounter - i + 8 ) & 7 ][0];
620 strafeMy += history[ ( historyCounter - i + 8 ) & 7 ][1];
627 if ( idMath::Fabs( mx ) > 1000 || idMath::Fabs( my ) > 1000 ) {
628 Sys_DebugPrintf( "idUsercmdGenLocal::MouseMove: Ignoring ridiculous mouse delta.\n" );
632 mx *= sensitivity.GetFloat();
633 my *= sensitivity.GetFloat();
635 if ( m_showMouseRate.GetBool() ) {
636 Sys_DebugPrintf( "[%3i %3i = %5.1f %5.1f = %5.1f %5.1f] ", mouseDx, mouseDy, mx, my, strafeMx, strafeMy );
642 if ( !strafeMx && !strafeMy ) {
646 if ( ButtonState( UB_STRAFE ) || !( cmd.buttons & BUTTON_MLOOK ) ) {
647 // add mouse X/Y movement to cmd
648 strafeMx *= m_strafeScale.GetFloat();
649 strafeMy *= m_strafeScale.GetFloat();
650 // clamp as a vector, instead of separate floats
651 float len = sqrt( strafeMx * strafeMx + strafeMy * strafeMy );
653 strafeMx = strafeMx * 127 / len;
654 strafeMy = strafeMy * 127 / len;
658 if ( !ButtonState( UB_STRAFE ) ) {
659 viewangles[YAW] -= m_yaw.GetFloat() * mx;
661 cmd.rightmove = idMath::ClampChar( (int)(cmd.rightmove + strafeMx) );
664 if ( !ButtonState( UB_STRAFE ) && ( cmd.buttons & BUTTON_MLOOK ) ) {
665 viewangles[PITCH] += m_pitch.GetFloat() * my;
667 cmd.forwardmove = idMath::ClampChar( (int)(cmd.forwardmove - strafeMy) );
673 idUsercmdGenLocal::JoystickMove
676 void idUsercmdGenLocal::JoystickMove( void ) {
679 if ( toggled_run.on ^ ( in_alwaysRun.GetBool() && idAsyncNetwork::IsActive() ) ) {
680 anglespeed = idMath::M_MS2SEC * USERCMD_MSEC * in_angleSpeedKey.GetFloat();
682 anglespeed = idMath::M_MS2SEC * USERCMD_MSEC;
685 if ( !ButtonState( UB_STRAFE ) ) {
686 viewangles[YAW] += anglespeed * in_yawSpeed.GetFloat() * joystickAxis[AXIS_SIDE];
687 viewangles[PITCH] += anglespeed * in_pitchSpeed.GetFloat() * joystickAxis[AXIS_FORWARD];
689 cmd.rightmove = idMath::ClampChar( cmd.rightmove + joystickAxis[AXIS_SIDE] );
690 cmd.forwardmove = idMath::ClampChar( cmd.forwardmove + joystickAxis[AXIS_FORWARD] );
693 cmd.upmove = idMath::ClampChar( cmd.upmove + joystickAxis[AXIS_UP] );
698 idUsercmdGenLocal::CmdButtons
701 void idUsercmdGenLocal::CmdButtons( void ) {
706 // figure button bits
707 for (i = 0 ; i <= 7 ; i++) {
708 if ( ButtonState( (usercmdButton_t)( UB_BUTTON0 + i ) ) ) {
709 cmd.buttons |= 1 << i;
713 // check the attack button
714 if ( ButtonState( UB_ATTACK ) ) {
715 cmd.buttons |= BUTTON_ATTACK;
718 // check the run button
719 if ( toggled_run.on ^ ( in_alwaysRun.GetBool() && idAsyncNetwork::IsActive() ) ) {
720 cmd.buttons |= BUTTON_RUN;
723 // check the zoom button
724 if ( toggled_zoom.on ) {
725 cmd.buttons |= BUTTON_ZOOM;
728 // check the scoreboard button
729 if ( ButtonState( UB_SHOWSCORES ) || ButtonState( UB_IMPULSE19 ) ) {
730 // the button is toggled in SP mode as well but without effect
731 cmd.buttons |= BUTTON_SCORES;
734 // check the mouse look button
735 if ( ButtonState( UB_MLOOK ) ^ in_freeLook.GetInteger() ) {
736 cmd.buttons |= BUTTON_MLOOK;
742 idUsercmdGenLocal::InitCurrent
744 inits the current command for this frame
747 void idUsercmdGenLocal::InitCurrent( void ) {
748 memset( &cmd, 0, sizeof( cmd ) );
750 cmd.impulse = impulse;
751 cmd.buttons |= ( in_alwaysRun.GetBool() && idAsyncNetwork::IsActive() ) ? BUTTON_RUN : 0;
752 cmd.buttons |= in_freeLook.GetBool() ? BUTTON_MLOOK : 0;
757 idUsercmdGenLocal::MakeCurrent
759 creates the current command for this frame
762 void idUsercmdGenLocal::MakeCurrent( void ) {
766 oldAngles = viewangles;
768 if ( !Inhibited() ) {
769 // update toggled key states
770 toggled_crouch.SetKeyState( ButtonState( UB_DOWN ), in_toggleCrouch.GetBool() );
771 toggled_run.SetKeyState( ButtonState( UB_SPEED ), in_toggleRun.GetBool() && idAsyncNetwork::IsActive() );
772 toggled_zoom.SetKeyState( ButtonState( UB_ZOOM ), in_toggleZoom.GetBool() );
774 // keyboard angle adjustment
780 // get basic movement from keyboard
783 // get basic movement from mouse
786 // get basic movement from joystick
789 // check to make sure the angles haven't wrapped
790 if ( viewangles[PITCH] - oldAngles[PITCH] > 90 ) {
791 viewangles[PITCH] = oldAngles[PITCH] + 90;
792 } else if ( oldAngles[PITCH] - viewangles[PITCH] > 90 ) {
793 viewangles[PITCH] = oldAngles[PITCH] - 90;
800 for ( i = 0; i < 3; i++ ) {
801 cmd.angles[i] = ANGLE2SHORT( viewangles[i] );
804 cmd.mx = continuousMouseX;
805 cmd.my = continuousMouseY;
808 impulse = cmd.impulse;
812 //=====================================================================
817 idUsercmdGenLocal::CommandStringUsercmdData
819 Returns the button if the command string is used by the async usercmd generator.
822 int idUsercmdGenLocal::CommandStringUsercmdData( const char *cmdString ) {
823 for ( userCmdString_t *ucs = userCmdStrings ; ucs->string ; ucs++ ) {
824 if ( idStr::Icmp( cmdString, ucs->string ) == 0 ) {
833 idUsercmdGenLocal::Init
836 void idUsercmdGenLocal::Init( void ) {
842 idUsercmdGenLocal::InitForNewMap
845 void idUsercmdGenLocal::InitForNewMap( void ) {
849 toggled_crouch.Clear();
851 toggled_zoom.Clear();
852 toggled_run.on = in_alwaysRun.GetBool();
860 idUsercmdGenLocal::Shutdown
863 void idUsercmdGenLocal::Shutdown( void ) {
869 idUsercmdGenLocal::Clear
872 void idUsercmdGenLocal::Clear( void ) {
873 // clears all key states
874 memset( buttonState, 0, sizeof( buttonState ) );
875 memset( keyState, false, sizeof( keyState ) );
877 inhibitCommands = false;
879 mouseDx = mouseDy = 0;
886 idUsercmdGenLocal::ClearAngles
889 void idUsercmdGenLocal::ClearAngles( void ) {
895 idUsercmdGenLocal::TicCmd
897 Returns a buffered usercmd
900 usercmd_t idUsercmdGenLocal::TicCmd( int ticNumber ) {
902 // the packetClient code can legally ask for com_ticNumber+1, because
903 // it is in the async code and com_ticNumber hasn't been updated yet,
904 // but all other code should never ask for anything > com_ticNumber
905 if ( ticNumber > com_ticNumber+1 ) {
906 common->Error( "idUsercmdGenLocal::TicCmd ticNumber > com_ticNumber" );
909 if ( ticNumber <= com_ticNumber - MAX_BUFFERED_USERCMD ) {
910 // this can happen when something in the game code hitches badly, allowing the
911 // async code to overflow the buffers
912 //common->Printf( "warning: idUsercmdGenLocal::TicCmd ticNumber <= com_ticNumber - MAX_BUFFERED_USERCMD\n" );
915 return buffered[ ticNumber & (MAX_BUFFERED_USERCMD-1) ];
918 //======================================================================
923 idUsercmdGenLocal::Key
925 Handles async mouse/keyboard button actions
928 void idUsercmdGenLocal::Key( int keyNum, bool down ) {
930 // Sanity check, sometimes we get double message :(
931 if ( keyState[ keyNum ] == down ) {
934 keyState[ keyNum ] = down;
936 int action = idKeyInput::GetUsercmdAction( keyNum );
940 buttonState[ action ]++;
942 if ( !Inhibited() ) {
943 if ( action >= UB_IMPULSE0 && action <= UB_IMPULSE61 ) {
944 cmd.impulse = action - UB_IMPULSE0;
945 cmd.flags ^= UCF_IMPULSE_SEQUENCE;
949 buttonState[ action ]--;
950 // we might have one held down across an app active transition
951 if ( buttonState[ action ] < 0 ) {
952 buttonState[ action ] = 0;
959 idUsercmdGenLocal::Mouse
962 void idUsercmdGenLocal::Mouse( void ) {
965 numEvents = Sys_PollMouseInputEvents();
969 // Study each of the buffer elements and process them.
971 for( i = 0; i < numEvents; i++ ) {
973 if ( Sys_ReturnMouseInputEvent( i, action, value ) ) {
974 if ( action >= M_ACTION1 && action <= M_ACTION8 ) {
975 mouseButton = K_MOUSE1 + ( action - M_ACTION1 );
976 mouseDown = ( value != 0 );
977 Key( mouseButton, mouseDown );
982 continuousMouseX += value;
986 continuousMouseY += value;
989 int key = value < 0 ? K_MWHEELDOWN : K_MWHEELUP;
990 value = abs( value );
991 while( value-- > 0 ) {
1004 Sys_EndMouseInputEvents();
1009 idUsercmdGenLocal::Keyboard
1012 void idUsercmdGenLocal::Keyboard( void ) {
1014 int numEvents = Sys_PollKeyboardInputEvents();
1018 // Study each of the buffer elements and process them.
1022 for( int i = 0; i < numEvents; i++ ) {
1023 if (Sys_ReturnKeyboardInputEvent( i, key, state )) {
1029 Sys_EndKeyboardInputEvents();
1034 idUsercmdGenLocal::Joystick
1037 void idUsercmdGenLocal::Joystick( void ) {
1038 memset( joystickAxis, 0, sizeof( joystickAxis ) );
1043 idUsercmdGenLocal::UsercmdInterrupt
1045 Called asyncronously
1048 void idUsercmdGenLocal::UsercmdInterrupt( void ) {
1049 // dedicated servers won't create usercmds
1050 if ( !initialized ) {
1054 // init the usercmd for com_ticNumber+1
1057 // process the system mouse events
1060 // process the system keyboard events
1063 // process the system joystick events
1066 // create the usercmd for com_ticNumber+1
1069 // save a number for debugging cmdDemos and networking
1070 cmd.sequence = com_ticNumber+1;
1072 buffered[(com_ticNumber+1) & (MAX_BUFFERED_USERCMD-1)] = cmd;
1077 idUsercmdGenLocal::MouseState
1080 void idUsercmdGenLocal::MouseState( int *x, int *y, int *button, bool *down ) {
1081 *x = continuousMouseX;
1082 *y = continuousMouseY;
1083 *button = mouseButton;
1089 idUsercmdGenLocal::GetDirectUsercmd
1092 usercmd_t idUsercmdGenLocal::GetDirectUsercmd( void ) {
1094 // initialize current usercmd
1097 // process the system mouse events
1100 // process the system keyboard events
1103 // process the system joystick events
1106 // create the usercmd
1109 cmd.duplicateCount = 0;