From abcd8acc6f94ed9e0354a7b6b5cfd980e14d0389 Mon Sep 17 00:00:00 2001 From: NeonDmn Date: Sun, 1 Jun 2025 17:55:38 +0200 Subject: [PATCH] feat: Working cover and camera system --- Config/DefaultEngine.ini | 3 +- .../Player/BP_ExoPlayerCharacter.uasset | Bin 99746 -> 100360 bytes Content/Levels/TestMap.umap | Bin 60122 -> 60122 bytes .../Private/Characters/ExoPlayerCharacter.cpp | 31 ++--- .../Private/Player/ExoPlayerController.cpp | 125 ++---------------- .../Public/Characters/ExoPlayerCharacter.h | 38 ++++-- .../Exo/Public/Player/ExoPlayerController.h | 27 +--- 7 files changed, 56 insertions(+), 168 deletions(-) diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 09ddd8d..3ef1e4d 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -73,4 +73,5 @@ GlobalDefaultServerGameMode=None +PropertyRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.CoverEyeHeight",NewName="/Script/Exo.ExoPlayerCharacter.LowEyeHeight") +FunctionRedirects=(OldName="/Script/Exo.ExoPlayerController.CalculateCoverAim",NewName="/Script/Exo.ExoPlayerController.CalculateCoverAimOffset") +PropertyRedirects=(OldName="/Script/Exo.ExoPlayerController.UseEyeHeight",NewName="/Script/Exo.ExoPlayerController.bUseEyeHeight") -+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.SetEyePositionOffset",NewName="/Script/Exo.ExoPlayerCharacter.SetEyePositionOffsetTarget") \ No newline at end of file ++FunctionRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.SetEyePositionOffset",NewName="/Script/Exo.ExoPlayerCharacter.SetEyePositionOffsetTarget") ++FunctionRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.UnCrouchCustom",NewName="/Script/Exo.ExoPlayerCharacter.TryUnCrouchCustom") \ No newline at end of file diff --git a/Content/Blueprints/Characters/Player/BP_ExoPlayerCharacter.uasset b/Content/Blueprints/Characters/Player/BP_ExoPlayerCharacter.uasset index 35df021b6fda851ac7b1017e71e8342ad82cf053..45020c5a7af2c947897b5df3fe74df3a3758e617 100644 GIT binary patch delta 9950 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 MlM1E^vp&R}CMYs4f&c&j delta 106 zcmV-w0G0pR)dSkq1F*IM5D>yPz@3UCO0C`XosV6a3A4rlhGzycE-*1JFtbu=Oj;RB zo4)PmTvSetRelativeLocation(FVector(0.0f, 0.0f, FromFeet(TargetEyeHeight))); GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AExoPlayerCharacter::OnActorBeginOverlap); - //UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->SetViewTarget(this); PlayerHud = CreateWidget(GetWorld(),PlayerHudClass); @@ -83,12 +82,6 @@ void AExoPlayerCharacter::BeginPlay() void AExoPlayerCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); - - //// NOT FINAL SOLUTION /// - /** Reset camera offset at the start of every frame */ - //TargetEyeLocationOffset = FVector::ZeroVector; - //TargetEyeRoll = 0.f; - ////////////////////////// UpdateCameraHeight(DeltaTime); ApplyCameraOffsets(DeltaTime); @@ -115,11 +108,6 @@ void AExoPlayerCharacter::UpdateCameraHeight(float DeltaTime) void AExoPlayerCharacter::ApplyCameraOffsets(float DeltaTime) { bool HasChanged = false; - //FVector NewOffset = EyeLocationOffset; - //FVector NoOffsetCameraPosition = FVector(0, 0, EyeHeight); - //FVector NoOffsetCameraPosition = CameraComponent->GetRelativeLocation() - EyeLocationOffset; - //UE_LOG(LogTemp, Log, TEXT("%s"), *NoOffsetCameraPosition.ToString()); - if (!FVector::PointsAreNear(EyeLocationOffset, TargetEyeLocationOffset, 0.01f)) { // Smoothly offset view @@ -141,15 +129,10 @@ void AExoPlayerCharacter::ApplyCameraOffsets(float DeltaTime) } // Update actual camera position - //FVector BaseLocation = FVector(0, 0, GetCurrentEyeHeightBase(true)); - //CameraComponent->SetRelativeLocation(NoOffsetCameraPosition + NewOffset); - //FVector CapsuleRelativeOffset = BaseLocation + EyeLocationOffset; - //CapsuleRelativeOffset.Z += GetCurrentEyeHeightBase(true); const FVector FinalOffset = FVector(EyeLocationOffset.X, EyeLocationOffset.Y, EyeLocationOffset.Z + TargetEyeHeight + GetFootOffset()); CameraComponent->SetRelativeLocation(FinalOffset); - - //UE_LOG(LogTemp, Log, TEXT("Camera relative: %s"), *CameraComponent->GetRelativeLocation().ToString()); + // Update actual camera rotation (Roll) FRotator NewRotator = GetController()->GetControlRotation(); NewRotator.Roll = EyeRoll; @@ -192,21 +175,22 @@ void AExoPlayerCharacter::CrouchCustom() { SetTargetEyeHeight(CrouchedEyeHeight); GetCharacterMovement()->MaxWalkSpeed = CrouchSpeed; + bIsCrouched = true; float CurrentCamHeight = GetCurrentEyeHeight(); - GetCapsuleComponent()->SetCapsuleHalfHeight(44.f); + GetCapsuleComponent()->SetCapsuleHalfHeight(GetCharacterMovement()->CrouchedHalfHeight); CameraComponent->SetRelativeLocation( FVector(0, 0, GetFootOffset()) + FVector(0, 0, CurrentCamHeight)); } -void AExoPlayerCharacter::UnCrouchCustom() +void AExoPlayerCharacter::TryUnCrouchCustom() { SetTargetEyeHeight(StandingEyeHeight); GetCharacterMovement()->MaxWalkSpeed = WalkSpeed; float CurrentCamHeight = GetCurrentEyeHeight(); - GetCapsuleComponent()->SetCapsuleHalfHeight(88.f); + GetCapsuleComponent()->SetCapsuleHalfHeight(StandingHalfHeight); CameraComponent->SetRelativeLocation( FVector(0, 0, GetFootOffset()) + FVector(0, 0, CurrentCamHeight)); @@ -255,6 +239,11 @@ float AExoPlayerCharacter::GetCrouchingEyeHeight(const bool bCapsuleRelative) co : CrouchedEyeHeight; } +bool AExoPlayerCharacter::IsCrouching() const +{ + return bIsCrouched; +} + void AExoPlayerCharacter::SetEyePositionOffsetTarget(const FVector LocationOffset) { diff --git a/Source/Exo/Private/Player/ExoPlayerController.cpp b/Source/Exo/Private/Player/ExoPlayerController.cpp index f064663..a036ab8 100644 --- a/Source/Exo/Private/Player/ExoPlayerController.cpp +++ b/Source/Exo/Private/Player/ExoPlayerController.cpp @@ -36,27 +36,17 @@ void AExoPlayerController::BeginPlay() PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed; } -void AExoPlayerController::PlayerTick(float DeltaTime) +void AExoPlayerController::PlayerTick(const float DeltaTime) { Super::PlayerTick(DeltaTime); + bIsCoverAiming = (PlayerCharacter->bIsInCover && PlayerCharacter->bIsAimingMode); - if (PlayerCharacter->bIsInCover) + if (bIsCoverAiming) { - //PlayerCharacter->SetEyePositionOffsetTarget( - // FVector(0, 0, PlayerCharacter->LowEyeHeightOffset) - // ); - if (PlayerCharacter->bIsAimingMode) - { - CoverAimHeightOffset = CalculateCoverAimOffset(); - PlayerCharacter->SetEyePositionOffsetTarget( - FVector(0.f, 0.f, CoverAimHeightOffset)); - } + CoverAimHeightOffset = CalculateCoverAimOffset(); + PlayerCharacter->SetEyePositionOffsetTarget(FVector(0.f, 0.f, CoverAimHeightOffset)); } - //else - //{ - // PlayerCharacter->SetEyePositionOffsetTarget(FVector::ZeroVector); - //} // On screen cover state DEBUG if (bShowCoverSystemDebug) @@ -167,15 +157,8 @@ void AExoPlayerController::PlayerStartCrouch() PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->LowEyeHeightOffset); GetWorldTimerManager().SetTimer(SlideCooldownTimer, this, &AExoPlayerController::ResetSlide, PlayerCharacter->SlideCooldown, false); } - - //PlayerCharacter->Crouch(); + PlayerCharacter->CrouchCustom(); - //PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->CrouchedEyeHeight); - // PlayerCharacter->CameraComponent->SetRelativeLocation(FVector( - // 0.0f, - // 0.0f, - // PlayerCharacter->CrouchedEyeHeight) - // ); // Start checking for cover PlayerCharacter->bIsInCover = CheckForCover(); @@ -190,19 +173,11 @@ void AExoPlayerController::PlayerStartCrouch() void AExoPlayerController::PlayerStopCrouch() { - //PlayerCharacter->UnCrouch(); - PlayerCharacter->UnCrouchCustom(); - //PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->GetStandingEyeHeight()); - // PlayerCharacter->CameraComponent->SetRelativeLocation(FVector( - // 0.0f, - // 0.0f, - // PlayerCharacter->BaseEyeHeight) - // ); + PlayerCharacter->TryUnCrouchCustom(); // Stop checking for cover GetWorld()->GetTimerManager().ClearTimer(CoverCheckTimer); PlayerCharacter->bIsInCover = false; - TargetCoverStandAlpha = 0.0f; } void AExoPlayerController::ResetSlide() @@ -253,7 +228,7 @@ void AExoPlayerController::PlayerStopAim() ShootingComponent->StopAiming(); if (PlayerCharacter->bIsInCover) { - CalculateCoverAimOffset(); + PlayerCharacter->SetEyePositionOffsetTarget(FVector(0, 0, 0)); } } @@ -289,9 +264,6 @@ void AExoPlayerController::PlayerReload() bool AExoPlayerController::CheckForCover() { - // Cover is recalculated every time the player crouches or stops moving while crouched - // Cover targets are cleared completely when player stands up again or dies - // Do a simple 8-directional line trace FVector TraceDirection = PlayerCharacter->GetActorForwardVector(); FVector TraceStart = PlayerCharacter->GetActorLocation(); @@ -372,16 +344,6 @@ float AExoPlayerController::CalculateCoverAimOffset() // Oblicz maksymalną wysokość, na którą można wychylić się znad osłony MaxCoverAimHeight = PlayerCharacter->GetStandingEyeHeight() * CoverAimStandFactor; - - FVector ObstacleTraceStart = GetCharacter()->GetActorLocation(); - ObstacleTraceStart.Z += - bUseEyeHeight ? - PlayerCharacter->GetCurrentEyeHeight(true) - : - PlayerCharacter->CrouchedEyeHeight - GetCharacter()->GetCapsuleComponent()->GetScaledCapsuleHalfHeight(); - - FVector ObstacleTraceEnd = - ObstacleTraceStart + PlayerCameraManager->GetCameraRotation().Vector() * CoverAimFreeDistance; FCollisionQueryParams QueryParams; QueryParams.AddIgnoredActor(PlayerCharacter); @@ -390,40 +352,9 @@ float AExoPlayerController::CalculateCoverAimOffset() FHitResult Hit; bool bFreeSpace = false; - // SphereTrace until no hit is found (free space to aim) - // for (int i = 0; i < MaxCoverAimHeight; i += CoverAimWindowRadius) - // { - // ObstacleTraceStart.Z += i; - // ObstacleTraceEnd.Z += i; - // - // GetWorld()->SweepSingleByChannel( - // Hit, - // ObstacleTraceStart, - // ObstacleTraceEnd, - // FQuat::Identity, - // ObstacleTraceChannel, - // FCollisionShape::MakeSphere(CoverAimWindowRadius), - // QueryParams - // ); - // - // if (bShowCoverSystemDebug) - // { - // DrawDebugSphere(GetWorld(), Hit.Location, CoverAimWindowRadius, 8, - // Hit.bBlockingHit ? FColor::Blue : FColor::Red, - // false, 0.0f, 0, 0); - // } - // - // if (Hit.bBlockingHit == false) - // { - // UE_LOG(LogTemp, Display, TEXT("Free space")); - // bFreeSpace = true; - // break; - // } - // } - - ObstacleTraceStart = PlayerCharacter->GetPlayerLocationAtFeet(); + FVector ObstacleTraceStart = PlayerCharacter->GetPlayerLocationAtFeet(); ObstacleTraceStart.Z += PlayerCharacter->CrouchedEyeHeight; - ObstacleTraceEnd = ObstacleTraceStart + PlayerCameraManager->GetCameraRotation().Vector() * CoverAimFreeDistance; + FVector ObstacleTraceEnd = ObstacleTraceStart + PlayerCameraManager->GetCameraRotation().Vector() * CoverAimFreeDistance; float SafeCoverAimZOffset = 0.f; while (SafeCoverAimZOffset < MaxCoverAimHeight) @@ -457,6 +388,7 @@ float AExoPlayerController::CalculateCoverAimOffset() // If this is true that means that free space was found if (FinalHitHeight <= MaxCoverAimHeight) { + PlayerCharacter->bIsCrouched = false; //// DEBUG //// if (bShowCoverSystemDebug) { @@ -469,44 +401,13 @@ float AExoPlayerController::CalculateCoverAimOffset() } // Return 0 offset if no free space to aim was found - return 0.f; -} - -void AExoPlayerController::UpdateSmoothCoverCamera(float DeltaTime) -{ - if (FMath::IsNearlyEqual(CoverStandAlpha, TargetCoverStandAlpha, 0.01f)) - { - return; - } - - CoverStandAlpha = FMath::Lerp(CoverStandAlpha, TargetCoverStandAlpha, DeltaTime * 5.0f); - - // BANDAID SOLUTION - const float NewZ = FMath::Lerp( - PlayerCharacter->GetCrouchingEyeHeight(), - PlayerCharacter->GetStandingEyeHeight(), - CoverStandAlpha - ); - - PlayerCharacter->CameraComponent->SetRelativeLocation( - FVector(0.0f, 0.0f, NewZ) - ); - - // DEBUG - if (bShowCoverSystemDebug && GEngine) - { - GEngine->AddOnScreenDebugMessage(1, -1, FColor::Red, FString::Printf(TEXT("Current cover stand alpha: %f"), CoverStandAlpha)); - } + //return 0.f; + return MaxCoverAimHeight - PlayerCharacter->CrouchedEyeHeight; } void AExoPlayerController::OnCoverTimer() { PlayerCharacter->bIsInCover = CheckForCover(); - if (PlayerCharacter->bIsInCover == false) - { - TargetCoverStandAlpha = 0.0f; - UpdateSmoothCoverCamera(GetWorld()->GetDeltaSeconds()); - } } void AExoPlayerController::DebugCoverSystem(bool show) diff --git a/Source/Exo/Public/Characters/ExoPlayerCharacter.h b/Source/Exo/Public/Characters/ExoPlayerCharacter.h index ab82e26..8f25f12 100644 --- a/Source/Exo/Public/Characters/ExoPlayerCharacter.h +++ b/Source/Exo/Public/Characters/ExoPlayerCharacter.h @@ -19,6 +19,7 @@ class EXO_API AExoPlayerCharacter : public AExoCharacterBase public: AExoPlayerCharacter(); + /// U PROPERTIES /// UPROPERTY(EditAnywhere, Category = "Combat") TObjectPtr Weapon; @@ -34,6 +35,9 @@ public: UPROPERTY(VisibleAnywhere, BlueprintReadOnly) TObjectPtr CapsuleBottom; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI") + TSubclassOf PlayerHudClass; + UPROPERTY(EditAnywhere, Category = "Dodge Properties") float DodgeForce = 5000.f; @@ -61,19 +65,35 @@ public: UPROPERTY(EditAnywhere, Category = "Health") float CurrentHealth = 50.0f; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI") - TSubclassOf PlayerHudClass; + /// Połowa wysokości kapsuły gracza podczas stania + UPROPERTY(EditAnywhere, BlueprintReadOnly) + float StandingHalfHeight = 88.f; + + /** Czy postać gracza jest obecnie schowana za osłoną */ + UPROPERTY(BlueprintReadOnly, Category = "Cover System") + bool bIsInCover = false; + + /** Offset kamery podczas leżenia (osłona, ślizg)
+ * Bezpiecznie będzie założyć że to najniżej jak kamera + * może zejść podczas gameplaya + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera") + float LowEyeHeightOffset; + + /// U FUNCTIONS /// UFUNCTION() void OnActorBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult ); + /// Przełącza gracza w tryb kucania UFUNCTION(BlueprintCallable, Category = "Movement") void CrouchCustom(); + /// Próbuje wyjść z trybu kucania UFUNCTION(BlueprintCallable, Category = "Movement") - void UnCrouchCustom(); + void TryUnCrouchCustom(); DECLARE_MULTICAST_DELEGATE(FOnPlayerCrouchEvent); FOnPlayerCrouchEvent OnPlayerCrouchStart; @@ -115,17 +135,9 @@ public: UFUNCTION(BlueprintPure, Category="Camera") float GetCrouchingEyeHeight(const bool bCapsuleRelative = false) const; - - /** Czy postać gracza jest obecnie schowana za osłoną */ - UPROPERTY(BlueprintReadOnly, Category = "Cover System") - bool bIsInCover = false; - /** Offset kamery podczas leżenia (osłona, ślizg)
- * Bezpiecznie będzie założyć że to najniżej jak kamera - * może zejść podczas gameplaya - */ - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera") - float LowEyeHeightOffset; + UFUNCTION(BlueprintPure, Category="Movement") + bool IsCrouching() const; protected: diff --git a/Source/Exo/Public/Player/ExoPlayerController.h b/Source/Exo/Public/Player/ExoPlayerController.h index edfe266..0964c22 100644 --- a/Source/Exo/Public/Player/ExoPlayerController.h +++ b/Source/Exo/Public/Player/ExoPlayerController.h @@ -25,6 +25,9 @@ public: virtual void PlayerTick(float DeltaTime) override; + UPROPERTY(BlueprintReadOnly) + bool bIsCoverAiming = false; + protected: virtual void SetupInputComponent() override; @@ -95,13 +98,7 @@ protected: UFUNCTION(BlueprintCallable, Category = "Cover System") bool CheckForCover(); - UFUNCTION(BlueprintCallable, Category = "Cover System") - float CalculateCoverAimOffset(); - - UFUNCTION(BlueprintCallable, Category = "Cover System") - void UpdateSmoothCoverCamera(float DeltaTime); - - void OnCoverTimer(); + //DECLARE_MULTICAST_DELEGATE(FOnPlayerAimEvent); // Cover System DEBUG UFUNCTION(Exec, Category = "Cover System") @@ -175,13 +172,6 @@ protected: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character") TObjectPtr PlayerCharacter; - /** Alpha wysokości kamery podczas wychulania zza osłony - * 0 - Wysokość kucania - * 1 - Maksymalna wysokość wychylenia określona przez CoverAimStandFactor - **/ - UPROPERTY(EditAnywhere, Category = "Cover System") - float TargetCoverStandAlpha = 0.0f; - /** Częstotliwość okresowego szukania osłon podczas kucania */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System") float CoverCheckRate = 0.5f; @@ -234,15 +224,10 @@ private: UShootingComponent* ShootingComponent; + float CalculateCoverAimOffset(); + void OnCoverTimer(); - - float CoverStandAlpha = 0.0f; // deprecated FTimerHandle CoverCheckTimer; float MaxCoverAimHeight; float CoverAimHeightOffset; - - - - //FTransform TargetCameraOffset; - //FTransform CameraOffset; };