// Content/Blueprints/BP_MainCharacter.ts import { AC_DebugHUD } from '/Content/Debug/Components/AC_DebugHUD.ts'; import { AC_InputDevice } from '/Content/Input/Components/AC_InputDevice.ts'; import { IMC_Default } from '/Content/Input/IMC_Default.ts'; import { AC_ToastSystem } from '/Content/Toasts/Components/AC_ToastSystem.ts'; import { Cast } from '/Content/UE/Cast.ts'; import type { Controller } from '/Content/UE/Controller.ts'; import { EnhancedInputLocalPlayerSubsystem } from '/Content/UE/EnhancedInputLocalPlayerSubsystem.ts'; import type { Float } from '/Content/UE/Float.ts'; import { MathLibrary } from '/Content/UE/MathLibrary.ts'; import type { PlayerController } from '/Content/UE/PlayerController.ts'; import { SystemLibrary } from '/Content/UE/SystemLibrary.ts'; import { Vector } from '/Content/UE/Vector.ts'; import { TengriCharacter } from '/Source/TengriPlatformer/Character/TengriCharacter.ts'; import { IA_Interact } from '/Content/Input/Actions/IA_Inreract.ts'; import { IA_Throw } from '/Content/Input/Actions/IA_Throw.ts'; import { IA_Aim } from '/Content/Input/Actions/IA_Aim.ts'; import { IMC_ItemHeld } from '/Content/Input/IMC_ItemHeld.ts'; import { CreateWidget } from '/Content/UE/CteateWidget.ts'; import { WBP_HUD } from '/Content/UI/WBP_HUD.ts'; import { CustomDefaultSkeletalMesh } from '/Content/BasicShapes/CustomDefaultSkeletalMesh.ts'; import { ETengriCameraBehavior } from '/Source/TengriPlatformer/Camera/Core/TengriCameraConfig.ts'; import { DA_CameraAiming } from '/Content/Camera/DA_CameraAiming.ts'; /** * Main Character Blueprint * Core player character with deterministic movement system * Integrates debug HUD and toast notification systems */ export class BP_MainCharacter extends TengriCharacter { // ════════════════════════════════════════════════════════════════════════════════════════ // 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 { if ( this.CameraManager.CurrentConfig.BehaviorType === ETengriCameraBehavior.FreeLook ) { this.AddControllerYawInput(actionValueX); this.AddControllerPitchInput(actionValueY); } } /** * 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.MovementComponent.SetInputVector( 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.MovementComponent.SetInputVector(new Vector(0, 0, 0)); } EnhancedInputActionJumpTriggered(): void { this.MovementComponent.SetJumpInput(true); } EnhancedInputActionJumpCompleted(): void { this.MovementComponent.SetJumpInput(false); } /** * 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 ); } CreateWidget(WBP_HUD).AddToViewport(); } /** * Update all systems each frame * Called by Unreal Engine game loop */ EventTick(): void { if (this.ShowDebugInfo) { this.DebugHUDComponent.UpdateHUD(SystemLibrary.GetGameTimeInSeconds()); this.ToastSystemComponent.UpdateToastSystem(); } if (this.ShowDebugInfo) { this.InputDeviceComponent.UpdateDebugPage(); } } // ════════════════════════════════════════════════════════════════════════════════════════ // VARIABLES // ════════════════════════════════════════════════════════════════════════════════════════ /** * 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(); /** * Master debug toggle - controls all debug systems (HUD, toasts, visual debug) * @category Debug * @instanceEditable true */ private ShowDebugInfo: boolean = true; constructor() { super(new DA_CameraAiming()); this.InteractAction = IA_Interact; this.ThrowAction = IA_Throw; this.AimAction = IA_Aim; this.ItemHeldMappingContext = IMC_ItemHeld; this.Mesh = new CustomDefaultSkeletalMesh(); } }