199{
200 if (IsValid(Character) == false)
201 {
202 return false;
203 }
204
206 UCapsuleComponent* CapsuleComponent = Character->GetCapsuleComponent();
207 UWorld* World = Character->GetWorld();
208 if (IsValid(MotionWarpingComponent) == false || IsValid(CapsuleComponent) == false || IsValid(World) == false)
209 {
210 return false;
211 }
212
213 FVector FacingDirection = IsValid(Instigator) ? Instigator->GetActorLocation() - Character->GetActorLocation() : Character->GetActorForwardVector();
214 FacingDirection.Z = 0.0f;
215
216 if (FacingDirection.Normalize() == false)
217 {
218 FacingDirection = Character->GetActorForwardVector();
219 FacingDirection.Z = 0.0f;
220 FacingDirection.Normalize();
221 }
222
223 const FVector KnockdownDirection = -FacingDirection;
224 const FVector SweepStart = CapsuleComponent->GetComponentLocation();
226
227
228 constexpr float CapsuleDecreaseValue = 2.0f;
229 const float CapsuleRadius = FMath::Max(CapsuleComponent->GetScaledCapsuleRadius() - CapsuleDecreaseValue , 1.0f);
230 const float CapsuleHalfHeight = FMath::Max(CapsuleComponent->GetScaledCapsuleHalfHeight() - CapsuleDecreaseValue , CapsuleRadius);
231 const FCollisionShape SweepShape = FCollisionShape::MakeCapsule(CapsuleRadius, CapsuleHalfHeight);
232
233
234 FCollisionObjectQueryParams ObjectQueryParams;
235 ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldStatic);
236 ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldDynamic);
237
238 FCollisionQueryParams QueryParams(SCENE_QUERY_STAT(PlayerKnockdownMotionWarp), false, Character);
239 FHitResult HitResult;
240 const bool bBlockingHit = World->SweepSingleByObjectType(HitResult, SweepStart, SweepEnd,FQuat::Identity, ObjectQueryParams, SweepShape, QueryParams);
241
242
243 constexpr float WallTolerance = 10.0f;
244 const float AvailableDistance = bBlockingHit ? FMath::Max(HitResult.Distance - WallTolerance, 0.0f) :
KnockDownDistance;
245 const FVector WarpTargetLocation = Character->GetActorLocation() + KnockdownDirection * AvailableDistance;
246
247 MotionWarpingComponent->UpdateMotionWarpTarget(
WarpTargetName, WarpTargetLocation, FacingDirection.Rotation());
248
249 return true;
250}