Claim set · data/claims/quake.yaml

Quake (id Software's engine source, WinQuake 1.09 and QuakeWorld, with the 1.01 QuakeC)

Game: Quake.

id Software's released Quake engine source numbers its single-player engine, WinQuake, as version 1.09 (VERSION in quakedef.h); the readme calls the release "the complete source code for winquake, glquake, quakeworld, and glquakeworld" and says the original DOS version "should also be buildable from these sources, but we didn't bother trying". quake/source-version

Value: 1.09

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/quakedef.h#L26#define VERSION 1.09Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · readme.txt#L2-L3This is the complete source code for winquake, glquake, quakeworld, and glquakeworld.Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · readme.txt#L13-L14The original dos version of Quake should also be buildable from these sources, but we didn't bother trying.Checked by claude, 2026-10-22 — read quakedef.h's version define and the readme at the pinned commit

Every engine claim here reads WinQuake's code unless it names QuakeWorld. The 1996 DOS executable is not in the release, so a claim holds for it only as far as the two share code.

Cited by: Quake

Quake's host runs a frame only once at least 1/72 second has passed since the last, so the game steps at most 72 times a second; each frame's time step (host_frametime) is the real time since the last frame, clamped to 0.001–0.1 second, unless host_framerate fixes it, and a time demo skips the 1/72 wait. quake/frame-time

Value: 72 frames/s

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/host.c#L503-L519realtime += time; … if (!cls.timedemo && realtime - oldrealtime < 1.0/72.0) return false; // framerate is too high … host_frametime = realtime - oldrealtime; … if (host_framerate.value > 0) host_frametime = host_framerate.value; … if (host_frametime > 0.1) host_frametime = 0.1; …Checked by claude, 2026-10-22 — read Host_FilterTime; the movement code below scales by host_frametime

Every rate below (acceleration, friction, gravity) is per second, times this step.

Cited by: Quake

Each Quake server frame reads every client's move and runs SV_ClientThink, which applies friction and acceleration, before SV_Physics, which runs the QuakeC PlayerPreThink (where the jump is), then gravity and the move; SV_ClientThink reads the on-ground flag the last move left, does nothing for a dead player or one with movetype none, and hands a water jump and a player at water level 2 or more (unless noclipping) to the water code. quake/frame-order

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/host.c#L611-L617// read client messages SV_RunClients (); … if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) ) SV_Physics ();Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L611if (!SV_ReadClientMessage ())Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L625-L626if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) ) SV_ClientThink ();Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L384-L429if (sv_player->v.movetype == MOVETYPE_NONE) return; … onground = (int)sv_player->v.flags & FL_ONGROUND; … if (sv_player->v.health <= 0) return; … if ( (int)sv_player->v.flags & FL_WATERJUMP ) { SV_WaterJump (); return; …Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L1534-L1535if (i > 0 && i <= svs.maxclients) SV_Physics_Client (ent, i);Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L1069PR_ExecuteProgram (pr_global_struct->PlayerPreThink);Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L1086-L1095case MOVETYPE_WALK: … if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) SV_AddGravity (ent); … SV_WalkMove (ent);Checked by claude, 2026-10-22 — read Host_ServerFrame (the #else branch; FPS_20 is tested in host.c and pr_exec.c but defined nowhere in WinQuake), SV_RunClients, SV_ClientThink, and SV_Physics_Client's walk case

The order matters for jumping: see quake/hop-friction. SV_WalkMove clears the on-ground flag and sets it again only when its move ends on a floor (quake/hop-friction cites the lines).

On the ground, Quake's SV_UserFriction takes the horizontal speed and lowers it by frame time × friction × the larger of the speed and sv_stopspeed, to no less than 0, scaling all three velocity axes by the same factor; sv_friction defaults to 4 and sv_stopspeed to 100, and when a trace 16 units ahead along the motion finds no floor within 34 units below the feet, the friction is multiplied by edgefriction (default 2). A standing player is left alone. quake/ground-friction

About: Quake Running

Value
{
 "sv_friction": 4,
 "sv_stopspeed": 100,
 "edgefriction": 2
}
CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L42-L43cvar_t sv_friction = {"sv_friction","4",false,true}; cvar_t sv_stopspeed = {"sv_stopspeed","100"};Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L27cvar_t sv_edgefriction = {"edgefriction", "2"};Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L132-L159speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); if (!speed) return; … // if the leading edge is over a dropoff, increase friction start[0] = stop[0] = origin[0] + vel[0]/speed*16; … stop[2] = start[2] - 34; … if (trace.fraction == 1.0) friction = sv_friction.value*sv_edgefriction.value; else …Checked by claude, 2026-10-22 — read SV_UserFriction and the three cvar definitions at the pinned commit

Above 100 units/s the loss is proportional to speed (4 per second, an exponential fade); below it, a constant 400 units/s². Note the edge cvar's console name is edgefriction, not sv_edgefriction.

Cited by: Quake

Quake builds the wish velocity from the forward and side moves along the view's forward and right vectors (zero vertical for a walking player), caps its length at sv_maxspeed (default 320), and on the ground runs friction and then SV_Accelerate: if the speed along the wish direction is under the wish speed, it adds sv_accelerate (default 10) × frame time × wish speed along that direction, no more than the shortfall. quake/ground-accelerate

About: Quake Running

Value
{
 "sv_accelerate": 10,
 "sv_maxspeed": 320
}
CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L167-L168cvar_t sv_maxspeed = {"sv_maxspeed", "320", false, true}; cvar_t sv_accelerate = {"sv_accelerate", "10"};Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L341-L365wishvel[i] = forward[i]*fmove + right[i]*smove; … if ( (int)sv_player->v.movetype != MOVETYPE_WALK) wishvel[2] = cmd.upmove; else wishvel[2] = 0; … wishspeed = VectorNormalize(wishdir); if (wishspeed > sv_maxspeed.value) { VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel); wishspeed = sv_maxspeed.value; …Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L190-L204void SV_Accelerate (void) … currentspeed = DotProduct (velocity, wishdir); addspeed = wishspeed - currentspeed; if (addspeed <= 0) return; accelspeed = sv_accelerate.value*host_frametime*wishspeed; if (accelspeed > addspeed) accelspeed = addspeed; … velocity[i] += accelspeed*wishdir[i];Checked by claude, 2026-10-22 — read SV_AirMove's wish velocity and the live SV_Accelerate (an older version above it is under

The test is on the speed along the wish direction, not the whole speed: a sideways velocity doesn't stop the push. The same test, with a cap, is the root of quake/air-accelerate.

Cited by: Quake

Quake's keyboard moves are cl_forwardspeed and cl_backspeed 200 and cl_sidespeed 350, doubled by the run key (cl_movespeedkey 2.0), and the menu's "always run" sets forward and back to 400. Computed from these and the 320 cap: walking forward wishes 200, while a strafe alone (350), a walk with a strafe (√(200² + 350²) ≈ 403), and any run all wish 320. quake/move-speeds

About: Quake Strafe-running

Value
{
 "forward": 200,
 "side": 350,
 "run": 2,
 "cap": 320
}
CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/cl_input.c#L213-L217cvar_t cl_forwardspeed = {"cl_forwardspeed","200", true}; cvar_t cl_backspeed = {"cl_backspeed","200", true}; cvar_t cl_sidespeed = {"cl_sidespeed","350"}; … cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0"};Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/cl_input.c#L298-L317cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright); … cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward); … if (in_speed.state & 1) { cmd->forwardmove *= cl_movespeedkey.value; cmd->sidemove *= cl_movespeedkey.value;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/menu.c#L1115-L1124case 8: // allways run … Cvar_SetValue ("cl_forwardspeed", 400); Cvar_SetValue ("cl_backspeed", 400);Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L351-L354if (wishspeed > sv_maxspeed.value) { VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel); wishspeed = sv_maxspeed.value;Checked by claude, 2026-10-22 — read CL_BaseMove's key sums and speed-key scaling, the menu toggle, and the server's cap

So on the ground a strafe adds speed only to a walk (320 against 200, 1.6 times), and none to a run, which the cap already holds at 320. Mouse and joystick moves add to the same command; they are not read here.

Cited by: Strafe-running

Computed from the friction and acceleration rules, not measured: because acceleration (10) outpaces friction (4), a Quake player on flat ground settles at exactly the wish speed, 320 units/s at a run; at the 72-frame rate a run from rest reaches it on frame 10 (0.14 s), and letting go from 320 comes to rest after 39 frames (0.54 s). quake/ground-speed

About: Quake Running

Value: 320 units/s

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L150-L151control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed; newspeed = speed - host_frametime*control*friction;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L195-L201currentspeed = DotProduct (velocity, wishdir); addspeed = wishspeed - currentspeed; … accelspeed = sv_accelerate.value*host_frametime*wishspeed; if (accelspeed > addspeed) accelspeed = addspeed;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L42-L43cvar_t sv_friction = {"sv_friction","4",false,true}; cvar_t sv_stopspeed = {"sv_stopspeed","100"};Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L167-L168cvar_t sv_maxspeed = {"sv_maxspeed", "320", false, true}; cvar_t sv_accelerate = {"sv_accelerate", "10"};Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/host.c#L505if (!cls.timedemo && realtime - oldrealtime < 1.0/72.0)Checked by claude, 2026-10-22 — stepped friction then acceleration per frame at dt 1/72 with the defaults, no edge; at speed W friction removes 4·dt·W and acceleration can restore up to 10·dt·W, so each frame returns to W exactly

A slower frame rate changes the frame counts but not the settled speed. Over a ledge the friction doubles to 8, still under 10, so the settled speed holds there too.

Cited by: Quake

In the air, Quake's SV_AirAccelerate takes the wish velocity's direction and length, caps that length at 30, and adds speed along the wish direction only while the velocity's component along it is under 30: the push is sv_accelerate × the uncapped wish speed (up to 320) × frame time, cut to the shortfall below 30. There is no friction in the air. quake/air-accelerate

About: Quake Strafe-running

Value: 30 units/s

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L207-L225void SV_AirAccelerate (vec3_t wishveloc) … wishspd = VectorNormalize (wishveloc); if (wishspd > 30) wishspd = 30; currentspeed = DotProduct (velocity, wishveloc); addspeed = wishspd - currentspeed; if (addspeed <= 0) return; // accelspeed = sv_accelerate.value * host_frametime; accelspeed = sv_accelerate.value*wishspeed * host_frametime; if (accelspeed > addspeed) …Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L361-L368else if ( onground ) { SV_UserFriction (); SV_Accelerate (); } else { // not on ground, so little effect on velocity SV_AirAccelerate (wishvel);Checked by claude, 2026-10-22 — read SV_AirAccelerate and its call; `wishspeed` in the accelspeed line is the global set by SV_AirMove (capped at 320), while `wishspd` is the local capped at 30

The cap limits only the speed along the wish direction, so a velocity pointing elsewhere gets the full push. The commented-out line above the live one is id's own.

Cited by: Quake, Strafe-running

Computed from SV_AirAccelerate, not measured: with a wish speed of 320 the push can reach 10 × 320 × frame time (44.4 at 1/72 s, more at longer frames), so a frame lifts the velocity's component c along the wish direction to 30 whenever c is between −14.4 and 30, and the new speed is √(v² + 900 − c²) for speed v. That is largest with the wish at 90° to the motion: each frame then adds √(v² + 900) − v, 1.40 units/s at 320 and 0.90 at 500, and turns the motion by atan(30/v), 5.4° per frame at 320. At 72 frames a second that is about 101 units/s gained per second at 320. quake/air-strafe-gain

About: Quake Strafe-running

Value: 1.4 units/s per frame at 320

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L212-L224wishspd = VectorNormalize (wishveloc); if (wishspd > 30) wishspd = 30; currentspeed = DotProduct (velocity, wishveloc); addspeed = wishspd - currentspeed; … accelspeed = sv_accelerate.value*wishspeed * host_frametime; if (accelspeed > addspeed) accelspeed = addspeed;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L168cvar_t sv_accelerate = {"sv_accelerate", "10"};Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/host.c#L505if (!cls.timedemo && realtime - oldrealtime < 1.0/72.0)Checked by claude, 2026-10-22 — with push a = 30 − c along unit ŵ, |v + aŵ|² = v² + 2ca + a² = v² + 900 − c², largest at c = 0; below c = −14.4 the push is held to 44.4 and the square is under v² + 700; evaluated at v = 320 and 500 with dt 1/72

Holding a strafe key alone gives a side move of 350, capped to 320, so a player in the air gains by turning the view to keep the strafe at right angles to the motion. A wish speed under 216 at 1/72 s would make the push, not the 30, the limit.

Cited by: Quake, Strafe-running

Quake's jump is QuakeC (1.01's client.qc): each frame PlayerPreThink calls PlayerJump while the jump button is held and otherwise sets FL_JUMPRELEASED; on land (water level under 2, not in a water jump), PlayerJump acts only when the player is on the ground and has released the button since the last jump, then clears both flags and adds 270 to the vertical velocity. Holding the button never jumps twice. quake/jump

About: Quake Jump

Value: 270 units/s

CodeQuake: the QuakeC source and compiler (id-Software/Quake-Tools, qcc/v101qc) · qcc/v101qc/client.qc#L972-L977if (self.button2) { PlayerJump (); } else self.flags = self.flags | FL_JUMPRELEASED;Quake: the QuakeC source and compiler (id-Software/Quake-Tools, qcc/v101qc) · qcc/v101qc/client.qc#L773-L776if (self.flags & FL_WATERJUMP) return; … if (self.waterlevel >= 2)Quake: the QuakeC source and compiler (id-Software/Quake-Tools, qcc/v101qc) · qcc/v101qc/client.qc#L798-L811if (!(self.flags & FL_ONGROUND)) return; … if ( !(self.flags & FL_JUMPRELEASED) ) return; // don't pogo stick … self.flags = self.flags - (self.flags & FL_JUMPRELEASED); … self.flags = self.flags - FL_ONGROUND; // don't stairwalk … self.velocity_z = self.velocity_z + 270;Checked by claude, 2026-10-22 — read PlayerPreThink's button test and PlayerJump in qcc/v101qc/client.qc

The jump adds to the vertical velocity rather than setting it. In deeper water the same button swims up at a set speed instead (100 in water, 80 in slime, and 50 otherwise).

Cited by: Quake

Computed from the jump and gravity, ignoring frame steps: a Quake jump from flat ground at the default gravity of 800 rises 270² / (2 × 800) ≈ 45.6 units and lands after 2 × 270 / 800 = 0.675 seconds. quake/jump-arc

About: Quake Jump

Value: 45.6 units

CodeQuake: the QuakeC source and compiler (id-Software/Quake-Tools, qcc/v101qc) · qcc/v101qc/client.qc#L811self.velocity_z = self.velocity_z + 270;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L389ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;Quake: the QuakeC source and compiler (id-Software/Quake-Tools, qcc/v101qc) · qcc/v101qc/world.qc#L198-L199else cvar_set ("sv_gravity", "800");Checked by claude, 2026-10-22 — constant-acceleration arithmetic; stepping it at 1/72 s gives 43.7 units and 48 frames, so the frame steps shave a little

On E1M8, with gravity 100, the same jump would rise eight times as high, about 365 units, by the same arithmetic.

Quake's gravity is the cvar sv_gravity, defaulting to 800, and each level's QuakeC worldspawn sets it to 800 again, or to 100 on E1M8; every frame a walking player is not in water (water level 2 or more) or a water jump, SV_AddGravity takes the entity's gravity field (1 when unset) × sv_gravity × frame time off its vertical velocity, on the ground as well as in the air. quake/gravity

About: Quake Gravity

Value: 800 units/s²

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L44cvar_t sv_gravity = {"sv_gravity","800",false,true};Quake: the QuakeC source and compiler (id-Software/Quake-Tools, qcc/v101qc) · qcc/v101qc/world.qc#L196-L199if (self.model == "maps/e1m8.bsp") cvar_set ("sv_gravity", "100"); else cvar_set ("sv_gravity", "800");Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L381-L389eval_t *val; … val = GetEdictFieldValue(ent, "gravity"); if (val && val->_float) ent_gravity = val->_float; else ent_gravity = 1.0; … ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L1089-L1090if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) SV_AddGravity (ent);Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L858return ent->v.waterlevel > 1;Checked by claude, 2026-10-22 — read the cvar, worldspawn, SV_AddGravity's non-QUAKE2 branch, and SV_Physics_Client's walk case; the call has no on-ground test

The gravity field is looked up by name, so a mod's QuakeC can give an entity its own scale.

Cited by: Quake

Because Quake runs friction in SV_ClientThink before the QuakeC jump in PlayerPreThink, and the on-ground flag is set by the walking move when it ends on a floor, a jump can come no sooner than the frame after landing, and that frame takes ground friction first: computed, a hop loses 4/72 of its horizontal speed (5.6%) at 72 frames a second above 100 units/s, or 8/72 (11.1%) when no floor lies within 34 units below a point 16 units ahead. quake/hop-friction

About: Quake Bunny hopping

Value: 5.6 % per hop at 72 frames/s

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/host.c#L612-L617SV_RunClients (); … SV_Physics ();Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L387onground = (int)sv_player->v.flags & FL_ONGROUND;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L361-L364else if ( onground ) { SV_UserFriction (); SV_Accelerate ();Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L1069PR_ExecuteProgram (pr_global_struct->PlayerPreThink);Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L970-L971oldonground = (int)ent->v.flags & FL_ONGROUND; ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L284-L287if (trace.ent->v.solid == SOLID_BSP) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L1033-L1037if (downtrace.plane.normal[2] > 0.7) { if (ent->v.solid == SOLID_BSP) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND;Quake: the QuakeC source and compiler (id-Software/Quake-Tools, qcc/v101qc) · qcc/v101qc/client.qc#L798-L799if (!(self.flags & FL_ONGROUND)) return;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L144-L151if (trace.fraction == 1.0) friction = sv_friction.value*sv_edgefriction.value; … newspeed = speed - host_frametime*control*friction;Checked by claude, 2026-10-22 — traced one frame: SV_RunClients → SV_ClientThink (friction on the flag from the last move) → SV_Physics → PlayerPreThink (jump) → SV_WalkMove (clears the flag, sets it on a floor); on the landing frame the jump test runs before the move that lands, so the earliest jump is the next frame, after its friction; loss = dt × 4 at speed over sv_stopspeed

The ground frame also runs SV_Accelerate, which can add up to 10 × 320 / 72 ≈ 44 units/s at right angles to a fast motion, so a strafing hop loses less than the friction alone. The jump also needs the button released and pressed again (quake/jump). Compare QuakeWorld, quake/qw-hop-friction.

Cited by: Bunny hopping, Quake

QuakeWorld's pmove.c checks the jump before friction: PlayerMove calls JumpButton, which clears onground, and then PM_Friction, whose ground friction runs only while onground is set, so a QuakeWorld hop on its first ground frame loses no speed to friction, where WinQuake's takes one frame of it (quake/hop-friction). Both still need the button released between jumps, and both add 270. quake/qw-hop-friction

About: Quake Bunny hopping

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · QW/client/pmove.c#L889-L894if (pmove.cmd.buttons & BUTTON_JUMP) JumpButton (); else pmove.oldbuttons &= ~BUTTON_JUMP; … PM_Friction ();Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · QW/client/pmove.c#L674-L681if (onground == -1) return; // in air, so no effect … if ( pmove.oldbuttons & BUTTON_JUMP ) return; // don't pogo stick … onground = -1; pmove.velocity[2] += 270;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · QW/client/pmove.c#L366-L369else if (onground != -1) // apply ground friction { control = speed < movevars.stopspeed ? movevars.stopspeed : speed; drop += control*friction*frametime;Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · QW/server/sv_user.c#L1460PlayerMove ();Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L361-L364else if ( onground ) { SV_UserFriction (); SV_Accelerate ();Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_phys.c#L1069PR_ExecuteProgram (pr_global_struct->PlayerPreThink);Checked by claude, 2026-10-22 — read PlayerMove, JumpButton, and PM_Friction in QW/client/pmove.c and the QuakeWorld server's call to PlayerMove; against WinQuake's order in quake/frame-order

QuakeWorld's friction also uses the full 3D speed where WinQuake's uses the horizontal speed.

Cited by: Bunny hopping, Quake

QuakeWorld's PM_AirAccelerate keeps WinQuake's air rule unchanged: the wish speed capped at 30 for the shortfall test, and the push from the uncapped wish speed × acceleration × frame time; it adds only an early return for a dead player or a water jump. quake/qw-air-accelerate

About: Quake Strafe-running

CodeQuake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · QW/client/pmove.c#L412-L433void PM_AirAccelerate (vec3_t wishdir, float wishspeed, float accel) … if (pmove.dead) return; if (pmove.waterjumptime) return; … if (wishspd > 30) wishspd = 30; currentspeed = DotProduct (pmove.velocity, wishdir); addspeed = wishspd - currentspeed; … …Quake: the engine source release (id-Software/Quake: WinQuake and QuakeWorld) · WinQuake/sv_user.c#L212-L222wishspd = VectorNormalize (wishveloc); if (wishspd > 30) wishspd = 30; currentspeed = DotProduct (velocity, wishveloc); addspeed = wishspd - currentspeed; … accelspeed = sv_accelerate.value*wishspeed * host_frametime; if (accelspeed > addspeed) accelspeed = addspeed;Checked by claude, 2026-10-22 — read both functions side by side; QW passes the direction and speed in, WinQuake normalizes the wish velocity itself

QuakeWorld takes its frame time from each command's milliseconds (pmove.cmd.msec), so the per-frame gain in quake/air-strafe-gain applies per command there.