void UProjectileMovementComponent::InitializeComponent()
{
	Super::InitializeComponent();

	if (Velocity.SizeSquared() > 0.f)
	{
		// InitialSpeed > 0 overrides initial velocity magnitude.
		if (InitialSpeed > 0.f)
		{
			Velocity = Velocity.GetSafeNormal() * InitialSpeed;
		}

		if (bInitialVelocityInLocalSpace)
		{
			SetVelocityInLocalSpace(Velocity);
		}

		if (bRotationFollowsVelocity)
		{
			if (UpdatedComponent)
			{
				UpdatedComponent->SetWorldRotation(Velocity.Rotation());
			}
		}

		UpdateComponentVelocity();
		
		if (UpdatedPrimitive && UpdatedPrimitive->IsSimulatingPhysics())
		{
			UpdatedPrimitive->SetPhysicsLinearVelocity(Velocity);
		}
	}
}
void UObstacleMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (!UpdatedComponent)
	{
		return;
	}

	AActor* ActorOwner = UpdatedComponent->GetOwner();
	if (!ActorOwner || ActorOwner->IsPendingKill())
	{
		return;
	}

	FVector CurrentLocation = UpdatedComponent->GetComponentLocation();
	FRotator CurrentRotation = UpdatedComponent->GetComponentRotation();

	if (MovingRight)
	{
		CurrentLocation.Y += MovementSpeed * DeltaTime;

		if (CurrentLocation.Y >= RightMovementTarget)
		{
			MovingRight = !MovingRight;
			CurrentLocation.Y = RightMovementTarget;
		}
	}
	else
	{
		CurrentLocation.Y -= MovementSpeed * DeltaTime;

		if (CurrentLocation.Y <= LeftMovementTarget)
		{
			MovingRight = !MovingRight;
			CurrentLocation.Y = LeftMovementTarget;
		}
	}

	FHitResult Hit(1.0f);
	MoveUpdatedComponent(CurrentLocation - UpdatedComponent->GetComponentLocation(), CurrentRotation, true, &Hit);

	// If we hit a trigger that destroyed us, abort.
	if (ActorOwner->IsPendingKill() || !UpdatedComponent)
	{
		return;
	}

	UpdateComponentVelocity();
}
void UFloatingPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
	{
		return;
	}

	const AController* Controller = PawnOwner->GetController();
	if (Controller && Controller->IsLocalController())
	{
		ApplyControlInputToVelocity(DeltaTime);
		LimitWorldBounds();
		bPositionCorrected = false;

		// Move actor
		FVector Delta = Velocity * DeltaTime;

		if (!Delta.IsNearlyZero(1e-6f))
		{
			const FVector OldLocation = UpdatedComponent->GetComponentLocation();
			const FRotator Rotation = UpdatedComponent->GetComponentRotation();
			FVector TraceStart = OldLocation;

			FHitResult Hit(1.f);
			SafeMoveUpdatedComponent(Delta, Rotation, true, Hit);

			if (Hit.IsValidBlockingHit())
			{
				HandleImpact(Hit, DeltaTime, Delta);
				// Try to slide the remaining distance along the surface.
				SlideAlongSurface(Delta, 1.f-Hit.Time, Hit.Normal, Hit, true);
			}

			// Update velocity
			// We don't want position changes to vastly reverse our direction (which can happen due to penetration fixups etc)
			if (!bPositionCorrected)
			{
				const FVector NewLocation = UpdatedComponent->GetComponentLocation();
				Velocity = ((NewLocation - OldLocation) / DeltaTime);
			}
		}
		
		// Finalize
		UpdateComponentVelocity();
	}
};
void UGridMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (Moving)
	{
		/* Find the next location */
		Distance = FMath::Min(Spline->GetSplineLength(), Distance + (MaxSpeed * DeltaTime));
		
		/* Grab our current transform so we can find the velocity if we need it later */
		AActor *Owner = GetOwner();
		FTransform OldTransform = Owner->GetTransform();

		/* Find the next loaction from the spline*/
		FTransform NewTransform = Spline->GetTransformAtDistanceAlongSpline(Distance, ESplineCoordinateSpace::Local);

		/* Restrain rotation axis */
		FRotator Rotation = NewTransform.Rotator();
		Rotation.Roll = LockRoll ? 0 : Rotation.Roll;
		Rotation.Pitch = LockPitch ? 0 : Rotation.Pitch; 
		Rotation.Yaw = LockYaw ? 0 : Rotation.Yaw;
		NewTransform.SetRotation(Rotation.Quaternion());

		Owner->SetActorTransform(NewTransform);

		/* Check if we're reached our destination*/
		if (Distance >= Spline->GetSplineLength())
		{
			Moving = false;
			Distance = 0;
			Velocity = FVector::ZeroVector;
			OnMovementEndEvent.Broadcast();
		}
		else
		{
			Velocity = (NewTransform.GetLocation() - OldTransform.GetLocation()) * (1 / DeltaTime);
		}

		// update velocity so it can be fetched by the pawn 
		UpdateComponentVelocity();
	}
}
void UProjectileMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	QUICK_SCOPE_CYCLE_COUNTER( STAT_ProjectileMovementComponent_TickComponent );

	// skip if don't want component updated when not rendered or updated component can't move
	if (HasStoppedSimulation() || ShouldSkipUpdate(DeltaTime))
	{
		return;
	}

	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	AActor* ActorOwner = UpdatedComponent->GetOwner();
	if ( !ActorOwner || !CheckStillInWorld() )
	{
		return;
	}

	if (UpdatedComponent->IsSimulatingPhysics())
	{
		return;
	}

	float RemainingTime	= DeltaTime;
	uint32 NumBounces = 0;
	int32 Iterations = 0;
	FHitResult Hit(1.f);
	
	while( RemainingTime >= MIN_TICK_TIME && (Iterations < MaxSimulationIterations) && !ActorOwner->IsPendingKill() && !HasStoppedSimulation() )
	{
		Iterations++;

		// subdivide long ticks to more closely follow parabolic trajectory
		const float TimeTick = ShouldUseSubStepping() ? GetSimulationTimeStep(RemainingTime, Iterations) : RemainingTime;
		RemainingTime -= TimeTick;

		Hit.Time = 1.f;
		const FVector OldVelocity = Velocity;
		const FVector MoveDelta = ComputeMoveDelta(OldVelocity, TimeTick);

		const FRotator NewRotation = (bRotationFollowsVelocity && !OldVelocity.IsNearlyZero(0.01f)) ? OldVelocity.Rotation() : ActorOwner->GetActorRotation();

		// Move the component
		if (bShouldBounce)
		{
			// If we can bounce, we are allowed to move out of penetrations, so use SafeMoveUpdatedComponent which does that automatically.
			SafeMoveUpdatedComponent( MoveDelta, NewRotation, true, Hit );
		}
		else
		{
			// If we can't bounce, then we shouldn't adjust if initially penetrating, because that should be a blocking hit that causes a hit event and stop simulation.
			TGuardValue<EMoveComponentFlags> ScopedFlagRestore(MoveComponentFlags, MoveComponentFlags | MOVECOMP_NeverIgnoreBlockingOverlaps);
			MoveUpdatedComponent(MoveDelta, NewRotation, true, &Hit );
		}
		
		// If we hit a trigger that destroyed us, abort.
		if( ActorOwner->IsPendingKill() || HasStoppedSimulation() )
		{
			return;
		}

		// Handle hit result after movement
		if( !Hit.bBlockingHit )
		{
			PreviousHitTime = 1.f;
			bIsSliding = false;

			// Only calculate new velocity if events didn't change it during the movement update.
			if (Velocity == OldVelocity)
			{
				Velocity = ComputeVelocity(Velocity, TimeTick);				
			}
		}
		else
		{
			// Only calculate new velocity if events didn't change it during the movement update.
			if (Velocity == OldVelocity)
			{
				// re-calculate end velocity for partial time
				Velocity = (Hit.Time > KINDA_SMALL_NUMBER) ? ComputeVelocity(OldVelocity, TimeTick * Hit.Time) : OldVelocity;
			}

			// Handle blocking hit
			float SubTickTimeRemaining = TimeTick * (1.f - Hit.Time);
			const EHandleBlockingHitResult HandleBlockingResult = HandleBlockingHit(Hit, TimeTick, MoveDelta, SubTickTimeRemaining);
			if (HandleBlockingResult == EHandleBlockingHitResult::Abort || HasStoppedSimulation())
			{
				break;
			}
			else if (HandleBlockingResult == EHandleBlockingHitResult::Deflect)
			{
				NumBounces++;
				HandleDeflection(Hit, OldVelocity, NumBounces, SubTickTimeRemaining);
				PreviousHitTime = Hit.Time;
				PreviousHitNormal = ConstrainNormalToPlane(Hit.Normal);
			}
			else if (HandleBlockingResult == EHandleBlockingHitResult::AdvanceNextSubstep)
			{
				// Reset deflection logic to ignore this hit
				PreviousHitTime = 1.f;
			}
			else
			{
				// Unhandled EHandleBlockingHitResult
				checkNoEntry();
			}
			
			
			// A few initial bounces should add more time and iterations to complete most of the simulation.
			if (NumBounces <= 2 && SubTickTimeRemaining >= MIN_TICK_TIME)
			{
				RemainingTime += SubTickTimeRemaining;
				Iterations--;
			}
		}
	}

	UpdateComponentVelocity();
}
void UInterpToMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_InterpToMovementComponent_TickComponent);
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// skip if don't want component updated when not rendered or updated component can't move
	if (!UpdatedComponent || ShouldSkipUpdate(DeltaTime))
	{
		return;
	}
	AActor* ActorOwner = UpdatedComponent->GetOwner();
	if (!ActorOwner || !CheckStillInWorld())
	{
		return;
	}

	if (UpdatedComponent->IsSimulatingPhysics())
	{
		return;
	}
	if((bStopped == true ) || ( ActorOwner->IsPendingKill() ) )
	{
		return;
	}
	if( ControlPoints.Num()== 0 ) 
	{
		return;
	}

	// This will update any control points coordinates that are linked to actors.
	UpdateControlPoints(false);

	float RemainingTime = DeltaTime;
	int32 NumBounces = 0;
	int32 Iterations = 0;
	FHitResult Hit(1.f);

	FVector WaitPos = FVector::ZeroVector;
	if (bIsWaiting == true)
	{
		WaitPos = UpdatedComponent->GetComponentLocation();
	}
	while (RemainingTime >= MIN_TICK_TIME && (Iterations < MaxSimulationIterations) && !ActorOwner->IsPendingKill() && UpdatedComponent)
	{
		Iterations++;

		const float TimeTick = ShouldUseSubStepping() ? GetSimulationTimeStep(RemainingTime, Iterations) : RemainingTime;
		RemainingTime -= TimeTick;

		// Calculate the current time with this tick iteration
		float Time = FMath::Clamp(CurrentTime + ((DeltaTime*TimeMultiplier)*CurrentDirection),0.0f,1.0f);		
		FVector MoveDelta = ComputeMoveDelta(Time);
		
		// Update the rotation on the spline if required
		FRotator CurrentRotation = UpdatedComponent->GetComponentRotation();				
		
		// Move the component
 		if ((bPauseOnImpact == false ) && (BehaviourType != EInterpToBehaviourType::OneShot))
 		{
 			// If we can bounce, we are allowed to move out of penetrations, so use SafeMoveUpdatedComponent which does that automatically.
 			SafeMoveUpdatedComponent(MoveDelta, CurrentRotation, true, Hit);
 		}
 		else
		{
			// If we can't bounce, then we shouldn't adjust if initially penetrating, because that should be a blocking hit that causes a hit event and stop simulation.
			TGuardValue<EMoveComponentFlags> ScopedFlagRestore(MoveComponentFlags, MoveComponentFlags | MOVECOMP_NeverIgnoreBlockingOverlaps);
			MoveUpdatedComponent(MoveDelta, CurrentRotation, true, &Hit);
		}
		//DrawDebugPoint(GetWorld(), UpdatedComponent->GetComponentLocation(), 16, FColor::White,true,5.0f);
		// If we hit a trigger that destroyed us, abort.
		if (ActorOwner->IsPendingKill() || !UpdatedComponent)
		{
			return;
		}

		// Handle hit result after movement
		if (!Hit.bBlockingHit)
		{
			// If we were 'waiting' were not any more - broadcast we are off again
			if( bIsWaiting == true )
			{
				OnWaitEndDelegate.Broadcast(Hit, Time);
				bIsWaiting = false;
			}
			else
			{				
				CalculateNewTime(CurrentTime, TimeTick, Hit, true, bStopped);
				if (bStopped == true)
				{
					return;
				}
			}
		}
		else
		{
			if (HandleHitWall(Hit, TimeTick, MoveDelta))
			{
				break;
			}

			NumBounces++;
			float SubTickTimeRemaining = TimeTick * (1.f - Hit.Time);
			
			// A few initial bounces should add more time and iterations to complete most of the simulation.
			if (NumBounces <= 2 && SubTickTimeRemaining >= MIN_TICK_TIME)
			{
				RemainingTime += SubTickTimeRemaining;
				Iterations--;
			}
		}
	}
	if( bIsWaiting == false )
	{		
		FHitResult DummyHit;
		CurrentTime = CalculateNewTime(CurrentTime, DeltaTime, DummyHit, false, bStopped);		
	}
	UpdateComponentVelocity();
}