Cite as
id-Software/Quake-2
Original
https://github.com/id-Software/Quake-2
Pinned
id-Software/Quake-2 @ 372afde46e7defc9dd2d719a1732b8ace1fa096e
Accessed
2026-10-22
Licence
GPL-2.0 (gnu.txt is the GNU General Public License, version 2; readme.txt says “The code is all licensed under the terms of the GPL (gnu public license)”, and each source file's header reads “Copyright (C) 1997-2001 Id Software, Inc.” under GPL version 2 or later). The readme adds that “All of the Q2 data files remain copyrighted and licensed under the original terms”.
Credit
id Software's source for Quake II, released by John Carmack (readme.txt is signed “John Carmack, Id Software”), who thanks Robert Duffy “for doing the grunt work of building this release.”
Notes
The pinned commit is titled “The original Quake 2 sources as originally released under the GPL license on December 21, 2001.” The readme calls it “the complete source code for Quake 2, version 3.19”, and `qcommon.h` sets `VERSION` 3.19, so every claim describes the 3.19 point release, not the 1997 retail build. Player movement (`qcommon/pmove.c`) is engine code that the server and the client's prediction both run; the game rules (weapons, damage, monsters, items) are the game library in `game/`. The repo also holds two save files under `baseq2/save/`; `paths` keeps the fetch to the root texts, the movement code, the game library's source, and the client and server files the claims read.

Cited on

Claims (14)

id Software's GPL source release of Quake II calls itself "the complete source code for Quake 2, version 3.19", and qcommon.h sets VERSION to 3.19, so the code read here is the 3.19 point release rather than the 1997 retail build.readme.txt L2qcommon/qcommon.h L26Code
On the ground, Quake II's Pmove runs PM_Friction, which lowers the speed by step time × 6 (pm_friction) × the larger of the speed and 100 (pm_stopspeed) on any ground that isn't slick, and then PM_Accelerate with pm_accelerate 10: if the speed along the wish direction is under the wish speed, it adds 10 × step time × wish speed, no more than the shortfall. The wish velocity's length is capped at 300 (pm_maxspeed), or 100 ducked. These are the numbers Quake III keeps (friction 6, acceleration 10), where Quake's friction is 4. Computed, not measured: since 10 outpaces 6, a run settles at exactly 300 units/s. The movement constants are C globals, not cvars.qcommon/pmove.c L53–59qcommon/pmove.c L1335–1337qcommon/pmove.c L364–370qcommon/pmove.c L397–411qcommon/pmove.c L607–613qcommon/pmove.c L635–638Code
Quake II's keyboard moves are cl_forwardspeed, cl_sidespeed, and cl_upspeed 200, all doubled while running, which the speed key toggles: with cl_run 0 holding the key runs, and with cl_run 1 holding it walks. The movement code builds the wish velocity from the view's forward and right vectors, with the pitch first divided by 3, then zeroes its vertical part and caps its length at 300. Computed from these, with the view level (pitch 0): walking forward wishes 200 and walking forward with a strafe about 283, but a run wishes 400 forward and about 566 on the diagonal, both cut to 300, so a strafe adds nothing to a run on the ground. Looking up or down shortens the forward part before the cap.client/cl_main.c L1441–1448client/cl_input.c L289–309qcommon/pmove.c L1344–1349qcommon/pmove.c L595–613Code
In the air, Quake II's PM_AirMove calls the ground's PM_Accelerate with an acceleration of 1 while pm_airaccelerate is 0: the push is 1 × step time × wish speed (up to 300), and it stops only when the velocity's component along the wish direction reaches the full wish speed. Quake III keeps this rule, with pm_airaccelerate 1 and a PM_Accelerate commented "q2 style". In deathmatch the server copies its latched cvar sv_airaccelerate (default 0) into pm_airaccelerate, and any nonzero value switches to PM_AirAccelerate, which is Quake's air rule: the wish speed capped at 30 for the shortfall, the push from the uncapped wish speed × pm_accelerate (10) × step time. The server's movement code uses the value only as a nonzero test, so it acts as an on-off switch; outside deathmatch it is forced to 0. The server also sends the value to clients as the CS_AIRACCEL config string, for their prediction, in code not read here.qcommon/pmove.c L57qcommon/pmove.c L652–657qcommon/pmove.c L414–427server/sv_main.c L974server/sv_init.c L196–205Code
Quake II's PM_CheckJump, which Pmove runs before friction, does nothing while the landing timer flag is set; otherwise it needs an up move of at least 10 and the jump-held flag clear, which only a command with the key released clears, so holding the key never jumps twice. On ground it adds 270 to the vertical velocity, raising it to at least 270, and clears the ground entity; in water at level 2 or more it sets an upward swim speed instead (100 in water, 80 in slime, 50 in lava). Quake's QuakeC jump and QuakeWorld's movement code also add 270. Gravity is sv_gravity, 800.qcommon/pmove.c L778–822game/g_save.c L164Code
Quake II checks the jump before friction: Pmove calls PM_CheckJump, which clears the ground entity, and then PM_Friction, whose ground friction needs a ground entity, so a hop on the first command that starts on the ground loses no speed to friction. QuakeWorld's PlayerMove has the same order: JumpButton clears onground before PM_Friction, whose ground friction needs it. Two conditions apply. The jump key must be released and pressed again (the jump claim). And when the position check first finds ground with the vertical speed below −200, it sets a landing timer of 18 units, or 25 below −400, that blocks the jump until it runs out; each command lowers it by its length in ms divided by 8, rounded down and at least 1, so 18 units last 144 ms at 8 or 16 ms commands and 180 ms at 10 ms (computed). By the atlas's reading the slide move clips the velocity along a floor it runs into, and the stepping move keeps that clipped vertical speed, so a landing step that reaches the floor would not set the timer; how often a hop's landing sets it has not been measured.qcommon/pmove.c L1333–1337qcommon/pmove.c L819qcommon/pmove.c L365qcommon/pmove.c L714–726qcommon/pmove.c L1302–1316qcommon/pmove.c L683–693qcommon/pmove.c L219–221qcommon/pmove.c L332–334Code
Quake II's bullets, pellets, and railgun are hitscan: fire_lead, which fire_bullet (the machine gun and chaingun) and fire_shotgun (once per pellet, for both shotguns) call, traces a line 8192 units long in the frame the gun fires, bent by a random spread (crandom × the spread, each way) for each bullet or pellet, and fire_rail traces 8192 units and keeps tracing past every monster or player it hits, damaging each. The blaster, grenades, and rockets launch entities that travel: the player's blaster bolt at 1000 units/s, the launcher's grenade at 600, and the rocket at 650.game/g_weapon.c L152–165game/g_weapon.c L667–689game/g_weapon.c L277–295game/p_weapon.c L1014game/p_weapon.c L1151game/p_weapon.c L1213game/p_weapon.c L1266game/p_weapon.c L728game/g_weapon.c L620–629game/p_weapon.c L783game/p_weapon.c L832Code
A Quake II rocket's direct hit does 100 + (int)(random() * 20.0) damage, 100 to 119, the roll made when it is fired; the explosion then does radius damage to everything else within 120 units, the rocket's 120 less half the distance from the explosion to the center of the target's box, and the target hit directly takes no splash. A quad damage multiplies both by 4. The railgun's damage is a constant, 150 in single player and 100 in deathmatch.game/p_weapon.c L767–774game/g_weapon.c L589–607game/g_combat.c L554–572game/g_utils.c L94–95game/p_weapon.c L1310–1318Code
Quake II's radius damage halves the points for the entity that caused it, so a player takes half splash from their own rocket or grenade, and T_Damage pushes a player who hurt themselves with 1600 × knockback / mass instead of 500 ×, commented "the rocket jump hack...". The player's mass is 200, so a self-inflicted push is 8 units/s per point against 2.5 from anyone else, and the radius damage passes its points as the knockback. Computed: a rocket exploding on the floor directly under a standing player, 28 units below the center of the player's box, does 120 − 14 = 106, halved to 53, which adds 424 units/s upward, against a jump's 270.game/g_combat.c L564–572game/g_combat.c L436–446game/p_client.c L1099–1100game/p_client.c L1170Code
On Easy (skill 0) outside deathmatch, Quake II's T_Damage halves the damage a player takes, to no less than 1; the knockback is worked out separately and isn't halved. Levels also pick their entities by skill: an entity flagged not-easy, not-medium, or not-hard is removed at load on that skill, with Nightmare (3) counted as hard.game/g_combat.c L404–410game/g_combat.c L428–446game/g_spawn.c L585–593Code
Quake II's T_Damage doubles the damage a player does to a living monster that has no enemy yet, commented "bonus damage for suprising a monster", unless the damage is radius damage; the doubling comes after Easy's halving, which applies only to players.game/g_combat.c L421–423Code
In the four Quake II monsters read, a flinch is a cooldown rather than a roll: the soldier's, infantry's, and gunner's pain functions play a pain animation unless one started within the last 3 seconds (pain_debounce_time), choosing which at random (soldier, infantry) or by the damage (gunner), and on Nightmare (skill 3) they return before the animation. The soldier has an exception both ways: knocked upward faster than 100, it switches to a fourth pain animation even within the cooldown (if already in one of the other three) and even on Nightmare. On Nightmare the cooldown is 5 seconds, not 3: T_Damage resets it to 5 after each hit that calls the pain function. The tank adds a roll: it ignores hits of 10 or less, and flinches from 11 to 30 only when random() is at most 0.2; on hard and Nightmare it doesn't flinch during two of its attacks.game/m_soldier.c L417–450game/m_infantry.c L222–230game/m_gunner.c L288–302game/m_tank.c L293–312game/g_combat.c L506–514Code
When a monster survives damage from another monster, Quake II's M_ReactToDamage makes the attacker its enemy if both move the same way (walking, flying, or swimming), their class names differ, and the attacker isn't a tank, super tank, Makron, or Jorg; failing that, it fights back only if the attacker was targeting it, and otherwise takes on the attacker's enemy, unless that enemy is itself. Nothing happens when it hurt itself or the attacker is already its enemy. A player it was chasing is kept as the old enemy. Quake's rule, in the version 1.01 QuakeC of id's Quake-Tools release, is simpler: a monster turns on any attacker of a different class, and soldiers turn on each other too.game/g_combat.c L295–301game/g_combat.c L335–367game/g_combat.c L506–508Code
A Quake II weapon pickup adds the weapon to the player's inventory, which keeps every weapon taken, and gives that weapon's ammo with it unless the item carries the DROPPED_ITEM flag. The player switches to it only when it is the first of its kind carried, and in deathmatch only while the blaster is in hand. In coop, or in deathmatch with weapons-stay set, a player who already has the weapon can't take a placed one. A placed weapon picked up in deathmatch stays where it is with weapons-stay set and otherwise respawns after 30 seconds, and in coop it stays; a weapon flagged DROPPED_PLAYER_ITEM, which a dying player's weapon is, gives its ammo but neither stays nor respawns.game/p_weapon.c L125–160game/g_items.c L814–819game/p_client.c L439–441Code