[cpp] Bird

Viewer

  1. // Copyright (c) 2019-2020 The Parasight
  2.  
  3. #include "AI/ForestEntity/Bird/RobinAIBirdMovementComponent.h"
  4. #include "AI/ForestEntity/RobinAIForestEntity.h"
  5. #include "AI/ForestEntity/RobinAIForestEntityAnimInstance.h"
  6. #include "DrawDebugHelpers.h"
  7. #include "GameLog.h"
  8. #include "GameProfiler.h"
  9. #include "Landscape.h"
  10. #include "LandscapeProxy.h"
  11. #include "Misc/RobinCharacterStatics.h"
  12. #include "Misc/RobinSplineActor.h"
  13. #include "Misc/RobinSplineComponent.h"
  14. #include "NavigationSystem.h"
  15. #include "Player/Character/RobinPlayerCharacter.h"
  16. #include "Player/Character/View/RobinPlayerViewControllerComponent.h"
  17. #include "Engine/TriggerBox.h"
  18. #include "Components/BoxComponent.h"
  19. #include "Kismet/KismetMathLibrary.h"
  20. #include "CommonGlobals.h"
  21. #include "AI/ForestEntity/Bird/RobinAIBirdAnimInstance.h"
  22. #include "CommonMathStatics.h"
  23.  
  24. DECLARE_CYCLE_STAT( TEXT( "Bird:Movement:Tick" ), STAT_ForestEntity_Bird_Movement_Tick, STATGROUP_RobinAI );
  25.  
  26. URobinAIBirdMovementComponent::URobinAIBirdMovementComponent()
  27. {
  28.         TraceFrequency = 0.2f;
  29. #if WITH_EDITORONLY_DATA
  30.         TraceFrequency.PerPlatform.Add( "XboxOne"0.5f );
  31.         TraceFrequency.PerPlatform.Add( "PS4"0.5f );
  32. #endif
  33. }
  34.  
  35. void URobinAIBirdMovementComponent::TickComponent( float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )
  36. {
  37.         GAME_SCOPE_CYCLE_COUNTER( STAT_ForestEntity_Bird_Movement_Tick );
  38.  
  39.         Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
  40.         if( Initialized && Status != ERobinAIBirdMovementType::Death )
  41.         {
  42.                 if( TraceTimer >= TraceFrequency.Default &&
  43.                         ( Status == ERobinAIBirdMovementType::AirMovement || Status == ERobinAIBirdMovementType::Landing || Status == ERobinAIBirdMovementType::StartLanding ||
  44.                                 Status == ERobinAIBirdMovementType::ChooseLanding ) &&
  45.                         !IsLerping )
  46.                 {
  47.                         TraceTimer = 0;
  48.  
  49.                         FCollisionQueryParams const QueryParams( SCENE_QUERY_STAT( BirdLandingTraceTest )false, GetOwner() );
  50.                         FCollisionResponseParams const ResponseParams = FCollisionResponseParams::DefaultResponseParam;
  51.                         GetWorld()->AsyncLineTraceByChannel( EAsyncTraceType::Single, UpdatedComponent->GetComponentLocation(),
  52.                                 UpdatedComponent->GetComponentLocation() + UpdatedComponent->GetForwardVector() * TraceLength, ECollisionChannel::ECC_WorldStatic, QueryParams, ResponseParams,
  53.                                 &DetectionTraceHandleDelegate );
  54.                 }
  55.                 else
  56.                 {
  57.                         TraceTimer += DeltaTime;
  58.                 }
  59.  
  60.                 UpdateActualMaxSpeed();
  61.  
  62.                 if( ObstacleRadius != 0.f && ( Status != ERobinAIBirdMovementType::LandMovement && Status != ERobinAIBirdMovementType::Death ) )
  63.                 {
  64.                         ProcessAvoidingObstacle( DeltaTime );
  65.                 }
  66.                 // else if (ObstacleRadius != 0.f && (Status != ERobinAIBirdMovementType::LandMovement && ))
  67.                 //{
  68.                 //      ObstacleRadius = 0;
  69.                 //}
  70.  
  71.                 if( UpdatedComponent && ObstacleRadius == 0.f )
  72.                 {
  73.                         RefreshAnimationModifierScales();
  74.  
  75.                         if( Status == ERobinAIBirdMovementType::LandMovement )
  76.                         {
  77.                                 if( IsFollowingPath() )
  78.                                 {
  79.                                         TimeSincePathFollowing += DeltaTime;
  80.                                         ProcessLandMovement( DeltaTime );
  81.                                 }
  82.                                 else
  83.                                 {
  84.                                         Velocity = FVector::ZeroVector;
  85.                                         DesiredVelocity = FVector::ZeroVector;
  86.                                 }
  87.                         }
  88.                         else if( Status == ERobinAIBirdMovementType::AirMovement && TakingOffMontage )
  89.                         {
  90.                                 ProcessAirMovement( DeltaTime );
  91.                         }
  92.                         else if( Status == ERobinAIBirdMovementType::StartLanding || Status == ERobinAIBirdMovementType::ChooseLanding )
  93.                         {
  94.                                 ProcessChoosingLandingTarget();
  95.                         }
  96.                         else if( Status == ERobinAIBirdMovementType::Landing )
  97.                         {
  98.                                 ProcessLanding( DeltaTime );
  99.                         }
  100.                 }
  101.         }
  102. }
  103.  
  104. void URobinAIBirdMovementComponent::BeginPlay()
  105. {
  106.         Super::BeginPlay();
  107.         if( ( !MovementSpline || AirMovementBox ) && Status == ERobinAIBirdMovementType::AirMovement )
  108.         {
  109.                 Status = ERobinAIBirdMovementType::ChooseLanding;
  110.         }
  111.         DetectionTraceHandleDelegate = FTraceDelegate::CreateUObject( this&URobinAIBirdMovementComponent::ProcessObstacleDetected );
  112.         CachedTraceFrequency = TraceFrequency.Default;
  113. }
  114.  
  115. uint32 URobinAIBirdMovementComponent::StartFollowingPath(
  116.         FNavigationPath const& PathToFollow, FName const& FinishMessageId, float const NewApproachTargetThreshold, UObject& Object )
  117. {
  118.         uint32 const RequestId = Super::StartFollowingPath( PathToFollow, FinishMessageId, NewApproachTargetThreshold, Object );
  119.         if( IsFollowingPath() )
  120.         {
  121.                 TimeSincePathFollowing = 0.0f;
  122.                 NextPathPoint = 1;
  123.         }
  124.         return RequestId;
  125. }
  126.  
  127. void URobinAIBirdMovementComponent::FinishFollowingPath( bool const Success )
  128. {
  129.         Super::FinishFollowingPath( Success );
  130. }
  131.  
  132. void URobinAIBirdMovementComponent::UpdateCurrentPath( FNavigationPath const& PathToFollow, float const NewApproachTargetThreshold )
  133. {
  134.         Super::UpdateCurrentPath( PathToFollow, NewApproachTargetThreshold );
  135.         if( Status == ERobinAIBirdMovementType::LandMovement )
  136.         {
  137.                 NextPathPoint = 1;
  138.                 TimeSincePathFollowing = 0.0f;
  139.         }
  140. }
  141.  
  142. void URobinAIBirdMovementComponent::StartStopping()
  143. {
  144.         Status = ERobinAIBirdMovementType::Stop;
  145. }
  146. // To change
  147. void URobinAIBirdMovementComponent::ProcessObstacleDetected( FTraceHandle const& Handle, FTraceDatum& Datum )
  148. {
  149.  
  150.         if( Datum.OutHits.IsValidIndex( 0 ) && !IsLerping )
  151.         {
  152.                 FHitResult const& Hit = Datum.OutHits.Last();
  153.                 if( Hit.bBlockingHit )
  154.                 {
  155.                         RequestGroundDetection();
  156.                         if( Hit.Actor.IsValid() && !Cast< ARobinAIForestEntity >( Hit.Actor ) )
  157.                         {
  158.                                 if( Cast< ALandscapeProxy >( Hit.Actor ) || Cast< ALandscape >( Hit.Actor ) || IsMovingOnGround() )
  159.                                 {
  160.                                         ObstacleAvoidTarget = UpdatedComponent->GetComponentLocation() + UpdatedComponent->GetUpVector() * TraceLength;
  161.                                         ObstacleRadius = TraceLength;
  162.                                         ObstacleLocation = Hit.Actor->GetActorLocation();
  163.                                         // FlyingPitchModifier = CachedFlyingPitchModifier + 0.1;
  164.                                 }
  165.                                 else
  166.                                 {
  167.                                         float const RandSign = FMath::RandBool() ? 1.0f : -1.0f;
  168.                                         FVector BoundingBox;
  169.                                         FVector Origin;
  170.                                         Hit.Actor->GetActorBounds( true, Origin, BoundingBox, false );
  171.                                         ObstacleRadius = BoundingBox.Size2D();
  172.                                         if( Hit.Component.IsValid() && Cast< UStaticMeshComponent >( Hit.Component ) )
  173.                                         {
  174.                                                 ObstacleRadius = BoundingBox.Size();
  175.                                                 ObstacleAvoidTarget = UpdatedComponent->GetComponentLocation() + UpdatedComponent->GetUpVector() * ( ObstacleRadius + TraceLength );
  176.                                                 ObstacleLocation = Hit.Component->GetComponentLocation();
  177.                                                 // FlyingPitchModifier = CachedFlyingPitchModifier + 0.1;
  178.                                                 // TraceFrequency = 0.1f;
  179.                                         }
  180.                                         else
  181.                                         {
  182.                                                 ObstacleAvoidTarget = UpdatedComponent->GetComponentLocation() + UpdatedComponent->GetUpVector() * 300 +
  183.                                                                                           RandSign * UpdatedComponent->GetRightVector() * 2 * ( ObstacleRadius + TraceLength );
  184.                                                 ObstacleLocation = Hit.Actor->GetActorLocation();
  185.                                         }
  186.                                 }
  187.                         }
  188.                 }
  189.         }
  190.         else
  191.         {
  192.                 ObstacleRadius = 0;
  193.                 FlyingPitchModifier = CachedFlyingPitchModifier;
  194.                 TraceFrequency = CachedTraceFrequency;
  195.         }
  196. }
  197.  
  198. void URobinAIBirdMovementComponent::SetStartingMovement( ERobinAIBirdStartingMovement const StartingMovement )
  199. {
  200.         switch( StartingMovement )
  201.         {
  202.                 case ERobinAIBirdStartingMovement::InAir:
  203.                         Status = ERobinAIBirdMovementType::AirMovement;
  204.                         if( MovementSpline && AirMovementBox )
  205.                         {
  206.                                 IsFlyingInBox = FMath::RandBool();
  207.                                 IsFlyingOnSpline = !IsFlyingInBox;
  208.                         }
  209.                         break;
  210.                 case ERobinAIBirdStartingMovement::OnLand:
  211.                         Status = ERobinAIBirdMovementType::LandMovement;
  212.                         break;
  213.                 case ERobinAIBirdStartingMovement::OnPoint:
  214.                         Status = ERobinAIBirdMovementType::LandMovement;
  215.                         break;
  216.         }
  217.  
  218.         FlyingRotationSpeedScale = FMath::RandRange( FlyingRotationSpeed.X, FlyingRotationSpeed.Y );
  219.         FlyingFrontOffset = FMath::RandRange( FrontFlyingOffset.X, FrontFlyingOffset.Y );
  220.         BirdRegularFlyMoveSpeed = FMath::RandRange( RegularFlyingMoveSpeed.X, RegularFlyingMoveSpeed.Y );
  221.         BirdAlertedFlyMoveSpeed = FMath::RandRange( AlertedFlyingMoveSpeed.X, AlertedFlyingMoveSpeed.Y );
  222. }
  223.  
  224. void URobinAIBirdMovementComponent::SetMovementSpline( ARobinSplineActor* const Spline )
  225. {
  226.         MovementSpline = Spline;
  227.         IsFlyingOnSpline = true;
  228.         // SideFlyOffset = FMath::RandRange( MinSideFlyOffset, MaxSideFlyOffset );
  229. }
  230.  
  231. void URobinAIBirdMovementComponent::SetMovementStatus( ERobinAIBirdMovementType const NewStatus )
  232. {
  233.         if( Status == ERobinAIBirdMovementType::LandMovement && NewStatus == ERobinAIBirdMovementType::AirMovement )
  234.         {
  235.                 // ProcessMainMontageBlendingOut(TakingOffMontage, false);
  236.                 PlayMontage( TakingOffMontage );
  237.                 if( MovementSpline && AirMovementBox )
  238.                 {
  239.                         IsFlyingInBox = FMath::RandBool();
  240.                         IsFlyingOnSpline = !IsFlyingInBox;
  241.                 }
  242.         }
  243.  
  244.         if( Status != ERobinAIBirdMovementType::Death && ( Status != ERobinAIBirdMovementType::LandMovement ) ) // && NewStatus == ERobinAIBirdMovementType::AirMovement))
  245.         {
  246.                 Status = NewStatus;
  247.         }
  248. }
  249.  
  250. ERobinAIBirdMovementType URobinAIBirdMovementComponent::GetMovementStatus() const
  251. {
  252.         return Status;
  253. }
  254.  
  255. void URobinAIBirdMovementComponent::SetAlerted( bool const Alert )
  256. {
  257.         IsAlerted = Alert;
  258. }
  259.  
  260. void URobinAIBirdMovementComponent::ProcessLandMovement( float const DeltaTime )
  261. {
  262.         check( UpdatedComponent );
  263.         if( ActivePath.IsValidLocationIndex( NextPathPoint ) && !CanLandOnObjects )
  264.         {
  265.                 FVector const InitialLocation = UpdatedComponent->GetComponentLocation();
  266.                 FVector const TargetLocation = ActivePath.GetLocation( NextPathPoint ).Location + GetFeetOffset();
  267.                 FVector const ToTargetFlat = CalculateFlatDirection( TargetLocation - InitialLocation, UpdatedComponent->GetForwardVector() );
  268.                 float const EffectiveRotationSpeed = ( RotationSpeed ? RotationSpeed->GetFloatValue( TimeSincePathFollowing ) : 1.0f );
  269.                 FRotator const NewRotation = FMath::RInterpConstantTo( UpdatedComponent->GetComponentRotation(), ToTargetFlat.ToOrientationRotator(), DeltaTime, EffectiveRotationSpeed );
  270.                 FVector const Forward = NewRotation.Vector();
  271.                 float const EffectiveMoveSpeed = LandMoveSpeed * ExtraMovementSpeedScale.GetMin( 1.0f ) * AnimationMovementModifierScale;
  272.                 FVector const LocationDelta = Forward * EffectiveMoveSpeed * DeltaTime;
  273.                 FVector const AppliedLocationDelta = ApplyLocationDelta( LocationDelta, Forward.ToOrientationQuat(), DeltaTime, true );
  274.                 Velocity = AppliedLocationDelta / FMath::Max( DeltaTime, 0.001f );
  275.                 DesiredVelocity = Velocity.GetSafeNormal() * LandMoveSpeed * ExtraMovementSpeedScale.GetMin( 1.0f );
  276.  
  277.                 RequestGroundDetection();
  278.                 if( !IsMovingOnGround() )
  279.                 {
  280.                         ApplyVelocity( -FVector::UpVector * 500.0f * DeltaTime, UpdatedComponent->GetComponentQuat(), DeltaTime, true );
  281.                 }
  282.  
  283.                 if( IsAtLocation( TargetLocation, TargetRadius ) )
  284.                 {
  285.                         FinishFollowingPath( true );
  286.                 }
  287.         }
  288.         else
  289.         {
  290.                 FinishFollowingPath( false );
  291.         }
  292. }
  293.  
  294. void URobinAIBirdMovementComponent::ProcessChoosingLandingTarget()
  295. {
  296.         check( UpdatedComponent );
  297.         FVector const InitialLocation = UpdatedComponent->GetComponentLocation();
  298.         if( !CanLandOnObjects )
  299.         {
  300.                 TOptional< FVector > SelectedTarget;
  301.                 UNavigationSystemV1* const NavigationSystem = UNavigationSystemV1::GetCurrent( GetWorld() );
  302.                 if( NavigationSystem )
  303.                 {
  304.                         if( OwnerEntity.IsValid() )
  305.                         {
  306.                                 INavAgentInterface* const Agent = Cast< INavAgentInterface >( OwnerEntity );
  307.                                 if( Agent )
  308.                                 {
  309.                                         FNavAgentProperties const& AgentProperties = Agent->GetNavAgentPropertiesRef();
  310.                                         ANavigationData* const NavigationData = NavigationSystem->GetNavDataForProps( AgentProperties );
  311.                                         if( NavigationData )
  312.                                         {
  313.                                                 FNavLocation ProjectedLocation;
  314.                                                 if( NavigationSystem->ProjectPointToNavigation(
  315.                                                                 InitialLocation + UpdatedComponent->GetForwardVector(), ProjectedLocation, FVector( 50.f50.f5000.f ), NavigationData ) )
  316.                                                 {
  317.                                                         SelectedTarget = ProjectedLocation.Location;
  318.                                                         LandingStartLocation = InitialLocation + UpdatedComponent->GetForwardVector() * FVector::Distance( InitialLocation, SelectedTarget.GetValue() ) / 3;
  319.                                                 }
  320.                                         }
  321.                                 }
  322.                         }
  323.                 }
  324.                 if( SelectedTarget.IsSet() )
  325.                 {
  326.                         LandingTarget = SelectedTarget.GetValue();
  327.                         Status = ERobinAIBirdMovementType::Landing;
  328.                         IsLerping = false;
  329.                 }
  330.                 else
  331.                 {
  332.                         Status = ERobinAIBirdMovementType::AirMovement;
  333.                 }
  334.         }
  335.         else
  336.         {
  337.                 if( LandingOnObjectTarget != FVector::ZeroVector )
  338.                 {
  339.                         LandingTarget = LandingOnObjectTarget;
  340.                         LandingStartLocation = InitialLocation + UpdatedComponent->GetForwardVector() * FVector::Distance( InitialLocation, LandingTarget ) / 3;
  341.                         SetMovementStatus( ERobinAIBirdMovementType::Landing );
  342.                         IsLerping = false;
  343.                 }
  344.                 else
  345.                 {
  346.                         SetMovementStatus( ERobinAIBirdMovementType::AirMovement );
  347.                 }
  348.         }
  349. }
  350.  
  351. // Work In Progress, Lot of magic numbers and random stuff, reading this may cause health issues
  352. void URobinAIBirdMovementComponent::ProcessAirMovement( float const DeltaTime )
  353. {
  354.         check( UpdatedComponent );
  355.         if( ( AirMovementBox || MovementSpline ) && Status != ERobinAIBirdMovementType::Death )
  356.         {
  357.                 FVector const InitialLocation = UpdatedComponent->GetComponentLocation();
  358.                 FVector DirectionToTarget;
  359.                 if( IsFlyingInBox && !IsFlyingOnSpline && !IsFlyingToPoint )
  360.                 {
  361.                         NextPoint = GetRandomPointForFlying();
  362.                 }
  363.                 else if( IsFlyingInBox && !IsFlyingOnSpline && IsFlyingToPoint && IsAtLocation( NextPoint, TargetRadius + 50 ) )
  364.                 {
  365.                         IsFlyingToPoint = false;
  366.                 }
  367.  
  368.                 else if( IsFlyingOnSpline && !IsFlyingInBox )
  369.                 {
  370.                         URobinSplineComponent const& SplineComponent = MovementSpline->GetSpline();
  371.                         FVector const ClosestPointOnSpline =
  372.                                 SplineComponent.FindTangentClosestToWorldLocation( InitialLocation, ESplineCoordinateSpace::World ).GetSafeNormal() * FlyingFrontOffset;
  373.                         FVector const TargetOnSplineVector = InitialLocation + ClosestPointOnSpline;
  374.                         FVector const ClosestPositionToGet = SplineComponent.FindLocationClosestToWorldLocation( TargetOnSplineVector, ESplineCoordinateSpace::World );
  375.                         NextPoint = ClosestPositionToGet + GetFeetOffset();
  376.                 }
  377.                 DirectionToTarget = NextPoint - InitialLocation;
  378.  
  379.                 float AngleToNextPoint =
  380.                         UCommonMathStatics::AngleSignedCoplanarVectorsDegrees( FVector::UpVector, UpdatedComponent->GetForwardVector(), NextPoint - UpdatedComponent->GetComponentLocation() );
  381.                 ////SCREEN_LOG("{}", ActualFlyingSpeed / ActualMaxSpeed );
  382.                 FRotator RotationToDirection = DirectionToTarget.ToOrientationRotator();
  383.                 // if (AngleToNextPoint > 0)
  384.                 //{
  385.                 //      UpdatedComponent->AddRelativeRotation(FRotator(0, 0, 50));
  386.                 //      //RotationToDirection.Yaw = 250;
  387.                 //      //RotationToDirection.Pitch = 250;
  388.                 //}
  389.                 // else
  390.                 //{
  391.                 //      UpdatedComponent->AddRelativeRotation(FRotator(0, 0, 50));
  392.                 //      //RotationToDirection.Pitch = -250;
  393.                 //      //RotationToDirection.Yaw = -250;
  394.                 //      //RotationToDirection.Pitch = -250;
  395.                 //}
  396.  
  397.                 FRotator const NewRotation = FMath::RInterpConstantTo(
  398.                         UpdatedComponent->GetComponentRotation(), RotationToDirection, DeltaTime, FlyingRotationSpeedScale / ( ActualMaxFlyingSpeed / ActualFlyingSpeed ) );
  399.                 UpdateFlyingSpeedOnSharpTurn(AngleToNextPoint, (IsFlyingInBox ? 90.f : 30), DeltaTime);
  400.                 //// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  401.                 //if( FMath::Abs( AngleToNextPoint ) >= ( IsFlyingInBox ? 90.f : 30 ) && ActualFlyingSpeed > 400 )
  402.                 //{
  403.                 //      ActualFlyingSpeed -= ( AirResistance + 150 ) * DeltaTime;
  404.                 //      // DrawDebugSphere(GetWorld(), NextPoint, 50, 10, FColor::Red, false, 20.f, 0, 1);
  405.                 //}
  406.  
  407.                 //if( ShouldGainSpeed )
  408.                 //{
  409.                 //      ActualFlyingSpeed += ( AirResistance + 60 ) * DeltaTime;
  410.                 //      if( ActualFlyingSpeed >= ActualMaxFlyingSpeed )
  411.                 //      {
  412.                 //              ShouldGainSpeed = false;
  413.                 //      }
  414.                 //}
  415.                 //else
  416.                 //{
  417.                 //      ActualFlyingSpeed -= AirResistance * DeltaTime;
  418.                 //      if( ActualFlyingSpeed <= 400 )
  419.                 //      {
  420.                 //              ShouldGainSpeed = true;
  421.                 //      }
  422.                 //}
  423.                 //// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  424.  
  425.                 // ActualFlyingSpeed -= ( FMath::Abs( NewRotation.Yaw ) / 180 )
  426.                 FVector const Forward = FRotator( NewRotation.Pitch * FlyingPitchModifier, NewRotation.Yaw, NewRotation.Roll ).Vector();
  427.                 // FVector const Forward = NewRotation.Vector();
  428.                 float const EffectiveMoveSpeed = ActualFlyingSpeed; //* AnimationMovementModifierScale;
  429.                 FVector const LocationDelta = Forward * EffectiveMoveSpeed * DeltaTime;
  430.                 FVector const AppliedLocationDelta = ApplyLocationDelta( LocationDelta, Forward.ToOrientationQuat(), DeltaTime, false );
  431.                 Velocity = AppliedLocationDelta / FMath::Max( DeltaTime, 0.001f );
  432.                 DesiredVelocity = Velocity.GetSafeNormal() * ActualFlyingSpeed;
  433.                 CanStartLanding = false;
  434.                 CanLandOnObjects = false;
  435.                 UpdateAnimInstance( DeltaTime );
  436.         }
  437. }
  438.  
  439. // Work In Progress, Lot of magic numbers and random stuff, reading this may cause health issues
  440. void URobinAIBirdMovementComponent::ProcessLanding( float const DeltaTime )
  441. {
  442.         check( UpdatedComponent );
  443.         if( !IsLerping )
  444.         {
  445.                 if( TimeSinceLanding <= MaxLandingTimeForForceMoveAttempt )
  446.                 {
  447.                         TimeSinceLanding += DeltaTime;
  448.                 }
  449.                 else
  450.                 {
  451.                         RequestGroundDetection();
  452.                         if( CanSnapToLandingTarget() )
  453.                         {
  454.                                 UpdatedComponent->SetWorldLocation( LandingTarget + GetFeetOffset() );
  455.                         }
  456.                         else if( !CanSnapToLandingTarget() && IsMovingOnGround() )
  457.                         {
  458.                                 CachedLandingRotationSpeed = CachedLandingRotationSpeed + 30;
  459.                         }
  460.                 }
  461.         }
  462.         FVector const InitialLocation = UpdatedComponent->GetComponentLocation();
  463.  
  464.         if( !CanStartLanding )
  465.         {
  466.                 FVector const ToTarget = LandingStartLocation - InitialLocation + GetFeetOffset();
  467.                 FRotator const RotationToTarget = ToTarget.ToOrientationRotator();
  468.  
  469.                 float const AngleToLandingTarget = UCommonMathStatics::AngleSignedCoplanarVectorsDegrees( FVector::UpVector, UpdatedComponent->GetForwardVector(), ToTarget );
  470.                 UpdateFlyingSpeedOnSharpTurn(AngleToLandingTarget, 120.f, DeltaTime);
  471.                 //// FMath::RInterpConstantTo( UpdatedComponent->GetComponentRotation(), ToTarget.ToOrientationRotator(), DeltaTime, FlyingRotationSpeedScale + DeltaTime );
  472.                 //// ToTarget.ToOrientationRotator();
  473.                 //// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  474.                 //if( FMath::Abs( AngleToLandingTarget ) >= 120.f && ActualFlyingSpeed > 200 )
  475.                 //{
  476.                 //      ActualFlyingSpeed -= ( AirResistance + 100 ) * DeltaTime;
  477.                 //      // DrawDebugSphere(GetWorld(), NextPoint, 50, 10, FColor::Red, false, 20.f, 0, 1);
  478.                 //}
  479.  
  480.                 //if( ShouldGainSpeed )
  481.                 //{
  482.                 //      ActualFlyingSpeed += ( AirResistance + 100 ) * DeltaTime;
  483.                 //      if( ActualFlyingSpeed >= ActualMaxFlyingSpeed )
  484.                 //      {
  485.                 //              ShouldGainSpeed = false;
  486.                 //      }
  487.                 //}
  488.                 //else
  489.                 //{
  490.                 //      ActualFlyingSpeed -= AirResistance * DeltaTime;
  491.                 //      if( ActualFlyingSpeed <= 200 )
  492.                 //      {
  493.                 //              ShouldGainSpeed = true;
  494.                 //      }
  495.                 //}
  496.                 //// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  497.  
  498.                 float Distance = FVector::Distance( InitialLocation, LandingStartLocation );
  499.                 FRotator const NewRotation = FMath::RInterpConstantTo(
  500.                         UpdatedComponent->GetComponentRotation(), RotationToTarget, DeltaTime, FlyingRotationSpeedScale * ( ActualMaxFlyingSpeed / ActualFlyingSpeed ) );
  501.                 if( Distance > LerpDistance )
  502.                 {
  503.                         FVector const Forward = NewRotation.Vector();
  504.                         float const EffectiveMoveSpeed = ActualFlyingSpeed * AnimationMovementModifierScale;
  505.                         FVector const LocationDelta = Forward * EffectiveMoveSpeed * DeltaTime;
  506.                         FVector const AppliedLocationDelta = ApplyLocationDelta( LocationDelta, Forward.ToOrientationQuat(), DeltaTime, false );
  507.                         Velocity = AppliedLocationDelta / FMath::Max( DeltaTime, 0.001f );
  508.                         DesiredVelocity = Velocity.GetSafeNormal() * ActualFlyingSpeed / TimeSinceLanding;
  509.                 }
  510.                 else
  511.                 {
  512.                         CanStartLanding = true;
  513.                 }
  514.                 UpdateAnimInstance( DeltaTime );
  515.         }
  516.         else
  517.         {
  518.                 FVector const ToTarget = LandingTarget - InitialLocation + GetFeetOffset();
  519.                 FRotator const RotationToTarget = ToTarget.ToOrientationRotator();
  520.  
  521.                 float AngleToLandingTarget = UCommonMathStatics::AngleSignedCoplanarVectorsDegrees( FVector::UpVector, UpdatedComponent->GetForwardVector(), ToTarget );
  522.                 UpdateFlyingSpeedOnSharpTurn( AngleToLandingTarget, 120.f, DeltaTime );
  523.                 // if (FMath::Abs(AngleToLandingTarget) >= 120.f  && ActualFlyingSpeed > 200)
  524.                 //{
  525.                 //      ActualFlyingSpeed -= (AirResistance + 150) * DeltaTime;
  526.                 //      // DrawDebugSphere(GetWorld(), NextPoint, 50, 10, FColor::Red, false, 20.f, 0, 1);
  527.                 //}
  528.  
  529.                 //// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  530.                 // if (FMath::Abs(AngleToLandingTarget) >= 120.f  && ActualFlyingSpeed > 200)
  531.                 //{
  532.                 //      ActualFlyingSpeed -= (AirResistance + 100) * DeltaTime;
  533.                 //      // DrawDebugSphere(GetWorld(), NextPoint, 50, 10, FColor::Red, false, 20.f, 0, 1);
  534.                 //}
  535.  
  536.                 // if (ShouldGainSpeed)
  537.                 //{
  538.                 //      ActualFlyingSpeed += (AirResistance + 100) * DeltaTime;
  539.                 //      if (ActualFlyingSpeed >= ActualMaxFlyingSpeed)
  540.                 //      {
  541.                 //              ShouldGainSpeed = false;
  542.                 //      }
  543.                 //}
  544.                 // else
  545.                 //{
  546.                 //      ActualFlyingSpeed -= AirResistance * DeltaTime;
  547.                 //      if (ActualFlyingSpeed <= 200)
  548.                 //      {
  549.                 //              ShouldGainSpeed = true;
  550.                 //      }
  551.                 //}
  552.                 //// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  553.  
  554.                 if( !IsLerping )
  555.                 {
  556.                         FRotator const NewRotation = FMath::RInterpConstantTo(
  557.                                 UpdatedComponent->GetComponentRotation(), RotationToTarget, DeltaTime, CachedLandingRotationSpeed * ( ActualMaxFlyingSpeed / ActualFlyingSpeed ) );
  558.                         FVector const Forward = FRotator( NewRotation.Pitch * LandingPitchModifier, NewRotation.Yaw, NewRotation.Roll ).Vector();
  559.                         float const EffectiveMoveSpeed = ActualFlyingSpeed * AnimationMovementModifierScale;
  560.                         FVector const LocationDelta = Forward * EffectiveMoveSpeed * DeltaTime;
  561.                         FVector const AppliedLocationDelta = ApplyLocationDelta( LocationDelta, Forward.ToOrientationQuat(), DeltaTime, false );
  562.                         Velocity = AppliedLocationDelta; // / FMath::Max( DeltaTime, 0.001f );
  563.                         DesiredVelocity = Velocity.GetSafeNormal() * ActualFlyingSpeed / TimeSinceLanding;
  564.  
  565.                         if( FVector::Distance( UpdatedComponent->GetComponentLocation(), LandingTarget ) < 200.0f )
  566.                         {
  567.                                 IsLerping = true;
  568.                                 CachedLandingRotationSpeed = LandingRotationSpeed;
  569.                                 CachedRotation = UpdatedComponent->GetComponentRotation();
  570.                                 CachedLocation = UpdatedComponent->GetComponentLocation();
  571.                                 CachedFlatDirectionToTarget = CalculateFlatDirection( ToTarget, UpdatedComponent->GetForwardVector() );
  572.                                 CachedFlatRotationToTarget = CachedFlatDirectionToTarget.ToOrientationRotator();
  573.                                 TimeSinceLerping = 0.0f;
  574.                         }
  575.                         UpdateAnimInstance( DeltaTime );
  576.                 }
  577.                 else
  578.                 {
  579.                         TimeSinceLerping += DeltaTime;
  580.                         float const Alpha = FMath::Clamp( TimeSinceLerping / LerpDuration, 0.0f1.0f );
  581.                         Velocity = FVector::ZeroVector;
  582.                         FVector const NewLocation = FMath::Lerp( CachedLocation, LandingTarget + GetFeetOffset(), Alpha );
  583.                         FRotator NewRotation = FMath::Lerp( CachedRotation, CachedFlatRotationToTarget, Alpha );
  584.                         NewRotation.Pitch = 0;
  585.                         UpdatedComponent->SetWorldLocationAndRotation( NewLocation, NewRotation );
  586.  
  587.                         if( Alpha > 0.8f )
  588.                         {
  589.                                 PlayMontage( LandingMontage );
  590.                                 OnFinishedLandingBP.Broadcast();
  591.                                 TimeSinceLanding = 0;
  592.                                 ActualFlyingSpeed = 300.f;
  593.                                 UpdateAnimInstance( DeltaTime );
  594.                         }
  595.                 }
  596.         }
  597. }
  598.  
  599. void URobinAIBirdMovementComponent::ProcessAvoidingObstacle( float const DeltaTime )
  600. {
  601.         if( !IsLerping )
  602.         {
  603.                 if( UpdatedComponent && ( FVector::Distance( UpdatedComponent->GetComponentLocation(), ObstacleAvoidTarget ) < GetFeetOffset().Size() ) )
  604.                 {
  605.                         FCollisionQueryParams const QueryParams( SCENE_QUERY_STAT( BirdLandingTraceTest )false, GetOwner() );
  606.                         FCollisionResponseParams const ResponseParams = FCollisionResponseParams::DefaultResponseParam;
  607.                         ObstacleRadius = 0;
  608.                         GetWorld()->AsyncLineTraceByChannel( EAsyncTraceType::Single, UpdatedComponent->GetComponentLocation(),
  609.                                 UpdatedComponent->GetComponentLocation() + UpdatedComponent->GetForwardVector() * TraceLength, ECollisionChannel::ECC_Visibility, QueryParams, ResponseParams,
  610.                                 &DetectionTraceHandleDelegate );
  611.                 }
  612.                 else
  613.                 {
  614.                         FVector const ToTarget = ObstacleAvoidTarget;
  615.                         FVector const DirectionToTarget = ToTarget - UpdatedComponent->GetComponentLocation();
  616.                         FRotator const NewRotation = FMath::RInterpConstantTo( UpdatedComponent->GetComponentRotation(), DirectionToTarget.ToOrientationRotator(), DeltaTime,
  617.                                 FlyingRotationSpeedScale * ( ActualMaxFlyingSpeed / ActualFlyingSpeed ) );
  618.                         FVector const Forward = NewRotation.Vector();
  619.                         float const EffectiveMoveSpeed = ActualFlyingSpeed * AnimationMovementModifierScale;
  620.                         FVector const LocationDelta = Forward * EffectiveMoveSpeed * DeltaTime;
  621.                         FVector const AppliedLocationDelta = ApplyLocationDelta( LocationDelta, Forward.ToOrientationQuat(), DeltaTime, false );
  622.                         Velocity = AppliedLocationDelta / FMath::Max( DeltaTime, 0.001f );
  623.                 }
  624.         }
  625. }
  626.  
  627. void URobinAIBirdMovementComponent::PlayMontage( UAnimMontage* const NewMontage )
  628. {
  629.         check( UpdatedComponent );
  630.         check( OwnerEntity.IsValid() );
  631.         if( NewMontage )
  632.         {
  633.                 if( URobinAIForestEntityAnimInstance* const AnimInstance = OwnerEntity->GetMainAnimInstance() )
  634.                 {
  635.                         if( NewMontage != ActiveMontage )
  636.                         {
  637.                                 AnimInstance->Montage_Play( NewMontage );
  638.                                 ActiveMontage = NewMontage;
  639.                         }
  640.                 }
  641.         }
  642. }
  643. // TO DELETE
  644. // void URobinAIBirdMovementComponent::PlayTakingOffMontage()
  645. //{
  646. // check( UpdatedComponent );
  647. // check( OwnerEntity.IsValid() );
  648. // if( URobinAIForestEntityAnimInstance* const AnimInstance = OwnerEntity->GetMainAnimInstance() )
  649. //{
  650. //      AnimInstance->Montage_Play( TakingOffMontage );
  651. //      ActiveMontage = TakingOffMontage;
  652. //      IsLerping = false;
  653. //}
  654. //}
  655.  
  656. void URobinAIBirdMovementComponent::ProcessMainMontageBlendingOut( UAnimMontage* Montage, bool Interrupted )
  657. {
  658.         if( Montage == LandingMontage )
  659.         {
  660.                 Status = ERobinAIBirdMovementType::LandMovement;
  661.         }
  662.         if( Montage == TakingOffMontage )
  663.         {
  664.                 Status = ERobinAIBirdMovementType::AirMovement;
  665.         }
  666. }
  667.  
  668. void URobinAIBirdMovementComponent::ProccessMainMontageEnded( UAnimMontage* Montage, bool Interrupted )
  669. {
  670.         if( Montage == LandingMontage || Montage == TakingOffMontage )
  671.         {
  672.                 ActiveMontage.Reset();
  673.         }
  674. }
  675.  
  676. void URobinAIBirdMovementComponent::UpdateAnimInstance( float const DeltaTime )
  677. {
  678.         if( OwnerEntity.IsValid() )
  679.         {
  680.                 float const EffectiveAnimationSpeedScale = AnimationSpeedScale.GetProduct( 1.0f );
  681.                 URobinAIBirdAnimInstance* BirdAnimInstance = Cast< URobinAIBirdAnimInstance >( OwnerEntity->GetMainAnimInstance() );
  682.                 if( BirdAnimInstance )
  683.                 {
  684.                         if( Status != ERobinAIBirdMovementType::Landing )
  685.                         {
  686.                                 BirdAnimInstance->SetSpeed( Velocity.Size2D() );
  687.                         }
  688.                         else
  689.                         {
  690.                                 // During landing it will have different value
  691.                                 BirdAnimInstance->SetSpeed( Velocity.Size2D() );
  692.                         }
  693.                 }
  694.         }
  695. }
  696.  
  697. void URobinAIBirdMovementComponent::SetCanLandOnObjects( bool const CanLand )
  698. {
  699.         CanLandOnObjects = CanLand;
  700. }
  701.  
  702. void URobinAIBirdMovementComponent::SetLandingOnObjectTarget( FVector const Location )
  703. {
  704.         LandingOnObjectTarget = Location;
  705. }
  706.  
  707. bool URobinAIBirdMovementComponent::CanSnapToLandingTarget() const
  708. {
  709.         check( UpdatedComponent );
  710.         ARobinPlayerCharacter* const Player = URobinCharacterStatics::GetMainPlayer( this );
  711.         if( Player )
  712.         {
  713.                 URobinPlayerViewControllerComponent const& ViewController = Player->GetViewController();
  714.                 if( !ViewController.IsPlayerFacingLocation( UpdatedComponent->GetComponentLocation()70.f4000.f ) )
  715.                 {
  716.                         if( !ViewController.IsPlayerFacingLocation( LandingTarget ) )
  717.                         {
  718.                                 return true;
  719.                         }
  720.                 }
  721.                 return false;
  722.         }
  723.         return true;
  724. }
  725.  
  726. bool URobinAIBirdMovementComponent::IsLandingOnObject() const
  727. {
  728.         return CanLandOnObjects;
  729. }
  730.  
  731. void URobinAIBirdMovementComponent::SetStartingPosition( FVector const Position )
  732. {
  733.         check( GetOwner() );
  734.         FRotator NewRotation = FRotator( 000 );
  735.         NewRotation.Yaw = FMath::FRandRange( 0360 );
  736.         GetOwner()->SetActorLocationAndRotation( Position + GetFeetOffset(), NewRotation );
  737. }
  738.  
  739. FVector URobinAIBirdMovementComponent::GetRandomPointForFlying() const
  740. {
  741.         UBoxComponent* Box = Cast< UBoxComponent >( AirMovementBox->GetCollisionComponent() );
  742.         if( Box )
  743.         {
  744.                 return UKismetMathLibrary::RandomPointInBoundingBox( Box->GetComponentLocation(), Box->GetScaledBoxExtent() );
  745.         }
  746.  
  747.         return AirMovementBox->GetActorLocation();
  748. }
  749.  
  750. void URobinAIBirdMovementComponent::SetSpawnerLocation( FVector const SpawnLocation )
  751. {
  752.         SpawnerLocation = SpawnLocation;
  753. }
  754.  
  755. void URobinAIBirdMovementComponent::SetAirMovementBox( ATriggerBox* const Box )
  756. {
  757.         AirMovementBox = Box;
  758.         IsFlyingInBox = true;
  759. }
  760.  
  761. bool URobinAIBirdMovementComponent::IsPlayerLookingAtBird()
  762. {
  763.         check( UpdatedComponent );
  764.         ARobinPlayerCharacter* const Player = URobinCharacterStatics::GetMainPlayer( this );
  765.         if( Player )
  766.         {
  767.                 URobinPlayerViewControllerComponent const& ViewController = Player->GetViewController();
  768.                 if( !ViewController.IsPlayerFacingLocation( UpdatedComponent->GetComponentLocation() ) )
  769.                 {
  770.                         return false;
  771.                 }
  772.                 return true;
  773.         }
  774.         return false;
  775. }
  776.  
  777. void URobinAIBirdMovementComponent::UpdateActualMaxSpeed()
  778. {
  779.         if( IsAlerted )
  780.         {
  781.                 ActualMaxFlyingSpeed = BirdAlertedFlyMoveSpeed;
  782.         }
  783.         else
  784.         {
  785.                 ActualMaxFlyingSpeed = BirdRegularFlyMoveSpeed;
  786.         }
  787. }
  788.  
  789. void URobinAIBirdMovementComponent::UpdateFlyingSpeedOnSharpTurn( float const AngleToTarget, float const MaxAngleRegularTurn, float const DeltaTime )
  790. {
  791.         // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Missing variables, moved it to separate function for testing
  792.         if( FMath::Abs( AngleToTarget ) >= MaxAngleRegularTurn && ActualFlyingSpeed > 400 )
  793.         {
  794.                 ActualFlyingSpeed -= ( AirResistance + 200 ) * DeltaTime;
  795.                 // DrawDebugSphere(GetWorld(), NextPoint, 50, 10, FColor::Red, false, 20.f, 0, 1);
  796.         }
  797.  
  798.         if( ShouldGainSpeed )
  799.         {
  800.                 ActualFlyingSpeed += ( AirResistance + 120 ) * DeltaTime;
  801.                 if( ActualFlyingSpeed >= ActualMaxFlyingSpeed )
  802.                 {
  803.                         ShouldGainSpeed = false;
  804.                 }
  805.         }
  806.         else
  807.         {
  808.                 ActualFlyingSpeed -= AirResistance * DeltaTime;
  809.                 if( ActualFlyingSpeed <= 400 )
  810.                 {
  811.                         ShouldGainSpeed = true;
  812.                 }
  813.         }
  814. }
  815.  

Editor

You can edit this paste and save as new:


File Description
  • Bird
  • Paste Code
  • 21 Jan-2021
  • 29.14 Kb
You can Share it: