HalfLifeModel

@three-blocks/proPresetGoldSrcHalf-LifeSurfBhopMovement
const HalfLifeModel = { name: 'halflife', targetFPS: 100, config: GOLDSRC_CONFIG, isGround( surfaceAngle ) { return surfaceAngle < this.con...
Value
{ name: 'halflife', targetFPS: 100, config: GOLDSRC_CONFIG, isGround( surfaceAngle ) { return surfaceAngle < this.config.groundAngleThreshold; }, groundMove( velocity, wishDir, wishSpeed, delta, isJumping = false ) { const frictionMult =...

Half-Life GoldSrc Physics Model

Authentic GoldSrc engine physics from pm_shared.c (Half-Life 1). Uses the Quake-style architecture with only TWO states: ground and air.

Key GoldSrc features:

  • Ground threshold: normal[2] >= 0.7 (~45.57 degrees)
  • Air speed cap: 30 HU (hardcoded in PM_AirAccelerate)
  • STOP_EPSILON: 0.1 (clamps small velocity components to 0)
  • Jump velocity: sqrt(2 * 800 * 45) ≈ 268 HU/s

Surfing emerges naturally:

  1. Player touches steep ramp (>45.57 degrees)
  2. isGround() returns false (too steep!)
  3. airMove() runs: air acceleration + gravity
  4. clipVelocity() projects velocity onto ramp surface
  5. Player slides down while air-strafing to steer

Usage

Example
import { Physics, HalfLifeModel, PresetNames } from '@three-blocks/pro';

// Using the preset name
const physics = new Physics( { physicsModel: PresetNames.HALFLIFE } );

// Or using the model directly
const physics = new Physics( {
  physicsModel: 'custom',
  customPhysicsModel: HalfLifeModel
} );

// Access GoldSrc-style configuration (values in meters, converted from HU)
console.log( HalfLifeModel.config.gravity ); // 800 HU converted to meters
console.log( HalfLifeModel.config.maxSpeed ); // 320 HU converted to meters
console.log( HalfLifeModel.targetFPS ); // 100 (authentic GoldSrc framerate)

Members

targetFPS#

Target physics FPS for this model. GoldSrc engine runs at ~100.5 FPS - physics are tied to frame rate. Using 100 FPS for authentic CS 1.6 / Half-Life movement feel.

config#

Configuration - Half-Life GoldSrc default settings Values are in meters (converted from Hammer Units via units.js)

Methods

isGround#

isGround(surfaceAngle : number) : boolean

Determine if surface is walkable ground GoldSrc: normal[2] >= 0.7

Parameters
surfaceAnglenumber
Angle from up vector in radians
Returns
boolean
  • True if walkable ground

groundMove#

groundMove(velocity : THREE.Vector3, wishDir : THREE.Vector3, wishSpeed : number, delta : number, isJumping : boolean)

Ground movement physics Called when player is on walkable ground (surface angle < 45.57 degrees)

Parameters
velocityTHREE.Vector3
Current velocity (modified in place)
wishDirTHREE.Vector3
Input direction
wishSpeednumber
Input magnitude (0-1)
deltanumber
Time step
isJumpingboolean
Whether player is jumping this frame (for bhop friction bypass)

airMove#

airMove(velocity : THREE.Vector3, wishDir : THREE.Vector3, wishSpeed : number, delta : number)

Air movement physics Called when player is NOT on ground (falling, jumping, surfing)

Parameters
velocityTHREE.Vector3
Current velocity (modified in place)
wishDirTHREE.Vector3
Input direction
wishSpeednumber
Input magnitude (0-1)
deltanumber
Time step

clipVelocity#

clipVelocity(velocity : THREE.Vector3, normal : THREE.Vector3)

Clip velocity against surface (PM_ClipVelocity) Called on ANY surface collision - this is what makes surfing work!

Parameters
velocityTHREE.Vector3
Current velocity (modified in place)
normalTHREE.Vector3
Surface normal

jump#

jump(velocity : THREE.Vector3, onGround : boolean) : boolean

Handle jump GoldSrc: sqrt(2 * 800 * 45) ≈ 268.3 HU/s

Parameters
velocityTHREE.Vector3
Current velocity (modified in place)
onGroundboolean
Whether player is on ground
Returns
boolean
  • True if jump was executed