class_name SandboxConstants extends RefCounted ## T-1088 locomotion sandbox — every feel/tuning knob in one file. ## § references point at the T-1088 final design (see ticket). Proto-production: ## values migrate to Phase-5 homes at the T-962 gate. ## ## Stance move intervals are deliberately NOT duplicated here — read ## InputMapper.MOVE_INTERVAL_MS at runtime (single source, no drift; design §13.8). # -- Coordinate & scale (design §2) ------------------------------------------- ## D-066/D-222 — THE convention: one sim TilePosition step = one 0.5 m subtile. ## All sandbox positions and speeds are metres. See SandboxSpace for conversions. const SUBTILE_M := 0.5 # -- Greybox walls + cutaway (design §3, §8) ----------------------------------- ## Wall height in metres — walls shorter than the ~1.7 m character read wrong. const WALL_H := 2.5 ## Cutaway stub height (m) camera-side walls drop to. const CUT_HEIGHT := 0.75 ## Cutaway sightline-corridor half-width (m) — character is 1 subtile wide; ## this covers them plus margin. Corridor length is pitch-derived per frame. const CUT_CORRIDOR_HALF_W := 1.4 ## Cutaway smoothstep falloff band (m) at the corridor edges. const CUT_BAND := 0.75 ## Cutaway mode default: 0 = sightline corridor, 1 = bottom walls low, 2 = both. ## User verdict (live session 2026-07-06): "both" — known interiors open at a ## glance AND the corridor punches through unexplored exterior walls. C cycles. const CUTAWAY_MODE := 2 # -- Locomotion interpolation (design §4) -------------------------------------- # Stance intervals: NOT duplicated — read InputMapper.MOVE_INTERVAL_MS at runtime. ## Leg-speed clamp for multi-tile latest-wins deltas: close within ~one interval. const CATCHUP_MAX_FACTOR := 3.0 ## 5 subtiles — matches the 2D TELEPORT_DISTANCE_THRESHOLD (main.gd:3). Beyond this, ## snap all channels (position, yaw, camera, 0.0-blend anim reset). const SNAP_DIST_M := 2.5 ## Walk↔idle flicker hysteresis (§4.2): is_moving stays true until at-target this long. const IDLE_ENTER_DELAY_S := 0.18 # -- Facing / turn smoothing (design §5, D-151) --------------------------------- ## Yaw ease rate (1/s): yaw = lerp_angle(yaw, target, 1 - exp(-TURN_SHARPNESS * delta)). const TURN_SHARPNESS := 14.0 ## Per-stance yaw budget clamp, degrees/second. const TURN_BUDGET_DEG := { "Sprint": 1080.0, "Walk": 720.0, "Careful": 540.0, "Crouch": 420.0, "Idle": 600.0, } # -- Animation (design §6) ------------------------------------------------------- ## Gait table (§6.1) — the ONLY place animation clip strings live. ## Clip names are the imported bare names: library "", "_Loop" stripped by the glTF ## importer, case-sensitive (design-input §2.2). Careful = Walk_Formal (D-053 stance ## readability at ortho distance; fallback if it reads "parade march": Walk at 0.6x — ## one table cell). Jog_Fwd is the reserve if Sprint reads too aggressive at 2.5 m/s. const GAIT_CLIP := { "Sprint": {"idle": &"Idle", "moving": &"Sprint"}, "Walk": {"idle": &"Idle", "moving": &"Walk"}, "Careful": {"idle": &"Idle", "moving": &"Walk_Formal"}, "Crouch": {"idle": &"Crouch_Idle", "moving": &"Crouch_Fwd"}, } ## Native clip ground speed (m/s) for cadence sync (§6.2): ## speed_scale = clamp(rig_speed / NATIVE_MPS[clip], SPEED_SCALE_CLAMP.x, .y). ## Initial guesses — tuned live against the DebugHud readout. const NATIVE_MPS := {"Walk": 1.4, "Walk_Formal": 1.2, "Sprint": 3.2, "Crouch_Fwd": 0.9} const SPEED_SCALE_CLAMP := Vector2(0.6, 1.8) ## Cross-fade seconds by transition kind (§6.3); teleport is a hard cut — a ## cross-map jump must not smear. const BLEND := { "idle_to_gait": 0.12, "gait_to_idle": 0.20, "gait_to_gait": 0.15, "crouch": 0.25, "teleport": 0.0, } # -- Camera (design §7; D-148, D-015, D-158) ------------------------------------- ## Pitch presets in degrees from horizontal — D-148 preset list is authoritative; ## the spike's -45 iso preset is struck. T-key cycles (sanctioned dev affordance). const CAM_PITCH_PRESETS := [-30.0, -5.0, -80.0] const CAM_DIST := 30.0 const CAM_ORTHO_SIZE := 9.0 ## Exponential pivot-follow rate (1/s) — deliberately the ONLY soft layer (§0). const CAM_FOLLOW_RATE := 6.0 ## Preset tilt lerp rate (1/s). const CAM_TILT_RATE := 3.0 ## Follow lookahead knob for the tuning pass (seconds of velocity lead). const LOOKAHEAD_S := 0.0 # -- Scene (design §1.2) ----------------------------------------------------------- ## WorldRoot yaw — the single static D-148 map-rotation Transform3D. Set once in ## locomotion_sandbox.tscn; sim coords stay axis-aligned inside WorldRoot and the ## camera never rotates. const MAP_ROTATION_DEG := 45.0 # -- Greybox tints (design §3.2) ----------------------------------------------------- ## Four-state visibility tint: Color values are used as instance color directly; ## float values multiply albedo value (85% / 70%). const TINTS := { "forward": Color.WHITE, "peripheral": 0.85, "boundary": 0.70, "remembered": Color(0.42, 0.45, 0.52), } # -- Input (design §9) --------------------------------------------------------------- ## Ground-plane deadzone (m) for the mouse facing provider — mirrors the 2D jitter guard. const MOUSE_AIM_DEADZONE_M := 0.1 # -- Head/torso look-at during path-follow (T-1088 follow-facing) --------------------- ## Head bone yaw limit (deg) for the mouse look-at while the body walks a path. const HEAD_LOOK_HEAD_LIMIT_DEG := 70.0 ## Torso (spine_02) contribution limit (deg) — engages when looking far lateral/behind. const HEAD_LOOK_TORSO_LIMIT_DEG := 30.0 ## Look-at influence fade in/out (s) on follow start/end. const HEAD_LOOK_FADE_S := 0.25 ## Aim point height above the mouse ground hit (m) — roughly eye level. const HEAD_LOOK_EYE_HEIGHT_M := 1.55 # -- Path preview / click-to-move (T-1088 live-session item 2) ------------------------ ## Move-here marker fill on the hovered destination subtile — distinct accent, ## semi-opaque so the floor tint reads through. const PATH_MARKER_COLOR := Color(0.30, 0.90, 1.0, 0.55) ## Optimal-path line colour (tile-center strip from the character to the destination). const PATH_LINE_COLOR := Color(0.30, 0.90, 1.0, 0.90) ## Marker sits this far above the floor plane (m) — clears grid-line z-fighting. const PATH_MARKER_Y := 0.02 ## Path line sits slightly higher than the marker so it reads on top of it. const PATH_LINE_Y := 0.06 ## RMB hold (ms) past which a right-click is a LONG-PRESS = go-there-then-crouch ## (committed on release), below which it is the click/double-click gesture. const RMB_LONG_PRESS_MS := 400