247 lines
7.4 KiB
C++
247 lines
7.4 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "BaseWeaponClass.h"
|
|
|
|
#include "AIHelpers.h"
|
|
#include "EndlessVendetta/EndlessVendettaCharacter.h"
|
|
#include "Kismet/KismetMathLibrary.h"
|
|
#include "Components/CapsuleComponent.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "Engine/DamageEvents.h"
|
|
#include "EndlessVendetta/AI/EnemyCharacter.h"
|
|
|
|
|
|
// Sets default values
|
|
ABaseWeaponClass::ABaseWeaponClass()
|
|
{
|
|
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
}
|
|
|
|
// Called when the game starts or when spawned
|
|
void ABaseWeaponClass::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
collisionParams.AddIgnoredActor(playerInWorld);
|
|
collisionParams.AddIgnoredActor(this);
|
|
|
|
// Attempt to find the player character
|
|
APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
|
|
playerInWorld = Cast<AEndlessVendettaCharacter>(PlayerController->GetCharacter());
|
|
|
|
endlessVendettaChar = Cast<AEndlessVendettaCharacter>(playerInWorld);
|
|
|
|
for (UActorComponent* actorComp : playerInWorld->GetComponentsByTag(UArrowComponent::StaticClass(), FName("GunStart")))
|
|
{
|
|
GunStartArrow = Cast<UArrowComponent>(actorComp);
|
|
break;
|
|
}
|
|
|
|
if (!playerControllerRef)
|
|
{
|
|
playerControllerRef = UGameplayStatics::GetPlayerController(GetWorld(), 0);
|
|
}
|
|
|
|
originalMagnitude = recoilMagnitude;
|
|
originalMaxAngleLeft = recoilMaxAngleLeft;
|
|
originalMaxAngleRight = recoilMaxAngleRight;
|
|
originalMinMultiplier = recoilMinMultiplier;
|
|
|
|
currentAmmoCount = MagazineSize;
|
|
|
|
UE_LOG(LogTemp, Display, TEXT("crnnt ammo: %d"), MagazineSize);
|
|
}
|
|
|
|
|
|
// Called every frame
|
|
void ABaseWeaponClass::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
|
|
if (playerInWorld)
|
|
{
|
|
ApplyRecoil(DeltaTime);
|
|
}
|
|
if (currentPitch < 0 && bStopShooting)
|
|
{
|
|
float increment = currentPitch * DeltaTime * 8;
|
|
currentPitch -= increment;
|
|
playerInWorld->AddControllerPitchInput(-increment);
|
|
}
|
|
}
|
|
|
|
|
|
// Recoil Handling ////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void ABaseWeaponClass::GenerateRecoilVector()
|
|
{
|
|
float angle = FMath::RandRange(recoilMaxAngleLeft, -recoilMaxAngleRight); //randomg recoil vector angle between left and right
|
|
float recMag = recoilMagnitude * 252.f; //converting degrees to controller units
|
|
float tempMag = -FMath::RandRange(recMag * recoilMinMultiplier, recMag); // recoil magnitude
|
|
|
|
recoilResultYaw = FMath::Sin(FMath::DegreesToRadians(angle));
|
|
recoilResultPitch = FMath::Cos(FMath::DegreesToRadians(angle));
|
|
|
|
if (bulletCountShoot >= howMnyShotsTillRclStop)
|
|
{
|
|
recoilResultPitch = 0;
|
|
}
|
|
//scaling direction to magnitude
|
|
recoilResultPitch *= -tempMag;
|
|
recoilResultYaw *= tempMag;
|
|
|
|
//reset recoil to 0 of curve
|
|
recoilTime = 0;
|
|
}
|
|
|
|
void ABaseWeaponClass::ApplyRecoil(float DeltaTime)
|
|
{
|
|
if (recoilTime < 0.3)
|
|
{
|
|
float amplitude = RecoilCurve->GetFloatValue(recoilTime); //get current value of curve in time
|
|
recoilTime += DeltaTime;
|
|
if (bulletCountShoot <= 3)
|
|
{
|
|
playerInWorld->AddControllerPitchInput(GetRecoilPitch(amplitude, recoilTime));
|
|
currentPitch += GetRecoilPitch(amplitude,recoilTime);
|
|
}
|
|
playerInWorld->AddControllerPitchInput(FMath::RandRange(-5 * DeltaTime, 5* DeltaTime));
|
|
GunStartArrow->AddRelativeRotation(FRotator(-GetRecoilPitch(amplitude, recoilTime), 0, 0));
|
|
playerInWorld->AddControllerYawInput(GetRecoilYaw(amplitude, recoilTime));
|
|
UpdateSamples(amplitude, recoilTime);
|
|
}
|
|
}
|
|
|
|
|
|
void ABaseWeaponClass::nullSamples()
|
|
{
|
|
recoilCurvet = 0;
|
|
recoilCurvez1 = 0;
|
|
}
|
|
|
|
float ABaseWeaponClass::GetRecoilPitch(float Amp, float Time)
|
|
{
|
|
//Using the trapez method and we are getting the surface under the curve, each trapezoid consist of square and right triangle
|
|
float lower = recoilCurvez1 < Amp ? recoilCurvez1 : Amp; //get which point is common for both triangle and square of trapezoid
|
|
//lower point
|
|
float mult = (Time - recoilCurvet) * lower; //getting surface of square
|
|
mult += (Time - recoilCurvet) * (Amp - recoilCurvez1) / 2.0f; //getting and adding surface of triangle
|
|
return (recoilResultPitch * mult) / playerControllerRef->InputPitchScale_DEPRECATED; //calculating and return recoil force for current frame
|
|
}
|
|
|
|
|
|
//Same as getrecoilpitch
|
|
float ABaseWeaponClass::GetRecoilYaw(float Amp, float Time)
|
|
{
|
|
float lower = recoilCurvez1 < Amp ? recoilCurvez1 : Amp;
|
|
float mult = (Time - recoilCurvet) * lower;
|
|
|
|
mult += (Time - recoilCurvet) * (Amp - recoilCurvez1) / 2.0f;
|
|
return (recoilResultYaw * mult) / playerControllerRef->InputYawScale_DEPRECATED;
|
|
}
|
|
|
|
void ABaseWeaponClass::UpdateSamples(float Amp, float Time)
|
|
{
|
|
recoilCurvez1 = Amp;
|
|
recoilCurvet = Time;
|
|
}
|
|
|
|
// Fire handling //////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void ABaseWeaponClass::ClickDetectionTimer()
|
|
{
|
|
GetWorldTimerManager().SetTimer(timerHandle, this, &ABaseWeaponClass::Fire, 1 / FireRate, false);
|
|
}
|
|
|
|
void ABaseWeaponClass::CancelFire()
|
|
{
|
|
GetWorldTimerManager().ClearTimer(timerHandle);
|
|
if (bulletCountShoot <= 0) return;
|
|
UE_LOG(LogTemp, Display, TEXT("FireCancelled"));
|
|
bulletCountShoot = 0;
|
|
GunStartArrow->SetRelativeRotation(FRotator(0));
|
|
//playerInWorld->GetController()->SetControlRotation(FRotator(0, playerInWorld->GetActorRotation().Yaw, playerInWorld->GetActorRotation().Roll));
|
|
bStopShooting = true;
|
|
nullSamples();
|
|
}
|
|
|
|
void ABaseWeaponClass::Fire()
|
|
{
|
|
if(currentAmmoCount > 0)
|
|
{
|
|
//do damage fallof based off distance
|
|
traceStart = GunStartArrow->GetComponentLocation();
|
|
traceEnd = traceStart + (GunStartArrow->GetForwardVector() * BulletDistance);
|
|
if (GetWorldTimerManager().IsTimerActive(timerHandle)) return;
|
|
GetWorld()->LineTraceSingleByChannel(outHit, traceStart, traceEnd, ECC_Visibility, collisionParams);
|
|
DrawDebugLine(this->GetWorld(), traceStart, traceEnd, FColor::Black , false, 0.2f, 0U, 0.2f);
|
|
playerControllerRef->PlayerCameraManager->StartCameraShake(CameraShakeClass, 1);
|
|
currentAmmoCount -= 1;
|
|
GenerateRecoilVector();
|
|
ClickDetectionTimer();
|
|
bulletCountShoot += 1;
|
|
bStopShooting = false;
|
|
if (outHit.bBlockingHit)
|
|
{
|
|
if (!Cast<AAICharacter>(outHit.GetActor())) return;
|
|
Cast<AAICharacter>(outHit.GetActor())->TakeDamage(WeaponDamage, FPointDamageEvent(), GetWorld()->GetFirstPlayerController(), this);
|
|
}
|
|
}
|
|
else if(currentAmmoCount <= 0)
|
|
{
|
|
UE_LOG(LogTemp, Display, TEXT("No ammo, Ammo count: %d"), currentAmmoCount);
|
|
}
|
|
|
|
}
|
|
|
|
void ABaseWeaponClass::WeaponScopedFire()
|
|
{
|
|
if (endlessVendettaChar->bIsScoped)
|
|
{
|
|
recoilMagnitude = scopedRecoilMag;
|
|
recoilMaxAngleLeft = scopedMaxAngleLeft;
|
|
recoilMaxAngleRight = scopedMaxAngleRight;
|
|
recoilMinMultiplier = scopedMinMultiplier;
|
|
|
|
}
|
|
else
|
|
{
|
|
recoilMagnitude = originalMagnitude;
|
|
recoilMaxAngleLeft = originalMaxAngleLeft;
|
|
recoilMaxAngleRight = originalMaxAngleRight;
|
|
recoilMinMultiplier = originalMinMultiplier;
|
|
}
|
|
}
|
|
|
|
void ABaseWeaponClass::ReloadTimer()
|
|
{
|
|
GetWorldTimerManager().SetTimer(reloadTimerHandle, this, &ABaseWeaponClass::WeaponReload, TimeToReload, false);
|
|
ShowReloadingWidget();
|
|
}
|
|
|
|
void ABaseWeaponClass::WeaponReload()
|
|
{
|
|
if(MagazineSize >= currentAmmoCount)
|
|
{
|
|
UE_LOG(LogTemp, Display, TEXT("Weapon Reloading: mag size: %d"), MagazineSize);
|
|
currentAmmoCount = MagazineSize;
|
|
endlessVendettaChar->bIsReloading = false;
|
|
HideReloadingWidget();
|
|
}
|
|
}
|
|
|
|
void ABaseWeaponClass::Interact()
|
|
{
|
|
GLog->Log("Interact Called");
|
|
}
|
|
|
|
void ABaseWeaponClass::InteractPrompt()
|
|
{
|
|
WeaponStatsPopUp();
|
|
UE_LOG(LogTemp, Warning, TEXT("InteractPrompt setup"))
|
|
}
|
|
|
|
|
|
|
|
|