feat: add grenade pickup, throw, and drop mechanics
Implemented basic grenade interaction: - Player can pick up, throw, and drop grenades. To-do: - Refine throwing mechanics (e.g. direction, force). - Clean up and refactor related code.
This commit is contained in:
parent
c372d9e8d5
commit
2b6bdf9f80
BIN
Content/Blueprints/Items/BP_GranadeBase.uasset
Normal file
BIN
Content/Blueprints/Items/BP_GranadeBase.uasset
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/Blueprints/Player/Inputs/Inputs/AI_Throw.uasset
Normal file
BIN
Content/Blueprints/Player/Inputs/Inputs/AI_Throw.uasset
Normal file
Binary file not shown.
Binary file not shown.
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "Characters/Components/ShootingComponent.h"
|
||||
|
||||
#include "Items/ThrowableBase.h"
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UShootingComponent::UShootingComponent()
|
||||
{
|
||||
|
|
@ -96,7 +98,7 @@ void UShootingComponent::Reload()
|
|||
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
|
||||
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)
|
||||
|
|
@ -121,6 +123,38 @@ void UShootingComponent::PickUpGun(AGunBase* gunItem)
|
|||
CurrentGun = NewGun;
|
||||
}
|
||||
|
||||
bool UShootingComponent::PickUpThrow(AThrowableBase* ThrowItem)
|
||||
{
|
||||
AThrowableBase* NewThrowable = NewObject<AThrowableBase>();
|
||||
|
||||
if (IsValid(ThrowableItem))
|
||||
{
|
||||
if (ThrowableItem->GetClass() == NewThrowable->GetClass())
|
||||
{
|
||||
if (ThrowableItem->Quantity + ThrowItem->Quantity >= ThrowableItem->MaxQuantity)
|
||||
{
|
||||
ThrowableItem->Quantity = ThrowableItem->MaxQuantity;
|
||||
return false;
|
||||
}
|
||||
|
||||
ThrowableItem->Quantity += ThrowItem->Quantity;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
DropThrow();
|
||||
}
|
||||
|
||||
NewThrowable->Damage = ThrowItem->Damage;
|
||||
NewThrowable->Quantity = ThrowItem->Quantity;
|
||||
NewThrowable->Radius = ThrowItem->Radius;
|
||||
NewThrowable->ThrowableType = ThrowItem->ThrowableType;
|
||||
NewThrowable->SceneItemClass = ThrowItem->GetClass();
|
||||
|
||||
ThrowableItem = NewThrowable;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UShootingComponent::DropGun()
|
||||
{
|
||||
if (!IsValid(CurrentGun)) return;
|
||||
|
|
@ -151,6 +185,30 @@ void UShootingComponent::DropGun()
|
|||
}
|
||||
}
|
||||
|
||||
void UShootingComponent::DropThrow()
|
||||
{
|
||||
if (!IsValid(ThrowableItem)) return;
|
||||
|
||||
FVector ForwardVector = PlayerCharacter->GetActorForwardVector();
|
||||
FVector DroppedPos = PlayerCharacter->GetActorLocation() + (ForwardVector * 100.f);
|
||||
|
||||
FTransform DroppedTransform = PlayerCharacter->GetActorTransform();
|
||||
DroppedTransform.SetLocation(DroppedPos);
|
||||
|
||||
AThrowableBase* DropedItem = GetWorld()->SpawnActor<AThrowableBase>(ThrowableItem->SceneItemClass, DroppedTransform);
|
||||
|
||||
if (DropedItem)
|
||||
{
|
||||
ThrowableItem->Quantity--;
|
||||
DropedItem->Damage = ThrowableItem->Damage;
|
||||
DropedItem->Radius = ThrowableItem->Radius;
|
||||
DropedItem->Quantity = ThrowableItem->Quantity;
|
||||
DropedItem->ThrowableType = ThrowableItem->ThrowableType;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UShootingComponent::ResetFireCooldown()
|
||||
{
|
||||
bCanShoot = true;
|
||||
|
|
@ -206,6 +264,40 @@ void UShootingComponent::StopAiming()
|
|||
TargetFOV = DefaultFOV;
|
||||
}
|
||||
|
||||
void UShootingComponent::Throw() // Wymaga dopracowania
|
||||
{
|
||||
if (IsValid(ThrowableItem))
|
||||
{
|
||||
FVector ForwardVector = PlayerCharacter->GetActorForwardVector();
|
||||
FVector DroppedPos = PlayerCharacter->GetActorLocation() + (ForwardVector * 100.f);
|
||||
|
||||
FTransform DroppedTransform = PlayerCharacter->GetActorTransform();
|
||||
DroppedTransform.SetLocation(DroppedPos);
|
||||
|
||||
AThrowableBase* ThrowedItem = GetWorld()->SpawnActor<AThrowableBase>(ThrowableItem->SceneItemClass, DroppedTransform);
|
||||
|
||||
if (ThrowedItem)
|
||||
{
|
||||
ThrowableItem->Quantity--;
|
||||
ThrowedItem->Damage = ThrowableItem->Damage;
|
||||
ThrowedItem->Radius = ThrowableItem->Radius;
|
||||
ThrowedItem->Quantity = 1;
|
||||
ThrowedItem->ThrowableType = ThrowableItem->ThrowableType;
|
||||
|
||||
FVector ThrowVector = (ThrowedItem->GetActorLocation() - PlayerCharacter->GetActorLocation()).GetSafeNormal();
|
||||
ThrowedItem->Mesh->SetPhysicsLinearVelocity(ThrowVector * 800.f);
|
||||
|
||||
if (ThrowableItem->Quantity <= 0)
|
||||
{
|
||||
ThrowableItem->Destroy();
|
||||
ThrowableItem = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
void UShootingComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
|
|
|
|||
45
Source/Exo/Private/Items/ThrowableBase.cpp
Normal file
45
Source/Exo/Private/Items/ThrowableBase.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Items/ThrowableBase.h"
|
||||
|
||||
#include "Characters/Components/ShootingComponent.h"
|
||||
|
||||
AThrowableBase::AThrowableBase()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
RootSceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
|
||||
SetRootComponent(RootSceneComponent);
|
||||
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
|
||||
Mesh->SetupAttachment(GetRootComponent());
|
||||
Mesh->SetSimulatePhysics(true);
|
||||
|
||||
}
|
||||
|
||||
void AThrowableBase::Interact_Implementation(AExoPlayerCharacter* PlayerCharacter)
|
||||
{
|
||||
if (PlayerCharacter->ShootingComponent->PickUpThrow(this))
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AThrowableBase::EffectActivate()
|
||||
{
|
||||
if (ThrowableType == ThrowableType::Hit)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Throwable Hit"));
|
||||
}
|
||||
if (ThrowableType == ThrowableType::Explode)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Throwable Explode"));
|
||||
}
|
||||
if (ThrowableType == ThrowableType::Area)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Throwable Area"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -57,6 +57,7 @@ void AExoPlayerController::SetupInputComponent()
|
|||
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerStartSprint);
|
||||
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerStopSprint);
|
||||
EnhancedInputComponent->BindAction(ShootAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerShoot);
|
||||
EnhancedInputComponent->BindAction(ThrowAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerThrow);
|
||||
EnhancedInputComponent->BindAction(AimAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerStartAim);
|
||||
EnhancedInputComponent->BindAction(AimAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerStopAim);
|
||||
EnhancedInputComponent->BindAction(MeleAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerMeleAttack);
|
||||
|
|
@ -166,6 +167,11 @@ void AExoPlayerController::PlayerShoot()
|
|||
ShootingComponent->Shoot();
|
||||
}
|
||||
|
||||
void AExoPlayerController::PlayerThrow()
|
||||
{
|
||||
ShootingComponent->Throw();
|
||||
}
|
||||
|
||||
void AExoPlayerController::PlayerStartAim()
|
||||
{
|
||||
ShootingComponent->StartAiming();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include "ShootingComponent.generated.h"
|
||||
|
||||
|
||||
class AThrowableBase;
|
||||
|
||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
||||
class EXO_API UShootingComponent : public UActorComponent
|
||||
{
|
||||
|
|
@ -49,9 +51,15 @@ public:
|
|||
UFUNCTION(BlueprintCallable, Category = "Shooting")
|
||||
void PickUpGun(AGunBase* gunItem);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Shooting")
|
||||
bool PickUpThrow(AThrowableBase* ThrowItem);
|
||||
|
||||
UFUNCTION(Category = "Shooting")
|
||||
void DropGun();
|
||||
|
||||
UFUNCTION(Category = "Shooting")
|
||||
void DropThrow();
|
||||
|
||||
UFUNCTION(Category = "Shooting")
|
||||
void SwitchGun();
|
||||
|
||||
|
|
@ -64,6 +72,9 @@ public:
|
|||
UFUNCTION(Category = "Shooting")
|
||||
void StopAiming();
|
||||
|
||||
UFUNCTION(Category = "Shooting")
|
||||
void Throw();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Aiming")
|
||||
float AimingAnimationSpeed = 30.0f;
|
||||
|
||||
|
|
@ -76,6 +87,9 @@ public:
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Mele Attack")
|
||||
float MeleRange = 75.f;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Shooting")
|
||||
AThrowableBase* ThrowableItem = nullptr;
|
||||
|
||||
AGunBase* CurrentGun = nullptr;
|
||||
AGunBase* SecondaryGun = nullptr;
|
||||
|
||||
|
|
|
|||
59
Source/Exo/Public/Items/ThrowableBase.h
Normal file
59
Source/Exo/Public/Items/ThrowableBase.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Interfaces/Interactable.h"
|
||||
#include "ThrowableBase.generated.h"
|
||||
|
||||
UENUM()
|
||||
enum class ThrowableType : uint8
|
||||
{
|
||||
Hit UMETA(DisplayName = "Hit"),
|
||||
Explode UMETA(DisplayName = "Explode"),
|
||||
Area UMETA(DisplayName = "Area")
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class EXO_API AThrowableBase : public AActor, public IInteractable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AThrowableBase();
|
||||
|
||||
virtual void Interact_Implementation(AExoPlayerCharacter* PlayerCharacter) override;
|
||||
|
||||
TSubclassOf<AActor> SceneItemClass;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Throw")
|
||||
TObjectPtr<USceneComponent> RootSceneComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Throw")
|
||||
TObjectPtr<UStaticMeshComponent> Mesh;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Throw Details")
|
||||
int Quantity = 1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Throw Details")
|
||||
int MaxQuantity = 6;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Throw Details")
|
||||
int NumberOfBounces = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Effect")
|
||||
ThrowableType ThrowableType = ThrowableType::Hit;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Effect")
|
||||
float Damage = 100.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Effect")
|
||||
float Radius = 0.f;
|
||||
|
||||
protected:
|
||||
UFUNCTION(BlueprintCallable, Category = "Effect")
|
||||
virtual void EffectActivate();
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -62,6 +62,9 @@ protected:
|
|||
UFUNCTION(BlueprintCallable, Category = "Input")
|
||||
void PlayerShoot(); // LPM
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Input")
|
||||
void PlayerThrow(); // G
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Input")
|
||||
void PlayerStartAim(); // PPM (pressed)
|
||||
|
||||
|
|
@ -119,7 +122,10 @@ protected:
|
|||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
TObjectPtr<UInputAction> ShootAction;
|
||||
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
TObjectPtr<UInputAction> ThrowAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
TObjectPtr<UInputAction> ReloadAction;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user