// Movement/Components/AC_Movement.ts import { BFL_Vectors } from '#root/Math/Libraries/BFL_Vectors.ts'; import { E_SurfaceType } from '#root/Movement/Enums/E_SurfaceType.ts'; import { S_AngleThresholds } from '#root/Movement/Structs/S_AngleThresholds.ts'; import type { S_MovementConstants } from '#root/Movement/Structs/S_MovementConstants.ts'; import { ActorComponent } from '#root/UE/ActorComponent.ts'; import type { Float } from '#root/UE/Float.ts'; import { MathLibrary } from '#root/UE/MathLibrary.ts'; import type { Vector } from '#root/UE/Vector.ts'; /** * Movement System Component * Core deterministic movement system for 3D platformer * Handles surface classification and movement physics calculations */ export class AC_Movement extends ActorComponent { // ════════════════════════════════════════════════════════════════════════════════════════ // FUNCTIONS // ════════════════════════════════════════════════════════════════════════════════════════ /** * Classify surface type based on normal vector * @param SurfaceNormal - Normalized surface normal vector * @param AngleThresholds - Angle thresholds in radians * @returns Surface type classification * @example * // Classify flat ground * ClassifySurface(new Vector(0,0,1), thresholds) // returns E_SurfaceType.Walkable * @pure true * @category Surface Detection */ public ClassifySurface( SurfaceNormal: Vector, AngleThresholds: S_AngleThresholds ): E_SurfaceType { const SurfaceAngle = BFL_Vectors.GetSurfaceAngle(SurfaceNormal); /** * Check if angle is within walkable range */ const IsWalkableAngle = (walkableAngle: Float): boolean => SurfaceAngle <= walkableAngle; /** * Check if angle is within steep slope range */ const IsSteepSlopeAngle = (steepSlopeAngle: Float): boolean => SurfaceAngle <= steepSlopeAngle; /** * Check if angle is within wall range */ const IsWallAngle = (wallAngle: Float): boolean => SurfaceAngle <= wallAngle; if (IsWalkableAngle(AngleThresholds.Walkable)) { return E_SurfaceType.Walkable; } else if (IsSteepSlopeAngle(AngleThresholds.SteepSlope)) { return E_SurfaceType.SteepSlope; } else if (IsWallAngle(AngleThresholds.Wall)) { return E_SurfaceType.Wall; } else { return E_SurfaceType.Ceiling; } } /** * Check if surface allows normal walking movement * @param SurfaceType - Surface type to check * @returns True if surface is walkable * @pure true * @category Surface Detection */ private IsSurfaceWalkable(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.Walkable; } /** * Check if surface causes sliding behavior * @param SurfaceType - Surface type to check * @returns True if surface is steep slope * @pure true * @category Surface Detection */ private IsSurfaceSteep(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.SteepSlope; } /** * Check if surface blocks movement (collision) * @param SurfaceType - Surface type to check * @returns True if surface is a wall * @pure true * @category Surface Detection */ private IsSurfaceWall(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.Wall; } /** * Check if surface is overhead (ceiling) * @param SurfaceType - Surface type to check * @returns True if surface is ceiling * @pure true * @category Surface Detection */ private IsSurfaceCeiling(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.Ceiling; } /** * Check if no surface detected (airborne state) * @param SurfaceType - Surface type to check * @returns True if no surface contact * @pure true * @category Surface Detection */ private IsSurfaceNone(SurfaceType: E_SurfaceType): boolean { return SurfaceType === E_SurfaceType.None; } /** * Initialize movement system with angle conversion * Converts degree thresholds to radians for runtime performance * @category System */ public InitializeMovementSystem(): void { this.IsInitialized = true; this.AngleThresholdsRads = { Walkable: MathLibrary.DegreesToRadians( this.AngleThresholdsDegrees.Walkable ), SteepSlope: MathLibrary.DegreesToRadians( this.AngleThresholdsDegrees.SteepSlope ), Wall: MathLibrary.DegreesToRadians(this.AngleThresholdsDegrees.Wall), }; } // ════════════════════════════════════════════════════════════════════════════════════════ // VARIABLES // ════════════════════════════════════════════════════════════════════════════════════════ /** * Movement physics constants * Controls speed, acceleration, friction, and gravity values * @category Movement Config * @instanceEditable true */ public readonly MovementConstants: S_MovementConstants = { MaxSpeed: 600.0, Acceleration: 2000.0, Friction: 8.0, Gravity: 980.0, }; /** * Surface classification angle thresholds in degrees * Walkable ≤50°, SteepSlope ≤85°, Wall ≤95°, Ceiling >95° * @category Movement Config * @instanceEditable true */ public readonly AngleThresholdsDegrees: S_AngleThresholds = { Walkable: 50.0, SteepSlope: 85.0, Wall: 95.0, }; /** * Runtime cached angle thresholds in radians * Converted from degrees during initialization for performance * @category Internal Cache */ private AngleThresholdsRads: S_AngleThresholds = { Walkable: 0.0, SteepSlope: 0.0, Wall: 0.0, }; /** * Flag indicating if movement system has been initialized * Ensures angle thresholds are converted before use * @category Debug */ public IsInitialized = false; }