Compare commits

..

No commits in common. "6ba42fd4004b418285211c3141788a8af4c9b157" and "ae416d567373db836749a17294e3079365bfd707" have entirely different histories.

13 changed files with 231 additions and 437 deletions

View File

@ -63,15 +63,3 @@ ServerDefaultMap=/Engine/Maps/Entry.Entry
GlobalDefaultGameMode=/Game/Blueprints/Game/BP_ExoGameMode.BP_ExoGameMode_C GlobalDefaultGameMode=/Game/Blueprints/Game/BP_ExoGameMode.BP_ExoGameMode_C
GlobalDefaultServerGameMode=None GlobalDefaultServerGameMode=None
[CoreRedirects]
+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerController.UpdateCoverStandHeight",NewName="/Script/Exo.ExoPlayerController.UpdateSmoothCoverCamera")
+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerController.AdjustCameraWhileInCover",NewName="/Script/Exo.ExoPlayerController.CalculateCoverAim")
+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerController.SetNewCameraLocationOffset",NewName="/Script/Exo.ExoPlayerController.SetEyePositionOffset")
+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerController.SetNewCameraRotationOffset",NewName="/Script/Exo.ExoPlayerController.SetEyeRoll")
+PropertyRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.IsInCover",NewName="/Script/Exo.ExoPlayerCharacter.bIsInCover")
+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")
+FunctionRedirects=(OldName="/Script/Exo.ExoPlayerCharacter.UnCrouchCustom",NewName="/Script/Exo.ExoPlayerCharacter.TryUnCrouchCustom")

Binary file not shown.

View File

@ -265,7 +265,6 @@ void UShootingComponent::StartAiming()
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed * AimingMoveSpeedScale; PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed * AimingMoveSpeedScale;
TargetFOV = CurrentGunBase->AimingFOV; TargetFOV = CurrentGunBase->AimingFOV;
OnStartedADS.Broadcast();
} }
} }
@ -275,8 +274,6 @@ void UShootingComponent::StopAiming()
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed; PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed;
TargetFOV = DefaultFOV; TargetFOV = DefaultFOV;
OnStoppedADS.Broadcast();
} }
void UShootingComponent::Throw() void UShootingComponent::Throw()

View File

@ -5,29 +5,16 @@
#include "Blueprint/UserWidget.h" #include "Blueprint/UserWidget.h"
#include "Characters/Components/ShootingComponent.h" #include "Characters/Components/ShootingComponent.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h" #include "GameFramework/CharacterMovementComponent.h"
#include "Items/AmmoBoxBase.h" #include "Items/AmmoBoxBase.h"
#include "Items/HealthBoxBase.h" #include "Items/HealthBoxBase.h"
#include "Kismet/GameplayStatics.h"
#include "Player/InteractionComponent.h" #include "Player/InteractionComponent.h"
#include "Widget/WBP_PlayerUI.h" #include "Widget/WBP_PlayerUI.h"
AExoPlayerCharacter::AExoPlayerCharacter() AExoPlayerCharacter::AExoPlayerCharacter()
{ {
PrimaryActorTick.bCanEverTick = true;
// Setup eye height values
StandingEyeHeight = 175.f;
CrouchedEyeHeight = 50.f;
LowEyeHeightOffset = -20.f;
// Create camera component
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
CameraComponent->bUsePawnControlRotation = true;
GetCharacterMovement()->bSnapToPlaneAtStart = true; GetCharacterMovement()->bSnapToPlaneAtStart = true;
InteractionComponent = CreateDefaultSubobject<UInteractionComponent>(TEXT("Interaction Component")); InteractionComponent = CreateDefaultSubobject<UInteractionComponent>(TEXT("Interaction Component"));
@ -43,27 +30,23 @@ AExoPlayerCharacter::AExoPlayerCharacter()
//bUseControllerRotationPitch = false; //bUseControllerRotationPitch = false;
//bUseControllerRotationYaw = true; //bUseControllerRotationYaw = true;
//bUseControllerRotationRoll = false; //bUseControllerRotationRoll = false;
// Setup camera component
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
CameraComponent->bUsePawnControlRotation = true;
CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, BaseEyeHeight));
} }
void AExoPlayerCharacter::BeginPlay() void AExoPlayerCharacter::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
// Set correct starting camera height
SetTargetEyeHeight(StandingEyeHeight);
CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, TargetEyeHeight + GetFootOffset()));
GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AExoPlayerCharacter::OnActorBeginOverlap); GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AExoPlayerCharacter::OnActorBeginOverlap);
//UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0)->SetViewTarget(this);
StandingEyeHeight = CameraComponent->GetRelativeLocation().Z;
// Setup crouch timeline
FOnTimelineFloat ProgressUpdate;
ProgressUpdate.BindUFunction(this, FName("CrouchingUpdate"));
FOnTimelineEvent FinishedEvent;
FinishedEvent.BindUFunction(this, FName("CrouchingFinished"));
CrouchTimeline.AddInterpFloat(CapsuleResizeCurve, ProgressUpdate);
CrouchTimeline.SetTimelineFinishedFunc(FinishedEvent);
PlayerHud = CreateWidget<UWBP_PlayerUI>(GetWorld(),PlayerHudClass); PlayerHud = CreateWidget<UWBP_PlayerUI>(GetWorld(),PlayerHudClass);
if (PlayerHud) if (PlayerHud)
{ {
@ -81,89 +64,8 @@ void AExoPlayerCharacter::BeginPlay()
} }
} }
void AExoPlayerCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
CrouchTimeline.TickTimeline(2*DeltaTime);
UpdateCameraHeight(DeltaTime);
ApplyCameraOffsets(DeltaTime);
}
float AExoPlayerCharacter::GetFootOffset()
{
return -GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
}
void AExoPlayerCharacter::CrouchingUpdate(float Alpha)
{
float CurrentCamHeight = GetCurrentEyeHeight();
float NewHalfHeight = FMath::Lerp(
StandingHalfHeight, GetCharacterMovement()->CrouchedHalfHeight, Alpha);
GetCapsuleComponent()->SetCapsuleHalfHeight(NewHalfHeight);
CameraComponent->SetRelativeLocation(
FVector(0, 0, GetFootOffset()) +
FVector(0, 0, CurrentCamHeight));
UE_LOG(LogTemp, Display, TEXT("Crouching Update"));
}
void AExoPlayerCharacter::CrouchingFinished()
{
}
void AExoPlayerCharacter::UpdateCameraHeight(float DeltaTime)
{
if (FMath::IsNearlyEqual(GetCurrentEyeHeight(), TargetEyeHeight, 0.01f))
{
return;
}
const float NewHeight = FMath::Lerp(GetCurrentEyeHeight(), TargetEyeHeight, DeltaTime*5);
const FVector CamRelXY = CameraComponent->GetRelativeLocation();
EyeHeight = GetFootOffset() + NewHeight;
CameraComponent->SetRelativeLocation(FVector(CamRelXY.X, CamRelXY.Y,EyeHeight));
}
void AExoPlayerCharacter::ApplyCameraOffsets(float DeltaTime)
{
bool HasChanged = false;
if (!FVector::PointsAreNear(EyeLocationOffset, TargetEyeLocationOffset, 0.01f))
{
// Smoothly offset view
EyeLocationOffset = FMath::Lerp(EyeLocationOffset, TargetEyeLocationOffset, 5*DeltaTime);
HasChanged = true;
}
if (!FMath::IsNearlyEqual(EyeRoll, TargetEyeRoll, 0.01f))
{
// Smoothly rotate view
EyeRoll = FMath::Lerp(EyeRoll, TargetEyeRoll, DeltaTime*5);
HasChanged = true;
}
if (!HasChanged)
{
// Do not calculate anything if nothing changed
return;
}
// Update actual camera position
const FVector FinalOffset = FVector(EyeLocationOffset.X, EyeLocationOffset.Y,
EyeLocationOffset.Z + TargetEyeHeight + GetFootOffset());
CameraComponent->SetRelativeLocation(FinalOffset);
// Update actual camera rotation (Roll)
FRotator NewRotator = GetController()->GetControlRotation();
NewRotator.Roll = EyeRoll;
GetController()->SetControlRotation(NewRotator);
}
void AExoPlayerCharacter::OnActorBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, void AExoPlayerCharacter::OnActorBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{ {
if (OtherActor && OtherActor != this) if (OtherActor && OtherActor != this)
{ {
@ -194,34 +96,6 @@ void AExoPlayerCharacter::OnActorBeginOverlap(UPrimitiveComponent* OverlappedCom
} }
} }
void AExoPlayerCharacter::CrouchCustom()
{
SetTargetEyeHeight(CrouchedEyeHeight);
GetCharacterMovement()->MaxWalkSpeed = CrouchSpeed;
bIsCrouched = true;
CrouchTimeline.Play();
//float CurrentCamHeight = GetCurrentEyeHeight();
//GetCapsuleComponent()->SetCapsuleHalfHeight(GetCharacterMovement()->CrouchedHalfHeight);
// CameraComponent->SetRelativeLocation(
// FVector(0, 0, GetFootOffset()) +
// FVector(0, 0, CurrentCamHeight));
}
void AExoPlayerCharacter::TryUnCrouchCustom()
{
SetTargetEyeHeight(StandingEyeHeight);
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
bIsCrouched = false;
CrouchTimeline.Reverse();
//float CurrentCamHeight = GetCurrentEyeHeight();
//GetCapsuleComponent()->SetCapsuleHalfHeight(StandingHalfHeight);
//CameraComponent->SetRelativeLocation(
// FVector(0, 0, GetFootOffset()) +
// FVector(0, 0, CurrentCamHeight));
}
void AExoPlayerCharacter::AddHealthPoints(float addValue) void AExoPlayerCharacter::AddHealthPoints(float addValue)
{ {
CurrentHealth += addValue; CurrentHealth += addValue;
@ -231,64 +105,4 @@ void AExoPlayerCharacter::AddHealthPoints(float addValue)
if (PlayerHud) if (PlayerHud)
PlayerHud->SetHp(CurrentHealth,MaxHealth); PlayerHud->SetHp(CurrentHealth,MaxHealth);
} }
float AExoPlayerCharacter::GetStandingEyeHeight(const bool bCapsuleRelative) const
{
return bCapsuleRelative ? StandingEyeHeight - GetCapsuleComponent()->GetScaledCapsuleHalfHeight()
: StandingEyeHeight;
}
float AExoPlayerCharacter::GetCrouchingEyeHeight(const bool bCapsuleRelative) const
{
return bCapsuleRelative ? CrouchedEyeHeight - GetCapsuleComponent()->GetScaledCapsuleHalfHeight()
: CrouchedEyeHeight;
}
bool AExoPlayerCharacter::IsCrouching() const
{
return bIsCrouched;
}
void AExoPlayerCharacter::SetEyePositionOffsetTarget(const FVector LocationOffset)
{
//LocationOffset.Z = FMath::Clamp(LocationOffset.Z, CoverEyeHeight, StandingEyeHeight);
UE_LOG(LogTemp, Log, TEXT("Eye offset set to: %s"), *LocationOffset.ToString());
TargetEyeLocationOffset = LocationOffset;
}
void AExoPlayerCharacter::SetEyeRoll(float RollValue)
{
TargetEyeRoll = RollValue;
}
FVector AExoPlayerCharacter::GetPlayerLocationAtFeet() const
{
FVector ReturnVector = GetActorLocation();
ReturnVector.Z -= GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
return ReturnVector;
}
void AExoPlayerCharacter::SetTargetEyeHeight(float NewEyeHeight, const bool bCapsuleRelative)
{
if (bCapsuleRelative)
{
NewEyeHeight += GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
}
UE_LOG(LogTemp, Log, TEXT("Target eye height set to: %f"), NewEyeHeight);
TargetEyeHeight = FMath::Clamp(NewEyeHeight,
CrouchedEyeHeight + LowEyeHeightOffset, StandingEyeHeight
);
}
float AExoPlayerCharacter::GetCurrentEyeHeight(const bool bCapsuleRelative) const
{
float ReturnValue = CameraComponent->GetRelativeLocation().Z;
if (!bCapsuleRelative)
{
ReturnValue += GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
}
return ReturnValue;
}

View File

@ -5,9 +5,9 @@
#include "EnhancedInputComponent.h" #include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h" #include "EnhancedInputSubsystems.h"
#include "Characters/ExoPlayerCharacter.h" #include "Characters/ExoPlayerCharacter.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/Character.h" #include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h" #include "GameFramework/CharacterMovementComponent.h"
#include "Kismet/GameplayStatics.h"
AExoPlayerController::AExoPlayerController() AExoPlayerController::AExoPlayerController()
{ {
@ -28,33 +28,34 @@ void AExoPlayerController::BeginPlay()
{ {
Subsystem->AddMappingContext(InputContext, 0); Subsystem->AddMappingContext(InputContext, 0);
} }
//InteractionComponent = PlayerCharacter->FindComponentByClass<UInteractionComponent>();
//ShootingComponent = PlayerCharacter->FindComponentByClass<UShootingComponent>();
InteractionComponent = PlayerCharacter->InteractionComponent; InteractionComponent = PlayerCharacter->InteractionComponent;
ShootingComponent = PlayerCharacter->ShootingComponent; ShootingComponent = PlayerCharacter->ShootingComponent;
// Ustawianie w komponencie poruszania pr<70>dko<6B>ci zapisanej w characterze // Ustawianie w komponencie poruszania pr<70>dko<6B>ci zapisanej w characterze
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed; PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed;
// Oblicz prawidłową maksymalną wysokość na którą można wychylić się z nad osłony
UE_LOG(LogTemp, Display, TEXT("MaxCoverAimHeight: %f"), MaxCoverAimHeight);
} }
void AExoPlayerController::PlayerTick(const float DeltaTime) void AExoPlayerController::PlayerTick(float DeltaTime)
{ {
Super::PlayerTick(DeltaTime); Super::PlayerTick(DeltaTime);
bIsCoverAiming = (PlayerCharacter->bIsInCover && PlayerCharacter->bIsAimingMode); // TESTING
if (bIsInCover)
if (bIsCoverAiming)
{ {
CoverAimHeightOffset = CalculateCoverAimOffset(); AdjustCameraWhileInCover();
PlayerCharacter->SetEyePositionOffsetTarget(FVector(0.f, 0.f, CoverAimHeightOffset));
} }
UpdateCoverStandHeight(DeltaTime);
// On screen cover state DEBUG
if (bShowCoverSystemDebug) if (bShowCoverSystemDebug)
{ {
GEngine->AddOnScreenDebugMessage(2, -1, FColor::Red, GEngine->AddOnScreenDebugMessage(2, -1, FColor::Red, FString::Printf(TEXT("In cover: %s"), bIsInCover ? "true" : "false"));
FString::Printf(TEXT("In cover: %hs"),
PlayerCharacter->bIsInCover ? "true" : "false")
);
} }
} }
@ -118,8 +119,6 @@ void AExoPlayerController::Interact()
void AExoPlayerController::PlayerJump() void AExoPlayerController::PlayerJump()
{ {
if (PlayerCharacter->IsCrouching()) return;
PlayerCharacter->Jump(); PlayerCharacter->Jump();
} }
@ -153,17 +152,21 @@ void AExoPlayerController::ResetDodge()
void AExoPlayerController::PlayerStartCrouch() void AExoPlayerController::PlayerStartCrouch()
{ {
if (bIsSprinting && !bWasSliding) if (bIsSprinting)
{ {
StartSlide(); PlayerCharacter->GetCharacterMovement()->MaxWalkSpeedCrouched = PlayerCharacter->SlideSpeed;
return; GetWorldTimerManager().SetTimer(SlideCooldownTimer, this, &AExoPlayerController::ResetSlide, PlayerCharacter->SlideCooldown, false);
} }
bWasSliding = false; PlayerCharacter->Crouch();
PlayerCharacter->CrouchCustom(); PlayerCharacter->CameraComponent->SetRelativeLocation(FVector(
0.0f,
0.0f,
PlayerCharacter->CrouchedEyeHeight)
);
// Start checking for cover // Start checking for cover
PlayerCharacter->bIsInCover = CheckForCover(); bIsInCover = CheckForCover();
GetWorld()->GetTimerManager().SetTimer( GetWorld()->GetTimerManager().SetTimer(
CoverCheckTimer, CoverCheckTimer,
this, this,
@ -175,28 +178,22 @@ void AExoPlayerController::PlayerStartCrouch()
void AExoPlayerController::PlayerStopCrouch() void AExoPlayerController::PlayerStopCrouch()
{ {
PlayerCharacter->TryUnCrouchCustom(); PlayerCharacter->UnCrouch();
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; bIsInCover = false;
} TargetCoverStandAlpha = 0.0f;
void AExoPlayerController::StartSlide()
{
bIsSliding = true;
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->SlideSpeed;
PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->LowEyeHeightOffset);
GetWorldTimerManager().SetTimer(SlideCooldownTimer, this, &AExoPlayerController::ResetSlide, PlayerCharacter->SlideCooldown, false);
} }
void AExoPlayerController::ResetSlide() void AExoPlayerController::ResetSlide()
{ {
bIsSliding = false; PlayerCharacter->GetCharacterMovement()->MaxWalkSpeedCrouched = PlayerCharacter->CrouchSpeed;
bWasSliding = true;
PlayerStartCrouch();
//PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->CrouchSpeed;
//PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->CrouchedEyeHeight);
} }
void AExoPlayerController::PlayerStartSprint() void AExoPlayerController::PlayerStartSprint()
@ -239,10 +236,6 @@ void AExoPlayerController::PlayerStartAim()
void AExoPlayerController::PlayerStopAim() void AExoPlayerController::PlayerStopAim()
{ {
ShootingComponent->StopAiming(); ShootingComponent->StopAiming();
if (PlayerCharacter->bIsInCover)
{
PlayerCharacter->SetEyePositionOffsetTarget(FVector(0, 0, 0));
}
} }
void AExoPlayerController::PlayerMeleAttack() void AExoPlayerController::PlayerMeleAttack()
@ -277,13 +270,13 @@ 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();
TraceStart.Z += bUseEyeHeight ? TraceStart.Z -= PlayerCharacter->GetCapsuleComponent()->GetScaledCapsuleHalfHeight() - CoverObstacleMinHeight;
PlayerCharacter->GetCrouchingEyeHeight(true)
:
PlayerCharacter->GetPlayerLocationAtFeet().Z + CoverObstacleMinHeight;
FCollisionQueryParams QueryParams; FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(PlayerCharacter); QueryParams.AddIgnoredActor(PlayerCharacter);
@ -313,9 +306,11 @@ bool AExoPlayerController::CheckForCover()
// Check if this particular hit isn't against a wall (>CoverMaxHeight) // Check if this particular hit isn't against a wall (>CoverMaxHeight)
FHitResult SphereHit; FHitResult SphereHit;
FVector SpherePosition = Hit.ImpactPoint; FVector SpherePosition = Hit.ImpactPoint +
SpherePosition.Z = PlayerCharacter->GetPlayerLocationAtFeet().Z + CoverObstacleMaxHeight + CoverAimWindowRadius; FVector(
0.0f, 0.0f,
CoverObstacleMaxHeight + CoverAimWindowRadius - CoverObstacleMinHeight);
GetWorld()->SweepSingleByChannel( GetWorld()->SweepSingleByChannel(
SphereHit, SphereHit,
SpherePosition, SpherePosition,
@ -347,17 +342,20 @@ bool AExoPlayerController::CheckForCover()
return ValidHits.Num() > 0; return ValidHits.Num() > 0;
} }
float AExoPlayerController::CalculateCoverAimOffset() void AExoPlayerController::AdjustCameraWhileInCover()
{ {
// Nic nie rób jak nie znajdujesz się za osłoną if (!bIsInCover)
if (!PlayerCharacter->bIsInCover)
{ {
return 0.f; return;
} }
// Oblicz maksymalną wysokość, na którą można wychylić się znad osłony MaxCoverAimHeight = PlayerCharacter->StandingEyeHeight * CoverAimStandFactor;
MaxCoverAimHeight = PlayerCharacter->GetStandingEyeHeight() * CoverAimStandFactor;
//FVector StartOffset = GetCharacter()->GetActorForwardVector() * 20.0f;
FVector ObstacleTraceStart = GetCharacter()->GetActorLocation();
ObstacleTraceStart.Z += GetCharacter()->CrouchedEyeHeight;
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;
@ -365,62 +363,159 @@ float AExoPlayerController::CalculateCoverAimOffset()
FHitResult Hit; FHitResult Hit;
bool bFreeSpace = false; bool bFreeSpace = false;
FVector ObstacleTraceStart = PlayerCharacter->GetPlayerLocationAtFeet(); // Trace until no hit is found (free space to aim)
ObstacleTraceStart.Z += PlayerCharacter->CrouchedEyeHeight; for (int i = 0; i < MaxCoverAimHeight; i += 2*CoverAimWindowRadius)
FVector ObstacleTraceEnd = ObstacleTraceStart + PlayerCameraManager->GetCameraRotation().Vector() * CoverAimFreeDistance;
float SafeCoverAimZOffset = 0.f;
while (SafeCoverAimZOffset < MaxCoverAimHeight)
{ {
ObstacleTraceStart.Z += SafeCoverAimZOffset; ObstacleTraceStart.Z += i;
ObstacleTraceEnd.Z += SafeCoverAimZOffset; ObstacleTraceEnd.Z += i;
GetWorld()->SweepSingleByChannel( GetWorld()->SweepSingleByChannel(
Hit, Hit,
ObstacleTraceStart, ObstacleTraceStart,
ObstacleTraceEnd, ObstacleTraceEnd,
FQuat::Identity, FQuat::Identity,
ObstacleTraceChannel, ObstacleTraceChannel,
FCollisionShape::MakeSphere(CoverAimWindowRadius), FCollisionShape::MakeSphere(CoverAimWindowRadius),
QueryParams QueryParams
); );
if (Hit.bBlockingHit == true) if (bShowCoverSystemDebug)
{ {
// Increment check height every failed iteration DrawDebugSphere(GetWorld(), Hit.Location, CoverAimWindowRadius, 8,
SafeCoverAimZOffset += 0.2f; Hit.bBlockingHit ? FColor::Blue : FColor::Red,
false, 0.0f, 0, 0);
} }
else
if (Hit.bBlockingHit == false)
{ {
// Break the loop if free space found UE_LOG(LogTemp, Display, TEXT("Free space"));
bFreeSpace = true;
break; break;
} }
} }
const float FinalHitHeight = Hit.TraceStart.Z - PlayerCharacter->GetPlayerLocationAtFeet().Z; if (bFreeSpace)
// If this is true that means that free space was found
if (FinalHitHeight <= MaxCoverAimHeight)
{ {
PlayerCharacter->bIsCrouched = false; TargetCoverStandAlpha = FMath::GetMappedRangeValueClamped(
//// DEBUG //// UE::Math::TVector2<float>(GetCharacter()->CrouchedEyeHeight, GetCharacter()->CrouchedEyeHeight + MaxCoverAimHeight),
UE::Math::TVector2(0.0f, 1.0f),
Hit.TraceStart.Z
);
if (bShowCoverSystemDebug) if (bShowCoverSystemDebug)
{ {
DrawDebugLine(GetWorld(), Hit.TraceStart, Hit.TraceEnd, FColor::Purple); DrawDebugLine(GetWorld(), Hit.TraceStart, Hit.TraceEnd, FColor::Red);
} }
//////////////
return FinalHitHeight - PlayerCharacter->CrouchedEyeHeight;// +
//PlayerCharacter->CrouchedEyeHeight - PlayerCharacter->GetCurrentEyeHeight();
} }
// Return 0 offset if no free space to aim was found // IDEA FOR A MORE COMPLEX SYSTEM IN THE FUTURE:
//return 0.f; //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
return MaxCoverAimHeight - PlayerCharacter->CrouchedEyeHeight; // To not introduce accidental flickering and optimize it a bit, all of this should run
// ONLY on cover update
// FVector CrouchedEyeWorldPosition = PlayerCharacter->GetActorLocation();
// CrouchedEyeWorldPosition.Z += PlayerCharacter->CrouchedEyeHeight;
// FVector CoverCeiling = CrouchedEyeWorldPosition + MaxCoverAimHeight;
// float PlayerCapsuleRadius = PlayerCharacter->GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
// TEnumAsByte<ECollisionChannel> ObstacleTraceChannel = ECC_WorldStatic;
// FCollisionQueryParams QueryParams;
// QueryParams.AddIgnoredActor(PlayerCharacter);
//
// // Shoot ray up at maximum cover length to determine how high the player can "stand up"
// FHitResult WallTopHit;
// GetWorld()->SweepSingleByChannel(
// WallTopHit,
// CrouchedEyeWorldPosition,
// CoverCeiling,
// FQuat::Identity,
// ObstacleTraceChannel,
// FCollisionShape::MakeSphere(PlayerCapsuleRadius),
// QueryParams
// );
//
// FVector CeilingWorldLocation;
// if (WallTopHit.bBlockingHit == true)
// {
// CeilingWorldLocation = WallTopHit.Location;
// }
// else
// {
// CeilingWorldLocation = WallTopHit.TraceEnd;
// }
//
// // From hit location (or if no hit - from end position) shoot ray towards camera's forward
// // vector at minimum cover length
//
// constexpr float WallFinderDistance = 75.0f;
// FVector WallFinderDirection = PlayerCharacter->GetActorForwardVector();
// WallFinderDirection.Z = 0.0f; // Not needed if the player always stays upright
//
// GetWorld()->LineTraceSingleByChannel(
// WallTopHit,
// CeilingWorldLocation,
// CeilingWorldLocation + (WallFinderDirection * WallFinderDistance),
// ObstacleTraceChannel,
// QueryParams
// );
//
// // regardless of the hit result shoot multi-ray downwards from end location
// // with maximum cover length
//
// FVector WallTopTraceStart = WallTopHit.bBlockingHit ? WallTopHit.Location : WallTopHit.TraceEnd;
// TArray<FHitResult> ValidHitsCandidateArray;
//
// GetWorld()->LineTraceMultiByChannel(
// ValidHitsCandidateArray,
// WallTopTraceStart,
// WallTopTraceStart + (FVector(0.0f, 0.0f, 0.0f) * MaxCoverAimHeight),
// ObstacleTraceChannel,
// QueryParams
// );
// On every ray hit trace an in-place sphere to determine if the aiming spot is valid
// All valid aiming spots are collected and the lowest (smallest Z) is chosen
// Sphere trace from camera forward a certain distance to regulate camera position while
// aiming up and down // TODO: elaborate
}
void AExoPlayerController::UpdateCoverStandHeight(float DeltaTime)
{
// if (FMath::IsNearlyEqual(CoverStandAlpha, TargetCoverStandAlpha, 0.01f))
// {
// return;
// }
CoverStandAlpha = FMath::Lerp(CoverStandAlpha, TargetCoverStandAlpha, DeltaTime * 5.0f);
//CoverStandAlpha = TargetCoverStandAlpha;
// BANDAID SOLUTION
const float NewZ = FMath::Lerp(
PlayerCharacter->CrouchedEyeHeight,
PlayerCharacter->StandingEyeHeight,
CoverStandAlpha
);
PlayerCharacter->CameraComponent->SetRelativeLocation(
FVector(0.0f, 0.0f, NewZ)
);
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(); bIsInCover = CheckForCover();
if (bIsInCover == false)
{
TargetCoverStandAlpha = 0.0f;
UpdateCoverStandHeight(GetWorld()->GetDeltaSeconds());
}
} }
void AExoPlayerController::DebugCoverSystem(bool show) void AExoPlayerController::DebugCoverSystem(bool show)

View File

@ -99,10 +99,6 @@ public:
AGunBase* SecondaryGunBase = nullptr; AGunBase* SecondaryGunBase = nullptr;
UStaticMeshComponent* SecondaryGunMesh = nullptr; UStaticMeshComponent* SecondaryGunMesh = nullptr;
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnADSEventSignature);
FOnADSEventSignature OnStartedADS;
FOnADSEventSignature OnStoppedADS;
private: private:
void ResetFireCooldown(); void ResetFireCooldown();
void ReloadCompleted(); void ReloadCompleted();

View File

@ -5,7 +5,7 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "Camera/CameraComponent.h" #include "Camera/CameraComponent.h"
#include "Characters/ExoCharacterBase.h" #include "Characters/ExoCharacterBase.h"
#include "Components/TimelineComponent.h" #include "Components/CapsuleComponent.h"
#include "ExoPlayerCharacter.generated.h" #include "ExoPlayerCharacter.generated.h"
class UInteractionComponent; class UInteractionComponent;
@ -20,7 +20,6 @@ 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;
@ -33,11 +32,8 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Camera") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Camera")
TObjectPtr<UCameraComponent> CameraComponent; TObjectPtr<UCameraComponent> CameraComponent;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly) UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Camera")
TObjectPtr<USceneComponent> CapsuleBottom; float StandingEyeHeight;
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;
@ -66,109 +62,21 @@ public:
UPROPERTY(EditAnywhere, Category = "Health") UPROPERTY(EditAnywhere, Category = "Health")
float CurrentHealth = 50.0f; float CurrentHealth = 50.0f;
/// Połowa wysokości kapsuły gracza podczas stania UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI")
UPROPERTY(EditAnywhere, BlueprintReadOnly) TSubclassOf<UUserWidget> PlayerHudClass;
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;
UPROPERTY(EditAnywhere)
TObjectPtr<UCurveFloat> CapsuleResizeCurve;
/// 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")
void CrouchCustom();
/// Próbuje wyjść z trybu kucania
UFUNCTION(BlueprintCallable, Category = "Movement")
void TryUnCrouchCustom();
DECLARE_MULTICAST_DELEGATE(FOnPlayerCrouchEvent);
FOnPlayerCrouchEvent OnPlayerCrouchStart;
FOnPlayerCrouchEvent OnPlayerCrouchStop;
UFUNCTION() UFUNCTION()
void AddHealthPoints(float addValue); void AddHealthPoints(float addValue);
UFUNCTION(BlueprintCallable, Category="Camera")
void SetEyePositionOffsetTarget(FVector LocationOffset);
UFUNCTION(BlueprintCallable, Category="Camera")
void SetEyeRoll(float RollValue);
UFUNCTION(BlueprintCallable)
FVector GetPlayerLocationAtFeet() const;
UFUNCTION(BlueprintCallable, Category="Camera")
void SetTargetEyeHeight(float NewEyeHeight, const bool bCapsuleRelative = false);
UFUNCTION(BlueprintCallable, Category="Camera")
float GetCurrentEyeHeight(const bool bCapsuleRelative = false) const;
UFUNCTION(BlueprintPure, Category="Camera")
float GetStandingEyeHeight(const bool bCapsuleRelative = false) const;
UFUNCTION(BlueprintPure, Category="Camera")
float GetCrouchingEyeHeight(const bool bCapsuleRelative = false) const;
UFUNCTION(BlueprintPure, Category="Movement")
bool IsCrouching() const;
protected: protected:
virtual void BeginPlay() override; virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
float MaxHealth = 100.0f; float MaxHealth = 100.0f;
UWBP_PlayerUI* PlayerHud; UWBP_PlayerUI* PlayerHud;
/** Wysokość kamery podczas kucania jest dostarczana przez Character.h*/
/** Wysokość kamery podczas stania <br>
* Też najwyższa wysokość na którą kamera może się wznieść
* podczas gameplaya
*/
UPROPERTY(EditAnywhere, Category="Camera")
float StandingEyeHeight;
UFUNCTION(BlueprintCallable)
float GetFootOffset();
private:
FVector TargetEyeLocationOffset;
FVector EyeLocationOffset;
float TargetEyeRoll;
float EyeRoll;
float TargetEyeHeight;
float EyeHeight;
FTimeline CrouchTimeline;
UFUNCTION()
void CrouchingUpdate(float Alpha);
UFUNCTION()
void CrouchingFinished();
void UpdateCameraHeight(float DeltaTime);
void ApplyCameraOffsets(float DeltaTime);
}; };

View File

@ -25,9 +25,6 @@ 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;
@ -56,9 +53,6 @@ protected:
UFUNCTION(BlueprintCallable, Category = "Input") UFUNCTION(BlueprintCallable, Category = "Input")
void PlayerStopCrouch(); // LCtrl\C\X void PlayerStopCrouch(); // LCtrl\C\X
UFUNCTION(BlueprintCallable, Category = "Movement")
void StartSlide();
UFUNCTION(BlueprintCallable, Category = "Input") UFUNCTION(BlueprintCallable, Category = "Input")
void ResetSlide(); void ResetSlide();
@ -101,9 +95,17 @@ protected:
UFUNCTION(BlueprintCallable, Category = "Cover System") UFUNCTION(BlueprintCallable, Category = "Cover System")
bool CheckForCover(); bool CheckForCover();
//DECLARE_MULTICAST_DELEGATE(FOnPlayerAimEvent); UFUNCTION(BlueprintCallable, Category = "Cover System")
void AdjustCameraWhileInCover();
// Cover System DEBUG UFUNCTION(BlueprintCallable, Category = "Cover System")
void UpdateCoverStandHeight(float DeltaTime);
void OnCoverTimer();
float MapAlphaToCoverStandHeight(float Alpha);
// DEBUG
UFUNCTION(Exec, Category = "Cover System") UFUNCTION(Exec, Category = "Cover System")
void DebugCoverSystem(bool show); void DebugCoverSystem(bool show);
bool bShowCoverSystemDebug = false; bool bShowCoverSystemDebug = false;
@ -144,9 +146,6 @@ protected:
UPROPERTY(EditAnywhere, Category = "Movement properties") UPROPERTY(EditAnywhere, Category = "Movement properties")
bool bIsSprinting = false; bool bIsSprinting = false;
UPROPERTY(EditAnywhere, Category = "Movement properties")
bool bIsSliding = false;
UPROPERTY(EditAnywhere, Category = "Input") UPROPERTY(EditAnywhere, Category = "Input")
TObjectPtr<UInputAction> ShootAction; TObjectPtr<UInputAction> ShootAction;
@ -177,41 +176,44 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character") UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character")
TObjectPtr<AExoPlayerCharacter> PlayerCharacter; TObjectPtr<AExoPlayerCharacter> PlayerCharacter;
// Czy postać gracza jest obecnie schowana za osłoną
UPROPERTY(EditAnywhere, Category = "Cover System")
bool bIsInCover = false;
/** 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;
/** Dystans na którym postać jest w stanie odnaleźć osłonę */ // Dystans na którym postać jest w stanie odnaleźć osłonę
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System")
float MaxDistanceFromCover = 50.0f; float MaxDistanceFromCover = 50.0f;
/** Używa wysokości oczu do określenia minimalnej wysokości przeszkody // Minimalna wysokość przeszkody którą można określić osłoną
* którą można określić osłoną UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System")
*/
UPROPERTY(EditAnywhere, Category = "Cover System")
bool bUseEyeHeight = true;
/** Minimalna wysokość przeszkody którą można określić osłoną */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System",
meta = (EditCondition = "!UseEyeHeight"))
float CoverObstacleMinHeight = 75.0f; float CoverObstacleMinHeight = 75.0f;
/** Maksymalna wysokość przeszkody którą można określić osłoną */ // Maksymalna wysokość przeszkody którą można określić osłoną
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System")
float CoverObstacleMaxHeight = 125.0f; float CoverObstacleMaxHeight = 125.0f;
/** Promień wolnej przestrzeni przez którą można się wychylić */ // Promień wolnej przestrzeni przez którą można się wychylić
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System")
float CoverAimWindowRadius = 2.0f; float CoverAimWindowRadius = 2.0f;
/** Dystans od kamery po wychyleniu który musi być wolny by dało się wychylić */ // Dystans od kamery po wychyleniu który musi być wolny by dało się wychylić
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cover System")
float CoverAimFreeDistance = 150.0f; float CoverAimFreeDistance = 150.0f;
/** Określa na jaki procent "Stania" postać może się podnieść podczas celowania /** Określa na jaki procent "Stania" postać może się podnieść podczas celowania
* zza osłony.<br> * zza osłony. 0 -> Nie podniesie się wogóle (jakby wychylanie się było wyłączone)
* 0 -> Nie podniesie się wogóle (jakby wychylanie się było wyłączone) <br>
* 1 -> Postać jest w stanie się podnieść do pełnej wysokości, tak jakby normalnie stała * 1 -> Postać jest w stanie się podnieść do pełnej wysokości, tak jakby normalnie stała
**/ **/
UPROPERTY(EditAnywhere, UPROPERTY(EditAnywhere,
@ -227,16 +229,10 @@ protected:
private: private:
UInteractionComponent* InteractionComponent; UInteractionComponent* InteractionComponent;
UShootingComponent* ShootingComponent; UShootingComponent* ShootingComponent;
float CalculateCoverAimOffset(); float CoverStandAlpha = 0.0f;
void OnCoverTimer();
FTimerHandle CoverCheckTimer; FTimerHandle CoverCheckTimer;
float MaxCoverAimHeight; float MaxCoverAimHeight;
float CoverAimHeightOffset;
// temporary
bool bWasSliding = false;
}; };