// Called every frame
void AMovingPlatform::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	FVector currentPos = movingObject->GetComponentLocation();
	if (pauseTimer > 0.0f)
	{
		pauseTimer -= DeltaTime;
	}
	else
	{
		t = smoothInterpolate->UpdatePosition(currentPos, DeltaTime);
	}

	// update lerp t
	if (t > 1.0f)
	{
		pauseTimer = pauseTime;
		t = 0.0f;
		delete smoothInterpolate;
		if (direction)
		{
			direction = false;
			smoothInterpolate = new SmoothInterpolate(startPos, sloopDist, distToTarget, moveSpeed, sloopPower, sloopMult, 0.0f);
		}
		else
		{
			direction = true;
			smoothInterpolate = new SmoothInterpolate(targetPos->GetComponentLocation(), sloopDist, distToTarget, moveSpeed, sloopPower, sloopMult, 0.0f);
		}
	}

	// calculate movment
	if (direction)
	{
		newPos = MathUtil::Lerp(targetPos->GetComponentLocation(), startPos, t);
	}
	else
	{
		newPos = MathUtil::Lerp(startPos, targetPos->GetComponentLocation(), t);
	}
	time += DeltaTime;
	// move
	FHitResult* moveHitResult = new FHitResult();
	ETeleportType teleType = teleportType ? ETeleportType::TeleportPhysics : ETeleportType::None;
	movingObject->AddWorldOffset(newPos - movingObject->GetComponentLocation(), bSweep, moveHitResult, teleType);
	if (bSweep && !moveHitResult->IsValidBlockingHit())
	{
		movingObject->AddWorldOffset(newPos - movingObject->GetComponentLocation(), false, moveHitResult, teleType);
	}
	else
	{
		smoothInterpolate->SetOldInterpolation();
	}
	//UE_LOG(LogTemp, Warning, TEXT("ReceiveHit - IsValidBlockingHit: %d - time: %d"), moveHitResult->IsValidBlockingHit() , time);

	delete moveHitResult;
}
float UMovementComponent::SlideAlongSurface(const FVector& Delta, float Time, const FVector& Normal, FHitResult& Hit, bool bHandleImpact)
{
	if (!Hit.bBlockingHit)
	{
		return 0.f;
	}

	float PercentTimeApplied = 0.f;
	const FVector OldHitNormal = Normal;

	FVector SlideDelta = ComputeSlideVector(Delta, Time, Normal, Hit);

	if ((SlideDelta | Delta) > 0.f)
	{
		const FQuat Rotation = UpdatedComponent->GetComponentQuat();
		SafeMoveUpdatedComponent(SlideDelta, Rotation, true, Hit);

		const float FirstHitPercent = Hit.Time;
		PercentTimeApplied = FirstHitPercent;
		if (Hit.IsValidBlockingHit())
		{
			// Notify first impact
			if (bHandleImpact)
			{
				HandleImpact(Hit, FirstHitPercent * Time, SlideDelta);
			}

			// Compute new slide normal when hitting multiple surfaces.
			TwoWallAdjust(SlideDelta, Hit, OldHitNormal);

			// Only proceed if the new direction is of significant length and not in reverse of original attempted move.
			if (!SlideDelta.IsNearlyZero(1e-3f) && (SlideDelta | Delta) > 0.f)
			{
				// Perform second move
				SafeMoveUpdatedComponent(SlideDelta, Rotation, true, Hit);
				const float SecondHitPercent = Hit.Time * (1.f - FirstHitPercent);
				PercentTimeApplied += SecondHitPercent;

				// Notify second impact
				if (bHandleImpact && Hit.bBlockingHit)
				{
					HandleImpact(Hit, SecondHitPercent * Time, SlideDelta);
				}
			}
		}

		return FMath::Clamp(PercentTimeApplied, 0.f, 1.f);
	}

	return 0.f;
}
bool ATankPlayerController::GetSightRayHitLocation(FVector& HitLocation) const
{
	FVector2D CrosshairLocation;
	GetCrosshairScreenLocation(CrosshairLocation);
	
	FVector WorldLocation;
	FVector WorldDirection;

	if (DeprojectScreenPositionToWorld(CrosshairLocation.X, CrosshairLocation.Y, WorldLocation, WorldDirection)) {
		//UE_LOG(LogTemp, Warning, TEXT("World location: %s World direction: %s"), *WorldLocation.ToString(), *WorldDirection.ToString());
	}
	
	TArray<FHitResult> HitResults = TArray<FHitResult>();
	
	if (LineTrace(WorldLocation, WorldDirection, HitResults)) {
		bool aimingThroughPlayer = false;
		for (int i = 0; i < HitResults.Num(); i++) {
			FHitResult HitResult = HitResults[i];
			if (HitResult.IsValidBlockingHit()) {
				if (HitResult.GetActor() != GetControlledTank()) {
					if (aimingThroughPlayer)
					{
						UE_LOG(LogTemp, Warning, TEXT("Aiming through player tank actor, next hit is: %s"), *HitResult.ImpactPoint.ToString());
					}

					HitLocation = HitResult.ImpactPoint;
					return true;
				}else
				{
					aimingThroughPlayer = true;
					UE_LOG(LogTemp, Warning, TEXT("%i hits, aiming through player tank actor: %s"),HitResults.Num(), *HitResult.ImpactPoint.ToString());
				}
			}
			else
			{
				HitLocation = FVector(0);
				return false;
			}
		}
		
	}

	return false;
}
Beispiel #4
0
/*Method called when wanting to place an object previously picked up back in the world.
After making sure that the call is valid and calculating the new location for the object,
all properties modified for manipulation purposes need to be reset to default.
@param AActor* CurrentObject  -->  Object currently manipulated and needing to be placed
@param FHitResult HitSurface  -->  Surface on which the object needs to be placed*/
void AMyCharacter::DropFromInventory(AActor* CurrentObject, FHitResult HitSurface)
{
	if (!HitSurface.IsValidBlockingHit())
	{          
		PopUp.Broadcast(FString(TEXT("Action not valid!")));
		return;
	}
	if (HitSurface.Distance > MaxGraspLength)
	{
		PopUp.Broadcast(FString(TEXT("You need to get closer!")));
		return;
	}

	//Case in which we are holding a stack
	if (TwoHandSlot.Num())
	{
		bool bFirstLoop = true;
		FVector WorldPositionChange = FVector(0.f, 0.f, 0.f);

		for (auto Iterator : TwoHandSlot)
		{
			GetStaticMesh(Iterator)->SetEnableGravity(true);
			GetStaticMesh(Iterator)->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);

			if (!bFirstLoop)
			{
				GetStaticMesh(Iterator)->SetWorldLocation(Iterator->GetActorLocation() - WorldPositionChange);
			}

			else
			{
				WorldPositionChange = Iterator->GetActorLocation();
				PlaceOnTop(Iterator, HitSurface);
				WorldPositionChange = WorldPositionChange - Iterator->GetActorLocation();
				bFirstLoop = false;
			}
		}
		TwoHandSlot.Empty();
		GetStaticMesh(SelectedObject)->SetCustomDepthStencilValue(1);
		GetStaticMesh(SelectedObject)->SetRenderCustomDepth(false);
		SelectedObject = nullptr;
		return;
	}

	PlaceOnTop(CurrentObject, HitSurface);
	
	//Reset ignored parameters
	TraceParams.ClearIgnoredComponents();

	//Remove the reference to the object because we are not holding it any more
	if (bRightHandSelected)
	{
		RightHandSlot = nullptr;

		//Reset the positioning vector back to default state
		RightZPos = 30.f;
		RightYPos = 20;

		//Add item in left hand back to ignored actor by line trace
		if (LeftHandSlot)
		{
			TraceParams.AddIgnoredComponent(GetStaticMesh(LeftHandSlot));
		}
	}
	else
	{
		LeftHandSlot = nullptr;
		//Reset the positioning vector back to default state
		LeftZPos = 30.f;
		LeftYPos = 20;

		//Add item in right hand back to ignored actor by line trace
		if (RightHandSlot)
		{
			TraceParams.AddIgnoredComponent(GetStaticMesh(RightHandSlot));
		}
	}

	//Reset outline color to blue
	GetStaticMesh(SelectedObject)->SetCustomDepthStencilValue(1);
	//Remove the reference because we just dropped the item that was selected
	SelectedObject = nullptr;
}
void UShardsMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	FHitResult HitResult;
	FHitResult ShapeTraceResult;
	FCollisionShape shape = FCollisionShape::MakeBox(FVector(0.72f*playerradius, 0.72f*playerradius,10.0f));

	FCollisionQueryParams Params;
	Params.bFindInitialOverlaps = true;
	Params.AddIgnoredActor(UpdatedComponent->GetAttachmentRootActor());

	// Telepads don't count.
	for (TActorIterator<ATelePad> ActorItr(GetWorld()); ActorItr; ++ActorItr) {
		Params.AddIgnoredActor(ActorItr.operator->());
	}

	// Neither do destructibles.
	for (TActorIterator<ADestructibleBox> ActorItr(GetWorld()); ActorItr; ++ActorItr) {
		// When they're broken, that is.
		if (ActorItr->fadetimer >= 0.0f) {
			Params.AddIgnoredActor(ActorItr.operator->());
		}
	}

	if (isclimbing) {
		return;
	}

	TArray<FHitResult> results;
	if (forceregiondirection.Z == 0.0f) {
		GetWorld()->SweepMultiByChannel(results, UpdatedComponent->GetComponentLocation() - 0.0f*45.0f*FVector::UpVector, UpdatedComponent->GetComponentLocation() - 1000.0f*FVector::UpVector, FQuat::Identity, ECC_Visibility, shape, Params); //100
		for (FHitResult r : results) {
			if (r.Normal.Z > 0.6f) {
				ShapeTraceResult = r;
				break;
			}
		}
		if (!ShapeTraceResult.IsValidBlockingHit()) {
			GetWorld()->LineTraceSingleByChannel(ShapeTraceResult, UpdatedComponent->GetComponentLocation(), UpdatedComponent->GetComponentLocation() - 1000.0f*FVector::UpVector, ECC_Visibility, Params);
		}
	}

	FVector PlayerCapsuleBottom = UpdatedComponent->GetComponentLocation() - 45.0f * FVector::UpVector; // 50
	float RequiredDistance = (onground ? 50.0f*grounddetecttfudgefactor : 10.0f)*FMath::Pow(playerhalfheight / 90.0f,4.0f) + playerhalfheight/2.0f; //50,1
	DistanceFromImpact = (PlayerCapsuleBottom - ShapeTraceResult.ImpactPoint).Z;
	overground = ShapeTraceResult.IsValidBlockingHit();

	FHitResult groundhitresult;
	GetWorld()->LineTraceSingleByChannel(groundhitresult, UpdatedComponent->GetComponentLocation(), UpdatedComponent->GetComponentLocation() - 10000.0f*FVector::UpVector, ECC_Visibility, Params);
	groundtracehit = groundhitresult.ImpactPoint;

	if (!onground) {
		offGroundTime += DeltaTime;
	}

	toosteep = false;
	if (enforcementtimer >= 0.0f) {
		enforcementtimer += DeltaTime;
		toosteep = true;
	}
	wasonground = onground;
	onground = false;
	prevgroundvelocity = groundvelocity;
	groundvelocity = FVector::ZeroVector;
	platformangularfrequency = 0.0f;
	platformspindir = 1;
	FloorNormal = FVector::ZeroVector;

	if ((enforcementtimer < timerlimit && ShapeTraceResult.Normal.Z>0.6f) && DistanceFromImpact < RequiredDistance && !justjumped) { // (PlayerVelocity.Z <= 0.0f || wasonground)
		if (ShapeTraceResult.Normal.Z < minnormalz) {
			if (enforcementtimer == -1.0f) {
				enforcementtimer = 0.0f;
			}
		} else {
			enforcementtimer = -1.0f;
		}

		FVector pvel;
		// Handle moving platforms.
		if (ShapeTraceResult.GetActor() != nullptr && ShapeTraceResult.GetComponent() != nullptr && ShapeTraceResult.GetComponent()->IsA(UStaticMeshComponent::StaticClass())) {
			
			// The motion of a point on a rigid body is the combination of its motion about the center of mass...
			FVector angvel = FMath::DegreesToRadians((((UStaticMeshComponent*)ShapeTraceResult.GetComponent())->GetPhysicsAngularVelocity()));
			FVector rr = GetActorLocation() - (((UStaticMeshComponent*)ShapeTraceResult.GetComponent())->GetComponentLocation());
			FVector rvel = FVector::CrossProduct(angvel, rr);

			// ...and the motion of the center of mass itself.
			FVector cmvel = (((UStaticMeshComponent*)ShapeTraceResult.GetComponent())->GetPhysicsLinearVelocity());
			
			groundvelocity = rvel + cmvel;
			platformangularfrequency = -angvel.Z;
		}

		if ((PlayerVelocity.Z <= groundvelocity.Z || wasonground)) {
			onground = true;
			offGroundTime = 0.0f;
		}
	}

	justjumped = false;

	bool TraceBlocked;
	FVector newlocation = UpdatedComponent->GetComponentLocation();

	FHitResult TraceHitResult;
	TraceBlocked = GetWorld()->LineTraceSingleByChannel(TraceHitResult, ShapeTraceResult.ImpactPoint + 1.0f*FVector::UpVector, ShapeTraceResult.ImpactPoint - 10.0f*FVector::UpVector, ECC_Visibility,Params);
	if (TraceHitResult.Normal.Z > minnormalz) {
		enforcementtimer = -1.0f;
	}

	if (onground) {

		if (TraceBlocked) {
			newlocation.Z = TraceHitResult.ImpactPoint.Z + playerhalfheight; // 50
			GetWorld()->LineTraceSingleByChannel(TraceHitResult, ShapeTraceResult.ImpactPoint + 1.0f*FVector::UpVector, ShapeTraceResult.ImpactPoint - 10.0f*FVector::UpVector, ECC_Visibility,Params);
			FloorNormal = TraceHitResult.ImpactNormal;
		}

		SafeMoveUpdatedComponent(newlocation - UpdatedComponent->GetComponentLocation(), UpdatedComponent->GetComponentRotation(), true, HitResult);
		SlideAlongSurface(newlocation - UpdatedComponent->GetComponentLocation(), 1.0 - HitResult.Time, HitResult.Normal, HitResult);
	}
};