mirror of
https://github.com/FWGS/hlsdk-xash3d
synced 2024-11-11 04:39:03 +01:00
1135 lines
21 KiB
C++
1135 lines
21 KiB
C++
//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================
|
|
|
|
// cl.input.c -- builds an intended movement command to send to the server
|
|
|
|
//xxxxxx Move bob and pitch drifting code here and other stuff from view if needed
|
|
|
|
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
|
|
// rights reserved.
|
|
|
|
#include "hud.h"
|
|
#include "cl_util.h"
|
|
#include "camera.h"
|
|
extern "C"
|
|
{
|
|
#include "kbutton.h"
|
|
}
|
|
#include "cvardef.h"
|
|
#include "usercmd.h"
|
|
#include "const.h"
|
|
#include "camera.h"
|
|
#include "in_defs.h"
|
|
//#include "view.h"
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
extern "C"
|
|
{
|
|
struct kbutton_s DLLEXPORT *KB_Find( const char *name );
|
|
void DLLEXPORT CL_CreateMove( float frametime, struct usercmd_s *cmd, int active );
|
|
void DLLEXPORT HUD_Shutdown( void );
|
|
int DLLEXPORT HUD_Key_Event( int eventcode, int keynum, const char *pszCurrentBinding );
|
|
}
|
|
|
|
extern int g_iAlive;
|
|
|
|
extern int g_weaponselect;
|
|
extern cl_enginefunc_t gEngfuncs;
|
|
|
|
// Defined in pm_math.c
|
|
extern "C" float anglemod( float a );
|
|
|
|
void IN_Init( void );
|
|
void IN_Move( float frametime, usercmd_t *cmd );
|
|
void IN_Shutdown( void );
|
|
void V_Init( void );
|
|
void VectorAngles( const float *forward, float *angles );
|
|
int CL_ButtonBits( int );
|
|
|
|
// xxx need client dll function to get and clear impuse
|
|
extern cvar_t *in_joystick;
|
|
|
|
int in_impulse = 0;
|
|
int in_cancel = 0;
|
|
|
|
cvar_t *m_pitch;
|
|
cvar_t *m_yaw;
|
|
cvar_t *m_forward;
|
|
cvar_t *m_side;
|
|
|
|
cvar_t *lookstrafe;
|
|
cvar_t *lookspring;
|
|
cvar_t *cl_pitchup;
|
|
cvar_t *cl_pitchdown;
|
|
cvar_t *cl_upspeed;
|
|
cvar_t *cl_forwardspeed;
|
|
cvar_t *cl_backspeed;
|
|
cvar_t *cl_sidespeed;
|
|
cvar_t *cl_movespeedkey;
|
|
cvar_t *cl_yawspeed;
|
|
cvar_t *cl_pitchspeed;
|
|
cvar_t *cl_anglespeedkey;
|
|
cvar_t *cl_vsmoothing;
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
KEY BUTTONS
|
|
|
|
Continuous button event tracking is complicated by the fact that two different
|
|
input sources (say, mouse button 1 and the control key) can both press the
|
|
same button, but the button should only be released when both of the
|
|
pressing key have been released.
|
|
|
|
When a key event issues a button command (+forward, +attack, etc), it appends
|
|
its key number as a parameter to the command so it can be matched up with
|
|
the release.
|
|
|
|
state bit 0 is the current state of the key
|
|
state bit 1 is edge triggered on the up to down transition
|
|
state bit 2 is edge triggered on the down to up transition
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
kbutton_t in_mlook;
|
|
kbutton_t in_klook;
|
|
kbutton_t in_jlook;
|
|
kbutton_t in_left;
|
|
kbutton_t in_right;
|
|
kbutton_t in_forward;
|
|
kbutton_t in_back;
|
|
kbutton_t in_lookup;
|
|
kbutton_t in_lookdown;
|
|
kbutton_t in_moveleft;
|
|
kbutton_t in_moveright;
|
|
kbutton_t in_strafe;
|
|
kbutton_t in_speed;
|
|
kbutton_t in_use;
|
|
kbutton_t in_jump;
|
|
kbutton_t in_attack;
|
|
kbutton_t in_attack2;
|
|
kbutton_t in_up;
|
|
kbutton_t in_down;
|
|
kbutton_t in_duck;
|
|
kbutton_t in_reload;
|
|
kbutton_t in_alt1;
|
|
kbutton_t in_score;
|
|
kbutton_t in_break;
|
|
kbutton_t in_graph; // Display the netgraph
|
|
|
|
typedef struct kblist_s
|
|
{
|
|
struct kblist_s *next;
|
|
kbutton_t *pkey;
|
|
char name[32];
|
|
} kblist_t;
|
|
|
|
kblist_t *g_kbkeys = NULL;
|
|
|
|
/*
|
|
============
|
|
KB_ConvertString
|
|
|
|
Removes references to +use and replaces them with the keyname in the output string. If
|
|
a binding is unfound, then the original text is retained.
|
|
NOTE: Only works for text with +word in it.
|
|
============
|
|
*/
|
|
int KB_ConvertString( char *in, char **ppout )
|
|
{
|
|
char sz[4096];
|
|
char binding[64];
|
|
char *p;
|
|
char *pOut;
|
|
char *pEnd;
|
|
const char *pBinding;
|
|
|
|
if( !ppout )
|
|
return 0;
|
|
|
|
*ppout = NULL;
|
|
p = in;
|
|
pOut = sz;
|
|
while( *p )
|
|
{
|
|
if( *p == '+' )
|
|
{
|
|
pEnd = binding;
|
|
while( *p && ( isalnum( *p ) || ( pEnd == binding ) ) && ( ( pEnd - binding ) < 63 ) )
|
|
{
|
|
*pEnd++ = *p++;
|
|
}
|
|
|
|
*pEnd = '\0';
|
|
|
|
pBinding = NULL;
|
|
if( binding[1] != '\0' )
|
|
{
|
|
// See if there is a binding for binding?
|
|
pBinding = gEngfuncs.Key_LookupBinding( binding + 1 );
|
|
}
|
|
|
|
if( pBinding )
|
|
{
|
|
*pOut++ = '[';
|
|
pEnd = (char *)pBinding;
|
|
}
|
|
else
|
|
{
|
|
pEnd = binding;
|
|
}
|
|
|
|
while( *pEnd )
|
|
{
|
|
*pOut++ = *pEnd++;
|
|
}
|
|
|
|
if( pBinding )
|
|
{
|
|
*pOut++ = ']';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pOut++ = *p++;
|
|
}
|
|
}
|
|
|
|
*pOut = '\0';
|
|
|
|
pOut = (char *)malloc( strlen( sz ) + 1 );
|
|
strcpy( pOut, sz );
|
|
*ppout = pOut;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
============
|
|
KB_Find
|
|
|
|
Allows the engine to get a kbutton_t directly ( so it can check +mlook state, etc ) for saving out to .cfg files
|
|
============
|
|
*/
|
|
struct kbutton_s DLLEXPORT *KB_Find( const char *name )
|
|
{
|
|
kblist_t *p;
|
|
p = g_kbkeys;
|
|
while( p )
|
|
{
|
|
if( !stricmp( name, p->name ) )
|
|
return p->pkey;
|
|
|
|
p = p->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
============
|
|
KB_Add
|
|
|
|
Add a kbutton_t * to the list of pointers the engine can retrieve via KB_Find
|
|
============
|
|
*/
|
|
void KB_Add( const char *name, kbutton_t *pkb )
|
|
{
|
|
kblist_t *p;
|
|
kbutton_t *kb;
|
|
|
|
kb = KB_Find( name );
|
|
|
|
if( kb )
|
|
return;
|
|
|
|
p = (kblist_t *)malloc( sizeof(kblist_t) );
|
|
memset( p, 0, sizeof(*p) );
|
|
|
|
strcpy( p->name, name );
|
|
p->pkey = pkb;
|
|
|
|
p->next = g_kbkeys;
|
|
g_kbkeys = p;
|
|
}
|
|
|
|
/*
|
|
============
|
|
KB_Init
|
|
|
|
Add kbutton_t definitions that the engine can query if needed
|
|
============
|
|
*/
|
|
void KB_Init( void )
|
|
{
|
|
g_kbkeys = NULL;
|
|
|
|
KB_Add( "in_graph", &in_graph );
|
|
KB_Add( "in_mlook", &in_mlook );
|
|
KB_Add( "in_jlook", &in_jlook );
|
|
}
|
|
|
|
/*
|
|
============
|
|
KB_Shutdown
|
|
|
|
Clear kblist
|
|
============
|
|
*/
|
|
void KB_Shutdown( void )
|
|
{
|
|
kblist_t *p, *n;
|
|
p = g_kbkeys;
|
|
while( p )
|
|
{
|
|
n = p->next;
|
|
free( p );
|
|
p = n;
|
|
}
|
|
g_kbkeys = NULL;
|
|
}
|
|
|
|
/*
|
|
============
|
|
KeyDown
|
|
============
|
|
*/
|
|
void KeyDown( kbutton_t *b )
|
|
{
|
|
int k;
|
|
char *c;
|
|
|
|
c = gEngfuncs.Cmd_Argv( 1 );
|
|
if( c[0] )
|
|
k = atoi( c );
|
|
else
|
|
k = -1; // typed manually at the console for continuous down
|
|
|
|
if( k == b->down[0] || k == b->down[1] )
|
|
return; // repeating key
|
|
|
|
if( !b->down[0] )
|
|
b->down[0] = k;
|
|
else if( !b->down[1] )
|
|
b->down[1] = k;
|
|
else
|
|
{
|
|
gEngfuncs.Con_DPrintf( "Three keys down for a button '%c' '%c' '%c'!\n", b->down[0], b->down[1], c );
|
|
return;
|
|
}
|
|
|
|
if( b->state & 1 )
|
|
return; // still down
|
|
b->state |= 1 + 2; // down + impulse down
|
|
}
|
|
|
|
/*
|
|
============
|
|
KeyUp
|
|
============
|
|
*/
|
|
void KeyUp( kbutton_t *b )
|
|
{
|
|
int k;
|
|
char *c;
|
|
|
|
c = gEngfuncs.Cmd_Argv( 1 );
|
|
if( c[0] )
|
|
k = atoi(c);
|
|
else
|
|
{
|
|
// typed manually at the console, assume for unsticking, so clear all
|
|
b->down[0] = b->down[1] = 0;
|
|
b->state = 4; // impulse up
|
|
return;
|
|
}
|
|
|
|
if( b->down[0] == k )
|
|
b->down[0] = 0;
|
|
else if( b->down[1] == k )
|
|
b->down[1] = 0;
|
|
else
|
|
return; // key up without coresponding down (menu pass through)
|
|
if( b->down[0] || b->down[1] )
|
|
{
|
|
//Con_Printf ( "Keys down for button: '%c' '%c' '%c' (%d,%d,%d)!\n", b->down[0], b->down[1], c, b->down[0], b->down[1], c );
|
|
return; // some other key is still holding it down
|
|
}
|
|
|
|
if( !( b->state & 1 ) )
|
|
return; // still up (this should not happen)
|
|
|
|
b->state &= ~1; // now up
|
|
b->state |= 4; // impulse up
|
|
}
|
|
|
|
/*
|
|
============
|
|
HUD_Key_Event
|
|
|
|
Return 1 to allow engine to process the key, otherwise, act on it as needed
|
|
============
|
|
*/
|
|
int DLLEXPORT HUD_Key_Event( int down, int keynum, const char *pszCurrentBinding )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
void IN_BreakDown( void )
|
|
{
|
|
KeyDown( &in_break );
|
|
}
|
|
|
|
void IN_BreakUp( void )
|
|
{
|
|
KeyUp( &in_break );
|
|
}
|
|
|
|
void IN_KLookDown( void )
|
|
{
|
|
KeyDown( &in_klook );
|
|
}
|
|
|
|
void IN_KLookUp( void )
|
|
{
|
|
KeyUp( &in_klook );
|
|
}
|
|
|
|
void IN_JLookDown( void )
|
|
{
|
|
KeyDown( &in_jlook );
|
|
}
|
|
|
|
void IN_JLookUp( void )
|
|
{
|
|
KeyUp( &in_jlook );
|
|
}
|
|
|
|
void IN_MLookDown( void )
|
|
{
|
|
KeyDown( &in_mlook );
|
|
}
|
|
|
|
void IN_UpDown( void )
|
|
{
|
|
KeyDown( &in_up );
|
|
}
|
|
|
|
void IN_UpUp( void )
|
|
{
|
|
KeyUp( &in_up );
|
|
}
|
|
|
|
void IN_DownDown( void )
|
|
{
|
|
KeyDown( &in_down );
|
|
}
|
|
|
|
void IN_DownUp( void )
|
|
{
|
|
KeyUp( &in_down );
|
|
}
|
|
|
|
void IN_LeftDown( void )
|
|
{
|
|
KeyDown( &in_left );
|
|
}
|
|
|
|
void IN_LeftUp( void )
|
|
{
|
|
KeyUp( &in_left );
|
|
}
|
|
|
|
void IN_RightDown( void )
|
|
{
|
|
KeyDown( &in_right );
|
|
}
|
|
|
|
void IN_RightUp( void )
|
|
{
|
|
KeyUp( &in_right );
|
|
}
|
|
|
|
void IN_ForwardDown( void )
|
|
{
|
|
KeyDown( &in_forward );
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_FORWARD );
|
|
}
|
|
|
|
void IN_ForwardUp( void )
|
|
{
|
|
KeyUp( &in_forward );
|
|
gHUD.m_Spectator.HandleButtonsUp( IN_FORWARD );
|
|
}
|
|
|
|
void IN_BackDown( void )
|
|
{
|
|
KeyDown( &in_back );
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_BACK );
|
|
}
|
|
|
|
void IN_BackUp( void )
|
|
{
|
|
KeyUp( &in_back );
|
|
gHUD.m_Spectator.HandleButtonsUp( IN_BACK );
|
|
}
|
|
|
|
void IN_LookupDown( void )
|
|
{
|
|
KeyDown( &in_lookup );
|
|
}
|
|
|
|
void IN_LookupUp( void )
|
|
{
|
|
KeyUp( &in_lookup );
|
|
}
|
|
|
|
void IN_LookdownDown( void )
|
|
{
|
|
KeyDown( &in_lookdown );
|
|
}
|
|
|
|
void IN_LookdownUp( void )
|
|
{
|
|
KeyUp( &in_lookdown );
|
|
}
|
|
|
|
void IN_MoveleftDown( void )
|
|
{
|
|
KeyDown( &in_moveleft );
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_MOVELEFT );
|
|
}
|
|
|
|
void IN_MoveleftUp( void )
|
|
{
|
|
KeyUp( &in_moveleft );
|
|
gHUD.m_Spectator.HandleButtonsUp( IN_MOVELEFT );
|
|
}
|
|
|
|
void IN_MoverightDown( void )
|
|
{
|
|
KeyDown( &in_moveright );
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_MOVERIGHT );
|
|
}
|
|
|
|
void IN_MoverightUp( void )
|
|
{
|
|
KeyUp( &in_moveright );
|
|
gHUD.m_Spectator.HandleButtonsUp( IN_MOVERIGHT );
|
|
}
|
|
|
|
void IN_SpeedDown( void )
|
|
{
|
|
KeyDown( &in_speed );
|
|
}
|
|
|
|
void IN_SpeedUp( void )
|
|
{
|
|
KeyUp( &in_speed );
|
|
}
|
|
|
|
void IN_StrafeDown( void )
|
|
{
|
|
KeyDown( &in_strafe );
|
|
}
|
|
|
|
void IN_StrafeUp( void )
|
|
{
|
|
KeyUp( &in_strafe );
|
|
}
|
|
|
|
// needs capture by hud/vgui also
|
|
extern void __CmdFunc_InputPlayerSpecial( void );
|
|
|
|
void IN_Attack2Down( void )
|
|
{
|
|
KeyDown( &in_attack2 );
|
|
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_ATTACK2 );
|
|
}
|
|
|
|
void IN_Attack2Up( void )
|
|
{
|
|
KeyUp( &in_attack2 );
|
|
}
|
|
|
|
void IN_UseDown( void )
|
|
{
|
|
KeyDown( &in_use );
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_USE );
|
|
}
|
|
void IN_UseUp( void )
|
|
{
|
|
KeyUp( &in_use );
|
|
}
|
|
void IN_JumpDown( void )
|
|
{
|
|
KeyDown( &in_jump );
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_JUMP );
|
|
}
|
|
|
|
void IN_JumpUp( void )
|
|
{
|
|
KeyUp( &in_jump );
|
|
}
|
|
|
|
void IN_DuckDown( void )
|
|
{
|
|
KeyDown( &in_duck );
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_DUCK );
|
|
}
|
|
|
|
void IN_DuckUp( void )
|
|
{
|
|
KeyUp( &in_duck );
|
|
}
|
|
|
|
void IN_ReloadDown( void )
|
|
{
|
|
KeyDown( &in_reload );
|
|
}
|
|
|
|
void IN_ReloadUp( void )
|
|
{
|
|
KeyUp( &in_reload );
|
|
}
|
|
|
|
void IN_Alt1Down( void )
|
|
{
|
|
KeyDown( &in_alt1 );
|
|
}
|
|
|
|
void IN_Alt1Up( void )
|
|
{
|
|
KeyUp( &in_alt1 );
|
|
}
|
|
|
|
void IN_GraphDown( void )
|
|
{
|
|
KeyDown( &in_graph );
|
|
}
|
|
|
|
void IN_GraphUp( void )
|
|
{
|
|
KeyUp( &in_graph );
|
|
}
|
|
|
|
void IN_AttackDown( void )
|
|
{
|
|
KeyDown( &in_attack );
|
|
gHUD.m_Spectator.HandleButtonsDown( IN_ATTACK );
|
|
}
|
|
|
|
void IN_AttackUp( void )
|
|
{
|
|
KeyUp( &in_attack );
|
|
in_cancel = 0;
|
|
}
|
|
|
|
// Special handling
|
|
void IN_Cancel( void )
|
|
{
|
|
in_cancel = 1;
|
|
}
|
|
|
|
void IN_Impulse( void )
|
|
{
|
|
in_impulse = atoi( gEngfuncs.Cmd_Argv( 1 ) );
|
|
}
|
|
|
|
void IN_ScoreDown( void )
|
|
{
|
|
KeyDown( &in_score );
|
|
}
|
|
|
|
void IN_ScoreUp( void )
|
|
{
|
|
KeyUp( &in_score );
|
|
}
|
|
|
|
void IN_MLookUp( void )
|
|
{
|
|
KeyUp( &in_mlook );
|
|
}
|
|
|
|
/*
|
|
===============
|
|
CL_KeyState
|
|
|
|
Returns 0.25 if a key was pressed and released during the frame,
|
|
0.5 if it was pressed and held
|
|
0 if held then released, and
|
|
1.0 if held for the entire time
|
|
===============
|
|
*/
|
|
float CL_KeyState( kbutton_t *key )
|
|
{
|
|
float val = 0.0;
|
|
int impulsedown, impulseup, down;
|
|
|
|
impulsedown = key->state & 2;
|
|
impulseup = key->state & 4;
|
|
down = key->state & 1;
|
|
|
|
if( impulsedown && !impulseup )
|
|
{
|
|
// pressed and held this frame?
|
|
val = down ? 0.5 : 0.0;
|
|
}
|
|
|
|
if( impulseup && !impulsedown )
|
|
{
|
|
// released this frame?
|
|
val = down ? 0.0 : 0.0;
|
|
}
|
|
|
|
if( !impulsedown && !impulseup )
|
|
{
|
|
// held the entire frame?
|
|
val = down ? 1.0 : 0.0;
|
|
}
|
|
|
|
if( impulsedown && impulseup )
|
|
{
|
|
if( down )
|
|
{
|
|
// released and re-pressed this frame
|
|
val = 0.75;
|
|
}
|
|
else
|
|
{
|
|
// pressed and released this frame
|
|
val = 0.25;
|
|
}
|
|
}
|
|
|
|
// clear impulses
|
|
key->state &= 1;
|
|
return val;
|
|
}
|
|
|
|
/*
|
|
================
|
|
CL_AdjustAngles
|
|
|
|
Moves the local angle positions
|
|
================
|
|
*/
|
|
void CL_AdjustAngles( float frametime, float *viewangles )
|
|
{
|
|
float speed;
|
|
float up, down;
|
|
|
|
if( in_speed.state & 1 )
|
|
{
|
|
speed = frametime * cl_anglespeedkey->value;
|
|
}
|
|
else
|
|
{
|
|
speed = frametime;
|
|
}
|
|
|
|
if( !( in_strafe.state & 1 ) )
|
|
{
|
|
viewangles[YAW] -= speed * cl_yawspeed->value * CL_KeyState( &in_right );
|
|
viewangles[YAW] += speed * cl_yawspeed->value * CL_KeyState( &in_left );
|
|
viewangles[YAW] = anglemod( viewangles[YAW] );
|
|
}
|
|
|
|
if( in_klook.state & 1 )
|
|
{
|
|
viewangles[PITCH] -= speed * cl_pitchspeed->value * CL_KeyState( &in_forward );
|
|
viewangles[PITCH] += speed * cl_pitchspeed->value * CL_KeyState( &in_back );
|
|
}
|
|
|
|
up = CL_KeyState( &in_lookup );
|
|
down = CL_KeyState( &in_lookdown );
|
|
|
|
viewangles[PITCH] -= speed * cl_pitchspeed->value * up;
|
|
viewangles[PITCH] += speed * cl_pitchspeed->value * down;
|
|
|
|
if( viewangles[PITCH] > cl_pitchdown->value )
|
|
viewangles[PITCH] = cl_pitchdown->value;
|
|
if( viewangles[PITCH] < -cl_pitchup->value )
|
|
viewangles[PITCH] = -cl_pitchup->value;
|
|
|
|
if( viewangles[ROLL] > 50 )
|
|
viewangles[ROLL] = 50;
|
|
if( viewangles[ROLL] < -50 )
|
|
viewangles[ROLL] = -50;
|
|
}
|
|
|
|
/*
|
|
================
|
|
CL_CreateMove
|
|
|
|
Send the intended movement message to the server
|
|
if active == 1 then we are 1) not playing back demos ( where our commands are ignored ) and
|
|
2 ) we have finished signing on to server
|
|
================
|
|
*/
|
|
void DLLEXPORT CL_CreateMove( float frametime, struct usercmd_s *cmd, int active )
|
|
{
|
|
float spd;
|
|
vec3_t viewangles;
|
|
static vec3_t oldangles;
|
|
|
|
if( active )
|
|
{
|
|
//memset( viewangles, 0, sizeof(vec3_t) );
|
|
//viewangles[0] = viewangles[1] = viewangles[2] = 0.0;
|
|
gEngfuncs.GetViewAngles( (float *)viewangles );
|
|
|
|
CL_AdjustAngles( frametime, viewangles );
|
|
|
|
memset( cmd, 0, sizeof(*cmd) );
|
|
|
|
gEngfuncs.SetViewAngles( (float *)viewangles );
|
|
|
|
if( in_strafe.state & 1 )
|
|
{
|
|
cmd->sidemove += cl_sidespeed->value * CL_KeyState( &in_right );
|
|
cmd->sidemove -= cl_sidespeed->value * CL_KeyState( &in_left );
|
|
}
|
|
|
|
cmd->sidemove += cl_sidespeed->value * CL_KeyState( &in_moveright );
|
|
cmd->sidemove -= cl_sidespeed->value * CL_KeyState( &in_moveleft );
|
|
|
|
cmd->upmove += cl_upspeed->value * CL_KeyState( &in_up );
|
|
cmd->upmove -= cl_upspeed->value * CL_KeyState( &in_down );
|
|
|
|
if( !(in_klook.state & 1 ) )
|
|
{
|
|
cmd->forwardmove += cl_forwardspeed->value * CL_KeyState( &in_forward );
|
|
cmd->forwardmove -= cl_backspeed->value * CL_KeyState( &in_back );
|
|
}
|
|
|
|
// adjust for speed key
|
|
if( in_speed.state & 1 )
|
|
{
|
|
cmd->forwardmove *= cl_movespeedkey->value;
|
|
cmd->sidemove *= cl_movespeedkey->value;
|
|
cmd->upmove *= cl_movespeedkey->value;
|
|
}
|
|
|
|
// clip to maxspeed
|
|
spd = gEngfuncs.GetClientMaxspeed();
|
|
if( spd != 0.0f )
|
|
{
|
|
// scale the 3 speeds so that the total velocity is not > cl.maxspeed
|
|
float fmov = sqrt( ( cmd->forwardmove * cmd->forwardmove ) + ( cmd->sidemove * cmd->sidemove ) + ( cmd->upmove * cmd->upmove ) );
|
|
|
|
if( fmov > spd )
|
|
{
|
|
float fratio = spd / fmov;
|
|
cmd->forwardmove *= fratio;
|
|
cmd->sidemove *= fratio;
|
|
cmd->upmove *= fratio;
|
|
}
|
|
}
|
|
|
|
// Allow mice and other controllers to add their inputs
|
|
IN_Move( frametime, cmd );
|
|
}
|
|
|
|
cmd->impulse = in_impulse;
|
|
in_impulse = 0;
|
|
|
|
cmd->weaponselect = g_weaponselect;
|
|
g_weaponselect = 0;
|
|
//
|
|
// set button and flag bits
|
|
//
|
|
cmd->buttons = CL_ButtonBits( 1 );
|
|
|
|
// Using joystick?
|
|
if( in_joystick->value )
|
|
{
|
|
if( cmd->forwardmove > 0 )
|
|
{
|
|
cmd->buttons |= IN_FORWARD;
|
|
}
|
|
else if( cmd->forwardmove < 0 )
|
|
{
|
|
cmd->buttons |= IN_BACK;
|
|
}
|
|
}
|
|
|
|
gEngfuncs.GetViewAngles( (float *)viewangles );
|
|
// Set current view angles.
|
|
|
|
if( g_iAlive )
|
|
{
|
|
VectorCopy( viewangles, cmd->viewangles );
|
|
VectorCopy( viewangles, oldangles );
|
|
}
|
|
else
|
|
{
|
|
VectorCopy( oldangles, cmd->viewangles );
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
============
|
|
CL_IsDead
|
|
|
|
Returns 1 if health is <= 0
|
|
============
|
|
*/
|
|
int CL_IsDead( void )
|
|
{
|
|
return ( gHUD.m_Health.m_iHealth <= 0 ) ? 1 : 0;
|
|
}
|
|
|
|
/*
|
|
============
|
|
CL_ButtonBits
|
|
|
|
Returns appropriate button info for keyboard and mouse state
|
|
Set bResetState to 1 to clear old state info
|
|
============
|
|
*/
|
|
int CL_ButtonBits( int bResetState )
|
|
{
|
|
int bits = 0;
|
|
|
|
if( in_attack.state & 3 )
|
|
{
|
|
if( gHUD.m_MOTD.m_bShow )
|
|
gHUD.m_MOTD.Reset();
|
|
else
|
|
bits |= IN_ATTACK;
|
|
}
|
|
|
|
if( in_duck.state & 3 )
|
|
{
|
|
bits |= IN_DUCK;
|
|
}
|
|
|
|
if( in_jump.state & 3 )
|
|
{
|
|
bits |= IN_JUMP;
|
|
}
|
|
|
|
if( in_forward.state & 3 )
|
|
{
|
|
bits |= IN_FORWARD;
|
|
}
|
|
|
|
if( in_back.state & 3 )
|
|
{
|
|
bits |= IN_BACK;
|
|
}
|
|
|
|
if( in_use.state & 3 )
|
|
{
|
|
bits |= IN_USE;
|
|
}
|
|
|
|
if( in_cancel )
|
|
{
|
|
bits |= IN_CANCEL;
|
|
}
|
|
|
|
if( in_left.state & 3 )
|
|
{
|
|
bits |= IN_LEFT;
|
|
}
|
|
|
|
if( in_right.state & 3 )
|
|
{
|
|
bits |= IN_RIGHT;
|
|
}
|
|
|
|
if( in_moveleft.state & 3 )
|
|
{
|
|
bits |= IN_MOVELEFT;
|
|
}
|
|
|
|
if( in_moveright.state & 3 )
|
|
{
|
|
bits |= IN_MOVERIGHT;
|
|
}
|
|
|
|
if( in_attack2.state & 3 )
|
|
{
|
|
bits |= IN_ATTACK2;
|
|
}
|
|
|
|
if( in_reload.state & 3 )
|
|
{
|
|
bits |= IN_RELOAD;
|
|
}
|
|
|
|
if( in_alt1.state & 3 )
|
|
{
|
|
bits |= IN_ALT1;
|
|
}
|
|
|
|
if( in_score.state & 3 )
|
|
{
|
|
bits |= IN_SCORE;
|
|
}
|
|
|
|
// Dead or in intermission? Shore scoreboard, too
|
|
if( CL_IsDead() || gHUD.m_iIntermission )
|
|
{
|
|
bits |= IN_SCORE;
|
|
}
|
|
|
|
if( bResetState )
|
|
{
|
|
in_attack.state &= ~2;
|
|
in_duck.state &= ~2;
|
|
in_jump.state &= ~2;
|
|
in_forward.state &= ~2;
|
|
in_back.state &= ~2;
|
|
in_use.state &= ~2;
|
|
in_left.state &= ~2;
|
|
in_right.state &= ~2;
|
|
in_moveleft.state &= ~2;
|
|
in_moveright.state &= ~2;
|
|
in_attack2.state &= ~2;
|
|
in_reload.state &= ~2;
|
|
in_alt1.state &= ~2;
|
|
in_score.state &= ~2;
|
|
}
|
|
|
|
return bits;
|
|
}
|
|
|
|
/*
|
|
============
|
|
CL_ResetButtonBits
|
|
|
|
============
|
|
*/
|
|
void CL_ResetButtonBits( int bits )
|
|
{
|
|
int bitsNew = CL_ButtonBits( 0 ) ^ bits;
|
|
|
|
// Has the attack button been changed
|
|
if( bitsNew & IN_ATTACK )
|
|
{
|
|
// Was it pressed? or let go?
|
|
if( bits & IN_ATTACK )
|
|
{
|
|
KeyDown( &in_attack );
|
|
}
|
|
else
|
|
{
|
|
// totally clear state
|
|
in_attack.state &= ~7;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
InitInput
|
|
============
|
|
*/
|
|
void InitInput( void )
|
|
{
|
|
gEngfuncs.pfnAddCommand( "+moveup", IN_UpDown );
|
|
gEngfuncs.pfnAddCommand( "-moveup", IN_UpUp );
|
|
gEngfuncs.pfnAddCommand( "+movedown", IN_DownDown );
|
|
gEngfuncs.pfnAddCommand( "-movedown", IN_DownUp );
|
|
gEngfuncs.pfnAddCommand( "+left", IN_LeftDown );
|
|
gEngfuncs.pfnAddCommand( "-left", IN_LeftUp );
|
|
gEngfuncs.pfnAddCommand( "+right", IN_RightDown );
|
|
gEngfuncs.pfnAddCommand( "-right", IN_RightUp );
|
|
gEngfuncs.pfnAddCommand( "+forward", IN_ForwardDown );
|
|
gEngfuncs.pfnAddCommand( "-forward", IN_ForwardUp );
|
|
gEngfuncs.pfnAddCommand( "+back", IN_BackDown );
|
|
gEngfuncs.pfnAddCommand( "-back", IN_BackUp );
|
|
gEngfuncs.pfnAddCommand( "+lookup", IN_LookupDown );
|
|
gEngfuncs.pfnAddCommand( "-lookup", IN_LookupUp );
|
|
gEngfuncs.pfnAddCommand( "+lookdown", IN_LookdownDown );
|
|
gEngfuncs.pfnAddCommand( "-lookdown", IN_LookdownUp );
|
|
gEngfuncs.pfnAddCommand( "+strafe", IN_StrafeDown );
|
|
gEngfuncs.pfnAddCommand( "-strafe", IN_StrafeUp );
|
|
gEngfuncs.pfnAddCommand( "+moveleft", IN_MoveleftDown );
|
|
gEngfuncs.pfnAddCommand( "-moveleft", IN_MoveleftUp );
|
|
gEngfuncs.pfnAddCommand( "+moveright", IN_MoverightDown );
|
|
gEngfuncs.pfnAddCommand( "-moveright", IN_MoverightUp );
|
|
gEngfuncs.pfnAddCommand( "+speed", IN_SpeedDown );
|
|
gEngfuncs.pfnAddCommand( "-speed", IN_SpeedUp );
|
|
gEngfuncs.pfnAddCommand( "+attack", IN_AttackDown );
|
|
gEngfuncs.pfnAddCommand( "-attack", IN_AttackUp );
|
|
gEngfuncs.pfnAddCommand( "+attack2", IN_Attack2Down );
|
|
gEngfuncs.pfnAddCommand( "-attack2", IN_Attack2Up );
|
|
gEngfuncs.pfnAddCommand( "+use", IN_UseDown );
|
|
gEngfuncs.pfnAddCommand( "-use", IN_UseUp );
|
|
gEngfuncs.pfnAddCommand( "+jump", IN_JumpDown );
|
|
gEngfuncs.pfnAddCommand( "-jump", IN_JumpUp );
|
|
gEngfuncs.pfnAddCommand( "impulse", IN_Impulse );
|
|
gEngfuncs.pfnAddCommand( "+klook", IN_KLookDown );
|
|
gEngfuncs.pfnAddCommand( "-klook", IN_KLookUp );
|
|
gEngfuncs.pfnAddCommand( "+mlook", IN_MLookDown );
|
|
gEngfuncs.pfnAddCommand( "-mlook", IN_MLookUp );
|
|
gEngfuncs.pfnAddCommand( "+jlook", IN_JLookDown );
|
|
gEngfuncs.pfnAddCommand( "-jlook", IN_JLookUp );
|
|
gEngfuncs.pfnAddCommand( "+duck", IN_DuckDown );
|
|
gEngfuncs.pfnAddCommand( "-duck", IN_DuckUp );
|
|
gEngfuncs.pfnAddCommand( "+reload", IN_ReloadDown );
|
|
gEngfuncs.pfnAddCommand( "-reload", IN_ReloadUp );
|
|
gEngfuncs.pfnAddCommand( "+alt1", IN_Alt1Down );
|
|
gEngfuncs.pfnAddCommand( "-alt1", IN_Alt1Up );
|
|
gEngfuncs.pfnAddCommand( "+graph", IN_GraphDown );
|
|
gEngfuncs.pfnAddCommand( "-graph", IN_GraphUp );
|
|
gEngfuncs.pfnAddCommand( "+break", IN_BreakDown );
|
|
gEngfuncs.pfnAddCommand( "-break", IN_BreakUp );
|
|
|
|
lookstrafe = gEngfuncs.pfnRegisterVariable( "lookstrafe", "0", FCVAR_ARCHIVE );
|
|
lookspring = gEngfuncs.pfnRegisterVariable( "lookspring", "0", FCVAR_ARCHIVE );
|
|
cl_anglespeedkey = gEngfuncs.pfnRegisterVariable( "cl_anglespeedkey", "0.67", 0 );
|
|
cl_yawspeed = gEngfuncs.pfnRegisterVariable( "cl_yawspeed", "210", 0 );
|
|
cl_pitchspeed = gEngfuncs.pfnRegisterVariable( "cl_pitchspeed", "225", 0 );
|
|
cl_upspeed = gEngfuncs.pfnRegisterVariable( "cl_upspeed", "320", 0 );
|
|
cl_forwardspeed = gEngfuncs.pfnRegisterVariable( "cl_forwardspeed", "400", FCVAR_ARCHIVE );
|
|
cl_backspeed = gEngfuncs.pfnRegisterVariable( "cl_backspeed", "400", FCVAR_ARCHIVE );
|
|
cl_sidespeed = gEngfuncs.pfnRegisterVariable( "cl_sidespeed", "400", 0 );
|
|
cl_movespeedkey = gEngfuncs.pfnRegisterVariable( "cl_movespeedkey", "0.3", 0 );
|
|
cl_pitchup = gEngfuncs.pfnRegisterVariable( "cl_pitchup", "89", 0 );
|
|
cl_pitchdown = gEngfuncs.pfnRegisterVariable( "cl_pitchdown", "89", 0 );
|
|
|
|
cl_vsmoothing = gEngfuncs.pfnRegisterVariable( "cl_vsmoothing", "0.05", FCVAR_ARCHIVE );
|
|
|
|
m_pitch = gEngfuncs.pfnRegisterVariable( "m_pitch","0.022", FCVAR_ARCHIVE );
|
|
m_yaw = gEngfuncs.pfnRegisterVariable( "m_yaw","0.022", FCVAR_ARCHIVE );
|
|
m_forward = gEngfuncs.pfnRegisterVariable( "m_forward","1", FCVAR_ARCHIVE );
|
|
m_side = gEngfuncs.pfnRegisterVariable( "m_side","0.8", FCVAR_ARCHIVE );
|
|
|
|
// Initialize third person camera controls.
|
|
CAM_Init();
|
|
// Initialize inputs
|
|
IN_Init();
|
|
// Initialize keyboard
|
|
KB_Init();
|
|
// Initialize view system
|
|
V_Init();
|
|
}
|
|
|
|
/*
|
|
============
|
|
ShutdownInput
|
|
============
|
|
*/
|
|
void ShutdownInput( void )
|
|
{
|
|
IN_Shutdown();
|
|
KB_Shutdown();
|
|
}
|
|
|
|
void DLLEXPORT HUD_Shutdown( void )
|
|
{
|
|
ShutdownInput();
|
|
}
|