218 lines
6.5 KiB
C++
218 lines
6.5 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
||
|
||
|
||
#include "Characters/Components/ShootingComponent.h"
|
||
|
||
// Sets default values for this component's properties
|
||
UShootingComponent::UShootingComponent()
|
||
{
|
||
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
||
// off to improve performance if you don't need them.
|
||
PrimaryComponentTick.bCanEverTick = true;
|
||
|
||
// ...
|
||
}
|
||
|
||
|
||
// Called when the game starts
|
||
void UShootingComponent::BeginPlay()
|
||
{
|
||
Super::BeginPlay();
|
||
|
||
PlayerCharacter = Cast<AExoPlayerCharacter>(GetOwner());
|
||
CameraManager = GetWorld()->GetFirstPlayerController()->PlayerCameraManager;
|
||
|
||
DefaultFOV = CameraManager->GetFOVAngle();
|
||
TargetFOV = DefaultFOV;
|
||
}
|
||
|
||
void UShootingComponent::Shoot()
|
||
{
|
||
if (!IsValid(CurrentGun) || CurrentGun->CurrentAmmo == 0 || bIsReloading || !bCanShoot) return;
|
||
|
||
bCanShoot = false;
|
||
CurrentGun->CurrentAmmo--;
|
||
|
||
AActor* HitActor = ExecuteLineTrace(CurrentGun->MaxRange);
|
||
if (HitActor)
|
||
{
|
||
IDamageable::Execute_TakeDamage(HitActor, CurrentGun->DamageValue);
|
||
|
||
UE_LOG(LogTemp, Display, TEXT("Shoot. Ammo: %d/%d"), CurrentGun->CurrentAmmo, CurrentGun->MaxAmmo); // Docelowo tutaj wywołanie UI aktualizujące stan ammo
|
||
}
|
||
|
||
PlayerCharacter->GetWorldTimerManager().SetTimer(ShootCooldownTimer, this, &UShootingComponent::ResetFireCooldown, CurrentGun->FireRateCooldown, false);
|
||
|
||
// Odrzut
|
||
float RecoilPitch = FMath::RandRange(-1.0f, -0.5f);
|
||
float RecoilYaw = FMath::RandRange(-0.5f, 0.5f);
|
||
|
||
PlayerCharacter->AddControllerPitchInput(RecoilPitch * CurrentGun->RecoilForceMultiplier);
|
||
PlayerCharacter->AddControllerYawInput(RecoilYaw * CurrentGun->RecoilForceMultiplier);
|
||
}
|
||
|
||
void UShootingComponent::MeleAttack()
|
||
{
|
||
AActor* HitActor = ExecuteLineTrace(MeleRange);
|
||
if (HitActor)
|
||
{
|
||
IDamageable::Execute_TakeDamage(HitActor, MeleDamageValue);
|
||
}
|
||
}
|
||
|
||
AActor* UShootingComponent::ExecuteLineTrace(float LineRange)
|
||
{
|
||
FVector ForwardVector = PlayerCharacter->GetActorForwardVector();
|
||
FVector ViewLocation;
|
||
FRotator ViewRotation;
|
||
PlayerCharacter->GetController()->GetPlayerViewPoint(ViewLocation, ViewRotation);
|
||
|
||
FVector EndVector = ViewLocation + ForwardVector * LineRange;
|
||
|
||
FHitResult Hit;
|
||
FCollisionQueryParams QueryParams;
|
||
QueryParams.AddIgnoredActor(PlayerCharacter);
|
||
|
||
// DEBUG
|
||
if (bShowDebugLine)
|
||
DrawDebugLine(GetWorld(), ViewLocation, EndVector, FColor::Red, false, 1.0f, 0, 1.0f);
|
||
|
||
if (GetWorld()->LineTraceSingleByChannel(Hit, ViewLocation, EndVector, ECC_Visibility, QueryParams) &&
|
||
IsValid(Hit.GetActor()) && Hit.GetActor()->Implements<UDamageable>())
|
||
{
|
||
return Hit.GetActor();
|
||
}
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
void UShootingComponent::Reload()
|
||
{
|
||
if (!IsValid(CurrentGun) || bIsReloading) return;
|
||
|
||
bIsReloading = true;
|
||
StopAiming();
|
||
|
||
CurrentGun->CurrentAmmo = CurrentGun->MaxAmmo;
|
||
PlayerCharacter->GetWorldTimerManager().SetTimer(ReloadTimer, this, &UShootingComponent::ReloadCompleted, CurrentGun->ReloadTime, false);
|
||
|
||
UE_LOG(LogTemp, Display, TEXT("Reloaded. Ammo: %d/%d"), CurrentGun->CurrentAmmo, CurrentGun->MaxAmmo); // Docelowo tutaj wywo<77>anie UI aktualizuj<75>ce stan ammo
|
||
}
|
||
|
||
void UShootingComponent::PickUpGun(AGunBase* gunItem)
|
||
{
|
||
if (IsValid(CurrentGun) && IsValid(SecondaryGun))
|
||
DropGun();
|
||
|
||
AGunBase* NewGun = NewObject<AGunBase>();
|
||
|
||
NewGun->MaxRange = gunItem->MaxRange;
|
||
NewGun->DamageValue = gunItem->DamageValue;
|
||
NewGun->FireRateCooldown = gunItem->FireRateCooldown;
|
||
NewGun->RecoilForceMultiplier = gunItem->RecoilForceMultiplier;
|
||
NewGun->ReloadTime = gunItem->ReloadTime;
|
||
NewGun->CurrentAmmo = gunItem->CurrentAmmo;
|
||
NewGun->MaxAmmo = gunItem->MaxAmmo;
|
||
NewGun->SceneItemClass = gunItem->GetClass();
|
||
|
||
if (IsValid(CurrentGun))
|
||
SecondaryGun = NewGun;
|
||
else
|
||
CurrentGun = NewGun;
|
||
}
|
||
|
||
void UShootingComponent::DropGun()
|
||
{
|
||
if (!IsValid(CurrentGun)) return;
|
||
|
||
StopAiming();
|
||
|
||
FVector ForwardVector = PlayerCharacter->GetActorForwardVector();
|
||
FVector PlayerPos = PlayerCharacter->GetActorLocation();
|
||
FVector DroppedGunPos = PlayerPos + (ForwardVector * DropGunRange);
|
||
|
||
FTransform DroppedGunTransform = PlayerCharacter->GetActorTransform();
|
||
DroppedGunTransform.SetLocation(DroppedGunPos);
|
||
|
||
AGunBase* DroppedGun = GetWorld()->SpawnActor<AGunBase>(CurrentGun->SceneItemClass, DroppedGunTransform);
|
||
|
||
if (DroppedGun)
|
||
{
|
||
DroppedGun->MaxRange = CurrentGun->MaxRange;
|
||
DroppedGun->DamageValue = CurrentGun->DamageValue;
|
||
DroppedGun->FireRateCooldown = CurrentGun->FireRateCooldown;
|
||
DroppedGun->RecoilForceMultiplier = CurrentGun->RecoilForceMultiplier;
|
||
DroppedGun->ReloadTime = CurrentGun->ReloadTime;
|
||
DroppedGun->CurrentAmmo = CurrentGun->CurrentAmmo;
|
||
DroppedGun->MaxAmmo = CurrentGun->MaxAmmo;
|
||
|
||
CurrentGun->Destroy();
|
||
CurrentGun = nullptr;
|
||
}
|
||
}
|
||
|
||
void UShootingComponent::ResetFireCooldown()
|
||
{
|
||
bCanShoot = true;
|
||
}
|
||
|
||
void UShootingComponent::ReloadCompleted()
|
||
{
|
||
bIsReloading = false;
|
||
}
|
||
|
||
void UShootingComponent::SelectGun(bool bSelectFirstSlot)
|
||
{
|
||
if (bSelectFirstSlot != bIsFirstGunSelected)
|
||
SwitchGun();
|
||
}
|
||
|
||
void UShootingComponent::SwitchGun()
|
||
{
|
||
AGunBase* temp = CurrentGun;
|
||
CurrentGun = SecondaryGun;
|
||
SecondaryGun = temp;
|
||
|
||
bIsFirstGunSelected = !bIsFirstGunSelected;
|
||
StopAiming();
|
||
|
||
// Debug info
|
||
if (bIsFirstGunSelected)
|
||
{
|
||
UE_LOG(LogTemp, Display, TEXT("Zmiana broni na broń 1"));
|
||
}
|
||
else
|
||
{
|
||
UE_LOG(LogTemp, Display, TEXT("Zmiana broni na broń 2"));
|
||
}
|
||
}
|
||
|
||
void UShootingComponent::StartAiming()
|
||
{
|
||
if (IsValid(CurrentGun))
|
||
{
|
||
PlayerCharacter->bIsAimingMode = true;
|
||
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed * AimingMoveSpeedScale;
|
||
|
||
TargetFOV = CurrentGun->AimingFOV;
|
||
}
|
||
}
|
||
|
||
void UShootingComponent::StopAiming()
|
||
{
|
||
PlayerCharacter->bIsAimingMode = false;
|
||
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed;
|
||
|
||
TargetFOV = DefaultFOV;
|
||
}
|
||
|
||
// Called every frame
|
||
void UShootingComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||
{
|
||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||
|
||
float CurrentFOV = CameraManager->GetFOVAngle();
|
||
float NewFOV = FMath::FInterpTo(CurrentFOV, TargetFOV, DeltaTime, AimingAnimationSpeed);
|
||
CameraManager->SetFOV(NewFOV);
|
||
}
|