// 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; }
/*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); } };