DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
cl_input.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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#include "csprogs.h"
27#include "thread.h"
28
29/*
30===============================================================================
31
32KEY BUTTONS
33
34Continuous button event tracking is complicated by the fact that two different
35input sources (say, mouse button 1 and the control key) can both press the
36same button, but the button should only be released when both of the
37pressing key have been released.
38
39When a key event issues a button command (+forward, +attack, etc), it appends
40its key number as a parameter to the command so it can be matched up with
41the release.
42
43state bit 0 is the current state of the key
44state bit 1 is edge triggered on the up to down transition
45state bit 2 is edge triggered on the down to up transition
46
47===============================================================================
48*/
49
50
56// LadyHavoc: added 6 new buttons
58//even more
60
62
63
64
66{
67 int k;
68 const char *c;
69
70 c = Cmd_Argv(cmd, 1);
71 if (c[0])
72 k = atoi(c);
73 else
74 k = -1; // typed manually at the console for continuous down
75
76 if (k == b->down[0] || k == b->down[1])
77 return; // repeating key
78
79 if (!b->down[0])
80 b->down[0] = k;
81 else if (!b->down[1])
82 b->down[1] = k;
83 else
84 {
85 Con_Print("Three keys down for a button!\n");
86 return;
87 }
88
89 if (b->state & 1)
90 return; // still down
91 b->state |= 1 + 2; // down + impulse down
92}
93
95{
96 int k;
97 const char *c;
98
99 c = Cmd_Argv(cmd, 1);
100 if (c[0])
101 k = atoi(c);
102 else
103 { // typed manually at the console, assume for unsticking, so clear all
104 b->down[0] = b->down[1] = 0;
105 b->state = 4; // impulse up
106 return;
107 }
108
109 if (b->down[0] == k)
110 b->down[0] = 0;
111 else if (b->down[1] == k)
112 b->down[1] = 0;
113 else
114 return; // key up without coresponding down (menu pass through)
115 if (b->down[0] || b->down[1])
116 return; // some other key is still holding it down
117
118 if (!(b->state & 1))
119 return; // still up (this should not happen)
120 b->state &= ~1; // now up
121 b->state |= 4; // impulse up
122}
123
128{
129 KeyUp(cmd, &in_mlook);
130 if ( !(in_mlook.state&1) && lookspring.value)
132}
153
158
161
164
165// LadyHavoc: added 6 new buttons
178
195
198
200
202
203static void IN_BestWeapon_Register(const char *name, int impulse, int weaponbit, int activeweaponcode, int ammostat, int ammomin)
204{
205 int i;
208 break;
209 if(i >= IN_BESTWEAPON_MAX)
210 {
211 Con_Printf("no slot left for weapon definition; increase IN_BESTWEAPON_MAX\n");
212 return; // sorry
213 }
216 if(weaponbit != -1)
217 in_bestweapon_info[i].weaponbit = weaponbit;
218 if(activeweaponcode != -1)
219 in_bestweapon_info[i].activeweaponcode = activeweaponcode;
220 if(ammostat != -1)
221 in_bestweapon_info[i].ammostat = ammostat;
222 if(ammomin != -1)
223 in_bestweapon_info[i].ammomin = ammomin;
224}
225
227{
228 memset(in_bestweapon_info, 0, sizeof(in_bestweapon_info));
237 IN_BestWeapon_Register("9", 9, 128, 128, STAT_CELLS, 1); // generic energy weapon for mods
238 IN_BestWeapon_Register("p", 209, 128, 128, STAT_CELLS, 1); // dpmod plasma gun
239 IN_BestWeapon_Register("w", 210, 8388608, 8388608, STAT_CELLS, 1); // dpmod plasma wave cannon
240 IN_BestWeapon_Register("l", 225, HIT_LASER_CANNON, HIT_LASER_CANNON, STAT_CELLS, 1); // hipnotic laser cannon
241 IN_BestWeapon_Register("h", 226, HIT_MJOLNIR, HIT_MJOLNIR, STAT_CELLS, 0); // hipnotic mjolnir hammer
242}
243
245{
246 if(Cmd_Argc(cmd) == 7)
247 {
249 Cmd_Argv(cmd, 1),
250 atoi(Cmd_Argv(cmd, 2)),
251 atoi(Cmd_Argv(cmd, 3)),
252 atoi(Cmd_Argv(cmd, 4)),
253 atoi(Cmd_Argv(cmd, 5)),
254 atoi(Cmd_Argv(cmd, 6))
255 );
256 }
257 else if(Cmd_Argc(cmd) == 2 && !strcmp(Cmd_Argv(cmd, 1), "clear"))
258 {
259 memset(in_bestweapon_info, 0, sizeof(in_bestweapon_info));
260 }
261 else if(Cmd_Argc(cmd) == 2 && !strcmp(Cmd_Argv(cmd, 1), "quake"))
262 {
264 }
265 else
266 {
267 Con_Printf("Usage: %s weaponshortname impulse itemcode activeweaponcode ammostat ammomin; %s clear; %s quake\n", Cmd_Argv(cmd, 0), Cmd_Argv(cmd, 0), Cmd_Argv(cmd, 0));
268 }
269}
270
272{
273 int i, n;
274 const char *t;
275 if (Cmd_Argc(cmd) < 2)
276 {
277 Con_Printf("bestweapon requires 1 or more parameters\n");
278 return;
279 }
280 for (i = 1;i < Cmd_Argc(cmd);i++)
281 {
282 t = Cmd_Argv(cmd, i);
283 // figure out which weapon this character refers to
285 {
286 if (!strcmp(in_bestweapon_info[n].name, t))
287 {
288 // we found out what weapon this character refers to
289 // check if the inventory contains the weapon and enough ammo
291 {
292 // we found one of the weapons the player wanted
293 // send an impulse to switch to it
295 return;
296 }
297 break;
298 }
299 }
300 // if we couldn't identify the weapon we just ignore it and continue checking for other weapons
301 }
302 // if we couldn't find any of the weapons, there's nothing more we can do...
303}
304
305/*
306===============
307CL_KeyState
308
309Returns 0.25 if a key was pressed and released during the frame,
3100.5 if it was pressed and held
3110 if held then released, and
3121.0 if held for the entire time
313===============
314*/
316{
317 float val;
318 qbool impulsedown, impulseup, down;
319
320 impulsedown = (key->state & 2) != 0;
321 impulseup = (key->state & 4) != 0;
322 down = (key->state & 1) != 0;
323 val = 0;
324
325 if (impulsedown && !impulseup)
326 {
327 if (down)
328 val = 0.5; // pressed and held this frame
329 else
330 val = 0; // I_Error ();
331 }
332 if (impulseup && !impulsedown)
333 {
334 if (down)
335 val = 0; // I_Error ();
336 else
337 val = 0; // released this frame
338 }
339 if (!impulsedown && !impulseup)
340 {
341 if (down)
342 val = 1.0; // held the entire frame
343 else
344 val = 0; // up the entire frame
345 }
346 if (impulsedown && impulseup)
347 {
348 if (down)
349 val = 0.75; // released and re-pressed this frame
350 else
351 val = 0.25; // pressed and released this frame
352 }
353
354 key->state &= 1; // clear impulses
355
356 return val;
357}
358
359
360
361
362//==========================================================================
363
364cvar_t cl_upspeed = {CF_CLIENT | CF_ARCHIVE, "cl_upspeed","400","vertical movement speed (while swimming or flying)"};
365cvar_t cl_forwardspeed = {CF_CLIENT | CF_ARCHIVE, "cl_forwardspeed","400","forward movement speed"};
366cvar_t cl_backspeed = {CF_CLIENT | CF_ARCHIVE, "cl_backspeed","400","backward movement speed"};
367cvar_t cl_sidespeed = {CF_CLIENT | CF_ARCHIVE, "cl_sidespeed","350","strafe movement speed"};
368
369cvar_t cl_movespeedkey = {CF_CLIENT | CF_ARCHIVE, "cl_movespeedkey","2.0","how much +speed multiplies keyboard movement speed"};
370cvar_t cl_movecliptokeyboard = {CF_CLIENT, "cl_movecliptokeyboard", "0", "if set to 1, any move is clipped to the nine keyboard states; if set to 2, only the direction is clipped, not the amount"};
371
372cvar_t cl_yawspeed = {CF_CLIENT | CF_ARCHIVE, "cl_yawspeed","140","keyboard yaw turning speed"};
373cvar_t cl_pitchspeed = {CF_CLIENT | CF_ARCHIVE, "cl_pitchspeed","150","keyboard pitch turning speed"};
374
375cvar_t cl_anglespeedkey = {CF_CLIENT | CF_ARCHIVE, "cl_anglespeedkey","1.5","how much +speed multiplies keyboard turning speed"};
376
377cvar_t cl_movement = {CF_CLIENT | CF_ARCHIVE, "cl_movement", "0", "enables clientside prediction of your player movement on DP servers (use cl_nopred for QWSV servers)"};
378cvar_t cl_movement_replay = {CF_CLIENT, "cl_movement_replay", "1", "use engine prediction"};
379cvar_t cl_movement_nettimeout = {CF_CLIENT | CF_ARCHIVE, "cl_movement_nettimeout", "0.3", "stops predicting moves when server is lagging badly (avoids major performance problems), timeout in seconds"};
380cvar_t cl_movement_minping = {CF_CLIENT | CF_ARCHIVE, "cl_movement_minping", "0", "whether to use prediction when ping is lower than this value in milliseconds"};
381cvar_t cl_movement_track_canjump = {CF_CLIENT | CF_ARCHIVE, "cl_movement_track_canjump", "1", "track if the player released the jump key between two jumps to decide if he is able to jump or not; when off, this causes some \"sliding\" slightly above the floor when the jump key is held too long; if the mod allows repeated jumping by holding space all the time, this has to be set to zero too"};
382cvar_t cl_movement_maxspeed = {CF_CLIENT, "cl_movement_maxspeed", "320", "how fast you can move (should match sv_maxspeed)"};
383cvar_t cl_movement_maxairspeed = {CF_CLIENT, "cl_movement_maxairspeed", "30", "how fast you can move while in the air (should match sv_maxairspeed)"};
384cvar_t cl_movement_stopspeed = {CF_CLIENT, "cl_movement_stopspeed", "100", "speed below which you will be slowed rapidly to a stop rather than sliding endlessly (should match sv_stopspeed)"};
385cvar_t cl_movement_friction = {CF_CLIENT, "cl_movement_friction", "4", "how fast you slow down (should match sv_friction)"};
386cvar_t cl_movement_wallfriction = {CF_CLIENT, "cl_movement_wallfriction", "1", "how fast you slow down while sliding along a wall (should match sv_wallfriction)"};
387cvar_t cl_movement_waterfriction = {CF_CLIENT, "cl_movement_waterfriction", "-1", "how fast you slow down (should match sv_waterfriction), if less than 0 the cl_movement_friction variable is used instead"};
388cvar_t cl_movement_edgefriction = {CF_CLIENT, "cl_movement_edgefriction", "1", "how much to slow down when you may be about to fall off a ledge (should match edgefriction)"};
389cvar_t cl_movement_stepheight = {CF_CLIENT, "cl_movement_stepheight", "18", "how tall a step you can step in one instant (should match sv_stepheight)"};
390cvar_t cl_movement_accelerate = {CF_CLIENT, "cl_movement_accelerate", "10", "how fast you accelerate (should match sv_accelerate)"};
391cvar_t cl_movement_airaccelerate = {CF_CLIENT, "cl_movement_airaccelerate", "-1", "how fast you accelerate while in the air (should match sv_airaccelerate), if less than 0 the cl_movement_accelerate variable is used instead"};
392cvar_t cl_movement_wateraccelerate = {CF_CLIENT, "cl_movement_wateraccelerate", "-1", "how fast you accelerate while in water (should match sv_wateraccelerate), if less than 0 the cl_movement_accelerate variable is used instead"};
393cvar_t cl_movement_jumpvelocity = {CF_CLIENT, "cl_movement_jumpvelocity", "270", "how fast you move upward when you begin a jump (should match the quakec code)"};
394cvar_t cl_movement_airaccel_qw = {CF_CLIENT, "cl_movement_airaccel_qw", "1", "ratio of QW-style air control as opposed to simple acceleration (reduces speed gain when zigzagging) (should match sv_airaccel_qw); when < 0, the speed is clamped against the maximum allowed forward speed after the move"};
395cvar_t cl_movement_airaccel_sideways_friction = {CF_CLIENT, "cl_movement_airaccel_sideways_friction", "0", "anti-sideways movement stabilization (should match sv_airaccel_sideways_friction); when < 0, only so much friction is applied that braking (by accelerating backwards) cannot be stronger"};
396cvar_t cl_nopred = {CF_CLIENT | CF_ARCHIVE, "cl_nopred", "0", "(QWSV only) disables player movement prediction when playing on QWSV servers (this setting is separate from cl_movement because player expectations are different when playing on DP vs QW servers)"};
397
398cvar_t in_pitch_min = {CF_CLIENT, "in_pitch_min", "-90", "how far you can aim upward (quake used -70)"};
399cvar_t in_pitch_max = {CF_CLIENT, "in_pitch_max", "90", "how far you can aim downward (quake used 80)"};
400
401cvar_t m_filter = {CF_CLIENT | CF_ARCHIVE, "m_filter","0", "smoothes mouse movement, less responsive but smoother aiming"};
402cvar_t m_accelerate = {CF_CLIENT | CF_ARCHIVE, "m_accelerate","1", "linear mouse acceleration factor (set to 1 to disable the linear acceleration and use only the power or natural acceleration; set to 0 to disable all acceleration)"};
403cvar_t m_accelerate_minspeed = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_minspeed","5000", "below this speed in px/s, no acceleration is done, with a linear slope between (applied only on linear acceleration)"};
404cvar_t m_accelerate_maxspeed = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_maxspeed","10000", "above this speed in px/s, full acceleration is done, with a linear slope between (applied only on linear acceleration)"};
405cvar_t m_accelerate_filter = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_filter","0", "linear mouse acceleration factor filtering lowpass constant in seconds (set to 0 for no filtering)"};
406cvar_t m_accelerate_power_offset = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_power_offset","0", "below this speed in px/ms, no power acceleration is done"};
407cvar_t m_accelerate_power = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_power","2", "acceleration power (must be above 1 to be useful)"};
408cvar_t m_accelerate_power_senscap = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_power_senscap", "0", "maximum acceleration factor generated by power acceleration; use 0 for unbounded"};
409cvar_t m_accelerate_power_strength = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_power_strength", "0", "strength of the power mouse acceleration effect"};
410cvar_t m_accelerate_natural_strength = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_natural_strength", "0", "How quickly the accelsensitivity approaches the m_accelerate_natural_accelsenscap, values are compressed between 0 and 1 but higher numbers are allowed"};
411cvar_t m_accelerate_natural_accelsenscap = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_natural_accelsenscap", "0", "Horizontal asymptote that sets the maximum value for the natural mouse acceleration curve, value 2, for example, means that the maximum sensitivity is 2 times the base sensitivity"};
412cvar_t m_accelerate_natural_offset = {CF_CLIENT | CF_ARCHIVE, "m_accelerate_natural_offset", "0", "below this speed in px/ms, no natural acceleration is done"};
413
414cvar_t cl_netfps = {CF_CLIENT | CF_ARCHIVE, "cl_netfps","72", "how many input packets to send to server each second"};
415cvar_t cl_netrepeatinput = {CF_CLIENT | CF_ARCHIVE, "cl_netrepeatinput", "1", "how many packets in a row can be lost without movement issues when using cl_movement (technically how many input messages to repeat in each packet that have not yet been acknowledged by the server), only affects DP7 and later servers (Quake uses 0, QuakeWorld uses 2, and just for comparison Quake3 uses 1)"};
416cvar_t cl_netimmediatebuttons = {CF_CLIENT | CF_ARCHIVE, "cl_netimmediatebuttons", "1", "sends extra packets whenever your buttons change or an impulse is used (basically: whenever you click fire or change weapon)"};
417
418cvar_t cl_nodelta = {CF_CLIENT, "cl_nodelta", "0", "disables delta compression of non-player entities in QW network protocol"};
419
420cvar_t cl_csqc_generatemousemoveevents = {CF_CLIENT, "cl_csqc_generatemousemoveevents", "1", "enables calls to CSQC_InputEvent with type 2, for compliance with EXT_CSQC spec"};
421
422extern cvar_t v_flipped;
423
424/*
425================
426CL_AdjustAngles
427
428Moves the local angle positions
429================
430*/
431static void CL_AdjustAngles (void)
432{
433 float speed;
434 float up, down;
435
436 if (in_speed.state & 1)
438 else
439 speed = cl.realframetime;
440
441 if (!(in_strafe.state & 1))
442 {
445 }
446 if (in_klook.state & 1)
447 {
451 }
452
454 down = CL_KeyState(&in_lookdown);
455
457 cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
458
459 if (up || down)
461
464 if (cl.viewangles[YAW] >= 180)
465 cl.viewangles[YAW] -= 360;
466 if (cl.viewangles[PITCH] >= 180)
467 cl.viewangles[PITCH] -= 360;
468 // TODO: honor serverinfo minpitch and maxpitch values in PROTOCOL_QUAKEWORLD
469 // TODO: honor proquake pq_fullpitch cvar when playing on proquake server (server stuffcmd's this to 0 usually)
471 cl.viewangles[ROLL] = bound(-180, cl.viewangles[ROLL], 180);
472}
473
475
476/*
477================
478CL_Input
479
480Send the intended movement message to the server
481================
482*/
483void CL_Input (void)
484{
485 float mx, my;
486 static float old_mouse_x = 0, old_mouse_y = 0;
487
488 // clamp before the move to prevent starting with bad angles
490
493
494 // reset some of the command fields
495 cl.cmd.forwardmove = 0;
496 cl.cmd.sidemove = 0;
497 cl.cmd.upmove = 0;
498
499 // get basic movement from keyboard
500 if (in_strafe.state & 1)
501 {
504 }
505
508
511
512 if (! (in_klook.state & 1) )
513 {
516 }
517
518 // adjust for speed key
519 if (in_speed.state & 1)
520 {
524 }
525
526 // allow mice or other external controllers to add to the move
527 IN_Move ();
528
529 // send mouse move to csqc
531 {
533 {
534 // event type 3 is a DP_CSQC thing
535 static int oldwindowmouse[2];
536 if (oldwindowmouse[0] != in_windowmouse_x || oldwindowmouse[1] != in_windowmouse_y)
537 {
539 oldwindowmouse[0] = in_windowmouse_x;
540 oldwindowmouse[1] = in_windowmouse_y;
541 }
542 }
543 else
544 {
545 if (in_mouse_x || in_mouse_y)
547 }
548 }
549
550 // apply m_accelerate if it is on
551 if(m_accelerate.value > 0)
552 {
553 float mouse_deltadist = sqrtf(in_mouse_x * in_mouse_x + in_mouse_y * in_mouse_y);
554 float speed = mouse_deltadist / cl.realframetime;
555 static float averagespeed = 0;
556 float f, mi, ma;
559 else
560 f = 1;
561 averagespeed = speed * f + averagespeed * (1 - f);
562
563 // Note: this check is technically unnecessary, as everything in here cancels out if it is zero.
564 if (m_accelerate.value != 1.0f)
565 {
566 // First do linear slope acceleration which was ripped "in
567 // spirit" from many classic mouse driver implementations.
568 // If m_accelerate.value == 1, this code does nothing at all.
569
572
573 if(averagespeed <= mi)
574 {
575 f = 1;
576 }
577 else if(averagespeed >= ma)
578 {
580 }
581 else
582 {
583 f = averagespeed;
584 f = (f - mi) / (ma - mi) * (m_accelerate.value - 1) + 1;
585 }
586 in_mouse_x *= f;
587 in_mouse_y *= f;
588 }
589
590 // Note: this check is technically unnecessary, as everything in here cancels out if it is zero.
592 {
593 // Then do Quake Live-style power acceleration.
594 // Note that this behavior REPLACES the usual
595 // sensitivity, so we apply it but then divide by
596 // sensitivity.value so that the later multiplication
597 // restores it again.
598 float accelsens = 1.0f;
599 float adjusted_speed_pxms = (averagespeed * 0.001f - m_accelerate_power_offset.value) * m_accelerate_power_strength.value;
600 float inv_sensitivity = 1.0f / sensitivity.value;
601 if (adjusted_speed_pxms > 0)
602 {
603 if (m_accelerate_power.value > 1.0f)
604 {
605 // TODO: How does this interact with sensitivity changes? Is this intended?
606 // Currently: more sensitivity = less acceleration at same pixel speed.
607 accelsens += expf((m_accelerate_power.value - 1.0f) * logf(adjusted_speed_pxms)) * inv_sensitivity;
608 }
609 else
610 {
611 // The limit of the then-branch for m_accelerate_power -> 1.
612 accelsens += inv_sensitivity;
613 // Note: QL had just accelsens = 1.0f.
614 // This is mathematically wrong though.
615 }
616 }
617 else
618 {
619 // The limit of the then-branch for adjusted_speed -> 0.
620 // accelsens += 0.0f;
621 }
622 if (m_accelerate_power_senscap.value > 0.0f && accelsens > m_accelerate_power_senscap.value * inv_sensitivity)
623 {
624 // TODO: How does this interact with sensitivity changes? Is this intended?
625 // Currently: senscap is in absolute sensitivity units, so if senscap < sensitivity, it overrides.
626 accelsens = m_accelerate_power_senscap.value * inv_sensitivity;
627 }
628
629 in_mouse_x *= accelsens;
630 in_mouse_y *= accelsens;
631 }
632
634 {
635 float accelsens = 1.0f;
636 float adjusted_speed_pxms = (averagespeed * 0.001f - m_accelerate_natural_offset.value);
637
638 if (adjusted_speed_pxms > 0 && m_accelerate_natural_accelsenscap.value != 1.0f)
639 {
640 float adjusted_accelsenscap = m_accelerate_natural_accelsenscap.value - 1.0f;
641 // This equation is made to multiply the sensitivity for a factor between 1 and m_accelerate_natural_accelsenscap
642 // this means there is no need to divide it for the sensitivity.value as the whole
643 // expression needs to be multiplied by the sensitivity at the end instead of only having the sens multiplied
644 accelsens += (adjusted_accelsenscap - adjusted_accelsenscap * exp( - ((adjusted_speed_pxms * m_accelerate_natural_strength.value) / fabs(adjusted_accelsenscap) )));
645 }
646
647 in_mouse_x *= accelsens;
648 in_mouse_y *= accelsens;
649 }
650 }
651
652 // apply m_filter if it is on
653 mx = in_mouse_x;
654 my = in_mouse_y;
655 if (m_filter.integer)
656 {
657 in_mouse_x = (mx + old_mouse_x) * 0.5;
658 in_mouse_y = (my + old_mouse_y) * 0.5;
659 }
660 old_mouse_x = mx;
661 old_mouse_y = my;
662
663 // ignore a mouse move if mouse was activated/deactivated this frame
665 {
667 in_mouse_x = old_mouse_x = 0;
668 in_mouse_y = old_mouse_y = 0;
669 }
670
671 // if not in menu, apply mouse move to viewangles/movement
673 {
674 float modulatedsensitivity = sensitivity.value * cl.sensitivityscale;
675 if (in_strafe.state & 1)
676 {
677 // strafing mode, all looking is movement
679 cl.cmd.sidemove += m_side.value * in_mouse_x * modulatedsensitivity;
681 cl.cmd.upmove -= m_forward.value * in_mouse_y * modulatedsensitivity;
682 else
683 cl.cmd.forwardmove -= m_forward.value * in_mouse_y * modulatedsensitivity;
684 }
685 else if ((in_mlook.state & 1) || freelook.integer)
686 {
687 // mouselook, lookstrafe causes turning to become strafing
690 cl.cmd.sidemove += m_side.value * in_mouse_x * modulatedsensitivity;
691 else
692 cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * modulatedsensitivity * cl.viewzoom;
693 cl.viewangles[PITCH] += m_pitch.value * in_mouse_y * modulatedsensitivity * cl.viewzoom;
694 }
695 else
696 {
697 // non-mouselook, yaw turning and forward/back movement
698 cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * modulatedsensitivity * cl.viewzoom;
699 cl.cmd.forwardmove -= m_forward.value * in_mouse_y * modulatedsensitivity;
700 }
701 }
702 else // don't pitch drift when csqc is controlling the mouse
703 {
704 // mouse interacting with the scene, mostly stationary view
706 // update prydon cursor
707 cl.cmd.cursor_screen[0] = in_windowmouse_x * 2.0 / vid.mode.width - 1.0;
709 }
710
712 {
715 }
716
717 // clamp after the move to prevent rendering with bad angles
719
721 {
722 vec_t f = 1;
723 if (in_speed.state & 1)
726 {
727 // digital direction, analog amount
728 vec_t wishvel_x, wishvel_y;
729 wishvel_x = fabs(cl.cmd.forwardmove);
730 wishvel_y = fabs(cl.cmd.sidemove);
731 if(wishvel_x != 0 && wishvel_y != 0 && wishvel_x != wishvel_y)
732 {
733 vec_t wishspeed = sqrt(wishvel_x * wishvel_x + wishvel_y * wishvel_y);
734 if(wishvel_x >= 2 * wishvel_y)
735 {
736 // pure X motion
737 if(cl.cmd.forwardmove > 0)
739 else
741 cl.cmd.sidemove = 0;
742 }
743 else if(wishvel_y >= 2 * wishvel_x)
744 {
745 // pure Y motion
746 cl.cmd.forwardmove = 0;
747 if(cl.cmd.sidemove > 0)
749 else
751 }
752 else
753 {
754 // diagonal
755 if(cl.cmd.forwardmove > 0)
756 cl.cmd.forwardmove = 0.70710678118654752440 * wishspeed;
757 else
758 cl.cmd.forwardmove = -0.70710678118654752440 * wishspeed;
759 if(cl.cmd.sidemove > 0)
760 cl.cmd.sidemove = 0.70710678118654752440 * wishspeed;
761 else
762 cl.cmd.sidemove = -0.70710678118654752440 * wishspeed;
763 }
764 }
765 }
767 {
768 // digital direction, digital amount
769 if(cl.cmd.sidemove >= cl_sidespeed.value * f * 0.5)
771 else if(cl.cmd.sidemove <= -cl_sidespeed.value * f * 0.5)
773 else
774 cl.cmd.sidemove = 0;
775 if(cl.cmd.forwardmove >= cl_forwardspeed.value * f * 0.5)
777 else if(cl.cmd.forwardmove <= -cl_backspeed.value * f * 0.5)
779 else
780 cl.cmd.forwardmove = 0;
781 }
782 }
783}
784
785#include "cl_collision.h"
786
787static void CL_UpdatePrydonCursor(void)
788{
789 vec3_t temp;
790
791 if (cl_prydoncursor.integer <= 0)
793
794 /*
795 if (cl.cmd.cursor_screen[0] < -1)
796 {
797 cl.viewangles[YAW] -= m_yaw.value * (cl.cmd.cursor_screen[0] - -1) * vid.width * sensitivity.value * cl.viewzoom;
798 cl.cmd.cursor_screen[0] = -1;
799 }
800 if (cl.cmd.cursor_screen[0] > 1)
801 {
802 cl.viewangles[YAW] -= m_yaw.value * (cl.cmd.cursor_screen[0] - 1) * vid.width * sensitivity.value * cl.viewzoom;
803 cl.cmd.cursor_screen[0] = 1;
804 }
805 if (cl.cmd.cursor_screen[1] < -1)
806 {
807 cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - -1) * vid.height * sensitivity.value * cl.viewzoom;
808 cl.cmd.cursor_screen[1] = -1;
809 }
810 if (cl.cmd.cursor_screen[1] > 1)
811 {
812 cl.viewangles[PITCH] += m_pitch.value * (cl.cmd.cursor_screen[1] - 1) * vid.height * sensitivity.value * cl.viewzoom;
813 cl.cmd.cursor_screen[1] = 1;
814 }
815 */
816 cl.cmd.cursor_screen[0] = bound(-1, cl.cmd.cursor_screen[0], 1);
817 cl.cmd.cursor_screen[1] = bound(-1, cl.cmd.cursor_screen[1], 1);
818 cl.cmd.cursor_screen[2] = 1;
819
820 // calculate current view matrix
822 // calculate direction vector of cursor in viewspace by using frustum slopes
823 VectorSet(temp, cl.cmd.cursor_screen[2] * 1000000, (v_flipped.integer ? -1 : 1) * cl.cmd.cursor_screen[0] * -r_refdef.view.frustum_x * 1000000, cl.cmd.cursor_screen[1] * -r_refdef.view.frustum_y * 1000000);
825 // trace from view origin to the cursor
827 {
828 cl.cmd.cursor_fraction = 1.0f;
832 }
833 else
835}
836
837#define NUMOFFSETS 27
839{
840// 1 no nudge (just return the original if this test passes)
841 { 0.000, 0.000, 0.000},
842// 6 simple nudges
843 { 0.000, 0.000, 0.125}, { 0.000, 0.000, -0.125},
844 {-0.125, 0.000, 0.000}, { 0.125, 0.000, 0.000},
845 { 0.000, -0.125, 0.000}, { 0.000, 0.125, 0.000},
846// 4 diagonal flat nudges
847 {-0.125, -0.125, 0.000}, { 0.125, -0.125, 0.000},
848 {-0.125, 0.125, 0.000}, { 0.125, 0.125, 0.000},
849// 8 diagonal upward nudges
850 {-0.125, 0.000, 0.125}, { 0.125, 0.000, 0.125},
851 { 0.000, -0.125, 0.125}, { 0.000, 0.125, 0.125},
852 {-0.125, -0.125, 0.125}, { 0.125, -0.125, 0.125},
853 {-0.125, 0.125, 0.125}, { 0.125, 0.125, 0.125},
854// 8 diagonal downward nudges
855 {-0.125, 0.000, -0.125}, { 0.125, 0.000, -0.125},
856 { 0.000, -0.125, -0.125}, { 0.000, 0.125, -0.125},
857 {-0.125, -0.125, -0.125}, { 0.125, -0.125, -0.125},
858 {-0.125, 0.125, -0.125}, { 0.125, 0.125, -0.125},
859};
860
862{
863 int i;
864 vec3_t neworigin;
865 for (i = 0;i < NUMOFFSETS;i++)
866 {
867 VectorAdd(offsets[i], s->origin, neworigin);
869 {
870 VectorCopy(neworigin, s->origin);
871 return true;
872 }
873 }
874 // if all offsets failed, give up
875 return false;
876}
877
879{
880 vec_t f;
881 vec3_t origin1, origin2;
882 trace_t trace;
883
884 // make sure player is not stuck
886
887 // set crouched
888 if (s->cmd.crouch)
889 {
890 // wants to crouch, this always works..
891 if (!s->crouched)
892 s->crouched = true;
893 }
894 else
895 {
896 // wants to stand, if currently crouching we need to check for a
897 // low ceiling first
898 if (s->crouched)
899 {
901 if (!trace.startsolid)
902 s->crouched = false;
903 }
904 }
905 if (s->crouched)
906 {
909 }
910 else
911 {
914 }
915
916 // set onground
917 VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + 1);
918 VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 1); // -2 causes clientside doublejump bug at above 150fps, raising that to 300fps :)
920 if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
921 {
922 s->onground = true;
923
924 // this code actually "predicts" an impact; so let's clip velocity first
925 f = DotProduct(s->velocity, trace.plane.normal);
926 if(f < 0) // only if moving downwards actually
927 VectorMA(s->velocity, -f, trace.plane.normal, s->velocity);
928 }
929 else
930 s->onground = false;
931
932 // set watertype/waterlevel
933 VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + s->mins[2] + 1);
935 s->watertype = CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
936 if (s->watertype)
937 {
939 origin1[2] = s->origin[2] + (s->mins[2] + s->maxs[2]) * 0.5f;
940 if (CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
941 {
943 origin1[2] = s->origin[2] + 22;
944 if (CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
946 }
947 }
948
949 // water jump prediction
950 if (s->onground || s->velocity[2] <= 0 || s->waterjumptime <= 0)
951 s->waterjumptime = 0;
952}
953
955{
956 int bump;
957 double t;
958 vec_t f;
959 vec3_t neworigin;
960 vec3_t currentorigin2;
961 vec3_t neworigin2;
962 vec3_t primalvelocity;
963 trace_t trace;
964 trace_t trace2;
965 trace_t trace3;
967 VectorCopy(s->velocity, primalvelocity);
968 for (bump = 0, t = s->cmd.frametime;bump < 8 && VectorLength2(s->velocity) > 0;bump++)
969 {
970 VectorMA(s->origin, t, s->velocity, neworigin);
972 if (trace.fraction < 1 && trace.plane.normal[2] == 0)
973 {
974 // may be a step or wall, try stepping up
975 // first move forward at a higher level
976 VectorSet(currentorigin2, s->origin[0], s->origin[1], s->origin[2] + cl.movevars_stepheight);
977 VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + cl.movevars_stepheight);
978 trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
979 if (!trace2.startsolid)
980 {
981 // then move down from there
982 VectorCopy(trace2.endpos, currentorigin2);
983 VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], s->origin[2]);
984 trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
985 //Con_Printf("%f %f %f %f : %f %f %f %f : %f %f %f %f\n", trace.fraction, trace.endpos[0], trace.endpos[1], trace.endpos[2], trace2.fraction, trace2.endpos[0], trace2.endpos[1], trace2.endpos[2], trace3.fraction, trace3.endpos[0], trace3.endpos[1], trace3.endpos[2]);
986 // accept the new trace if it made some progress
987 if (fabs(trace3.endpos[0] - trace.endpos[0]) >= 0.03125 || fabs(trace3.endpos[1] - trace.endpos[1]) >= 0.03125)
988 {
989 trace = trace2;
990 VectorCopy(trace3.endpos, trace.endpos);
991 }
992 }
993 }
994
995 // check if it moved at all
996 if (trace.fraction >= 0.001)
997 VectorCopy(trace.endpos, s->origin);
998
999 // check if it moved all the way
1000 if (trace.fraction == 1)
1001 break;
1002
1003 // this is only really needed for nogravityonground combined with gravityunaffectedbyticrate
1004 // <LadyHavoc> I'm pretty sure I commented it out solely because it seemed redundant
1005 // this got commented out in a change that supposedly makes the code match QW better
1006 // so if this is broken, maybe put it in an if(cls.protocol != PROTOCOL_QUAKEWORLD) block
1007 if (trace.plane.normal[2] > 0.7)
1008 s->onground = true;
1009
1010 t -= t * trace.fraction;
1011
1012 f = DotProduct(s->velocity, trace.plane.normal);
1013 VectorMA(s->velocity, -f, trace.plane.normal, s->velocity);
1014 }
1015 if (s->waterjumptime > 0)
1016 VectorCopy(primalvelocity, s->velocity);
1017}
1018
1019
1021{
1023 vec_t f;
1024 vec3_t wishvel;
1026
1027 // water jump only in certain situations
1028 // this mimics quakeworld code
1029 if (s->cmd.jump && s->waterlevel == 2 && s->velocity[2] >= -180)
1030 {
1032 vec3_t yawangles;
1033 vec3_t spot;
1034 VectorSet(yawangles, 0, s->cmd.viewangles[1], 0);
1035 AngleVectors(yawangles, forward, NULL, NULL);
1036 VectorMA(s->origin, 24, forward, spot);
1037 spot[2] += 8;
1038 if (CL_TracePoint(spot, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsolid)
1039 {
1040 spot[2] += 24;
1041 if (!CL_TracePoint(spot, MOVE_NOMONSTERS, s->self, 0, 0, 0, true, false, NULL, false).startsolid)
1042 {
1043 VectorScale(forward, 50, s->velocity);
1044 s->velocity[2] = 310;
1045 s->waterjumptime = 2;
1046 s->onground = false;
1047 s->cmd.canjump = false;
1048 }
1049 }
1050 }
1051
1052 if (!(s->cmd.forwardmove*s->cmd.forwardmove + s->cmd.sidemove*s->cmd.sidemove + s->cmd.upmove*s->cmd.upmove))
1053 {
1054 // drift towards bottom
1055 VectorSet(wishvel, 0, 0, -60);
1056 }
1057 else
1058 {
1059 // swim
1061 vec3_t right;
1062 vec3_t up;
1063 // calculate movement vector
1065 VectorSet(up, 0, 0, 1);
1066 VectorMAMAM(s->cmd.forwardmove, forward, s->cmd.sidemove, right, s->cmd.upmove, up, wishvel);
1067 }
1068
1069 // split wishvel into wishspeed and wishdir
1070 VectorCopy(wishvel, wishdir);
1073
1074 if (s->crouched)
1075 wishspeed *= 0.5;
1076
1077 if (s->waterjumptime <= 0)
1078 {
1079 // water friction
1081 f = bound(0, f, 1);
1082 VectorScale(s->velocity, f, s->velocity);
1083
1084 // water acceleration
1086 if (f > 0)
1087 {
1090 }
1091
1092 // holding jump button swims upward slowly
1093 if (s->cmd.jump)
1094 {
1096 s->velocity[2] = 50;
1097 else if (s->watertype & SUPERCONTENTS_SLIME)
1098 s->velocity[2] = 80;
1099 else
1100 {
1102 s->velocity[2] = 200;
1103 else
1104 s->velocity[2] = 100;
1105 }
1106 }
1107 }
1108
1110}
1111
1113{
1114 if(forward == 0 && side == 0)
1115 return 0; // avoid division by zero
1116 angle -= RAD2DEG(atan2(side, forward));
1117 angle = (ANGLEMOD(angle + 180) - 180) / 45;
1118 if(angle > 1)
1119 return 0;
1120 if(angle < -1)
1121 return 0;
1122 return 1 - fabs(angle);
1123}
1124
1126{
1127 if(a == 0)
1128 {
1129 if(lerp < 1)
1130 return 0;
1131 else
1132 return b;
1133 }
1134 if(b == 0)
1135 {
1136 if(lerp > 0)
1137 return 0;
1138 else
1139 return a;
1140 }
1141 return a * pow(fabs(b / a), lerp);
1142}
1143
1145{
1146 vec_t zspeed, speed, dot, k;
1147
1148#if 0
1149 // this doesn't play well with analog input
1150 if(s->cmd.forwardmove == 0 || s->cmd.sidemove != 0)
1151 return;
1152 k = 32;
1153#else
1154 k = 32 * (2 * CL_IsMoveInDirection(s->cmd.forwardmove, s->cmd.sidemove, 0) - 1);
1155 if(k <= 0)
1156 return;
1157#endif
1158
1159 k *= bound(0, wishspeed / cl.movevars_maxairspeed, 1);
1160
1161 zspeed = s->velocity[2];
1162 s->velocity[2] = 0;
1163 speed = VectorNormalizeLength(s->velocity);
1164
1165 dot = DotProduct(s->velocity, wishdir);
1166
1167 if(dot > 0) { // we can't change direction while slowing down
1169 speed = max(0, speed - cl.movevars_aircontrol_penalty * sqrt(max(0, 1 - dot*dot)) * k/32);
1171 VectorMAM(speed, s->velocity, k, wishdir, s->velocity);
1173 }
1174
1175 VectorScale(s->velocity, speed, s->velocity);
1176 s->velocity[2] = zspeed;
1177}
1178
1179static float CL_ClientMovement_Physics_AdjustAirAccelQW(float accelqw, float factor)
1180{
1181 return
1182 (accelqw < 0 ? -1 : +1)
1183 *
1184 bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1);
1185}
1186
1187static void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t stretchfactor, vec_t sidefric, vec_t speedlimit)
1188{
1189 vec_t vel_straight;
1190 vec_t vel_z;
1191 vec3_t vel_perpend;
1192 vec_t step;
1193 vec3_t vel_xy;
1194 vec_t vel_xy_current;
1195 vec_t vel_xy_backward, vel_xy_forward;
1196 vec_t speedclamp;
1197
1198 if(stretchfactor > 0)
1199 speedclamp = stretchfactor;
1200 else if(accelqw < 0)
1201 speedclamp = 1;
1202 else
1203 speedclamp = -1; // no clamping
1204
1205 if(accelqw < 0)
1206 accelqw = -accelqw;
1207
1209 wishspeed0 = wishspeed; // don't need to emulate this Q1 bug
1210
1211 vel_straight = DotProduct(s->velocity, wishdir);
1212 vel_z = s->velocity[2];
1213 VectorCopy(s->velocity, vel_xy); vel_xy[2] -= vel_z;
1214 VectorMA(vel_xy, -vel_straight, wishdir, vel_perpend);
1215
1216 step = accel * s->cmd.frametime * wishspeed0;
1217
1218 vel_xy_current = VectorLength(vel_xy);
1219 if(speedlimit > 0)
1220 accelqw = CL_ClientMovement_Physics_AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
1221 vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
1222 vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
1223 if(vel_xy_backward < 0)
1224 vel_xy_backward = 0; // not that it REALLY occurs that this would cause wrong behaviour afterwards
1225
1226 vel_straight = vel_straight + bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
1227
1228 if(sidefric < 0 && VectorLength2(vel_perpend))
1229 // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
1230 {
1231 vec_t f, fmin;
1232 f = max(0, 1 + s->cmd.frametime * wishspeed * sidefric);
1233 fmin = (vel_xy_backward*vel_xy_backward - vel_straight*vel_straight) / VectorLength2(vel_perpend);
1234 // assume: fmin > 1
1235 // vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
1236 // vel_xy_backward*vel_xy_backward > vel_straight*vel_straight + vel_perpend*vel_perpend
1237 // vel_xy_backward*vel_xy_backward > vel_xy * vel_xy
1238 // obviously, this cannot be
1239 if(fmin <= 0)
1240 VectorScale(vel_perpend, f, vel_perpend);
1241 else
1242 {
1243 fmin = sqrt(fmin);
1244 VectorScale(vel_perpend, max(fmin, f), vel_perpend);
1245 }
1246 }
1247 else
1248 VectorScale(vel_perpend, max(0, 1 - s->cmd.frametime * wishspeed * sidefric), vel_perpend);
1249
1250 VectorMA(vel_perpend, vel_straight, wishdir, s->velocity);
1251
1252 if(speedclamp >= 0)
1253 {
1254 vec_t vel_xy_preclamp;
1255 vel_xy_preclamp = VectorLength(s->velocity);
1256 if(vel_xy_preclamp > 0) // prevent division by zero
1257 {
1258 vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
1259 if(vel_xy_current < vel_xy_preclamp)
1260 VectorScale(s->velocity, (vel_xy_current / vel_xy_preclamp), s->velocity);
1261 }
1262 }
1263
1264 s->velocity[2] += vel_z;
1265}
1266
1268{
1269 vec3_t curvel, wishvel, acceldir, curdir;
1270 float addspeed, accelspeed, curspeed;
1271 float dot;
1272
1273 float airforwardaccel = cl.movevars_warsowbunny_airforwardaccel;
1274 float bunnyaccel = cl.movevars_warsowbunny_accel;
1275 float bunnytopspeed = cl.movevars_warsowbunny_topspeed;
1276 float turnaccel = cl.movevars_warsowbunny_turnaccel;
1277 float backtosideratio = cl.movevars_warsowbunny_backtosideratio;
1278
1279 if( !wishspeed )
1280 return;
1281
1282 VectorCopy( s->velocity, curvel );
1283 curvel[2] = 0;
1284 curspeed = VectorLength( curvel );
1285
1286 if( wishspeed > curspeed * 1.01f )
1287 {
1288 float faccelspeed = curspeed + airforwardaccel * cl.movevars_maxairspeed * s->cmd.frametime;
1289 if( faccelspeed < wishspeed )
1290 wishspeed = faccelspeed;
1291 }
1292 else
1293 {
1294 float f = ( bunnytopspeed - curspeed ) / ( bunnytopspeed - cl.movevars_maxairspeed );
1295 if( f < 0 )
1296 f = 0;
1297 wishspeed = max( curspeed, cl.movevars_maxairspeed ) + bunnyaccel * f * cl.movevars_maxairspeed * s->cmd.frametime;
1298 }
1299 VectorScale( wishdir, wishspeed, wishvel );
1300 VectorSubtract( wishvel, curvel, acceldir );
1301 addspeed = VectorNormalizeLength( acceldir );
1302
1303 accelspeed = turnaccel * cl.movevars_maxairspeed /* wishspeed */ * s->cmd.frametime;
1304 if( accelspeed > addspeed )
1305 accelspeed = addspeed;
1306
1307 if( backtosideratio < 1.0f )
1308 {
1309 VectorNormalize2( curvel, curdir );
1310 dot = DotProduct( acceldir, curdir );
1311 if( dot < 0 )
1312 VectorMA( acceldir, -( 1.0f - backtosideratio ) * dot, curdir, acceldir );
1313 }
1314
1315 VectorMA( s->velocity, accelspeed, acceldir, s->velocity );
1316}
1317
1319{
1320 // jump if on ground with jump button pressed but only if it has been
1321 // released at least once since the last jump
1322 if (s->cmd.jump)
1323 {
1325 {
1327 s->onground = false;
1328 s->cmd.canjump = false;
1329 }
1330 }
1331 else
1332 s->cmd.canjump = true;
1333}
1334
1336{
1339 vec_t addspeed;
1340 vec_t accelspeed;
1341 vec_t speed;
1342 vec_t gravity;
1344 vec3_t right;
1345 vec3_t up;
1346 vec3_t wishvel;
1348 vec3_t yawangles;
1349 trace_t trace;
1350
1352
1353 // calculate movement vector
1354 VectorSet(yawangles, 0, s->cmd.viewangles[1], 0);
1355 AngleVectors(yawangles, forward, right, up);
1356 VectorMAM(s->cmd.forwardmove, forward, s->cmd.sidemove, right, wishvel);
1357
1358 // split wishvel into wishspeed and wishdir
1359 VectorCopy(wishvel, wishdir);
1361
1362 // check if onground
1363 if (s->onground)
1364 {
1366 if (s->crouched)
1367 wishspeed *= 0.5;
1368
1369 // apply edge friction
1370 speed = Vector2Length(s->velocity);
1371 if (speed > 0)
1372 {
1374 if (cl.movevars_edgefriction != 1)
1375 {
1376 vec3_t neworigin2;
1377 vec3_t neworigin3;
1378 // note: QW uses the full player box for the trace, and yet still
1379 // uses s->origin[2] + s->mins[2], which is clearly an bug, but
1380 // this mimics it for compatibility
1381 VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/speed), s->origin[1] + s->velocity[1]*(16/speed), s->origin[2] + s->mins[2]);
1382 VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34);
1384 trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true);
1385 else
1386 trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true, false);
1387 if (trace.fraction == 1 && !trace.startsolid)
1389 }
1390 // apply ground friction
1391 speed = 1 - s->cmd.frametime * friction * ((speed < cl.movevars_stopspeed) ? (cl.movevars_stopspeed / speed) : 1);
1392 speed = max(speed, 0);
1393 VectorScale(s->velocity, speed, s->velocity);
1394 }
1395 addspeed = wishspeed - DotProduct(s->velocity, wishdir);
1396 if (addspeed > 0)
1397 {
1398 accelspeed = min(cl.movevars_accelerate * s->cmd.frametime * wishspeed, addspeed);
1399 VectorMA(s->velocity, accelspeed, wishdir, s->velocity);
1400 }
1403 {
1405 s->velocity[2] -= gravity * 0.5f;
1406 else
1407 s->velocity[2] -= gravity;
1408 }
1410 s->velocity[2] = 0;
1411 if (VectorLength2(s->velocity))
1414 {
1416 s->velocity[2] -= gravity * 0.5f;
1417 }
1418 }
1419 else
1420 {
1421 if (s->waterjumptime <= 0)
1422 {
1423 // apply air speed limit
1424 vec_t accel, wishspeed0, wishspeed2, accelqw, strafity;
1425 qbool accelerating;
1426
1427 accelqw = cl.movevars_airaccel_qw;
1428 wishspeed0 = wishspeed;
1430 if (s->crouched)
1431 wishspeed *= 0.5;
1432 accel = cl.movevars_airaccelerate;
1433
1434 accelerating = (DotProduct(s->velocity, wishdir) > 0);
1435 wishspeed2 = wishspeed;
1436
1437 // CPM: air control
1439 {
1440 vec3_t curdir;
1441 curdir[0] = s->velocity[0];
1442 curdir[1] = s->velocity[1];
1443 curdir[2] = 0;
1444 VectorNormalize(curdir);
1445 accel = accel + (cl.movevars_airstopaccelerate - accel) * max(0, -DotProduct(curdir, wishdir));
1446 }
1447 strafity = CL_IsMoveInDirection(s->cmd.forwardmove, s->cmd.sidemove, -90) + CL_IsMoveInDirection(s->cmd.forwardmove, s->cmd.sidemove, +90); // if one is nonzero, other is always zero
1453 accelqw =
1454 (((strafity > 0.5 ? cl.movevars_airstrafeaccel_qw : cl.movevars_airaccel_qw) >= 0) ? +1 : -1)
1455 *
1457 // !CPM
1458
1459 if(cl.movevars_warsowbunny_turnaccel && accelerating && s->cmd.sidemove == 0 && s->cmd.forwardmove != 0)
1461 else
1463
1466 }
1469 s->velocity[2] -= gravity * 0.5f;
1470 else
1471 s->velocity[2] -= gravity;
1474 {
1476 s->velocity[2] -= gravity * 0.5f;
1477 }
1478 }
1479}
1480
1482{
1483 //Con_Printf(" %f", frametime);
1484 if (!s->cmd.jump)
1485 s->cmd.canjump = true;
1486 s->waterjumptime -= s->cmd.frametime;
1490 else
1492}
1493
1494extern cvar_t host_timescale;
1496{
1498 {
1499 cl.moveflags = 0;
1500 }
1501 else if (cl.stats[STAT_MOVEVARS_TICRATE])
1502 {
1537 }
1538 else
1539 {
1540 cl.moveflags = 0;
1541 cl.movevars_ticrate = 0; // bones_was_here: no guessing, unavailable ticrate triggers better fallbacks
1574 }
1575
1576 if(!(cl.moveflags & MOVEFLAG_VALID))
1577 {
1578 if(gamemode == GAME_NEXUIZ) // Legacy hack to work with old servers of Nexuiz.
1580 }
1581
1583 cl.movevars_aircontrol_power = 2; // CPMA default
1584}
1585
1587{
1588 // if a move is more than 50ms, do it as two moves (matching qwsv)
1589 //Con_Printf("%i ", s.cmd.msec);
1590 if(s->cmd.frametime > 0.0005)
1591 {
1592 if (s->cmd.frametime > 0.05)
1593 {
1594 s->cmd.frametime /= 2;
1596 }
1598 }
1599 else
1600 {
1601 // we REALLY need this handling to happen, even if the move is not executed
1602 if (!s->cmd.jump)
1603 s->cmd.canjump = true;
1604 }
1605}
1606
1608{
1609 int i;
1610 double totalmovemsec;
1612
1614
1616 return;
1617
1619 return;
1620
1621 // set up starting state for the series of moves
1622 memset(&s, 0, sizeof(s));
1625 s.crouched = true; // will be updated on first move
1626 //Con_Printf("movement replay starting org %f %f %f vel %f %f %f\n", s.origin[0], s.origin[1], s.origin[2], s.velocity[0], s.velocity[1], s.velocity[2]);
1627
1628 totalmovemsec = 0;
1629 for (i = 0;i < CL_MAX_USERCMDS;i++)
1631 totalmovemsec += cl.movecmd[i].msec;
1633 //Con_Printf("%i = %.0f >= %.0f && %u && (%i && %i && %i == %i && %i > 0 && %i\n", cl.movement_predicted, totalmovemsec, cl_movement_minping.value, cls.servermovesequence, cl_movement.integer, !cls.demoplayback, cls.signon, SIGNONS, cl.stats[STAT_HEALTH], !cl.intermission);
1635 {
1636 //Con_Printf("%ims\n", cl.movecmd[0].msec);
1637
1638 // replay the input queue to predict current location
1639 // note: this relies on the fact there's always one queue item at the end
1640
1641 // find how many are still valid
1642 for (i = 0;i < CL_MAX_USERCMDS;i++)
1644 break;
1645 // now walk them in oldest to newest order
1646 for (i--;i >= 0;i--)
1647 {
1648 s.cmd = cl.movecmd[i];
1649 if (i < CL_MAX_USERCMDS - 1)
1650 s.cmd.canjump = cl.movecmd[i+1].canjump;
1651
1653
1655 }
1656 //Con_Printf("\n");
1658 }
1659 else
1660 {
1661 // get the first movement queue entry to know whether to crouch and such
1662 s.cmd = cl.movecmd[0];
1663 }
1664
1665 if (!cls.demoplayback) // for bob, speedometer
1666 {
1667 cl.movement_replay = false;
1668 // update the interpolation target position and velocity
1671 }
1672
1673 // update the onground flag if appropriate
1675 {
1676 // when predicted we simply set the flag according to the UpdateStatus
1677 cl.onground = s.onground;
1678 }
1679 else
1680 {
1681 // when not predicted, cl.onground is cleared by cl_parse.c each time
1682 // an update packet is received, but can be forced on here to hide
1683 // server inconsistencies in the onground flag
1684 // (which mostly occur when stepping up stairs at very high framerates
1685 // where after the step up the move continues forward and not
1686 // downward so the ground is not detected)
1687 //
1688 // such onground inconsistencies can cause jittery gun bobbing and
1689 // stair smoothing, so we set onground if UpdateStatus says so
1690 if (s.onground)
1691 cl.onground = true;
1692 }
1693}
1694
1696{
1697 int bits;
1698
1699 bits = 0;
1700 if (to->viewangles[0] != from->viewangles[0])
1701 bits |= QW_CM_ANGLE1;
1702 if (to->viewangles[1] != from->viewangles[1])
1703 bits |= QW_CM_ANGLE2;
1704 if (to->viewangles[2] != from->viewangles[2])
1705 bits |= QW_CM_ANGLE3;
1706 if (to->forwardmove != from->forwardmove)
1707 bits |= QW_CM_FORWARD;
1708 if (to->sidemove != from->sidemove)
1709 bits |= QW_CM_SIDE;
1710 if (to->upmove != from->upmove)
1711 bits |= QW_CM_UP;
1712 if (to->buttons != from->buttons)
1713 bits |= QW_CM_BUTTONS;
1714 if (to->impulse != from->impulse)
1715 bits |= QW_CM_IMPULSE;
1716
1717 MSG_WriteByte(buf, bits);
1718 if (bits & QW_CM_ANGLE1)
1720 if (bits & QW_CM_ANGLE2)
1722 if (bits & QW_CM_ANGLE3)
1724 if (bits & QW_CM_FORWARD)
1725 MSG_WriteShort(buf, (short) to->forwardmove);
1726 if (bits & QW_CM_SIDE)
1727 MSG_WriteShort(buf, (short) to->sidemove);
1728 if (bits & QW_CM_UP)
1729 MSG_WriteShort(buf, (short) to->upmove);
1730 if (bits & QW_CM_BUTTONS)
1732 if (bits & QW_CM_IMPULSE)
1734 MSG_WriteByte(buf, to->msec);
1735}
1736
1745
1747{
1748 // rotate viewangles in all previous moves
1749 vec3_t v;
1750 vec3_t f, r, u;
1751 int i;
1752 for (i = 0;i < CL_MAX_USERCMDS;i++)
1753 {
1755 {
1756 usercmd_t *c = &cl.movecmd[i];
1757 AngleVectors(c->viewangles, f, r, u);
1759 Matrix4x4_Transform(m, u, v); VectorCopy(v, u);
1760 AnglesFromVectors(c->viewangles, f, u, false);
1761 }
1762 }
1763}
1764
1765/*
1766==============
1767CL_SendMove
1768==============
1769*/
1770usercmd_t nullcmd; // for delta compression of qw moves
1771void CL_SendMove(void)
1772{
1773 int i, j, packetloss;
1774 int checksumindex;
1775 int bits;
1776 int maxusercmds;
1777 usercmd_t *cmd;
1778 sizebuf_t buf;
1779 unsigned char data[1024];
1780 float packettime, lag;
1781 qbool opportune_moment;
1782 qbool quemove;
1783 qbool important;
1784
1785 // if playing a demo, do nothing
1786 if (!cls.netcon)
1787 return;
1788
1789 // we don't que moves during a lag spike (potential network timeout)
1791
1792 // we build up cl.cmd and then decide whether to send or not
1793 // we store this into cl.movecmd[0] for prediction each frame even if we
1794 // do not send, to make sure that prediction is instant
1795 cl.cmd.time = cl.time;
1797
1798 // set button bits
1799 // LadyHavoc: added 6 new buttons and use and chat buttons, and prydon cursor active button
1800 bits = 0;
1801 if (in_attack.state & 3) bits |= 1;
1802 if (in_jump.state & 3) bits |= 2;
1803 if (in_button3.state & 3) bits |= 4;
1804 if (in_button4.state & 3) bits |= 8;
1805 if (in_button5.state & 3) bits |= 16;
1806 if (in_button6.state & 3) bits |= 32;
1807 if (in_button7.state & 3) bits |= 64;
1808 if (in_button8.state & 3) bits |= 128;
1809 if (in_use.state & 3) bits |= 256;
1810 if (key_dest != key_game || key_consoleactive || !vid_activewindow) bits |= 512;
1811 if (cl_prydoncursor.integer > 0) bits |= 1024;
1812 if (in_button9.state & 3) bits |= 2048;
1813 if (in_button10.state & 3) bits |= 4096;
1814 if (in_button11.state & 3) bits |= 8192;
1815 if (in_button12.state & 3) bits |= 16384;
1816 if (in_button13.state & 3) bits |= 32768;
1817 if (in_button14.state & 3) bits |= 65536;
1818 if (in_button15.state & 3) bits |= 131072;
1819 if (in_button16.state & 3) bits |= 262144;
1820 // button bits 19-31 unused currently
1821 // rotate/zoom view serverside if PRYDON_CLIENTCURSOR cursor is at edge of screen
1822 if(cl_prydoncursor.integer > 0)
1823 {
1824 if (cl.cmd.cursor_screen[0] <= -1) bits |= 8;
1825 if (cl.cmd.cursor_screen[0] >= 1) bits |= 16;
1826 if (cl.cmd.cursor_screen[1] <= -1) bits |= 32;
1827 if (cl.cmd.cursor_screen[1] >= 1) bits |= 64;
1828 }
1829
1830 // set buttons and impulse
1831 cl.cmd.buttons = bits;
1833
1834 // set viewangles
1836
1837 // bones_was_here: previously cl.cmd.frametime was floored to nearest millisec
1838 // this meant the smoothest async movement required integer millisec
1839 // client and server frame times (eg 125fps)
1840 cl.cmd.frametime = bound(0.0, cl.cmd.time - cl.movecmd[1].time, 0.255);
1841 // ridiculous value rejection (matches qw)
1842 if (cl.cmd.frametime > 0.25)
1843 cl.cmd.frametime = 0.1;
1844 cl.cmd.msec = (unsigned char)floor(cl.cmd.frametime * 1000);
1845
1846 switch(cls.protocol)
1847 {
1849 // quakeworld uses a different cvar with opposite meaning, for compatibility
1851 break;
1856 break;
1857 default:
1858 cl.cmd.predicted = false;
1859 break;
1860 }
1861
1862 // movement is set by input code (forwardmove/sidemove/upmove)
1863 // always dump the first two moves, because they may contain leftover inputs from the last level
1864 if (cl.cmd.sequence <= 2)
1866
1867 cl.cmd.jump = (cl.cmd.buttons & 2) != 0;
1868 cl.cmd.crouch = 0;
1869 switch (cls.protocol)
1870 {
1872 case PROTOCOL_QUAKE:
1873 case PROTOCOL_QUAKEDP:
1883 break;
1887 // FIXME: cl.cmd.buttons & 16 is +button5, Nexuiz/Xonotic specific
1888 cl.cmd.crouch = (cl.cmd.buttons & 16) != 0;
1889 break;
1890 case PROTOCOL_UNKNOWN:
1891 break;
1892 }
1893
1894 if (quemove)
1895 cl.movecmd[0] = cl.cmd;
1896
1897 /* Accumulating cl.realframetime to prevent low packet rates,
1898 * previously with cl_maxfps == cl_netfps it did not send every frame because
1899 * host.realtime - cl.lastpackettime was often well below (or above) cl_packetinterval.
1900 */
1902
1903 // don't predict more than 256fps
1904 if (cl.timesincepacket >= 1/256)
1905 cl.movement_replay = true; // redo the prediction
1906
1907 // now decide whether to actually send this move
1908 // (otherwise it is only for prediction)
1909
1910 // do not send 0ms packets because they mess up physics
1911 // DP servers discard (treat like lost) predicted moves shorter than 0.0005s
1912 // the time advancing check must be unaffected by time sync as it may have caused the short move
1913 if(cl.cmd.msec == 0 && cl.mtime[0] > cl.mtime[1] && (cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon == SIGNONS))
1914 return;
1915
1916 // don't send too often or else network connections can get clogged by a
1917 // high renderer framerate
1918 packettime = 1.0f / bound(10.0f, cl_netfps.value, 1000.0f);
1919 if (cl.movevars_ticrate)
1920 packettime = bound(cl.movevars_ticrate * 0.5f, packettime, cl.movevars_ticrate);
1921
1922 // always send if buttons changed or an impulse is pending
1923 // even if it violates the rate limit!
1925
1926 // improve and stabilise ping by synchronising with the server
1927 lag = cl.mtime[0] - cl.cmd.time;
1928 // unknown ticrate || PL or ping spike || loading
1929 if (!cl.movevars_ticrate || lag > cl.movevars_ticrate || lag < 0)
1930 opportune_moment = false;
1931 else // sync should be possible
1932 {
1933 float frames_per_tic = cl.movevars_ticrate / cl.realframetime;
1934 opportune_moment = lag < 0.999f * (float)cl.realframetime * (frames_per_tic <= 1 ? 1 : sqrtf(frames_per_tic));
1935 }
1936
1937 // don't send too often (cl_netfps)
1938 if (!important && cl.timesincepacket < packettime * 0.999f
1939 && (!opportune_moment || cl.opt_inputs_since_update))
1940 {
1941// Con_Printf("^1moveft %f realft %f lag %f tic %f inputsince %d opp %d\n", cl.cmd.frametime, cl.realframetime, lag, cl.movevars_ticrate, cl.opt_inputs_since_update, opportune_moment);
1942 return;
1943 }
1944
1945 // don't choke the connection with packets (obey rate limit)
1946 // it is important that this check be last, because it adds a new
1947 // frame to the shownetgraph output and any cancelation after this
1948 // will produce a nasty spike-like look to the netgraph
1949 // we also still send if it is important
1950 if (!NetConn_CanSend(cls.netcon) && !important)
1951 return;
1952
1953// Con_Printf("%smoveft %f realft %f lag %f tic %f inputsince %d opp %d import %d\n", (lag < 0.0005 || !opportune_moment) ? "^3" : "^2", cl.cmd.frametime, cl.realframetime, lag, cl.movevars_ticrate, cl.opt_inputs_since_update, opportune_moment, important);
1954
1955 if (opportune_moment)
1957 cl.timesincepacket = 0;
1958
1959 buf.maxsize = sizeof(data);
1960 buf.cursize = 0;
1961 buf.data = data;
1962
1963 // send the movement message
1964 // PROTOCOL_QUAKE clc_move = 16 bytes total
1965 // PROTOCOL_QUAKEDP clc_move = 16 bytes total
1966 // PROTOCOL_NEHAHRAMOVIE clc_move = 16 bytes total
1967 // PROTOCOL_DARKPLACES1 clc_move = 19 bytes total
1968 // PROTOCOL_DARKPLACES2 clc_move = 25 bytes total
1969 // PROTOCOL_DARKPLACES3 clc_move = 25 bytes total
1970 // PROTOCOL_DARKPLACES4 clc_move = 19 bytes total
1971 // PROTOCOL_DARKPLACES5 clc_move = 19 bytes total
1972 // PROTOCOL_DARKPLACES6 clc_move = 52 bytes total
1973 // PROTOCOL_DARKPLACES7 clc_move = 56 bytes total per move (can be up to 16 moves)
1974 // PROTOCOL_DARKPLACES8 clc_move = 56 bytes total per move (can be up to 16 moves)
1975 // PROTOCOL_QUAKEWORLD clc_move = 34 bytes total (typically, but can reach 43 bytes, or even 49 bytes with roll)
1976
1977 // set prydon cursor info
1979
1981 {
1982 switch (cls.protocol)
1983 {
1986 // save the position for a checksum byte
1987 checksumindex = buf.cursize;
1988 MSG_WriteByte(&buf, 0);
1989 // packet loss percentage
1990 for (j = 0, packetloss = 0;j < NETGRAPH_PACKETS;j++)
1992 packetloss++;
1993 packetloss = packetloss * 100 / NETGRAPH_PACKETS;
1994 MSG_WriteByte(&buf, packetloss);
1995 // write most recent 3 moves
1999 // calculate the checksum
2000 buf.data[checksumindex] = COM_BlockSequenceCRCByteQW(buf.data + checksumindex + 1, buf.cursize - checksumindex - 1, cls.netcon->outgoing_unreliable_sequence);
2001 // if delta compression history overflows, request no delta
2003 cl.qw_validsequence = 0;
2004 // request delta compression if appropriate
2006 {
2010 }
2011 else
2013 break;
2014 case PROTOCOL_QUAKE:
2015 case PROTOCOL_QUAKEDP:
2020 // 5 bytes
2022 MSG_WriteFloat (&buf, cl.cmd.time); // last server packet time
2023 // 3 bytes (6 bytes in proquake)
2024 if (cls.proquake_servermod == 1) // MOD_PROQUAKE
2025 {
2026 for (i = 0;i < 3;i++)
2028 }
2029 else
2030 {
2031 for (i = 0;i < 3;i++)
2033 }
2034 // 6 bytes
2038 // 2 bytes
2041 break;
2044 // 5 bytes
2046 MSG_WriteFloat (&buf, cl.cmd.time); // last server packet time
2047 // 12 bytes
2048 for (i = 0;i < 3;i++)
2050 // 6 bytes
2054 // 2 bytes
2057 break;
2061 // 5 bytes
2063 MSG_WriteFloat (&buf, cl.cmd.time); // last server packet time
2064 // 6 bytes
2065 for (i = 0;i < 3;i++)
2067 // 6 bytes
2071 // 2 bytes
2077 // set the maxusercmds variable to limit how many should be sent
2078 maxusercmds = bound(1, cl_netrepeatinput.integer + 1, min(3, CL_MAX_USERCMDS));
2079 // when movement prediction is off, there's not much point in repeating old input as it will just be ignored
2080 if (!cl.cmd.predicted)
2081 maxusercmds = 1;
2082
2083 // send the latest moves in order, the old ones will be
2084 // ignored by the server harmlessly, however if the previous
2085 // packets were lost these moves will be used
2086 //
2087 // this reduces packet loss impact on gameplay.
2088 for (j = 0, cmd = &cl.movecmd[maxusercmds-1];j < maxusercmds;j++, cmd--)
2089 {
2090 // don't repeat any stale moves
2091 if (cmd->sequence && cmd->sequence < cls.servermovesequence)
2092 continue;
2093 // 5/9 bytes
2096 MSG_WriteLong (&buf, cmd->predicted ? cmd->sequence : 0);
2097 MSG_WriteFloat (&buf, cmd->time); // last server packet time
2098 // 6 bytes
2099 for (i = 0;i < 3;i++)
2100 MSG_WriteAngle16i (&buf, cmd->viewangles[i]);
2101 // 6 bytes
2102 MSG_WriteCoord16i (&buf, cmd->forwardmove);
2103 MSG_WriteCoord16i (&buf, cmd->sidemove);
2104 MSG_WriteCoord16i (&buf, cmd->upmove);
2105 // 5 bytes
2106 MSG_WriteLong (&buf, cmd->buttons);
2107 MSG_WriteByte (&buf, cmd->impulse);
2108 // PRYDON_CLIENTCURSOR
2109 // 30 bytes
2110 MSG_WriteShort (&buf, (short)(cmd->cursor_screen[0] * 32767.0f));
2111 MSG_WriteShort (&buf, (short)(cmd->cursor_screen[1] * 32767.0f));
2112 MSG_WriteFloat (&buf, cmd->cursor_start[0]);
2113 MSG_WriteFloat (&buf, cmd->cursor_start[1]);
2114 MSG_WriteFloat (&buf, cmd->cursor_start[2]);
2115 MSG_WriteFloat (&buf, cmd->cursor_impact[0]);
2116 MSG_WriteFloat (&buf, cmd->cursor_impact[1]);
2117 MSG_WriteFloat (&buf, cmd->cursor_impact[2]);
2118 MSG_WriteShort (&buf, cmd->cursor_entitynumber);
2119 }
2120 break;
2121 case PROTOCOL_UNKNOWN:
2122 break;
2123 }
2124 }
2125
2126 if (cls.protocol != PROTOCOL_QUAKEWORLD && buf.cursize)
2127 {
2128 // ack entity frame numbers received since the last input was sent
2129 // (redundent to improve handling of client->server packet loss)
2130 // if cl_netrepeatinput is 1 and client framerate matches server
2131 // framerate, this is 10 bytes, if client framerate is lower this
2132 // will be more...
2133 unsigned int oldsequence = cl.cmd.sequence;
2134 unsigned int delta = bound(1, cl_netrepeatinput.integer + 1, 3);
2135 if (oldsequence > delta)
2136 oldsequence = oldsequence - delta;
2137 else
2138 oldsequence = 1;
2139 for (i = 0;i < LATESTFRAMENUMS;i++)
2140 {
2142 if (cl.latestsendnums[j] >= oldsequence)
2143 {
2145 Con_Printf("send clc_ackframe %i\n", cl.latestframenums[j]);
2148 }
2149 }
2150 }
2151
2152 // PROTOCOL_DARKPLACES6 = 67 bytes per packet
2153 // PROTOCOL_DARKPLACES7 = 71 bytes per packet
2154
2155 // acknowledge any recently received data blocks
2157 {
2162 cls.dp_downloadack[i].size = 0;
2163 }
2164
2165 // send the reliable message (forwarded commands) if there is one
2166 if (buf.cursize || cls.netcon->message.cursize)
2168
2169 if (quemove)
2170 {
2171 // update the cl.movecmd array which holds the most recent moves,
2172 // because we now need a new slot for the next input
2173 for (i = CL_MAX_USERCMDS - 1;i >= 1;i--)
2174 cl.movecmd[i] = cl.movecmd[i-1];
2175 cl.movecmd[0].msec = 0;
2176 cl.movecmd[0].frametime = 0;
2177 }
2178
2179 // clear button 'click' states
2180 in_attack.state &= ~2;
2181 in_jump.state &= ~2;
2182 in_button3.state &= ~2;
2183 in_button4.state &= ~2;
2184 in_button5.state &= ~2;
2185 in_button6.state &= ~2;
2186 in_button7.state &= ~2;
2187 in_button8.state &= ~2;
2188 in_use.state &= ~2;
2189 in_button9.state &= ~2;
2190 in_button10.state &= ~2;
2191 in_button11.state &= ~2;
2192 in_button12.state &= ~2;
2193 in_button13.state &= ~2;
2194 in_button14.state &= ~2;
2195 in_button15.state &= ~2;
2196 in_button16.state &= ~2;
2197 // clear impulse
2198 in_impulse = 0;
2199
2201 CL_DisconnectEx(true, "Lost connection to server");
2202}
2203
2204/*
2205============
2206CL_InitInput
2207============
2208*/
2209void CL_InitInput (void)
2210{
2211 Cmd_AddCommand(CF_CLIENT, "+moveup",IN_UpDown, "swim upward");
2212 Cmd_AddCommand(CF_CLIENT, "-moveup",IN_UpUp, "stop swimming upward");
2213 Cmd_AddCommand(CF_CLIENT, "+movedown",IN_DownDown, "swim downward");
2214 Cmd_AddCommand(CF_CLIENT, "-movedown",IN_DownUp, "stop swimming downward");
2215 Cmd_AddCommand(CF_CLIENT, "+left",IN_LeftDown, "turn left");
2216 Cmd_AddCommand(CF_CLIENT, "-left",IN_LeftUp, "stop turning left");
2217 Cmd_AddCommand(CF_CLIENT, "+right",IN_RightDown, "turn right");
2218 Cmd_AddCommand(CF_CLIENT, "-right",IN_RightUp, "stop turning right");
2219 Cmd_AddCommand(CF_CLIENT, "+forward",IN_ForwardDown, "move forward");
2220 Cmd_AddCommand(CF_CLIENT, "-forward",IN_ForwardUp, "stop moving forward");
2221 Cmd_AddCommand(CF_CLIENT, "+back",IN_BackDown, "move backward");
2222 Cmd_AddCommand(CF_CLIENT, "-back",IN_BackUp, "stop moving backward");
2223 Cmd_AddCommand(CF_CLIENT, "+lookup", IN_LookupDown, "look upward");
2224 Cmd_AddCommand(CF_CLIENT, "-lookup", IN_LookupUp, "stop looking upward");
2225 Cmd_AddCommand(CF_CLIENT, "+lookdown", IN_LookdownDown, "look downward");
2226 Cmd_AddCommand(CF_CLIENT, "-lookdown", IN_LookdownUp, "stop looking downward");
2227 Cmd_AddCommand(CF_CLIENT, "+strafe", IN_StrafeDown, "activate strafing mode (move instead of turn)");
2228 Cmd_AddCommand(CF_CLIENT, "-strafe", IN_StrafeUp, "deactivate strafing mode");
2229 Cmd_AddCommand(CF_CLIENT, "+moveleft", IN_MoveleftDown, "strafe left");
2230 Cmd_AddCommand(CF_CLIENT, "-moveleft", IN_MoveleftUp, "stop strafing left");
2231 Cmd_AddCommand(CF_CLIENT, "+moveright", IN_MoverightDown, "strafe right");
2232 Cmd_AddCommand(CF_CLIENT, "-moveright", IN_MoverightUp, "stop strafing right");
2233 Cmd_AddCommand(CF_CLIENT, "+speed", IN_SpeedDown, "activate run mode (faster movement and turning)");
2234 Cmd_AddCommand(CF_CLIENT, "-speed", IN_SpeedUp, "deactivate run mode");
2235 Cmd_AddCommand(CF_CLIENT, "+attack", IN_AttackDown, "begin firing");
2236 Cmd_AddCommand(CF_CLIENT, "-attack", IN_AttackUp, "stop firing");
2237 Cmd_AddCommand(CF_CLIENT, "+jump", IN_JumpDown, "jump");
2238 Cmd_AddCommand(CF_CLIENT, "-jump", IN_JumpUp, "end jump (so you can jump again)");
2239 Cmd_AddCommand(CF_CLIENT, "impulse", IN_Impulse, "send an impulse number to server (select weapon, use item, etc)");
2240 Cmd_AddCommand(CF_CLIENT, "+klook", IN_KLookDown, "activate keyboard looking mode, do not recenter view");
2241 Cmd_AddCommand(CF_CLIENT, "-klook", IN_KLookUp, "deactivate keyboard looking mode");
2242 Cmd_AddCommand(CF_CLIENT, "+mlook", IN_MLookDown, "activate mouse looking mode, do not recenter view");
2243 Cmd_AddCommand(CF_CLIENT, "-mlook", IN_MLookUp, "deactivate mouse looking mode");
2244
2245 // LadyHavoc: added lots of buttons
2246 Cmd_AddCommand(CF_CLIENT, "+use", IN_UseDown, "use something (may be used by some mods)");
2247 Cmd_AddCommand(CF_CLIENT, "-use", IN_UseUp, "stop using something");
2248 Cmd_AddCommand(CF_CLIENT, "+button3", IN_Button3Down, "activate button3 (behavior depends on mod)");
2249 Cmd_AddCommand(CF_CLIENT, "-button3", IN_Button3Up, "deactivate button3");
2250 Cmd_AddCommand(CF_CLIENT, "+button4", IN_Button4Down, "activate button4 (behavior depends on mod)");
2251 Cmd_AddCommand(CF_CLIENT, "-button4", IN_Button4Up, "deactivate button4");
2252 Cmd_AddCommand(CF_CLIENT, "+button5", IN_Button5Down, "activate button5 (behavior depends on mod)");
2253 Cmd_AddCommand(CF_CLIENT, "-button5", IN_Button5Up, "deactivate button5");
2254 Cmd_AddCommand(CF_CLIENT, "+button6", IN_Button6Down, "activate button6 (behavior depends on mod)");
2255 Cmd_AddCommand(CF_CLIENT, "-button6", IN_Button6Up, "deactivate button6");
2256 Cmd_AddCommand(CF_CLIENT, "+button7", IN_Button7Down, "activate button7 (behavior depends on mod)");
2257 Cmd_AddCommand(CF_CLIENT, "-button7", IN_Button7Up, "deactivate button7");
2258 Cmd_AddCommand(CF_CLIENT, "+button8", IN_Button8Down, "activate button8 (behavior depends on mod)");
2259 Cmd_AddCommand(CF_CLIENT, "-button8", IN_Button8Up, "deactivate button8");
2260 Cmd_AddCommand(CF_CLIENT, "+button9", IN_Button9Down, "activate button9 (behavior depends on mod)");
2261 Cmd_AddCommand(CF_CLIENT, "-button9", IN_Button9Up, "deactivate button9");
2262 Cmd_AddCommand(CF_CLIENT, "+button10", IN_Button10Down, "activate button10 (behavior depends on mod)");
2263 Cmd_AddCommand(CF_CLIENT, "-button10", IN_Button10Up, "deactivate button10");
2264 Cmd_AddCommand(CF_CLIENT, "+button11", IN_Button11Down, "activate button11 (behavior depends on mod)");
2265 Cmd_AddCommand(CF_CLIENT, "-button11", IN_Button11Up, "deactivate button11");
2266 Cmd_AddCommand(CF_CLIENT, "+button12", IN_Button12Down, "activate button12 (behavior depends on mod)");
2267 Cmd_AddCommand(CF_CLIENT, "-button12", IN_Button12Up, "deactivate button12");
2268 Cmd_AddCommand(CF_CLIENT, "+button13", IN_Button13Down, "activate button13 (behavior depends on mod)");
2269 Cmd_AddCommand(CF_CLIENT, "-button13", IN_Button13Up, "deactivate button13");
2270 Cmd_AddCommand(CF_CLIENT, "+button14", IN_Button14Down, "activate button14 (behavior depends on mod)");
2271 Cmd_AddCommand(CF_CLIENT, "-button14", IN_Button14Up, "deactivate button14");
2272 Cmd_AddCommand(CF_CLIENT, "+button15", IN_Button15Down, "activate button15 (behavior depends on mod)");
2273 Cmd_AddCommand(CF_CLIENT, "-button15", IN_Button15Up, "deactivate button15");
2274 Cmd_AddCommand(CF_CLIENT, "+button16", IN_Button16Down, "activate button16 (behavior depends on mod)");
2275 Cmd_AddCommand(CF_CLIENT, "-button16", IN_Button16Up, "deactivate button16");
2276
2277 // LadyHavoc: added bestweapon command
2278 Cmd_AddCommand(CF_CLIENT, "bestweapon", IN_BestWeapon_f, "send an impulse number to server to select the first usable weapon out of several (example: 8 7 6 5 4 3 2 1)");
2279 Cmd_AddCommand(CF_CLIENT, "register_bestweapon", IN_BestWeapon_Register_f, "(for QC usage only) change weapon parameters to be used by bestweapon; stuffcmd this in ClientConnect");
2280
2302
2317
2321
2323
2325}
2326
#define SUPERCONTENTS_BODY
Definition bspfile.h:201
#define SUPERCONTENTS_LAVA
Definition bspfile.h:199
#define SUPERCONTENTS_SLIME
Definition bspfile.h:198
#define SUPERCONTENTS_SOLID
Definition bspfile.h:196
#define SUPERCONTENTS_LIQUIDSMASK
Definition bspfile.h:218
#define SUPERCONTENTS_PLAYERCLIP
Definition bspfile.h:204
cvar_t cl_rate_burstsize
Definition cl_cmd.c:34
cvar_t cl_rate
Definition cl_cmd.c:33
trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend, qbool hitnetworkbrushmodels, qbool hitnetworkplayers, int *hitnetworkentity, qbool hitcsqcentities, qbool hitsurfaces)
trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend, qbool hitnetworkbrushmodels, qbool hitnetworkplayers, int *hitnetworkentity, qbool hitcsqcentities)
trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, qbool hitnetworkbrushmodels, qbool hitnetworkplayers, int *hitnetworkentity, qbool hitcsqcentities)
float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent)
Definition cl_collision.c:5
static vec_t CL_IsMoveInDirection(vec_t forward, vec_t side, vec_t angle)
Definition cl_input.c:1112
cvar_t cl_yawspeed
Definition cl_input.c:372
cvar_t cl_csqc_generatemousemoveevents
Definition cl_input.c:420
static void IN_Button3Down(cmd_state_t *cmd)
Definition cl_input.c:166
static void IN_Button7Down(cmd_state_t *cmd)
Definition cl_input.c:174
kbutton_t in_right
Definition cl_input.c:52
static void IN_Button12Down(cmd_state_t *cmd)
Definition cl_input.c:185
static void IN_Button10Up(cmd_state_t *cmd)
Definition cl_input.c:182
cvar_t cl_backspeed
Definition cl_input.c:366
cvar_t cl_movement_edgefriction
Definition cl_input.c:388
cvar_t cl_movement_stopspeed
Definition cl_input.c:384
cvar_t cl_sidespeed
Definition cl_input.c:367
kbutton_t in_button3
Definition cl_input.c:57
static void IN_JumpDown(cmd_state_t *cmd)
Definition cl_input.c:196
kbutton_t in_lookdown
Definition cl_input.c:53
static void IN_Button8Down(cmd_state_t *cmd)
Definition cl_input.c:176
static void CL_ClientMovement_Physics_PM_AirAccelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed)
Definition cl_input.c:1267
kbutton_t in_klook
Definition cl_input.c:51
static void IN_LeftDown(cmd_state_t *cmd)
Definition cl_input.c:137
static void CL_ClientMovement_Physics_CPM_PM_Aircontrol(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed)
Definition cl_input.c:1144
static qbool CL_ClientMovement_Unstick(cl_clientmovement_state_t *s)
Definition cl_input.c:861
static void IN_Button6Up(cmd_state_t *cmd)
Definition cl_input.c:173
void CL_Input(void)
Definition cl_input.c:483
static void IN_Button15Up(cmd_state_t *cmd)
Definition cl_input.c:192
static void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
Definition cl_input.c:1020
static void IN_AttackUp(cmd_state_t *cmd)
Definition cl_input.c:160
cvar_t cl_movement_minping
Definition cl_input.c:380
int in_impulse
Definition cl_input.c:61
static void IN_ForwardDown(cmd_state_t *cmd)
Definition cl_input.c:141
cvar_t cl_pitchspeed
Definition cl_input.c:373
kbutton_t in_button11
Definition cl_input.c:59
cvar_t cl_movement_nettimeout
Definition cl_input.c:379
cvar_t cl_netrepeatinput
Definition cl_input.c:415
static void IN_Impulse(cmd_state_t *cmd)
Definition cl_input.c:199
static void IN_MoveleftUp(cmd_state_t *cmd)
Definition cl_input.c:150
cvar_t cl_movement_replay
Definition cl_input.c:378
kbutton_t in_button15
Definition cl_input.c:59
cvar_t cl_movement_accelerate
Definition cl_input.c:390
static void IN_SpeedDown(cmd_state_t *cmd)
Definition cl_input.c:154
static void CL_ClientMovement_PlayerMove(cl_clientmovement_state_t *s)
Definition cl_input.c:1481
cvar_t cl_upspeed
Definition cl_input.c:364
static void KeyDown(cmd_state_t *cmd, kbutton_t *b)
Definition cl_input.c:65
kbutton_t in_button6
Definition cl_input.c:57
cvar_t v_flipped
Definition gl_backend.c:20
static void IN_Button10Down(cmd_state_t *cmd)
Definition cl_input.c:181
cvar_t m_accelerate
Definition cl_input.c:402
kbutton_t in_forward
Definition cl_input.c:52
static void CL_AdjustAngles(void)
Definition cl_input.c:431
cvar_t cl_movement_maxspeed
Definition cl_input.c:382
cvar_t cl_movement
Definition cl_input.c:377
static void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t stretchfactor, vec_t sidefric, vec_t speedlimit)
Definition cl_input.c:1187
void IN_BestWeapon_ResetData(void)
call before each map so QC can start from a clean state
Definition cl_input.c:226
static void IN_UpUp(cmd_state_t *cmd)
Definition cl_input.c:134
static void IN_Button14Up(cmd_state_t *cmd)
Definition cl_input.c:190
static void IN_Button13Up(cmd_state_t *cmd)
Definition cl_input.c:188
static void IN_Button3Up(cmd_state_t *cmd)
Definition cl_input.c:167
static void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
Definition cl_input.c:878
static void IN_UseUp(cmd_state_t *cmd)
Definition cl_input.c:163
void CL_ClientMovement_Replay(void)
Definition cl_input.c:1607
static void IN_MoverightUp(cmd_state_t *cmd)
Definition cl_input.c:152
kbutton_t in_button7
Definition cl_input.c:57
static void IN_KLookDown(cmd_state_t *cmd)
Definition cl_input.c:124
static void IN_Button15Down(cmd_state_t *cmd)
Definition cl_input.c:191
void CL_NewFrameReceived(int num)
Definition cl_input.c:1737
static void CL_ClientMovement_Physics_CheckJump(cl_clientmovement_state_t *s)
Definition cl_input.c:1318
void CL_RotateMoves(const matrix4x4_t *m)
Definition cl_input.c:1746
static void IN_LeftUp(cmd_state_t *cmd)
Definition cl_input.c:138
static void IN_StrafeDown(cmd_state_t *cmd)
Definition cl_input.c:156
int cl_ignoremousemoves
Definition cl_input.c:474
cvar_t cl_movement_wateraccelerate
Definition cl_input.c:392
static void IN_Button9Up(cmd_state_t *cmd)
Definition cl_input.c:180
#define NUMOFFSETS
Definition cl_input.c:837
cvar_t m_accelerate_maxspeed
Definition cl_input.c:404
static void IN_KLookUp(cmd_state_t *cmd)
Definition cl_input.c:125
static void IN_AttackDown(cmd_state_t *cmd)
Definition cl_input.c:159
void CL_InitInput(void)
Definition cl_input.c:2209
kbutton_t in_button13
Definition cl_input.c:59
kbutton_t in_button5
Definition cl_input.c:57
static void IN_SpeedUp(cmd_state_t *cmd)
Definition cl_input.c:155
kbutton_t in_speed
Definition cl_input.c:54
static void IN_Button12Up(cmd_state_t *cmd)
Definition cl_input.c:186
static void IN_UseDown(cmd_state_t *cmd)
Definition cl_input.c:162
cvar_t m_accelerate_power_offset
Definition cl_input.c:406
cvar_t m_accelerate_power_strength
Definition cl_input.c:409
kbutton_t in_strafe
Definition cl_input.c:54
cvar_t cl_movement_waterfriction
Definition cl_input.c:387
cvar_t cl_movement_jumpvelocity
Definition cl_input.c:393
kbutton_t in_jump
Definition cl_input.c:54
cvar_t m_accelerate_natural_strength
Definition cl_input.c:410
kbutton_t in_back
Definition cl_input.c:52
kbutton_t in_down
Definition cl_input.c:55
static void IN_Button11Up(cmd_state_t *cmd)
Definition cl_input.c:184
cvar_t m_filter
Definition cl_input.c:401
static void IN_BestWeapon_Register_f(cmd_state_t *cmd)
Definition cl_input.c:244
static void IN_MLookDown(cmd_state_t *cmd)
Definition cl_input.c:126
in_bestweapon_info_t in_bestweapon_info[IN_BESTWEAPON_MAX]
Definition cl_input.c:201
kbutton_t in_button10
Definition cl_input.c:59
cvar_t m_accelerate_natural_offset
Definition cl_input.c:412
static void IN_Button5Up(cmd_state_t *cmd)
Definition cl_input.c:171
kbutton_t in_moveleft
Definition cl_input.c:53
static void IN_LookdownUp(cmd_state_t *cmd)
Definition cl_input.c:148
static void IN_ForwardUp(cmd_state_t *cmd)
Definition cl_input.c:142
static void IN_Button4Up(cmd_state_t *cmd)
Definition cl_input.c:169
void CL_SendMove(void)
Definition cl_input.c:1771
void CL_ClientMovement_PlayerMove_Frame(cl_clientmovement_state_t *s)
Definition cl_input.c:1586
static void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
Definition cl_input.c:1335
cvar_t m_accelerate_power_senscap
Definition cl_input.c:408
static void IN_MoverightDown(cmd_state_t *cmd)
Definition cl_input.c:151
cvar_t cl_anglespeedkey
Definition cl_input.c:375
cvar_t in_pitch_min
Definition cl_input.c:398
kbutton_t in_button4
Definition cl_input.c:57
static vec3_t offsets[NUMOFFSETS]
Definition cl_input.c:838
cvar_t cl_movement_stepheight
Definition cl_input.c:389
cvar_t cl_movement_friction
Definition cl_input.c:385
static void KeyUp(cmd_state_t *cmd, kbutton_t *b)
Definition cl_input.c:94
cvar_t cl_movement_maxairspeed
Definition cl_input.c:383
cvar_t cl_movement_airaccelerate
Definition cl_input.c:391
static void IN_Button13Down(cmd_state_t *cmd)
Definition cl_input.c:187
static vec_t CL_GeomLerp(vec_t a, vec_t lerp, vec_t b)
Definition cl_input.c:1125
static void QW_MSG_WriteDeltaUsercmd(sizebuf_t *buf, usercmd_t *from, usercmd_t *to)
Definition cl_input.c:1695
cvar_t in_pitch_max
Definition cl_input.c:399
cvar_t cl_netfps
Definition cl_input.c:414
static void IN_Button4Down(cmd_state_t *cmd)
Definition cl_input.c:168
cvar_t m_accelerate_minspeed
Definition cl_input.c:403
cvar_t m_accelerate_power
Definition cl_input.c:407
kbutton_t in_button9
Definition cl_input.c:59
static void IN_Button6Down(cmd_state_t *cmd)
Definition cl_input.c:172
static void IN_BackDown(cmd_state_t *cmd)
Definition cl_input.c:143
static void IN_Button9Down(cmd_state_t *cmd)
Definition cl_input.c:179
cvar_t cl_movespeedkey
Definition cl_input.c:369
static void IN_MLookUp(cmd_state_t *cmd)
Definition cl_input.c:127
static void IN_Button16Down(cmd_state_t *cmd)
Definition cl_input.c:193
static void IN_DownDown(cmd_state_t *cmd)
Definition cl_input.c:135
cvar_t cl_nopred
Definition cl_input.c:396
static void IN_UpDown(cmd_state_t *cmd)
Definition cl_input.c:133
static void IN_BestWeapon_Register(const char *name, int impulse, int weaponbit, int activeweaponcode, int ammostat, int ammomin)
Definition cl_input.c:203
cvar_t cl_movement_airaccel_sideways_friction
Definition cl_input.c:395
static void IN_Button8Up(cmd_state_t *cmd)
Definition cl_input.c:177
kbutton_t in_left
Definition cl_input.c:52
usercmd_t nullcmd
Definition cl_input.c:1770
cvar_t host_timescale
Definition sv_main.c:228
kbutton_t in_moveright
Definition cl_input.c:53
static void IN_Button11Down(cmd_state_t *cmd)
Definition cl_input.c:183
static void IN_Button16Up(cmd_state_t *cmd)
Definition cl_input.c:194
static float CL_ClientMovement_Physics_AdjustAirAccelQW(float accelqw, float factor)
Definition cl_input.c:1179
float CL_KeyState(kbutton_t *key)
Definition cl_input.c:315
kbutton_t in_button12
Definition cl_input.c:59
static void CL_UpdatePrydonCursor(void)
Definition cl_input.c:787
static void IN_DownUp(cmd_state_t *cmd)
Definition cl_input.c:136
static void IN_Button5Down(cmd_state_t *cmd)
Definition cl_input.c:170
static void IN_LookdownDown(cmd_state_t *cmd)
Definition cl_input.c:147
cvar_t m_accelerate_filter
Definition cl_input.c:405
cvar_t m_accelerate_natural_accelsenscap
Definition cl_input.c:411
static void IN_Button7Up(cmd_state_t *cmd)
Definition cl_input.c:175
kbutton_t in_button14
Definition cl_input.c:59
kbutton_t in_up
Definition cl_input.c:55
static void CL_ClientMovement_Move(cl_clientmovement_state_t *s)
Definition cl_input.c:954
void CL_UpdateMoveVars(void)
Definition cl_input.c:1495
cvar_t cl_nodelta
Definition cl_input.c:418
static void IN_LookupDown(cmd_state_t *cmd)
Definition cl_input.c:145
cvar_t cl_netimmediatebuttons
Definition cl_input.c:416
static void IN_BestWeapon_f(cmd_state_t *cmd)
Definition cl_input.c:271
kbutton_t in_attack
Definition cl_input.c:54
kbutton_t in_lookup
Definition cl_input.c:53
static void IN_BackUp(cmd_state_t *cmd)
Definition cl_input.c:144
static void IN_JumpUp(cmd_state_t *cmd)
Definition cl_input.c:197
static void IN_MoveleftDown(cmd_state_t *cmd)
Definition cl_input.c:149
static void IN_LookupUp(cmd_state_t *cmd)
Definition cl_input.c:146
static void IN_RightUp(cmd_state_t *cmd)
Definition cl_input.c:140
kbutton_t in_use
Definition cl_input.c:54
kbutton_t in_mlook
Definition cl_input.c:51
static void IN_Button14Down(cmd_state_t *cmd)
Definition cl_input.c:189
cvar_t cl_movement_wallfriction
Definition cl_input.c:386
static void IN_RightDown(cmd_state_t *cmd)
Definition cl_input.c:139
cvar_t cl_movecliptokeyboard
Definition cl_input.c:370
kbutton_t in_button8
Definition cl_input.c:57
cvar_t cl_movement_airaccel_qw
Definition cl_input.c:394
cvar_t cl_forwardspeed
Definition cl_input.c:365
static void IN_StrafeUp(cmd_state_t *cmd)
Definition cl_input.c:157
kbutton_t in_button16
Definition cl_input.c:59
cvar_t cl_movement_track_canjump
Definition cl_input.c:381
void CL_DisconnectEx(qbool kicked, const char *fmt,...)
Definition cl_main.c:370
cvar_t freelook
Definition cl_main.c:60
cvar_t lookspring
Definition cl_main.c:51
cvar_t cl_prydoncursor_notrace
Definition cl_main.c:93
cvar_t m_side
Definition cl_main.c:58
cvar_t m_yaw
Definition cl_main.c:56
cvar_t m_forward
Definition cl_main.c:57
client_state_t cl
Definition cl_main.c:117
cvar_t sensitivity
Definition cl_main.c:53
client_static_t cls
Definition cl_main.c:116
cvar_t cl_prydoncursor
Definition cl_main.c:92
cvar_t m_pitch
Definition cl_main.c:55
cvar_t lookstrafe
Definition cl_main.c:52
cvar_t developer_networkentities
Definition cl_parse.c:173
cvar_t vid_conheight
Definition cl_screen.c:57
cvar_t vid_conwidth
Definition cl_screen.c:56
#define LATESTFRAMENUMS
Definition client.h:959
@ WATERLEVEL_WETFEET
Definition client.h:1326
@ WATERLEVEL_SUBMERGED
Definition client.h:1328
@ WATERLEVEL_SWIMMING
Definition client.h:1327
@ WATERLEVEL_NONE
Definition client.h:1325
@ ca_connected
Definition client.h:532
#define SIGNONS
Definition client.h:525
#define CL_MAX_DOWNLOADACKS
Definition client.h:546
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
Definition cmd.c:1661
static int Cmd_Argc(cmd_state_t *cmd)
Definition cmd.h:249
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
Definition cmd.h:254
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53
cvar_t collision_extendmovelength
Definition collision.c:14
unsigned char COM_BlockSequenceCRCByteQW(unsigned char *base, int length, int sequence)
Definition com_crc16.c:132
gamemode_t gamemode
Definition com_game.c:26
#define IS_NEXUIZ_DERIVED(g)
Definition com_game.h:71
@ GAME_NEXUIZ
Definition com_game.h:33
void MSG_WriteShort(sizebuf_t *sb, int c)
Definition com_msg.c:138
void MSG_WriteAngle16i(sizebuf_t *sb, float f)
Definition com_msg.c:227
void MSG_WriteLong(sizebuf_t *sb, int c)
Definition com_msg.c:147
void MSG_WriteByte(sizebuf_t *sb, int c)
Definition com_msg.c:130
void MSG_WriteFloat(sizebuf_t *sb, float f)
Definition com_msg.c:158
void MSG_WriteAngle32f(sizebuf_t *sb, float f)
Definition com_msg.c:232
void MSG_WriteAngle8i(sizebuf_t *sb, float f)
Definition com_msg.c:222
void MSG_WriteCoord16i(sizebuf_t *sb, float f)
Definition com_msg.c:192
@ PROTOCOL_DARKPLACES2
various changes
Definition common.h:140
@ PROTOCOL_DARKPLACES4
various changes
Definition common.h:138
@ PROTOCOL_NEHAHRABJP2
same as NEHAHRABJP but with 16bit soundindex
Definition common.h:147
@ PROTOCOL_DARKPLACES3
uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snaps...
Definition common.h:139
@ PROTOCOL_NEHAHRABJP
same as QUAKEDP but with 16bit modelindex
Definition common.h:146
@ PROTOCOL_DARKPLACES5
uses EntityFrame5 entity snapshot encoder/decoder which is based on a Tribes networking article at ht...
Definition common.h:137
@ PROTOCOL_DARKPLACES7
added QuakeWorld-style movement protocol to allow more consistent prediction
Definition common.h:135
@ PROTOCOL_QUAKEDP
darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as n...
Definition common.h:142
@ PROTOCOL_UNKNOWN
Definition common.h:133
@ PROTOCOL_DARKPLACES6
various changes
Definition common.h:136
@ PROTOCOL_QUAKE
quake (aka netquake/normalquake/nq) protocol
Definition common.h:144
@ PROTOCOL_DARKPLACES8
added parting messages. WIP
Definition common.h:134
@ PROTOCOL_NEHAHRABJP3
same as NEHAHRABJP2 but with some changes
Definition common.h:148
@ PROTOCOL_NEHAHRAMOVIE
Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but ...
Definition common.h:143
@ PROTOCOL_QUAKEWORLD
quakeworld protocol
Definition common.h:145
@ PROTOCOL_DARKPLACES1
uses EntityFrame entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta com...
Definition common.h:141
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
qbool CL_VM_InputEvent(int eventtype, float x, float y)
Definition csprogs.c:459
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
float friction
#define n(x, y)
r_refdef_t r_refdef
Definition gl_rmain.c:57
const GLdouble * v
Definition glquake.h:762
GLsizeiptr const GLvoid * data
Definition glquake.h:639
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
const GLchar * name
Definition glquake.h:601
host_static_t host
Definition host.c:41
float in_windowmouse_y
Definition input.h:32
float in_windowmouse_x
Definition vid_shared.c:71
void IN_Move(void)
Definition vid_null.c:58
float in_mouse_y
Definition input.h:33
float in_mouse_x
Definition vid_shared.c:70
#define IN_BESTWEAPON_MAX
Definition input.h:40
keydest_t key_dest
Definition keys.c:37
int key_consoleactive
Definition keys.c:38
@ key_game
Definition keys.h:372
void AnglesFromVectors(vec3_t angles, const vec3_t forward, const vec3_t up, qbool flippitch)
LadyHavoc: calculates pitch/yaw/roll angles from forward and up vectors.
Definition mathlib.c:650
float VectorNormalizeLength(vec3_t v)
returns vector length
Definition mathlib.c:763
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition mathlib.c:444
#define ANGLEMOD(a)
Definition mathlib.h:67
#define max(A, B)
Definition mathlib.h:38
#define min(A, B)
Definition mathlib.h:37
#define VectorNormalize(v)
Definition mathlib.h:104
#define VectorClear(a)
Definition mathlib.h:97
#define bound(min, num, max)
Definition mathlib.h:34
#define VectorLength(a)
Definition mathlib.h:109
#define RAD2DEG(a)
Definition mathlib.h:66
#define VectorMAMAM(scale1, b1, scale2, b2, scale3, b3, out)
Definition mathlib.h:117
#define VectorLength2(a)
Definition mathlib.h:110
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
#define VectorNormalize2(v, dest)
Definition mathlib.h:105
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
#define DotProduct(a, b)
Definition mathlib.h:98
#define VectorCopy(in, out)
Definition mathlib.h:101
#define VectorScale(in, scale, out)
Definition mathlib.h:111
#define VectorMAM(scale1, b1, scale2, b2, out)
Definition mathlib.h:116
#define VectorAdd(a, b, out)
Definition mathlib.h:100
#define VectorMA(a, scale, b, out)
Definition mathlib.h:114
#define Vector2Length(a)
Definition mathlib.h:79
void Matrix4x4_Transform(const matrix4x4_t *in, const float v[3], float out[3])
Definition matrixlib.c:1657
void Matrix4x4_OriginFromMatrix(const matrix4x4_t *in, float *out)
Definition matrixlib.c:1792
float pow(float a, float b)
float sqrt(float f)
void cmd(string command,...)
float fabs(float f)
float floor(float f)
qbool NetConn_CanSend(netconn_t *conn)
Definition netconn.c:789
int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, int burstsize, qbool quakesignon_suppressreliables)
Definition netconn.c:844
#define NETGRAPH_PACKETS
Definition netconn.h:222
#define NETGRAPH_LOSTPACKET
Definition netconn.h:224
float impulse
Definition progsdefs.qc:158
#define CLVM_prog
Definition progsvm.h:767
#define qw_clc_delta
Definition protocol.h:958
#define clc_move
Definition protocol.h:290
#define QW_CM_UP
Definition protocol.h:984
#define clc_ackdownloaddata
Definition protocol.h:295
#define QW_UPDATE_BACKUP
Definition protocol.h:1033
#define QW_CM_FORWARD
Definition protocol.h:982
#define QW_CM_ANGLE1
Definition protocol.h:980
#define QW_CM_BUTTONS
Definition protocol.h:985
#define qw_clc_move
Definition protocol.h:956
#define QW_CM_ANGLE2
Definition protocol.h:987
#define clc_ackframe
Definition protocol.h:294
#define QW_UPDATE_MASK
Definition protocol.h:1034
#define QW_CM_ANGLE3
Definition protocol.h:981
#define QW_CM_IMPULSE
Definition protocol.h:986
#define QW_CM_SIDE
Definition protocol.h:983
int i
#define CL_MAX_USERCMDS
max number of predicted input packets in queue
Definition qdefs.h:115
#define STAT_MOVEVARS_WARSOWBUNNY_ACCEL
DP.
Definition qstats.h:37
#define STAT_MOVEFLAGS
DP.
Definition qstats.h:35
#define STAT_MOVEVARS_MAXAIRSPEED
DP.
Definition qstats.h:62
#define STAT_HEALTH
Definition qstats.h:8
#define STAT_MOVEVARS_AIRACCELERATE
DP.
Definition qstats.h:57
#define STAT_MOVEVARS_WATERACCELERATE
DP.
Definition qstats.h:58
#define STAT_SHELLS
Definition qstats.h:14
#define STAT_MOVEVARS_AIRACCEL_QW
DP.
Definition qstats.h:64
#define STAT_MOVEVARS_AIRSTOPACCELERATE
DP.
Definition qstats.h:41
#define STAT_MOVEVARS_TIMESCALE
DP.
Definition qstats.h:51
#define STAT_NAILS
Definition qstats.h:15
#define STAT_MOVEVARS_AIRSTRAFEACCEL_QW
DP.
Definition qstats.h:33
#define STAT_MOVEVARS_AIRCONTROL
DP.
Definition qstats.h:44
#define STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO
DP.
Definition qstats.h:40
#define STAT_MOVEVARS_GRAVITY
DP.
Definition qstats.h:52
#define STAT_MOVEVARS_AIRSTRAFEACCELERATE
DP.
Definition qstats.h:42
#define STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR
DP.
Definition qstats.h:30
#define STAT_MOVEVARS_TICRATE
DP.
Definition qstats.h:50
#define STAT_MOVEVARS_SPECTATORMAXSPEED
DP.
Definition qstats.h:55
#define STAT_MOVEVARS_MAXSPEED
DP.
Definition qstats.h:54
#define STAT_MOVEVARS_WALLFRICTION
DP.
Definition qstats.h:47
#define STAT_CELLS
Definition qstats.h:17
#define STAT_MOVEVARS_STEPHEIGHT
DP.
Definition qstats.h:63
#define STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW
DP.
Definition qstats.h:32
#define STAT_MOVEVARS_AIRCONTROL_PENALTY
DP.
Definition qstats.h:31
#define STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION
DP.
Definition qstats.h:65
#define STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL
DP.
Definition qstats.h:36
#define STAT_MOVEVARS_MAXAIRSTRAFESPEED
DP.
Definition qstats.h:43
#define STAT_MOVEVARS_STOPSPEED
DP.
Definition qstats.h:53
#define STAT_MOVEVARS_ACCELERATE
DP.
Definition qstats.h:56
#define STAT_MOVEVARS_ENTGRAVITY
DP.
Definition qstats.h:59
#define STAT_MOVEVARS_WATERFRICTION
DP.
Definition qstats.h:49
#define STAT_MOVEVARS_EDGEFRICTION
DP.
Definition qstats.h:61
#define STAT_MOVEVARS_AIRCONTROL_POWER
DP.
Definition qstats.h:34
#define STAT_ITEMS
FTE, DP.
Definition qstats.h:23
#define STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL
DP.
Definition qstats.h:39
#define STAT_MOVEVARS_JUMPVELOCITY
DP.
Definition qstats.h:60
#define STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED
DP.
Definition qstats.h:38
#define STAT_ROCKETS
Definition qstats.h:16
#define STAT_MOVEVARS_FRICTION
DP.
Definition qstats.h:48
#define NULL
Definition qtypes.h:12
float vec_t
Definition qtypes.h:68
vec_t vec3_t[3]
Definition qtypes.h:71
bool qbool
Definition qtypes.h:9
#define YAW
Definition qtypes.h:19
#define PITCH
Definition qtypes.h:16
#define ROLL
Definition qtypes.h:22
#define MOVEFLAG_Q2AIRACCELERATE
Definition quakedef.h:33
#define IT_LIGHTNING
Definition quakedef.h:44
#define IT_GRENADE_LAUNCHER
Definition quakedef.h:42
qbool noclip_anglehack
Definition sv_ccmds.c:190
#define IT_AXE
Definition quakedef.h:50
#define IT_SHOTGUN
Definition quakedef.h:38
#define HIT_MJOLNIR
Definition quakedef.h:118
#define IT_SUPER_SHOTGUN
Definition quakedef.h:39
#define IT_NAILGUN
Definition quakedef.h:40
cvar_t chase_active
Definition view.c:132
#define IT_ROCKET_LAUNCHER
Definition quakedef.h:43
#define MOVEFLAG_NOGRAVITYONGROUND
Definition quakedef.h:34
#define IT_SUPER_NAILGUN
Definition quakedef.h:41
#define MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE
Definition quakedef.h:35
#define MOVEFLAG_VALID
Definition quakedef.h:32
#define HIT_LASER_CANNON
Definition quakedef.h:119
cvar_t sv_gravity
Definition sv_main.c:134
dp_FragColor r
precision highp float
Definition shader_glsl.h:53
float f
dp_FragColor b
ret a
struct prvm_edict_s * self
Definition client.h:1335
waterlevel_t waterlevel
Definition client.h:1349
float movevars_warsowbunny_airforwardaccel
Definition client.h:1081
float movevars_stopspeed
Definition client.h:1060
float movevars_timescale
Definition client.h:1058
vec3_t movement_origin
Definition client.h:809
float movevars_maxairstrafespeed
Definition client.h:1076
float movevars_entgravity
Definition client.h:1066
float movevars_waterfriction
Definition client.h:1056
vec3_t movement_velocity
Definition client.h:810
float movevars_ticrate
Definition client.h:1086
float movevars_jumpvelocity
Definition client.h:1067
qbool onground
Definition client.h:843
unsigned int latestsendnums[LATESTFRAMENUMS]
Definition client.h:962
float movevars_warsowbunny_accel
Definition client.h:1082
float movevars_spectatormaxspeed
Definition client.h:1062
float last_received_message
Definition client.h:885
vec3_t playerstandmins
Definition client.h:972
float sensitivityscale
Definition client.h:833
float movevars_aircontrol
Definition client.h:1078
float movevars_airaccel_qw_stretchfactor
Definition client.h:1072
uint8_t opt_inputs_since_update
Definition client.h:1051
float movevars_airaccel_qw
Definition client.h:1071
float movevars_warsowbunny_topspeed
Definition client.h:1083
float movevars_gravity
Definition client.h:1059
vec3_t playerstandmaxs
Definition client.h:973
vec3_t viewangles
Definition client.h:786
int latestframenumsposition
Definition client.h:960
float movevars_airspeedlimit_nonqw
Definition client.h:1087
float movevars_airstrafeaccelerate
Definition client.h:1075
float * statsf
Definition client.h:759
entity_t * entities
Definition client.h:991
vec3_t playercrouchmaxs
Definition client.h:975
int intermission
Definition client.h:856
float movevars_maxairspeed
Definition client.h:1069
qbool csqc_wantsmousemove
Definition client.h:835
float movevars_warsowbunny_turnaccel
Definition client.h:1084
float movevars_accelerate
Definition client.h:1063
double realframetime
Definition client.h:871
float movevars_aircontrol_power
Definition client.h:1079
float movevars_maxspeed
Definition client.h:1061
float movevars_airaccel_sideways_friction
Definition client.h:1073
double time
Definition client.h:868
vec_t viewzoom
Definition client.h:794
float movevars_edgefriction
Definition client.h:1068
vec3_t playercrouchmins
Definition client.h:974
float movevars_warsowbunny_backtosideratio
Definition client.h:1085
float movevars_friction
Definition client.h:1057
usercmd_t movecmd[CL_MAX_USERCMDS]
Definition client.h:754
double mtime[2]
Definition client.h:861
vec3_t mvelocity[2]
Definition client.h:792
int latestframenums[LATESTFRAMENUMS]
Definition client.h:961
unsigned int moveflags
Definition client.h:1054
qbool movement_predicted
Definition client.h:805
float movevars_aircontrol_penalty
Definition client.h:1080
float movevars_airaccelerate
Definition client.h:1064
float movevars_stepheight
Definition client.h:1070
int playerentity
Definition client.h:910
unsigned int qw_validsequence
Definition client.h:1104
qbool movement_replay
Definition client.h:807
int stats[MAX_CL_STATS]
Definition client.h:758
usercmd_t cmd
Definition client.h:752
unsigned int qw_deltasequence[QW_UPDATE_BACKUP]
Definition client.h:1106
float movevars_wateraccelerate
Definition client.h:1065
float movevars_airstrafeaccel_qw
Definition client.h:1077
float movevars_airstopaccelerate
Definition client.h:1074
float timesincepacket
Definition client.h:1049
float movevars_wallfriction
Definition client.h:1055
unsigned int servermovesequence
Definition client.h:637
qbool demoplayback
Definition client.h:587
cactive_t state
Definition client.h:568
qbool demorecording
Definition client.h:584
cl_downloadack_t dp_downloadack[CL_MAX_DOWNLOADACKS]
Definition client.h:634
netconn_t * netcon
Definition client.h:630
int proquake_servermod
Definition client.h:683
protocolversion_t protocol
Definition client.h:617
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127
Definition cvar.h:66
float value
Definition cvar.h:74
int integer
Definition cvar.h:73
float origin[3]
Definition protocol.h:444
entity_state_t state_current
Definition client.h:471
entity_render_t render
Definition client.h:477
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
Definition host.h:46
int state
Definition client.h:1246
netgraphitem_t incoming_netgraph[NETGRAPH_PACKETS]
Definition netconn.h:227
unsigned int outgoing_unreliable_sequence
used by both NQ and QW protocols
Definition netconn.h:176
sizebuf_t message
writing buffer to send to peer as the next reliable message can be added to at any time,...
Definition netconn.h:161
int unreliablebytes
Definition netconn.h:136
r_refdef_view_t view
Definition render.h:406
float frustum_y
Definition render.h:277
float frustum_x
Definition render.h:277
matrix4x4_t matrix
Definition render.h:266
int cursize
Definition common.h:54
qbool overflowed
set to true if the buffer size failed
Definition common.h:51
double fraction
Definition collision.h:40
double endpos[3]
Definition collision.h:42
int startsupercontents
Definition collision.h:56
plane_t plane
Definition collision.h:44
qbool startsolid
Definition collision.h:26
int impulse
Definition protocol.h:396
vec3_t cursor_end
Definition protocol.h:386
vec3_t cursor_start
Definition protocol.h:385
qbool jump
Definition protocol.h:404
vec3_t viewangles
Definition protocol.h:377
vec3_t cursor_screen
Definition protocol.h:384
vec3_t cursor_normal
Definition protocol.h:388
qbool predicted
Definition protocol.h:399
unsigned char msec
Definition protocol.h:394
vec_t cursor_fraction
Definition protocol.h:389
int cursor_entitynumber
Definition protocol.h:390
vec3_t cursor_impact
Definition protocol.h:387
double time
Definition protocol.h:392
float forwardmove
Definition protocol.h:380
qbool canjump
Definition protocol.h:403
qbool crouch
Definition protocol.h:405
int buttons
Definition protocol.h:395
float upmove
Definition protocol.h:382
double frametime
Definition protocol.h:402
unsigned int sequence
Definition protocol.h:397
float sidemove
Definition protocol.h:381
int width
Definition vid.h:60
int height
Definition vid.h:61
viddef_mode_t mode
currently active video mode
Definition vid.h:73
static vec3_t wishdir
Definition sv_user.c:305
static float wishspeed
Definition sv_user.c:306
static vec3_t forward
Definition sv_user.c:305
static vec3_t right
Definition sv_user.c:305
static vec3_t up
Definition sv_user.c:305
vec3_t normal
Definition collision.h:13
viddef_t vid
global video state
Definition vid_shared.c:64
qbool vid_activewindow
Definition vid_shared.c:77
void V_StartPitchDrift_f(cmd_state_t *cmd)
Definition view.c:164
void V_StopPitchDrift(void)
Definition view.c:169
#define MOVE_NORMAL
Definition world.h:28
#define MOVE_NOMONSTERS
Definition world.h:29