Home | History | Annotate | Download | only in WinQuake
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // cl.input.c  -- builds an intended movement command to send to the server
     21 
     22 // Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
     23 // rights reserved.
     24 
     25 #include "quakedef.h"
     26 
     27 /*
     28 ===============================================================================
     29 
     30 KEY BUTTONS
     31 
     32 Continuous button event tracking is complicated by the fact that two different
     33 input sources (say, mouse button 1 and the control key) can both press the
     34 same button, but the button should only be released when both of the
     35 pressing key have been released.
     36 
     37 When a key event issues a button command (+forward, +attack, etc), it appends
     38 its key number as a parameter to the command so it can be matched up with
     39 the release.
     40 
     41 state bit 0 is the current state of the key
     42 state bit 1 is edge triggered on the up to down transition
     43 state bit 2 is edge triggered on the down to up transition
     44 
     45 ===============================================================================
     46 */
     47 
     48 
     49 kbutton_t	in_mlook, in_klook;
     50 kbutton_t	in_left, in_right, in_forward, in_back;
     51 kbutton_t	in_lookup, in_lookdown, in_moveleft, in_moveright;
     52 kbutton_t	in_strafe, in_speed, in_use, in_jump, in_attack;
     53 kbutton_t	in_up, in_down;
     54 
     55 int			in_impulse;
     56 
     57 
     58 void KeyDown (kbutton_t *b)
     59 {
     60 	int		k;
     61 	const char	*c;
     62 
     63 	c = Cmd_Argv(1);
     64 	if (c[0])
     65 		k = atoi(c);
     66 	else
     67 		k = -1;		// typed manually at the console for continuous down
     68 
     69 	if (k == b->down[0] || k == b->down[1])
     70 		return;		// repeating key
     71 
     72 	if (!b->down[0])
     73 		b->down[0] = k;
     74 	else if (!b->down[1])
     75 		b->down[1] = k;
     76 	else
     77 	{
     78 		Con_Printf ("Three keys down for a button!\n");
     79 		return;
     80 	}
     81 
     82 	if (b->state & 1)
     83 		return;		// still down
     84 	b->state |= 1 + 2;	// down + impulse down
     85 }
     86 
     87 void KeyUp (kbutton_t *b)
     88 {
     89 	int		k;
     90 	const char	*c;
     91 
     92 	c = Cmd_Argv(1);
     93 	if (c[0])
     94 		k = atoi(c);
     95 	else
     96 	{ // typed manually at the console, assume for unsticking, so clear all
     97 		b->down[0] = b->down[1] = 0;
     98 		b->state = 4;	// impulse up
     99 		return;
    100 	}
    101 
    102 	if (b->down[0] == k)
    103 		b->down[0] = 0;
    104 	else if (b->down[1] == k)
    105 		b->down[1] = 0;
    106 	else
    107 		return;		// key up without coresponding down (menu pass through)
    108 	if (b->down[0] || b->down[1])
    109 		return;		// some other key is still holding it down
    110 
    111 	if (!(b->state & 1))
    112 		return;		// still up (this should not happen)
    113 	b->state &= ~1;		// now up
    114 	b->state |= 4; 		// impulse up
    115 }
    116 
    117 void IN_KLookDown (void) {KeyDown(&in_klook);}
    118 void IN_KLookUp (void) {KeyUp(&in_klook);}
    119 void IN_MLookDown (void) {KeyDown(&in_mlook);}
    120 void IN_MLookUp (void) {
    121 KeyUp(&in_mlook);
    122 if ( !(in_mlook.state&1) &&  lookspring.value)
    123 	V_StartPitchDrift();
    124 }
    125 void IN_UpDown(void) {KeyDown(&in_up);}
    126 void IN_UpUp(void) {KeyUp(&in_up);}
    127 void IN_DownDown(void) {KeyDown(&in_down);}
    128 void IN_DownUp(void) {KeyUp(&in_down);}
    129 void IN_LeftDown(void) {KeyDown(&in_left);}
    130 void IN_LeftUp(void) {KeyUp(&in_left);}
    131 void IN_RightDown(void) {KeyDown(&in_right);}
    132 void IN_RightUp(void) {KeyUp(&in_right);}
    133 void IN_ForwardDown(void) {KeyDown(&in_forward);}
    134 void IN_ForwardUp(void) {KeyUp(&in_forward);}
    135 void IN_BackDown(void) {KeyDown(&in_back);}
    136 void IN_BackUp(void) {KeyUp(&in_back);}
    137 void IN_LookupDown(void) {KeyDown(&in_lookup);}
    138 void IN_LookupUp(void) {KeyUp(&in_lookup);}
    139 void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
    140 void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
    141 void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
    142 void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
    143 void IN_MoverightDown(void) {KeyDown(&in_moveright);}
    144 void IN_MoverightUp(void) {KeyUp(&in_moveright);}
    145 
    146 void IN_SpeedDown(void) {KeyDown(&in_speed);}
    147 void IN_SpeedUp(void) {KeyUp(&in_speed);}
    148 void IN_StrafeDown(void) {KeyDown(&in_strafe);}
    149 void IN_StrafeUp(void) {KeyUp(&in_strafe);}
    150 
    151 void IN_AttackDown(void) {KeyDown(&in_attack);}
    152 void IN_AttackUp(void) {KeyUp(&in_attack);}
    153 
    154 void IN_UseDown (void) {KeyDown(&in_use);}
    155 void IN_UseUp (void) {KeyUp(&in_use);}
    156 void IN_JumpDown (void) {KeyDown(&in_jump);}
    157 void IN_JumpUp (void) {KeyUp(&in_jump);}
    158 
    159 void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));}
    160 
    161 /*
    162 ===============
    163 CL_KeyState
    164 
    165 Returns 0.25 if a key was pressed and released during the frame,
    166 0.5 if it was pressed and held
    167 0 if held then released, and
    168 1.0 if held for the entire time
    169 ===============
    170 */
    171 float CL_KeyState (kbutton_t *key)
    172 {
    173 	float		val;
    174 	qboolean	impulsedown, impulseup, down;
    175 
    176 	impulsedown = key->state & 2;
    177 	impulseup = key->state & 4;
    178 	down = key->state & 1;
    179 	val = 0;
    180 
    181 	if (impulsedown && !impulseup)
    182 	{
    183 		if (down)
    184 			val = 0.5;	// pressed and held this frame
    185 		else
    186 			val = 0;	//	I_Error ();
    187 	}
    188 
    189 	if (impulseup && !impulsedown)
    190 	{
    191 		if (down)
    192 			val = 0;	//	I_Error ();
    193 		else
    194 			val = 0;	// released this frame
    195 	}
    196 
    197 	if (!impulsedown && !impulseup)
    198 	{
    199 		if (down)
    200 			val = 1.0;	// held the entire frame
    201 		else
    202 			val = 0;	// up the entire frame
    203 	}
    204 
    205 	if (impulsedown && impulseup)
    206 	{
    207 		if (down)
    208 			val = 0.75;	// released and re-pressed this frame
    209 		else
    210 			val = 0.25;	// pressed and released this frame
    211 	}
    212 
    213 	key->state &= 1;		// clear impulses
    214 
    215 	return val;
    216 }
    217 
    218 
    219 
    220 
    221 //==========================================================================
    222 
    223 cvar_t	cl_upspeed = CVAR2("cl_upspeed","200");
    224 cvar_t	cl_forwardspeed = CVAR3("cl_forwardspeed","200", true);
    225 cvar_t	cl_backspeed = CVAR3("cl_backspeed","200", true);
    226 cvar_t	cl_sidespeed = CVAR2("cl_sidespeed","350");
    227 
    228 cvar_t	cl_movespeedkey = CVAR2("cl_movespeedkey","2.0");
    229 
    230 cvar_t	cl_yawspeed = CVAR2("cl_yawspeed","140");
    231 cvar_t	cl_pitchspeed = CVAR2("cl_pitchspeed","150");
    232 
    233 cvar_t	cl_anglespeedkey = CVAR2("cl_anglespeedkey","1.5");
    234 
    235 
    236 /*
    237 ================
    238 CL_AdjustAngles
    239 
    240 Moves the local angle positions
    241 ================
    242 */
    243 void CL_AdjustAngles (void)
    244 {
    245 	float	speed;
    246 	float	up, down;
    247 
    248 	if (in_speed.state & 1)
    249 		speed = host_frametime * cl_anglespeedkey.value;
    250 	else
    251 		speed = host_frametime;
    252 
    253 	if (!(in_strafe.state & 1))
    254 	{
    255 		cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right);
    256 		cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left);
    257 		cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
    258 	}
    259 	if (in_klook.state & 1)
    260 	{
    261 		V_StopPitchDrift ();
    262 		cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
    263 		cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
    264 	}
    265 
    266 	up = CL_KeyState (&in_lookup);
    267 	down = CL_KeyState(&in_lookdown);
    268 
    269 	cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
    270 	cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
    271 
    272 	if (up || down)
    273 		V_StopPitchDrift ();
    274 
    275 	if (cl.viewangles[PITCH] > 80)
    276 		cl.viewangles[PITCH] = 80;
    277 	if (cl.viewangles[PITCH] < -70)
    278 		cl.viewangles[PITCH] = -70;
    279 
    280 	if (cl.viewangles[ROLL] > 50)
    281 		cl.viewangles[ROLL] = 50;
    282 	if (cl.viewangles[ROLL] < -50)
    283 		cl.viewangles[ROLL] = -50;
    284 
    285 }
    286 
    287 /*
    288 ================
    289 CL_BaseMove
    290 
    291 Send the intended movement message to the server
    292 ================
    293 */
    294 void CL_BaseMove (usercmd_t *cmd)
    295 {
    296 	if (cls.signon != SIGNONS)
    297 		return;
    298 
    299 	CL_AdjustAngles ();
    300 
    301 	Q_memset (cmd, 0, sizeof(*cmd));
    302 
    303 	if (in_strafe.state & 1)
    304 	{
    305 		cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
    306 		cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
    307 	}
    308 
    309 	cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
    310 	cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
    311 
    312 	cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
    313 	cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
    314 
    315 	if (! (in_klook.state & 1) )
    316 	{
    317 		cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
    318 		cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
    319 	}
    320 
    321 //
    322 // adjust for speed key
    323 //
    324 	if (in_speed.state & 1)
    325 	{
    326 		cmd->forwardmove *= cl_movespeedkey.value;
    327 		cmd->sidemove *= cl_movespeedkey.value;
    328 		cmd->upmove *= cl_movespeedkey.value;
    329 	}
    330 
    331 #ifdef QUAKE2
    332 	cmd->lightlevel = cl.light_level;
    333 #endif
    334 }
    335 
    336 
    337 
    338 /*
    339 ==============
    340 CL_SendMove
    341 ==============
    342 */
    343 void CL_SendMove (usercmd_t *cmd)
    344 {
    345 	int		i;
    346 	int		bits;
    347 	sizebuf_t	buf;
    348 	byte	data[128];
    349 
    350 	buf.maxsize = 128;
    351 	buf.cursize = 0;
    352 	buf.data = data;
    353 
    354 	cl.cmd = *cmd;
    355 
    356 //
    357 // send the movement message
    358 //
    359     MSG_WriteByte (&buf, clc_move);
    360 
    361 	MSG_WriteFloat (&buf, cl.mtime[0]);	// so server can get ping times
    362 
    363 	for (i=0 ; i<3 ; i++)
    364 		MSG_WriteAngle (&buf, cl.viewangles[i]);
    365 
    366     MSG_WriteShort (&buf, (short) cmd->forwardmove);
    367     MSG_WriteShort (&buf, (short) cmd->sidemove);
    368     MSG_WriteShort (&buf, (short) cmd->upmove);
    369 
    370 //
    371 // send button bits
    372 //
    373 	bits = 0;
    374 
    375 	if ( in_attack.state & 3 )
    376 		bits |= 1;
    377 	in_attack.state &= ~2;
    378 
    379 	if (in_jump.state & 3)
    380 		bits |= 2;
    381 	in_jump.state &= ~2;
    382 
    383     MSG_WriteByte (&buf, bits);
    384 
    385     MSG_WriteByte (&buf, in_impulse);
    386 	in_impulse = 0;
    387 
    388 #ifdef QUAKE2
    389 //
    390 // light level
    391 //
    392 	MSG_WriteByte (&buf, cmd->lightlevel);
    393 #endif
    394 
    395 //
    396 // deliver the message
    397 //
    398 	if (cls.demoplayback)
    399 		return;
    400 
    401 //
    402 // allways dump the first two message, because it may contain leftover inputs
    403 // from the last level
    404 //
    405 	if (++cl.movemessages <= 2)
    406 		return;
    407 
    408 	if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1)
    409 	{
    410 		Con_Printf ("CL_SendMove: lost server connection\n");
    411 		CL_Disconnect ();
    412 	}
    413 }
    414 
    415 /*
    416 ============
    417 CL_InitInput
    418 ============
    419 */
    420 void CL_InitInput (void)
    421 {
    422 	Cmd_AddCommand ("+moveup",IN_UpDown);
    423 	Cmd_AddCommand ("-moveup",IN_UpUp);
    424 	Cmd_AddCommand ("+movedown",IN_DownDown);
    425 	Cmd_AddCommand ("-movedown",IN_DownUp);
    426 	Cmd_AddCommand ("+left",IN_LeftDown);
    427 	Cmd_AddCommand ("-left",IN_LeftUp);
    428 	Cmd_AddCommand ("+right",IN_RightDown);
    429 	Cmd_AddCommand ("-right",IN_RightUp);
    430 	Cmd_AddCommand ("+forward",IN_ForwardDown);
    431 	Cmd_AddCommand ("-forward",IN_ForwardUp);
    432 	Cmd_AddCommand ("+back",IN_BackDown);
    433 	Cmd_AddCommand ("-back",IN_BackUp);
    434 	Cmd_AddCommand ("+lookup", IN_LookupDown);
    435 	Cmd_AddCommand ("-lookup", IN_LookupUp);
    436 	Cmd_AddCommand ("+lookdown", IN_LookdownDown);
    437 	Cmd_AddCommand ("-lookdown", IN_LookdownUp);
    438 	Cmd_AddCommand ("+strafe", IN_StrafeDown);
    439 	Cmd_AddCommand ("-strafe", IN_StrafeUp);
    440 	Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
    441 	Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
    442 	Cmd_AddCommand ("+moveright", IN_MoverightDown);
    443 	Cmd_AddCommand ("-moveright", IN_MoverightUp);
    444 	Cmd_AddCommand ("+speed", IN_SpeedDown);
    445 	Cmd_AddCommand ("-speed", IN_SpeedUp);
    446 	Cmd_AddCommand ("+attack", IN_AttackDown);
    447 	Cmd_AddCommand ("-attack", IN_AttackUp);
    448 	Cmd_AddCommand ("+use", IN_UseDown);
    449 	Cmd_AddCommand ("-use", IN_UseUp);
    450 	Cmd_AddCommand ("+jump", IN_JumpDown);
    451 	Cmd_AddCommand ("-jump", IN_JumpUp);
    452 	Cmd_AddCommand ("impulse", IN_Impulse);
    453 	Cmd_AddCommand ("+klook", IN_KLookDown);
    454 	Cmd_AddCommand ("-klook", IN_KLookUp);
    455 	Cmd_AddCommand ("+mlook", IN_MLookDown);
    456 	Cmd_AddCommand ("-mlook", IN_MLookUp);
    457 
    458 }
    459 
    460