blaster/Source/Blaster/Components/CombatComponent.cpp

303 lines
7.8 KiB
C++
Raw Normal View History

2022-04-30 11:09:28 +00:00
// Fill out your copyright notice in the Description page of Project Settings.
#include "CombatComponent.h"
#include "Blaster/Character/BlasterCharacter.h"
2022-05-05 15:57:57 +00:00
#include "Blaster/PlayerController/BlasterPlayerController.h"
2022-04-30 11:09:28 +00:00
#include "Blaster/Weapon/Weapon.h"
2022-05-05 19:56:31 +00:00
#include "Camera/CameraComponent.h"
2022-04-30 11:09:28 +00:00
#include "Engine/SkeletalMeshSocket.h"
2022-05-02 13:40:33 +00:00
#include "GameFramework/CharacterMovementComponent.h"
2022-05-04 22:39:17 +00:00
#include "Kismet/GameplayStatics.h"
2022-04-30 14:48:34 +00:00
#include "Net/UnrealNetwork.h"
2022-04-30 11:09:28 +00:00
UCombatComponent::UCombatComponent()
{
2022-05-04 22:39:17 +00:00
PrimaryComponentTick.bCanEverTick = true;
2022-05-03 17:50:47 +00:00
BaseWalkSpeed = 600.f;
2022-05-04 12:57:48 +00:00
AimWalkSpeed = 350.f;
2022-04-30 11:09:28 +00:00
}
2022-05-04 20:57:45 +00:00
void UCombatComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(UCombatComponent, EquippedWeapon);
DOREPLIFETIME(UCombatComponent, bAiming);
}
2022-04-30 11:09:28 +00:00
void UCombatComponent::BeginPlay()
{
Super::BeginPlay();
2022-05-03 17:50:47 +00:00
if (Character)
{
Character->GetCharacterMovement()->MaxWalkSpeed = BaseWalkSpeed;
2022-05-05 19:56:31 +00:00
if (Character->GetFollowCamera())
{
DefaultFOV = Character->GetFollowCamera()->FieldOfView;
CurrentFOV = DefaultFOV;
}
2022-05-03 17:50:47 +00:00
}
2022-04-30 11:09:28 +00:00
}
2022-05-05 15:57:57 +00:00
void UCombatComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
2022-05-05 20:46:35 +00:00
2022-05-05 18:14:17 +00:00
if (Character && Character->IsLocallyControlled())
{
FHitResult HitResult;
TraceUnderCrosshairs(HitResult);
HitTarget = HitResult.ImpactPoint;
2022-05-05 19:56:31 +00:00
SetHUDCrosshairs(DeltaTime);
InterpFOV(DeltaTime);
2022-05-05 18:14:17 +00:00
}
2022-05-05 15:57:57 +00:00
}
void UCombatComponent::SetHUDCrosshairs(float DeltaTime)
{
if (Character == nullptr || Character->Controller == nullptr) return;
Controller = Controller == nullptr ? Cast<ABlasterPlayerController>(Character->Controller) : Controller;
if (Controller)
{
HUD = HUD == nullptr ? Cast<ABlasterHUD>(Controller->GetHUD()) : HUD;
if (HUD)
{
if (EquippedWeapon)
{
HUDPackage.CrosshairsCenter = EquippedWeapon->CrosshairsCenter;
HUDPackage.CrosshairsLeft = EquippedWeapon->CrosshairsLeft;
HUDPackage.CrosshairsRight = EquippedWeapon->CrosshairsRight;
HUDPackage.CrosshairsTop = EquippedWeapon->CrosshairsTop;
HUDPackage.CrosshairsBottom = EquippedWeapon->CrosshairsBottom;
}
else
{
HUDPackage.CrosshairsCenter = nullptr;
HUDPackage.CrosshairsLeft = nullptr;
HUDPackage.CrosshairsRight = nullptr;
HUDPackage.CrosshairsTop = nullptr;
HUDPackage.CrosshairsBottom = nullptr;
}
2022-05-05 16:48:17 +00:00
// Calculate crosshair spread
// Velocity [0, 600] -> Spread [0, 1]
const FVector2D WalkSpeedRange(0.f, Character->GetCharacterMovement()->MaxWalkSpeed);
const FVector2D VelocityMultiplierRange(0.f, 1.f);
FVector Velocity = Character->GetVelocity();
Velocity.Z = 0.f;
CrosshairVelocityFactor = FMath::GetMappedRangeValueClamped(WalkSpeedRange, VelocityMultiplierRange, Velocity.Size());
2022-05-05 20:46:35 +00:00
2022-05-05 16:48:17 +00:00
if (Character->GetCharacterMovement()->IsFalling())
{
CrosshairInAirFactor = FMath::FInterpTo(CrosshairInAirFactor, 2.25f, DeltaTime, 2.25f);
}
else
{
CrosshairInAirFactor = FMath::FInterpTo(CrosshairInAirFactor, 0.f, DeltaTime, 30.f);
}
2022-05-05 20:13:12 +00:00
if (bAiming)
{
CrosshairAimFactor = FMath::FInterpTo(CrosshairAimFactor, 0.58f, DeltaTime, 30.f);
}
else
{
CrosshairAimFactor = FMath::FInterpTo(CrosshairAimFactor, 0.f, DeltaTime, 30.f);
}
CrosshairShootingFactor = FMath::FInterpTo(CrosshairShootingFactor, 0.f, DeltaTime, 40.f);
2022-05-05 20:46:35 +00:00
2022-05-05 20:13:12 +00:00
HUDPackage.CrosshairSpread =
2022-05-05 20:46:35 +00:00
0.5f +
CrosshairVelocityFactor +
CrosshairInAirFactor -
CrosshairAimFactor +
CrosshairShootingFactor;
2022-05-05 15:57:57 +00:00
HUD->SetHUDPackage(HUDPackage);
}
}
}
2022-05-05 19:56:31 +00:00
void UCombatComponent::InterpFOV(float DeltaTime)
{
if (EquippedWeapon == nullptr) return;
if (bAiming)
{
CurrentFOV = FMath::FInterpTo(CurrentFOV, EquippedWeapon->GetZoomedFOV(), DeltaTime, EquippedWeapon->GetZoomInterpSpeed());
}
else
{
CurrentFOV = FMath::FInterpTo(CurrentFOV, DefaultFOV, DeltaTime, ZoomInterpSpeed);
}
if (Character && Character->GetFollowCamera())
{
Character->GetFollowCamera()->SetFieldOfView(CurrentFOV);
}
}
2022-04-30 15:38:03 +00:00
void UCombatComponent::SetAiming(bool bIsAiming)
{
bAiming = bIsAiming;
ServerSetAiming(bIsAiming);
2022-05-03 17:50:47 +00:00
if (Character)
{
Character->GetCharacterMovement()->MaxWalkSpeed = bIsAiming ? AimWalkSpeed : BaseWalkSpeed;
}
}
void UCombatComponent::ServerSetAiming_Implementation(bool bIsAiming)
{
bAiming = bIsAiming;
if (Character)
{
Character->GetCharacterMovement()->MaxWalkSpeed = bIsAiming ? AimWalkSpeed : BaseWalkSpeed;
}
2022-04-30 15:38:03 +00:00
}
2022-05-06 20:54:23 +00:00
void UCombatComponent::Fire()
2022-05-04 20:13:31 +00:00
{
2022-05-06 20:54:23 +00:00
if (bCanFire)
2022-05-04 20:57:45 +00:00
{
2022-05-06 20:54:23 +00:00
bCanFire = false;
ServerFire(HitTarget);
2022-05-05 20:13:12 +00:00
if (EquippedWeapon)
{
CrosshairShootingFactor = 0.75f;
}
2022-05-06 20:54:23 +00:00
StartFireTimer();
}
}
void UCombatComponent::FireButtonPressed(bool bPressed)
{
bFireButtonPressed = bPressed;
if (bFireButtonPressed && EquippedWeapon)
{
Fire();
}
}
void UCombatComponent::StartFireTimer()
{
if (EquippedWeapon == nullptr || Character == nullptr) return;
Character->GetWorldTimerManager().SetTimer(FireTimer, this, &UCombatComponent::FireTimerFinished, EquippedWeapon->FireDelay);
}
void UCombatComponent::FireTimerFinished()
{
if (EquippedWeapon == nullptr) return;
bCanFire = true;
if (bFireButtonPressed && EquippedWeapon->bAutomatic)
{
Fire();
}
}
void UCombatComponent::ServerFire_Implementation(const FVector_NetQuantize& TraceHitTarget)
{
MulticastFire(TraceHitTarget);
}
void UCombatComponent::MulticastFire_Implementation(const FVector_NetQuantize& TraceHitTarget)
{
if (EquippedWeapon == nullptr) return;
if (Character)
{
Character->PlayFireMontage(bAiming);
EquippedWeapon->Fire(TraceHitTarget);
2022-05-04 20:57:45 +00:00
}
}
2022-05-04 22:39:17 +00:00
void UCombatComponent::TraceUnderCrosshairs(FHitResult& TraceHitResult)
{
FVector2d ViewPortSize;
if (GEngine && GEngine->GameViewport)
{
GEngine->GameViewport->GetViewportSize(ViewPortSize);
}
FVector2d CrosshairLocation(ViewPortSize.X / 2.f, ViewPortSize.Y / 2.0f);
FVector CrosshairWorldPosition;
FVector CrosshairWorldDirection;
bool bScreenToWorld = UGameplayStatics::DeprojectScreenToWorld(
UGameplayStatics::GetPlayerController(this, 0),
CrosshairLocation,
CrosshairWorldPosition,
CrosshairWorldDirection
);
if (bScreenToWorld)
{
FVector Start = CrosshairWorldPosition;
2022-05-05 21:03:09 +00:00
if (Character)
{
float DistanceToCharacter = (Character->GetActorLocation() - Start).Size();
Start += CrosshairWorldDirection * (DistanceToCharacter + 60.f);
}
2022-05-04 22:39:17 +00:00
FVector End = Start + CrosshairWorldDirection * TRACE_LENGTH;
GetWorld()->LineTraceSingleByChannel(
TraceHitResult,
Start,
End,
ECollisionChannel::ECC_Visibility
);
2022-05-05 20:46:35 +00:00
if (TraceHitResult.GetActor() && TraceHitResult.GetActor()->Implements<UInteractWithCrosshairInterface>())
{
HUDPackage.CrosshairColor = FLinearColor::Red;
}
else
{
HUDPackage.CrosshairColor = FLinearColor::White;
}
2022-05-05 18:14:17 +00:00
2022-05-05 20:46:35 +00:00
if (!TraceHitResult.bBlockingHit) TraceHitResult.ImpactPoint = End;
2022-05-04 22:39:17 +00:00
}
}
2022-04-30 11:09:28 +00:00
void UCombatComponent::EquipWeapon(AWeapon* WeaponToEquip)
{
if (Character == nullptr || WeaponToEquip == nullptr) return;
EquippedWeapon = WeaponToEquip;
EquippedWeapon->SetWeaponState(EWeaponState::EWS_Equipped);
const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(FName("RightHandSocket"));
if (HandSocket)
{
HandSocket->AttachActor(EquippedWeapon, Character->GetMesh());
}
EquippedWeapon->SetOwner(Character);
2022-05-02 13:40:33 +00:00
Character->GetCharacterMovement()->bOrientRotationToMovement = false;
Character->bUseControllerRotationYaw = true;
2022-04-30 11:09:28 +00:00
}
2022-05-08 17:31:58 +00:00
void UCombatComponent::OnRep_EquippedWeapon()
{
if (EquippedWeapon && Character)
{
EquippedWeapon->SetWeaponState(EWeaponState::EWS_Equipped);
const USkeletalMeshSocket* HandSocket = Character->GetMesh()->GetSocketByName(FName("RightHandSocket"));
if (HandSocket)
{
HandSocket->AttachActor(EquippedWeapon, Character->GetMesh());
}
Character->GetCharacterMovement()->bOrientRotationToMovement = false;
Character->bUseControllerRotationYaw = true;
}
}