// Copyright Epic Games, Inc. All Rights Reserved. #include "LyraCharacterMovementComponent.h" #include "GameFramework/Character.h" #include "CollisionQueryParams.h" #include "Components/CapsuleComponent.h" #include "AbilitySystemGlobals.h" #include "NativeGameplayTags.h" #include "AbilitySystemComponent.h" UE_DEFINE_GAMEPLAY_TAG(TAG_Gameplay_MovementStopped, "Gameplay.MovementStopped"); namespace LyraCharacter { static float GroundTraceDistance = 100000.0f; FAutoConsoleVariableRef CVar_GroundTraceDistance(TEXT("LyraCharacter.GroundTraceDistance"), GroundTraceDistance, TEXT("Distance to trace down when generating ground information."), ECVF_Cheat); }; ULyraCharacterMovementComponent::ULyraCharacterMovementComponent(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { } void ULyraCharacterMovementComponent::SimulateMovement(float DeltaTime) { if (bHasReplicatedAcceleration) { // Preserve our replicated acceleration const FVector OriginalAcceleration = Acceleration; Super::SimulateMovement(DeltaTime); Acceleration = OriginalAcceleration; } else { Super::SimulateMovement(DeltaTime); } } bool ULyraCharacterMovementComponent::CanAttemptJump() const { // Same as UCharacterMovementComponent's implementation but without the crouch check return IsJumpAllowed() && (IsMovingOnGround() || IsFalling()); // Falling included for double-jump and non-zero jump hold time, but validated by character. } void ULyraCharacterMovementComponent::InitializeComponent() { Super::InitializeComponent(); } const FLyraCharacterGroundInfo& ULyraCharacterMovementComponent::GetGroundInfo() { if (!CharacterOwner || (GFrameCounter == CachedGroundInfo.LastUpdateFrame)) { return CachedGroundInfo; } if (MovementMode == MOVE_Walking) { CachedGroundInfo.GroundHitResult = CurrentFloor.HitResult; CachedGroundInfo.GroundDistance = 0.0f; } else { const UCapsuleComponent* CapsuleComp = CharacterOwner->GetCapsuleComponent(); check(CapsuleComp); const float CapsuleHalfHeight = CapsuleComp->GetUnscaledCapsuleHalfHeight(); const ECollisionChannel CollisionChannel = (UpdatedComponent ? UpdatedComponent->GetCollisionObjectType() : ECC_Pawn); const FVector TraceStart(GetActorLocation()); const FVector TraceEnd(TraceStart.X, TraceStart.Y, (TraceStart.Z - LyraCharacter::GroundTraceDistance - CapsuleHalfHeight)); FCollisionQueryParams QueryParams(SCENE_QUERY_STAT(LyraCharacterMovementComponent_GetGroundInfo), false, CharacterOwner); FCollisionResponseParams ResponseParam; InitCollisionParams(QueryParams, ResponseParam); FHitResult HitResult; GetWorld()->LineTraceSingleByChannel(HitResult, TraceStart, TraceEnd, CollisionChannel, QueryParams, ResponseParam); CachedGroundInfo.GroundHitResult = HitResult; CachedGroundInfo.GroundDistance = LyraCharacter::GroundTraceDistance; if (MovementMode == MOVE_NavWalking) { CachedGroundInfo.GroundDistance = 0.0f; } else if (HitResult.bBlockingHit) { CachedGroundInfo.GroundDistance = FMath::Max((HitResult.Distance - CapsuleHalfHeight), 0.0f); } } CachedGroundInfo.LastUpdateFrame = GFrameCounter; return CachedGroundInfo; } void ULyraCharacterMovementComponent::SetReplicatedAcceleration(const FVector& InAcceleration) { bHasReplicatedAcceleration = true; Acceleration = InAcceleration; } FRotator ULyraCharacterMovementComponent::GetDeltaRotation(float DeltaTime) const { if (UAbilitySystemComponent* ASC = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetOwner())) { if (ASC->HasMatchingGameplayTag(TAG_Gameplay_MovementStopped)) { return FRotator(0,0,0); } } return Super::GetDeltaRotation(DeltaTime); } float ULyraCharacterMovementComponent::GetMaxSpeed() const { if (UAbilitySystemComponent* ASC = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetOwner())) { if (ASC->HasMatchingGameplayTag(TAG_Gameplay_MovementStopped)) { return 0; } } return Super::GetMaxSpeed(); }