// Blueprints/BP_MainCharacter.ts import { AC_Camera } from '#root/Camera/Components/AC_Camera.ts'; import { AC_DebugHUD } from '#root/Debug/Components/AC_DebugHUD.ts'; import { AC_InputDevice } from '#root/Input/Components/AC_InputDevice.ts'; import { IMC_Default } from '#root/Input/IMC_Default.ts'; import { AC_Movement } from '#root/Movement/Components/AC_Movement.ts'; import { AC_ToastSystem } from '#root/Toasts/Components/AC_ToastSystem.ts'; import { CapsuleComponent } from '#root/UE/CapsuleComponent.ts'; import { Cast } from '#root/UE/Cast.ts'; import type { Controller } from '#root/UE/Controller.ts'; import { EnhancedInputLocalPlayerSubsystem } from '#root/UE/EnhancedInputLocalPlayerSubsystem.ts'; import type { Float } from '#root/UE/Float.ts'; import { MathLibrary } from '#root/UE/MathLibrary.ts'; import { Pawn } from '#root/UE/Pawn.ts'; import type { PlayerController } from '#root/UE/PlayerController.ts'; import { Rotator } from '#root/UE/Rotator.ts'; import { SystemLibrary } from '#root/UE/SystemLibrary.ts'; import { Vector } from '#root/UE/Vector.ts'; /** * Main Character Blueprint * Core player character with deterministic movement system * Integrates debug HUD and toast notification systems */ export class BP_MainCharacter extends Pawn { // ════════════════════════════════════════════════════════════════════════════════════════ // GRAPHS // ════════════════════════════════════════════════════════════════════════════════════════ // ──────────────────────────────────────────────────────────────────────────────────────── // EventGraph // ──────────────────────────────────────────────────────────────────────────────────────── /** * Handle controller change events - sets up Enhanced Input mapping context */ EventReceiveControllerChanged(NewController: Controller): void { const controller = Cast(NewController); const system = new EnhancedInputLocalPlayerSubsystem(); if (controller) { system.AddMappingContext(IMC_Default); } } /** Navigate to previous debug page */ EnhancedInputActionPrevDebugMode(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.PreviousPage(); } } /** Navigate to next debug page */ EnhancedInputActionINextDebugMode(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.NextPage(); } } /** Toggle debug HUD visibility */ EnhancedInputActionToggleHUD(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.ToggleDebugHUD(); } } /** Toggle visual debug rendering */ EnhancedInputActionToggleVisualDebug(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.ToggleVisualDebug(); } } /** * Process look input for camera rotation * @param actionValueX - Horizontal look input value * @param actionValueY - Vertical look input value */ EnhancedInputActionLookTriggered( actionValueX: Float, actionValueY: Float ): void { this.CameraComponent.ProcessLookInput( new Vector(actionValueX, actionValueY, 0), this.DeltaTime ); } /** * Reset look input when look action is completed */ EnhancedInputActionLookCompleted(): void { this.CameraComponent.ProcessLookInput(new Vector(0, 0, 0), this.DeltaTime); } /** * Process movement input for ground-based movement * @param ActionValueX - Horizontal movement input value (-1 to 1) * @param ActionValueY - Vertical movement input value (-1 to 1) */ EnhancedInputActionMoveTriggered( ActionValueX: Float, ActionValueY: Float ): void { const CalculateResultMovementInputVector = ( rightVector: Vector, forwardVector: Vector, actionValueX: Float, actionValueY: Float ): Vector => { const vec1 = new Vector( rightVector.X * actionValueX, rightVector.Y * actionValueX, 0 ); const vec2 = new Vector( forwardVector.X * actionValueY, forwardVector.Y * actionValueY, 0 ); return new Vector(vec1.X + vec2.X, vec1.Y + vec2.Y, 0); }; this.CurrentMovementInput = CalculateResultMovementInputVector( MathLibrary.GetRightVector( this.GetControlRotation().roll, 0, this.GetControlRotation().yaw ), MathLibrary.GetForwardVector(0, 0, this.GetControlRotation().yaw), ActionValueX, ActionValueY ); } /** * Reset movement input when move action is completed */ EnhancedInputActionMoveCompleted(): void { this.CurrentMovementInput = new Vector(0, 0, 0); } /** * Initialize all systems when character spawns * Order: Toast → Debug → Movement (movement last as it may generate debug output) */ EventBeginPlay(): void { if (this.ShowDebugInfo) { this.ToastSystemComponent.InitializeToastSystem(); } this.InputDeviceComponent.InitializeDeviceDetection( this.ToastSystemComponent, this.DebugHUDComponent ); if (this.ShowDebugInfo) { this.DebugHUDComponent.InitializeDebugHUD( this.ToastSystemComponent, this.InputDeviceComponent ); } this.MovementComponent.InitializeMovementSystem( this.CharacterCapsule, this.DebugHUDComponent ); this.CameraComponent.InitializeCameraSystem( this.InputDeviceComponent, this.DebugHUDComponent ); } /** * Update all systems each frame * Called by Unreal Engine game loop */ EventTick(DeltaTime: Float): void { this.DeltaTime = DeltaTime; if (this.ShowDebugInfo) { this.DebugHUDComponent.UpdateHUD(SystemLibrary.GetGameTimeInSeconds()); this.ToastSystemComponent.UpdateToastSystem(); } this.CameraComponent.UpdateCameraRotation(DeltaTime); this.GetController().SetControlRotation( new Rotator( 0, this.CameraComponent.GetCameraRotation().Pitch, this.CameraComponent.GetCameraRotation().Yaw ) ); this.MovementComponent.ProcessMovementInput( this.CurrentMovementInput, DeltaTime ); this.SetActorRotation(this.MovementComponent.GetCurrentRotation()); if (this.ShowDebugInfo) { this.MovementComponent.UpdateDebugPage(); this.InputDeviceComponent.UpdateDebugPage(); this.CameraComponent.UpdateDebugPage(); } } // ════════════════════════════════════════════════════════════════════════════════════════ // VARIABLES // ════════════════════════════════════════════════════════════════════════════════════════ /** * Camera system component - handles camera rotation and sensitivity * @category Components */ CameraComponent = new AC_Camera(); /** * Input device detection component - manages input device state and detection * @category Components */ InputDeviceComponent = new AC_InputDevice(); /** * Toast notification system - displays temporary status messages * @category Components */ ToastSystemComponent = new AC_ToastSystem(); /** * Debug HUD system - displays movement parameters and performance metrics * @category Components */ DebugHUDComponent = new AC_DebugHUD(); /** * Character's capsule component for collision detection * @category Components */ CharacterCapsule = new CapsuleComponent(); /** * Core movement system component - handles deterministic 3D platformer movement * @category Components */ MovementComponent = new AC_Movement(); /** * Master debug toggle - controls all debug systems (HUD, toasts, visual debug) * @category Debug * @instanceEditable true */ private ShowDebugInfo: boolean = true; /** * Cached delta time from last tick - used for time-based calculations */ private DeltaTime: Float = 0.0; /** * Current movement input vector - updated by input actions */ private CurrentMovementInput: Vector = new Vector(0, 0, 0); }