1 /*
2  * cl.input.c -- builds an intended movement command to send to the server
3  * $Id: cl_input.c,v 1.15 2008-03-21 18:00:07 sezero Exp $
4  *
5  * Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc.
6  * All rights reserved.
7  * Copyright (C) 1996-1997  Id Software, Inc.
8  * Copyright (C) 1997-1998  Raven Software Corp.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * See the GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24  */
25 
26 
27 #include "quakedef.h"
28 
29 static	cvar_t	cl_nodelta = {"cl_nodelta", "0", CVAR_NONE};
30 
31 /*
32 ===============================================================================
33 
34 KEY BUTTONS
35 
36 Continuous button event tracking is complicated by the fact that two different
37 input sources (say, mouse button 1 and the control key) can both press the
38 same button, but the button should only be released when both of the
39 pressing key have been released.
40 
41 When a key event issues a button command (+forward, +attack, etc), it appends
42 its key number as a parameter to the command so it can be matched up with
43 the release.
44 
45 state bit 0 is the current state of the key
46 state bit 1 is edge triggered on the up to down transition
47 state bit 2 is edge triggered on the down to up transition
48 
49 ===============================================================================
50 */
51 
52 kbutton_t	in_mlook, in_klook;
53 kbutton_t	in_left, in_right, in_forward, in_back;
54 kbutton_t	in_lookup, in_lookdown, in_moveleft, in_moveright;
55 kbutton_t	in_strafe, in_speed, in_use, in_jump, in_attack;
56 kbutton_t	in_up, in_down, in_crouch;
57 
58 int		in_impulse;
59 
KeyDown(kbutton_t * b)60 static void KeyDown (kbutton_t *b)
61 {
62 	int		k;
63 	const char	*c;
64 
65 	c = Cmd_Argv(1);
66 	if (c[0])
67 		k = atoi(c);
68 	else	k = -1;		// typed manually at the console for continuous down
69 
70 	if (k == b->down[0] || k == b->down[1])
71 		return;		// repeating key
72 
73 	if (!b->down[0])
74 		b->down[0] = k;
75 	else if (!b->down[1])
76 		b->down[1] = k;
77 	else
78 	{
79 		Con_Printf ("Three keys down for a button!\n");
80 		return;
81 	}
82 
83 	if (b->state & 1)
84 		return;		// still down
85 	b->state |= 1 + 2;	// down + impulse down
86 }
87 
KeyUp(kbutton_t * b)88 static void KeyUp (kbutton_t *b)
89 {
90 	int		k;
91 	const char	*c;
92 
93 	c = Cmd_Argv(1);
94 	if (c[0])
95 	{
96 		k = atoi(c);
97 	}
98 	else
99 	{ // typed manually at the console, assume for unsticking, so clear all
100 		b->down[0] = b->down[1] = 0;
101 		b->state = 4;	// impulse up
102 		return;
103 	}
104 
105 	if (b->down[0] == k)
106 		b->down[0] = 0;
107 	else if (b->down[1] == k)
108 		b->down[1] = 0;
109 	else	return;		// key up without coresponding down (menu pass through)
110 
111 	if (b->down[0] || b->down[1])
112 		return;		// some other key is still holding it down
113 
114 	if (!(b->state & 1))
115 		return;		// still up (this should not happen)
116 
117 	b->state &= ~1;		// now up
118 	b->state |= 4; 		// impulse up
119 }
120 
IN_KLookDown(void)121 static void IN_KLookDown (void)
122 {
123 	KeyDown(&in_klook);
124 }
125 
IN_KLookUp(void)126 static void IN_KLookUp (void)
127 {
128 	KeyUp(&in_klook);
129 }
130 
IN_MLookDown(void)131 static void IN_MLookDown (void)
132 {
133 	KeyDown(&in_mlook);
134 }
135 
IN_MLookUp(void)136 static void IN_MLookUp (void)
137 {
138 	KeyUp(&in_mlook);
139 	if (!(in_mlook.state & 1) && lookspring.integer)
140 		V_StartPitchDrift();
141 }
142 
IN_UpDown(void)143 static void IN_UpDown (void)
144 {
145 	KeyDown(&in_up);
146 }
147 
IN_UpUp(void)148 static void IN_UpUp (void)
149 {
150 	KeyUp(&in_up);
151 }
152 
IN_DownDown(void)153 static void IN_DownDown (void)
154 {
155 	KeyDown(&in_down);
156 }
157 
IN_DownUp(void)158 static void IN_DownUp (void)
159 {
160 	KeyUp(&in_down);
161 }
162 
IN_LeftDown(void)163 static void IN_LeftDown (void)
164 {
165 	KeyDown(&in_left);
166 }
167 
IN_LeftUp(void)168 static void IN_LeftUp (void)
169 {
170 	KeyUp(&in_left);
171 }
172 
IN_RightDown(void)173 static void IN_RightDown (void)
174 {
175 	KeyDown(&in_right);
176 }
177 
IN_RightUp(void)178 static void IN_RightUp (void)
179 {
180 	KeyUp(&in_right);
181 }
182 
IN_ForwardDown(void)183 static void IN_ForwardDown (void)
184 {
185 	KeyDown(&in_forward);
186 }
187 
IN_ForwardUp(void)188 static void IN_ForwardUp (void)
189 {
190 	KeyUp(&in_forward);
191 }
192 
IN_BackDown(void)193 static void IN_BackDown (void)
194 {
195 	KeyDown(&in_back);
196 }
197 
IN_BackUp(void)198 static void IN_BackUp (void)
199 {
200 	KeyUp(&in_back);
201 }
202 
IN_LookupDown(void)203 static void IN_LookupDown (void)
204 {
205 	KeyDown(&in_lookup);
206 }
207 
IN_LookupUp(void)208 static void IN_LookupUp (void)
209 {
210 	KeyUp(&in_lookup);
211 }
212 
IN_LookdownDown(void)213 static void IN_LookdownDown (void)
214 {
215 	KeyDown(&in_lookdown);
216 }
217 
IN_LookdownUp(void)218 static void IN_LookdownUp (void)
219 {
220 	KeyUp(&in_lookdown);
221 }
222 
IN_MoveleftDown(void)223 static void IN_MoveleftDown (void)
224 {
225 	KeyDown(&in_moveleft);
226 }
227 
IN_MoveleftUp(void)228 static void IN_MoveleftUp (void)
229 {
230 	KeyUp(&in_moveleft);
231 }
232 
IN_MoverightDown(void)233 static void IN_MoverightDown (void)
234 {
235 	KeyDown(&in_moveright);
236 }
237 
IN_MoverightUp(void)238 static void IN_MoverightUp (void)
239 {
240 	KeyUp(&in_moveright);
241 }
242 
IN_SpeedDown(void)243 static void IN_SpeedDown (void)
244 {
245 	KeyDown(&in_speed);
246 }
247 
IN_SpeedUp(void)248 static void IN_SpeedUp (void)
249 {
250 	KeyUp(&in_speed);
251 }
252 
IN_StrafeDown(void)253 static void IN_StrafeDown (void)
254 {
255 	KeyDown(&in_strafe);
256 }
257 
IN_StrafeUp(void)258 static void IN_StrafeUp (void)
259 {
260 	KeyUp(&in_strafe);
261 }
262 
IN_AttackDown(void)263 static void IN_AttackDown (void)
264 {
265 	KeyDown(&in_attack);
266 }
267 
IN_AttackUp(void)268 static void IN_AttackUp (void)
269 {
270 	KeyUp(&in_attack);
271 }
272 
IN_UseDown(void)273 static void IN_UseDown (void)
274 {
275 	KeyDown(&in_use);
276 }
277 
IN_UseUp(void)278 static void IN_UseUp (void)
279 {
280 	KeyUp(&in_use);
281 }
282 
IN_JumpDown(void)283 static void IN_JumpDown (void)
284 {
285 	KeyDown(&in_jump);
286 }
287 
IN_JumpUp(void)288 static void IN_JumpUp (void)
289 {
290 	KeyUp(&in_jump);
291 }
292 
IN_Impulse(void)293 static void IN_Impulse (void)
294 {
295 	in_impulse = atoi(Cmd_Argv(1));
296 }
297 
IN_CrouchDown(void)298 static void IN_CrouchDown (void)
299 {
300 	if (Key_GetDest() == key_game)
301 	{
302 //		int state = in_crouch.state;
303 		KeyDown(&in_crouch);
304 //		if (!(state & 1) && (in_crouch.state & 1))
305 //			in_impulse = 22;
306 	}
307 }
308 
IN_CrouchUp(void)309 static void IN_CrouchUp (void)
310 {
311 //	if (Key_GetDest() == key_game)
312 //	{
313 //		int state = in_crouch.state;
314 		KeyUp(&in_crouch);
315 //		if ((state & 1) && !(in_crouch.state & 1))
316 //			in_impulse = 22;
317 //	}
318 }
319 
320 /*
321 ===============
322 CL_KeyState
323 
324 Returns 0.25 if a key was pressed and released during the frame,
325 0.5 if it was pressed and held
326 0 if held then released, and
327 1.0 if held for the entire time
328 ===============
329 */
CL_KeyState(kbutton_t * key)330 static float CL_KeyState (kbutton_t *key)
331 {
332 	float		val;
333 	qboolean	impulsedown, impulseup, down;
334 
335 	impulsedown = key->state & 2;
336 	impulseup = key->state & 4;
337 	down = key->state & 1;
338 	val = 0;
339 
340 	if (impulsedown && !impulseup)
341 	{
342 		if (down)
343 			val = 0.5;	// pressed and held this frame
344 		else	val = 0;
345 	}
346 	if (impulseup && !impulsedown)
347 	{
348 		if (down)
349 			val = 0;
350 		else	val = 0;	// released this frame
351 	}
352 	if (!impulsedown && !impulseup)
353 	{
354 		if (down)
355 			val = 1.0;	// held the entire frame
356 		else	val = 0;	// up the entire frame
357 	}
358 	if (impulsedown && impulseup)
359 	{
360 		if (down)
361 			val = 0.75;	// released and re-pressed this frame
362 		else	val = 0.25;	// pressed and released this frame
363 	}
364 
365 	key->state &= 1;		// clear impulses
366 
367 	return val;
368 }
369 
370 
371 //==========================================================================
372 
373 cvar_t	cl_upspeed = {"cl_upspeed", "200", CVAR_NONE};
374 cvar_t	cl_forwardspeed = {"cl_forwardspeed", "200", CVAR_ARCHIVE};
375 cvar_t	cl_backspeed = {"cl_backspeed", "200", CVAR_ARCHIVE};
376 cvar_t	cl_sidespeed = {"cl_sidespeed", "225", CVAR_NONE};
377 cvar_t	cl_movespeedkey = {"cl_movespeedkey", "2.0", CVAR_NONE};
378 cvar_t	cl_yawspeed = {"cl_yawspeed", "140", CVAR_NONE};
379 cvar_t	cl_pitchspeed = {"cl_pitchspeed", "150", CVAR_NONE};
380 cvar_t	cl_anglespeedkey = {"cl_anglespeedkey", "1.5", CVAR_NONE};
381 
382 
383 /*
384 ================
385 CL_AdjustAngles
386 
387 Moves the local angle positions
388 ================
389 */
CL_AdjustAngles(void)390 static void CL_AdjustAngles (void)
391 {
392 	float	speed;
393 	float	up, down;
394 
395 	if ((in_speed.state & 1) || cl.spectator)
396 		speed = host_frametime * cl_anglespeedkey.value;
397 	else	speed = host_frametime;
398 
399 	if (!(in_strafe.state & 1))
400 	{
401 		cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right);
402 		cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left);
403 		cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
404 	}
405 	if (in_klook.state & 1)
406 	{
407 		V_StopPitchDrift ();
408 		cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
409 		cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
410 	}
411 
412 // FIXME: This is a cheap way of doing this, it belongs in V_CalcViewRoll
413 // but I don't see where I can get the yaw velocity.
414 	cl.idealroll = 0;
415 	if (cl.v.movetype == MOVETYPE_FLY)
416 	{
417 		if (CL_KeyState (&in_left) != 0)
418 			cl.idealroll = -10;
419 		else if (CL_KeyState (&in_right) != 0)
420 			cl.idealroll = 10;
421 	}
422 
423 	up = CL_KeyState (&in_lookup);
424 	down = CL_KeyState(&in_lookdown);
425 
426 	cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
427 	cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
428 
429 	if (up || down)
430 		V_StopPitchDrift ();
431 
432 	if (cl.viewangles[PITCH] > 80)
433 		cl.viewangles[PITCH] = 80;
434 	if (cl.viewangles[PITCH] < -70)
435 		cl.viewangles[PITCH] = -70;
436 
437 	if (cl.viewangles[ROLL] > 50)
438 		cl.viewangles[ROLL] = 50;
439 	if (cl.viewangles[ROLL] < -50)
440 		cl.viewangles[ROLL] = -50;
441 }
442 
443 /*
444 ================
445 CL_BaseMove
446 
447 Send the intended movement message to the server
448 ================
449 */
CL_BaseMove(usercmd_t * cmd)450 void CL_BaseMove (usercmd_t *cmd)
451 {
452 	if (cl.v.cameramode)	// stuck in a different camera so don't move
453 	{
454 		memset (cmd, 0, sizeof(*cmd));
455 		return;
456 	}
457 
458 	CL_AdjustAngles ();
459 
460 	memset (cmd, 0, sizeof(*cmd));
461 	VectorCopy (cl.viewangles, cmd->angles);
462 
463 	if (in_strafe.state & 1)
464 	{
465 //		cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
466 //		cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
467 		cmd->sidemove += 225 * CL_KeyState (&in_right);
468 		cmd->sidemove -= 225 * CL_KeyState (&in_left);
469 	}
470 
471 //	cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
472 //	cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
473 	cmd->sidemove += 225 * CL_KeyState (&in_moveright);
474 	cmd->sidemove -= 225 * CL_KeyState (&in_moveleft);
475 
476 	cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
477 	cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
478 
479 	if (! (in_klook.state & 1))
480 	{
481 //		cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
482 		cmd->forwardmove += 200 * CL_KeyState (&in_forward);
483 //		cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
484 		cmd->forwardmove -= 200 * CL_KeyState (&in_back);
485 	}
486 
487 // adjust for speed key, but not if "always run" has been chosen
488 // speed key now acts as slow key when always run is chosen - OS
489 //	if ( ( (cl_forwardspeed.value > 200) ||(in_speed.state & 1)  || cl.spectator)
490 	if ( (((cl_forwardspeed.value > 200) ^ (in_speed.state & 1)) || cl.spectator)
491 					     && (cl.v.hasted <= 1) )
492 	{
493 		cmd->forwardmove *= cl_movespeedkey.value;
494 		cmd->sidemove *= cl_movespeedkey.value;
495 		cmd->upmove *= cl_movespeedkey.value;
496 	}
497 
498 // Hasted player?
499 	if (cl.v.hasted)
500 	{
501 		cmd->forwardmove = cmd->forwardmove * cl.v.hasted;
502 		cmd->sidemove = cmd->sidemove * cl.v.hasted;
503 		cmd->upmove = cmd->upmove * cl.v.hasted;
504 	}
505 
506 	cmd->light_level = cl.light_level;
507 }
508 
MakeChar(int i)509 static int MakeChar (int i)
510 {
511 	i &= ~3;
512 	if (i < -127*4)
513 		i = -127*4;
514 	if (i > 127*4)
515 		i = 127*4;
516 	return i;
517 }
518 
519 /*
520 ==============
521 CL_FinishMove
522 ==============
523 */
CL_FinishMove(usercmd_t * cmd)524 static void CL_FinishMove (usercmd_t *cmd)
525 {
526 	int	i, ms;
527 
528 // always dump the first two message, because it may
529 // contain leftover inputs from the last level
530 	if (++cl.movemessages <= 2)
531 		return;
532 
533 // figure button bits
534 	if (in_attack.state & 3)
535 		cmd->buttons |= 1;
536 	in_attack.state &= ~2;
537 
538 	if (in_jump.state & 3)
539 		cmd->buttons |= 2;
540 	in_jump.state &= ~2;
541 
542 	if (in_crouch.state & 1)
543 		cmd->buttons |= 4;
544 
545 // send milliseconds of time to apply the move
546 	ms = host_frametime * 1000;
547 	if (ms > 250)
548 		ms = 100;	// time was unreasonable
549 	cmd->msec = ms;
550 
551 	VectorCopy (cl.viewangles, cmd->angles);
552 
553 	cmd->impulse = in_impulse;
554 	in_impulse = 0;
555 
556 // chop down so no extra bits are kept that the server wouldn't get
557 	if ((int)cl.v.artifact_active & ARTFLAG_FROZEN)
558 	{
559 		cmd->forwardmove = 0;
560 		cmd->sidemove = 0;
561 		cmd->upmove = 0;
562 	}
563 	else
564 	{
565 		cmd->forwardmove = MakeChar (cmd->forwardmove);
566 		cmd->sidemove = MakeChar (cmd->sidemove);
567 		cmd->upmove = MakeChar (cmd->upmove);
568 	}
569 
570 	for (i = 0; i < 3; i++)
571 		cmd->angles[i] = ((int)(cmd->angles[i]*65536.0/360)&65535) * (360.0/65536.0);
572 }
573 
574 /*
575 =================
576 CL_SendCmd
577 =================
578 */
CL_SendCmd(void)579 void CL_SendCmd (void)
580 {
581 	sizebuf_t	buf;
582 	byte		data[128];
583 	int			i;
584 	usercmd_t	*cmd;
585 
586 	if (cls.demoplayback)
587 		return;
588 
589 // save this command off for prediction
590 	i = cls.netchan.outgoing_sequence & UPDATE_MASK;
591 	cmd = &cl.frames[i].cmd;
592 	cl.frames[i].senttime = realtime;
593 	cl.frames[i].receivedtime = -1;		// we haven't gotten a reply yet
594 
595 // get basic movement from keyboard
596 	CL_BaseMove (cmd);
597 
598 // allow mice or other external controllers to add to the move
599 	IN_Move (cmd);
600 
601 // if we are spectator, try autocam
602 	if (cl.spectator)
603 		Cam_Track(cmd);
604 
605 	CL_FinishMove(cmd);
606 
607 	Cam_FinishMove(cmd);
608 
609 // send this and the previous cmds in the message, so
610 // if the last packet was dropped, it can be recovered
611 	SZ_Init (&buf, data, sizeof(data));
612 
613 	MSG_WriteByte (&buf, clc_move);
614 	i = (cls.netchan.outgoing_sequence-2) & UPDATE_MASK;
615 	MSG_WriteUsercmd (&buf, &cl.frames[i].cmd, false);
616 	i = (cls.netchan.outgoing_sequence-1) & UPDATE_MASK;
617 	MSG_WriteUsercmd (&buf, &cl.frames[i].cmd, false);
618 	i = (cls.netchan.outgoing_sequence) & UPDATE_MASK;
619 	MSG_WriteUsercmd (&buf, &cl.frames[i].cmd, true);
620 
621 //	Con_Printf("I  %hd %hd %hd\n",cmd->forwardmove, cmd->sidemove, cmd->upmove);
622 
623 // request delta compression of entities
624 	if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP-1)
625 		cl.validsequence = 0;
626 	if (cl.validsequence && !cl_nodelta.integer && cls.state == ca_active &&
627 		!cls.demorecording)
628 	{
629 		cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = cl.validsequence;
630 		MSG_WriteByte (&buf, clc_delta);
631 		MSG_WriteByte (&buf, cl.validsequence&255);
632 	}
633 	else	cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = -1;
634 
635 	if (cls.demorecording)
636 		CL_WriteDemoCmd(cmd);
637 
638 // deliver the message
639 	Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);
640 }
641 
642 
643 /*
644 ============
645 CL_InitInput
646 ============
647 */
CL_InitInput(void)648 void CL_InitInput (void)
649 {
650 	Cmd_AddCommand ("+moveup",IN_UpDown);
651 	Cmd_AddCommand ("-moveup",IN_UpUp);
652 	Cmd_AddCommand ("+movedown",IN_DownDown);
653 	Cmd_AddCommand ("-movedown",IN_DownUp);
654 	Cmd_AddCommand ("+left",IN_LeftDown);
655 	Cmd_AddCommand ("-left",IN_LeftUp);
656 	Cmd_AddCommand ("+right",IN_RightDown);
657 	Cmd_AddCommand ("-right",IN_RightUp);
658 	Cmd_AddCommand ("+forward",IN_ForwardDown);
659 	Cmd_AddCommand ("-forward",IN_ForwardUp);
660 	Cmd_AddCommand ("+back",IN_BackDown);
661 	Cmd_AddCommand ("-back",IN_BackUp);
662 	Cmd_AddCommand ("+lookup", IN_LookupDown);
663 	Cmd_AddCommand ("-lookup", IN_LookupUp);
664 	Cmd_AddCommand ("+lookdown", IN_LookdownDown);
665 	Cmd_AddCommand ("-lookdown", IN_LookdownUp);
666 	Cmd_AddCommand ("+strafe", IN_StrafeDown);
667 	Cmd_AddCommand ("-strafe", IN_StrafeUp);
668 	Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
669 	Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
670 	Cmd_AddCommand ("+moveright", IN_MoverightDown);
671 	Cmd_AddCommand ("-moveright", IN_MoverightUp);
672 	Cmd_AddCommand ("+speed", IN_SpeedDown);
673 	Cmd_AddCommand ("-speed", IN_SpeedUp);
674 	Cmd_AddCommand ("+attack", IN_AttackDown);
675 	Cmd_AddCommand ("-attack", IN_AttackUp);
676 	Cmd_AddCommand ("+use", IN_UseDown);
677 	Cmd_AddCommand ("-use", IN_UseUp);
678 	Cmd_AddCommand ("+jump", IN_JumpDown);
679 	Cmd_AddCommand ("-jump", IN_JumpUp);
680 	Cmd_AddCommand ("impulse", IN_Impulse);
681 	Cmd_AddCommand ("+klook", IN_KLookDown);
682 	Cmd_AddCommand ("-klook", IN_KLookUp);
683 	Cmd_AddCommand ("+mlook", IN_MLookDown);
684 	Cmd_AddCommand ("-mlook", IN_MLookUp);
685 	Cmd_AddCommand ("+crouch", IN_CrouchDown);
686 	Cmd_AddCommand ("-crouch", IN_CrouchUp);
687 
688 	Cvar_RegisterVariable (&cl_nodelta);
689 }
690 
691 /*
692 ============
693 CL_ClearStates
694 ============
695 */
696 #if 0
697 void CL_ClearStates (void)
698 {
699 	in_mlook.state = 0;
700 	in_klook.state = 0;
701 	in_left.state = 0;
702 	in_right.state = 0;
703 	in_forward.state = 0;
704 	in_back.state = 0;
705 	in_lookup.state = 0;
706 	in_lookdown.state = 0;
707 	in_moveleft.state = 0;
708 	in_moveright.state = 0;
709 	in_strafe.state = 0;
710 	in_speed.state = 0;
711 	in_use.state = 0;
712 	in_jump.state = 0;
713 	in_attack.state = 0;
714 	in_up.state = 0;
715 	in_down.state = 0;
716 	in_crouch.state = 0;
717 }
718 #endif
719 
720