void CRateOfDeathSimple::UpdateTargetOffset( const float elapsedSeconds ) { // TODO: For now not doing anything fancy here with the silhouette of the target. // TODO: Smaller offsets when missing so that it's not over the top, and use a weapon that does no damage but looks the same... it looks a bit silly if it misses too much on purpose! if ( m_canDamageTarget ) { m_missOffsetNextUpdateSeconds = 0; m_hitOffsetNextUpdateSeconds -= elapsedSeconds; if ( m_hitOffsetNextUpdateSeconds <= 0 ) { const float minRange = min( m_hitMinRange, m_hitMaxRange ); const float maxRange = max( m_hitMinRange, m_hitMaxRange ); m_targetOffset = CalculateTargetOffset( minRange, maxRange ); m_hitOffsetNextUpdateSeconds = m_hitOffsetIntervalSeconds; } } else { m_hitOffsetNextUpdateSeconds = 0; m_missOffsetNextUpdateSeconds -= elapsedSeconds; if ( m_missOffsetNextUpdateSeconds <= 0 ) { const float minRange = min( m_missMinRange, m_missMaxRange ); const float maxRange = max( m_missMinRange, m_missMaxRange ); m_targetOffset = CalculateTargetOffset( minRange, maxRange ); m_missOffsetNextUpdateSeconds = m_missOffsetIntervalSeconds; } } }
bool UAbilityTask_ApplyRootMotionMoveToActorForce::UpdateTargetLocation(float DeltaTime) { if (TargetActor && GetWorld()) { const FVector PreviousTargetLocation = TargetLocation; FVector ExactTargetLocation = CalculateTargetOffset(); const float CurrentTime = GetWorld()->GetTimeSeconds(); const float CompletionPercent = (CurrentTime - StartTime) / Duration; const float TargetLerpSpeedHorizontal = TargetLerpSpeedHorizontalCurve ? TargetLerpSpeedHorizontalCurve->GetFloatValue(CompletionPercent) : 1000.f; const float TargetLerpSpeedVertical = TargetLerpSpeedVerticalCurve ? TargetLerpSpeedVerticalCurve->GetFloatValue(CompletionPercent) : 500.f; const float MaxHorizontalChange = FMath::Max(0.f, TargetLerpSpeedHorizontal * DeltaTime); const float MaxVerticalChange = FMath::Max(0.f, TargetLerpSpeedVertical * DeltaTime); FVector ToExactLocation = ExactTargetLocation - PreviousTargetLocation; FVector TargetLocationDelta = ToExactLocation; // Cap vertical lerp if (FMath::Abs(ToExactLocation.Z) > MaxVerticalChange) { if (ToExactLocation.Z >= 0.f) { TargetLocationDelta.Z = MaxVerticalChange; } else { TargetLocationDelta.Z = -MaxVerticalChange; } } // Cap horizontal lerp if (FMath::Abs(ToExactLocation.SizeSquared2D()) > MaxHorizontalChange*MaxHorizontalChange) { FVector ToExactLocationHorizontal(ToExactLocation.X, ToExactLocation.Y, 0.f); ToExactLocationHorizontal.Normalize(); ToExactLocationHorizontal *= MaxHorizontalChange; TargetLocationDelta.X = ToExactLocationHorizontal.X; TargetLocationDelta.Y = ToExactLocationHorizontal.Y; } TargetLocation += TargetLocationDelta; return true; } return false; }
void UAbilityTask_ApplyRootMotionMoveToActorForce::SharedInitAndApply() { if (AbilitySystemComponent->AbilityActorInfo->MovementComponent.IsValid()) { MovementComponent = Cast<UCharacterMovementComponent>(AbilitySystemComponent->AbilityActorInfo->MovementComponent.Get()); StartTime = GetWorld()->GetTimeSeconds(); EndTime = StartTime + Duration; if (MovementComponent) { if (bSetNewMovementMode) { PreviousMovementMode = MovementComponent->MovementMode; MovementComponent->SetMovementMode(NewMovementMode); } // Set initial target location if (TargetActor) { TargetLocation = CalculateTargetOffset(); } ForceName = ForceName.IsNone() ? FName("AbilityTaskApplyRootMotionMoveToActorForce") : ForceName; FRootMotionSource_MoveToDynamicForce* MoveToActorForce = new FRootMotionSource_MoveToDynamicForce(); MoveToActorForce->InstanceName = ForceName; MoveToActorForce->AccumulateMode = ERootMotionAccumulateMode::Override; MoveToActorForce->Settings.SetFlag(ERootMotionSourceSettingsFlags::UseSensitiveLiftoffCheck); MoveToActorForce->Priority = 900; MoveToActorForce->InitialTargetLocation = TargetLocation; MoveToActorForce->TargetLocation = TargetLocation; MoveToActorForce->StartLocation = StartLocation; MoveToActorForce->Duration = Duration; MoveToActorForce->bRestrictSpeedToExpected = bRestrictSpeedToExpected; MoveToActorForce->PathOffsetCurve = PathOffsetCurve; MoveToActorForce->TimeMappingCurve = TimeMappingCurve; RootMotionSourceID = MovementComponent->ApplyRootMotionSource(MoveToActorForce); if (Ability) { Ability->SetMovementSyncPoint(ForceName); } } } else { ABILITY_LOG(Warning, TEXT("UAbilityTask_ApplyRootMotionMoveToActorForce called in Ability %s with null MovementComponent; Task Instance Name %s."), Ability ? *Ability->GetName() : TEXT("NULL"), *InstanceName.ToString()); } }