Drift Scoring System
Reference for `gameplay_drift_scoring`, which calculates continuous drift scores, manages the combo system, tracks tier progression, handles stunt zone bonuses, and determines career rewards.
Reference for gameplay_drift_scoring, which calculates continuous drift scores, manages the combo system, tracks tier progression, handles stunt zone bonuses, and determines career rewards.
Overview
The scoring engine runs every frame during a drift, accumulating points based on angle, speed, and wall proximity. Points are cached until the drift chain completes, then multiplied by the combo and added to the permanent score. A tier system (Drift → Legendary Drift) adds bonus continuous points. The combo builds through sustained drifting, transitions, and stunt zones.
Exports
Score Management
| Function | Signature | Description |
|---------
| M.getGC | () | any | getGC |
| M.getDriftDebugInfo | () | any | getDriftDebugInfo |-|
| M.onSerialize | onSerialize handler |-----------|-------------|
| getScore | () → table | {score, combo, potentialScore, cachedScore, comboCreepup} |
| getPotentialScore | () → number | cachedScore × combo |
| getScoreAddedThisFrame | () → number | Points added this frame (with tier) |
| addCachedScore | (value, useStallingSystem?) → number | Add to cached score |
| reset | () | Reset all score state |
| wrapUp | () → number\|false | Confirm cached score × combo to permanent |
| wrapUpWithText | () → number\|false | Wrap up + fire display hook |
| M.onDeserialized | onDeserialized handler |
Tiers
| Function | Signature | Description |
|---|---|---|
getDriftTiers | () → table | All tier definitions |
getCurrentDriftTier | () → table | Active tier |
Performance
| Function | Signature | Description |
|---|---|---|
getDriftPerformanceFactor | () → number | 0-1 raw performance |
getSteppedDriftPerformanceFactor | () → number | 0-4 smoothed stepped factor |
getScoreOptions | () → table | All scoring constants |
getStuntZoneBasePoints | (type) → number | Base points for stunt type |
Hooks
| Function | Description |
|---|---|
onUpdate | Main scoring loop |
onDriftCompleted | Score confirmation on chain end |
onDriftTransition | Combo creep on direction change |
onAnyStuntZoneAccomplished | Combo creep from stunt zones |
onDriftThroughAccomplished | Score tight drift zone |
onHitPoleAccomplished | Score pole hit |
onDonutDriftAccomplished | Score donut |
onNearPoleAccomplished | Score near-pole drift |
onDriftCrash / onDriftSpinout | Reset cached score |
onDriftChainStarted | Announce first tier |
onDriftPlVehReset | Full reset |
Score Formula
-- Per frame while drifting:
angleMulti = linearScale(angle, minAngle, maxAngle, 1, 10)
speedMulti = linearScale(airSpeed, 22, 200, 1, 4) -- clamped to [1, 4]
wallMulti = 1 + linearScale(wallDistFront, 3, 0, 0, 3) + linearScale(wallDistRear, 3, 0, 0, 3)
scoreBeforeTier = angleMulti × speedMulti × wallMulti × distSinceLastFrame × 0.6
scoreWithTier = scoreBeforeTier + driftTiers[currentTier].continuousScore × dtSim
-- Final score on chain completion:
permanentScore += floor(cachedScore × combo)Tier System
| Tier | Min Score | Continuous Bonus/sec |
|---|---|---|
| Drift | 0 | 10 |
| Great Drift | 250 | 20 |
| Awesome Drift | 750 | 30 |
| Superior Drift | 2000 | 40 |
| Epic Drift | 5000 | 50 |
| Apex Drift | 9000 | 60 |
| Legendary Drift | 15000 | 75 |
Combo System
-- Combo builds via comboCreepup (0-100 → +0.1 combo):
-- Sources:
-- oneSideDrift: +10 creep per 0.1s (min 25° angle, max 100 increments)
-- driftTransition: +100-500 creep based on speed bracket (2s cooldown)
-- stuntZone: +140 creep per zone
-- closeWall: +50 creep (via quick messages)
-- Limits:
-- comboSoftCap = 10 (above this, use lower creep values)
-- comboHardCap = 25 (absolute maximum)Performance Factor
-- Compares current score to a simulated "good drift":
-- Good drift: wallDist=1.8m, angle=80°, speed=70kph
veryGoodScore = getContinuousScore(0.15, goodDriftData)
performanceFactor = scoreBeforeTier / veryGoodScore -- 0 to 1+
-- Stepped: 1=poor, 2=okay, 3=good, 4=excellent
-- Level 4 has hysteresis (0.3s hold both ways) to prevent flickering
-- Smoothed via newTemporalSmoothing(8, 8)Stunt Zone Scoring
| Type | Formula |
|---|---|
| Drift Through | linearScale(angle, 0, 90, 0, zonePoints) |
| Hit Pole | linearScale(angle + speed, 0, 250, 0, zonePoints) |
| Near Pole | (angle × closeness / 90) × zonePoints |
| Donut | zonePoints (flat) |
All stunt scores pass through addCachedScore(score, useStallingSystem=true).
Key Behaviors
- Score only accumulates when
!frozenand!paused - Cached score resets on crash or spinout (losing the combo)
wrapUp()is called by drift chain completion or challenge finish- Career rewards:
floor(score × 0.0017)beamXP if score ≥ 300 (currently commented out) - Performance factor smoothing prevents UI jitter during erratic drifts
- Combo transition requires 2s cooldown and >25 kph to prevent rapid back-and-forth farming
| Function | Signature | Returns | Description |
|---|---|---|---|
M.onSerialize | () | nil | onSerialize |
M.onDeserialized | (data) | nil | onDeserialized |
M.getDriftDebugInfo | () | nil | getDriftDebugInfo |
M.getGC | () | nil | getGC |
M.addCachedScore | (valueToAdd, useStallingSystem) | - | addCachedScore handler |
M.getCurrentDriftTier | () | - | Returns CurrentDriftTier |
M.getDriftPerformanceFactor | () | - | Returns DriftPerformanceFactor |
M.getDriftTiers | () | - | Returns DriftTiers |
M.getPotentialScore | () | - | Returns PotentialScore |
M.getScore | () | - | Returns Score |
M.getScoreAddedThisFrame | () | - | Returns ScoreAddedThisFrame |
M.getScoreOptions | () | - | Returns ScoreOptions |
M.getSteppedDriftPerformanceFactor | () | - | Returns SteppedDriftPerformanceFactor |
M.getStuntZoneBasePoints | (stuntZoneType) | - | Returns StuntZoneBasePoints |
M.onAnyStuntZoneAccomplished | () | - | Drift stunts -- |
M.onDonutDriftAccomplished | (data) | - | Callback for DonutDriftAccomplished event |
M.onDriftChainStarted | () | - | Callback for DriftChainStarted event |
M.onDriftCompleted | () | - | finished a whole drift chain |
M.onDriftCrash | () | - | Callback for DriftCrash event |
M.onDriftPlVehReset | () | - | Callback for DriftPlVehReset event |
M.onDriftSpinout | () | - | Callback for DriftSpinout event |
M.onDriftThroughAccomplished | (data) | - | Callback for DriftThroughAccomplished event |
M.onDriftTransition | () | - | this is combo when doing drift transitions |
M.onHitPoleAccomplished | (data) | - | Callback for HitPoleAccomplished event |
M.onNearPoleAccomplished | (data) | - | Callback for NearPoleAccomplished event |
M.onUpdate | (dtReal, _dtSim) | - | Callback for Update event |
M.reset | () | - | Resets state |
M.wrapUp | () | - | preemptively "confirm" cached score |
M.wrapUpWithText | () | - | wrapUpWithText handler |
See Also
- drift/bounds - Drift Zone Boundary Detection - Related reference
- drift/destination - Race Path & Wrong-Way Detection - Related reference
- drift/display - Drift UI & HUD Management - Related reference
- Gameplay Systems Guide - Guide
Drift Scoreboard
Reference for `gameplay_drift_scoreboard`, which accumulates detailed performance statistics during formal drift challenges for end-screen display.
Drift Audio
Reference for `gameplay_drift_sounds`, which manages all audio feedback for the drift system including continuous drift sounds, tier/combo sounds, and crash/spinout audio cues.