1 /*
2 Copyright (C) 1997-2001 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 //
21 // cl_input.c
22 // Builds an intended movement command to send to the server
23 //
24
25 #include "cl_local.h"
26
27 cVar_t *cl_nodelta;
28
29 cVar_t *cl_upspeed;
30 cVar_t *cl_forwardspeed;
31 cVar_t *cl_sidespeed;
32
33 cVar_t *cl_yawspeed;
34 cVar_t *cl_pitchspeed;
35
36 static cVar_t *autosensitivity;
37 static cVar_t *cl_anglespeedkey;
38 static cVar_t *cl_run;
39 static cVar_t *m_filter;
40
41 static uint32 in_frameTime;
42 static uint32 in_lastFrameTime;
43 static uint32 in_frameMSec;
44
45 static ivec2_t in_mouseMove;
46 static ivec2_t in_lastMouseMove;
47 static qBool in_mLooking;
48
49 /*
50 ============
51 IN_CenterView_f
52 ============
53 */
IN_CenterView_f(void)54 static void IN_CenterView_f (void)
55 {
56 cl.viewAngles[PITCH] = -SHORT2ANGLE (cl.frame.playerState.pMove.deltaAngles[PITCH]);
57 }
58
59 /*
60 =============================================================================
61
62 KEY BUTTONS
63
64 Continuous button event tracking is complicated by the fact that two
65 different input sources (say, mouse button 1 and the control key) can both
66 press the same button, but the button should only be released when both of
67 the pressing key have been released.
68
69 When a key event issues a button command (+forward, +attack, etc), it
70 appends its key number as a parameter to the command so it can be matched
71 up with the release.
72
73 state bit 0 is the current state of the key
74 state bit 1 is edge triggered on the up to down transition
75 state bit 2 is edge triggered on the down to up transition
76
77 =============================================================================
78 */
79
80 typedef struct kButton_s {
81 int down[2]; // key nums holding it down
82 uint32 downTime; // msec timestamp
83 uint32 msec; // msec down this frame
84 int state;
85 } kButton_t;
86
87 static kButton_t btn_moveUp;
88 static kButton_t btn_moveDown;
89 static kButton_t btn_lookLeft;
90 static kButton_t btn_lookRight;
91 static kButton_t btn_moveForward;
92 static kButton_t btn_moveBack;
93 static kButton_t btn_lookUp;
94 static kButton_t btn_lookDown;
95 static kButton_t btn_moveLeft;
96 static kButton_t btn_moveRight;
97
98 static kButton_t btn_speed;
99 static kButton_t btn_strafe;
100
101 static kButton_t btn_attack;
102 static kButton_t btn_use;
103
104 static kButton_t btn_keyLook;
105
106 static int btn_impulse;
107
108 /*
109 ====================
110 CL_KeyDown
111 ====================
112 */
CL_KeyDown(kButton_t * b)113 static void CL_KeyDown (kButton_t *b)
114 {
115 int k;
116 char *c;
117
118 c = Cmd_Argv (1);
119 if (c[0])
120 k = atoi (c);
121 else
122 k = -1; // Typed manually at the console for continuous down
123
124 if (k == b->down[0] || k == b->down[1])
125 return; // Repeating key
126
127 if (!b->down[0])
128 b->down[0] = k;
129 else if (!b->down[1])
130 b->down[1] = k;
131 else {
132 Com_Printf (PRNT_WARNING, "Three keys down for a button!\n");
133 return;
134 }
135
136 if (b->state & 1)
137 return; // still down
138
139 // Save timestamp
140 c = Cmd_Argv (2);
141 b->downTime = atoi(c);
142 if (!b->downTime)
143 b->downTime = in_frameTime - 100;
144
145 b->state |= 1 + 2; // down + impulse down
146 }
147
148
149 /*
150 ====================
151 CL_KeyUp
152 ====================
153 */
CL_KeyUp(kButton_t * b)154 static void CL_KeyUp (kButton_t *b)
155 {
156 int k;
157 char *c;
158 uint32 uptime;
159
160 c = Cmd_Argv (1);
161 if (c[0])
162 k = atoi(c);
163 else {
164 // Typed manually at the console, assume for unsticking, so clear all
165 b->down[0] = b->down[1] = 0;
166 b->state = 4; // Impulse up
167 return;
168 }
169
170 if (b->down[0] == k)
171 b->down[0] = 0;
172 else if (b->down[1] == k)
173 b->down[1] = 0;
174 else
175 return; // Key up without coresponding down (menu pass through)
176 if (b->down[0] || b->down[1])
177 return; // Some other key is still holding it down
178
179 if (!(b->state & 1))
180 return; // Still up (this should not happen)
181
182 // Save timestamp
183 c = Cmd_Argv (2);
184 uptime = atoi(c);
185 if (uptime)
186 b->msec += uptime - b->downTime;
187 else
188 b->msec += 10;
189
190 b->state &= ~1; // Now up
191 b->state |= 4; // Impulse up
192 }
193
194
195 /*
196 ===============
197 CL_KeyState
198
199 Returns the fraction of the frame that the key was down
200 ===============
201 */
CL_KeyState(kButton_t * key)202 static float CL_KeyState (kButton_t *key)
203 {
204 int msec;
205
206 key->state &= 1; // clear impulses
207
208 msec = key->msec;
209 key->msec = 0;
210
211 if (key->state) {
212 // Still down
213 msec += in_frameTime - key->downTime;
214 key->downTime = in_frameTime;
215 }
216
217 return clamp ((float)msec / (float)in_frameMSec, 0, 1);
218 }
219
220
IN_UpDown_f(void)221 static void IN_UpDown_f (void) { CL_KeyDown (&btn_moveUp); }
IN_UpUp_f(void)222 static void IN_UpUp_f (void) { CL_KeyUp (&btn_moveUp); }
IN_DownDown_f(void)223 static void IN_DownDown_f (void) { CL_KeyDown (&btn_moveDown); }
IN_DownUp_f(void)224 static void IN_DownUp_f (void) { CL_KeyUp (&btn_moveDown); }
IN_LeftDown_f(void)225 static void IN_LeftDown_f (void) { CL_KeyDown (&btn_lookLeft); }
IN_LeftUp_f(void)226 static void IN_LeftUp_f (void) { CL_KeyUp (&btn_lookLeft); }
IN_RightDown_f(void)227 static void IN_RightDown_f (void) { CL_KeyDown (&btn_lookRight); }
IN_RightUp_f(void)228 static void IN_RightUp_f (void) { CL_KeyUp (&btn_lookRight); }
IN_ForwardDown_f(void)229 static void IN_ForwardDown_f (void) { CL_KeyDown (&btn_moveForward); }
IN_ForwardUp_f(void)230 static void IN_ForwardUp_f (void) { CL_KeyUp (&btn_moveForward); }
IN_BackDown_f(void)231 static void IN_BackDown_f (void) { CL_KeyDown (&btn_moveBack); }
IN_BackUp_f(void)232 static void IN_BackUp_f (void) { CL_KeyUp (&btn_moveBack); }
IN_LookupDown_f(void)233 static void IN_LookupDown_f (void) { CL_KeyDown (&btn_lookUp); }
IN_LookupUp_f(void)234 static void IN_LookupUp_f (void) { CL_KeyUp (&btn_lookUp); }
IN_LookdownDown_f(void)235 static void IN_LookdownDown_f (void) { CL_KeyDown (&btn_lookDown); }
IN_LookdownUp_f(void)236 static void IN_LookdownUp_f (void) { CL_KeyUp (&btn_lookDown); }
237
238 // FIXME: Treat like the other keys here?
239 // Only like this because it was done like this in win32 input...
IN_MLookDown_f(void)240 static void IN_MLookDown_f (void)
241 {
242 in_mLooking = qTrue;
243 }
IN_MLookUp_f(void)244 static void IN_MLookUp_f (void)
245 {
246 in_mLooking = qFalse;
247 if (!freelook->intVal && lookspring->intVal)
248 IN_CenterView_f ();
249 }
250
IN_MoveleftDown_f(void)251 static void IN_MoveleftDown_f (void) { CL_KeyDown (&btn_moveLeft); }
IN_MoveleftUp_f(void)252 static void IN_MoveleftUp_f (void) { CL_KeyUp (&btn_moveLeft); }
IN_MoverightDown_f(void)253 static void IN_MoverightDown_f (void) { CL_KeyDown (&btn_moveRight); }
IN_MoverightUp_f(void)254 static void IN_MoverightUp_f (void) { CL_KeyUp (&btn_moveRight); }
255
IN_SpeedDown_f(void)256 static void IN_SpeedDown_f (void) { CL_KeyDown (&btn_speed); }
IN_SpeedUp_f(void)257 static void IN_SpeedUp_f (void) { CL_KeyUp (&btn_speed); }
IN_StrafeDown_f(void)258 static void IN_StrafeDown_f (void) { CL_KeyDown (&btn_strafe); }
IN_StrafeUp_f(void)259 static void IN_StrafeUp_f (void) { CL_KeyUp (&btn_strafe); }
260
IN_AttackDown_f(void)261 static void IN_AttackDown_f (void) { CL_KeyDown (&btn_attack); }
IN_AttackUp_f(void)262 static void IN_AttackUp_f (void) { CL_KeyUp (&btn_attack); }
263
IN_UseDown_f(void)264 static void IN_UseDown_f (void) { CL_KeyDown (&btn_use); }
IN_UseUp_f(void)265 static void IN_UseUp_f (void) { CL_KeyUp (&btn_use); }
266
IN_Impulse_f(void)267 static void IN_Impulse_f (void) { btn_impulse=atoi (Cmd_Argv (1)); }
268
IN_KLookDown_f(void)269 static void IN_KLookDown_f (void) { CL_KeyDown (&btn_keyLook); }
IN_KLookUp_f(void)270 static void IN_KLookUp_f (void) { CL_KeyUp (&btn_keyLook); }
271
272 //==========================================================================
273
274 /*
275 ================
276 CL_GetRunState
277
278 For Win32 joystick input.
279 ================
280 */
CL_GetRunState(void)281 qBool CL_GetRunState (void)
282 {
283 return ((btn_speed.state & 1) ^ cl_run->intVal);
284 }
285
286
287 /*
288 ================
289 CL_GetStrafeState
290
291 For Win32 joystick input.
292 ================
293 */
CL_GetStrafeState(void)294 qBool CL_GetStrafeState (void)
295 {
296 return (btn_strafe.state & 1);
297 }
298
299
300 /*
301 ================
302 CL_GetMLookState
303
304 For Win32 joystick input.
305 ================
306 */
CL_GetMLookState(void)307 qBool CL_GetMLookState (void)
308 {
309 return in_mLooking;
310 }
311
312 /*
313 =============================================================================
314
315 MOUSE MOVEMENT
316
317 This takes mouse moves from the operating system and queues up the moves
318 to later factor into the transmitted move command.
319
320 =============================================================================
321 */
322
323 /*
324 ================
325 CL_MoveMouse
326
327 Queue cursor movement.
328 ================
329 */
CL_MoveMouse(int xMove,int yMove)330 void CL_MoveMouse (int xMove, int yMove)
331 {
332 // Update GUI
333 if (Key_GetDest () == KD_MENU) {
334 CL_CGModule_MoveMouse (xMove, yMove);
335 GUI_MoveMouse (xMove, yMove);
336
337 Vec2Clear (in_mouseMove);
338 Vec2Clear (in_lastMouseMove);
339 return;
340 }
341
342 // Queue movement
343 in_mouseMove[0] += xMove;
344 in_mouseMove[1] += yMove;
345 }
346
347 /*
348 =============================================================================
349
350 MOVE USER COMMAND
351
352 =============================================================================
353 */
354
355 /*
356 ================
357 CL_BaseMove
358
359 Send the intended movement message to the server
360 ================
361 */
CL_BaseMove(userCmd_t * cmd)362 static void CL_BaseMove (userCmd_t *cmd)
363 {
364 float turnSpeed;
365 float moveSpeed;
366
367 // Adjust for turning speed
368 if (btn_speed.state & 1)
369 turnSpeed = cls.netFrameTime * cl_anglespeedkey->floatVal;
370 else
371 turnSpeed = cls.netFrameTime;
372
373 // Adjust for running speed
374 if (CL_GetRunState ())
375 moveSpeed = 2;
376 else
377 moveSpeed = 1;
378
379 // Handle left/right on keyboard
380 cl.cmdNum = cls.netChan.outgoingSequence & CMD_MASK;
381 cmd = &cl.cmds[cl.cmdNum];
382 cl.cmdTime[cl.cmdNum] = cls.realTime; // for netgraph ping calculation
383
384 if (CL_GetStrafeState ()) {
385 // Keyboard strafe
386 cmd->sideMove += cl_sidespeed->floatVal * CL_KeyState (&btn_lookRight);
387 cmd->sideMove -= cl_sidespeed->floatVal * CL_KeyState (&btn_lookLeft);
388 }
389 else {
390 // Keyboard turn
391 cl.viewAngles[YAW] -= turnSpeed * cl_yawspeed->floatVal * CL_KeyState (&btn_lookRight);
392 cl.viewAngles[YAW] += turnSpeed * cl_yawspeed->floatVal * CL_KeyState (&btn_lookLeft);
393 }
394
395 if (btn_keyLook.state & 1) {
396 // Keyboard look
397 cl.viewAngles[PITCH] -= turnSpeed * cl_pitchspeed->floatVal * CL_KeyState (&btn_moveForward);
398 cl.viewAngles[PITCH] += turnSpeed * cl_pitchspeed->floatVal * CL_KeyState (&btn_moveBack);
399 }
400 else {
401 // Keyboard move front/back
402 cmd->forwardMove += cl_forwardspeed->floatVal * CL_KeyState (&btn_moveForward);
403 cmd->forwardMove -= cl_forwardspeed->floatVal * CL_KeyState (&btn_moveBack);
404 }
405
406 // Keyboard look up/down
407 cl.viewAngles[PITCH] -= turnSpeed * cl_pitchspeed->floatVal * CL_KeyState (&btn_lookUp);
408 cl.viewAngles[PITCH] += turnSpeed * cl_pitchspeed->floatVal * CL_KeyState (&btn_lookDown);
409
410 // Keyboard strafe left/right
411 cmd->sideMove += cl_sidespeed->floatVal * CL_KeyState (&btn_moveRight);
412 cmd->sideMove -= cl_sidespeed->floatVal * CL_KeyState (&btn_moveLeft);
413
414 // Keyboard jump/crouch
415 cmd->upMove += cl_upspeed->floatVal * CL_KeyState (&btn_moveUp);
416 cmd->upMove -= cl_upspeed->floatVal * CL_KeyState (&btn_moveDown);
417
418 // Cap to max allowed ranges
419 if (cmd->forwardMove > cl_forwardspeed->floatVal * moveSpeed)
420 cmd->forwardMove = cl_forwardspeed->floatVal * moveSpeed;
421 else if (cmd->forwardMove < -cl_forwardspeed->floatVal * moveSpeed)
422 cmd->forwardMove = -cl_forwardspeed->floatVal * moveSpeed;
423
424 if (cmd->sideMove > cl_sidespeed->floatVal * moveSpeed)
425 cmd->sideMove = cl_sidespeed->floatVal * moveSpeed;
426 else if (cmd->sideMove < -cl_sidespeed->floatVal * moveSpeed)
427 cmd->sideMove = -cl_sidespeed->floatVal * moveSpeed;
428
429 if (cmd->upMove > cl_upspeed->floatVal * moveSpeed)
430 cmd->upMove = cl_upspeed->floatVal * moveSpeed;
431 else if (cmd->upMove < -cl_upspeed->floatVal * moveSpeed)
432 cmd->upMove = -cl_upspeed->floatVal * moveSpeed;
433 }
434
435
436 /*
437 ================
438 CL_MouseMove
439
440 Add mouse X/Y movement to cmd
441 ================
442 */
CL_MouseMove(userCmd_t * cmd)443 static void CL_MouseMove (userCmd_t *cmd)
444 {
445 ivec2_t move;
446
447 // Movement filtering
448 if (m_filter->intVal) {
449 move[0] = (in_mouseMove[0] + in_lastMouseMove[0]) * 0.5f;
450 move[1] = (in_mouseMove[1] + in_lastMouseMove[1]) * 0.5f;
451 }
452 else {
453 move[0] = in_mouseMove[0];
454 move[1] = in_mouseMove[1];
455 }
456 in_lastMouseMove[0] = in_mouseMove[0];
457 in_lastMouseMove[1] = in_mouseMove[1];
458
459 // Zooming in preserves sensitivity
460 if (autosensitivity->intVal) {
461 move[0] *= sensitivity->floatVal * (cl.refDef.fovX/90.0f);
462 move[1] *= sensitivity->floatVal * (cl.refDef.fovY/90.0f);
463 }
464 else {
465 move[0] *= sensitivity->floatVal;
466 move[1] *= sensitivity->floatVal;
467 }
468
469 // Side/yaw movement
470 if (CL_GetStrafeState () || (lookstrafe->intVal && in_mLooking))
471 cmd->sideMove += m_side->floatVal * move[0];
472 else
473 cl.viewAngles[YAW] -= m_yaw->floatVal * move[0];
474
475 // Forward/pitch movement
476 if (!CL_GetStrafeState () && (freelook->intVal || in_mLooking))
477 cl.viewAngles[PITCH] += m_pitch->floatVal * move[1];
478 else
479 cmd->forwardMove -= m_forward->floatVal * move[1];
480
481 // Clear
482 Vec2Clear (in_mouseMove);
483 }
484
485
486 /*
487 ==============
488 CL_ClampPitch
489 ==============
490 */
CL_ClampPitch(void)491 static void CL_ClampPitch (void)
492 {
493 float pitch;
494
495 pitch = SHORT2ANGLE (cl.frame.playerState.pMove.deltaAngles[PITCH]);
496 if (pitch > 180)
497 pitch -= 360;
498
499 if (cl.viewAngles[PITCH] + pitch < -360)
500 cl.viewAngles[PITCH] += 360; // wrapped
501 if (cl.viewAngles[PITCH] + pitch > 360)
502 cl.viewAngles[PITCH] -= 360; // wrapped
503
504 if (cl.viewAngles[PITCH] + pitch > 89)
505 cl.viewAngles[PITCH] = 89 - pitch;
506 if (cl.viewAngles[PITCH] + pitch < -89)
507 cl.viewAngles[PITCH] = -89 - pitch;
508 }
509
510
511 /*
512 =================
513 CL_RefreshCmd
514 =================
515 */
CL_RefreshCmd(void)516 void CL_RefreshCmd (void)
517 {
518 int ms;
519 userCmd_t *cmd = &cl.cmds[cls.netChan.outgoingSequence & CMD_MASK];
520
521 // Get delta for this sample.
522 in_frameMSec = in_frameTime - in_lastFrameTime;
523 if (in_frameMSec < 1)
524 return;
525 else if (in_frameMSec > 200)
526 in_frameMSec = 200;
527
528 // Get basic movement from keyboard
529 CL_BaseMove (cmd);
530
531 // Allow mice or other external controllers to add to the move
532 IN_Move (cmd);
533
534 // Add mouse movement
535 CL_MouseMove (cmd);
536
537 // Update cmd viewangles for CL_PredictMove
538 CL_ClampPitch ();
539
540 // Transmit data
541 cmd->angles[0] = ANGLE2SHORT(cl.viewAngles[0]);
542 cmd->angles[1] = ANGLE2SHORT(cl.viewAngles[1]);
543 cmd->angles[2] = ANGLE2SHORT(cl.viewAngles[2]);
544
545 // Update cmd->msec for CL_PredictMove
546 ms = (int)(cls.netFrameTime * 1000);
547 if (ms > 250)
548 ms = 100;
549 cmd->msec = ms;
550
551 // Update counter
552 in_lastFrameTime = in_frameTime;
553
554 // Send packet immediately on important events
555 if (btn_attack.state & 2 || btn_use.state & 2)
556 cls.forcePacket = qTrue;
557 }
558
559
560 /*
561 =================
562 CL_FinalizeCmd
563 =================
564 */
CL_FinalizeCmd(void)565 static void CL_FinalizeCmd (void)
566 {
567 userCmd_t *cmd = &cl.cmds[cls.netChan.outgoingSequence & CMD_MASK];
568
569 // Set any button hits that occured since last frame
570 if (btn_attack.state & 3)
571 cmd->buttons |= BUTTON_ATTACK;
572 btn_attack.state &= ~2;
573
574 if (btn_use.state & 3)
575 cmd->buttons |= BUTTON_USE;
576 btn_use.state &= ~2;
577
578 if (key_anyKeyDown && Key_GetDest () == KD_GAME)
579 cmd->buttons |= BUTTON_ANY;
580
581 // ...
582 cmd->impulse = btn_impulse;
583 btn_impulse = 0;
584
585 // Set the ambient light level at the player's current position
586 cmd->lightLevel = (byte)cl_lightlevel->floatVal;
587 }
588
589
590 /*
591 =================
592 CL_SendCmd
593 =================
594 */
CL_SendCmd(void)595 void CL_SendCmd (void)
596 {
597 byte data[128];
598 netMsg_t buf;
599 userCmd_t *cmd, *oldCmd;
600 userCmd_t nullCmd;
601 int checkSumIndex;
602
603 switch (Com_ClientState ()) {
604 case CA_CONNECTED:
605 if (cls.netChan.gotReliable || cls.netChan.message.curSize || Sys_Milliseconds()-cls.netChan.lastSent > 100)
606 Netchan_Transmit (&cls.netChan, 0, NULL);
607 return;
608
609 case CA_DISCONNECTED:
610 case CA_CONNECTING:
611 // Wait until active
612 return;
613 }
614
615 cl.cmdNum = cls.netChan.outgoingSequence & CMD_MASK;
616 cmd = &cl.cmds[cl.cmdNum];
617 cl.cmdTime[cl.cmdNum] = cls.realTime; // for ping calculation
618
619 CL_FinalizeCmd ();
620
621 cl.cmd = *cmd;
622
623 // Send a userinfo update if needed
624 if (com_userInfoModified) {
625 com_userInfoModified = qFalse;
626 MSG_WriteByte (&cls.netChan.message, CLC_USERINFO);
627 MSG_WriteString (&cls.netChan.message, Cvar_BitInfo (CVAR_USERINFO));
628 }
629
630 MSG_Init (&buf, data, sizeof (data));
631
632 if (cmd->buttons && cl.cin.time > 0 && !cl.attractLoop && cls.realTime-cl.cin.time > 1000) {
633 // Skip the rest of the cinematic
634 CIN_FinishCinematic ();
635 }
636
637 // Begin a client move command
638 MSG_WriteByte (&buf, CLC_MOVE);
639
640 // Save the position for a checksum byte
641 if (cls.serverProtocol != ENHANCED_PROTOCOL_VERSION) {
642 checkSumIndex = buf.curSize;
643 MSG_WriteByte (&buf, 0);
644 }
645 else
646 checkSumIndex = 0;
647
648 /*
649 ** Let the server know what the last frame we got was,
650 ** so the next message can be delta compressed
651 */
652 if (cl_nodelta->intVal || !cl.frame.valid || cls.demoWaiting)
653 MSG_WriteLong (&buf, -1); // no compression
654 else
655 MSG_WriteLong (&buf, cl.frame.serverFrame);
656
657 /*
658 ** Send this and the previous cmds in the message,
659 ** so if the last packet was dropped, it can be recovered
660 */
661 cmd = &cl.cmds[(cls.netChan.outgoingSequence-2)&CMD_MASK];
662 memset (&nullCmd, 0, sizeof (nullCmd));
663 MSG_WriteDeltaUsercmd (&buf, &nullCmd, cmd);
664 oldCmd = cmd;
665
666 cmd = &cl.cmds[(cls.netChan.outgoingSequence-1)&CMD_MASK];
667 MSG_WriteDeltaUsercmd (&buf, oldCmd, cmd);
668 oldCmd = cmd;
669
670 cmd = &cl.cmds[(cls.netChan.outgoingSequence)&CMD_MASK];
671 MSG_WriteDeltaUsercmd (&buf, oldCmd, cmd);
672
673 // Calculate a checksum over the move commands
674 if (cls.serverProtocol != ENHANCED_PROTOCOL_VERSION) {
675 buf.data[checkSumIndex] = Com_BlockSequenceCRCByte (
676 buf.data + checkSumIndex + 1, buf.curSize - checkSumIndex - 1,
677 cls.netChan.outgoingSequence);
678 }
679
680 // Deliver the message
681 Netchan_Transmit (&cls.netChan, buf.curSize, buf.data);
682
683 // Init the current cmd buffer and clear it
684 cmd = &cl.cmds[cls.netChan.outgoingSequence&CMD_MASK];
685 memset (cmd, 0, sizeof (userCmd_t));
686 }
687
688
689 /*
690 ============
691 CL_UpdateFrameTime
692 ============
693 */
CL_UpdateFrameTime(uint32 time)694 void CL_UpdateFrameTime (uint32 time)
695 {
696 in_frameTime = time;
697 }
698
699
700 /*
701 ============
702 CL_InputInit
703 ============
704 */
CL_InputInit(void)705 void CL_InputInit (void)
706 {
707 // Cvars
708 autosensitivity = Cvar_Register ("autosensitivity", "0", CVAR_ARCHIVE);
709
710 cl_nodelta = Cvar_Register ("cl_nodelta", "0", 0);
711
712 cl_upspeed = Cvar_Register ("cl_upspeed", "200", 0);
713 cl_forwardspeed = Cvar_Register ("cl_forwardspeed", "200", 0);
714 cl_sidespeed = Cvar_Register ("cl_sidespeed", "200", 0);
715 cl_yawspeed = Cvar_Register ("cl_yawspeed", "140", 0);
716 cl_pitchspeed = Cvar_Register ("cl_pitchspeed", "150", 0);
717
718 cl_run = Cvar_Register ("cl_run", "0", CVAR_ARCHIVE);
719
720 cl_anglespeedkey = Cvar_Register ("cl_anglespeedkey", "1.5", 0);
721
722 m_filter = Cvar_Register ("m_filter", "0", 0);
723
724 // Commands
725 Cmd_AddCommand ("centerview", IN_CenterView_f, "Centers the view");
726
727 Cmd_AddCommand ("+moveup", IN_UpDown_f, "");
728 Cmd_AddCommand ("-moveup", IN_UpUp_f, "");
729 Cmd_AddCommand ("+movedown", IN_DownDown_f, "");
730 Cmd_AddCommand ("-movedown", IN_DownUp_f, "");
731 Cmd_AddCommand ("+left", IN_LeftDown_f, "");
732 Cmd_AddCommand ("-left", IN_LeftUp_f, "");
733 Cmd_AddCommand ("+right", IN_RightDown_f, "");
734 Cmd_AddCommand ("-right", IN_RightUp_f, "");
735 Cmd_AddCommand ("+forward", IN_ForwardDown_f, "");
736 Cmd_AddCommand ("-forward", IN_ForwardUp_f, "");
737 Cmd_AddCommand ("+back", IN_BackDown_f, "");
738 Cmd_AddCommand ("-back", IN_BackUp_f, "");
739 Cmd_AddCommand ("+lookup", IN_LookupDown_f, "");
740 Cmd_AddCommand ("-lookup", IN_LookupUp_f, "");
741 Cmd_AddCommand ("+lookdown", IN_LookdownDown_f, "");
742 Cmd_AddCommand ("-lookdown", IN_LookdownUp_f, "");
743 Cmd_AddCommand ("+strafe", IN_StrafeDown_f, "");
744 Cmd_AddCommand ("-strafe", IN_StrafeUp_f, "");
745 Cmd_AddCommand ("+mlook", IN_MLookDown_f, "");
746 Cmd_AddCommand ("-mlook", IN_MLookUp_f, "");
747 Cmd_AddCommand ("+moveleft", IN_MoveleftDown_f, "");
748 Cmd_AddCommand ("-moveleft", IN_MoveleftUp_f, "");
749 Cmd_AddCommand ("+moveright", IN_MoverightDown_f, "");
750 Cmd_AddCommand ("-moveright", IN_MoverightUp_f, "");
751 Cmd_AddCommand ("+speed", IN_SpeedDown_f, "");
752 Cmd_AddCommand ("-speed", IN_SpeedUp_f, "");
753 Cmd_AddCommand ("+attack", IN_AttackDown_f, "");
754 Cmd_AddCommand ("-attack", IN_AttackUp_f, "");
755 Cmd_AddCommand ("+use", IN_UseDown_f, "");
756 Cmd_AddCommand ("-use", IN_UseUp_f, "");
757
758 Cmd_AddCommand ("impulse", IN_Impulse_f, "");
759
760 Cmd_AddCommand ("+klook", IN_KLookDown_f, "");
761 Cmd_AddCommand ("-klook", IN_KLookUp_f, "");
762 }
763