feat: Working cover and camera system

This commit is contained in:
NeonDmn 2025-06-01 17:55:38 +02:00
parent f3567a115e
commit abcd8acc6f
7 changed files with 56 additions and 168 deletions

View File

@ -74,3 +74,4 @@ GlobalDefaultServerGameMode=None
+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerController.CalculateCoverAim",NewName="/Script/Exo.ExoPlayerController.CalculateCoverAimOffset") +FunctionRedirects=(OldName="/Script/Exo.ExoPlayerController.CalculateCoverAim",NewName="/Script/Exo.ExoPlayerController.CalculateCoverAimOffset")
+PropertyRedirects=(OldName="/Script/Exo.ExoPlayerController.UseEyeHeight",NewName="/Script/Exo.ExoPlayerController.bUseEyeHeight") +PropertyRedirects=(OldName="/Script/Exo.ExoPlayerController.UseEyeHeight",NewName="/Script/Exo.ExoPlayerController.bUseEyeHeight")
+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.SetEyePositionOffset",NewName="/Script/Exo.ExoPlayerCharacter.SetEyePositionOffsetTarget") +FunctionRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.SetEyePositionOffset",NewName="/Script/Exo.ExoPlayerCharacter.SetEyePositionOffsetTarget")
+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.UnCrouchCustom",NewName="/Script/Exo.ExoPlayerCharacter.TryUnCrouchCustom")

Binary file not shown.

View File

@ -60,7 +60,6 @@ void AExoPlayerCharacter::BeginPlay()
CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, FromFeet(TargetEyeHeight))); CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, FromFeet(TargetEyeHeight)));
GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AExoPlayerCharacter::OnActorBeginOverlap); GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AExoPlayerCharacter::OnActorBeginOverlap);
//UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->SetViewTarget(this);
PlayerHud = CreateWidget<UWBP_PlayerUI>(GetWorld(),PlayerHudClass); PlayerHud = CreateWidget<UWBP_PlayerUI>(GetWorld(),PlayerHudClass);
@ -84,12 +83,6 @@ void AExoPlayerCharacter::Tick(float DeltaTime)
{ {
Super::Tick(DeltaTime); Super::Tick(DeltaTime);
//// NOT FINAL SOLUTION ///
/** Reset camera offset at the start of every frame */
//TargetEyeLocationOffset = FVector::ZeroVector;
//TargetEyeRoll = 0.f;
//////////////////////////
UpdateCameraHeight(DeltaTime); UpdateCameraHeight(DeltaTime);
ApplyCameraOffsets(DeltaTime); ApplyCameraOffsets(DeltaTime);
} }
@ -115,11 +108,6 @@ void AExoPlayerCharacter::UpdateCameraHeight(float DeltaTime)
void AExoPlayerCharacter::ApplyCameraOffsets(float DeltaTime) void AExoPlayerCharacter::ApplyCameraOffsets(float DeltaTime)
{ {
bool HasChanged = false; 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)) if (!FVector::PointsAreNear(EyeLocationOffset, TargetEyeLocationOffset, 0.01f))
{ {
// Smoothly offset view // Smoothly offset view
@ -141,15 +129,10 @@ void AExoPlayerCharacter::ApplyCameraOffsets(float DeltaTime)
} }
// Update actual camera position // 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, const FVector FinalOffset = FVector(EyeLocationOffset.X, EyeLocationOffset.Y,
EyeLocationOffset.Z + TargetEyeHeight + GetFootOffset()); EyeLocationOffset.Z + TargetEyeHeight + GetFootOffset());
CameraComponent->SetRelativeLocation(FinalOffset); CameraComponent->SetRelativeLocation(FinalOffset);
//UE_LOG(LogTemp, Log, TEXT("Camera relative: %s"), *CameraComponent->GetRelativeLocation().ToString());
// Update actual camera rotation (Roll) // Update actual camera rotation (Roll)
FRotator NewRotator = GetController()->GetControlRotation(); FRotator NewRotator = GetController()->GetControlRotation();
NewRotator.Roll = EyeRoll; NewRotator.Roll = EyeRoll;
@ -192,21 +175,22 @@ void AExoPlayerCharacter::CrouchCustom()
{ {
SetTargetEyeHeight(CrouchedEyeHeight); SetTargetEyeHeight(CrouchedEyeHeight);
GetCharacterMovement()->MaxWalkSpeed = CrouchSpeed; GetCharacterMovement()->MaxWalkSpeed = CrouchSpeed;
bIsCrouched = true;
float CurrentCamHeight = GetCurrentEyeHeight(); float CurrentCamHeight = GetCurrentEyeHeight();
GetCapsuleComponent()->SetCapsuleHalfHeight(44.f); GetCapsuleComponent()->SetCapsuleHalfHeight(GetCharacterMovement()->CrouchedHalfHeight);
CameraComponent->SetRelativeLocation( CameraComponent->SetRelativeLocation(
FVector(0, 0, GetFootOffset()) + FVector(0, 0, GetFootOffset()) +
FVector(0, 0, CurrentCamHeight)); FVector(0, 0, CurrentCamHeight));
} }
void AExoPlayerCharacter::UnCrouchCustom() void AExoPlayerCharacter::TryUnCrouchCustom()
{ {
SetTargetEyeHeight(StandingEyeHeight); SetTargetEyeHeight(StandingEyeHeight);
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed; GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
float CurrentCamHeight = GetCurrentEyeHeight(); float CurrentCamHeight = GetCurrentEyeHeight();
GetCapsuleComponent()->SetCapsuleHalfHeight(88.f); GetCapsuleComponent()->SetCapsuleHalfHeight(StandingHalfHeight);
CameraComponent->SetRelativeLocation( CameraComponent->SetRelativeLocation(
FVector(0, 0, GetFootOffset()) + FVector(0, 0, GetFootOffset()) +
FVector(0, 0, CurrentCamHeight)); FVector(0, 0, CurrentCamHeight));
@ -255,6 +239,11 @@ float AExoPlayerCharacter::GetCrouchingEyeHeight(const bool bCapsuleRelative) co
: CrouchedEyeHeight; : CrouchedEyeHeight;
} }
bool AExoPlayerCharacter::IsCrouching() const
{
return bIsCrouched;
}
void AExoPlayerCharacter::SetEyePositionOffsetTarget(const FVector LocationOffset) void AExoPlayerCharacter::SetEyePositionOffsetTarget(const FVector LocationOffset)
{ {

View File

@ -36,27 +36,17 @@ void AExoPlayerController::BeginPlay()
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed; PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed;
} }
void AExoPlayerController::PlayerTick(float DeltaTime) void AExoPlayerController::PlayerTick(const float DeltaTime)
{ {
Super::PlayerTick(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(); CoverAimHeightOffset = CalculateCoverAimOffset();
PlayerCharacter->SetEyePositionOffsetTarget( PlayerCharacter->SetEyePositionOffsetTarget(FVector(0.f, 0.f, CoverAimHeightOffset));
FVector(0.f, 0.f, CoverAimHeightOffset));
} }
}
//else
//{
// PlayerCharacter->SetEyePositionOffsetTarget(FVector::ZeroVector);
//}
// On screen cover state DEBUG // On screen cover state DEBUG
if (bShowCoverSystemDebug) if (bShowCoverSystemDebug)
@ -168,14 +158,7 @@ void AExoPlayerController::PlayerStartCrouch()
GetWorldTimerManager().SetTimer(SlideCooldownTimer, this, &AExoPlayerController::ResetSlide, PlayerCharacter->SlideCooldown, false); GetWorldTimerManager().SetTimer(SlideCooldownTimer, this, &AExoPlayerController::ResetSlide, PlayerCharacter->SlideCooldown, false);
} }
//PlayerCharacter->Crouch();
PlayerCharacter->CrouchCustom(); PlayerCharacter->CrouchCustom();
//PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->CrouchedEyeHeight);
// PlayerCharacter->CameraComponent->SetRelativeLocation(FVector(
// 0.0f,
// 0.0f,
// PlayerCharacter->CrouchedEyeHeight)
// );
// Start checking for cover // Start checking for cover
PlayerCharacter->bIsInCover = CheckForCover(); PlayerCharacter->bIsInCover = CheckForCover();
@ -190,19 +173,11 @@ void AExoPlayerController::PlayerStartCrouch()
void AExoPlayerController::PlayerStopCrouch() void AExoPlayerController::PlayerStopCrouch()
{ {
//PlayerCharacter->UnCrouch(); PlayerCharacter->TryUnCrouchCustom();
PlayerCharacter->UnCrouchCustom();
//PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->GetStandingEyeHeight());
// PlayerCharacter->CameraComponent->SetRelativeLocation(FVector(
// 0.0f,
// 0.0f,
// PlayerCharacter->BaseEyeHeight)
// );
// Stop checking for cover // Stop checking for cover
GetWorld()->GetTimerManager().ClearTimer(CoverCheckTimer); GetWorld()->GetTimerManager().ClearTimer(CoverCheckTimer);
PlayerCharacter->bIsInCover = false; PlayerCharacter->bIsInCover = false;
TargetCoverStandAlpha = 0.0f;
} }
void AExoPlayerController::ResetSlide() void AExoPlayerController::ResetSlide()
@ -253,7 +228,7 @@ void AExoPlayerController::PlayerStopAim()
ShootingComponent->StopAiming(); ShootingComponent->StopAiming();
if (PlayerCharacter->bIsInCover) if (PlayerCharacter->bIsInCover)
{ {
CalculateCoverAimOffset(); PlayerCharacter->SetEyePositionOffsetTarget(FVector(0, 0, 0));
} }
} }
@ -289,9 +264,6 @@ void AExoPlayerController::PlayerReload()
bool AExoPlayerController::CheckForCover() 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 // Do a simple 8-directional line trace
FVector TraceDirection = PlayerCharacter->GetActorForwardVector(); FVector TraceDirection = PlayerCharacter->GetActorForwardVector();
FVector TraceStart = PlayerCharacter->GetActorLocation(); FVector TraceStart = PlayerCharacter->GetActorLocation();
@ -373,16 +345,6 @@ float AExoPlayerController::CalculateCoverAimOffset()
// Oblicz maksymalną wysokość, na którą można wychylić się znad osłony // Oblicz maksymalną wysokość, na którą można wychylić się znad osłony
MaxCoverAimHeight = PlayerCharacter->GetStandingEyeHeight() * CoverAimStandFactor; 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; FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(PlayerCharacter); QueryParams.AddIgnoredActor(PlayerCharacter);
TEnumAsByte<ECollisionChannel> ObstacleTraceChannel = ECC_WorldStatic; TEnumAsByte<ECollisionChannel> ObstacleTraceChannel = ECC_WorldStatic;
@ -390,40 +352,9 @@ float AExoPlayerController::CalculateCoverAimOffset()
FHitResult Hit; FHitResult Hit;
bool bFreeSpace = false; bool bFreeSpace = false;
// SphereTrace until no hit is found (free space to aim) FVector ObstacleTraceStart = PlayerCharacter->GetPlayerLocationAtFeet();
// 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();
ObstacleTraceStart.Z += PlayerCharacter->CrouchedEyeHeight; ObstacleTraceStart.Z += PlayerCharacter->CrouchedEyeHeight;
ObstacleTraceEnd = ObstacleTraceStart + PlayerCameraManager->GetCameraRotation().Vector() * CoverAimFreeDistance; FVector ObstacleTraceEnd = ObstacleTraceStart + PlayerCameraManager->GetCameraRotation().Vector() * CoverAimFreeDistance;
float SafeCoverAimZOffset = 0.f; float SafeCoverAimZOffset = 0.f;
while (SafeCoverAimZOffset < MaxCoverAimHeight) while (SafeCoverAimZOffset < MaxCoverAimHeight)
@ -457,6 +388,7 @@ float AExoPlayerController::CalculateCoverAimOffset()
// If this is true that means that free space was found // If this is true that means that free space was found
if (FinalHitHeight <= MaxCoverAimHeight) if (FinalHitHeight <= MaxCoverAimHeight)
{ {
PlayerCharacter->bIsCrouched = false;
//// DEBUG //// //// DEBUG ////
if (bShowCoverSystemDebug) if (bShowCoverSystemDebug)
{ {
@ -469,44 +401,13 @@ float AExoPlayerController::CalculateCoverAimOffset()
} }
// Return 0 offset if no free space to aim was found // Return 0 offset if no free space to aim was found
return 0.f; //return 0.f;
} return MaxCoverAimHeight - PlayerCharacter->CrouchedEyeHeight;
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));
}
} }
void AExoPlayerController::OnCoverTimer() void AExoPlayerController::OnCoverTimer()
{ {
PlayerCharacter->bIsInCover = CheckForCover(); PlayerCharacter->bIsInCover = CheckForCover();
if (PlayerCharacter->bIsInCover == false)
{
TargetCoverStandAlpha = 0.0f;
UpdateSmoothCoverCamera(GetWorld()->GetDeltaSeconds());
}
} }
void AExoPlayerController::DebugCoverSystem(bool show) void AExoPlayerController::DebugCoverSystem(bool show)

View File

@ -19,6 +19,7 @@ class EXO_API AExoPlayerCharacter : public AExoCharacterBase
public: public:
AExoPlayerCharacter(); AExoPlayerCharacter();
/// U PROPERTIES ///
UPROPERTY(EditAnywhere, Category = "Combat") UPROPERTY(EditAnywhere, Category = "Combat")
TObjectPtr<USkeletalMeshComponent> Weapon; TObjectPtr<USkeletalMeshComponent> Weapon;
@ -34,6 +35,9 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly) UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
TObjectPtr<USceneComponent> CapsuleBottom; TObjectPtr<USceneComponent> CapsuleBottom;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI")
TSubclassOf<UUserWidget> PlayerHudClass;
UPROPERTY(EditAnywhere, Category = "Dodge Properties") UPROPERTY(EditAnywhere, Category = "Dodge Properties")
float DodgeForce = 5000.f; float DodgeForce = 5000.f;
@ -61,19 +65,35 @@ public:
UPROPERTY(EditAnywhere, Category = "Health") UPROPERTY(EditAnywhere, Category = "Health")
float CurrentHealth = 50.0f; float CurrentHealth = 50.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI") /// Połowa wysokości kapsuły gracza podczas stania
TSubclassOf<UUserWidget> PlayerHudClass; 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) <br>
* 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() UFUNCTION()
void OnActorBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, void OnActorBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult
); );
/// Przełącza gracza w tryb kucania
UFUNCTION(BlueprintCallable, Category = "Movement") UFUNCTION(BlueprintCallable, Category = "Movement")
void CrouchCustom(); void CrouchCustom();
/// Próbuje wyjść z trybu kucania
UFUNCTION(BlueprintCallable, Category = "Movement") UFUNCTION(BlueprintCallable, Category = "Movement")
void UnCrouchCustom(); void TryUnCrouchCustom();
DECLARE_MULTICAST_DELEGATE(FOnPlayerCrouchEvent); DECLARE_MULTICAST_DELEGATE(FOnPlayerCrouchEvent);
FOnPlayerCrouchEvent OnPlayerCrouchStart; FOnPlayerCrouchEvent OnPlayerCrouchStart;
@ -116,16 +136,8 @@ public:
UFUNCTION(BlueprintPure, Category="Camera") UFUNCTION(BlueprintPure, Category="Camera")
float GetCrouchingEyeHeight(const bool bCapsuleRelative = false) const; float GetCrouchingEyeHeight(const bool bCapsuleRelative = false) const;
/** Czy postać gracza jest obecnie schowana za osłoną */ UFUNCTION(BlueprintPure, Category="Movement")
UPROPERTY(BlueprintReadOnly, Category = "Cover System") bool IsCrouching() const;
bool bIsInCover = false;
/** Offset kamery podczas leżenia (osłona, ślizg) <br>
* Bezpiecznie będzie założyć że to najniżej jak kamera
* może zejść podczas gameplaya
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
float LowEyeHeightOffset;
protected: protected:

View File

@ -25,6 +25,9 @@ public:
virtual void PlayerTick(float DeltaTime) override; virtual void PlayerTick(float DeltaTime) override;
UPROPERTY(BlueprintReadOnly)
bool bIsCoverAiming = false;
protected: protected:
virtual void SetupInputComponent() override; virtual void SetupInputComponent() override;
@ -95,13 +98,7 @@ protected:
UFUNCTION(BlueprintCallable, Category = "Cover System") UFUNCTION(BlueprintCallable, Category = "Cover System")
bool CheckForCover(); bool CheckForCover();
UFUNCTION(BlueprintCallable, Category = "Cover System") //DECLARE_MULTICAST_DELEGATE(FOnPlayerAimEvent);
float CalculateCoverAimOffset();
UFUNCTION(BlueprintCallable, Category = "Cover System")
void UpdateSmoothCoverCamera(float DeltaTime);
void OnCoverTimer();
// Cover System DEBUG // Cover System DEBUG
UFUNCTION(Exec, Category = "Cover System") UFUNCTION(Exec, Category = "Cover System")
@ -175,13 +172,6 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character") UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character")
TObjectPtr<AExoPlayerCharacter> PlayerCharacter; TObjectPtr<AExoPlayerCharacter> 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 */ /** Częstotliwość okresowego szukania osłon podczas kucania */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System")
float CoverCheckRate = 0.5f; float CoverCheckRate = 0.5f;
@ -234,15 +224,10 @@ private:
UShootingComponent* ShootingComponent; UShootingComponent* ShootingComponent;
float CalculateCoverAimOffset();
void OnCoverTimer();
float CoverStandAlpha = 0.0f; // deprecated
FTimerHandle CoverCheckTimer; FTimerHandle CoverCheckTimer;
float MaxCoverAimHeight; float MaxCoverAimHeight;
float CoverAimHeightOffset; float CoverAimHeightOffset;
//FTransform TargetCameraOffset;
//FTransform CameraOffset;
}; };