Nakatomi/Source/Nakatomi/PlayerCharacter.cpp

658 lines
18 KiB
C++
Raw Normal View History

2022-12-13 05:11:56 +01:00
// Fill out your copyright notice in the Description page of Project Settings.
#include "PlayerCharacter.h"
// You can remove these, this is just to get intellisense to work
2023-06-29 19:10:31 +02:00
#include <string>
2023-06-27 23:17:03 +02:00
#include <Components/CapsuleComponent.h>
#include <Kismet/GameplayStatics.h>
2023-06-27 23:17:03 +02:00
2022-12-13 05:11:56 +01:00
#include "InputTriggers.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "InputMappingContext.h"
#include "EnemyCharacter.h"
#include "WeaponThrowable.h"
2022-12-13 05:11:56 +01:00
#define COLLISION_WEAPON ECC_GameTraceChannel1
// Sets default values
APlayerCharacter::APlayerCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.SetTickFunctionEnable(true);
PrimaryActorTick.bStartWithTickEnabled = true;
//bUseControllerRotationPitch = true;
//bUseControllerRotationYaw = true;
//bUseControllerRotationRoll = false;
// Setup the camera boom
2023-07-18 23:21:28 +02:00
CameraSpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArmComponent"));
CameraSpringArmComponent->SetupAttachment(RootComponent);
CameraSpringArmComponent->bDoCollisionTest = true;
CameraSpringArmComponent->bUsePawnControlRotation = true;
CameraSpringArmComponent->TargetArmLength = 350.0f;
CameraSpringArmComponent->bEnableCameraLag = true;
CameraSpringArmComponent->CameraLagSpeed = 10.0f;
CameraSpringArmComponent->SocketOffset = {0.0f, 75.0f, 110.0f};
2022-12-13 05:11:56 +01:00
// Setup the camera component
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
2023-07-18 23:21:28 +02:00
CameraComponent->SetupAttachment(CameraSpringArmComponent, USpringArmComponent::SocketName);
2022-12-13 05:11:56 +01:00
CameraComponent->bUsePawnControlRotation = false;
2023-06-23 22:06:18 +02:00
CameraComponent->SetRelativeRotation({-5.0f, 0.0f, 0.0f});
2022-12-13 05:11:56 +01:00
2023-07-18 23:21:28 +02:00
// Setup the camera sights boom
CameraADSSpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraADSSpringArmComponent"));
CameraADSSpringArmComponent->SetupAttachment(RootComponent);
CameraADSSpringArmComponent->bDoCollisionTest = true;
CameraADSSpringArmComponent->bUsePawnControlRotation = true;
CameraADSSpringArmComponent->TargetArmLength = 100.0f;
CameraADSSpringArmComponent->bEnableCameraLag = false;
CameraADSSpringArmComponent->SocketOffset = {0.0f, 50.0f, 75.0f};
2022-12-13 05:11:56 +01:00
// Setup the character movement
UCharacterMovementComponent* CharacterMovementComponent = GetCharacterMovement();
CharacterMovementComponent->AirControl = 1.0f;
CharacterMovementComponent->bOrientRotationToMovement = true;
// Setup the character perception component
PerceptionSource = CreateDefaultSubobject<UAIPerceptionStimuliSourceComponent>(TEXT("Perception Source Stimuli"));
PerceptionSource->bAutoRegister = true;
2023-09-20 02:57:37 +02:00
this->Tags.Add(FName("Player"));
2022-12-13 05:11:56 +01:00
}
// Called when the game starts or when spawned
void APlayerCharacter::BeginPlay()
{
Super::BeginPlay();
DefaultMovementSpeed = GetCharacterMovement()->MaxWalkSpeed;
2023-07-26 23:43:29 +02:00
AimSensitivity = DefaultAimSensitivity;
if (!this->ActorHasTag(FName("Player")))
{
this->Tags.Add(FName("Player"));
}
2023-02-06 02:07:01 +01:00
if (PlayerHUD)
{
currentPlayerHUD = UUserWidget::CreateWidgetInstance(*GetWorld(), PlayerHUD, FName("PLayer HUD"));
if (currentPlayerHUD)
{
currentPlayerHUD->AddToViewport();
}
}
if (PauseMenuWidget)
{
currentPauseMenuWidget = CreateWidget<UUserWidget>(GetWorld(), PauseMenuWidget);
}
2022-12-13 05:11:56 +01:00
}
void APlayerCharacter::Destroyed()
{
2023-06-29 19:10:31 +02:00
FString map = GetWorld()->GetMapName();
map.RemoveFromStart("UEDPIE_0_"); // We have to remove this for reason, I don't fully understand at the moment
UGameplayStatics::OpenLevel(this, FName(map), false);
2023-06-29 19:10:31 +02:00
Super::Destroyed();
}
2022-12-13 05:11:56 +01:00
// Called every frame
void APlayerCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
if (APlayerController* PC = Cast<APlayerController>(GetController()))
{
2023-06-23 22:06:18 +02:00
if (UEnhancedInputLocalPlayerSubsystem* InputSystem = ULocalPlayer::GetSubsystem<
UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
2022-12-13 05:11:56 +01:00
{
if (!InputMappingContext.IsNull())
{
InputSystem->AddMappingContext(InputMappingContext.LoadSynchronous(), MappingPriority);
}
}
}
if (UEnhancedInputComponent* Input = Cast<UEnhancedInputComponent>(PlayerInputComponent))
{
if (MovementAction)
{
Input->BindAction(MovementAction, ETriggerEvent::Triggered, this, &APlayerCharacter::MovementCallback);
}
if (LookAction)
{
Input->BindAction(LookAction, ETriggerEvent::Triggered, this, &APlayerCharacter::LookCallback);
}
if (JumpAction)
{
Input->BindAction(JumpAction, ETriggerEvent::Triggered, this, &APlayerCharacter::JumpCallback);
}
if (FireAction)
{
2023-01-13 22:11:07 +01:00
Input->BindAction(FireAction, ETriggerEvent::Started, this, &APlayerCharacter::BeginFireCallback);
Input->BindAction(FireAction, ETriggerEvent::Completed, this, &APlayerCharacter::EndFireCallback);
2022-12-13 05:11:56 +01:00
}
if (QuitAction)
{
Input->BindAction(QuitAction, ETriggerEvent::Completed, this, &APlayerCharacter::QuitCallback);
2022-12-13 05:11:56 +01:00
}
if (SprintAction)
{
Input->BindAction(SprintAction, ETriggerEvent::Started, this, &APlayerCharacter::SetSprintingCallback);
Input->BindAction(SprintAction, ETriggerEvent::Completed, this, &APlayerCharacter::SetWalkingCallback);
}
if (WeaponSwitchingAction)
{
2023-06-23 22:06:18 +02:00
Input->BindAction(WeaponSwitchingAction, ETriggerEvent::Triggered, this,
&APlayerCharacter::WeaponSwitchingCallback);
}
2023-07-18 23:21:28 +02:00
if (AimDownSightsAction)
{
Input->BindAction(AimDownSightsAction, ETriggerEvent::Started, this,
&APlayerCharacter::BeginAimDownSightsCallback);
Input->BindAction(AimDownSightsAction, ETriggerEvent::Completed, this,
&APlayerCharacter::EndAimDownSightsCallback);
}
2023-09-13 00:39:05 +02:00
if (ThrowWeaponAction)
2023-09-13 00:39:05 +02:00
{
Input->BindAction(ThrowWeaponAction, ETriggerEvent::Started, this, &APlayerCharacter::ThrowWeaponCallback);
}
if (ThrowExplosiveAction)
{
Input->BindAction(ThrowExplosiveAction, ETriggerEvent::Started, this,
&APlayerCharacter::ThrowExplosiveCallback);
2023-09-13 00:39:05 +02:00
}
2023-09-26 00:00:32 +02:00
if (PauseAction)
{
Input->BindAction(PauseAction, ETriggerEvent::Completed, this, &APlayerCharacter::PauseCallback);
}
2022-12-13 05:11:56 +01:00
}
}
void APlayerCharacter::MovementCallback(const FInputActionInstance& Instance)
{
FVector2D vec2 = Instance.GetValue().Get<FVector2D>();
if (vec2.Size() != 0.0f)
{
AddMovementInput(GetActorForwardVector(), vec2.Y);
AddMovementInput(GetActorRightVector(), vec2.X);
}
}
void APlayerCharacter::LookCallback(const FInputActionInstance& Instance)
{
FVector2D vec2 = Instance.GetValue().Get<FVector2D>();
if (vec2.Size() != 0.0f)
{
2023-07-26 23:43:29 +02:00
AddControllerYawInput(vec2.X * AimSensitivity * GetWorld()->GetDeltaSeconds());
AddControllerPitchInput((vec2.Y * (-1.0f)) * AimSensitivity * GetWorld()->GetDeltaSeconds());
2022-12-13 05:11:56 +01:00
}
}
void APlayerCharacter::JumpCallback(const FInputActionInstance& Instance)
{
Jump();
}
2023-01-13 22:11:07 +01:00
void APlayerCharacter::BeginFireCallback(const FInputActionInstance& Instance)
2022-12-13 05:11:56 +01:00
{
2023-06-23 22:06:18 +02:00
if (CurrentWeapon == nullptr || CurrentWeapon->GetCurrentWeaponStatus()->GetValue() != Idle)
2023-01-13 22:11:07 +01:00
{
return;
}
2022-12-13 05:11:56 +01:00
if (CurrentWeapon->GetAmmoCount() == 0)
{
ThrowWeaponCallback();
return;
}
2023-01-13 22:11:07 +01:00
IsFiring = true;
OnFire();
if (CurrentWeapon == nullptr)
{
return;
}
2023-01-13 22:11:07 +01:00
if (CurrentWeapon->GetWeaponProperties()->IsAutomatic)
{
2023-06-23 22:06:18 +02:00
GetWorldTimerManager().SetTimer(CooldownTimerHandle, this, &APlayerCharacter::WeaponCooldownHandler,
CurrentWeapon->GetWeaponProperties()->WeaponCooldown, true);
GetWorldTimerManager().SetTimer(FireTimerHandle, this, &APlayerCharacter::OnFire,
CurrentWeapon->GetWeaponProperties()->WeaponCooldown, true);
2023-01-13 22:11:07 +01:00
}
else
{
2023-06-23 22:06:18 +02:00
GetWorldTimerManager().SetTimer(CooldownTimerHandle, this, &APlayerCharacter::WeaponCooldownHandler,
CurrentWeapon->GetWeaponProperties()->WeaponCooldown, true);
2023-01-13 22:11:07 +01:00
}
}
void APlayerCharacter::EndFireCallback(const FInputActionInstance& Instance)
{
IsFiring = false;
2022-12-13 05:11:56 +01:00
}
void APlayerCharacter::QuitCallback(const FInputActionInstance& Instance)
{
// TODO: Add platform specific Exit requests
// This is not a bit deal for the moment as we are only building for windows
// For some reason the generic version does not work the same as FWindowsPlatformMisc
FWindowsPlatformMisc::RequestExit(false);
2022-12-13 05:11:56 +01:00
}
void APlayerCharacter::SetSprintingCallback(const FInputActionInstance& Instance)
{
IsSpriting = true;
SetMovementSpeed();
2022-12-13 05:11:56 +01:00
}
void APlayerCharacter::SetWalkingCallback(const FInputActionInstance& Instance)
{
IsSpriting = false;
SetMovementSpeed();
2022-12-13 05:11:56 +01:00
}
void APlayerCharacter::CalculateHits(TArray<FHitResult>* hits)
{
// Set up the collision query params, use the Weapon trace settings, Ignore the actor firing this trace
FCollisionQueryParams TraceParams(SCENE_QUERY_STAT(WeaponTrace), true, GetInstigator());
TraceParams.bReturnPhysicalMaterial = true;
2022-12-13 05:11:56 +01:00
// Set up randomness
const int32 RandomSeed = FMath::Rand();
FRandomStream WeaponRandomStream(RandomSeed);
2023-07-27 23:22:14 +02:00
const float Spread = CurrentWeapon->GetWeaponProperties()->WeaponSpread * WeaponSpreadMultiplier;
const float Range = CurrentWeapon->GetWeaponProperties()->ProjectileRange;
2022-12-13 05:11:56 +01:00
FVector CamStart = CameraComponent->GetComponentTransform().GetLocation();
FVector CamRot = CameraComponent->GetComponentTransform().GetRotation().Vector();
FVector CamEnd = CamStart + CamRot * 99999.f;
FHitResult CamHit;
if (!GetWorld()->LineTraceSingleByChannel(CamHit, CamStart, CamEnd, ECC_Camera))
{
return;
}
2023-06-22 00:08:06 +02:00
// TODO: have this start from the end point of the weapon rather than character center
2022-12-13 05:11:56 +01:00
// Calculate starting position and direction
FVector TraceStart;
FRotator PlayerRot;
2023-06-29 00:14:41 +02:00
GetController<APlayerController>()->GetPlayerViewPoint(TraceStart, PlayerRot);
2022-12-13 05:11:56 +01:00
TraceStart = GetRootComponent()->GetComponentLocation();
FVector AimDir = CamHit.ImpactPoint - TraceStart;
AimDir.Normalize();
2022-12-13 05:11:56 +01:00
TraceStart = TraceStart + AimDir * ((GetInstigator()->GetActorLocation() - TraceStart) | AimDir);
// Calculate the hit results from the trace
TArray<FHitResult> HitResults;
for (size_t i = 0; i < CurrentWeapon->GetWeaponProperties()->ProjectilesPerShot; i++)
2022-12-13 05:11:56 +01:00
{
// Calculate the maximum distance the weapon can fire
2023-06-23 22:06:18 +02:00
FVector ShootDir = WeaponRandomStream.VRandCone(AimDir, FMath::DegreesToRadians(Spread),
FMath::DegreesToRadians(Spread));
FVector MaxHitLoc = TraceStart + (ShootDir * Range);
GetWorld()->LineTraceMultiByChannel(HitResults, TraceStart, MaxHitLoc, COLLISION_WEAPON, TraceParams);
2022-12-13 05:11:56 +01:00
for (FHitResult Result : HitResults)
{
hits->Add(Result);
DrawDebugLine(GetWorld(), TraceStart, Result.ImpactPoint, FColor::Blue, true, 500, 0U, 0);
2023-03-13 22:47:42 +01:00
}
}
}
2023-03-13 22:47:42 +01:00
void APlayerCharacter::ProcessHits(TArray<FHitResult> hits)
{
for (FHitResult Hit : hits)
{
// TODO: Handle hits in a meaningful way
FActorSpawnParameters SpawnParameters;
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
// Spawn field actor
if (CurrentWeapon->GetFieldSystemActor())
{
FTransform transform;
transform.SetLocation(Hit.ImpactPoint);
2023-06-23 22:06:18 +02:00
auto field = GetWorld()->SpawnActor<AFieldSystemActor>(CurrentWeapon->GetFieldSystemActor(), transform,
SpawnParameters);
if (field)
{
field->Destroy();
2023-06-23 22:06:18 +02:00
}
}
2023-03-13 22:47:42 +01:00
if (Hit.GetActor())
{
if (auto interactableComponent = Hit.GetActor()->GetComponentByClass<UInteractableComponent>())
{
interactableComponent->Interact();
}
if (auto healthComponent = Hit.GetActor()->GetComponentByClass<UHealthComponent>())
2023-01-17 00:14:03 +01:00
{
2023-06-23 22:06:18 +02:00
healthComponent->TakeDamage(Hit.GetActor(), CurrentWeapon->GetWeaponProperties()->WeaponDamage, nullptr,
GetController(), this);
if (!healthComponent->GetIsDead())
{
OnEnemyHit.ExecuteIfBound();
2023-08-16 13:31:07 +02:00
if (HitMarkerSound)
{
UGameplayStatics::PlaySound2D(GetWorld(), HitMarkerSound);
}
}
2023-01-17 00:14:03 +01:00
}
}
2022-12-13 05:11:56 +01:00
}
2023-01-02 00:59:59 +01:00
}
void APlayerCharacter::OnDamaged()
{
Super::OnDamaged();
}
void APlayerCharacter::OnDeath()
{
Super::OnDeath();
2023-06-27 23:17:03 +02:00
this->DetachFromControllerPendingDestroy();
this->GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
this->GetCapsuleComponent()->SetCollisionResponseToAllChannels(ECR_Ignore);
this->GetMesh()->SetCollisionProfileName("Ragdoll");
this->SetActorEnableCollision(true);
this->GetMesh()->SetAllBodiesSimulatePhysics(true);
this->GetMesh()->SetSimulatePhysics(true);
this->GetMesh()->WakeAllRigidBodies();
this->GetMesh()->bBlendPhysics = true;
if (auto characterMovementComponent = this->GetCharacterMovement())
{
characterMovementComponent->StopMovementImmediately();
characterMovementComponent->DisableMovement();
characterMovementComponent->SetComponentTickEnabled(false);
}
this->SetLifeSpan(10.0f);
IsFiring = false;
ClearAllTimers();
}
void APlayerCharacter::SetMovementSpeed()
{
if (IsADS)
{
GetCharacterMovement()->MaxWalkSpeed = DefaultMovementSpeed * ADSSpeedMultiplier;
}
else if (IsSpriting)
{
GetCharacterMovement()->MaxWalkSpeed = DefaultMovementSpeed * SprintSpeedMultiplier;
}
else
{
GetCharacterMovement()->MaxWalkSpeed = DefaultMovementSpeed;
}
}
void APlayerCharacter::WeaponSwitchingCallback(const FInputActionInstance& Instance)
2023-01-02 00:59:59 +01:00
{
float value = Instance.GetValue().Get<float>();
if (value > 0)
{
InventoryIncrement();
}
else
{
InventoryDecrement();
}
2023-01-02 00:59:59 +01:00
}
2023-07-18 23:21:28 +02:00
void APlayerCharacter::BeginAimDownSightsCallback(const FInputActionInstance& Instance)
{
IsADS = true;
SetMovementSpeed();
2023-07-26 23:43:29 +02:00
AimSensitivity = DefaultAimSensitivity * ADSAimSensitivityMultiplier;
2023-07-27 23:22:14 +02:00
if (CurrentWeapon)
{
WeaponSpreadMultiplier = CurrentWeapon->GetWeaponProperties()->ADSWeaponSpreadMultiplier;
}
2023-07-18 23:21:28 +02:00
FLatentActionInfo LatentActionInfo;
LatentActionInfo.CallbackTarget = this;
CameraComponent->AttachToComponent(CameraADSSpringArmComponent, FAttachmentTransformRules::KeepWorldTransform,
USpringArmComponent::SocketName);
UKismetSystemLibrary::MoveComponentTo(CameraComponent, FVector::ZeroVector, FRotator::ZeroRotator, true, true,
CameraBlendTime,
true, EMoveComponentAction::Type::Move, LatentActionInfo);
}
void APlayerCharacter::EndAimDownSightsCallback(const FInputActionInstance& Instance)
{
IsADS = false;
SetMovementSpeed();
2023-07-26 23:43:29 +02:00
AimSensitivity = DefaultAimSensitivity;
2023-07-27 23:22:14 +02:00
WeaponSpreadMultiplier = 1.0f;
2023-07-18 23:21:28 +02:00
FLatentActionInfo LatentActionInfo;
LatentActionInfo.CallbackTarget = this;
CameraComponent->AttachToComponent(CameraSpringArmComponent, FAttachmentTransformRules::KeepWorldTransform,
USpringArmComponent::SocketName);
UKismetSystemLibrary::MoveComponentTo(CameraComponent, FVector::ZeroVector, FRotator::ZeroRotator, true, true,
CameraBlendTime,
true, EMoveComponentAction::Type::Move, LatentActionInfo);
}
2023-09-26 00:00:32 +02:00
void APlayerCharacter::PauseCallback(const FInputActionInstance& Instance)
{
2023-10-03 23:52:28 +02:00
APlayerController* PlayerController = Cast<APlayerController>(GetController());
if (PlayerController->SetPause(true))
{
2023-10-03 23:52:28 +02:00
if (PauseMenuWidget)
{
// TODO: Add pause functionality
currentPauseMenuWidget->AddToViewport();
}
}
2023-09-26 00:00:32 +02:00
}
2023-01-13 22:11:07 +01:00
void APlayerCharacter::OnFire()
{
if (!IsFiring || CurrentWeapon->GetAmmoCount() == 0)
2023-01-13 22:11:07 +01:00
{
return;
}
2023-06-27 23:17:03 +02:00
2023-06-23 22:06:18 +02:00
CurrentWeapon->SetCurrentWeaponStatus(Firing);
2023-01-13 22:11:07 +01:00
TArray<FHitResult> Hits = TArray<FHitResult>();
CalculateHits(&Hits);
2023-03-13 22:47:42 +01:00
ProcessHits(Hits);
2023-01-13 22:11:07 +01:00
2023-01-18 01:10:39 +01:00
CurrentWeapon->DecrementAmmoCount(1);
2023-03-17 00:50:15 +01:00
CurrentWeapon->PlayFireSoundAtLocation(this->GetTransform().GetLocation());
2023-01-18 01:35:06 +01:00
// TODO: Play some animation here
2023-01-13 22:11:07 +01:00
2023-06-23 22:06:18 +02:00
CurrentWeapon->SetCurrentWeaponStatus(Cooldown);
2023-08-02 00:02:32 +02:00
Super::OnFire();
2023-01-13 22:11:07 +01:00
}
void APlayerCharacter::WeaponCooldownHandler()
{
2023-06-23 22:06:18 +02:00
if (CurrentWeapon->GetCurrentWeaponStatus()->GetValue() != Idle)
2023-01-13 22:11:07 +01:00
{
2023-06-23 22:06:18 +02:00
CurrentWeapon->SetCurrentWeaponStatus(Idle);
2023-01-13 22:11:07 +01:00
}
2023-01-13 22:11:07 +01:00
if (!IsFiring)
{
GetWorldTimerManager().ClearTimer(FireTimerHandle);
GetWorldTimerManager().ClearTimer(CooldownTimerHandle);
}
}
void APlayerCharacter::ClearAllTimers()
{
GetWorldTimerManager().ClearTimer(FireTimerHandle);
GetWorldTimerManager().ClearTimer(CooldownTimerHandle);
}
2023-02-06 02:07:01 +01:00
int APlayerCharacter::GetCurrentAmmoCount()
{
if (CurrentWeapon == nullptr)
{
2023-07-03 21:05:31 +02:00
return 0;
2023-02-06 02:07:01 +01:00
}
return CurrentWeapon->GetAmmoCount();
}
float APlayerCharacter::GetCurrentHealthCount()
{
if (!GetHealthComponent())
{
2023-07-03 21:05:31 +02:00
return 0;
2023-02-06 02:07:01 +01:00
}
return GetHealthComponent()->GetCurrentHealth();
}
2023-07-03 21:05:31 +02:00
int APlayerCharacter::GetWeaponProjectiles()
{
if (CurrentWeapon == nullptr)
{
return 0;
}
return CurrentWeapon->GetWeaponProperties()->ProjectilesPerShot;
}
float APlayerCharacter::GetWeaponCooldown()
{
if (CurrentWeapon == nullptr)
{
return 0;
}
return CurrentWeapon->GetWeaponProperties()->WeaponCooldown;
}
float APlayerCharacter::GetWeaponSpread()
{
if (CurrentWeapon == nullptr)
{
return 0;
}
return CurrentWeapon->GetWeaponProperties()->WeaponSpread;
}
2023-09-08 23:17:05 +02:00
void APlayerCharacter::ThrowWeaponCallback()
{
if (CurrentWeapon)
{
FVector Location;
FVector BoxExtent;
GetActorBounds(true, Location, BoxExtent, false);
FVector SpawnLocation = (BoxExtent.X * GetActorForwardVector()) * 2;
SpawnLocation += Location;
SpawnLocation.Z += BoxExtent.Z;
TSubclassOf<AWeaponThrowable> WeaponThrowableTemplate = CurrentWeapon->GetWeaponThrowableTemplate();
AWeaponThrowable* Throwable = GetWorld()->SpawnActor<AWeaponThrowable>(
WeaponThrowableTemplate, SpawnLocation, FRotator::ZeroRotator);
Throwable->SetWeaponSkeletalMesh(GetCurrentWeapon()->GetSkeletalMesh());
RemoveCurrentWeaponFromInventory();
}
}
void APlayerCharacter::ThrowExplosiveCallback()
{
2023-09-20 02:57:37 +02:00
if (ThrowableInventory.Num() > 0)
{
FVector Location;
FVector BoxExtent;
GetActorBounds(true, Location, BoxExtent, false);
2023-09-20 02:57:37 +02:00
FVector SpawnLocation = (BoxExtent.X * GetActorForwardVector()) * 2;
SpawnLocation += Location;
SpawnLocation += (25.0f * GetActorForwardVector());
SpawnLocation.Z += BoxExtent.Z;
AThrowable* Throwable = GetWorld()->SpawnActor<AThrowable>(ThrowableInventory.Pop(), SpawnLocation, FRotator::ZeroRotator);
}
}
AThrowable* APlayerCharacter::ThrowThrowable()
2023-09-08 23:17:05 +02:00
{
FVector Location;
FVector BoxExtent;
GetActorBounds(true, Location, BoxExtent, false);
FVector SpawnLocation = FVector(Location.Z, Location.Y + (BoxExtent.Y / 2), Location.Z + (BoxExtent.Z / 2));
if (AThrowable* Throwable = GetWorld()->SpawnActor<AThrowable>(SpawnLocation, FRotator::ZeroRotator))
{
return Throwable;
}
2023-09-08 23:17:05 +02:00
return nullptr;
2023-09-08 23:17:05 +02:00
}