317 lines
9.5 KiB
C++
317 lines
9.5 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "Item.h"
|
|
|
|
#include "ShooterCharacter.h"
|
|
#include "Components/BoxComponent.h"
|
|
#include "Components/SphereComponent.h"
|
|
#include "Components/WidgetComponent.h"
|
|
#include "Camera/CameraComponent.h"
|
|
|
|
// Sets default values
|
|
AItem::AItem() :
|
|
ItemName(FString("Default")),
|
|
ItemCount(0),
|
|
ItemRarity(EItemRarity::EIR_Common),
|
|
ItemState(EItemState::EIS_Pickup),
|
|
// Item interp variables
|
|
ItemInterpStartLocation(FVector(0.f)),
|
|
CameraTargetLocation(FVector(0.f)),
|
|
bInterping(false),
|
|
ZCurveTime(0.7f),
|
|
ItemIntepX(0.f),
|
|
ItemIntepY(0.f),
|
|
InterpInitialYawOffset(0.f)
|
|
{
|
|
// 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;
|
|
|
|
ItemMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("ItemMesh"));
|
|
SetRootComponent(ItemMesh);
|
|
|
|
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
|
|
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
|
|
void AItem::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
// Hide Pickup Widget
|
|
if (PickupWidget)
|
|
PickupWidget->SetVisibility(false);
|
|
|
|
// Set ActiveStars array based on item rarity
|
|
setActiveStars();
|
|
|
|
// Setup overlap for AreaSphere
|
|
AreaSphere->OnComponentBeginOverlap.AddDynamic(this, &AItem::OnSphereOverlap);
|
|
AreaSphere->OnComponentEndOverlap.AddDynamic(this, &AItem::OnSphereEndOverlap);
|
|
|
|
//Set Item properties based on ItemState
|
|
SetItemProperties(ItemState);
|
|
}
|
|
|
|
void AItem::setActiveStars()
|
|
{
|
|
// The 0 element isn't used
|
|
for (int32 i = 0; i <= 5; ++i)
|
|
{
|
|
ActiveStars.Add(false);
|
|
}
|
|
|
|
switch (ItemRarity)
|
|
{
|
|
case EItemRarity::EIR_Damaged:
|
|
ActiveStars[1] = true;
|
|
break;
|
|
case EItemRarity::EIR_Common:
|
|
ActiveStars[1] = true;
|
|
ActiveStars[2] = true;
|
|
break;
|
|
case EItemRarity::EIR_Uncommon:
|
|
ActiveStars[1] = true;
|
|
ActiveStars[2] = true;
|
|
ActiveStars[3] = true;
|
|
break;
|
|
case EItemRarity::EIR_Rare:
|
|
ActiveStars[1] = true;
|
|
ActiveStars[2] = true;
|
|
ActiveStars[3] = true;
|
|
ActiveStars[4] = true;
|
|
break;
|
|
case EItemRarity::EIR_Legendary:
|
|
ActiveStars[1] = true;
|
|
ActiveStars[2] = true;
|
|
ActiveStars[3] = true;
|
|
ActiveStars[4] = true;
|
|
ActiveStars[5] = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Called every frame
|
|
void AItem::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
|
|
// Handle Item interping when in the EquipInterping state
|
|
ItemInterp(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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AItem::ItemInterp(float DeltaTime)
|
|
{
|
|
if (!bInterping) return;
|
|
|
|
if (Character && ItemZCurve)
|
|
{
|
|
// Elapsed time since we started ItemInterpTimer
|
|
const float ElapsedTime = GetWorldTimerManager().GetTimerElapsed(ItemInterpTimer);
|
|
|
|
// Get curve value corresponding to ElapsedTime
|
|
const float CurveValue = ItemZCurve->GetFloatValue(ElapsedTime);
|
|
|
|
// Get the item's initial location when the curve started
|
|
FVector ItemLocation = ItemInterpStartLocation;
|
|
|
|
// Get location in front of the camera
|
|
const FVector CameraInterpLocation{ Character->GetCameraInterpLocation() };
|
|
|
|
// Vector from Item to Camera Interp Location, X and Y are zeroed out
|
|
const FVector ItemToCamera{ FVector(0.f, 0.f, (CameraInterpLocation - ItemLocation).Z) };
|
|
|
|
// SCale factor to multiply with CurveValue
|
|
const float DeltaZ = ItemToCamera.Size();
|
|
|
|
const FVector CurrentLocation{ GetActorLocation() };
|
|
|
|
// Interpolated X Value
|
|
const float InterpXValue = FMath::FInterpTo(CurrentLocation.X,
|
|
CameraInterpLocation.X,
|
|
DeltaTime, 30.f);
|
|
|
|
// Interpolated Y Value
|
|
const float InterpYValue = FMath::FInterpTo(CurrentLocation.Y,
|
|
CameraInterpLocation.Y,
|
|
DeltaTime, 30.f);
|
|
|
|
// Set X and Y of ItemLocation to Interped values
|
|
ItemLocation.X = InterpXValue;
|
|
ItemLocation.Y = InterpYValue;
|
|
|
|
// Adding curve value to the Z component of the Initial Location (Scaled by DeltaZ)
|
|
ItemLocation.Z += CurveValue * DeltaZ;
|
|
SetActorLocation(ItemLocation, true,
|
|
nullptr, ETeleportType::TeleportPhysics);
|
|
|
|
// Camera rotation this frame
|
|
const FRotator CameraRotation{Character->GetFollowCamera()->GetComponentRotation()};
|
|
// Camera rotation plus initial Yaw Offset
|
|
const FRotator ItemRotation{0.f, CameraRotation.Yaw + InterpInitialYawOffset, 0.f};
|
|
SetActorRotation(ItemRotation, ETeleportType::TeleportPhysics);
|
|
|
|
if (ItemScaleCurve)
|
|
{
|
|
const float ScaleCurveValue = ItemScaleCurve->GetFloatValue(ElapsedTime);
|
|
SetActorScale3D(FVector(ScaleCurveValue, ScaleCurveValue, ScaleCurveValue));
|
|
}
|
|
}
|
|
}
|
|
|
|
void AItem::SetItemState(EItemState State)
|
|
{
|
|
ItemState = State;
|
|
SetItemProperties(State);
|
|
}
|
|
|
|
void AItem::SetItemProperties(EItemState State)
|
|
{
|
|
switch (State)
|
|
{
|
|
case EItemState::EIS_Pickup:
|
|
// Set Mesh properties
|
|
ItemMesh->SetSimulatePhysics(false);
|
|
ItemMesh->SetEnableGravity(false);
|
|
ItemMesh->SetVisibility(true);
|
|
ItemMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
ItemMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
|
|
// Set AreaSphere properties
|
|
AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
|
|
AreaSphere->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
|
|
|
// Set CollisionBox properties
|
|
CollisionBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
CollisionBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
|
|
CollisionBox->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
|
break;
|
|
case EItemState::EIS_Equipped:
|
|
// Set Mesh properties
|
|
ItemMesh->SetSimulatePhysics(false);
|
|
ItemMesh->SetEnableGravity(false);
|
|
ItemMesh->SetVisibility(true);
|
|
ItemMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
ItemMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
|
|
// Set AreaSphere properties
|
|
AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
|
|
// Set CollisionBox properties
|
|
CollisionBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
CollisionBox->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
break;
|
|
case EItemState::EIS_Falling:
|
|
// Set Mesh properties
|
|
ItemMesh->SetSimulatePhysics(true);
|
|
ItemMesh->SetEnableGravity(true);
|
|
ItemMesh->SetVisibility(true);
|
|
ItemMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
ItemMesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
|
|
ItemMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
|
|
|
// Set AreaSphere properties
|
|
AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
|
|
// Set CollisionBox properties
|
|
CollisionBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
CollisionBox->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
break;
|
|
case EItemState::EIS_EquipInterping:
|
|
PickupWidget->SetVisibility(false);
|
|
|
|
// Set Mesh properties
|
|
ItemMesh->SetSimulatePhysics(false);
|
|
ItemMesh->SetEnableGravity(false);
|
|
ItemMesh->SetVisibility(true);
|
|
ItemMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
ItemMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
|
|
// Set AreaSphere properties
|
|
AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
|
|
// Set CollisionBox properties
|
|
CollisionBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
|
|
CollisionBox->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AItem::StartItemCurve(AShooterCharacter* Char)
|
|
{
|
|
// Store a handle to the Character
|
|
Character = Char;
|
|
|
|
// Store the initial locatino of the Item
|
|
ItemInterpStartLocation = GetActorLocation();
|
|
|
|
bInterping = true;
|
|
SetItemState(EItemState::EIS_EquipInterping);
|
|
|
|
GetWorldTimerManager().SetTimer(ItemInterpTimer, this,
|
|
&AItem::FinishInterping, ZCurveTime);
|
|
|
|
// Get initial Yaw of the Camera
|
|
const float CameraRotationYaw{
|
|
static_cast<float>(Character->GetFollowCamera()->GetComponentRotation().Yaw)
|
|
};
|
|
|
|
// Get initial Yaw of the Item
|
|
const float ItemRotationYaw{ static_cast<float>(GetActorRotation().Yaw) };
|
|
|
|
// Initial Yaw Offset between Camera and Item
|
|
InterpInitialYawOffset = ItemRotationYaw - CameraRotationYaw;
|
|
}
|
|
|
|
void AItem::FinishInterping()
|
|
{
|
|
bInterping = false;
|
|
if (Character)
|
|
{
|
|
Character->GetPickupItem(this);
|
|
}
|
|
// Set scale back to normal
|
|
SetActorScale3D(FVector(1.f));
|
|
}
|
|
|