2025-02-12 19:10:23 +01:00
|
|
|
|
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "Player/ExoPlayerController.h"
|
|
|
|
|
|
#include "EnhancedInputComponent.h"
|
|
|
|
|
|
#include "EnhancedInputSubsystems.h"
|
2025-02-21 15:59:46 +01:00
|
|
|
|
#include "Characters/ExoPlayerCharacter.h"
|
2025-06-01 15:24:30 +02:00
|
|
|
|
#include "Components/CapsuleComponent.h"
|
2025-02-12 19:10:23 +01:00
|
|
|
|
#include "GameFramework/Character.h"
|
2025-02-20 18:00:26 +01:00
|
|
|
|
#include "GameFramework/CharacterMovementComponent.h"
|
2025-02-12 19:10:23 +01:00
|
|
|
|
|
|
|
|
|
|
AExoPlayerController::AExoPlayerController()
|
|
|
|
|
|
{
|
|
|
|
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::BeginPlay()
|
|
|
|
|
|
{
|
|
|
|
|
|
Super::BeginPlay();
|
|
|
|
|
|
check(InputContext);
|
2025-02-20 18:00:26 +01:00
|
|
|
|
|
2025-02-21 15:59:46 +01:00
|
|
|
|
PlayerCharacter = Cast<AExoPlayerCharacter>(GetPawn<ACharacter>());
|
|
|
|
|
|
check(PlayerCharacter);
|
|
|
|
|
|
|
2025-02-12 19:10:23 +01:00
|
|
|
|
UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
|
|
|
|
|
|
|
|
|
|
|
|
if (Subsystem)
|
|
|
|
|
|
{
|
|
|
|
|
|
Subsystem->AddMappingContext(InputContext, 0);
|
|
|
|
|
|
}
|
2025-06-01 15:24:30 +02:00
|
|
|
|
|
2025-05-22 21:32:39 +02:00
|
|
|
|
InteractionComponent = PlayerCharacter->InteractionComponent;
|
|
|
|
|
|
ShootingComponent = PlayerCharacter->ShootingComponent;
|
2025-02-22 23:31:23 +01:00
|
|
|
|
|
2025-03-07 11:11:22 +01:00
|
|
|
|
// Ustawianie w komponencie poruszania pr<70>dko<6B>ci zapisanej w characterze
|
2025-02-22 23:31:23 +01:00
|
|
|
|
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed;
|
2025-02-12 19:10:23 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-01 17:55:38 +02:00
|
|
|
|
void AExoPlayerController::PlayerTick(const float DeltaTime)
|
2025-02-12 19:10:23 +01:00
|
|
|
|
{
|
|
|
|
|
|
Super::PlayerTick(DeltaTime);
|
2025-05-22 21:32:39 +02:00
|
|
|
|
|
2025-06-01 17:55:38 +02:00
|
|
|
|
bIsCoverAiming = (PlayerCharacter->bIsInCover && PlayerCharacter->bIsAimingMode);
|
2025-06-01 15:24:30 +02:00
|
|
|
|
|
2025-06-01 17:55:38 +02:00
|
|
|
|
if (bIsCoverAiming)
|
2025-05-22 21:32:39 +02:00
|
|
|
|
{
|
2025-06-01 17:55:38 +02:00
|
|
|
|
CoverAimHeightOffset = CalculateCoverAimOffset();
|
|
|
|
|
|
PlayerCharacter->SetEyePositionOffsetTarget(FVector(0.f, 0.f, CoverAimHeightOffset));
|
2025-05-22 21:32:39 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-01 15:24:30 +02:00
|
|
|
|
// On screen cover state DEBUG
|
2025-05-22 21:32:39 +02:00
|
|
|
|
if (bShowCoverSystemDebug)
|
|
|
|
|
|
{
|
2025-06-01 15:24:30 +02:00
|
|
|
|
GEngine->AddOnScreenDebugMessage(2, -1, FColor::Red,
|
|
|
|
|
|
FString::Printf(TEXT("In cover: %hs"),
|
|
|
|
|
|
PlayerCharacter->bIsInCover ? "true" : "false")
|
|
|
|
|
|
);
|
2025-05-22 21:32:39 +02:00
|
|
|
|
}
|
2025-02-12 19:10:23 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::SetupInputComponent()
|
|
|
|
|
|
{
|
|
|
|
|
|
Super::SetupInputComponent();
|
|
|
|
|
|
|
|
|
|
|
|
UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent);
|
|
|
|
|
|
|
|
|
|
|
|
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AExoPlayerController::Move);
|
|
|
|
|
|
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AExoPlayerController::Look);
|
2025-02-17 15:28:18 +01:00
|
|
|
|
EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Triggered, this, &AExoPlayerController::Interact);
|
2025-02-20 18:00:26 +01:00
|
|
|
|
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerJump);
|
|
|
|
|
|
EnhancedInputComponent->BindAction(DodgeAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerDodge);
|
2025-02-22 23:31:23 +01:00
|
|
|
|
EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerStartCrouch);
|
|
|
|
|
|
EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerStopCrouch);
|
|
|
|
|
|
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerStartSprint);
|
|
|
|
|
|
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerStopSprint);
|
2025-02-21 20:42:52 +01:00
|
|
|
|
EnhancedInputComponent->BindAction(ShootAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerShoot);
|
2025-04-08 18:22:33 +02:00
|
|
|
|
EnhancedInputComponent->BindAction(ThrowAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerThrow);
|
2025-04-04 16:33:54 +02:00
|
|
|
|
EnhancedInputComponent->BindAction(AimAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerStartAim);
|
|
|
|
|
|
EnhancedInputComponent->BindAction(AimAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerStopAim);
|
2025-02-21 20:42:52 +01:00
|
|
|
|
EnhancedInputComponent->BindAction(MeleAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerMeleAttack);
|
|
|
|
|
|
EnhancedInputComponent->BindAction(ChangeWeaponAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerChangeWeapon);
|
2025-03-23 21:47:10 +01:00
|
|
|
|
EnhancedInputComponent->BindAction(SelectFirstWeaponAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerSelectFirstWeapon);
|
|
|
|
|
|
EnhancedInputComponent->BindAction(SelectSecondWeaponAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerSelectSecondWeapon);
|
2025-03-15 22:43:58 +01:00
|
|
|
|
EnhancedInputComponent->BindAction(DropWeaponAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerDropWeapon);
|
2025-02-21 20:42:52 +01:00
|
|
|
|
EnhancedInputComponent->BindAction(ReloadAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerReload);
|
2025-02-12 19:10:23 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::Move(const FInputActionValue& InputActionValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
const FVector2D InputAxisVector = InputActionValue.Get<FVector2D>();
|
|
|
|
|
|
const FRotator Rotation = GetControlRotation();
|
|
|
|
|
|
const FRotator YawRotation(0.f, Rotation.Yaw, 0.f);
|
|
|
|
|
|
|
|
|
|
|
|
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
|
|
|
|
|
|
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
|
|
|
|
|
|
|
|
|
|
|
|
if (PlayerCharacter)
|
|
|
|
|
|
{
|
|
|
|
|
|
PlayerCharacter->AddMovementInput(ForwardDirection, InputAxisVector.X);
|
|
|
|
|
|
PlayerCharacter->AddMovementInput(RightDirection, InputAxisVector.Y);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::Look(const FInputActionValue& InputActionValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
FVector2D InputAxisVector = InputActionValue.Get<FVector2D>();
|
|
|
|
|
|
|
|
|
|
|
|
AddYawInput(InputAxisVector.X);
|
|
|
|
|
|
AddPitchInput(InputAxisVector.Y);
|
|
|
|
|
|
}
|
2025-02-17 15:28:18 +01:00
|
|
|
|
|
|
|
|
|
|
|
2025-02-21 20:42:52 +01:00
|
|
|
|
void AExoPlayerController::Interact()
|
2025-02-17 15:28:18 +01:00
|
|
|
|
{
|
|
|
|
|
|
if (InteractionComponent->InteractedActor)
|
2025-03-15 20:17:03 +01:00
|
|
|
|
IInteractable::Execute_Interact(InteractionComponent->InteractedActor, PlayerCharacter);
|
2025-02-17 15:28:18 +01:00
|
|
|
|
}
|
2025-02-20 18:00:26 +01:00
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerJump()
|
|
|
|
|
|
{
|
2025-02-22 23:31:23 +01:00
|
|
|
|
PlayerCharacter->Jump();
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerDodge()
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(LogTemp, Error, TEXT("Player Dodge"));
|
|
|
|
|
|
|
|
|
|
|
|
if (PlayerCharacter->GetCharacterMovement()->IsFalling()) return;
|
|
|
|
|
|
|
2025-02-22 23:31:23 +01:00
|
|
|
|
if (PlayerCharacter->GetCharacterMovement()->IsCrouching()) return;
|
|
|
|
|
|
|
2025-02-20 18:00:26 +01:00
|
|
|
|
if (!CanDodge) return;
|
|
|
|
|
|
|
|
|
|
|
|
CanDodge = false;
|
|
|
|
|
|
|
|
|
|
|
|
FVector DodgeDirection = PlayerCharacter->GetVelocity().GetSafeNormal();
|
|
|
|
|
|
DodgeDirection.Z = 0.f;
|
|
|
|
|
|
|
|
|
|
|
|
if (DodgeDirection.IsNearlyZero())
|
|
|
|
|
|
DodgeDirection = PlayerCharacter->GetActorForwardVector();
|
|
|
|
|
|
|
2025-02-22 23:31:23 +01:00
|
|
|
|
PlayerCharacter->LaunchCharacter(DodgeDirection * PlayerCharacter->DodgeForce, true, true);
|
2025-02-20 18:00:26 +01:00
|
|
|
|
|
2025-02-22 23:31:23 +01:00
|
|
|
|
GetWorldTimerManager().SetTimer(DodgeCooldownTimer, this, &AExoPlayerController::ResetDodge, PlayerCharacter->DodgeCooldown, false);
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::ResetDodge()
|
|
|
|
|
|
{
|
|
|
|
|
|
CanDodge = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-22 23:31:23 +01:00
|
|
|
|
void AExoPlayerController::PlayerStartCrouch()
|
2025-02-20 18:00:26 +01:00
|
|
|
|
{
|
2025-04-18 15:14:43 +02:00
|
|
|
|
if (bIsSprinting)
|
|
|
|
|
|
{
|
|
|
|
|
|
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeedCrouched = PlayerCharacter->SlideSpeed;
|
2025-06-01 15:24:30 +02:00
|
|
|
|
PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->LowEyeHeightOffset);
|
2025-04-18 15:14:43 +02:00
|
|
|
|
GetWorldTimerManager().SetTimer(SlideCooldownTimer, this, &AExoPlayerController::ResetSlide, PlayerCharacter->SlideCooldown, false);
|
|
|
|
|
|
}
|
2025-06-01 17:55:38 +02:00
|
|
|
|
|
2025-06-01 15:24:30 +02:00
|
|
|
|
PlayerCharacter->CrouchCustom();
|
2025-05-22 21:32:39 +02:00
|
|
|
|
|
|
|
|
|
|
// Start checking for cover
|
2025-06-01 15:24:30 +02:00
|
|
|
|
PlayerCharacter->bIsInCover = CheckForCover();
|
2025-05-22 21:32:39 +02:00
|
|
|
|
GetWorld()->GetTimerManager().SetTimer(
|
|
|
|
|
|
CoverCheckTimer,
|
|
|
|
|
|
this,
|
|
|
|
|
|
&AExoPlayerController::OnCoverTimer,
|
|
|
|
|
|
CoverCheckRate,
|
|
|
|
|
|
true
|
|
|
|
|
|
);
|
2025-02-22 23:31:23 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerStopCrouch()
|
|
|
|
|
|
{
|
2025-06-01 17:55:38 +02:00
|
|
|
|
PlayerCharacter->TryUnCrouchCustom();
|
2025-05-22 21:32:39 +02:00
|
|
|
|
|
|
|
|
|
|
// Stop checking for cover
|
|
|
|
|
|
GetWorld()->GetTimerManager().ClearTimer(CoverCheckTimer);
|
2025-06-01 15:24:30 +02:00
|
|
|
|
PlayerCharacter->bIsInCover = false;
|
2025-02-22 23:31:23 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-18 15:14:43 +02:00
|
|
|
|
void AExoPlayerController::ResetSlide()
|
|
|
|
|
|
{
|
|
|
|
|
|
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeedCrouched = PlayerCharacter->CrouchSpeed;
|
2025-06-01 15:24:30 +02:00
|
|
|
|
PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->CrouchedEyeHeight);
|
2025-04-18 15:14:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-22 23:31:23 +01:00
|
|
|
|
void AExoPlayerController::PlayerStartSprint()
|
|
|
|
|
|
{
|
2025-04-04 19:53:32 +02:00
|
|
|
|
if (!PlayerCharacter->bIsAimingMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(LogTemp, Display, TEXT("Start sprint"));
|
2025-02-22 23:31:23 +01:00
|
|
|
|
|
2025-04-18 15:14:43 +02:00
|
|
|
|
bIsSprinting = true;
|
2025-04-04 19:53:32 +02:00
|
|
|
|
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->SprintSpeed;
|
|
|
|
|
|
}
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-22 23:31:23 +01:00
|
|
|
|
void AExoPlayerController::PlayerStopSprint()
|
2025-02-20 18:00:26 +01:00
|
|
|
|
{
|
2025-04-04 19:53:32 +02:00
|
|
|
|
if (!PlayerCharacter->bIsAimingMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(LogTemp, Display, TEXT("Stop sprint"));
|
2025-02-20 18:00:26 +01:00
|
|
|
|
|
2025-04-18 15:14:43 +02:00
|
|
|
|
bIsSprinting = false;
|
2025-04-04 19:53:32 +02:00
|
|
|
|
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed;
|
|
|
|
|
|
}
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerShoot()
|
|
|
|
|
|
{
|
2025-02-21 20:42:52 +01:00
|
|
|
|
ShootingComponent->Shoot();
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-08 18:22:33 +02:00
|
|
|
|
void AExoPlayerController::PlayerThrow()
|
|
|
|
|
|
{
|
|
|
|
|
|
ShootingComponent->Throw();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-04 16:33:54 +02:00
|
|
|
|
void AExoPlayerController::PlayerStartAim()
|
2025-02-20 18:00:26 +01:00
|
|
|
|
{
|
2025-04-04 16:33:54 +02:00
|
|
|
|
ShootingComponent->StartAiming();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerStopAim()
|
|
|
|
|
|
{
|
|
|
|
|
|
ShootingComponent->StopAiming();
|
2025-06-01 15:24:30 +02:00
|
|
|
|
if (PlayerCharacter->bIsInCover)
|
|
|
|
|
|
{
|
2025-06-01 17:55:38 +02:00
|
|
|
|
PlayerCharacter->SetEyePositionOffsetTarget(FVector(0, 0, 0));
|
2025-06-01 15:24:30 +02:00
|
|
|
|
}
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerMeleAttack()
|
|
|
|
|
|
{
|
2025-03-22 13:46:05 +01:00
|
|
|
|
ShootingComponent->MeleAttack();
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerChangeWeapon()
|
|
|
|
|
|
{
|
2025-03-23 21:47:10 +01:00
|
|
|
|
ShootingComponent->SwitchGun();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerSelectFirstWeapon()
|
|
|
|
|
|
{
|
|
|
|
|
|
ShootingComponent->SelectGun(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::PlayerSelectSecondWeapon()
|
|
|
|
|
|
{
|
|
|
|
|
|
ShootingComponent->SelectGun(false);
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-15 22:43:58 +01:00
|
|
|
|
void AExoPlayerController::PlayerDropWeapon()
|
|
|
|
|
|
{
|
|
|
|
|
|
ShootingComponent->DropGun();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-20 18:00:26 +01:00
|
|
|
|
void AExoPlayerController::PlayerReload()
|
|
|
|
|
|
{
|
2025-02-22 01:28:07 +01:00
|
|
|
|
ShootingComponent->Reload();
|
2025-02-20 18:00:26 +01:00
|
|
|
|
}
|
2025-05-22 21:32:39 +02:00
|
|
|
|
|
|
|
|
|
|
bool AExoPlayerController::CheckForCover()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Do a simple 8-directional line trace
|
|
|
|
|
|
FVector TraceDirection = PlayerCharacter->GetActorForwardVector();
|
|
|
|
|
|
FVector TraceStart = PlayerCharacter->GetActorLocation();
|
2025-06-01 15:24:30 +02:00
|
|
|
|
TraceStart.Z += bUseEyeHeight ?
|
|
|
|
|
|
PlayerCharacter->GetCrouchingEyeHeight(true)
|
|
|
|
|
|
:
|
|
|
|
|
|
PlayerCharacter->GetPlayerLocationAtFeet().Z + CoverObstacleMinHeight;
|
2025-05-22 21:32:39 +02:00
|
|
|
|
FCollisionQueryParams QueryParams;
|
|
|
|
|
|
QueryParams.AddIgnoredActor(PlayerCharacter);
|
|
|
|
|
|
|
|
|
|
|
|
TArray<FHitResult> ValidHits;
|
|
|
|
|
|
for (int i = 0; i <= 8; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Trace for possible cover at set distance
|
|
|
|
|
|
FHitResult Hit;
|
|
|
|
|
|
FVector TraceEnd = TraceStart + (TraceDirection * MaxDistanceFromCover);
|
|
|
|
|
|
GetWorld()->LineTraceSingleByChannel(
|
|
|
|
|
|
Hit,
|
|
|
|
|
|
TraceStart,
|
|
|
|
|
|
TraceEnd,
|
|
|
|
|
|
CoverTraceChannel,
|
|
|
|
|
|
QueryParams
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (bShowCoverSystemDebug)
|
|
|
|
|
|
{
|
|
|
|
|
|
// DEBUG
|
|
|
|
|
|
DrawDebugLine(GetWorld(), TraceStart,TraceEnd,
|
|
|
|
|
|
Hit.bBlockingHit ? FColor::Blue : FColor::Red,
|
|
|
|
|
|
false, 5.0f, 0, 1.0f);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Hit.bBlockingHit == true) {
|
|
|
|
|
|
// Check if this particular hit isn't against a wall (>CoverMaxHeight)
|
|
|
|
|
|
|
|
|
|
|
|
FHitResult SphereHit;
|
2025-06-01 15:24:30 +02:00
|
|
|
|
FVector SpherePosition = Hit.ImpactPoint;
|
|
|
|
|
|
SpherePosition.Z = PlayerCharacter->GetPlayerLocationAtFeet().Z + CoverObstacleMaxHeight + CoverAimWindowRadius;
|
|
|
|
|
|
|
2025-05-22 21:32:39 +02:00
|
|
|
|
GetWorld()->SweepSingleByChannel(
|
|
|
|
|
|
SphereHit,
|
|
|
|
|
|
SpherePosition,
|
|
|
|
|
|
SpherePosition,
|
|
|
|
|
|
FQuat::Identity,
|
|
|
|
|
|
CoverTraceChannel,
|
|
|
|
|
|
FCollisionShape::MakeSphere(CoverAimWindowRadius),
|
|
|
|
|
|
QueryParams);
|
|
|
|
|
|
|
|
|
|
|
|
if (bShowCoverSystemDebug)
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawDebugSphere(GetWorld(), SphereHit.TraceStart, CoverAimWindowRadius, 8,
|
|
|
|
|
|
Hit.bBlockingHit ? FColor::Blue : FColor::Red,
|
|
|
|
|
|
false, 5.0f, 0, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SphereHit.bBlockingHit == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
ValidHits.Add(Hit);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Rotate trace to search in another direction next time
|
|
|
|
|
|
TraceDirection = TraceDirection.RotateAngleAxis(45, FVector(0, 0, 1));
|
|
|
|
|
|
//UE_LOG(LogTemp, Display, TEXT("Check Cover %d"), i);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ValidHits.Num() > 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-01 15:24:30 +02:00
|
|
|
|
float AExoPlayerController::CalculateCoverAimOffset()
|
2025-05-22 21:32:39 +02:00
|
|
|
|
{
|
2025-06-01 15:24:30 +02:00
|
|
|
|
// Nic nie rób jak nie znajdujesz się za osłoną
|
|
|
|
|
|
if (!PlayerCharacter->bIsInCover)
|
2025-05-22 21:32:39 +02:00
|
|
|
|
{
|
2025-06-01 15:24:30 +02:00
|
|
|
|
return 0.f;
|
2025-05-22 21:32:39 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-01 15:57:17 +02:00
|
|
|
|
// Oblicz maksymalną wysokość, na którą można wychylić się znad osłony
|
|
|
|
|
|
MaxCoverAimHeight = PlayerCharacter->GetStandingEyeHeight() * CoverAimStandFactor;
|
2025-06-01 15:24:30 +02:00
|
|
|
|
|
2025-05-22 21:32:39 +02:00
|
|
|
|
FCollisionQueryParams QueryParams;
|
|
|
|
|
|
QueryParams.AddIgnoredActor(PlayerCharacter);
|
|
|
|
|
|
TEnumAsByte<ECollisionChannel> ObstacleTraceChannel = ECC_WorldStatic;
|
|
|
|
|
|
|
|
|
|
|
|
FHitResult Hit;
|
|
|
|
|
|
bool bFreeSpace = false;
|
|
|
|
|
|
|
2025-06-01 17:55:38 +02:00
|
|
|
|
FVector ObstacleTraceStart = PlayerCharacter->GetPlayerLocationAtFeet();
|
2025-06-01 15:57:17 +02:00
|
|
|
|
ObstacleTraceStart.Z += PlayerCharacter->CrouchedEyeHeight;
|
2025-06-01 17:55:38 +02:00
|
|
|
|
FVector ObstacleTraceEnd = ObstacleTraceStart + PlayerCameraManager->GetCameraRotation().Vector() * CoverAimFreeDistance;
|
2025-06-01 15:24:30 +02:00
|
|
|
|
|
|
|
|
|
|
float SafeCoverAimZOffset = 0.f;
|
2025-06-01 15:57:17 +02:00
|
|
|
|
while (SafeCoverAimZOffset < MaxCoverAimHeight)
|
2025-05-22 21:32:39 +02:00
|
|
|
|
{
|
2025-06-01 15:24:30 +02:00
|
|
|
|
ObstacleTraceStart.Z += SafeCoverAimZOffset;
|
|
|
|
|
|
ObstacleTraceEnd.Z += SafeCoverAimZOffset;
|
2025-05-22 21:32:39 +02:00
|
|
|
|
|
|
|
|
|
|
GetWorld()->SweepSingleByChannel(
|
2025-06-01 15:24:30 +02:00
|
|
|
|
Hit,
|
|
|
|
|
|
ObstacleTraceStart,
|
|
|
|
|
|
ObstacleTraceEnd,
|
|
|
|
|
|
FQuat::Identity,
|
|
|
|
|
|
ObstacleTraceChannel,
|
|
|
|
|
|
FCollisionShape::MakeSphere(CoverAimWindowRadius),
|
|
|
|
|
|
QueryParams
|
|
|
|
|
|
);
|
2025-05-22 21:32:39 +02:00
|
|
|
|
|
2025-06-01 15:24:30 +02:00
|
|
|
|
if (Hit.bBlockingHit == true)
|
2025-05-22 21:32:39 +02:00
|
|
|
|
{
|
2025-06-01 15:24:30 +02:00
|
|
|
|
// Increment check height every failed iteration
|
|
|
|
|
|
SafeCoverAimZOffset += 0.2f;
|
2025-05-22 21:32:39 +02:00
|
|
|
|
}
|
2025-06-01 15:24:30 +02:00
|
|
|
|
else
|
2025-05-22 21:32:39 +02:00
|
|
|
|
{
|
2025-06-01 15:24:30 +02:00
|
|
|
|
// Break the loop if free space found
|
2025-05-22 21:32:39 +02:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-01 15:57:17 +02:00
|
|
|
|
|
|
|
|
|
|
const float FinalHitHeight = Hit.TraceStart.Z - PlayerCharacter->GetPlayerLocationAtFeet().Z;
|
2025-06-01 15:24:30 +02:00
|
|
|
|
// If this is true that means that free space was found
|
2025-06-01 15:57:17 +02:00
|
|
|
|
if (FinalHitHeight <= MaxCoverAimHeight)
|
2025-05-22 21:32:39 +02:00
|
|
|
|
{
|
2025-06-01 17:55:38 +02:00
|
|
|
|
PlayerCharacter->bIsCrouched = false;
|
2025-06-01 15:24:30 +02:00
|
|
|
|
//// DEBUG ////
|
2025-05-22 21:32:39 +02:00
|
|
|
|
if (bShowCoverSystemDebug)
|
|
|
|
|
|
{
|
2025-06-01 15:24:30 +02:00
|
|
|
|
DrawDebugLine(GetWorld(), Hit.TraceStart, Hit.TraceEnd, FColor::Purple);
|
2025-05-22 21:32:39 +02:00
|
|
|
|
}
|
2025-06-01 15:24:30 +02:00
|
|
|
|
//////////////
|
|
|
|
|
|
|
2025-06-01 15:57:17 +02:00
|
|
|
|
return FinalHitHeight - PlayerCharacter->CrouchedEyeHeight;// +
|
2025-06-01 15:24:30 +02:00
|
|
|
|
//PlayerCharacter->CrouchedEyeHeight - PlayerCharacter->GetCurrentEyeHeight();
|
2025-05-22 21:32:39 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-01 15:24:30 +02:00
|
|
|
|
// Return 0 offset if no free space to aim was found
|
2025-06-01 17:55:38 +02:00
|
|
|
|
//return 0.f;
|
|
|
|
|
|
return MaxCoverAimHeight - PlayerCharacter->CrouchedEyeHeight;
|
2025-05-22 21:32:39 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::OnCoverTimer()
|
|
|
|
|
|
{
|
2025-06-01 15:24:30 +02:00
|
|
|
|
PlayerCharacter->bIsInCover = CheckForCover();
|
2025-05-22 21:32:39 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AExoPlayerController::DebugCoverSystem(bool show)
|
|
|
|
|
|
{
|
|
|
|
|
|
bShowCoverSystemDebug = show;
|
|
|
|
|
|
}
|