parent
402ede1696
commit
ec9991e77c
|
@ -72,3 +72,6 @@ Plugins/*/Intermediate/*
|
||||||
|
|
||||||
# Cache files for the editor to use
|
# Cache files for the editor to use
|
||||||
DerivedDataCache/*
|
DerivedDataCache/*
|
||||||
|
/Content/ModSci_Engineer/
|
||||||
|
/Content/ModSci_EngiProps/
|
||||||
|
/Content/ModSciInteriors/
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
[/Script/EngineSettings.GameMapsSettings]
|
[/Script/EngineSettings.GameMapsSettings]
|
||||||
GameDefaultMap=/Game/_Game/Maps/Factory.Factory
|
GameDefaultMap=/Game/ModSciInteriors/Maps/Example_2_Dynamic.Example_2_Dynamic
|
||||||
EditorStartupMap=/Game/_Game/Maps/Factory.Factory
|
EditorStartupMap=/Game/ModSciInteriors/Maps/Example_2_Dynamic.Example_2_Dynamic
|
||||||
GlobalDefaultGameMode=/Game/_Game/GameMode/ShooterGameModeBaseBP.ShooterGameModeBaseBP_C
|
GlobalDefaultGameMode=/Game/_Game/GameMode/ShooterGameModeBaseBP.ShooterGameModeBaseBP_C
|
||||||
|
|
||||||
[/Script/HardwareTargeting.HardwareTargetingSettings]
|
[/Script/HardwareTargeting.HardwareTargetingSettings]
|
||||||
|
|
BIN
Content/_Game/HUD/PickupWidgetBP.uasset (Stored with Git LFS)
BIN
Content/_Game/HUD/PickupWidgetBP.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Maps/Factory.umap (Stored with Git LFS)
BIN
Content/_Game/Maps/Factory.umap (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Weapons/BaseWeapon/BaseWeaponBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Weapons/BaseWeapon/BaseWeaponBP.uasset (Stored with Git LFS)
Binary file not shown.
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
|
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
|
|
||||||
|
#include "ShooterCharacter.h"
|
||||||
#include "Components/BoxComponent.h"
|
#include "Components/BoxComponent.h"
|
||||||
|
#include "Components/SphereComponent.h"
|
||||||
|
#include "Components/WidgetComponent.h"
|
||||||
|
|
||||||
// Sets default values
|
// Sets default values
|
||||||
AItem::AItem()
|
AItem::AItem()
|
||||||
|
@ -15,6 +19,14 @@ AItem::AItem()
|
||||||
|
|
||||||
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
|
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
|
||||||
CollisionBox->SetupAttachment(ItemMesh);
|
CollisionBox->SetupAttachment(ItemMesh);
|
||||||
|
CollisionBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
||||||
|
CollisionBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
|
||||||
|
|
||||||
|
PickupWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("PickupWidget"));
|
||||||
|
PickupWidget->SetupAttachment(GetRootComponent());
|
||||||
|
|
||||||
|
AreaSphere = CreateDefaultSubobject<USphereComponent>(TEXT("AreaSphere"));
|
||||||
|
AreaSphere->SetupAttachment(GetRootComponent());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the game starts or when spawned
|
// Called when the game starts or when spawned
|
||||||
|
@ -22,6 +34,12 @@ void AItem::BeginPlay()
|
||||||
{
|
{
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
// Hide Pickup Widget
|
||||||
|
PickupWidget->SetVisibility(false);
|
||||||
|
|
||||||
|
// Setup overlap for AreaSphere
|
||||||
|
AreaSphere->OnComponentBeginOverlap.AddDynamic(this, &AItem::OnSphereOverlap);
|
||||||
|
AreaSphere->OnComponentEndOverlap.AddDynamic(this, &AItem::OnSphereEndOverlap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every frame
|
// Called every frame
|
||||||
|
@ -31,3 +49,31 @@ void AItem::Tick(float DeltaTime)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AItem::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
|
||||||
|
int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
|
||||||
|
{
|
||||||
|
if (OtherActor)
|
||||||
|
{
|
||||||
|
AShooterCharacter* ShooterCharacter = Cast<AShooterCharacter>(OtherActor);
|
||||||
|
|
||||||
|
if (ShooterCharacter)
|
||||||
|
{
|
||||||
|
ShooterCharacter->IncrementOverlappedItemCount(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AItem::OnSphereEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||||
|
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
|
||||||
|
{
|
||||||
|
if (OtherActor)
|
||||||
|
{
|
||||||
|
AShooterCharacter* ShooterCharacter = Cast<AShooterCharacter>(OtherActor);
|
||||||
|
|
||||||
|
if (ShooterCharacter)
|
||||||
|
{
|
||||||
|
ShooterCharacter->IncrementOverlappedItemCount(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
class UBoxComponent;
|
class UBoxComponent;
|
||||||
class UWidgetComponent;
|
class UWidgetComponent;
|
||||||
|
class USphereComponent;
|
||||||
|
|
||||||
UCLASS()
|
UCLASS()
|
||||||
class SHOOTER_API AItem : public AActor
|
class SHOOTER_API AItem : public AActor
|
||||||
|
@ -26,6 +27,17 @@ public:
|
||||||
// Called every frame
|
// Called every frame
|
||||||
virtual void Tick(float DeltaTime) override;
|
virtual void Tick(float DeltaTime) override;
|
||||||
|
|
||||||
|
/* Called when overlapping AreaSphere */
|
||||||
|
UFUNCTION()
|
||||||
|
void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||||
|
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
|
||||||
|
const FHitResult& SweepResult);
|
||||||
|
|
||||||
|
/* Called when end overlapping AreaSphere */
|
||||||
|
UFUNCTION()
|
||||||
|
void OnSphereEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||||
|
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/* Skeletal mesh for the item */
|
/* Skeletal mesh for the item */
|
||||||
|
@ -40,6 +52,10 @@ private:
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = true))
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = true))
|
||||||
UWidgetComponent* PickupWidget;
|
UWidgetComponent* PickupWidget;
|
||||||
|
|
||||||
public:
|
/* Enables item tracing when overlapped */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item Properties", meta = (AllowPrivateAccess = true))
|
||||||
|
USphereComponent* AreaSphere;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE UWidgetComponent* GetPickupWidget() const { return PickupWidget; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
#include "ShooterCharacter.h"
|
#include "ShooterCharacter.h"
|
||||||
|
|
||||||
|
#include "Item.h"
|
||||||
#include "Camera/CameraComponent.h"
|
#include "Camera/CameraComponent.h"
|
||||||
|
#include "Components/WidgetComponent.h"
|
||||||
#include "Engine/SkeletalMeshSocket.h"
|
#include "Engine/SkeletalMeshSocket.h"
|
||||||
#include "GameFramework/SpringArmComponent.h"
|
#include "GameFramework/SpringArmComponent.h"
|
||||||
#include "GameFramework/CharacterMovementComponent.h"
|
#include "GameFramework/CharacterMovementComponent.h"
|
||||||
|
@ -45,7 +47,9 @@ AShooterCharacter::AShooterCharacter() :
|
||||||
// Automatic fire
|
// Automatic fire
|
||||||
bShouldFire(true),
|
bShouldFire(true),
|
||||||
bFireButtonPressed(false),
|
bFireButtonPressed(false),
|
||||||
AutomaticFireRate(0.1f)
|
AutomaticFireRate(0.1f),
|
||||||
|
// Item trace variables
|
||||||
|
bShouldTraceForItems(false)
|
||||||
{
|
{
|
||||||
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
|
// 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.bCanEverTick = true;
|
||||||
|
@ -215,56 +219,24 @@ void AShooterCharacter::FireWeapon()
|
||||||
|
|
||||||
bool AShooterCharacter::GetBeamEndLocation(const FVector& MuzzleSocketLocation, FVector& OutBeamLocation)
|
bool AShooterCharacter::GetBeamEndLocation(const FVector& MuzzleSocketLocation, FVector& OutBeamLocation)
|
||||||
{
|
{
|
||||||
// Get current size of the viewport
|
// Check for crosshair trace hit
|
||||||
FVector2D ViewportSize;
|
FHitResult CrosshairHitResult;
|
||||||
|
bool bCrosshairHit = TraceUnderCrosshairs(CrosshairHitResult, OutBeamLocation);
|
||||||
|
|
||||||
if (GEngine && GEngine->GameViewport)
|
// Perform a second trace, this time from the gun barrel
|
||||||
|
FHitResult WeaponTraceHit;
|
||||||
|
const FVector WeaponTraceStart{ MuzzleSocketLocation };
|
||||||
|
const FVector StartToEnd{ OutBeamLocation - MuzzleSocketLocation };
|
||||||
|
const FVector WeaponTraceEnd{ MuzzleSocketLocation + StartToEnd * 1.25f };
|
||||||
|
|
||||||
|
GetWorld()->LineTraceSingleByChannel(WeaponTraceHit, WeaponTraceStart, WeaponTraceEnd,
|
||||||
|
ECollisionChannel::ECC_Visibility);
|
||||||
|
|
||||||
|
if (WeaponTraceHit.bBlockingHit) // Object between barrel and BeamEndPoint ?
|
||||||
{
|
{
|
||||||
GEngine->GameViewport->GetViewportSize(ViewportSize);
|
OutBeamLocation = WeaponTraceHit.Location;
|
||||||
}
|
|
||||||
|
|
||||||
// Get screen space location of crosshairs
|
|
||||||
FVector2D CrosshairLocation{ ViewportSize.X / 2.f, ViewportSize.Y / 2.f };
|
|
||||||
|
|
||||||
// Get world position and direction of crosshairs
|
|
||||||
FVector CrosshairWorldPosition;
|
|
||||||
FVector CrosshairWorldDirection;
|
|
||||||
bool bScreenToWorld = UGameplayStatics::DeprojectScreenToWorld(
|
|
||||||
UGameplayStatics::GetPlayerController(this, 0),
|
|
||||||
CrosshairLocation, CrosshairWorldPosition, CrosshairWorldDirection);
|
|
||||||
|
|
||||||
if (bScreenToWorld) // Was deprojection successful
|
|
||||||
{
|
|
||||||
FHitResult ScreenTraceHit;
|
|
||||||
const FVector Start{ CrosshairWorldPosition };
|
|
||||||
const FVector End{ CrosshairWorldPosition + CrosshairWorldDirection * 50'000.f };
|
|
||||||
|
|
||||||
// Set beam end point to line trace end point
|
|
||||||
OutBeamLocation = End;
|
|
||||||
|
|
||||||
// Trace outward from crosshairs world location
|
|
||||||
GetWorld()->LineTraceSingleByChannel(ScreenTraceHit, Start, End, ECollisionChannel::ECC_Visibility);
|
|
||||||
if (ScreenTraceHit.bBlockingHit) // was there a trace hit ?
|
|
||||||
{
|
|
||||||
// Beam end point is now trace hit location
|
|
||||||
OutBeamLocation = ScreenTraceHit.Location;
|
|
||||||
}
|
|
||||||
|
|
||||||
FHitResult WeaponTraceHit;
|
|
||||||
const FVector WeaponTraceStart{ MuzzleSocketLocation };
|
|
||||||
const FVector WeaponTraceEnd{ OutBeamLocation };
|
|
||||||
|
|
||||||
GetWorld()->LineTraceSingleByChannel(WeaponTraceHit, WeaponTraceStart, WeaponTraceEnd,
|
|
||||||
ECollisionChannel::ECC_Visibility);
|
|
||||||
|
|
||||||
if (WeaponTraceHit.bBlockingHit) // Object between barrel and BeamEndPoint ?
|
|
||||||
{
|
|
||||||
OutBeamLocation = WeaponTraceHit.Location;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,6 +389,83 @@ void AShooterCharacter::AutoFireReset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AShooterCharacter::TraceUnderCrosshairs(FHitResult& OutHitResult, FVector& OutHitLocation)
|
||||||
|
{
|
||||||
|
// Get Viewport Size
|
||||||
|
FVector2D ViewportSize;
|
||||||
|
|
||||||
|
if (GEngine && GEngine->GameViewport)
|
||||||
|
{
|
||||||
|
GEngine->GameViewport->GetViewportSize(ViewportSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get screen space location of crosshairs
|
||||||
|
FVector2D CrosshairLocation{ ViewportSize.X / 2.f, ViewportSize.Y / 2.f };
|
||||||
|
|
||||||
|
// Get world position and direction of crosshairs
|
||||||
|
FVector CrosshairWorldPosition;
|
||||||
|
FVector CrosshairWorldDirection;
|
||||||
|
bool bScreenToWorld = UGameplayStatics::DeprojectScreenToWorld(
|
||||||
|
UGameplayStatics::GetPlayerController(this, 0),
|
||||||
|
CrosshairLocation, CrosshairWorldPosition, CrosshairWorldDirection);
|
||||||
|
|
||||||
|
if (bScreenToWorld)
|
||||||
|
{
|
||||||
|
// Trace from Crosshair world location outward
|
||||||
|
const FVector Start{ CrosshairWorldPosition };
|
||||||
|
const FVector End{ Start + CrosshairWorldDirection * 50'000.f };
|
||||||
|
OutHitLocation = End;
|
||||||
|
|
||||||
|
GetWorld()->LineTraceSingleByChannel(OutHitResult, Start, End, ECollisionChannel::ECC_Visibility);
|
||||||
|
|
||||||
|
if (OutHitResult.bBlockingHit)
|
||||||
|
{
|
||||||
|
OutHitLocation = OutHitResult.Location;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AShooterCharacter::TraceForItems()
|
||||||
|
{
|
||||||
|
static AItem* HitItem;
|
||||||
|
if (bShouldTraceForItems)
|
||||||
|
{
|
||||||
|
FHitResult ItemTraceResult;
|
||||||
|
FVector HitLocation;
|
||||||
|
TraceUnderCrosshairs(ItemTraceResult, HitLocation);
|
||||||
|
|
||||||
|
if (ItemTraceResult.bBlockingHit)
|
||||||
|
{
|
||||||
|
// If an item was being looked at from last frame, we should hide its widget
|
||||||
|
SetItemPickupWidgetVisibility(HitItem, false);
|
||||||
|
|
||||||
|
// Show the new item's widget
|
||||||
|
HitItem = Cast<AItem>(ItemTraceResult.GetActor());
|
||||||
|
SetItemPickupWidgetVisibility(HitItem, true);
|
||||||
|
}
|
||||||
|
else if (HitItem) // Hide widget for the item from last frame
|
||||||
|
{
|
||||||
|
SetItemPickupWidgetVisibility(HitItem, false);
|
||||||
|
HitItem = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (HitItem) // Hide widget for the item from last frame
|
||||||
|
{
|
||||||
|
SetItemPickupWidgetVisibility(HitItem, false);
|
||||||
|
HitItem = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AShooterCharacter::SetItemPickupWidgetVisibility(AItem* Item, bool visibility)
|
||||||
|
{
|
||||||
|
if (Item && Item->GetPickupWidget())
|
||||||
|
{
|
||||||
|
Item->GetPickupWidget()->SetVisibility(visibility);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Called every frame
|
// Called every frame
|
||||||
void AShooterCharacter::Tick(float DeltaTime)
|
void AShooterCharacter::Tick(float DeltaTime)
|
||||||
{
|
{
|
||||||
|
@ -430,6 +479,8 @@ void AShooterCharacter::Tick(float DeltaTime)
|
||||||
|
|
||||||
// Calculate crosshair spread multiplier
|
// Calculate crosshair spread multiplier
|
||||||
CalculateCrosshairSpread(DeltaTime);
|
CalculateCrosshairSpread(DeltaTime);
|
||||||
|
|
||||||
|
TraceForItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called to bind functionality to input
|
// Called to bind functionality to input
|
||||||
|
@ -466,3 +517,17 @@ float AShooterCharacter::GetCrosshairSpreadMultiplier() const
|
||||||
return CrosshairSpreadMultiplier;
|
return CrosshairSpreadMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AShooterCharacter::IncrementOverlappedItemCount(int8 Amount)
|
||||||
|
{
|
||||||
|
if (OverlappedItemCount + Amount <= 0)
|
||||||
|
{
|
||||||
|
OverlappedItemCount = 0;
|
||||||
|
bShouldTraceForItems = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OverlappedItemCount += Amount;
|
||||||
|
bShouldTraceForItems = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ class UCameraComponent;
|
||||||
class USoundCue;
|
class USoundCue;
|
||||||
class UParticleSystem;
|
class UParticleSystem;
|
||||||
class UAnimMontage;
|
class UAnimMontage;
|
||||||
|
class AItem;
|
||||||
|
|
||||||
UCLASS()
|
UCLASS()
|
||||||
class SHOOTER_API AShooterCharacter : public ACharacter
|
class SHOOTER_API AShooterCharacter : public ACharacter
|
||||||
|
@ -88,6 +89,14 @@ protected:
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void AutoFireReset();
|
void AutoFireReset();
|
||||||
|
|
||||||
|
/** Line trace for items under the crosshairs */
|
||||||
|
bool TraceUnderCrosshairs(FHitResult& OutHitResult, FVector& OutHitLocation);
|
||||||
|
|
||||||
|
/* Trace for items if OverlappedItemCount > 0 */
|
||||||
|
void TraceForItems();
|
||||||
|
|
||||||
|
void SetItemPickupWidgetVisibility(AItem* Item, bool visibility);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Called every frame
|
// Called every frame
|
||||||
virtual void Tick(float DeltaTime) override;
|
virtual void Tick(float DeltaTime) override;
|
||||||
|
@ -218,6 +227,12 @@ private:
|
||||||
/* Sets a timer between gunshots */
|
/* Sets a timer between gunshots */
|
||||||
FTimerHandle AutoFireTimer;
|
FTimerHandle AutoFireTimer;
|
||||||
|
|
||||||
|
/* True if we should trace every frame for items */
|
||||||
|
bool bShouldTraceForItems;
|
||||||
|
|
||||||
|
/* Number of overlapped AItems */
|
||||||
|
int8 OverlappedItemCount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Returns CameraBoom SubObject */
|
/* Returns CameraBoom SubObject */
|
||||||
FORCEINLINE USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
|
FORCEINLINE USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
|
||||||
|
@ -229,4 +244,9 @@ public:
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable)
|
UFUNCTION(BlueprintCallable)
|
||||||
float GetCrosshairSpreadMultiplier() const;
|
float GetCrosshairSpreadMultiplier() const;
|
||||||
|
|
||||||
|
FORCEINLINE int8 GetOverlappedItemCount() const { return OverlappedItemCount; }
|
||||||
|
|
||||||
|
/* Adds/Subtracts to/from OverlappedItemCount and updates bShouldTraceForItems */
|
||||||
|
void IncrementOverlappedItemCount(int8 Amount);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue