1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: p_player_input.cpp 4338 2010-12-13 21:09:47Z dj_jl $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 //**
26 //**	KEY BUTTONS
27 //**
28 //**	Continuous button event tracking is complicated by the fact that two
29 //**  different input sources (say, mouse button 1 and the control key) can
30 //**  both press the same button, but the button should only be released
31 //**  when both of the pressing key have been released.
32 //**
33 //**	When a key event issues a button command (+forward, +attack, etc),
34 //**  it appends its key number as a parameter to the command so it can be
35 //**  matched up with the release.
36 //**
37 //**	state bit 0 is the current state of the key
38 //**	state bit 1 is edge triggered on the up to down transition
39 //**	state bit 2 is edge triggered on the down to up transition
40 //**
41 //**************************************************************************
42 
43 // HEADER FILES ------------------------------------------------------------
44 
45 #include "gamedefs.h"
46 
47 // MACROS ------------------------------------------------------------------
48 
49 #define BUTTON(name) \
50 static TKButton		Key ## name; \
51 static TCmdKeyDown	name ## Down_f("+" #name, Key ## name); \
52 static TCmdKeyUp	name ## Up_f("-" #name, Key ## name);
53 
54 // TYPES -------------------------------------------------------------------
55 
56 class TKButton
57 {
58 public:
59 	int		down[2];		// key nums holding it down
60 	int		state;			// low bit is down state
61 
62 	void KeyDown(const char* c);
63 	void KeyUp(const char* c);
64 	float KeyState();
65 };
66 
67 class TCmdKeyDown : public VCommand
68 {
69 public:
TCmdKeyDown(const char * AName,TKButton & AKey)70 	TCmdKeyDown(const char *AName, TKButton &AKey) : VCommand(AName), Key(AKey) { }
71 	void Run();
72 
73 	TKButton	&Key;
74 };
75 
76 class TCmdKeyUp : public VCommand
77 {
78 public:
TCmdKeyUp(const char * AName,TKButton & AKey)79 	TCmdKeyUp(const char *AName, TKButton &AKey) : VCommand(AName), Key(AKey)	{ }
80 	void Run();
81 
82 	TKButton	&Key;
83 };
84 
85 enum
86 {
87 	INPUT_OLDBUTTONS,
88 	INPUT_BUTTONS,
89 	INPUT_PITCH,
90 	INPUT_YAW,
91 	INPUT_ROLL,
92 	INPUT_FORWARDMOVE,
93 	INPUT_SIDEMOVE,
94 	INPUT_UPMOVE,
95 	MODINPUT_OLDBUTTONS,
96 	MODINPUT_BUTTONS,
97 	MODINPUT_PITCH,
98 	MODINPUT_YAW,
99 	MODINPUT_ROLL,
100 	MODINPUT_FORWARDMOVE,
101 	MODINPUT_SIDEMOVE,
102 	MODINPUT_UPMOVE
103 };
104 
105 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
106 
107 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
108 
109 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
110 
111 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
112 
113 // PUBLIC DATA DEFINITIONS -------------------------------------------------
114 
115 // PRIVATE DATA DEFINITIONS ------------------------------------------------
116 
117 // mouse values are used once
118 static float	mousex;
119 static float	mousey;
120 // joystick values are repeated
121 static int		joyxmove;
122 static int		joyymove;
123 
124 static int		impulse_cmd;
125 
126 static VCvarI	allways_run("allways_run", "1", CVAR_Archive);
127 static VCvarI	artiskip("artiskip", "1", CVAR_Archive);	// whether shift-enter skips an artifact
128 
129 static VCvarF	cl_forwardspeed("cl_forwardspeed", "200", CVAR_Archive);
130 static VCvarF	cl_backspeed("cl_backspeed", "200", CVAR_Archive);
131 static VCvarF	cl_sidespeed("cl_sidespeed", "200", CVAR_Archive);
132 static VCvarF	cl_flyspeed("cl_flyspeed", "80", CVAR_Archive);
133 
134 static VCvarF	cl_movespeedkey("cl_movespeedkey", "2.0", CVAR_Archive);
135 
136 static VCvarF	cl_yawspeed("cl_yawspeed", "140", CVAR_Archive);
137 static VCvarF	cl_pitchspeed("cl_pitchspeed", "150", CVAR_Archive);
138 static VCvarF	cl_pitchdriftspeed("cl_pitchdriftspeed", "270", CVAR_Archive);
139 
140 static VCvarF	cl_anglespeedkey("cl_anglespeedkey", "1.5", CVAR_Archive);
141 
142 static VCvarF	cl_deathroll("cl_deathroll", "75", CVAR_Archive);
143 static VCvarF	cl_deathrollspeed("cl_deathrollspeed", "80", CVAR_Archive);
144 
145 static VCvarF	mouse_x_sensitivity("mouse_x_sensitivity", "5.0", CVAR_Archive);
146 static VCvarF	mouse_y_sensitivity("mouse_y_sensitivity", "5.0", CVAR_Archive);
147 static VCvarI	mouse_look("mouse_look", "1", CVAR_Archive);
148 static VCvarI	invert_mouse("invert_mouse", "0", CVAR_Archive);
149 static VCvarI	lookstrafe("lookstrafe", "0", CVAR_Archive);
150 static VCvarI	lookspring("lookspring", "0", CVAR_Archive);
151 
152 static VCvarF	m_yaw("m_yaw", "0.022", CVAR_Archive);
153 static VCvarF	m_pitch("m_pitch", "0.022", CVAR_Archive);
154 static VCvarF	m_forward("m_forward", "1.0", CVAR_Archive);
155 static VCvarF	m_side("m_side", "0.8", CVAR_Archive);
156 
157 static VCvarF	joy_yaw("joy_yaw", "140", CVAR_Archive);
158 
159 BUTTON(Forward)
BUTTON(Backward)160 BUTTON(Backward)
161 BUTTON(Left)
162 BUTTON(Right)
163 BUTTON(LookUp)
164 BUTTON(LookDown)
165 BUTTON(LookCentre)
166 BUTTON(MoveLeft)
167 BUTTON(MoveRight)
168 BUTTON(FlyUp)
169 BUTTON(FlyDown)
170 BUTTON(FlyCentre)
171 BUTTON(Attack)
172 BUTTON(Use)
173 BUTTON(Jump)
174 BUTTON(AltAttack)
175 BUTTON(Button5)
176 BUTTON(Button6)
177 BUTTON(Button7)
178 BUTTON(Button8)
179 BUTTON(Speed)
180 BUTTON(Strafe)
181 BUTTON(MouseLook)
182 
183 // CODE --------------------------------------------------------------------
184 
185 //==========================================================================
186 //
187 //	TKButton::KeyDown
188 //
189 //==========================================================================
190 
191 void TKButton::KeyDown(const char* c)
192 {
193 	guard(TKButton::KeyDown);
194 	int		k;
195 
196 	if (c[0])
197 	{
198 		k = atoi(c);
199 	}
200 	else
201 	{
202 		k = -1;		// typed manually at the console for continuous down
203 	}
204 
205 	if (k == down[0] || k == down[1])
206 	{
207 		return;		// repeating key
208 	}
209 
210 	if (!down[0])
211 	{
212 		down[0] = k;
213 	}
214 	else if (!down[1])
215 	{
216 		down[1] = k;
217 	}
218 	else
219 	{
220 		GCon->Log(NAME_Dev, "Three keys down for a button!");
221 		return;
222 	}
223 
224 	if (state & 1)
225 	{
226 		return;		// still down
227 	}
228 	state |= 1 + 2;	// down + impulse down
229 	unguard;
230 }
231 
232 //==========================================================================
233 //
234 //	TKButton::KeyUp
235 //
236 //==========================================================================
237 
KeyUp(const char * c)238 void TKButton::KeyUp(const char* c)
239 {
240 	guard(TKButton::KeyUp);
241 	int		k;
242 
243 	if (c[0])
244 	{
245 		k = atoi(c);
246 	}
247 	else
248 	{ // typed manually at the console, assume for unsticking, so clear all
249 		down[0] = down[1] = 0;
250 		state = 4;	// impulse up
251 		return;
252 	}
253 
254 	if (down[0] == k)
255 	{
256 		down[0] = 0;
257 	}
258 	else if (down[1] == k)
259 	{
260 		down[1] = 0;
261 	}
262 	else
263 	{
264 		return;		// key up without coresponding down (menu pass through)
265 	}
266 	if (down[0] || down[1])
267 	{
268 		return;		// some other key is still holding it down
269 	}
270 
271 	if (!(state & 1))
272 	{
273 		return;		// still up (this should not happen)
274 	}
275 	state &= ~1;		// now up
276 	state |= 4; 		// impulse up
277 	unguard;
278 }
279 
280 //==========================================================================
281 //
282 //	TKButton::KeyState
283 //
284 //	Returns 0.25 if a key was pressed and released during the frame,
285 //	0.5 if it was pressed and held
286 //	0 if held then released, and
287 //	1.0 if held for the entire time
288 //
289 //==========================================================================
290 
KeyState()291 float TKButton::KeyState()
292 {
293 	guard(TKButton::KeyState);
294 	static const float newVal[8] =
295 	{
296 		0.0f,	// up the entire frame
297 		1.0f,	// held the entire frame
298 		0.0f,	// Sys_Error();
299 		0.5f,	// pressed and held this frame
300 		0.0f,	// released this frame
301 		0.0f,	// Sys_Error();
302 		0.25f,	// pressed and released this frame
303 		0.75f	// released and re-pressed this frame
304 	};
305 
306 	float val = newVal[state & 7];
307 	state &= 1;		// clear impulses
308 
309 	return val;
310 	unguard;
311 }
312 
313 //==========================================================================
314 //
315 //	TCmdKeyDown::Run
316 //
317 //==========================================================================
318 
Run()319 void TCmdKeyDown::Run()
320 {
321 	guard(TCmdKeyDown::Run);
322 	Key.KeyDown(Args.Num() > 1 ? *Args[1] : "");
323 	unguard;
324 }
325 
326 //==========================================================================
327 //
328 //	TCmdKeyUp::Run
329 //
330 //==========================================================================
331 
Run()332 void TCmdKeyUp::Run()
333 {
334 	guard(TCmdKeyUp::Run);
335 	Key.KeyUp(Args.Num() > 1 ? *Args[1] : "");
336 	unguard;
337 }
338 
339 //==========================================================================
340 //
341 //	COMMAND Impulse
342 //
343 //==========================================================================
344 
COMMAND(Impulse)345 COMMAND(Impulse)
346 {
347 	guard(COMMAND Impulse);
348 	if (Args.Num() < 2)
349 	{
350 		return;
351 	}
352 	impulse_cmd = atoi(*Args[1]);
353 	unguard;
354 }
355 
356 //==========================================================================
357 //
358 //	COMMAND ToggleAlwaysRun
359 //
360 //==========================================================================
361 
COMMAND(ToggleAlwaysRun)362 COMMAND(ToggleAlwaysRun)
363 {
364 	guard(COMMAND ToggleAlwaysRun);
365 	allways_run = !allways_run;
366 #ifdef CLIENT
367 	if (cl)
368 	{
369 		cl->Printf(allways_run ? "Always run on" : "Always run off");
370 	}
371 	else
372 #endif
373 	{
374 		GCon->Log(allways_run ? "Always run on" : "Always run off");
375 	}
376 	unguard;
377 }
378 
379 //==========================================================================
380 //
381 //	COMMAND Use
382 //
383 //==========================================================================
384 
COMMAND(Use)385 COMMAND(Use)
386 {
387 	guard(COMMAND Use);
388 	if (Args.Num() < 1)
389 	{
390 		return;
391 	}
392 #ifdef CLIENT
393 	cl->eventUseInventory(*Args[1]);
394 #endif
395 	unguard;
396 }
397 
398 //==========================================================================
399 //
400 //	VBasePlayer::StartPitchDrift
401 //
402 //==========================================================================
403 
StartPitchDrift()404 void VBasePlayer::StartPitchDrift()
405 {
406 	PlayerFlags |= PF_Centreing;
407 }
408 
409 //==========================================================================
410 //
411 //	VBasePlayer::StopPitchDrift
412 //
413 //==========================================================================
414 
StopPitchDrift()415 void VBasePlayer::StopPitchDrift()
416 {
417 	PlayerFlags &= ~PF_Centreing;
418 }
419 
420 //==========================================================================
421 //
422 //	VBasePlayer::AdjustAngles
423 //
424 //==========================================================================
425 
AdjustAngles()426 void VBasePlayer::AdjustAngles()
427 {
428 	guard(VBasePlayer::AdjustAngles);
429 	float speed;
430 
431 	if (KeySpeed.state & 1)
432 	{
433 		speed = host_frametime * cl_anglespeedkey;
434 	}
435 	else
436 	{
437 		speed = host_frametime;
438 	}
439 
440 	if ((KeyMouseLook.state & 4) && lookspring)
441 	{
442 		StartPitchDrift();
443 	}
444 	KeyMouseLook.state &= 1;
445 
446 	//	YAW
447 	if (!(KeyStrafe.state & 1))
448 	{
449 		ViewAngles.yaw -= KeyRight.KeyState() * cl_yawspeed * speed;
450 		ViewAngles.yaw += KeyLeft.KeyState() * cl_yawspeed * speed;
451 		if (joyxmove > 0)
452 		{
453 			ViewAngles.yaw -= joy_yaw * speed;
454 		}
455 		if (joyxmove < 0)
456 		{
457 			ViewAngles.yaw += joy_yaw * speed;
458 		}
459 	}
460 	if (!(KeyStrafe.state & 1) &&
461 		(!lookstrafe || (!mouse_look && !(KeyMouseLook.state & 1))))
462 	{
463 		ViewAngles.yaw -= mousex * m_yaw;
464 	}
465 	ViewAngles.yaw = AngleMod(ViewAngles.yaw);
466 
467 	//	PITCH
468 	float up = KeyLookUp.KeyState();
469 	float down = KeyLookDown.KeyState();
470 	ViewAngles.pitch -= cl_pitchspeed * up * speed;
471 	ViewAngles.pitch += cl_pitchspeed * down * speed;
472 	if (up || down || (KeyMouseLook.state & 1))
473 	{
474 		StopPitchDrift();
475 	}
476 	if ((mouse_look || (KeyMouseLook.state & 1)) && !(KeyStrafe.state & 1))
477 	{
478 		ViewAngles.pitch -= mousey * m_pitch;
479 	}
480 
481 	//	Centre look
482 	if ((KeyLookCentre.state & 1) || (KeyFlyCentre.state & 1))
483 	{
484 		StartPitchDrift();
485 	}
486 	if (PlayerFlags & PF_Centreing)
487 	{
488 		float adelta = cl_pitchdriftspeed * host_frametime;
489 		if (fabs(ViewAngles.pitch) < adelta)
490 		{
491 			ViewAngles.pitch = 0;
492 			PlayerFlags &= ~PF_Centreing;
493 		}
494 		else
495 		{
496 			if (ViewAngles.pitch > 0.0)
497 			{
498 				ViewAngles.pitch -= adelta;
499 			}
500 			else if (ViewAngles.pitch < 0.0)
501 			{
502 				ViewAngles.pitch += adelta;
503 			}
504 		}
505 	}
506 
507 	//	ROLL
508 	if (Health <= 0)
509 	{
510 		if (ViewAngles.roll >= 0 && ViewAngles.roll < cl_deathroll)
511 		{
512 			ViewAngles.roll += cl_deathrollspeed * host_frametime;
513 		}
514 		if (ViewAngles.roll < 0 && ViewAngles.roll > -cl_deathroll)
515 		{
516 			ViewAngles.roll -= cl_deathrollspeed * host_frametime;
517 		}
518 	}
519 	else
520 	{
521 		ViewAngles.roll = 0.0;
522 	}
523 
524 	//	Check angles
525 	if (ViewAngles.pitch > 80.0)
526 	{
527 		ViewAngles.pitch = 80.0;
528 	}
529 	if (ViewAngles.pitch < -70.0)
530 	{
531 		ViewAngles.pitch = -70.0;
532 	}
533 
534 	if (ViewAngles.roll > 80.0)
535 	{
536 		ViewAngles.roll = 80.0;
537 	}
538 	if (ViewAngles.roll < -80.0)
539 	{
540 		ViewAngles.roll = -80.0;
541 	}
542 
543 	if (Level->LevelInfoFlags & VLevelInfo::LIF_NoFreelook)
544 	{
545 		ViewAngles.pitch = 0;
546 	}
547 	unguard;
548 }
549 
550 //==========================================================================
551 //
552 //	VBasePlayer::HandleInput
553 //
554 //	Creates movement commands from all of the available inputs.
555 //
556 //==========================================================================
557 
HandleInput()558 void VBasePlayer::HandleInput()
559 {
560 	guard(VBasePlayer::HandleInput);
561 	float		forward;
562 	float		side;
563 	float		flyheight;
564 
565 	AdjustAngles();
566 
567 	forward = side = flyheight = 0;
568 
569 	// let movement keys cancel each other out
570 	if (KeyStrafe.state & 1)
571 	{
572 		side += KeyRight.KeyState() * cl_sidespeed;
573 		side -= KeyLeft.KeyState() * cl_sidespeed;
574 		if (joyxmove > 0)
575 		{
576 			side += cl_sidespeed;
577 		}
578 		if (joyxmove < 0)
579 		{
580 			side -= cl_sidespeed;
581 		}
582 	}
583 
584 	forward += KeyForward.KeyState() * cl_forwardspeed;
585 	forward -= KeyBackward.KeyState() * cl_backspeed;
586 
587 	side += KeyMoveRight.KeyState() * cl_sidespeed;
588 	side -= KeyMoveLeft.KeyState() * cl_sidespeed;
589 
590 	if (joyymove < 0)
591 	{
592 		forward += cl_forwardspeed;
593 	}
594 	if (joyymove > 0)
595 	{
596 		forward -= cl_backspeed;
597 	}
598 
599 	// Fly up/down/drop keys
600 	flyheight += KeyFlyUp.KeyState() * cl_flyspeed; // note that the actual flyheight will be twice this
601 	flyheight -= KeyFlyDown.KeyState() * cl_flyspeed;
602 
603 	if ((!mouse_look && !(KeyMouseLook.state & 1)) || (KeyStrafe.state & 1))
604 	{
605 		forward += m_forward * mousey;
606 	}
607 
608 	if ((KeyStrafe.state & 1) ||
609 		(lookstrafe && (mouse_look || (KeyMouseLook.state & 1))))
610 	{
611 		side += m_side * mousex;
612 	}
613 
614 	forward = MID(forward, -cl_backspeed, cl_forwardspeed);
615 	side = MID(side, -cl_sidespeed, cl_sidespeed);
616 
617 	if (allways_run || (KeySpeed.state & 1))
618 	{
619 		forward *= cl_movespeedkey;
620 		side *= cl_movespeedkey;
621 		flyheight *= cl_movespeedkey;
622 	}
623 
624 	flyheight = MID(flyheight, -127, 127);
625 	if (KeyFlyCentre.KeyState())
626 	{
627 		flyheight = TOCENTRE;
628 	}
629 
630 	//
631 	//	BUTTONS
632 	//
633 
634 	Buttons = 0;
635 
636 	// Fire buttons
637 	if (KeyAttack.KeyState())
638 	{
639 		Buttons |= BT_ATTACK;
640 	}
641 
642 	// Use buttons
643 	if (KeyUse.KeyState())
644 	{
645 		Buttons |= BT_USE;
646 	}
647 
648 	// Jumping
649 	if (KeyJump.KeyState())
650 	{
651 		Buttons |= BT_JUMP;
652 	}
653 
654 	if (KeyAltAttack.KeyState())
655 	{
656 		Buttons |= BT_ALT_ATTACK;
657 	}
658 
659 	if (KeyButton5.KeyState())
660 	{
661 		Buttons |= 0x10;
662 	}
663 
664 	if (KeyButton6.KeyState())
665 	{
666 		Buttons |= 0x20;
667 	}
668 
669 	if (KeyButton7.KeyState())
670 	{
671 		Buttons |= 0x40;
672 	}
673 
674 	if (KeyButton8.KeyState())
675 	{
676 		Buttons |= 0x80;
677 	}
678 
679 	//
680 	//	IMPULSE
681 	//
682 	if (impulse_cmd)
683 	{
684 		eventServerImpulse(impulse_cmd);
685 		impulse_cmd = 0;
686 	}
687 
688 	ClientForwardMove = forward;
689 	ClientSideMove = side;
690 	FlyMove = flyheight;
691 
692 	mousex = 0;
693 	mousey = 0;
694 	unguard;
695 }
696 
697 //==========================================================================
698 //
699 //	VBasePlayer::Responder
700 //
701 //	Get info needed to make movement commands for the players.
702 //
703 //==========================================================================
704 
Responder(event_t * ev)705 bool VBasePlayer::Responder(event_t* ev)
706 {
707 	guard(VBasePlayer::Responder);
708 	switch (ev->type)
709 	{
710 	case ev_mouse:
711 		mousex = ev->data2 * mouse_x_sensitivity;
712 		mousey = ev->data3 * mouse_y_sensitivity;
713 		if (invert_mouse)
714 		{
715 			mousey = -mousey;
716 		}
717 		return true;    // eat events
718 
719 	case ev_joystick:
720 		joyxmove = ev->data2;
721 		joyymove = ev->data3;
722 		return true;    // eat events
723 
724 	default:
725 		break;
726 	}
727 	return false;
728 	unguard;
729 }
730 
731 //==========================================================================
732 //
733 //	VBasePlayer::ClearInput
734 //
735 //==========================================================================
736 
ClearInput()737 void VBasePlayer::ClearInput()
738 {
739 	guard(VBasePlayer::ClearInput);
740 	// clear cmd building stuff
741 	joyxmove = joyymove = 0;
742 	mousex = mousey = 0;
743 	impulse_cmd = 0;
744 	unguard;
745 }
746 
747 //==========================================================================
748 //
749 //	VBasePlayer::AcsGetInput
750 //
751 //==========================================================================
752 
AcsGetInput(int InputType)753 int VBasePlayer::AcsGetInput(int InputType)
754 {
755 	guard(VBasePlayer::AcsGetInput);
756 	int Btn;
757 	int Ret = 0;
758 	switch (InputType)
759 	{
760 	case INPUT_OLDBUTTONS:
761 	case MODINPUT_OLDBUTTONS:
762 	case INPUT_BUTTONS:
763 	case MODINPUT_BUTTONS:
764 		if (InputType == INPUT_OLDBUTTONS ||
765 			InputType == MODINPUT_OLDBUTTONS)
766 		{
767 			Btn = OldButtons;
768 		}
769 		else
770 		{
771 			Btn = Buttons;
772 		}
773 		//	Convert buttons to what ACS expects.
774 		if (Btn & BT_ATTACK)
775 		{
776 			Ret |= 1;
777 		}
778 		if (Btn & BT_USE)
779 		{
780 			Ret |= 2;
781 		}
782 		if (Btn & BT_JUMP)
783 		{
784 			Ret |= 4;
785 		}
786 		if (Btn & BT_ALT_ATTACK)
787 		{
788 			Ret |= 32;
789 		}
790 		return Ret;
791 
792 	case INPUT_PITCH:
793 		return (int)(AngleMod(OldViewAngles.pitch) * 0x10000 / 360);
794 
795 	case MODINPUT_PITCH:
796 		return (int)(AngleMod(ViewAngles.pitch) * 0x10000 / 360);
797 
798 	case INPUT_YAW:
799 		return (int)(AngleMod(OldViewAngles.yaw) * 0x10000 / 360);
800 
801 	case MODINPUT_YAW:
802 		return (int)(AngleMod(ViewAngles.yaw) * 0x10000 / 360);
803 
804 	case INPUT_ROLL:
805 		return (int)(AngleMod(OldViewAngles.roll) * 0x10000 / 360);
806 
807 	case MODINPUT_ROLL:
808 		return (int)(AngleMod(ViewAngles.roll) * 0x10000 / 360);
809 
810 	case INPUT_FORWARDMOVE:
811 		return (int)(ClientForwardMove * 0x32 / 400);
812 
813 	case MODINPUT_FORWARDMOVE:
814 		return (int)(ForwardMove * 0x32 / 400);
815 
816 	case INPUT_SIDEMOVE:
817 		return (int)(ClientSideMove * 0x32 / 400);
818 
819 	case MODINPUT_SIDEMOVE:
820 		return (int)(SideMove * 0x32 / 400);
821 
822 	case INPUT_UPMOVE:
823 	case MODINPUT_UPMOVE:
824 		return (int)(FlyMove * 3 * 256 / 80);
825 	}
826 	return 0;
827 	unguard;
828 }
829