Duke Nukem 3D
3D Realms' 1996 first-person shooter for DOS, built on Ken Silverman's Build engine, read through 3D Realms' 2003 GPL release of the version 1.5 source.
On this page
The atlas reads Duke Nukem 3D through the source 3D Realms released under the GPL in 2003, version 1.51,1. Much of the game’s tuning sits in its CON scripts, which the release includes; the Build engine underneath, with its hitscan trace, ships only as object files and a separately licensed source zip, so the claims here read the game code’s calls to it.
The game runs at 30 tics/s2,2. The pistol, shotgun, and chaingun are hitscan3, and each shot carries its weapon’s strength plus a small roll: strength + 0–54,4. A target’s pending damage rests at −1, so a single shot takes 1 less than it carries5. The shotgun and chaingun always spread their shots, but the pistol flies straight at a target autoaim has picked6. Autoaim turns the shot toward the nearest target within 8.4 °7 of the facing, across as well as up or down7. A pipe bomb’s blast rolls its damage in three distance bands8.
Movement adds a thrust each tic, in the air as on the ground9, against a friction of 53,200 / 65,53610 set by the CON script10. Forward and side moves are capped apart, the root of strafe-running11.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Hitscan | Hitscan beside projectiles | the pistol, shotgun, and chaingun trace a line in the call that fires them; the RPG fires a rocket sprite with a speed of its own |
| Damage formula | Base plus a roll | a gun shot carries its CON strength plus 0 to 5, less 1 at the target; a blast rolls in three distance bands of the strength |
| Autoaim | Nearest in a cone | the nearest target within 8.4° of the facing turns the shot both across and up or down |
| Running | Momentum | a thrust each tic, in the air too, against 0.812 friction from the CON's RUNNINGSPEED |
| Strafe-running | Separately capped axes | forward and side moves are capped apart at 90, so a diagonal keyboard run is 1.41 times as fast |
Every claim about this game, by concept (11)
References
- ^ abThe Duke Nukem 3D source 3D Realms released on 2003-04-01 is version 1.5, the Atomic Edition: README.TXT calls it the "v1.5 CD Version" and "the complete source code for Duke Nukem 3D version 1.5", and the CON scripts in
testdata/call themselves part of "Duke Nukem 3D version 1.5 - Atomic Edition".Code3D Realms, duke3dsource.zipHow we know
2Duke Nukem 3D (v1.5 CD Version) Source Code Release - April 1, 2003README.TXT line 2 at e75bb06 · upstream ↗ 11This is the complete source code for Duke Nukem 3D version 1.5, buildable as detailed in the next section.README.TXT line 11 at e75bb06 · upstream ↗ 5This file is part of Duke Nukem 3D version 1.5 - Atomic Editiontestdata/USER.CON line 5 at e75bb06 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abDuke Nukem 3D schedules its timer with
TS_ScheduleTaskat a rate ofTICRATE, 120, which the atlas reads as counts per second (the task manager's source isn't in the release), andfaketimerhandlerreads the player's input and queues one move everyTICSPERFRAMEcounts,TICRATE/26, which integer division makes 4;domovethingsruns once per queued move, so on that reading the game runs 30 tics a second (computed), where Doom runs 35.Code3D Realms, duke3dsource.zip · id-Software/DOOMrevisedHow we know
92#define TICRATE (120) 93#define TICSPERFRAME (TICRATE/26)
source/DUKE3D.H lines 92–93 at e75bb06 · upstream ↗ 106void timerhandler() ⋮ 108 totalclock++; ⋮ 113 TimerPtr = TS_ScheduleTask( timerhandler,TICRATE, 1, NULL );
source/GAME.C lines 106–114 at e75bb06 · upstream ↗ 56task *TS_ScheduleTask( void ( *Function )( task * ), int rate,source/TASK_MAN.H line 56 at e75bb06 · upstream ↗ 643 if ((totalclock < ototalclock+TICSPERFRAME) || (ready2send == 0)) return; 644 ototalclock += TICSPERFRAME; ⋮ 652 getinput(myconnectindex);
source/GAME.C lines 643–652 at e75bb06 · upstream ↗ 659 if (movefifoend[myconnectindex]&(movesperpacket-1)) ⋮ 663 movefifoend[myconnectindex]++; 664 return; ⋮ 673 movefifoend[myconnectindex]++;
source/GAME.C lines 659–673 at e75bb06 · upstream ↗ 7973 while (movefifoend[myconnectindex]-movefifoplc > bufferjitter) ⋮ 7978 if( domovethings() ) return 1;
source/GAME.C lines 7973–7978 at e75bb06 · upstream ↗ 121// State updates, number of tics / second. 122#define TICRATE 35
linuxdoom-1.10/doomdef.h lines 121–122 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^Duke Nukem 3D's pistol, shotgun, and chaingun are hitscan:
shoottraces each shot with the Build engine'shitscanwithin the same call and spawns aSHOTSPARK1sprite at the point hit, which carries the damage; the RPG instead spawns a rocket sprite with a velocity of 644. Doom's guns likewise trace a line withP_LineAttackin the tic they fire.Code3D Realms, duke3dsource.zip · id-Software/DOOMrevisedHow we know
481 case SHOTSPARK1: 482 case SHOTGUN: 483 case CHAINGUN:
source/PLAYER.C lines 481–483 at e75bb06 · upstream ↗ 546 hitscan(sx,sy,sz,sect, 547 sintable[(sa+512)&2047], 548 sintable[sa&2047], 549 zvel<<6,&hitsect,&hitwall,&hitspr,&hitx,&hity,&hitz,CLIPMASK1); ⋮ 559 k = EGS(hitsect,hitx,hity,hitz,SHOTSPARK1,-15,10,10,sa,0,0,i,4); 560 sprite[k].extra = *actorscrptr[atwith];
source/PLAYER.C lines 546–560 at e75bb06 · upstream ↗ 796 case RPG: ⋮ 801 vel = 644;
source/PLAYER.C lines 796–801 at e75bb06 · upstream ↗ 843 j = EGS(sect, ⋮ 846 sz-(1<<8),atwith,0,14,14,sa,vel,zvel,i,4);
source/PLAYER.C lines 843–846 at e75bb06 · upstream ↗ 2994short EGS(short whatsect,long s_x,long s_y,long s_z,short s_pn,signed char s_s,signed char s_xr,signed char s_yr,short s_a,short s_ve,long s_zv,short s_ow,signed char s_ss)source/GAME.C line 2994 at e75bb06 · upstream ↗ 3021 s->xvel = s_ve;source/GAME.C line 3021 at e75bb06 · upstream ↗ 626P_GunShot ⋮ 639 P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage);
linuxdoom-1.10/p_pspr.c lines 625–639 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abEach shot a Duke Nukem 3D player fires from the pistol, shotgun, or chaingun carries the strength its actor declares in the CON script plus
TRAND%6(0 to 5): 6 to 11 for the pistol (SHOTSPARK1), 10 to 15 for each of the shotgun's 7 pellets, and 9 to 14 for the chaingun; a monster's shot carries the strength alone. Each bullet from Doom's pistol, chaingun, or shotgun deals 5, 10, or 15.Code3D Realms, duke3dsource.zip · id-Software/DOOMHow we know
557 if(p >= 0) ⋮ 559 k = EGS(hitsect,hitx,hity,hitz,SHOTSPARK1,-15,10,10,sa,0,0,i,4); 560 sprite[k].extra = *actorscrptr[atwith]; 561 sprite[k].extra += (TRAND%6);
source/PLAYER.C lines 557–561 at e75bb06 · upstream ↗ 674 k = EGS(hitsect,hitx,hity,hitz,SHOTSPARK1,-15,24,24,sa,0,0,i,4); 675 sprite[k].extra = *actorscrptr[atwith];
source/PLAYER.C lines 674–675 at e75bb06 · upstream ↗ 849 scriptptr--; 850 parsing_actor = scriptptr; ⋮ 853 scriptptr--; 854 actorscrptr[*scriptptr] = parsing_actor; ⋮ 865 scriptptr--; ⋮ 881 *(parsing_actor+j) = *(scriptptr-1);
source/GAMEDEF.C lines 849–881 at e75bb06 · upstream ↗ 3165actor CHAINGUN CHAINGUN_WEAPON_STRENGTH enda 3166actor SHOTGUN SHOTGUN_WEAPON_STRENGTH enda
testdata/GAME.CON lines 3165–3166 at e75bb06 · upstream ↗ 3200actor SHOTSPARK1 PISTOL_WEAPON_STRENGTH WEAP2FRAMEStestdata/GAME.CON line 3200 at e75bb06 · upstream ↗ 148define PISTOL_WEAPON_STRENGTH 6testdata/USER.CON line 148 at e75bb06 · upstream ↗ 163define SHOTGUN_WEAPON_STRENGTH 10 164define CHAINGUN_WEAPON_STRENGTH 9
testdata/USER.CON lines 163–164 at e75bb06 · upstream ↗ 3647 case PISTOL_WEAPON: 3648 if( (*kb)==1) ⋮ 3650 shoot(pi,SHOTSPARK1);
source/PLAYER.C lines 3647–3650 at e75bb06 · upstream ↗ 3690 case SHOTGUN_WEAPON: ⋮ 3694 if(*kb == 4) ⋮ 3696 shoot(pi,SHOTGUN); 3697 shoot(pi,SHOTGUN); 3698 shoot(pi,SHOTGUN); 3699 shoot(pi,SHOTGUN); 3700 shoot(pi,SHOTGUN); 3701 shoot(pi,SHOTGUN); 3702 shoot(pi,SHOTGUN);
source/PLAYER.C lines 3690–3702 at e75bb06 · upstream ↗ 3759 shoot(pi,CHAINGUN);source/PLAYER.C line 3759 at e75bb06 · upstream ↗ 626P_GunShot ⋮ 633 damage = 5*(P_Random ()%3+1);
linuxdoom-1.10/p_pspr.c lines 625–639 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^A Duke Nukem 3D sprite's pending damage (
hittype[].extra) is set to −1 when the sprite is created and again each timeifhitbyweapontakes it; a shot thatcheckhitspritehandles in its default branch adds its damage to the pending total, andifhitbyweaponsubtracts the total from the target's health, so a target hit once between checks loses 1 less than the shot carries, and several hits between checks take 1 less than their sum (computed). An explosion'shitradiussets the pending damage outright for the targets it rolls for, so those lose the full roll.Code3D Realms, duke3dsource.ziprevisedHow we know
3038 hittype[i].extra = -1;source/GAME.C line 3038 at e75bb06 · upstream ↗ 3143 hittype[i].extra = -1;source/GAME.C line 3143 at e75bb06 · upstream ↗ 2329 if( sprite[i].statnum != 2 ) ⋮ 2334 hittype[i].picnum = sprite[sn].picnum; 2335 hittype[i].extra += sprite[sn].extra;
source/SECTOR.C lines 2329–2335 at e75bb06 · upstream ↗ 994short ifhitbyweapon(short sn) ⋮ 999 if( hittype[sn].extra >= 0 ) ⋮ 1018 npc->extra -= hittype[sn].extra;
source/ACTORS.C lines 994–1018 at e75bb06 · upstream ↗ 1063 npc->extra -= hittype[sn].extra; ⋮ 1068 hittype[sn].extra = -1; 1069 return hittype[sn].picnum; ⋮ 1073 hittype[sn].extra = -1;
source/ACTORS.C lines 1063–1073 at e75bb06 · upstream ↗ 538 if ( d < r/3 ) ⋮ 540 if(hp4 == hp3) hp4++; 541 hittype[j].extra = hp3 + (TRAND%(hp4-hp3));
source/ACTORS.C lines 538–541 at e75bb06 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^A Duke Nukem 3D player's shotgun and chaingun turn every shot by
16-(TRAND&31), −15 to +16 of the 2,048 angle units in a turn (up to about 2.8°, computed), and add128-(TRAND&255)to its vertical speed, with or without an autoaim target; the pistol does both only when autoaim found none, so a pistol shot at an autoaim target flies straight to it. Doom's shotgun turns each of its 7 pellets by up to about 5.6°.Code3D Realms, duke3dsource.zip · id-Software/DOOMHow we know
489 j = aim( s, AUTO_AIM_ANGLE );source/PLAYER.C line 489 at e75bb06 · upstream ↗ 511 if(atwith == SHOTSPARK1) ⋮ 513 if(j == -1) ⋮ 515 sa += 16-(TRAND&31); 516 zvel = (100-ps[p].horiz-ps[p].horizoff)<<5; 517 zvel += 128-(TRAND&255); ⋮ 520 else ⋮ 522 sa += 16-(TRAND&31); 523 if(j == -1) zvel = (100-ps[p].horiz-ps[p].horizoff)<<5; 524 zvel += 128-(TRAND&255);
source/PLAYER.C lines 511–525 at e75bb06 · upstream ↗ 546 hitscan(sx,sy,sz,sect, 547 sintable[(sa+512)&2047], 548 sintable[sa&2047],
source/PLAYER.C lines 546–548 at e75bb06 · upstream ↗ 627( mobj_t* mo, 628 boolean accurate ) ⋮ 636 if (!accurate) 637 angle += (P_Random()-P_Random())<<18;
linuxdoom-1.10/p_pspr.c lines 626–639 at a77dfb9 · upstream ↗ 684 P_BulletSlope (player->mo); ⋮ 686 for (i=0 ; i<7 ; i++) 687 P_GunShot (player->mo, false);
linuxdoom-1.10/p_pspr.c lines 684–687 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abWhen a Duke Nukem 3D player fires the pistol, shotgun, or chaingun,
aimlooks for a target withinAUTO_AIM_ANGLE, 48 of 2,048 angle units (about 8.4°, computed), to either side of the facing; of those in sight, more than 512 along the facing, and with a height difference over that distance (scaled by 10) within 100 of the view's pitch, it takes the nearest along the facing, searching the sprite lists 10, 13, 1, and 2 in that order and stopping at the first list with a match, and skipping fellow players in co-op. The shot then turns to the target's angle (getangle) and takes the slope to a point((xrepeat × tile height) << 1) + (5 << 8)above the target's z. Doom'sP_BulletSlopetraces only straight ahead and 5.625° to each side, and its bullet keeps the player's facing.Code3D Realms, duke3dsource.zip · id-Software/DOOMHow we know
62#define AUTO_AIM_ANGLE 48source/DUKE3D.H line 62 at e75bb06 · upstream ↗ 204short aim(spritetype *s,short aang) ⋮ 208 short aimstats[] = {10,13,1,2}; ⋮ 222 dx1 = sintable[(a+512-aang)&2047]; 223 dy1 = sintable[(a-aang)&2047]; 224 dx2 = sintable[(a+512+aang)&2047]; 225 dy2 = sintable[(a+aang)&2047];
source/PLAYER.C lines 204–227 at e75bb06 · upstream ↗ 230 for(k=0;k<4;k++) ⋮ 232 if( j >= 0 ) 233 break; ⋮ 240 if( PN == APLAYER && ⋮ 242 ud.coop == 1 && 243 s->picnum == APLAYER && 244 s != &sprite[i]) 245 continue;
source/PLAYER.C lines 230–246 at e75bb06 · upstream ↗ 273 if( (dy1*xv) <= (dx1*yv) ) 274 if( ( dy2*xv ) >= (dx2*yv) ) ⋮ 276 sdist = mulscale(dx3,xv,14) + mulscale(dy3,yv,14); 277 if( sdist > 512 && sdist < smax ) ⋮ 279 if(s->picnum == APLAYER) 280 a = (klabs(scale(SZ-s->z,10,sdist)-(ps[s->yvel].horiz+ps[s->yvel].horizoff-100)) < 100); ⋮ 287 if( a && cans ) ⋮ 289 smax = sdist; 290 j = i;
source/PLAYER.C lines 273–291 at e75bb06 · upstream ↗ 489 j = aim( s, AUTO_AIM_ANGLE ); 490 if(j >= 0) ⋮ 492 dal = ((sprite[j].xrepeat*tilesizy[sprite[j].picnum])<<1)+(5<<8); ⋮ 507 zvel = ( ( sprite[j].z-sz-dal )<<8 ) / ldist(&sprite[ps[p].i], &sprite[j]) ; 508 sa = getangle(sprite[j].x-sx,sprite[j].y-sy);
source/PLAYER.C lines 489–508 at e75bb06 · upstream ↗ 601void P_BulletSlope (mobj_t* mo) ⋮ 606 an = mo->angle; 607 bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); ⋮ 611 an += 1<<26; 612 bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); ⋮ 615 an -= 2<<26; 616 bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
linuxdoom-1.10/p_pspr.c lines 601–619 at a77dfb9 · upstream ↗ 627( mobj_t* mo, 628 boolean accurate ) ⋮ 634 angle = mo->angle; ⋮ 639 P_LineAttack (mo, angle, MISSILERANGE, bulletslope, damage);
linuxdoom-1.10/p_pspr.c lines 626–639 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^A Duke Nukem 3D pipe bomb that goes off passes its strength, 140 (
HANDBOMB_WEAPON_STRENGTH), tohitradiuswith the radiusPIPEBOMBRADIUS, 2,500; each sprite in lists 1, 6, 10, or 12 (not flammable) withextraof 0 or more that is a tripbomb, a monster (badguy), a QUEBALL, a STRIPEBALL, a DUKELYINGDEAD, or solid (cstat&257), within thatdistand in sight of the blast, takes 105 to 139 inside a third of the radius, 70 to 104 inside two thirds, and 35 to 69 beyond: three quarters, a half, or a quarter of the strength plusTRANDmodulo the next band's gap, 35 (computed). A monster in sprite list 2, which the hit wakes into list 1, goes throughcheckhitspriteinstead unless a sight test at a random height fails, and loses 139 at any distance in the radius, the bomb's 140 added to its pending −1; a bomb set off by a hit first loses that hit's damage from its strength. A Doom rocket's blast falls off linearly, 128 minus the distance.Code3D Realms, duke3dsource.zip · id-Software/DOOMrevisedHow we know
127define PIPEBOMBRADIUS 2500testdata/USER.CON line 127 at e75bb06 · upstream ↗ 149define HANDBOMB_WEAPON_STRENGTH 140testdata/USER.CON line 149 at e75bb06 · upstream ↗ 3168actor HEAVYHBOMB HANDBOMB_WEAPON_STRENGTH endatestdata/GAME.CON line 3168 at e75bb06 · upstream ↗ 1358 case 9:pipebombblastradius = *scriptptr;break;source/GAMEDEF.C line 1358 at e75bb06 · upstream ↗ 3048 if( actorscrptr[s_pn] ) ⋮ 3050 s->extra = *actorscrptr[s_pn];
source/GAME.C lines 3048–3050 at e75bb06 · upstream ↗ 3989 if(t[3] == 0 ) ⋮ 3991 j = ifhitbyweapon(i); 3992 if(j >= 0) ⋮ 3994 t[3] = 1; ⋮ 3998 goto DETONATEB;
source/ACTORS.C lines 3988–3998 at e75bb06 · upstream ↗ 4076 DETONATEB: ⋮ 4084 x = s->extra; ⋮ 4088 case HEAVYHBOMB: m = pipebombblastradius;break; ⋮ 4093 hitradius( i, m,x>>2,x>>1,x-(x>>2),x);
source/ACTORS.C lines 4076–4093 at e75bb06 · upstream ↗ 486 q = -(16<<8)+(TRAND&((32<<8)-1)); ⋮ 496 if( x == 0 || x >= 5 || AFLAMABLE(sj->picnum) ) ⋮ 499 if( dist( s, sj ) < r ) ⋮ 501 if( badguy(sj) && !cansee( sj->x, sj->y,sj->z+q, sj->sectnum, s->x, s->y, s->z+q, s->sectnum) ) 502 goto BOLT; 503 checkhitsprite( j, i ); ⋮ 506 else if( sj->extra >= 0 && sj != s && ( sj->picnum == TRIPBOMB || badguy(sj) || sj->picnum == QUEBALL || sj->picnum == STRIPEBALL || (sj->cstat&257) || sj->picnum == DUKELYINGDEAD ) )
source/ACTORS.C lines 486–506 at e75bb06 · upstream ↗ 433 char statlist[] = {0,1,6,10,12,2,5};source/ACTORS.C line 433 at e75bb06 · upstream ↗ 519 if(sj->picnum == APLAYER) sj->z -= PHEIGHT; 520 d = dist( s, sj ); 521 if(sj->picnum == APLAYER) sj->z += PHEIGHT; ⋮ 523 if ( d < r && cansee( sj->x, sj->y, sj->z-(8<<8), sj->sectnum, s->x, s->y, s->z-(12<<8), s->sectnum) )
source/ACTORS.C lines 519–523 at e75bb06 · upstream ↗ 536 if(s->picnum != SHRINKSPARK) ⋮ 538 if ( d < r/3 ) ⋮ 540 if(hp4 == hp3) hp4++; 541 hittype[j].extra = hp3 + (TRAND%(hp4-hp3)); ⋮ 543 else if ( d < 2*r/3 ) ⋮ 545 if(hp3 == hp2) hp3++; 546 hittype[j].extra = hp2 + (TRAND%(hp3-hp2)); ⋮ 548 else if ( d < r ) ⋮ 550 if(hp2 == hp1) hp2++; 551 hittype[j].extra = hp1 + (TRAND%(hp2-hp1));
source/ACTORS.C lines 536–552 at e75bb06 · upstream ↗ 2282 if( badguy(&sprite[i]) == 1) ⋮ 2321 if(sprite[i].statnum == 2) ⋮ 2323 changespritestat(i,1); 2324 hittype[i].timetosleep = SLEEPTIME; ⋮ 2329 if( sprite[i].statnum != 2 ) ⋮ 2335 hittype[i].extra += sprite[sn].extra;
source/SECTOR.C lines 2282–2335 at e75bb06 · upstream ↗ 1598void A_Explode (mobj_t* thingy) ⋮ 1600 P_RadiusAttack ( thingy, thingy->target, 128 );
linuxdoom-1.10/p_enemy.c lines 1598–1600 at a77dfb9 · upstream ↗ 1182 dist = dx>dy ? dx : dy; 1183 dist = (dist - thing->radius) >> FRACBITS; ⋮ 1194 P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist);
linuxdoom-1.10/p_map.c lines 1180–1194 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^A Duke Nukem 3D keyboard sets the forward and side moves to 40 walking or 80 running (
NORMALKEYMOVE), each clamped apart to ±90 (MAXVEL,MAXSVEL);getinputturns the pair by the facing, and each ticprocessinputadds it to the player's velocity timesTICSPERFRAME(4) and 64, doubled while steroids last and the jetpack is off, in the air as on the ground. A hard landing and a few other actions zero the velocity instead. Doom thrusts only on the floor, with moves of 25 or 50 forward and 24 or 40 sideways.Code3D Realms, duke3dsource.zip · id-Software/DOOMHow we know
1771#define NORMALKEYMOVE 40 1772#define MAXVEL ((NORMALKEYMOVE*2)+10) 1773#define MAXSVEL ((NORMALKEYMOVE*2)+10)
source/PLAYER.C lines 1771–1773 at e75bb06 · upstream ↗ 1914 if (running) ⋮ 1916 turnamount = NORMALTURN<<1; 1917 keymove = NORMALKEYMOVE<<1; ⋮ 1919 else ⋮ 1921 turnamount = NORMALTURN; 1922 keymove = NORMALKEYMOVE;
source/PLAYER.C lines 1913–1923 at e75bb06 · upstream ↗ 1974 if ( BUTTON(gamefunc_Move_Forward) ) 1975 vel += keymove; ⋮ 1980 if(vel < -MAXVEL) vel = -MAXVEL; 1981 if(vel > MAXVEL) vel = MAXVEL; 1982 if(svel < -MAXSVEL) svel = -MAXSVEL; 1983 if(svel > MAXSVEL) svel = MAXSVEL;
source/PLAYER.C lines 1974–1983 at e75bb06 · upstream ↗ 2004 momx = mulscale9(vel,sintable[(daang+2560)&2047]); 2005 momy = mulscale9(vel,sintable[(daang+2048)&2047]); ⋮ 2007 momx += mulscale9(svel,sintable[(daang+2048)&2047]); 2008 momy += mulscale9(svel,sintable[(daang+1536)&2047]); ⋮ 2013 loc.fvel = momx; 2014 loc.svel = momy;
source/PLAYER.C lines 2004–2014 at e75bb06 · upstream ↗ 2603 doubvel = TICSPERFRAME;source/PLAYER.C line 2603 at e75bb06 · upstream ↗ 3002 if ( p->fist_incs || 3003 p->transporter_hold > 2 || 3004 p->hard_landing || 3005 p->access_incs > 0 || 3006 p->knee_incs > 0 || ⋮ 3011 doubvel = 0; 3012 p->posxv = 0; 3013 p->posyv = 0;
source/PLAYER.C lines 3002–3013 at e75bb06 · upstream ↗ 3117 if ( p->posxv || p->posyv || sync[snum].fvel || sync[snum].svel )source/PLAYER.C line 3117 at e75bb06 · upstream ↗ 3156 if(p->jetpack_on == 0 && p->steroids_amount > 0 && p->steroids_amount < 400) 3157 doubvel <<= 1; ⋮ 3159 p->posxv += ((sync[snum].fvel*doubvel)<<6); 3160 p->posyv += ((sync[snum].svel*doubvel)<<6);
source/PLAYER.C lines 3156–3160 at e75bb06 · upstream ↗ 156 // Do not let the player control movement 157 // if not onground. 158 onground = (player->mo->z <= player->mo->floorz); ⋮ 160 if (cmd->forwardmove && onground) 161 P_Thrust (player, player->mo->angle, cmd->forwardmove*2048);
linuxdoom-1.10/p_user.c lines 156–164 at a77dfb9 · upstream ↗ 175fixed_t forwardmove[2] = {0x19, 0x32}; 176fixed_t sidemove[2] = {0x18, 0x28};
linuxdoom-1.10/g_game.c lines 175–176 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abAfter the thrust, Duke Nukem 3D multiplies the player's velocity each tic by
dukefriction, which the CON'sgamestartupsets fromRUNNINGSPEED, 53,200 of 65,536 (0.812; the C default is0xcc00, 0.797): 0x2000 less when kicking or crouching on the ground, 0x1400 less underwater, and three quarters of it again while shrunk; the velocity drops to 0 once both axes are under 2,048. A steady run moves 4.31 times the per-tic thrust (0.812 / 0.188, computed), and a released run falls under half its speed within 4 tics (computed). Doom keeps 0.90625 of its momentum each tic.Code3D Realms, duke3dsource.zip · id-Software/DOOMHow we know
156long myhorizbak[MOVEFIFOSIZ],dukefriction = 0xcc00, show_shareware;source/GLOBAL.C line 156 at e75bb06 · upstream ↗ 112define RUNNINGSPEED 53200testdata/USER.CON line 112 at e75bb06 · upstream ↗ 134gamestartup DEFAULTVISIBILITY GENERICIMPACTDAMAGE MAXPLAYERHEALTH 135 STARTARMORHEALTH RESPAWNACTORTIME RESPAWNITEMTIME 136 RUNNINGSPEED GRAVITATIONALCONSTANT RPGBLASTRADIUS
testdata/USER.CON lines 134–136 at e75bb06 · upstream ↗ 105 "gamestartup", // 60source/GAMEDEF.C line 105 at e75bb06 · upstream ↗ 1328 case 60: 1329 j = 0; 1330 while(j < 30) ⋮ 1339 break; ⋮ 1342 break; ⋮ 1345 break; ⋮ 1348 break; ⋮ 1353 case 6: 1354 dukefriction = *scriptptr;break;
source/GAMEDEF.C lines 1328–1354 at e75bb06 · upstream ↗ 1833 loc.bits |= BUTTON(gamefunc_Crouch)<<1;source/PLAYER.C line 1833 at e75bb06 · upstream ↗ 3162 if( ( p->curr_weapon == KNEE_WEAPON && *kb > 10 && p->on_ground ) || ( p->on_ground && (sb_snum&2) ) ) ⋮ 3164 p->posxv = mulscale(p->posxv,dukefriction-0x2000,16); ⋮ 3169 if(psectlotag == 2) ⋮ 3171 p->posxv = mulscale(p->posxv,dukefriction-0x1400,16); ⋮ 3176 p->posxv = mulscale(p->posxv,dukefriction,16); ⋮ 3181 if( abs(p->posxv) < 2048 && abs(p->posyv) < 2048 ) 3182 p->posxv = p->posyv = 0; ⋮ 3184 if( shrunk ) ⋮ 3186 p->posxv = 3187 mulscale16(p->posxv,dukefriction-(dukefriction>>1)+(dukefriction>>2)); 3188 p->posyv =
source/PLAYER.C lines 3162–3190 at e75bb06 · upstream ↗ 3193 HORIZONLY: ⋮ 3204 p->posx += p->posxv>>14; 3205 p->posy += p->posyv>>14;
source/PLAYER.C lines 3193–3205 at e75bb06 · upstream ↗ 111#define STOPSPEED 0x1000 112#define FRICTION 0xe800
linuxdoom-1.10/p_mobj.c lines 111–112 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^Duke Nukem 3D clamps the forward and side moves apart and adds them as perpendicular pushes, so running forward (80) while running sideways (80) gives √2 ≈ 1.41 times the forward run alone (computed); holding the strafe modifier with a turn key and a strafe key together reaches the side move's cap of 90, about 1.51 times. Doom's diagonal run, 50 forward and 40 sideways, is 1.28 times its forward run.Code3D Realms, duke3dsource.zip · id-Software/DOOM
How we know
1925 if (BUTTON(gamefunc_Strafe)) ⋮ 1927 if ( BUTTON(gamefunc_Turn_Left)) ⋮ 1929 svel -= -keymove; ⋮ 1931 if ( BUTTON(gamefunc_Turn_Right)) ⋮ 1933 svel -= keymove;
source/PLAYER.C lines 1925–1934 at e75bb06 · upstream ↗ 1968 if ( BUTTON( gamefunc_Strafe_Left ) ) 1969 svel += keymove; ⋮ 1974 if ( BUTTON(gamefunc_Move_Forward) ) 1975 vel += keymove; ⋮ 1981 if(vel > MAXVEL) vel = MAXVEL; ⋮ 1983 if(svel > MAXSVEL) svel = MAXSVEL;
source/PLAYER.C lines 1965–1983 at e75bb06 · upstream ↗ 2004 momx = mulscale9(vel,sintable[(daang+2560)&2047]); 2005 momy = mulscale9(vel,sintable[(daang+2048)&2047]); ⋮ 2007 momx += mulscale9(svel,sintable[(daang+2048)&2047]); 2008 momy += mulscale9(svel,sintable[(daang+1536)&2047]);
source/PLAYER.C lines 2004–2008 at e75bb06 · upstream ↗ 160 if (cmd->forwardmove && onground) 161 P_Thrust (player, player->mo->angle, cmd->forwardmove*2048); ⋮ 163 if (cmd->sidemove && onground) 164 P_Thrust (player, player->mo->angle-ANG90, cmd->sidemove*2048);
linuxdoom-1.10/p_user.c lines 160–164 at a77dfb9 · upstream ↗ 175fixed_t forwardmove[2] = {0x19, 0x32}; 176fixed_t sidemove[2] = {0x18, 0x28};
linuxdoom-1.10/g_game.c lines 175–176 at a77dfb9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
Sources
Code
- Realms, 3D. 2003. “Duke Nukem 3D: 3D Realms' source release (version 1.5, 2003).” Commit e75bb06. commercial-game-sources/duke_nukem_3d @ e75bb06 · licence, all uses
- Software, id. 2024. “DOOM: the Linux source release (id-Software/DOOM, linuxdoom-1.10).” Commit a77dfb9. id-Software/DOOM @ a77dfb9 · licence, all uses