quake2ts 0.0.297 → 0.0.299
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/cgame/dist/index.cjs +55 -2
- package/packages/cgame/dist/index.cjs.map +1 -1
- package/packages/cgame/dist/index.d.cts +7 -0
- package/packages/cgame/dist/index.d.ts +7 -0
- package/packages/cgame/dist/index.js +56 -3
- package/packages/cgame/dist/index.js.map +1 -1
- package/packages/client/dist/browser/index.global.js +13 -13
- package/packages/client/dist/browser/index.global.js.map +1 -1
- package/packages/client/dist/cjs/index.cjs +76 -19
- package/packages/client/dist/cjs/index.cjs.map +1 -1
- package/packages/client/dist/esm/index.js +71 -14
- package/packages/client/dist/esm/index.js.map +1 -1
- package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/client/dist/types/cgameBridge.d.ts.map +1 -1
- package/packages/client/dist/types/input/controller.d.ts +1 -0
- package/packages/client/dist/types/input/controller.d.ts.map +1 -1
- package/packages/client/dist/types/net/connection.d.ts +3 -0
- package/packages/client/dist/types/net/connection.d.ts.map +1 -1
- package/packages/engine/dist/browser/index.global.js +8 -8
- package/packages/engine/dist/browser/index.global.js.map +1 -1
- package/packages/engine/dist/cjs/index.cjs.map +1 -1
- package/packages/engine/dist/esm/index.js.map +1 -1
- package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/game/dist/browser/index.global.js +4 -4
- package/packages/game/dist/browser/index.global.js.map +1 -1
- package/packages/game/dist/cjs/index.cjs +67 -20
- package/packages/game/dist/cjs/index.cjs.map +1 -1
- package/packages/game/dist/esm/index.js +67 -20
- package/packages/game/dist/esm/index.js.map +1 -1
- package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/game/dist/types/ai/movement.d.ts.map +1 -1
- package/packages/server/dist/index.cjs +9 -2
- package/packages/server/dist/index.js +9 -2
- package/packages/shared/dist/browser/index.global.js +1 -1
- package/packages/shared/dist/browser/index.global.js.map +1 -1
- package/packages/shared/dist/cjs/index.cjs +1342 -1038
- package/packages/shared/dist/cjs/index.cjs.map +1 -1
- package/packages/shared/dist/esm/index.js +1340 -1038
- package/packages/shared/dist/esm/index.js.map +1 -1
- package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/shared/dist/types/pmove/jump.d.ts +2 -0
- package/packages/shared/dist/types/pmove/jump.d.ts.map +1 -1
- package/packages/shared/dist/types/pmove/move.d.ts +20 -0
- package/packages/shared/dist/types/pmove/move.d.ts.map +1 -1
- package/packages/shared/dist/types/pmove/pmove.d.ts +5 -1
- package/packages/shared/dist/types/pmove/pmove.d.ts.map +1 -1
- package/packages/shared/dist/types/pmove/types.d.ts +25 -1
- package/packages/shared/dist/types/pmove/types.d.ts.map +1 -1
- package/packages/shared/dist/types/protocol/usercmd.d.ts +3 -0
- package/packages/shared/dist/types/protocol/usercmd.d.ts.map +1 -1
- package/packages/tools/dist/tsconfig.tsbuildinfo +1 -1
|
@@ -1842,206 +1842,301 @@ var PmType = /* @__PURE__ */ ((PmType2) => {
|
|
|
1842
1842
|
PmType2[PmType2["Freeze"] = 6] = "Freeze";
|
|
1843
1843
|
return PmType2;
|
|
1844
1844
|
})(PmType || {});
|
|
1845
|
-
var PlayerButton = /* @__PURE__ */ ((
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
return
|
|
1845
|
+
var PlayerButton = /* @__PURE__ */ ((PlayerButton3) => {
|
|
1846
|
+
PlayerButton3[PlayerButton3["None"] = 0] = "None";
|
|
1847
|
+
PlayerButton3[PlayerButton3["Attack"] = 1] = "Attack";
|
|
1848
|
+
PlayerButton3[PlayerButton3["Use"] = 2] = "Use";
|
|
1849
|
+
PlayerButton3[PlayerButton3["Holster"] = 4] = "Holster";
|
|
1850
|
+
PlayerButton3[PlayerButton3["Jump"] = 8] = "Jump";
|
|
1851
|
+
PlayerButton3[PlayerButton3["Crouch"] = 16] = "Crouch";
|
|
1852
|
+
PlayerButton3[PlayerButton3["Any"] = 128] = "Any";
|
|
1853
|
+
return PlayerButton3;
|
|
1854
1854
|
})(PlayerButton || {});
|
|
1855
1855
|
|
|
1856
|
-
// src/pmove/
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
pmFriction,
|
|
1866
|
-
pmStopSpeed,
|
|
1867
|
-
pmWaterFriction
|
|
1868
|
-
} = params;
|
|
1869
|
-
const speed = lengthVec3(velocity);
|
|
1870
|
-
if (speed < 1) {
|
|
1871
|
-
return { x: 0, y: 0, z: velocity.z };
|
|
1856
|
+
// src/pmove/jump.ts
|
|
1857
|
+
var DEFAULT_JUMP_HEIGHT = 270;
|
|
1858
|
+
function hasButton(buttons, button) {
|
|
1859
|
+
return (buttons & button) !== 0;
|
|
1860
|
+
}
|
|
1861
|
+
function checkJump(params) {
|
|
1862
|
+
const { pmFlags, pmType, buttons, waterlevel, onGround, velocity, origin, jumpHeight = DEFAULT_JUMP_HEIGHT } = params;
|
|
1863
|
+
if (pmFlags & 16 /* TimeLand */) {
|
|
1864
|
+
return { pmFlags, onGround, velocity, origin, jumpSound: false, jumped: false };
|
|
1872
1865
|
}
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1866
|
+
const holdingJump = hasButton(buttons, 8 /* Jump */);
|
|
1867
|
+
let nextFlags = pmFlags;
|
|
1868
|
+
let nextOnGround = onGround;
|
|
1869
|
+
let jumpSound = false;
|
|
1870
|
+
let jumped = false;
|
|
1871
|
+
let nextVelocity = velocity;
|
|
1872
|
+
let nextOrigin = origin;
|
|
1873
|
+
if (!holdingJump) {
|
|
1874
|
+
nextFlags = removePmFlag(nextFlags, 2 /* JumpHeld */);
|
|
1875
|
+
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, origin: nextOrigin, jumpSound, jumped };
|
|
1878
1876
|
}
|
|
1879
|
-
if (
|
|
1880
|
-
|
|
1877
|
+
if (hasPmJumpHold(nextFlags)) {
|
|
1878
|
+
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, origin: nextOrigin, jumpSound, jumped };
|
|
1881
1879
|
}
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
newspeed = 0;
|
|
1880
|
+
if (pmType === 4 /* Dead */) {
|
|
1881
|
+
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, origin: nextOrigin, jumpSound, jumped };
|
|
1885
1882
|
}
|
|
1886
|
-
if (
|
|
1887
|
-
|
|
1883
|
+
if (waterlevel >= 2 /* Waist */) {
|
|
1884
|
+
nextOnGround = false;
|
|
1885
|
+
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, origin: nextOrigin, jumpSound, jumped };
|
|
1888
1886
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1887
|
+
if (!nextOnGround) {
|
|
1888
|
+
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, origin: nextOrigin, jumpSound, jumped };
|
|
1889
|
+
}
|
|
1890
|
+
nextFlags = addPmFlag(nextFlags, 2 /* JumpHeld */);
|
|
1891
|
+
nextFlags = removePmFlag(nextFlags, 4 /* OnGround */);
|
|
1892
|
+
nextOnGround = false;
|
|
1893
|
+
jumpSound = true;
|
|
1894
|
+
jumped = true;
|
|
1895
|
+
const z = velocity.z + jumpHeight;
|
|
1896
|
+
const finalZ = z < jumpHeight ? jumpHeight : z;
|
|
1897
|
+
nextVelocity = { ...velocity, z: finalZ };
|
|
1898
|
+
nextOrigin = { ...origin, z: origin.z + 1 };
|
|
1899
|
+
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, origin: nextOrigin, jumpSound, jumped };
|
|
1891
1900
|
}
|
|
1892
|
-
function
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1901
|
+
function hasPmJumpHold(flags) {
|
|
1902
|
+
return (flags & 2 /* JumpHeld */) !== 0;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
// src/pmove/currents.ts
|
|
1906
|
+
var DEFAULT_GROUND_CURRENT_SCALE = 100;
|
|
1907
|
+
var DEFAULT_FORWARD_LADDER_CLAMP = 200;
|
|
1908
|
+
var DEFAULT_SIDE_LADDER_CLAMP = 150;
|
|
1909
|
+
var LADDER_HORIZONTAL_CAP = 25;
|
|
1910
|
+
var LADDER_ASCEND_PITCH_THRESHOLD = 15;
|
|
1911
|
+
var LADDER_TRACE_DISTANCE = 1;
|
|
1912
|
+
var UP_VECTOR = { x: 0, y: 0, z: 1 };
|
|
1913
|
+
var DEFAULT_TRACE = (_, end) => ({
|
|
1914
|
+
fraction: 1,
|
|
1915
|
+
endpos: end,
|
|
1916
|
+
allsolid: false,
|
|
1917
|
+
startsolid: false
|
|
1918
|
+
});
|
|
1919
|
+
function currentVectorFromContents(contents) {
|
|
1920
|
+
let x = 0;
|
|
1921
|
+
let y = 0;
|
|
1922
|
+
let z = 0;
|
|
1923
|
+
if (contents & CONTENTS_CURRENT_0) {
|
|
1924
|
+
x += 1;
|
|
1898
1925
|
}
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
accelSpeed = addSpeed;
|
|
1926
|
+
if (contents & CONTENTS_CURRENT_90) {
|
|
1927
|
+
y += 1;
|
|
1902
1928
|
}
|
|
1903
|
-
|
|
1904
|
-
x
|
|
1905
|
-
y: velocity.y + wishdir.y * accelSpeed,
|
|
1906
|
-
z: velocity.z + wishdir.z * accelSpeed
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
function applyPmoveAirAccelerate(params) {
|
|
1910
|
-
const { velocity, wishdir, wishspeed, accel, frametime } = params;
|
|
1911
|
-
const wishspd = Math.min(wishspeed, 30);
|
|
1912
|
-
const currentSpeed = dotVec3(velocity, wishdir);
|
|
1913
|
-
const addSpeed = wishspd - currentSpeed;
|
|
1914
|
-
if (addSpeed <= 0) {
|
|
1915
|
-
return velocity;
|
|
1929
|
+
if (contents & CONTENTS_CURRENT_180) {
|
|
1930
|
+
x -= 1;
|
|
1916
1931
|
}
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
accelSpeed = addSpeed;
|
|
1932
|
+
if (contents & CONTENTS_CURRENT_270) {
|
|
1933
|
+
y -= 1;
|
|
1920
1934
|
}
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
y: velocity.y + wishdir.y * accelSpeed,
|
|
1924
|
-
z: velocity.z + wishdir.z * accelSpeed
|
|
1925
|
-
};
|
|
1926
|
-
}
|
|
1927
|
-
function pmoveCmdScale(cmd, maxSpeed) {
|
|
1928
|
-
const forward = Math.abs(cmd.forwardmove);
|
|
1929
|
-
const side = Math.abs(cmd.sidemove);
|
|
1930
|
-
const up = Math.abs(cmd.upmove);
|
|
1931
|
-
const max = Math.max(forward, side, up);
|
|
1932
|
-
if (max === 0) {
|
|
1933
|
-
return 0;
|
|
1935
|
+
if (contents & CONTENTS_CURRENT_UP) {
|
|
1936
|
+
z += 1;
|
|
1934
1937
|
}
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
}
|
|
1938
|
-
function buildAirGroundWish(params) {
|
|
1939
|
-
const { forward, right, cmd, maxSpeed } = params;
|
|
1940
|
-
let wishvel = {
|
|
1941
|
-
x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
|
|
1942
|
-
y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
|
|
1943
|
-
z: 0
|
|
1944
|
-
};
|
|
1945
|
-
let wishspeed = lengthVec3(wishvel);
|
|
1946
|
-
if (wishspeed > maxSpeed) {
|
|
1947
|
-
const scale = maxSpeed / wishspeed;
|
|
1948
|
-
wishvel = scaleVec3(wishvel, scale);
|
|
1949
|
-
wishspeed = maxSpeed;
|
|
1938
|
+
if (contents & CONTENTS_CURRENT_DOWN) {
|
|
1939
|
+
z -= 1;
|
|
1950
1940
|
}
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
};
|
|
1941
|
+
if (x === 0 && y === 0 && z === 0) {
|
|
1942
|
+
return ZERO_VEC3;
|
|
1943
|
+
}
|
|
1944
|
+
return { x, y, z };
|
|
1955
1945
|
}
|
|
1956
|
-
function
|
|
1957
|
-
const {
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
|
|
1961
|
-
z: forward.z * cmd.forwardmove + right.z * cmd.sidemove
|
|
1962
|
-
};
|
|
1963
|
-
if (cmd.upmove > 10) {
|
|
1964
|
-
wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
|
|
1965
|
-
} else if (cmd.upmove < -10) {
|
|
1966
|
-
wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
|
|
1967
|
-
} else if (Math.abs(cmd.forwardmove) < 10 && Math.abs(cmd.sidemove) < 10) {
|
|
1968
|
-
wishvel = addVec3(wishvel, { x: 0, y: 0, z: -60 });
|
|
1969
|
-
} else {
|
|
1970
|
-
wishvel = addVec3(wishvel, { x: 0, y: 0, z: 10 });
|
|
1946
|
+
function waterCurrentVelocity(params) {
|
|
1947
|
+
const { watertype, waterlevel, onGround, waterSpeed } = params;
|
|
1948
|
+
if ((watertype & MASK_CURRENT) === 0) {
|
|
1949
|
+
return ZERO_VEC3;
|
|
1971
1950
|
}
|
|
1972
|
-
|
|
1973
|
-
if (
|
|
1974
|
-
|
|
1975
|
-
wishvel = scaleVec3(wishvel, scale);
|
|
1976
|
-
wishspeed = maxSpeed;
|
|
1951
|
+
const direction = currentVectorFromContents(watertype);
|
|
1952
|
+
if (direction === ZERO_VEC3) {
|
|
1953
|
+
return ZERO_VEC3;
|
|
1977
1954
|
}
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
wishspeed
|
|
1982
|
-
};
|
|
1983
|
-
}
|
|
1984
|
-
|
|
1985
|
-
// src/pmove/slide.ts
|
|
1986
|
-
var DEFAULT_MAX_CLIP_PLANES = 5;
|
|
1987
|
-
var DEFAULT_MAX_BUMPS = 4;
|
|
1988
|
-
var DEFAULT_STEP_SIZE = 18;
|
|
1989
|
-
var MIN_STEP_NORMAL = 0.7;
|
|
1990
|
-
var SLIDEMOVE_BLOCKED_FLOOR = 1;
|
|
1991
|
-
var SLIDEMOVE_BLOCKED_WALL = 2;
|
|
1992
|
-
function resolveSlideMove(initialVelocity, planesEncountered, overbounce, maxClipPlanes = DEFAULT_MAX_CLIP_PLANES, primalVelocity = initialVelocity) {
|
|
1993
|
-
if (planesEncountered.length === 0) {
|
|
1994
|
-
return { velocity: initialVelocity, planes: [], stopped: false };
|
|
1955
|
+
let scale = waterSpeed;
|
|
1956
|
+
if (waterlevel === 1 /* Feet */ && onGround) {
|
|
1957
|
+
scale *= 0.5;
|
|
1995
1958
|
}
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
if (duplicate) {
|
|
2004
|
-
continue;
|
|
2005
|
-
}
|
|
2006
|
-
planes.push(plane);
|
|
2007
|
-
let clipped;
|
|
2008
|
-
let i = 0;
|
|
2009
|
-
for (; i < planes.length; i++) {
|
|
2010
|
-
const candidate = clipVelocityVec3(velocity, planes[i], overbounce);
|
|
2011
|
-
let j = 0;
|
|
2012
|
-
for (; j < planes.length; j++) {
|
|
2013
|
-
if (j === i) continue;
|
|
2014
|
-
if (dotVec3(candidate, planes[j]) < 0) break;
|
|
2015
|
-
}
|
|
2016
|
-
if (j === planes.length) {
|
|
2017
|
-
clipped = candidate;
|
|
2018
|
-
break;
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
if (clipped) {
|
|
2022
|
-
velocity = clipped;
|
|
2023
|
-
} else {
|
|
2024
|
-
if (planes.length !== 2) {
|
|
2025
|
-
return { velocity: ZERO_VEC3, planes, stopped: true };
|
|
2026
|
-
}
|
|
2027
|
-
const dir = crossVec3(planes[0], planes[1]);
|
|
2028
|
-
const d = dotVec3(dir, velocity);
|
|
2029
|
-
velocity = scaleVec3(dir, d);
|
|
2030
|
-
}
|
|
2031
|
-
if (dotVec3(velocity, primalVelocity) <= 0) {
|
|
2032
|
-
return { velocity: ZERO_VEC3, planes, stopped: true };
|
|
2033
|
-
}
|
|
1959
|
+
return scaleVec3(direction, scale);
|
|
1960
|
+
}
|
|
1961
|
+
function groundCurrentVelocity(params) {
|
|
1962
|
+
const { groundContents, scale = DEFAULT_GROUND_CURRENT_SCALE } = params;
|
|
1963
|
+
const direction = currentVectorFromContents(groundContents);
|
|
1964
|
+
if (direction === ZERO_VEC3) {
|
|
1965
|
+
return ZERO_VEC3;
|
|
2034
1966
|
}
|
|
2035
|
-
|
|
2036
|
-
return { velocity, planes, stopped };
|
|
1967
|
+
return scaleVec3(direction, scale);
|
|
2037
1968
|
}
|
|
2038
|
-
function
|
|
1969
|
+
function applyPmoveAddCurrents(params) {
|
|
2039
1970
|
const {
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
1971
|
+
wishVelocity,
|
|
1972
|
+
onLadder,
|
|
1973
|
+
onGround,
|
|
1974
|
+
waterlevel,
|
|
1975
|
+
watertype,
|
|
1976
|
+
groundContents,
|
|
1977
|
+
cmd,
|
|
1978
|
+
viewPitch,
|
|
1979
|
+
maxSpeed,
|
|
1980
|
+
ladderMod,
|
|
1981
|
+
waterSpeed,
|
|
1982
|
+
forward,
|
|
1983
|
+
origin,
|
|
1984
|
+
mins,
|
|
1985
|
+
maxs,
|
|
1986
|
+
trace = DEFAULT_TRACE
|
|
1987
|
+
} = params;
|
|
1988
|
+
let adjusted = wishVelocity;
|
|
1989
|
+
if (onLadder) {
|
|
1990
|
+
adjusted = applyLadderAdjustments({
|
|
1991
|
+
wishVelocity: adjusted,
|
|
1992
|
+
cmd,
|
|
1993
|
+
waterlevel,
|
|
1994
|
+
viewPitch,
|
|
1995
|
+
maxSpeed,
|
|
1996
|
+
ladderMod,
|
|
1997
|
+
onGround,
|
|
1998
|
+
forward,
|
|
1999
|
+
origin,
|
|
2000
|
+
mins,
|
|
2001
|
+
maxs,
|
|
2002
|
+
trace
|
|
2003
|
+
});
|
|
2004
|
+
}
|
|
2005
|
+
const waterVelocity = waterCurrentVelocity({ watertype, waterlevel, onGround, waterSpeed });
|
|
2006
|
+
if (waterVelocity !== ZERO_VEC3) {
|
|
2007
|
+
adjusted = addVec3(adjusted, waterVelocity);
|
|
2008
|
+
}
|
|
2009
|
+
if (onGround) {
|
|
2010
|
+
const groundVelocity = groundCurrentVelocity({ groundContents });
|
|
2011
|
+
if (groundVelocity !== ZERO_VEC3) {
|
|
2012
|
+
adjusted = addVec3(adjusted, groundVelocity);
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
return adjusted;
|
|
2016
|
+
}
|
|
2017
|
+
function applyLadderAdjustments(params) {
|
|
2018
|
+
const { wishVelocity, cmd, waterlevel, viewPitch, maxSpeed, ladderMod, onGround, forward, origin, mins, maxs, trace } = params;
|
|
2019
|
+
const buttons = cmd.buttons ?? 0;
|
|
2020
|
+
let adjusted = { ...wishVelocity };
|
|
2021
|
+
if ((buttons & (8 /* Jump */ | 16 /* Crouch */)) !== 0) {
|
|
2022
|
+
const ladderSpeed = isAtLeastWaistDeep(waterlevel) ? maxSpeed : DEFAULT_FORWARD_LADDER_CLAMP;
|
|
2023
|
+
adjusted = {
|
|
2024
|
+
...adjusted,
|
|
2025
|
+
z: buttons & 8 /* Jump */ ? ladderSpeed : -ladderSpeed
|
|
2026
|
+
};
|
|
2027
|
+
} else if (cmd.forwardmove) {
|
|
2028
|
+
const clamped = clamp(cmd.forwardmove, -DEFAULT_FORWARD_LADDER_CLAMP, DEFAULT_FORWARD_LADDER_CLAMP);
|
|
2029
|
+
if (cmd.forwardmove > 0) {
|
|
2030
|
+
const climb = viewPitch < LADDER_ASCEND_PITCH_THRESHOLD ? clamped : -clamped;
|
|
2031
|
+
adjusted = { ...adjusted, z: climb };
|
|
2032
|
+
} else {
|
|
2033
|
+
if (!onGround) {
|
|
2034
|
+
adjusted = { ...adjusted, x: 0, y: 0 };
|
|
2035
|
+
}
|
|
2036
|
+
adjusted = { ...adjusted, z: clamped };
|
|
2037
|
+
}
|
|
2038
|
+
} else {
|
|
2039
|
+
adjusted = { ...adjusted, z: 0 };
|
|
2040
|
+
}
|
|
2041
|
+
if (!onGround) {
|
|
2042
|
+
if (cmd.sidemove) {
|
|
2043
|
+
let sideSpeed = clamp(cmd.sidemove, -DEFAULT_SIDE_LADDER_CLAMP, DEFAULT_SIDE_LADDER_CLAMP);
|
|
2044
|
+
if (waterlevel < 2 /* Waist */) {
|
|
2045
|
+
sideSpeed *= ladderMod;
|
|
2046
|
+
}
|
|
2047
|
+
const flatForward = normalizeVec3({ x: forward.x, y: forward.y, z: 0 });
|
|
2048
|
+
if (flatForward.x !== 0 || flatForward.y !== 0) {
|
|
2049
|
+
const spot = addVec3(origin, scaleVec3(flatForward, LADDER_TRACE_DISTANCE));
|
|
2050
|
+
const tr = trace(origin, spot, mins, maxs);
|
|
2051
|
+
if (tr.fraction !== 1 && !tr.allsolid && tr.contents !== void 0 && (tr.contents & CONTENTS_LADDER) !== 0 && tr.planeNormal) {
|
|
2052
|
+
const right = crossVec3(tr.planeNormal, UP_VECTOR);
|
|
2053
|
+
adjusted = { ...adjusted, x: 0, y: 0 };
|
|
2054
|
+
adjusted = addVec3(adjusted, scaleVec3(right, -sideSpeed));
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
} else {
|
|
2058
|
+
adjusted = {
|
|
2059
|
+
...adjusted,
|
|
2060
|
+
x: clampHorizontal(adjusted.x),
|
|
2061
|
+
y: clampHorizontal(adjusted.y)
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
return adjusted;
|
|
2066
|
+
}
|
|
2067
|
+
function clamp(value, min, max) {
|
|
2068
|
+
return Math.max(min, Math.min(max, value));
|
|
2069
|
+
}
|
|
2070
|
+
function clampHorizontal(value) {
|
|
2071
|
+
if (value < -LADDER_HORIZONTAL_CAP) {
|
|
2072
|
+
return -LADDER_HORIZONTAL_CAP;
|
|
2073
|
+
}
|
|
2074
|
+
if (value > LADDER_HORIZONTAL_CAP) {
|
|
2075
|
+
return LADDER_HORIZONTAL_CAP;
|
|
2076
|
+
}
|
|
2077
|
+
return value;
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
// src/pmove/slide.ts
|
|
2081
|
+
var DEFAULT_MAX_CLIP_PLANES = 5;
|
|
2082
|
+
var DEFAULT_MAX_BUMPS = 4;
|
|
2083
|
+
var DEFAULT_STEP_SIZE = 18;
|
|
2084
|
+
var MIN_STEP_NORMAL = 0.7;
|
|
2085
|
+
var SLIDEMOVE_BLOCKED_FLOOR = 1;
|
|
2086
|
+
var SLIDEMOVE_BLOCKED_WALL = 2;
|
|
2087
|
+
function resolveSlideMove(initialVelocity, planesEncountered, overbounce, maxClipPlanes = DEFAULT_MAX_CLIP_PLANES, primalVelocity = initialVelocity) {
|
|
2088
|
+
if (planesEncountered.length === 0) {
|
|
2089
|
+
return { velocity: initialVelocity, planes: [], stopped: false };
|
|
2090
|
+
}
|
|
2091
|
+
const planes = [];
|
|
2092
|
+
let velocity = initialVelocity;
|
|
2093
|
+
for (const plane of planesEncountered) {
|
|
2094
|
+
if (planes.length >= maxClipPlanes) {
|
|
2095
|
+
return { velocity: ZERO_VEC3, planes, stopped: true };
|
|
2096
|
+
}
|
|
2097
|
+
const duplicate = planes.find((existing) => dotVec3(existing, plane) > 0.99);
|
|
2098
|
+
if (duplicate) {
|
|
2099
|
+
continue;
|
|
2100
|
+
}
|
|
2101
|
+
planes.push(plane);
|
|
2102
|
+
let clipped;
|
|
2103
|
+
let i = 0;
|
|
2104
|
+
for (; i < planes.length; i++) {
|
|
2105
|
+
const candidate = clipVelocityVec3(velocity, planes[i], overbounce);
|
|
2106
|
+
let j = 0;
|
|
2107
|
+
for (; j < planes.length; j++) {
|
|
2108
|
+
if (j === i) continue;
|
|
2109
|
+
if (dotVec3(candidate, planes[j]) < 0) break;
|
|
2110
|
+
}
|
|
2111
|
+
if (j === planes.length) {
|
|
2112
|
+
clipped = candidate;
|
|
2113
|
+
break;
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
if (clipped) {
|
|
2117
|
+
velocity = clipped;
|
|
2118
|
+
} else {
|
|
2119
|
+
if (planes.length !== 2) {
|
|
2120
|
+
return { velocity: ZERO_VEC3, planes, stopped: true };
|
|
2121
|
+
}
|
|
2122
|
+
const dir = crossVec3(planes[0], planes[1]);
|
|
2123
|
+
const d = dotVec3(dir, velocity);
|
|
2124
|
+
velocity = scaleVec3(dir, d);
|
|
2125
|
+
}
|
|
2126
|
+
if (dotVec3(velocity, primalVelocity) <= 0) {
|
|
2127
|
+
return { velocity: ZERO_VEC3, planes, stopped: true };
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
const stopped = velocity.x === 0 && velocity.y === 0 && velocity.z === 0;
|
|
2131
|
+
return { velocity, planes, stopped };
|
|
2132
|
+
}
|
|
2133
|
+
function slideMove(params) {
|
|
2134
|
+
const {
|
|
2135
|
+
origin: initialOrigin,
|
|
2136
|
+
velocity: initialVelocity,
|
|
2137
|
+
frametime,
|
|
2138
|
+
overbounce,
|
|
2139
|
+
trace,
|
|
2045
2140
|
maxBumps = DEFAULT_MAX_BUMPS,
|
|
2046
2141
|
maxClipPlanes = DEFAULT_MAX_CLIP_PLANES,
|
|
2047
2142
|
mins,
|
|
@@ -2140,250 +2235,45 @@ function stepSlideMove(params) {
|
|
|
2140
2235
|
};
|
|
2141
2236
|
}
|
|
2142
2237
|
|
|
2143
|
-
// src/pmove/
|
|
2144
|
-
var
|
|
2145
|
-
var
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
{ normal: [1, 0, 0], mins: [0, -1, -1], maxs: [0, 1, 1] },
|
|
2149
|
-
{ normal: [-1, 0, 0], mins: [0, -1, -1], maxs: [0, 1, 1] },
|
|
2150
|
-
{ normal: [0, 1, 0], mins: [-1, 0, -1], maxs: [1, 0, 1] },
|
|
2151
|
-
{ normal: [0, -1, 0], mins: [-1, 0, -1], maxs: [1, 0, 1] }
|
|
2152
|
-
];
|
|
2153
|
-
var ZERO_VEC = { x: 0, y: 0, z: 0 };
|
|
2154
|
-
function cloneMutable(vec) {
|
|
2155
|
-
return { x: vec.x, y: vec.y, z: vec.z };
|
|
2156
|
-
}
|
|
2157
|
-
function tupleToVec3(tuple) {
|
|
2158
|
-
return { x: tuple[0], y: tuple[1], z: tuple[2] };
|
|
2159
|
-
}
|
|
2160
|
-
function adjustAxis(vec, axis, delta) {
|
|
2161
|
-
if (delta === 0) return;
|
|
2162
|
-
switch (axis) {
|
|
2163
|
-
case "x":
|
|
2164
|
-
vec.x += delta;
|
|
2165
|
-
break;
|
|
2166
|
-
case "y":
|
|
2167
|
-
vec.y += delta;
|
|
2168
|
-
break;
|
|
2169
|
-
case "z":
|
|
2170
|
-
vec.z += delta;
|
|
2171
|
-
break;
|
|
2172
|
-
}
|
|
2173
|
-
}
|
|
2174
|
-
function setAxis(vec, axis, value) {
|
|
2175
|
-
switch (axis) {
|
|
2176
|
-
case "x":
|
|
2177
|
-
vec.x = value;
|
|
2178
|
-
break;
|
|
2179
|
-
case "y":
|
|
2180
|
-
vec.y = value;
|
|
2181
|
-
break;
|
|
2182
|
-
case "z":
|
|
2183
|
-
vec.z = value;
|
|
2184
|
-
break;
|
|
2185
|
-
}
|
|
2186
|
-
}
|
|
2187
|
-
function axisValue(vec, axis) {
|
|
2188
|
-
switch (axis) {
|
|
2189
|
-
case "x":
|
|
2190
|
-
return vec.x;
|
|
2191
|
-
case "y":
|
|
2192
|
-
return vec.y;
|
|
2193
|
-
case "z":
|
|
2194
|
-
default:
|
|
2195
|
-
return vec.z;
|
|
2196
|
-
}
|
|
2197
|
-
}
|
|
2198
|
-
function boundValue(code, axis, mins, maxs) {
|
|
2199
|
-
if (code === -1) {
|
|
2200
|
-
return axisValue(mins, axis);
|
|
2201
|
-
}
|
|
2202
|
-
if (code === 1) {
|
|
2203
|
-
return axisValue(maxs, axis);
|
|
2204
|
-
}
|
|
2205
|
-
return 0;
|
|
2206
|
-
}
|
|
2207
|
-
function applySideOffset(base, side, mins, maxs) {
|
|
2208
|
-
const result = cloneMutable(base);
|
|
2209
|
-
for (let i = 0; i < AXES.length; i++) {
|
|
2210
|
-
const axis = AXES[i];
|
|
2211
|
-
const normal = side.normal[i];
|
|
2212
|
-
if (normal < 0) {
|
|
2213
|
-
adjustAxis(result, axis, axisValue(mins, axis));
|
|
2214
|
-
} else if (normal > 0) {
|
|
2215
|
-
adjustAxis(result, axis, axisValue(maxs, axis));
|
|
2216
|
-
}
|
|
2217
|
-
}
|
|
2218
|
-
return result;
|
|
2219
|
-
}
|
|
2220
|
-
function buildSideBounds(side, mins, maxs) {
|
|
2221
|
-
const localMins = cloneMutable(ZERO_VEC);
|
|
2222
|
-
const localMaxs = cloneMutable(ZERO_VEC);
|
|
2223
|
-
for (let i = 0; i < AXES.length; i++) {
|
|
2224
|
-
const axis = AXES[i];
|
|
2225
|
-
setAxis(localMins, axis, boundValue(side.mins[i], axis, mins, maxs));
|
|
2226
|
-
setAxis(localMaxs, axis, boundValue(side.maxs[i], axis, mins, maxs));
|
|
2227
|
-
}
|
|
2228
|
-
return { mins: localMins, maxs: localMaxs };
|
|
2229
|
-
}
|
|
2230
|
-
function addEpsilon(source, axis, direction) {
|
|
2231
|
-
if (!axis || direction === 0) {
|
|
2232
|
-
return source;
|
|
2233
|
-
}
|
|
2234
|
-
const clone = cloneMutable(source);
|
|
2235
|
-
adjustAxis(clone, axis, direction);
|
|
2236
|
-
return clone;
|
|
2237
|
-
}
|
|
2238
|
-
function addEpsilonImmutable(vec, axis, direction) {
|
|
2239
|
-
if (!axis || direction === 0) {
|
|
2240
|
-
return vec;
|
|
2241
|
-
}
|
|
2242
|
-
switch (axis) {
|
|
2243
|
-
case "x":
|
|
2244
|
-
return { ...vec, x: vec.x + direction };
|
|
2245
|
-
case "y":
|
|
2246
|
-
return { ...vec, y: vec.y + direction };
|
|
2247
|
-
case "z":
|
|
2248
|
-
default:
|
|
2249
|
-
return { ...vec, z: vec.z + direction };
|
|
2250
|
-
}
|
|
2251
|
-
}
|
|
2252
|
-
function fixStuckObjectGeneric(params) {
|
|
2253
|
-
const { origin, mins, maxs, trace } = params;
|
|
2254
|
-
const initial = trace(origin, mins, maxs, origin);
|
|
2255
|
-
if (!initial.startsolid) {
|
|
2256
|
-
return { result: "good-position", origin: { ...origin } };
|
|
2257
|
-
}
|
|
2258
|
-
const candidates = [];
|
|
2259
|
-
for (let i = 0; i < SIDE_CHECKS.length; i++) {
|
|
2260
|
-
const side = SIDE_CHECKS[i];
|
|
2261
|
-
const { mins: localMins, maxs: localMaxs } = buildSideBounds(side, mins, maxs);
|
|
2262
|
-
let start = applySideOffset(origin, side, mins, maxs);
|
|
2263
|
-
let tr = trace(start, localMins, localMaxs, start);
|
|
2264
|
-
let epsilonAxis;
|
|
2265
|
-
let epsilonDir = 0;
|
|
2266
|
-
if (tr.startsolid) {
|
|
2267
|
-
for (let axisIndex = 0; axisIndex < AXES.length; axisIndex++) {
|
|
2268
|
-
if (side.normal[axisIndex] !== 0) {
|
|
2269
|
-
continue;
|
|
2270
|
-
}
|
|
2271
|
-
const axis = AXES[axisIndex];
|
|
2272
|
-
let epsilonStart = cloneMutable(start);
|
|
2273
|
-
adjustAxis(epsilonStart, axis, 1);
|
|
2274
|
-
tr = trace(epsilonStart, localMins, localMaxs, epsilonStart);
|
|
2275
|
-
if (!tr.startsolid) {
|
|
2276
|
-
start = epsilonStart;
|
|
2277
|
-
epsilonAxis = axis;
|
|
2278
|
-
epsilonDir = 1;
|
|
2279
|
-
break;
|
|
2280
|
-
}
|
|
2281
|
-
epsilonStart = cloneMutable(start);
|
|
2282
|
-
adjustAxis(epsilonStart, axis, -1);
|
|
2283
|
-
tr = trace(epsilonStart, localMins, localMaxs, epsilonStart);
|
|
2284
|
-
if (!tr.startsolid) {
|
|
2285
|
-
start = epsilonStart;
|
|
2286
|
-
epsilonAxis = axis;
|
|
2287
|
-
epsilonDir = -1;
|
|
2288
|
-
break;
|
|
2289
|
-
}
|
|
2290
|
-
}
|
|
2291
|
-
}
|
|
2292
|
-
if (tr.startsolid) {
|
|
2293
|
-
continue;
|
|
2294
|
-
}
|
|
2295
|
-
const otherSide = SIDE_CHECKS[i ^ 1];
|
|
2296
|
-
let oppositeStart = applySideOffset(origin, otherSide, mins, maxs);
|
|
2297
|
-
oppositeStart = addEpsilon(oppositeStart, epsilonAxis, epsilonDir);
|
|
2298
|
-
tr = trace(start, localMins, localMaxs, oppositeStart);
|
|
2299
|
-
if (tr.startsolid) {
|
|
2300
|
-
continue;
|
|
2301
|
-
}
|
|
2302
|
-
const normal = tupleToVec3(side.normal);
|
|
2303
|
-
const end = addVec3(tr.endpos ?? oppositeStart, scaleVec3(normal, 0.125));
|
|
2304
|
-
const delta = subtractVec3(end, oppositeStart);
|
|
2305
|
-
let newOrigin = addVec3(origin, delta);
|
|
2306
|
-
newOrigin = addEpsilonImmutable(newOrigin, epsilonAxis, epsilonDir);
|
|
2307
|
-
const validation = trace(newOrigin, mins, maxs, newOrigin);
|
|
2308
|
-
if (validation.startsolid) {
|
|
2309
|
-
continue;
|
|
2310
|
-
}
|
|
2311
|
-
candidates.push({ origin: newOrigin, distance: lengthSquaredVec3(delta) });
|
|
2312
|
-
}
|
|
2313
|
-
if (candidates.length === 0) {
|
|
2314
|
-
return { result: "no-good-position", origin: { ...origin } };
|
|
2315
|
-
}
|
|
2316
|
-
candidates.sort((a, b) => a.distance - b.distance);
|
|
2317
|
-
return { result: "fixed", origin: { ...candidates[0].origin } };
|
|
2318
|
-
}
|
|
2319
|
-
|
|
2320
|
-
// src/pmove/currents.ts
|
|
2321
|
-
var DEFAULT_GROUND_CURRENT_SCALE = 100;
|
|
2322
|
-
var DEFAULT_FORWARD_LADDER_CLAMP = 200;
|
|
2323
|
-
var DEFAULT_SIDE_LADDER_CLAMP = 150;
|
|
2324
|
-
var LADDER_HORIZONTAL_CAP = 25;
|
|
2325
|
-
var LADDER_ASCEND_PITCH_THRESHOLD = 15;
|
|
2326
|
-
var LADDER_TRACE_DISTANCE = 1;
|
|
2327
|
-
var UP_VECTOR = { x: 0, y: 0, z: 1 };
|
|
2328
|
-
var DEFAULT_TRACE = (_, end) => ({
|
|
2329
|
-
fraction: 1,
|
|
2330
|
-
endpos: end,
|
|
2331
|
-
allsolid: false,
|
|
2332
|
-
startsolid: false
|
|
2333
|
-
});
|
|
2334
|
-
function currentVectorFromContents(contents) {
|
|
2335
|
-
let x = 0;
|
|
2336
|
-
let y = 0;
|
|
2337
|
-
let z = 0;
|
|
2338
|
-
if (contents & CONTENTS_CURRENT_0) {
|
|
2339
|
-
x += 1;
|
|
2340
|
-
}
|
|
2341
|
-
if (contents & CONTENTS_CURRENT_90) {
|
|
2342
|
-
y += 1;
|
|
2343
|
-
}
|
|
2344
|
-
if (contents & CONTENTS_CURRENT_180) {
|
|
2345
|
-
x -= 1;
|
|
2346
|
-
}
|
|
2347
|
-
if (contents & CONTENTS_CURRENT_270) {
|
|
2348
|
-
y -= 1;
|
|
2349
|
-
}
|
|
2350
|
-
if (contents & CONTENTS_CURRENT_UP) {
|
|
2351
|
-
z += 1;
|
|
2352
|
-
}
|
|
2353
|
-
if (contents & CONTENTS_CURRENT_DOWN) {
|
|
2354
|
-
z -= 1;
|
|
2355
|
-
}
|
|
2356
|
-
if (x === 0 && y === 0 && z === 0) {
|
|
2357
|
-
return ZERO_VEC3;
|
|
2358
|
-
}
|
|
2359
|
-
return { x, y, z };
|
|
2360
|
-
}
|
|
2361
|
-
function waterCurrentVelocity(params) {
|
|
2362
|
-
const { watertype, waterlevel, onGround, waterSpeed } = params;
|
|
2363
|
-
if ((watertype & MASK_CURRENT) === 0) {
|
|
2364
|
-
return ZERO_VEC3;
|
|
2365
|
-
}
|
|
2366
|
-
const direction = currentVectorFromContents(watertype);
|
|
2367
|
-
if (direction === ZERO_VEC3) {
|
|
2368
|
-
return ZERO_VEC3;
|
|
2369
|
-
}
|
|
2370
|
-
let scale = waterSpeed;
|
|
2371
|
-
if (waterlevel === 1 /* Feet */ && onGround) {
|
|
2372
|
-
scale *= 0.5;
|
|
2373
|
-
}
|
|
2374
|
-
return scaleVec3(direction, scale);
|
|
2375
|
-
}
|
|
2376
|
-
function groundCurrentVelocity(params) {
|
|
2377
|
-
const { groundContents, scale = DEFAULT_GROUND_CURRENT_SCALE } = params;
|
|
2378
|
-
const direction = currentVectorFromContents(groundContents);
|
|
2379
|
-
if (direction === ZERO_VEC3) {
|
|
2380
|
-
return ZERO_VEC3;
|
|
2381
|
-
}
|
|
2382
|
-
return scaleVec3(direction, scale);
|
|
2383
|
-
}
|
|
2384
|
-
function applyPmoveAddCurrents(params) {
|
|
2238
|
+
// src/pmove/move.ts
|
|
2239
|
+
var DEFAULT_AIR_ACCELERATE = 1;
|
|
2240
|
+
var WATER_DRIFT_SPEED = 60;
|
|
2241
|
+
var DEFAULT_STEP_OVERBOUNCE = 1.01;
|
|
2242
|
+
function applyPmoveAirMove(params) {
|
|
2385
2243
|
const {
|
|
2386
|
-
|
|
2244
|
+
origin,
|
|
2245
|
+
frametime,
|
|
2246
|
+
mins,
|
|
2247
|
+
maxs,
|
|
2248
|
+
trace,
|
|
2249
|
+
overbounce = DEFAULT_STEP_OVERBOUNCE,
|
|
2250
|
+
stepSize,
|
|
2251
|
+
maxBumps,
|
|
2252
|
+
maxClipPlanes,
|
|
2253
|
+
hasTime,
|
|
2254
|
+
forward,
|
|
2255
|
+
right,
|
|
2256
|
+
cmd,
|
|
2257
|
+
pmFlags,
|
|
2258
|
+
onGround,
|
|
2259
|
+
gravity,
|
|
2260
|
+
pmType,
|
|
2261
|
+
pmAccelerate,
|
|
2262
|
+
pmAirAccelerate = DEFAULT_AIR_ACCELERATE,
|
|
2263
|
+
pmMaxSpeed,
|
|
2264
|
+
pmDuckSpeed,
|
|
2265
|
+
onLadder,
|
|
2266
|
+
waterlevel,
|
|
2267
|
+
watertype,
|
|
2268
|
+
groundContents,
|
|
2269
|
+
viewPitch,
|
|
2270
|
+
ladderMod,
|
|
2271
|
+
pmWaterSpeed
|
|
2272
|
+
} = params;
|
|
2273
|
+
let velocity = { ...params.velocity };
|
|
2274
|
+
let wishvel = buildPlanarWishVelocity(forward, right, cmd);
|
|
2275
|
+
wishvel = applyPmoveAddCurrents({
|
|
2276
|
+
wishVelocity: wishvel,
|
|
2387
2277
|
onLadder,
|
|
2388
2278
|
onGround,
|
|
2389
2279
|
waterlevel,
|
|
@@ -2391,223 +2281,354 @@ function applyPmoveAddCurrents(params) {
|
|
|
2391
2281
|
groundContents,
|
|
2392
2282
|
cmd,
|
|
2393
2283
|
viewPitch,
|
|
2394
|
-
maxSpeed,
|
|
2284
|
+
maxSpeed: hasPmFlag(pmFlags, 1 /* Ducked */) ? pmDuckSpeed : pmMaxSpeed,
|
|
2395
2285
|
ladderMod,
|
|
2396
|
-
waterSpeed,
|
|
2286
|
+
waterSpeed: pmWaterSpeed,
|
|
2397
2287
|
forward,
|
|
2398
2288
|
origin,
|
|
2399
2289
|
mins,
|
|
2400
2290
|
maxs,
|
|
2401
|
-
trace
|
|
2402
|
-
}
|
|
2403
|
-
|
|
2291
|
+
trace
|
|
2292
|
+
});
|
|
2293
|
+
const ducked = hasPmFlag(pmFlags, 1 /* Ducked */);
|
|
2294
|
+
const maxSpeed = ducked ? pmDuckSpeed : pmMaxSpeed;
|
|
2295
|
+
let wishdir = wishvel;
|
|
2296
|
+
let wishspeed = lengthVec3(wishdir);
|
|
2297
|
+
if (wishspeed !== 0) {
|
|
2298
|
+
wishdir = normalizeVec3(wishdir);
|
|
2299
|
+
}
|
|
2300
|
+
if (wishspeed > maxSpeed) {
|
|
2301
|
+
const scale = maxSpeed / wishspeed;
|
|
2302
|
+
wishvel = scaleVec3(wishvel, scale);
|
|
2303
|
+
wishspeed = maxSpeed;
|
|
2304
|
+
if (wishspeed !== 0) {
|
|
2305
|
+
wishdir = normalizeVec3(wishvel);
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2404
2308
|
if (onLadder) {
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
maxSpeed,
|
|
2411
|
-
ladderMod,
|
|
2412
|
-
onGround,
|
|
2413
|
-
forward,
|
|
2309
|
+
velocity = applyPmoveAccelerate({ velocity, wishdir, wishspeed, accel: pmAccelerate, frametime });
|
|
2310
|
+
if (Math.abs(wishvel.z) < Number.EPSILON) {
|
|
2311
|
+
velocity = dampVerticalVelocity(velocity, gravity, frametime);
|
|
2312
|
+
}
|
|
2313
|
+
return runStepSlideMove({
|
|
2414
2314
|
origin,
|
|
2315
|
+
velocity,
|
|
2316
|
+
frametime,
|
|
2415
2317
|
mins,
|
|
2416
2318
|
maxs,
|
|
2417
|
-
trace
|
|
2319
|
+
trace,
|
|
2320
|
+
overbounce,
|
|
2321
|
+
stepSize,
|
|
2322
|
+
maxBumps,
|
|
2323
|
+
maxClipPlanes,
|
|
2324
|
+
hasTime
|
|
2418
2325
|
});
|
|
2419
2326
|
}
|
|
2420
|
-
const waterVelocity = waterCurrentVelocity({ watertype, waterlevel, onGround, waterSpeed });
|
|
2421
|
-
if (waterVelocity !== ZERO_VEC3) {
|
|
2422
|
-
adjusted = addVec3(adjusted, waterVelocity);
|
|
2423
|
-
}
|
|
2424
2327
|
if (onGround) {
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2328
|
+
velocity = { ...velocity, z: 0 };
|
|
2329
|
+
velocity = applyPmoveAccelerate({ velocity, wishdir, wishspeed, accel: pmAccelerate, frametime });
|
|
2330
|
+
if (gravity > 0) {
|
|
2331
|
+
velocity = { ...velocity, z: 0 };
|
|
2332
|
+
} else {
|
|
2333
|
+
velocity = { ...velocity, z: velocity.z - gravity * frametime };
|
|
2428
2334
|
}
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
adjusted = {
|
|
2439
|
-
...adjusted,
|
|
2440
|
-
z: buttons & 8 /* Jump */ ? ladderSpeed : -ladderSpeed
|
|
2441
|
-
};
|
|
2442
|
-
} else if (cmd.forwardmove) {
|
|
2443
|
-
const clamped = clamp(cmd.forwardmove, -DEFAULT_FORWARD_LADDER_CLAMP, DEFAULT_FORWARD_LADDER_CLAMP);
|
|
2444
|
-
if (cmd.forwardmove > 0) {
|
|
2445
|
-
const climb = viewPitch < LADDER_ASCEND_PITCH_THRESHOLD ? clamped : -clamped;
|
|
2446
|
-
adjusted = { ...adjusted, z: climb };
|
|
2447
|
-
} else {
|
|
2448
|
-
if (!onGround) {
|
|
2449
|
-
adjusted = { ...adjusted, x: 0, y: 0 };
|
|
2450
|
-
}
|
|
2451
|
-
adjusted = { ...adjusted, z: clamped };
|
|
2452
|
-
}
|
|
2453
|
-
} else {
|
|
2454
|
-
adjusted = { ...adjusted, z: 0 };
|
|
2455
|
-
}
|
|
2456
|
-
if (!onGround) {
|
|
2457
|
-
if (cmd.sidemove) {
|
|
2458
|
-
let sideSpeed = clamp(cmd.sidemove, -DEFAULT_SIDE_LADDER_CLAMP, DEFAULT_SIDE_LADDER_CLAMP);
|
|
2459
|
-
if (waterlevel < 2 /* Waist */) {
|
|
2460
|
-
sideSpeed *= ladderMod;
|
|
2461
|
-
}
|
|
2462
|
-
const flatForward = normalizeVec3({ x: forward.x, y: forward.y, z: 0 });
|
|
2463
|
-
if (flatForward.x !== 0 || flatForward.y !== 0) {
|
|
2464
|
-
const spot = addVec3(origin, scaleVec3(flatForward, LADDER_TRACE_DISTANCE));
|
|
2465
|
-
const tr = trace(origin, spot, mins, maxs);
|
|
2466
|
-
if (tr.fraction !== 1 && !tr.allsolid && tr.contents !== void 0 && (tr.contents & CONTENTS_LADDER) !== 0 && tr.planeNormal) {
|
|
2467
|
-
const right = crossVec3(tr.planeNormal, UP_VECTOR);
|
|
2468
|
-
adjusted = { ...adjusted, x: 0, y: 0 };
|
|
2469
|
-
adjusted = addVec3(adjusted, scaleVec3(right, -sideSpeed));
|
|
2470
|
-
}
|
|
2471
|
-
}
|
|
2472
|
-
} else {
|
|
2473
|
-
adjusted = {
|
|
2474
|
-
...adjusted,
|
|
2475
|
-
x: clampHorizontal(adjusted.x),
|
|
2476
|
-
y: clampHorizontal(adjusted.y)
|
|
2335
|
+
if (velocity.x === 0 && velocity.y === 0) {
|
|
2336
|
+
return {
|
|
2337
|
+
origin,
|
|
2338
|
+
velocity,
|
|
2339
|
+
planes: [],
|
|
2340
|
+
blocked: 0,
|
|
2341
|
+
stopped: true,
|
|
2342
|
+
stepped: false,
|
|
2343
|
+
stepHeight: 0
|
|
2477
2344
|
};
|
|
2478
2345
|
}
|
|
2346
|
+
return runStepSlideMove({
|
|
2347
|
+
origin,
|
|
2348
|
+
velocity,
|
|
2349
|
+
frametime,
|
|
2350
|
+
mins,
|
|
2351
|
+
maxs,
|
|
2352
|
+
trace,
|
|
2353
|
+
overbounce,
|
|
2354
|
+
stepSize,
|
|
2355
|
+
maxBumps,
|
|
2356
|
+
maxClipPlanes,
|
|
2357
|
+
hasTime
|
|
2358
|
+
});
|
|
2479
2359
|
}
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2360
|
+
if (pmAirAccelerate > 0) {
|
|
2361
|
+
velocity = applyPmoveAirAccelerate({
|
|
2362
|
+
velocity,
|
|
2363
|
+
wishdir,
|
|
2364
|
+
wishspeed,
|
|
2365
|
+
accel: pmAirAccelerate,
|
|
2366
|
+
frametime
|
|
2367
|
+
});
|
|
2368
|
+
} else {
|
|
2369
|
+
velocity = applyPmoveAccelerate({ velocity, wishdir, wishspeed, accel: DEFAULT_AIR_ACCELERATE, frametime });
|
|
2488
2370
|
}
|
|
2489
|
-
if (
|
|
2490
|
-
|
|
2371
|
+
if (pmType !== 1 /* Grapple */) {
|
|
2372
|
+
velocity = { ...velocity, z: velocity.z - gravity * frametime };
|
|
2491
2373
|
}
|
|
2492
|
-
return
|
|
2374
|
+
return runStepSlideMove({
|
|
2375
|
+
origin,
|
|
2376
|
+
velocity,
|
|
2377
|
+
frametime,
|
|
2378
|
+
mins,
|
|
2379
|
+
maxs,
|
|
2380
|
+
trace,
|
|
2381
|
+
overbounce,
|
|
2382
|
+
stepSize,
|
|
2383
|
+
maxBumps,
|
|
2384
|
+
maxClipPlanes,
|
|
2385
|
+
hasTime
|
|
2386
|
+
});
|
|
2493
2387
|
}
|
|
2494
|
-
|
|
2495
|
-
// src/pmove/fly.ts
|
|
2496
|
-
var FLY_FRICTION_MULTIPLIER = 1.5;
|
|
2497
|
-
var BUTTON_VERTICAL_SCALE = 0.5;
|
|
2498
|
-
var DEFAULT_OVERBOUNCE = 1.01;
|
|
2499
|
-
function applyPmoveFlyMove(params) {
|
|
2388
|
+
function applyPmoveWaterMove(params) {
|
|
2500
2389
|
const {
|
|
2501
2390
|
origin,
|
|
2502
|
-
cmd,
|
|
2503
2391
|
frametime,
|
|
2504
|
-
pmFriction,
|
|
2505
|
-
pmStopSpeed,
|
|
2506
|
-
pmMaxSpeed,
|
|
2507
|
-
pmAccelerate,
|
|
2508
|
-
pmWaterSpeed,
|
|
2509
|
-
doclip,
|
|
2510
|
-
forward,
|
|
2511
|
-
right,
|
|
2512
2392
|
mins,
|
|
2513
2393
|
maxs,
|
|
2514
2394
|
trace,
|
|
2515
|
-
overbounce =
|
|
2395
|
+
overbounce = DEFAULT_STEP_OVERBOUNCE,
|
|
2516
2396
|
stepSize,
|
|
2517
2397
|
maxBumps,
|
|
2518
|
-
maxClipPlanes
|
|
2519
|
-
|
|
2520
|
-
let velocity = applyFlyFriction({ velocity: params.velocity, pmFriction, pmStopSpeed, frametime });
|
|
2521
|
-
const wishdirVelocity = buildFlyWishVelocity({
|
|
2522
|
-
cmd,
|
|
2398
|
+
maxClipPlanes,
|
|
2399
|
+
hasTime,
|
|
2523
2400
|
forward,
|
|
2524
2401
|
right,
|
|
2402
|
+
cmd,
|
|
2403
|
+
pmFlags,
|
|
2404
|
+
onGround,
|
|
2525
2405
|
pmMaxSpeed,
|
|
2526
|
-
|
|
2406
|
+
pmDuckSpeed,
|
|
2407
|
+
pmWaterAccelerate,
|
|
2408
|
+
pmWaterSpeed,
|
|
2409
|
+
onLadder,
|
|
2410
|
+
watertype,
|
|
2411
|
+
groundContents,
|
|
2412
|
+
waterlevel,
|
|
2413
|
+
viewPitch,
|
|
2414
|
+
ladderMod
|
|
2415
|
+
} = params;
|
|
2416
|
+
let velocity = { ...params.velocity };
|
|
2417
|
+
let wishvel = buildFullWishVelocity(forward, right, cmd);
|
|
2418
|
+
if (isIdleInWater(cmd, onGround)) {
|
|
2419
|
+
wishvel = { ...wishvel, z: wishvel.z - WATER_DRIFT_SPEED };
|
|
2420
|
+
} else {
|
|
2421
|
+
if (hasButton2(cmd, 16 /* Crouch */)) {
|
|
2422
|
+
wishvel = addVec3(wishvel, { x: 0, y: 0, z: -pmWaterSpeed * 0.5 });
|
|
2423
|
+
} else if (hasButton2(cmd, 8 /* Jump */)) {
|
|
2424
|
+
wishvel = addVec3(wishvel, { x: 0, y: 0, z: pmWaterSpeed * 0.5 });
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
wishvel = applyPmoveAddCurrents({
|
|
2428
|
+
wishVelocity: wishvel,
|
|
2429
|
+
onLadder,
|
|
2430
|
+
onGround,
|
|
2431
|
+
waterlevel,
|
|
2432
|
+
watertype,
|
|
2433
|
+
groundContents,
|
|
2434
|
+
cmd,
|
|
2435
|
+
viewPitch,
|
|
2436
|
+
maxSpeed: hasPmFlag(pmFlags, 1 /* Ducked */) ? pmDuckSpeed : pmMaxSpeed,
|
|
2437
|
+
ladderMod,
|
|
2438
|
+
waterSpeed: pmWaterSpeed,
|
|
2439
|
+
forward,
|
|
2440
|
+
origin,
|
|
2441
|
+
mins,
|
|
2442
|
+
maxs,
|
|
2443
|
+
trace
|
|
2527
2444
|
});
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
wishspeed: wishdirVelocity.accelSpeed,
|
|
2533
|
-
accel: pmAccelerate,
|
|
2534
|
-
frametime
|
|
2535
|
-
});
|
|
2445
|
+
let wishdir = wishvel;
|
|
2446
|
+
let wishspeed = lengthVec3(wishdir);
|
|
2447
|
+
if (wishspeed !== 0) {
|
|
2448
|
+
wishdir = normalizeVec3(wishdir);
|
|
2536
2449
|
}
|
|
2537
|
-
if (
|
|
2538
|
-
const
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
blocked: 0,
|
|
2545
|
-
stopped: velocity.x === 0 && velocity.y === 0 && velocity.z === 0,
|
|
2546
|
-
stepped: false,
|
|
2547
|
-
stepHeight: 0
|
|
2548
|
-
};
|
|
2450
|
+
if (wishspeed > pmMaxSpeed) {
|
|
2451
|
+
const scale = pmMaxSpeed / wishspeed;
|
|
2452
|
+
wishvel = scaleVec3(wishvel, scale);
|
|
2453
|
+
wishspeed = pmMaxSpeed;
|
|
2454
|
+
if (wishspeed !== 0) {
|
|
2455
|
+
wishdir = normalizeVec3(wishvel);
|
|
2456
|
+
}
|
|
2549
2457
|
}
|
|
2550
|
-
|
|
2551
|
-
|
|
2458
|
+
wishspeed *= 0.5;
|
|
2459
|
+
const ducked = hasPmFlag(pmFlags, 1 /* Ducked */);
|
|
2460
|
+
if (ducked && wishspeed > pmDuckSpeed) {
|
|
2461
|
+
const scale = pmDuckSpeed / wishspeed;
|
|
2462
|
+
wishvel = scaleVec3(wishvel, scale);
|
|
2463
|
+
wishspeed = pmDuckSpeed;
|
|
2464
|
+
if (wishspeed !== 0) {
|
|
2465
|
+
wishdir = normalizeVec3(wishvel);
|
|
2466
|
+
}
|
|
2552
2467
|
}
|
|
2553
|
-
|
|
2468
|
+
velocity = applyPmoveAccelerate({ velocity, wishdir, wishspeed, accel: pmWaterAccelerate, frametime });
|
|
2469
|
+
return runStepSlideMove({
|
|
2554
2470
|
origin,
|
|
2555
2471
|
velocity,
|
|
2556
2472
|
frametime,
|
|
2557
|
-
overbounce,
|
|
2558
|
-
trace,
|
|
2559
2473
|
mins,
|
|
2560
2474
|
maxs,
|
|
2475
|
+
trace,
|
|
2476
|
+
overbounce,
|
|
2561
2477
|
stepSize,
|
|
2562
2478
|
maxBumps,
|
|
2563
|
-
maxClipPlanes
|
|
2479
|
+
maxClipPlanes,
|
|
2480
|
+
hasTime
|
|
2564
2481
|
});
|
|
2565
2482
|
}
|
|
2566
|
-
function
|
|
2567
|
-
const {
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2483
|
+
function applyPmoveWalkMove(params) {
|
|
2484
|
+
const {
|
|
2485
|
+
origin,
|
|
2486
|
+
frametime,
|
|
2487
|
+
mins,
|
|
2488
|
+
maxs,
|
|
2489
|
+
trace,
|
|
2490
|
+
overbounce = DEFAULT_STEP_OVERBOUNCE,
|
|
2491
|
+
stepSize,
|
|
2492
|
+
maxBumps,
|
|
2493
|
+
maxClipPlanes,
|
|
2494
|
+
hasTime,
|
|
2495
|
+
forward,
|
|
2496
|
+
right,
|
|
2497
|
+
cmd,
|
|
2498
|
+
pmFlags,
|
|
2499
|
+
onGround,
|
|
2500
|
+
gravity,
|
|
2501
|
+
pmAccelerate,
|
|
2502
|
+
pmMaxSpeed,
|
|
2503
|
+
pmDuckSpeed,
|
|
2504
|
+
onLadder,
|
|
2505
|
+
waterlevel,
|
|
2506
|
+
watertype,
|
|
2507
|
+
groundContents,
|
|
2508
|
+
viewPitch,
|
|
2509
|
+
ladderMod,
|
|
2510
|
+
pmWaterSpeed
|
|
2511
|
+
} = params;
|
|
2512
|
+
let velocity = { ...params.velocity };
|
|
2513
|
+
let wishvel = buildPlanarWishVelocity(forward, right, cmd);
|
|
2514
|
+
wishvel = applyPmoveAddCurrents({
|
|
2515
|
+
wishVelocity: wishvel,
|
|
2516
|
+
onLadder,
|
|
2517
|
+
onGround,
|
|
2518
|
+
waterlevel,
|
|
2519
|
+
watertype,
|
|
2520
|
+
groundContents,
|
|
2521
|
+
cmd,
|
|
2522
|
+
viewPitch,
|
|
2523
|
+
maxSpeed: hasPmFlag(pmFlags, 1 /* Ducked */) ? pmDuckSpeed : pmMaxSpeed,
|
|
2524
|
+
ladderMod,
|
|
2525
|
+
waterSpeed: pmWaterSpeed,
|
|
2526
|
+
forward,
|
|
2527
|
+
origin,
|
|
2528
|
+
mins,
|
|
2529
|
+
maxs,
|
|
2530
|
+
trace
|
|
2531
|
+
});
|
|
2532
|
+
const ducked = hasPmFlag(pmFlags, 1 /* Ducked */);
|
|
2533
|
+
const maxSpeed = ducked ? pmDuckSpeed : pmMaxSpeed;
|
|
2534
|
+
let wishdir = wishvel;
|
|
2535
|
+
let wishspeed = lengthVec3(wishdir);
|
|
2536
|
+
if (wishspeed !== 0) {
|
|
2537
|
+
wishdir = normalizeVec3(wishdir);
|
|
2600
2538
|
}
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2539
|
+
if (wishspeed > maxSpeed) {
|
|
2540
|
+
const scale = maxSpeed / wishspeed;
|
|
2541
|
+
wishvel = scaleVec3(wishvel, scale);
|
|
2542
|
+
wishspeed = maxSpeed;
|
|
2543
|
+
if (wishspeed !== 0) {
|
|
2544
|
+
wishdir = normalizeVec3(wishvel);
|
|
2545
|
+
}
|
|
2608
2546
|
}
|
|
2609
|
-
|
|
2610
|
-
|
|
2547
|
+
velocity = { ...velocity, z: 0 };
|
|
2548
|
+
velocity = applyPmoveAccelerate({ velocity, wishdir, wishspeed, accel: pmAccelerate, frametime });
|
|
2549
|
+
if (gravity > 0) {
|
|
2550
|
+
velocity = { ...velocity, z: 0 };
|
|
2551
|
+
} else {
|
|
2552
|
+
velocity = { ...velocity, z: velocity.z - gravity * frametime };
|
|
2553
|
+
}
|
|
2554
|
+
if (velocity.x === 0 && velocity.y === 0) {
|
|
2555
|
+
return {
|
|
2556
|
+
origin,
|
|
2557
|
+
velocity,
|
|
2558
|
+
planes: [],
|
|
2559
|
+
blocked: 0,
|
|
2560
|
+
stopped: true,
|
|
2561
|
+
stepped: false,
|
|
2562
|
+
stepHeight: 0
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
return runStepSlideMove({
|
|
2566
|
+
origin,
|
|
2567
|
+
velocity,
|
|
2568
|
+
frametime,
|
|
2569
|
+
mins,
|
|
2570
|
+
maxs,
|
|
2571
|
+
trace,
|
|
2572
|
+
overbounce,
|
|
2573
|
+
stepSize,
|
|
2574
|
+
maxBumps,
|
|
2575
|
+
maxClipPlanes,
|
|
2576
|
+
hasTime
|
|
2577
|
+
});
|
|
2578
|
+
}
|
|
2579
|
+
function buildPlanarWishVelocity(forward, right, cmd) {
|
|
2580
|
+
return {
|
|
2581
|
+
x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
|
|
2582
|
+
y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
|
|
2583
|
+
z: 0
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
function buildFullWishVelocity(forward, right, cmd) {
|
|
2587
|
+
return {
|
|
2588
|
+
x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
|
|
2589
|
+
y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
|
|
2590
|
+
z: forward.z * cmd.forwardmove + right.z * cmd.sidemove
|
|
2591
|
+
};
|
|
2592
|
+
}
|
|
2593
|
+
function hasButton2(cmd, button) {
|
|
2594
|
+
return (cmd.buttons ?? 0) & button ? true : false;
|
|
2595
|
+
}
|
|
2596
|
+
function isIdleInWater(cmd, onGround) {
|
|
2597
|
+
const noMove = cmd.forwardmove === 0 && cmd.sidemove === 0;
|
|
2598
|
+
const noButtons = (cmd.buttons ?? 0) & (8 /* Jump */ | 16 /* Crouch */) ? false : true;
|
|
2599
|
+
return noMove && noButtons && !onGround;
|
|
2600
|
+
}
|
|
2601
|
+
function dampVerticalVelocity(velocity, gravity, frametime) {
|
|
2602
|
+
let z = velocity.z;
|
|
2603
|
+
const delta = gravity * frametime;
|
|
2604
|
+
if (z > 0) {
|
|
2605
|
+
z -= delta;
|
|
2606
|
+
if (z < 0) {
|
|
2607
|
+
z = 0;
|
|
2608
|
+
}
|
|
2609
|
+
} else {
|
|
2610
|
+
z += delta;
|
|
2611
|
+
if (z > 0) {
|
|
2612
|
+
z = 0;
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
return { ...velocity, z };
|
|
2616
|
+
}
|
|
2617
|
+
function runStepSlideMove(params) {
|
|
2618
|
+
const { origin, velocity, frametime, mins, maxs, trace, overbounce = DEFAULT_STEP_OVERBOUNCE, stepSize, maxBumps, maxClipPlanes, hasTime } = params;
|
|
2619
|
+
return stepSlideMove({
|
|
2620
|
+
origin,
|
|
2621
|
+
velocity,
|
|
2622
|
+
frametime,
|
|
2623
|
+
trace,
|
|
2624
|
+
mins,
|
|
2625
|
+
maxs,
|
|
2626
|
+
overbounce,
|
|
2627
|
+
stepSize,
|
|
2628
|
+
maxBumps,
|
|
2629
|
+
maxClipPlanes,
|
|
2630
|
+
hasTime
|
|
2631
|
+
});
|
|
2611
2632
|
}
|
|
2612
2633
|
|
|
2613
2634
|
// src/pmove/water.ts
|
|
@@ -2639,184 +2660,23 @@ function getWaterLevel(params) {
|
|
|
2639
2660
|
return { waterlevel, watertype };
|
|
2640
2661
|
}
|
|
2641
2662
|
|
|
2642
|
-
// src/pmove/
|
|
2643
|
-
var
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
nextFlags = removePmFlag(nextFlags, 2 /* JumpHeld */);
|
|
2660
|
-
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, jumpSound, jumped };
|
|
2661
|
-
}
|
|
2662
|
-
if (hasPmJumpHold(nextFlags)) {
|
|
2663
|
-
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, jumpSound, jumped };
|
|
2664
|
-
}
|
|
2665
|
-
if (pmType === 4 /* Dead */) {
|
|
2666
|
-
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, jumpSound, jumped };
|
|
2667
|
-
}
|
|
2668
|
-
if (waterlevel >= 2 /* Waist */) {
|
|
2669
|
-
nextOnGround = false;
|
|
2670
|
-
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, jumpSound, jumped };
|
|
2671
|
-
}
|
|
2672
|
-
if (!nextOnGround) {
|
|
2673
|
-
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, jumpSound, jumped };
|
|
2674
|
-
}
|
|
2675
|
-
nextFlags = addPmFlag(nextFlags, 2 /* JumpHeld */);
|
|
2676
|
-
nextFlags = removePmFlag(nextFlags, 4 /* OnGround */);
|
|
2677
|
-
nextOnGround = false;
|
|
2678
|
-
jumpSound = true;
|
|
2679
|
-
jumped = true;
|
|
2680
|
-
const z = velocity.z + jumpHeight;
|
|
2681
|
-
const finalZ = z < jumpHeight ? jumpHeight : z;
|
|
2682
|
-
nextVelocity = { ...velocity, z: finalZ };
|
|
2683
|
-
return { pmFlags: nextFlags, onGround: nextOnGround, velocity: nextVelocity, jumpSound, jumped };
|
|
2684
|
-
}
|
|
2685
|
-
function hasPmJumpHold(flags) {
|
|
2686
|
-
return (flags & 2 /* JumpHeld */) !== 0;
|
|
2687
|
-
}
|
|
2688
|
-
|
|
2689
|
-
// src/pmove/dimensions.ts
|
|
2690
|
-
function createVec3(x, y, z) {
|
|
2691
|
-
return { x, y, z };
|
|
2692
|
-
}
|
|
2693
|
-
function computePlayerDimensions(pmType, pmFlags) {
|
|
2694
|
-
const minsBase = createVec3(-16, -16, 0);
|
|
2695
|
-
const maxsBase = createVec3(16, 16, 16);
|
|
2696
|
-
if (pmType === 5 /* Gib */) {
|
|
2697
|
-
return {
|
|
2698
|
-
mins: minsBase,
|
|
2699
|
-
maxs: maxsBase,
|
|
2700
|
-
viewheight: 8
|
|
2701
|
-
};
|
|
2702
|
-
}
|
|
2703
|
-
const ducked = pmType === 4 /* Dead */ || (pmFlags & 1 /* Ducked */) !== 0;
|
|
2704
|
-
const mins = createVec3(minsBase.x, minsBase.y, -24);
|
|
2705
|
-
const maxs = createVec3(maxsBase.x, maxsBase.y, ducked ? 4 : 32);
|
|
2706
|
-
return {
|
|
2707
|
-
mins,
|
|
2708
|
-
maxs,
|
|
2709
|
-
viewheight: ducked ? -2 : 22
|
|
2710
|
-
};
|
|
2711
|
-
}
|
|
2712
|
-
|
|
2713
|
-
// src/pmove/duck.ts
|
|
2714
|
-
var CROUCH_MAX_Z = 4;
|
|
2715
|
-
var STAND_MAX_Z = 32;
|
|
2716
|
-
var ABOVE_WATER_OFFSET = 8;
|
|
2717
|
-
function checkDuckState(params) {
|
|
2718
|
-
const { pmType } = params;
|
|
2719
|
-
if (pmType === 5 /* Gib */) {
|
|
2720
|
-
const dims2 = computePlayerDimensions(pmType, params.pmFlags);
|
|
2721
|
-
return { pmFlags: params.pmFlags, ducked: hasPmFlag(params.pmFlags, 1 /* Ducked */), changed: false, ...dims2 };
|
|
2722
|
-
}
|
|
2723
|
-
let flags = params.pmFlags;
|
|
2724
|
-
let changed = false;
|
|
2725
|
-
if (pmType === 4 /* Dead */) {
|
|
2726
|
-
if (!hasPmFlag(flags, 1 /* Ducked */)) {
|
|
2727
|
-
flags = addPmFlag(flags, 1 /* Ducked */);
|
|
2728
|
-
changed = true;
|
|
2729
|
-
}
|
|
2730
|
-
} else if (shouldDuck(params)) {
|
|
2731
|
-
if (!hasPmFlag(flags, 1 /* Ducked */) && !isDuckBlocked(params)) {
|
|
2732
|
-
flags = addPmFlag(flags, 1 /* Ducked */);
|
|
2733
|
-
changed = true;
|
|
2734
|
-
}
|
|
2735
|
-
} else if (hasPmFlag(flags, 1 /* Ducked */) && !isStandBlocked(params)) {
|
|
2736
|
-
flags = removePmFlag(flags, 1 /* Ducked */);
|
|
2737
|
-
changed = true;
|
|
2738
|
-
}
|
|
2739
|
-
const dims = computePlayerDimensions(pmType, flags);
|
|
2740
|
-
const ducked = pmType === 4 /* Dead */ || hasPmFlag(flags, 1 /* Ducked */);
|
|
2741
|
-
return { pmFlags: flags, ducked, changed, ...dims };
|
|
2742
|
-
}
|
|
2743
|
-
function shouldDuck(params) {
|
|
2744
|
-
if ((params.buttons & 16 /* Crouch */) === 0) {
|
|
2745
|
-
return false;
|
|
2746
|
-
}
|
|
2747
|
-
if (params.onLadder || params.n64Physics) {
|
|
2748
|
-
return false;
|
|
2749
|
-
}
|
|
2750
|
-
if (params.hasGroundEntity) {
|
|
2751
|
-
return true;
|
|
2752
|
-
}
|
|
2753
|
-
if (params.waterlevel <= 1 /* Feet */ && !isAboveWater(params)) {
|
|
2754
|
-
return true;
|
|
2755
|
-
}
|
|
2756
|
-
return false;
|
|
2757
|
-
}
|
|
2758
|
-
function isDuckBlocked(params) {
|
|
2759
|
-
const trace = params.trace({
|
|
2760
|
-
start: params.origin,
|
|
2761
|
-
end: params.origin,
|
|
2762
|
-
mins: params.mins,
|
|
2763
|
-
maxs: withZ(params.maxs, CROUCH_MAX_Z),
|
|
2764
|
-
mask: MASK_SOLID
|
|
2765
|
-
});
|
|
2766
|
-
return trace.allsolid;
|
|
2767
|
-
}
|
|
2768
|
-
function isStandBlocked(params) {
|
|
2769
|
-
const trace = params.trace({
|
|
2770
|
-
start: params.origin,
|
|
2771
|
-
end: params.origin,
|
|
2772
|
-
mins: params.mins,
|
|
2773
|
-
maxs: withZ(params.maxs, STAND_MAX_Z),
|
|
2774
|
-
mask: MASK_SOLID
|
|
2775
|
-
});
|
|
2776
|
-
return trace.allsolid;
|
|
2777
|
-
}
|
|
2778
|
-
function isAboveWater(params) {
|
|
2779
|
-
const below = { x: params.origin.x, y: params.origin.y, z: params.origin.z - ABOVE_WATER_OFFSET };
|
|
2780
|
-
const solidTrace = params.trace({
|
|
2781
|
-
start: params.origin,
|
|
2782
|
-
end: below,
|
|
2783
|
-
mins: params.mins,
|
|
2784
|
-
maxs: params.maxs,
|
|
2785
|
-
mask: MASK_SOLID
|
|
2786
|
-
});
|
|
2787
|
-
if (solidTrace.fraction < 1) {
|
|
2788
|
-
return false;
|
|
2789
|
-
}
|
|
2790
|
-
const waterTrace = params.trace({
|
|
2791
|
-
start: params.origin,
|
|
2792
|
-
end: below,
|
|
2793
|
-
mins: params.mins,
|
|
2794
|
-
maxs: params.maxs,
|
|
2795
|
-
mask: MASK_WATER
|
|
2796
|
-
});
|
|
2797
|
-
return waterTrace.fraction < 1;
|
|
2798
|
-
}
|
|
2799
|
-
function withZ(vec, z) {
|
|
2800
|
-
return { x: vec.x, y: vec.y, z };
|
|
2801
|
-
}
|
|
2802
|
-
|
|
2803
|
-
// src/pmove/categorize.ts
|
|
2804
|
-
var GROUND_PROBE_DISTANCE = 0.25;
|
|
2805
|
-
var LADDER_BYPASS_VELOCITY = 180;
|
|
2806
|
-
var TRICK_VELOCITY_THRESHOLD = 100;
|
|
2807
|
-
var SLANTED_NORMAL_THRESHOLD = 0.7;
|
|
2808
|
-
var TRICK_NORMAL_THRESHOLD = 0.9;
|
|
2809
|
-
var TRICK_PM_TIME = 64;
|
|
2810
|
-
var LAND_PM_TIME = 128;
|
|
2811
|
-
var IMPACT_CLIP_OVERBOUNCE = 1.01;
|
|
2812
|
-
var WATERJUMP_CLEAR = 8 /* TimeWaterJump */ | 16 /* TimeLand */ | 32 /* TimeTeleport */ | 1024 /* TimeTrick */;
|
|
2813
|
-
function categorizePosition(params) {
|
|
2814
|
-
const {
|
|
2815
|
-
pmType,
|
|
2816
|
-
n64Physics,
|
|
2817
|
-
velocity,
|
|
2818
|
-
startVelocity,
|
|
2819
|
-
origin,
|
|
2663
|
+
// src/pmove/categorize.ts
|
|
2664
|
+
var GROUND_PROBE_DISTANCE = 0.25;
|
|
2665
|
+
var LADDER_BYPASS_VELOCITY = 180;
|
|
2666
|
+
var TRICK_VELOCITY_THRESHOLD = 100;
|
|
2667
|
+
var SLANTED_NORMAL_THRESHOLD = 0.7;
|
|
2668
|
+
var TRICK_NORMAL_THRESHOLD = 0.9;
|
|
2669
|
+
var TRICK_PM_TIME = 64;
|
|
2670
|
+
var LAND_PM_TIME = 128;
|
|
2671
|
+
var IMPACT_CLIP_OVERBOUNCE = 1.01;
|
|
2672
|
+
var WATERJUMP_CLEAR = 8 /* TimeWaterJump */ | 16 /* TimeLand */ | 32 /* TimeTeleport */ | 1024 /* TimeTrick */;
|
|
2673
|
+
function categorizePosition(params) {
|
|
2674
|
+
const {
|
|
2675
|
+
pmType,
|
|
2676
|
+
n64Physics,
|
|
2677
|
+
velocity,
|
|
2678
|
+
startVelocity,
|
|
2679
|
+
origin,
|
|
2820
2680
|
mins,
|
|
2821
2681
|
maxs,
|
|
2822
2682
|
viewheight,
|
|
@@ -2890,304 +2750,744 @@ function categorizePosition(params) {
|
|
|
2890
2750
|
};
|
|
2891
2751
|
}
|
|
2892
2752
|
|
|
2893
|
-
// src/pmove/
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
function
|
|
2898
|
-
const
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
cmd,
|
|
2912
|
-
pmFlags,
|
|
2913
|
-
onGround,
|
|
2914
|
-
gravity,
|
|
2915
|
-
pmType,
|
|
2916
|
-
pmAccelerate,
|
|
2917
|
-
pmAirAccelerate = DEFAULT_AIR_ACCELERATE,
|
|
2918
|
-
pmMaxSpeed,
|
|
2919
|
-
pmDuckSpeed,
|
|
2920
|
-
onLadder,
|
|
2921
|
-
waterlevel,
|
|
2922
|
-
watertype,
|
|
2923
|
-
groundContents,
|
|
2924
|
-
viewPitch,
|
|
2925
|
-
ladderMod,
|
|
2926
|
-
pmWaterSpeed
|
|
2927
|
-
} = params;
|
|
2928
|
-
let velocity = { ...params.velocity };
|
|
2929
|
-
let wishvel = buildPlanarWishVelocity(forward, right, cmd);
|
|
2930
|
-
wishvel = applyPmoveAddCurrents({
|
|
2931
|
-
wishVelocity: wishvel,
|
|
2932
|
-
onLadder,
|
|
2933
|
-
onGround,
|
|
2934
|
-
waterlevel,
|
|
2935
|
-
watertype,
|
|
2936
|
-
groundContents,
|
|
2937
|
-
cmd,
|
|
2938
|
-
viewPitch,
|
|
2939
|
-
maxSpeed: hasPmFlag(pmFlags, 1 /* Ducked */) ? pmDuckSpeed : pmMaxSpeed,
|
|
2940
|
-
ladderMod,
|
|
2941
|
-
waterSpeed: pmWaterSpeed,
|
|
2942
|
-
forward,
|
|
2943
|
-
origin,
|
|
2753
|
+
// src/pmove/dimensions.ts
|
|
2754
|
+
function createVec3(x, y, z) {
|
|
2755
|
+
return { x, y, z };
|
|
2756
|
+
}
|
|
2757
|
+
function computePlayerDimensions(pmType, pmFlags) {
|
|
2758
|
+
const minsBase = createVec3(-16, -16, 0);
|
|
2759
|
+
const maxsBase = createVec3(16, 16, 16);
|
|
2760
|
+
if (pmType === 5 /* Gib */) {
|
|
2761
|
+
return {
|
|
2762
|
+
mins: minsBase,
|
|
2763
|
+
maxs: maxsBase,
|
|
2764
|
+
viewheight: 8
|
|
2765
|
+
};
|
|
2766
|
+
}
|
|
2767
|
+
const ducked = pmType === 4 /* Dead */ || (pmFlags & 1 /* Ducked */) !== 0;
|
|
2768
|
+
const mins = createVec3(minsBase.x, minsBase.y, -24);
|
|
2769
|
+
const maxs = createVec3(maxsBase.x, maxsBase.y, ducked ? 4 : 32);
|
|
2770
|
+
return {
|
|
2944
2771
|
mins,
|
|
2945
2772
|
maxs,
|
|
2946
|
-
|
|
2947
|
-
}
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2773
|
+
viewheight: ducked ? -2 : 22
|
|
2774
|
+
};
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
// src/pmove/duck.ts
|
|
2778
|
+
var CROUCH_MAX_Z = 4;
|
|
2779
|
+
var STAND_MAX_Z = 32;
|
|
2780
|
+
var ABOVE_WATER_OFFSET = 8;
|
|
2781
|
+
function checkDuckState(params) {
|
|
2782
|
+
const { pmType } = params;
|
|
2783
|
+
if (pmType === 5 /* Gib */) {
|
|
2784
|
+
const dims2 = computePlayerDimensions(pmType, params.pmFlags);
|
|
2785
|
+
return { pmFlags: params.pmFlags, ducked: hasPmFlag(params.pmFlags, 1 /* Ducked */), changed: false, ...dims2 };
|
|
2954
2786
|
}
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2787
|
+
let flags = params.pmFlags;
|
|
2788
|
+
let changed = false;
|
|
2789
|
+
if (pmType === 4 /* Dead */) {
|
|
2790
|
+
if (!hasPmFlag(flags, 1 /* Ducked */)) {
|
|
2791
|
+
flags = addPmFlag(flags, 1 /* Ducked */);
|
|
2792
|
+
changed = true;
|
|
2961
2793
|
}
|
|
2962
|
-
}
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
velocity = dampVerticalVelocity(velocity, gravity, frametime);
|
|
2794
|
+
} else if (shouldDuck(params)) {
|
|
2795
|
+
if (!hasPmFlag(flags, 1 /* Ducked */) && !isDuckBlocked(params)) {
|
|
2796
|
+
flags = addPmFlag(flags, 1 /* Ducked */);
|
|
2797
|
+
changed = true;
|
|
2967
2798
|
}
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
frametime,
|
|
2972
|
-
mins,
|
|
2973
|
-
maxs,
|
|
2974
|
-
trace,
|
|
2975
|
-
overbounce,
|
|
2976
|
-
stepSize,
|
|
2977
|
-
maxBumps,
|
|
2978
|
-
maxClipPlanes,
|
|
2979
|
-
hasTime
|
|
2980
|
-
});
|
|
2799
|
+
} else if (hasPmFlag(flags, 1 /* Ducked */) && !isStandBlocked(params)) {
|
|
2800
|
+
flags = removePmFlag(flags, 1 /* Ducked */);
|
|
2801
|
+
changed = true;
|
|
2981
2802
|
}
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
}
|
|
2990
|
-
if (velocity.x === 0 && velocity.y === 0) {
|
|
2991
|
-
return {
|
|
2992
|
-
origin,
|
|
2993
|
-
velocity,
|
|
2994
|
-
planes: [],
|
|
2995
|
-
blocked: 0,
|
|
2996
|
-
stopped: true,
|
|
2997
|
-
stepped: false,
|
|
2998
|
-
stepHeight: 0
|
|
2999
|
-
};
|
|
3000
|
-
}
|
|
3001
|
-
return runStepSlideMove({
|
|
3002
|
-
origin,
|
|
3003
|
-
velocity,
|
|
3004
|
-
frametime,
|
|
3005
|
-
mins,
|
|
3006
|
-
maxs,
|
|
3007
|
-
trace,
|
|
3008
|
-
overbounce,
|
|
3009
|
-
stepSize,
|
|
3010
|
-
maxBumps,
|
|
3011
|
-
maxClipPlanes,
|
|
3012
|
-
hasTime
|
|
3013
|
-
});
|
|
2803
|
+
const dims = computePlayerDimensions(pmType, flags);
|
|
2804
|
+
const ducked = pmType === 4 /* Dead */ || hasPmFlag(flags, 1 /* Ducked */);
|
|
2805
|
+
return { pmFlags: flags, ducked, changed, ...dims };
|
|
2806
|
+
}
|
|
2807
|
+
function shouldDuck(params) {
|
|
2808
|
+
if ((params.buttons & 16 /* Crouch */) === 0) {
|
|
2809
|
+
return false;
|
|
3014
2810
|
}
|
|
3015
|
-
if (
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
2811
|
+
if (params.onLadder || params.n64Physics) {
|
|
2812
|
+
return false;
|
|
2813
|
+
}
|
|
2814
|
+
if (params.hasGroundEntity) {
|
|
2815
|
+
return true;
|
|
2816
|
+
}
|
|
2817
|
+
if (params.waterlevel <= 1 /* Feet */ && !isAboveWater(params)) {
|
|
2818
|
+
return true;
|
|
2819
|
+
}
|
|
2820
|
+
return false;
|
|
2821
|
+
}
|
|
2822
|
+
function isDuckBlocked(params) {
|
|
2823
|
+
const trace = params.trace({
|
|
2824
|
+
start: params.origin,
|
|
2825
|
+
end: params.origin,
|
|
2826
|
+
mins: params.mins,
|
|
2827
|
+
maxs: withZ(params.maxs, CROUCH_MAX_Z),
|
|
2828
|
+
mask: MASK_SOLID
|
|
2829
|
+
});
|
|
2830
|
+
return trace.allsolid;
|
|
2831
|
+
}
|
|
2832
|
+
function isStandBlocked(params) {
|
|
2833
|
+
const trace = params.trace({
|
|
2834
|
+
start: params.origin,
|
|
2835
|
+
end: params.origin,
|
|
2836
|
+
mins: params.mins,
|
|
2837
|
+
maxs: withZ(params.maxs, STAND_MAX_Z),
|
|
2838
|
+
mask: MASK_SOLID
|
|
2839
|
+
});
|
|
2840
|
+
return trace.allsolid;
|
|
2841
|
+
}
|
|
2842
|
+
function isAboveWater(params) {
|
|
2843
|
+
const below = { x: params.origin.x, y: params.origin.y, z: params.origin.z - ABOVE_WATER_OFFSET };
|
|
2844
|
+
const solidTrace = params.trace({
|
|
2845
|
+
start: params.origin,
|
|
2846
|
+
end: below,
|
|
2847
|
+
mins: params.mins,
|
|
2848
|
+
maxs: params.maxs,
|
|
2849
|
+
mask: MASK_SOLID
|
|
2850
|
+
});
|
|
2851
|
+
if (solidTrace.fraction < 1) {
|
|
2852
|
+
return false;
|
|
2853
|
+
}
|
|
2854
|
+
const waterTrace = params.trace({
|
|
2855
|
+
start: params.origin,
|
|
2856
|
+
end: below,
|
|
2857
|
+
mins: params.mins,
|
|
2858
|
+
maxs: params.maxs,
|
|
2859
|
+
mask: MASK_WATER
|
|
2860
|
+
});
|
|
2861
|
+
return waterTrace.fraction < 1;
|
|
2862
|
+
}
|
|
2863
|
+
function withZ(vec, z) {
|
|
2864
|
+
return { x: vec.x, y: vec.y, z };
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
// src/pmove/pmove.ts
|
|
2868
|
+
var FRAMETIME = 0.025;
|
|
2869
|
+
function applyPmoveFriction(params) {
|
|
2870
|
+
const {
|
|
2871
|
+
velocity,
|
|
2872
|
+
frametime,
|
|
2873
|
+
onGround,
|
|
2874
|
+
groundIsSlick,
|
|
2875
|
+
onLadder,
|
|
2876
|
+
waterlevel,
|
|
2877
|
+
pmFriction,
|
|
2878
|
+
pmStopSpeed,
|
|
2879
|
+
pmWaterFriction
|
|
2880
|
+
} = params;
|
|
2881
|
+
const speed = lengthVec3(velocity);
|
|
2882
|
+
if (speed < 1) {
|
|
2883
|
+
return { x: 0, y: 0, z: velocity.z };
|
|
2884
|
+
}
|
|
2885
|
+
let drop = 0;
|
|
2886
|
+
if (onGround && !groundIsSlick || onLadder) {
|
|
2887
|
+
const control = speed < pmStopSpeed ? pmStopSpeed : speed;
|
|
2888
|
+
const friction = pmFriction;
|
|
2889
|
+
drop += control * friction * frametime;
|
|
2890
|
+
}
|
|
2891
|
+
if (waterlevel > 0 && !onLadder) {
|
|
2892
|
+
drop += speed * pmWaterFriction * waterlevel * frametime;
|
|
2893
|
+
}
|
|
2894
|
+
let newspeed = speed - drop;
|
|
2895
|
+
if (newspeed < 0) {
|
|
2896
|
+
newspeed = 0;
|
|
2897
|
+
}
|
|
2898
|
+
if (newspeed === speed) {
|
|
2899
|
+
return velocity;
|
|
2900
|
+
}
|
|
2901
|
+
const scale = newspeed / speed;
|
|
2902
|
+
return scaleVec3(velocity, scale);
|
|
2903
|
+
}
|
|
2904
|
+
function applyPmoveAccelerate(params) {
|
|
2905
|
+
const { velocity, wishdir, wishspeed, accel, frametime } = params;
|
|
2906
|
+
const currentSpeed = dotVec3(velocity, wishdir);
|
|
2907
|
+
const addSpeed = wishspeed - currentSpeed;
|
|
2908
|
+
if (addSpeed <= 0) {
|
|
2909
|
+
return velocity;
|
|
2910
|
+
}
|
|
2911
|
+
let accelSpeed = accel * frametime * wishspeed;
|
|
2912
|
+
if (accelSpeed > addSpeed) {
|
|
2913
|
+
accelSpeed = addSpeed;
|
|
2914
|
+
}
|
|
2915
|
+
return {
|
|
2916
|
+
x: velocity.x + wishdir.x * accelSpeed,
|
|
2917
|
+
y: velocity.y + wishdir.y * accelSpeed,
|
|
2918
|
+
z: velocity.z + wishdir.z * accelSpeed
|
|
2919
|
+
};
|
|
2920
|
+
}
|
|
2921
|
+
function applyPmoveAirAccelerate(params) {
|
|
2922
|
+
const { velocity, wishdir, wishspeed, accel, frametime } = params;
|
|
2923
|
+
const wishspd = Math.min(wishspeed, 30);
|
|
2924
|
+
const currentSpeed = dotVec3(velocity, wishdir);
|
|
2925
|
+
const addSpeed = wishspd - currentSpeed;
|
|
2926
|
+
if (addSpeed <= 0) {
|
|
2927
|
+
return velocity;
|
|
2928
|
+
}
|
|
2929
|
+
let accelSpeed = accel * wishspeed * frametime;
|
|
2930
|
+
if (accelSpeed > addSpeed) {
|
|
2931
|
+
accelSpeed = addSpeed;
|
|
2932
|
+
}
|
|
2933
|
+
return {
|
|
2934
|
+
x: velocity.x + wishdir.x * accelSpeed,
|
|
2935
|
+
y: velocity.y + wishdir.y * accelSpeed,
|
|
2936
|
+
z: velocity.z + wishdir.z * accelSpeed
|
|
2937
|
+
};
|
|
2938
|
+
}
|
|
2939
|
+
function pmoveCmdScale(cmd, maxSpeed) {
|
|
2940
|
+
const forward = Math.abs(cmd.forwardmove);
|
|
2941
|
+
const side = Math.abs(cmd.sidemove);
|
|
2942
|
+
const up = Math.abs(cmd.upmove);
|
|
2943
|
+
const max = Math.max(forward, side, up);
|
|
2944
|
+
if (max === 0) {
|
|
2945
|
+
return 0;
|
|
2946
|
+
}
|
|
2947
|
+
const total = Math.sqrt(cmd.forwardmove * cmd.forwardmove + cmd.sidemove * cmd.sidemove + cmd.upmove * cmd.upmove);
|
|
2948
|
+
return maxSpeed * max / (127 * total);
|
|
2949
|
+
}
|
|
2950
|
+
function buildAirGroundWish(params) {
|
|
2951
|
+
const { forward, right, cmd, maxSpeed } = params;
|
|
2952
|
+
let wishvel = {
|
|
2953
|
+
x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
|
|
2954
|
+
y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
|
|
2955
|
+
z: 0
|
|
2956
|
+
};
|
|
2957
|
+
let wishspeed = lengthVec3(wishvel);
|
|
2958
|
+
if (wishspeed > maxSpeed) {
|
|
2959
|
+
const scale = maxSpeed / wishspeed;
|
|
2960
|
+
wishvel = scaleVec3(wishvel, scale);
|
|
2961
|
+
wishspeed = maxSpeed;
|
|
2962
|
+
}
|
|
2963
|
+
return {
|
|
2964
|
+
wishdir: wishspeed === 0 ? wishvel : normalizeVec3(wishvel),
|
|
2965
|
+
wishspeed
|
|
2966
|
+
};
|
|
2967
|
+
}
|
|
2968
|
+
function buildWaterWish(params) {
|
|
2969
|
+
const { forward, right, cmd, maxSpeed } = params;
|
|
2970
|
+
let wishvel = {
|
|
2971
|
+
x: forward.x * cmd.forwardmove + right.x * cmd.sidemove,
|
|
2972
|
+
y: forward.y * cmd.forwardmove + right.y * cmd.sidemove,
|
|
2973
|
+
z: forward.z * cmd.forwardmove + right.z * cmd.sidemove
|
|
2974
|
+
};
|
|
2975
|
+
if (cmd.upmove > 10) {
|
|
2976
|
+
wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
|
|
2977
|
+
} else if (cmd.upmove < -10) {
|
|
2978
|
+
wishvel = addVec3(wishvel, { x: 0, y: 0, z: cmd.upmove });
|
|
2979
|
+
} else if (Math.abs(cmd.forwardmove) < 10 && Math.abs(cmd.sidemove) < 10) {
|
|
2980
|
+
wishvel = addVec3(wishvel, { x: 0, y: 0, z: -60 });
|
|
3023
2981
|
} else {
|
|
3024
|
-
|
|
2982
|
+
wishvel = addVec3(wishvel, { x: 0, y: 0, z: 10 });
|
|
2983
|
+
}
|
|
2984
|
+
let wishspeed = lengthVec3(wishvel);
|
|
2985
|
+
if (wishspeed > maxSpeed) {
|
|
2986
|
+
const scale = maxSpeed / wishspeed;
|
|
2987
|
+
wishvel = scaleVec3(wishvel, scale);
|
|
2988
|
+
wishspeed = maxSpeed;
|
|
2989
|
+
}
|
|
2990
|
+
wishspeed *= 0.5;
|
|
2991
|
+
return {
|
|
2992
|
+
wishdir: wishspeed === 0 ? wishvel : normalizeVec3(wishvel),
|
|
2993
|
+
wishspeed
|
|
2994
|
+
};
|
|
2995
|
+
}
|
|
2996
|
+
function runPmove(state, imports) {
|
|
2997
|
+
if (state.pmType === 4 /* Dead */) {
|
|
2998
|
+
return state;
|
|
2999
|
+
}
|
|
3000
|
+
let nextState = { ...state };
|
|
3001
|
+
const catResult = categorizePosition({
|
|
3002
|
+
pmType: nextState.pmType,
|
|
3003
|
+
pmFlags: nextState.pmFlags,
|
|
3004
|
+
pmTime: 0,
|
|
3005
|
+
n64Physics: false,
|
|
3006
|
+
velocity: nextState.velocity,
|
|
3007
|
+
startVelocity: nextState.velocity,
|
|
3008
|
+
origin: nextState.origin,
|
|
3009
|
+
mins: nextState.mins,
|
|
3010
|
+
maxs: nextState.maxs,
|
|
3011
|
+
viewheight: nextState.viewHeight,
|
|
3012
|
+
trace: imports.trace,
|
|
3013
|
+
pointContents: imports.pointcontents
|
|
3014
|
+
});
|
|
3015
|
+
nextState.pmFlags = catResult.pmFlags;
|
|
3016
|
+
nextState.waterlevel = catResult.waterlevel;
|
|
3017
|
+
nextState.watertype = catResult.watertype;
|
|
3018
|
+
const duckResult = checkDuckState({
|
|
3019
|
+
pmType: nextState.pmType,
|
|
3020
|
+
pmFlags: nextState.pmFlags,
|
|
3021
|
+
buttons: nextState.cmd.buttons,
|
|
3022
|
+
waterlevel: nextState.waterlevel,
|
|
3023
|
+
hasGroundEntity: (nextState.pmFlags & 4 /* OnGround */) !== 0,
|
|
3024
|
+
onLadder: false,
|
|
3025
|
+
n64Physics: false,
|
|
3026
|
+
origin: nextState.origin,
|
|
3027
|
+
mins: nextState.mins,
|
|
3028
|
+
maxs: nextState.maxs,
|
|
3029
|
+
trace: (params) => {
|
|
3030
|
+
return imports.trace(params.start, params.end, params.mins, params.maxs);
|
|
3031
|
+
}
|
|
3032
|
+
});
|
|
3033
|
+
nextState.pmFlags = duckResult.pmFlags;
|
|
3034
|
+
nextState.mins = duckResult.mins;
|
|
3035
|
+
nextState.maxs = duckResult.maxs;
|
|
3036
|
+
nextState.viewHeight = duckResult.viewheight;
|
|
3037
|
+
const jumpResult = checkJump({
|
|
3038
|
+
pmFlags: nextState.pmFlags,
|
|
3039
|
+
pmType: nextState.pmType,
|
|
3040
|
+
buttons: nextState.cmd.buttons,
|
|
3041
|
+
waterlevel: nextState.waterlevel,
|
|
3042
|
+
onGround: (nextState.pmFlags & 4 /* OnGround */) !== 0,
|
|
3043
|
+
velocity: nextState.velocity,
|
|
3044
|
+
origin: nextState.origin
|
|
3045
|
+
});
|
|
3046
|
+
nextState.pmFlags = jumpResult.pmFlags;
|
|
3047
|
+
nextState.velocity = jumpResult.velocity;
|
|
3048
|
+
nextState.origin = jumpResult.origin;
|
|
3049
|
+
if (jumpResult.onGround !== ((nextState.pmFlags & 4 /* OnGround */) !== 0)) {
|
|
3050
|
+
if (jumpResult.onGround) {
|
|
3051
|
+
nextState.pmFlags = addPmFlag(nextState.pmFlags, 4 /* OnGround */);
|
|
3052
|
+
} else {
|
|
3053
|
+
nextState.pmFlags = removePmFlag(nextState.pmFlags, 4 /* OnGround */);
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
const onGround = (nextState.pmFlags & 4 /* OnGround */) !== 0;
|
|
3057
|
+
const velocityBeforeFriction = nextState.velocity;
|
|
3058
|
+
nextState.velocity = applyPmoveFriction({
|
|
3059
|
+
velocity: nextState.velocity,
|
|
3060
|
+
frametime: FRAMETIME,
|
|
3061
|
+
onGround,
|
|
3062
|
+
groundIsSlick: false,
|
|
3063
|
+
onLadder: false,
|
|
3064
|
+
// Defaulting to false for now as ladder logic is complex
|
|
3065
|
+
waterlevel: nextState.waterlevel,
|
|
3066
|
+
pmFriction: 6,
|
|
3067
|
+
// Default
|
|
3068
|
+
pmStopSpeed: 100,
|
|
3069
|
+
// Default
|
|
3070
|
+
pmWaterFriction: 1
|
|
3071
|
+
// Default
|
|
3072
|
+
});
|
|
3073
|
+
const { forward, right } = angleVectors(nextState.viewAngles);
|
|
3074
|
+
if (nextState.pmType === 2 /* NoClip */) {
|
|
3075
|
+
const wishvel = {
|
|
3076
|
+
x: forward.x * nextState.cmd.forwardmove + right.x * nextState.cmd.sidemove,
|
|
3077
|
+
y: forward.y * nextState.cmd.forwardmove + right.y * nextState.cmd.sidemove,
|
|
3078
|
+
z: nextState.cmd.upmove
|
|
3079
|
+
};
|
|
3080
|
+
const scale = FRAMETIME;
|
|
3081
|
+
nextState.velocity = wishvel;
|
|
3082
|
+
nextState.origin = {
|
|
3083
|
+
x: nextState.origin.x + wishvel.x * scale,
|
|
3084
|
+
y: nextState.origin.y + wishvel.y * scale,
|
|
3085
|
+
z: nextState.origin.z + wishvel.z * scale
|
|
3086
|
+
};
|
|
3087
|
+
} else if (nextState.waterlevel >= 2) {
|
|
3088
|
+
const outcome = applyPmoveWaterMove({
|
|
3089
|
+
origin: nextState.origin,
|
|
3090
|
+
velocity: nextState.velocity,
|
|
3091
|
+
frametime: FRAMETIME,
|
|
3092
|
+
mins: nextState.mins,
|
|
3093
|
+
maxs: nextState.maxs,
|
|
3094
|
+
trace: imports.trace,
|
|
3095
|
+
cmd: nextState.cmd,
|
|
3096
|
+
forward,
|
|
3097
|
+
right,
|
|
3098
|
+
pmFlags: nextState.pmFlags,
|
|
3099
|
+
onGround,
|
|
3100
|
+
pmMaxSpeed: 300,
|
|
3101
|
+
pmDuckSpeed: 100,
|
|
3102
|
+
pmWaterAccelerate: 4,
|
|
3103
|
+
pmWaterSpeed: 400,
|
|
3104
|
+
onLadder: false,
|
|
3105
|
+
watertype: nextState.watertype,
|
|
3106
|
+
groundContents: 0,
|
|
3107
|
+
// Should be passed in?
|
|
3108
|
+
waterlevel: nextState.waterlevel,
|
|
3109
|
+
viewPitch: nextState.viewAngles.x,
|
|
3110
|
+
ladderMod: 1,
|
|
3111
|
+
stepSize: 18
|
|
3112
|
+
// Added stepSize for consistency, though water move might not use it heavily
|
|
3113
|
+
});
|
|
3114
|
+
nextState.origin = outcome.origin;
|
|
3115
|
+
nextState.velocity = outcome.velocity;
|
|
3116
|
+
} else if ((nextState.pmFlags & 4 /* OnGround */) === 0) {
|
|
3117
|
+
const outcome = applyPmoveAirMove({
|
|
3118
|
+
origin: nextState.origin,
|
|
3119
|
+
velocity: nextState.velocity,
|
|
3120
|
+
frametime: FRAMETIME,
|
|
3121
|
+
mins: nextState.mins,
|
|
3122
|
+
maxs: nextState.maxs,
|
|
3123
|
+
trace: imports.trace,
|
|
3124
|
+
cmd: nextState.cmd,
|
|
3125
|
+
forward,
|
|
3126
|
+
right,
|
|
3127
|
+
pmFlags: nextState.pmFlags,
|
|
3128
|
+
onGround,
|
|
3129
|
+
gravity: nextState.gravity,
|
|
3130
|
+
pmType: nextState.pmType,
|
|
3131
|
+
pmAccelerate: 10,
|
|
3132
|
+
pmAirAccelerate: 1,
|
|
3133
|
+
pmMaxSpeed: 300,
|
|
3134
|
+
pmDuckSpeed: 100,
|
|
3135
|
+
onLadder: false,
|
|
3136
|
+
waterlevel: nextState.waterlevel,
|
|
3137
|
+
watertype: nextState.watertype,
|
|
3138
|
+
groundContents: 0,
|
|
3139
|
+
viewPitch: nextState.viewAngles.x,
|
|
3140
|
+
ladderMod: 1,
|
|
3141
|
+
pmWaterSpeed: 400,
|
|
3142
|
+
stepSize: 18
|
|
3143
|
+
// Added stepSize
|
|
3144
|
+
});
|
|
3145
|
+
nextState.origin = outcome.origin;
|
|
3146
|
+
nextState.velocity = outcome.velocity;
|
|
3147
|
+
} else {
|
|
3148
|
+
const outcome = applyPmoveWalkMove({
|
|
3149
|
+
origin: nextState.origin,
|
|
3150
|
+
velocity: nextState.velocity,
|
|
3151
|
+
frametime: FRAMETIME,
|
|
3152
|
+
mins: nextState.mins,
|
|
3153
|
+
maxs: nextState.maxs,
|
|
3154
|
+
trace: imports.trace,
|
|
3155
|
+
cmd: nextState.cmd,
|
|
3156
|
+
forward,
|
|
3157
|
+
right,
|
|
3158
|
+
pmFlags: nextState.pmFlags,
|
|
3159
|
+
onGround,
|
|
3160
|
+
gravity: nextState.gravity,
|
|
3161
|
+
pmType: nextState.pmType,
|
|
3162
|
+
pmAccelerate: 10,
|
|
3163
|
+
pmMaxSpeed: 300,
|
|
3164
|
+
pmDuckSpeed: 100,
|
|
3165
|
+
onLadder: false,
|
|
3166
|
+
waterlevel: nextState.waterlevel,
|
|
3167
|
+
watertype: nextState.watertype,
|
|
3168
|
+
groundContents: 0,
|
|
3169
|
+
viewPitch: nextState.viewAngles.x,
|
|
3170
|
+
ladderMod: 1,
|
|
3171
|
+
pmWaterSpeed: 400,
|
|
3172
|
+
stepSize: 18
|
|
3173
|
+
// Added stepSize
|
|
3174
|
+
});
|
|
3175
|
+
nextState.origin = outcome.origin;
|
|
3176
|
+
nextState.velocity = outcome.velocity;
|
|
3177
|
+
}
|
|
3178
|
+
const catResultEnd = categorizePosition({
|
|
3179
|
+
pmType: nextState.pmType,
|
|
3180
|
+
pmFlags: nextState.pmFlags,
|
|
3181
|
+
pmTime: 0,
|
|
3182
|
+
n64Physics: false,
|
|
3183
|
+
velocity: nextState.velocity,
|
|
3184
|
+
startVelocity: nextState.velocity,
|
|
3185
|
+
origin: nextState.origin,
|
|
3186
|
+
mins: nextState.mins,
|
|
3187
|
+
maxs: nextState.maxs,
|
|
3188
|
+
viewheight: nextState.viewHeight,
|
|
3189
|
+
trace: imports.trace,
|
|
3190
|
+
pointContents: imports.pointcontents
|
|
3191
|
+
});
|
|
3192
|
+
nextState.pmFlags = catResultEnd.pmFlags;
|
|
3193
|
+
nextState.waterlevel = catResultEnd.waterlevel;
|
|
3194
|
+
nextState.watertype = catResultEnd.watertype;
|
|
3195
|
+
return nextState;
|
|
3196
|
+
}
|
|
3197
|
+
|
|
3198
|
+
// src/pmove/stuck.ts
|
|
3199
|
+
var AXES = ["x", "y", "z"];
|
|
3200
|
+
var SIDE_CHECKS = [
|
|
3201
|
+
{ normal: [0, 0, 1], mins: [-1, -1, 0], maxs: [1, 1, 0] },
|
|
3202
|
+
{ normal: [0, 0, -1], mins: [-1, -1, 0], maxs: [1, 1, 0] },
|
|
3203
|
+
{ normal: [1, 0, 0], mins: [0, -1, -1], maxs: [0, 1, 1] },
|
|
3204
|
+
{ normal: [-1, 0, 0], mins: [0, -1, -1], maxs: [0, 1, 1] },
|
|
3205
|
+
{ normal: [0, 1, 0], mins: [-1, 0, -1], maxs: [1, 0, 1] },
|
|
3206
|
+
{ normal: [0, -1, 0], mins: [-1, 0, -1], maxs: [1, 0, 1] }
|
|
3207
|
+
];
|
|
3208
|
+
var ZERO_VEC = { x: 0, y: 0, z: 0 };
|
|
3209
|
+
function cloneMutable(vec) {
|
|
3210
|
+
return { x: vec.x, y: vec.y, z: vec.z };
|
|
3211
|
+
}
|
|
3212
|
+
function tupleToVec3(tuple) {
|
|
3213
|
+
return { x: tuple[0], y: tuple[1], z: tuple[2] };
|
|
3214
|
+
}
|
|
3215
|
+
function adjustAxis(vec, axis, delta) {
|
|
3216
|
+
if (delta === 0) return;
|
|
3217
|
+
switch (axis) {
|
|
3218
|
+
case "x":
|
|
3219
|
+
vec.x += delta;
|
|
3220
|
+
break;
|
|
3221
|
+
case "y":
|
|
3222
|
+
vec.y += delta;
|
|
3223
|
+
break;
|
|
3224
|
+
case "z":
|
|
3225
|
+
vec.z += delta;
|
|
3226
|
+
break;
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
function setAxis(vec, axis, value) {
|
|
3230
|
+
switch (axis) {
|
|
3231
|
+
case "x":
|
|
3232
|
+
vec.x = value;
|
|
3233
|
+
break;
|
|
3234
|
+
case "y":
|
|
3235
|
+
vec.y = value;
|
|
3236
|
+
break;
|
|
3237
|
+
case "z":
|
|
3238
|
+
vec.z = value;
|
|
3239
|
+
break;
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
function axisValue(vec, axis) {
|
|
3243
|
+
switch (axis) {
|
|
3244
|
+
case "x":
|
|
3245
|
+
return vec.x;
|
|
3246
|
+
case "y":
|
|
3247
|
+
return vec.y;
|
|
3248
|
+
case "z":
|
|
3249
|
+
default:
|
|
3250
|
+
return vec.z;
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
function boundValue(code, axis, mins, maxs) {
|
|
3254
|
+
if (code === -1) {
|
|
3255
|
+
return axisValue(mins, axis);
|
|
3256
|
+
}
|
|
3257
|
+
if (code === 1) {
|
|
3258
|
+
return axisValue(maxs, axis);
|
|
3259
|
+
}
|
|
3260
|
+
return 0;
|
|
3261
|
+
}
|
|
3262
|
+
function applySideOffset(base, side, mins, maxs) {
|
|
3263
|
+
const result = cloneMutable(base);
|
|
3264
|
+
for (let i = 0; i < AXES.length; i++) {
|
|
3265
|
+
const axis = AXES[i];
|
|
3266
|
+
const normal = side.normal[i];
|
|
3267
|
+
if (normal < 0) {
|
|
3268
|
+
adjustAxis(result, axis, axisValue(mins, axis));
|
|
3269
|
+
} else if (normal > 0) {
|
|
3270
|
+
adjustAxis(result, axis, axisValue(maxs, axis));
|
|
3271
|
+
}
|
|
3272
|
+
}
|
|
3273
|
+
return result;
|
|
3274
|
+
}
|
|
3275
|
+
function buildSideBounds(side, mins, maxs) {
|
|
3276
|
+
const localMins = cloneMutable(ZERO_VEC);
|
|
3277
|
+
const localMaxs = cloneMutable(ZERO_VEC);
|
|
3278
|
+
for (let i = 0; i < AXES.length; i++) {
|
|
3279
|
+
const axis = AXES[i];
|
|
3280
|
+
setAxis(localMins, axis, boundValue(side.mins[i], axis, mins, maxs));
|
|
3281
|
+
setAxis(localMaxs, axis, boundValue(side.maxs[i], axis, mins, maxs));
|
|
3282
|
+
}
|
|
3283
|
+
return { mins: localMins, maxs: localMaxs };
|
|
3284
|
+
}
|
|
3285
|
+
function addEpsilon(source, axis, direction) {
|
|
3286
|
+
if (!axis || direction === 0) {
|
|
3287
|
+
return source;
|
|
3288
|
+
}
|
|
3289
|
+
const clone = cloneMutable(source);
|
|
3290
|
+
adjustAxis(clone, axis, direction);
|
|
3291
|
+
return clone;
|
|
3292
|
+
}
|
|
3293
|
+
function addEpsilonImmutable(vec, axis, direction) {
|
|
3294
|
+
if (!axis || direction === 0) {
|
|
3295
|
+
return vec;
|
|
3296
|
+
}
|
|
3297
|
+
switch (axis) {
|
|
3298
|
+
case "x":
|
|
3299
|
+
return { ...vec, x: vec.x + direction };
|
|
3300
|
+
case "y":
|
|
3301
|
+
return { ...vec, y: vec.y + direction };
|
|
3302
|
+
case "z":
|
|
3303
|
+
default:
|
|
3304
|
+
return { ...vec, z: vec.z + direction };
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
function fixStuckObjectGeneric(params) {
|
|
3308
|
+
const { origin, mins, maxs, trace } = params;
|
|
3309
|
+
const initial = trace(origin, mins, maxs, origin);
|
|
3310
|
+
if (!initial.startsolid) {
|
|
3311
|
+
return { result: "good-position", origin: { ...origin } };
|
|
3312
|
+
}
|
|
3313
|
+
const candidates = [];
|
|
3314
|
+
for (let i = 0; i < SIDE_CHECKS.length; i++) {
|
|
3315
|
+
const side = SIDE_CHECKS[i];
|
|
3316
|
+
const { mins: localMins, maxs: localMaxs } = buildSideBounds(side, mins, maxs);
|
|
3317
|
+
let start = applySideOffset(origin, side, mins, maxs);
|
|
3318
|
+
let tr = trace(start, localMins, localMaxs, start);
|
|
3319
|
+
let epsilonAxis;
|
|
3320
|
+
let epsilonDir = 0;
|
|
3321
|
+
if (tr.startsolid) {
|
|
3322
|
+
for (let axisIndex = 0; axisIndex < AXES.length; axisIndex++) {
|
|
3323
|
+
if (side.normal[axisIndex] !== 0) {
|
|
3324
|
+
continue;
|
|
3325
|
+
}
|
|
3326
|
+
const axis = AXES[axisIndex];
|
|
3327
|
+
let epsilonStart = cloneMutable(start);
|
|
3328
|
+
adjustAxis(epsilonStart, axis, 1);
|
|
3329
|
+
tr = trace(epsilonStart, localMins, localMaxs, epsilonStart);
|
|
3330
|
+
if (!tr.startsolid) {
|
|
3331
|
+
start = epsilonStart;
|
|
3332
|
+
epsilonAxis = axis;
|
|
3333
|
+
epsilonDir = 1;
|
|
3334
|
+
break;
|
|
3335
|
+
}
|
|
3336
|
+
epsilonStart = cloneMutable(start);
|
|
3337
|
+
adjustAxis(epsilonStart, axis, -1);
|
|
3338
|
+
tr = trace(epsilonStart, localMins, localMaxs, epsilonStart);
|
|
3339
|
+
if (!tr.startsolid) {
|
|
3340
|
+
start = epsilonStart;
|
|
3341
|
+
epsilonAxis = axis;
|
|
3342
|
+
epsilonDir = -1;
|
|
3343
|
+
break;
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
if (tr.startsolid) {
|
|
3348
|
+
continue;
|
|
3349
|
+
}
|
|
3350
|
+
const otherSide = SIDE_CHECKS[i ^ 1];
|
|
3351
|
+
let oppositeStart = applySideOffset(origin, otherSide, mins, maxs);
|
|
3352
|
+
oppositeStart = addEpsilon(oppositeStart, epsilonAxis, epsilonDir);
|
|
3353
|
+
tr = trace(start, localMins, localMaxs, oppositeStart);
|
|
3354
|
+
if (tr.startsolid) {
|
|
3355
|
+
continue;
|
|
3356
|
+
}
|
|
3357
|
+
const normal = tupleToVec3(side.normal);
|
|
3358
|
+
const end = addVec3(tr.endpos ?? oppositeStart, scaleVec3(normal, 0.125));
|
|
3359
|
+
const delta = subtractVec3(end, oppositeStart);
|
|
3360
|
+
let newOrigin = addVec3(origin, delta);
|
|
3361
|
+
newOrigin = addEpsilonImmutable(newOrigin, epsilonAxis, epsilonDir);
|
|
3362
|
+
const validation = trace(newOrigin, mins, maxs, newOrigin);
|
|
3363
|
+
if (validation.startsolid) {
|
|
3364
|
+
continue;
|
|
3365
|
+
}
|
|
3366
|
+
candidates.push({ origin: newOrigin, distance: lengthSquaredVec3(delta) });
|
|
3025
3367
|
}
|
|
3026
|
-
if (
|
|
3027
|
-
|
|
3368
|
+
if (candidates.length === 0) {
|
|
3369
|
+
return { result: "no-good-position", origin: { ...origin } };
|
|
3028
3370
|
}
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
velocity,
|
|
3032
|
-
frametime,
|
|
3033
|
-
mins,
|
|
3034
|
-
maxs,
|
|
3035
|
-
trace,
|
|
3036
|
-
overbounce,
|
|
3037
|
-
stepSize,
|
|
3038
|
-
maxBumps,
|
|
3039
|
-
maxClipPlanes,
|
|
3040
|
-
hasTime
|
|
3041
|
-
});
|
|
3371
|
+
candidates.sort((a, b) => a.distance - b.distance);
|
|
3372
|
+
return { result: "fixed", origin: { ...candidates[0].origin } };
|
|
3042
3373
|
}
|
|
3043
|
-
|
|
3374
|
+
|
|
3375
|
+
// src/pmove/fly.ts
|
|
3376
|
+
var FLY_FRICTION_MULTIPLIER = 1.5;
|
|
3377
|
+
var BUTTON_VERTICAL_SCALE = 0.5;
|
|
3378
|
+
var DEFAULT_OVERBOUNCE = 1.01;
|
|
3379
|
+
function applyPmoveFlyMove(params) {
|
|
3044
3380
|
const {
|
|
3045
3381
|
origin,
|
|
3382
|
+
cmd,
|
|
3046
3383
|
frametime,
|
|
3384
|
+
pmFriction,
|
|
3385
|
+
pmStopSpeed,
|
|
3386
|
+
pmMaxSpeed,
|
|
3387
|
+
pmAccelerate,
|
|
3388
|
+
pmWaterSpeed,
|
|
3389
|
+
doclip,
|
|
3390
|
+
forward,
|
|
3391
|
+
right,
|
|
3047
3392
|
mins,
|
|
3048
3393
|
maxs,
|
|
3049
3394
|
trace,
|
|
3050
|
-
overbounce =
|
|
3395
|
+
overbounce = DEFAULT_OVERBOUNCE,
|
|
3051
3396
|
stepSize,
|
|
3052
3397
|
maxBumps,
|
|
3053
|
-
maxClipPlanes
|
|
3054
|
-
hasTime,
|
|
3055
|
-
forward,
|
|
3056
|
-
right,
|
|
3057
|
-
cmd,
|
|
3058
|
-
pmFlags,
|
|
3059
|
-
onGround,
|
|
3060
|
-
pmMaxSpeed,
|
|
3061
|
-
pmDuckSpeed,
|
|
3062
|
-
pmWaterAccelerate,
|
|
3063
|
-
pmWaterSpeed,
|
|
3064
|
-
onLadder,
|
|
3065
|
-
watertype,
|
|
3066
|
-
groundContents,
|
|
3067
|
-
waterlevel,
|
|
3068
|
-
viewPitch,
|
|
3069
|
-
ladderMod
|
|
3398
|
+
maxClipPlanes
|
|
3070
3399
|
} = params;
|
|
3071
|
-
let velocity = {
|
|
3072
|
-
|
|
3073
|
-
if (isIdleInWater(cmd, onGround)) {
|
|
3074
|
-
wishvel = { ...wishvel, z: wishvel.z - WATER_DRIFT_SPEED };
|
|
3075
|
-
} else {
|
|
3076
|
-
if (hasButton2(cmd, 16 /* Crouch */)) {
|
|
3077
|
-
wishvel = addVec3(wishvel, { x: 0, y: 0, z: -pmWaterSpeed * 0.5 });
|
|
3078
|
-
} else if (hasButton2(cmd, 8 /* Jump */)) {
|
|
3079
|
-
wishvel = addVec3(wishvel, { x: 0, y: 0, z: pmWaterSpeed * 0.5 });
|
|
3080
|
-
}
|
|
3081
|
-
}
|
|
3082
|
-
wishvel = applyPmoveAddCurrents({
|
|
3083
|
-
wishVelocity: wishvel,
|
|
3084
|
-
onLadder,
|
|
3085
|
-
onGround,
|
|
3086
|
-
waterlevel,
|
|
3087
|
-
watertype,
|
|
3088
|
-
groundContents,
|
|
3400
|
+
let velocity = applyFlyFriction({ velocity: params.velocity, pmFriction, pmStopSpeed, frametime });
|
|
3401
|
+
const wishdirVelocity = buildFlyWishVelocity({
|
|
3089
3402
|
cmd,
|
|
3090
|
-
viewPitch,
|
|
3091
|
-
maxSpeed: hasPmFlag(pmFlags, 1 /* Ducked */) ? pmDuckSpeed : pmMaxSpeed,
|
|
3092
|
-
ladderMod,
|
|
3093
|
-
waterSpeed: pmWaterSpeed,
|
|
3094
3403
|
forward,
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
trace
|
|
3404
|
+
right,
|
|
3405
|
+
pmMaxSpeed,
|
|
3406
|
+
pmWaterSpeed
|
|
3099
3407
|
});
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3408
|
+
if (wishdirVelocity.wishspeed > 0) {
|
|
3409
|
+
velocity = applyPmoveAccelerate({
|
|
3410
|
+
velocity,
|
|
3411
|
+
wishdir: wishdirVelocity.wishdir,
|
|
3412
|
+
wishspeed: wishdirVelocity.accelSpeed,
|
|
3413
|
+
accel: pmAccelerate,
|
|
3414
|
+
frametime
|
|
3415
|
+
});
|
|
3104
3416
|
}
|
|
3105
|
-
if (
|
|
3106
|
-
const
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3417
|
+
if (!doclip) {
|
|
3418
|
+
const originDelta = scaleVec3(velocity, frametime);
|
|
3419
|
+
const nextOrigin = addVec3(origin, originDelta);
|
|
3420
|
+
return {
|
|
3421
|
+
origin: nextOrigin,
|
|
3422
|
+
velocity,
|
|
3423
|
+
planes: [],
|
|
3424
|
+
blocked: 0,
|
|
3425
|
+
stopped: velocity.x === 0 && velocity.y === 0 && velocity.z === 0,
|
|
3426
|
+
stepped: false,
|
|
3427
|
+
stepHeight: 0
|
|
3428
|
+
};
|
|
3112
3429
|
}
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
if (ducked && wishspeed > pmDuckSpeed) {
|
|
3116
|
-
const scale = pmDuckSpeed / wishspeed;
|
|
3117
|
-
wishvel = scaleVec3(wishvel, scale);
|
|
3118
|
-
wishspeed = pmDuckSpeed;
|
|
3119
|
-
if (wishspeed !== 0) {
|
|
3120
|
-
wishdir = normalizeVec3(wishvel);
|
|
3121
|
-
}
|
|
3430
|
+
if (!trace || !mins || !maxs) {
|
|
3431
|
+
throw new Error("applyPmoveFlyMove: doclip=true requires trace/mins/maxs");
|
|
3122
3432
|
}
|
|
3123
|
-
|
|
3124
|
-
return runStepSlideMove({
|
|
3433
|
+
return stepSlideMove({
|
|
3125
3434
|
origin,
|
|
3126
3435
|
velocity,
|
|
3127
3436
|
frametime,
|
|
3437
|
+
overbounce,
|
|
3438
|
+
trace,
|
|
3128
3439
|
mins,
|
|
3129
3440
|
maxs,
|
|
3130
|
-
trace,
|
|
3131
|
-
overbounce,
|
|
3132
3441
|
stepSize,
|
|
3133
3442
|
maxBumps,
|
|
3134
|
-
maxClipPlanes
|
|
3135
|
-
hasTime
|
|
3443
|
+
maxClipPlanes
|
|
3136
3444
|
});
|
|
3137
3445
|
}
|
|
3138
|
-
function
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
z: 0
|
|
3143
|
-
}
|
|
3446
|
+
function applyFlyFriction(params) {
|
|
3447
|
+
const { velocity, pmFriction, pmStopSpeed, frametime } = params;
|
|
3448
|
+
const speed = lengthVec3(velocity);
|
|
3449
|
+
if (speed < 1) {
|
|
3450
|
+
return { x: 0, y: 0, z: 0 };
|
|
3451
|
+
}
|
|
3452
|
+
const friction = pmFriction * FLY_FRICTION_MULTIPLIER;
|
|
3453
|
+
const control = speed < pmStopSpeed ? pmStopSpeed : speed;
|
|
3454
|
+
const drop = control * friction * frametime;
|
|
3455
|
+
let newspeed = speed - drop;
|
|
3456
|
+
if (newspeed < 0) {
|
|
3457
|
+
newspeed = 0;
|
|
3458
|
+
}
|
|
3459
|
+
if (newspeed === speed) {
|
|
3460
|
+
return velocity;
|
|
3461
|
+
}
|
|
3462
|
+
return scaleVec3(velocity, newspeed / speed);
|
|
3144
3463
|
}
|
|
3145
|
-
function
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3464
|
+
function buildFlyWishVelocity(params) {
|
|
3465
|
+
const { cmd, forward, right, pmMaxSpeed, pmWaterSpeed } = params;
|
|
3466
|
+
const forwardNorm = normalizeVec3(forward);
|
|
3467
|
+
const rightNorm = normalizeVec3(right);
|
|
3468
|
+
const wishvel = {
|
|
3469
|
+
x: forwardNorm.x * cmd.forwardmove + rightNorm.x * cmd.sidemove,
|
|
3470
|
+
y: forwardNorm.y * cmd.forwardmove + rightNorm.y * cmd.sidemove,
|
|
3471
|
+
z: forwardNorm.z * cmd.forwardmove + rightNorm.z * cmd.sidemove
|
|
3150
3472
|
};
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
}
|
|
3155
|
-
function isIdleInWater(cmd, onGround) {
|
|
3156
|
-
const noMove = cmd.forwardmove === 0 && cmd.sidemove === 0;
|
|
3157
|
-
const noButtons = (cmd.buttons ?? 0) & (8 /* Jump */ | 16 /* Crouch */) ? false : true;
|
|
3158
|
-
return noMove && noButtons && !onGround;
|
|
3159
|
-
}
|
|
3160
|
-
function dampVerticalVelocity(velocity, gravity, frametime) {
|
|
3161
|
-
let z = velocity.z;
|
|
3162
|
-
const delta = gravity * frametime;
|
|
3163
|
-
if (z > 0) {
|
|
3164
|
-
z -= delta;
|
|
3165
|
-
if (z < 0) {
|
|
3166
|
-
z = 0;
|
|
3167
|
-
}
|
|
3168
|
-
} else {
|
|
3169
|
-
z += delta;
|
|
3170
|
-
if (z > 0) {
|
|
3171
|
-
z = 0;
|
|
3172
|
-
}
|
|
3473
|
+
let adjusted = wishvel;
|
|
3474
|
+
const buttons = cmd.buttons ?? 0;
|
|
3475
|
+
if (buttons & 8 /* Jump */) {
|
|
3476
|
+
adjusted = addVec3(adjusted, { x: 0, y: 0, z: pmWaterSpeed * BUTTON_VERTICAL_SCALE });
|
|
3173
3477
|
}
|
|
3174
|
-
|
|
3175
|
-
}
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
maxBumps,
|
|
3188
|
-
maxClipPlanes,
|
|
3189
|
-
hasTime
|
|
3190
|
-
});
|
|
3478
|
+
if (buttons & 16 /* Crouch */) {
|
|
3479
|
+
adjusted = addVec3(adjusted, { x: 0, y: 0, z: -pmWaterSpeed * BUTTON_VERTICAL_SCALE });
|
|
3480
|
+
}
|
|
3481
|
+
let wishspeed = lengthVec3(adjusted);
|
|
3482
|
+
let wishdir = wishspeed === 0 ? { x: 0, y: 0, z: 0 } : normalizeVec3(adjusted);
|
|
3483
|
+
if (wishspeed > pmMaxSpeed) {
|
|
3484
|
+
const scale = pmMaxSpeed / wishspeed;
|
|
3485
|
+
adjusted = scaleVec3(adjusted, scale);
|
|
3486
|
+
wishspeed = pmMaxSpeed;
|
|
3487
|
+
wishdir = wishspeed === 0 ? { x: 0, y: 0, z: 0 } : normalizeVec3(adjusted);
|
|
3488
|
+
}
|
|
3489
|
+
const accelSpeed = wishspeed * 2;
|
|
3490
|
+
return { wishdir, wishspeed, accelSpeed };
|
|
3191
3491
|
}
|
|
3192
3492
|
|
|
3193
3493
|
// src/pmove/special.ts
|
|
@@ -4131,7 +4431,7 @@ var U_MODEL4 = 1 << 2;
|
|
|
4131
4431
|
var U_REMOVE = 32768;
|
|
4132
4432
|
|
|
4133
4433
|
// src/pmove/apply.ts
|
|
4134
|
-
var
|
|
4434
|
+
var FRAMETIME2 = 0.025;
|
|
4135
4435
|
var MASK_WATER2 = 33554432;
|
|
4136
4436
|
var WaterLevel3 = {
|
|
4137
4437
|
None: 0,
|
|
@@ -4185,7 +4485,7 @@ var applyPmove = (state, cmd, trace, pointContents2) => {
|
|
|
4185
4485
|
const { forward, right } = angleVectors(adjustedAngles);
|
|
4186
4486
|
const frictionedVelocity = applyPmoveFriction({
|
|
4187
4487
|
velocity,
|
|
4188
|
-
frametime:
|
|
4488
|
+
frametime: FRAMETIME2,
|
|
4189
4489
|
onGround,
|
|
4190
4490
|
groundIsSlick: false,
|
|
4191
4491
|
onLadder: false,
|
|
@@ -4211,12 +4511,12 @@ var applyPmove = (state, cmd, trace, pointContents2) => {
|
|
|
4211
4511
|
wishspeed: wish.wishspeed,
|
|
4212
4512
|
// Water movement uses ground acceleration (10), not air acceleration (1)
|
|
4213
4513
|
accel: onGround || waterLevel >= 2 ? 10 : 1,
|
|
4214
|
-
frametime:
|
|
4514
|
+
frametime: FRAMETIME2
|
|
4215
4515
|
});
|
|
4216
4516
|
const traceResult = trace(origin, {
|
|
4217
|
-
x: origin.x + finalVelocity.x *
|
|
4218
|
-
y: origin.y + finalVelocity.y *
|
|
4219
|
-
z: origin.z + finalVelocity.z *
|
|
4517
|
+
x: origin.x + finalVelocity.x * FRAMETIME2,
|
|
4518
|
+
y: origin.y + finalVelocity.y * FRAMETIME2,
|
|
4519
|
+
z: origin.z + finalVelocity.z * FRAMETIME2
|
|
4220
4520
|
});
|
|
4221
4521
|
return {
|
|
4222
4522
|
...newState,
|
|
@@ -5084,6 +5384,7 @@ export {
|
|
|
5084
5384
|
applyPmoveAirMove,
|
|
5085
5385
|
applyPmoveFlyMove,
|
|
5086
5386
|
applyPmoveFriction,
|
|
5387
|
+
applyPmoveWalkMove,
|
|
5087
5388
|
applyPmoveWaterMove,
|
|
5088
5389
|
assertContract,
|
|
5089
5390
|
attenuationToDistanceMultiplier,
|
|
@@ -5159,6 +5460,7 @@ export {
|
|
|
5159
5460
|
removePmFlag,
|
|
5160
5461
|
resolveSlideMove,
|
|
5161
5462
|
rotatePointAroundVector,
|
|
5463
|
+
runPmove,
|
|
5162
5464
|
scaleVec3,
|
|
5163
5465
|
slerpVec3,
|
|
5164
5466
|
slideClipVelocityVec3,
|