PURPOSE
Centralized data table for gameplay-side tunable constants. Holds every numeric balance dial that governs movement, heat, warp, damage, camera, world geometry, entity pool ceilings, pickups, spawner cadence, collision, mission objectives, boss flow, vision, revive, events, portals, and mission timers. The whole file is one frozen-shape CFG literal exported by name so the rest of the engine reads but does not mutate it.
OWNS
- The
CFGobject literal — single source of truth for gameplay constants. - Movement constants:
DRAG_BASE,SPEED_LERP. - Heat system constants:
HEAT_DANGER,HEAT_STALL_DMG,HEAT_THR_RS,HEAT_THR_RA,HEAT_ZOOM_S,HEAT_ZOOM_A,HEAT_SMOKE_S,HEAT_DIL_S,HEAT_DIL_A,HEAT_COOL_RAMP,HEAT_COOL_MAX. - Warp drive constants:
WARP_DURATION,WARP_SPEED,WARP_EXIT_ENEMY_RANGE,WARP_SPAWN_INTERVAL,WARP_SPAWN_DIST_MIN,WARP_SPAWN_DIST_MAX,WARP_MAX_ON_MAP. - Damage balance:
PLAYER_DAMAGE_MULT,ENEMY_DAMAGE_CAP,INVULN. - Camera:
CAMERA_LERP,BASE_ZOOM(computed once at module load fromwindow.innerWidthwith a 0.85× multiplier under 900px and a further linear pinch under 480px). - World geometry:
CHUNK,INNER_BELT_RADIUS,INNER_BELT_WIDTH,OUTER_BELT_RADIUS,OUTER_BELT_WIDTH. - Entity pool ceilings:
MAX_ENEMIES,MAX_ENEMY_BULLETS,MAX_HORDE_ENEMIES,MAX_STRUCTURES,MAX_JUNK,MAX_PARTICLES,MAX_XP_ORBS,MAX_WARNINGS,MAX_SFX_PER_RAF. - Pickup system:
MAGNET_SPEED,MAGNET_SNAP_MULT,MAGNET_COLLECT_DIST,XP_COLLECT_RADIUS,ORB_LIFETIME. - Spawner tuning:
PROXIMITY_INTERVAL,PROXIMITY_COUNT,PROXIMITY_DISTANCE,PROXIMITY_WARN_TIME,PATROL_BASE_TIMER,WAVE_MIN_PROGRESS,WAVE_INTERVAL. - Collision grid:
GRID_CELL_SIZE. - Mission objectives:
BEACON_CHARGE_TIME,BEACON_RADIUS. - Boss legacy + room + intro sequence:
BOSS_INTRO_TIME,BOSS_ROOM_MARGIN,BOSS_ROOM_SHRINK_DURATION,BOSS_ROOM_INITIAL_SCALE,BOSS_ROOM_WALL_THICKNESS,BOSS_ROOM_SIZE_MULT,BOSS_INTRO_DURATION,BOSS_INTRO_FADE_DURATION,BOSS_INTRO_PAN_DURATION,BOSS_INTRO_HP_FILL_DURATION,BOSS_INTRO_SQUASH_DURATION,BOSS_INTRO_PAN_BACK_DURATION,BOSS_DEATH_SEQUENCE_DURATION,BOSS_ENRAGE_TIME,BOSS_ENRAGE_FIRE_MULT,BOSS_ENRAGE_SPEED_MULT,BOSS_ZOOM,BOSS_HP_SCALE_PER_LEVEL,BOSS_MAX_ENEMY_BULLETS,BOSS_LOOT_XP_COUNT,BOSS_LOOT_WEAPON_CHESTS,BOSS_LOOT_ARTIFACTS_A. - Vision defaults:
VISION_DEFAULT(base_radius,dim_width,dark_opacity,fog_density,ambient_light). - Death-defiance / revive:
REVIVE_HP_PCT,REVIVE_INVULN_TIME,REVIVE_DISMISS_TIME. - Event system:
EVENT_TYPES,EVENT_CHARGE_TIME,EVENT_RADIUS. - Portal room:
PORTAL_ROOM_RADIUS,PORTAL_BASE_RADIUS,PORTAL_VFX_START_RADIUS,PORTAL_VFX_GROWTH_RATE,PORTAL_VORTEX_RAMP,PORTAL_VORTEX_RADIAL,PORTAL_VORTEX_TANGENTIAL. - Mission base timers map:
MISSION_BASE_TIMERSkeyed bybeacons,extraction,wanted,chase,scavenge,gauntlet,holdout,infiltrate,convoy,exterminate. - The named re-export
_IS_MOBILEfor downstream perf-flag consumers.
READS FROM
../device-capabilities— importsisMobile()to populate the module-local_IS_MOBILEboolean. That boolean is computed once at module load.window.innerWidth(browser global) — read once inside theBASE_ZOOMIIFE to compute a screen-width-conditioned zoom. Falls back to0.675whenwindowis undefined (SSR / Node test environments).
PUSHES TO
Nothing. The module performs no writes, dispatches no events, and triggers no side effects beyond evaluating its constant table at import time. Consumers import CFG (or _IS_MOBILE) by name and read fields directly.
DOES NOT
- Does not freeze or seal the
CFGobject — runtime mutation is possible but not the intended contract. - Does not register listeners on resize, orientation change, or any other event —
BASE_ZOOMis a one-shot snapshot at module load, not a reactive value. - Does not vary any pool ceiling by device tier inside this file —
_IS_MOBILEis exported but only theBASE_ZOOMIIFE inspects viewport width here. Mobile-tier budget cuts live elsewhere (perf-flags layer). - Does not own boss intro orchestration timing — the constants here must stay summed to match
boss-fight.tsupdateIntrosub-phase totals, but the orchestration itself is not in this file. - Does not own per-mission spawn data, enemy stats, weapon stats, artifact stats, passive stats, or progression curves — those live in data tables under
data/and balance code elsewhere.
Signals
None. No emitter, no observer, no callback registration.
Entry points
import { CFG } from '...config/_gameplay'— direct field reads by every gameplay system that needs a tunable.import { _IS_MOBILE } from '...config/_gameplay'— perf-flag layer reads this to gate mobile-specific budgets and effects.CFG.BASE_ZOOM— computed at module evaluation; treated as a constant by the camera system.CFG.MISSION_BASE_TIMERS[<mission-type>]— keyed lookup used by mission setup code to seed countdown clocks.CFG.VISION_DEFAULT— read as a starting object by the vision system before any per-biome overrides.
Pattern notes
- Pure data module — content in a data table, no behavior. Aligns with the project rule that stats, rates, and curves live in data while logic lives in functions.
- Single declaration
export const CFG = { ... }keeps all gameplay-balance dials co-located so a balance pass touches one file. BASE_ZOOMis the only computed field; it uses a self-invoked function expression to fold viewport-dependent logic into the literal. The SSR guard (typeof window === 'undefined') keeps the module safe to import from test or build contexts.- Comment-block headers group fields by subsystem (MOVEMENT / HEAT SYSTEM / WARP DRIVE / DAMAGE BALANCE / CAMERA / WORLD GEOMETRY / ENTITY POOL LIMITS / PICKUP SYSTEM / SPAWNER TUNING / COLLISION / MISSION OBJECTIVES / BOSS / BOSS ROOM / VISION SYSTEM / DEATH DEFIANCE / REVIVE / EVENT SYSTEM / PORTAL ROOM / MISSION TYPE CONFIGS). The grouping is convention only — the runtime shape is one flat object.
BOSS_INTRO_DURATIONis a derived total that must equal the sum of the five sub-phase durations (BOSS_INTRO_FADE_DURATION+BOSS_INTRO_PAN_DURATION+BOSS_INTRO_HP_FILL_DURATION+BOSS_INTRO_SQUASH_DURATION+BOSS_INTRO_PAN_BACK_DURATION). Edits to any sub-phase require updating the total in lockstep.- Tuple-typed range fields (
PROXIMITY_INTERVAL,PROXIMITY_COUNT,PROXIMITY_DISTANCE,WAVE_INTERVAL) are written as two-element arrays for[min, max]ranges sampled by spawner code. - Pool ceilings carry an inline comment marking the deliberate 10× headroom raise so the kill-cap curve, bullet pool, and orb storage saturate at peak difficulty.
EVENT_TYPESis a string array used as a discrete enum domain; new event kinds added elsewhere must be registered here for the spawner to pick them._IS_MOBILEis the only export besidesCFGand is re-exported explicitly so downstream perf-flag code can avoid re-importingdevice-capabilitiesdirectly.- No backwards-compatibility shims, no aliases — every consumer reads canonical field names.