FatJohnsLifter/SeagullGame/Source/SeagullGame/SeagullGameCharacter.cpp

261 lines
8.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SeagullGameCharacter.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "ItemActor.h"
#include "UObject/ConstructorHelpers.h"
#include "Camera/CameraComponent.h"
#include "Components/BoxComponent.h"
#include "Components/DecalComponent.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/SpringArmComponent.h"
#include "Materials/Material.h"
#include "Engine/World.h"
ASeagullGameCharacter::ASeagullGameCharacter()
{
// Set size for player capsule
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
// Don't rotate character to camera direction
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
// Configure character movement
GetCharacterMovement()->bOrientRotationToMovement = true; // Rotate character to moving direction
GetCharacterMovement()->RotationRate = FRotator(0.f, 640.f, 0.f);
GetCharacterMovement()->bConstrainToPlane = true;
GetCharacterMovement()->bSnapToPlaneAtStart = true;
// Create a camera boom...
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(RootComponent);
CameraBoom->SetUsingAbsoluteRotation(true); // Don't want arm to rotate when character does
CameraBoom->TargetArmLength = 800.f;
CameraBoom->SetRelativeRotation(FRotator(-60.f, 0.f, 0.f));
CameraBoom->bDoCollisionTest = false; // Don't want to pull camera in when it collides with level
// Create a camera...
TopDownCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("TopDownCamera"));
TopDownCameraComponent->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
TopDownCameraComponent->bUsePawnControlRotation = false; // Camera does not rotate relative to arm
// Activate ticking in order to update the cursor every frame.
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
}
void ASeagullGameCharacter::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
if (JohnsCurrentHunger > 0)
{
JohnsCurrentHunger -= DeltaSeconds * JohnsHungerDeclineAmount;
}
else if (!bHasGameEnded)
{
JohnsCurrentHunger = 0;
OnGameEnd.Broadcast("You Lose!");
bHasGameEnded = true;
}
if (!IsValid(PickupBox)) return;
TArray<AActor*> OverlappingActors;
PickupBox->GetOverlappingActors(OverlappingActors, AItemActor::StaticClass());
float ClosestDistance = 0;
for (AActor* Actor : OverlappingActors)
{
if (Actor == this) continue;
float Distance = FVector::Dist(Actor->GetActorLocation(), GetActorLocation());
if (ClosestItemActor == nullptr || Distance < ClosestDistance)
{
if (IsValid(ClosestItemActor))
{
Cast<UMeshComponent>(ClosestItemActor->GetComponentByClass(UMeshComponent::StaticClass()))->SetRenderCustomDepth(false);
}
ClosestItemActor = Actor;
ClosestDistance = Distance;
}
}
if (!IsValid(ClosestItemActor)) return;
Cast<UMeshComponent>(ClosestItemActor->GetComponentByClass(UMeshComponent::StaticClass()))->SetRenderCustomDepth(true);
}
void ASeagullGameCharacter::BeginPlay()
{
Super::BeginPlay();
//Add Input Mapping Context
if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
PickupBox = Cast<UBoxComponent>(GetComponentByClass(UBoxComponent::StaticClass()));
PickupBox->OnComponentBeginOverlap.AddDynamic(this, &ASeagullGameCharacter::OnPickupBoxBeginOverlap);
PickupBox->OnComponentEndOverlap.AddDynamic(this, &ASeagullGameCharacter::OnPickupBoxEndOverlap);
}
void ASeagullGameCharacter::DamagePlayer(float DamageAmount)
{
CurrentHealth -= DamageAmount;
OnPlayerDamage.Broadcast();
if (CurrentHealth <= 0)
{
CurrentHealth = 0;
OnPlayerDeath.Broadcast();
OnGameEnd.Broadcast("You Lose!");
bHasGameEnded = true;
}
}
void ASeagullGameCharacter::HealPlayer(float HealAmount)
{
CurrentHealth += HealAmount;
if (CurrentHealth > MaxHealth)
{
CurrentHealth = MaxHealth;
}
}
void ASeagullGameCharacter::StartGame()
{
JohnsCurrentHunger = JohnsDefaultHunger;
if (GetWorld()->GetTimerManager().IsTimerActive(GameTimerHandle))
{
GetWorld()->GetTimerManager().ClearTimer(GameTimerHandle);
}
GetWorld()->GetTimerManager().SetTimer(GameTimerHandle, this, &ASeagullGameCharacter::EndGame, GameTime, false);
FTimerHandle CravingTimerHandle;
GetWorld()->GetTimerManager().SetTimer(CravingTimerHandle, [this]()
{
TSubclassOf<AItemActor> ItemActor = ItemActors[FMath::RandRange(0, ItemActors.Num() - 1)];
if (IsValid(CravingItemActor)) CravingItemActor->Destroy();
CravingItemActor = GetWorld()->SpawnActor(ItemActor);
CurrentCraving = Cast<AItemActor>(CravingItemActor)->ItemType;
CravingItemActor->SetActorEnableCollision(false);
USkeletalMeshComponent* MeshComponent = GetMesh();
if (!MeshComponent->HasAnySockets()) return;
CravingItemActor->AttachToComponent(MeshComponent, FAttachmentTransformRules::SnapToTargetNotIncludingScale, "CravingSocket");
}, 30, true, 3);
}
void ASeagullGameCharacter::EndGame()
{
OnGameEnd.Broadcast("You Win!");
}
void ASeagullGameCharacter::PickupItem()
{
OnPlayerPickupItem.Broadcast();
if (IsValid(CurrentItem))
{
DropItem();
return;
}
USkeletalMeshComponent* MeshComponent = GetMesh();
if (!MeshComponent->HasAnySockets()) return;
if (!IsValid(ClosestItemActor)) return;
CurrentItem = GetWorld()->SpawnActor(Cast<AItemActor>(ClosestItemActor)->ItemNoPhysics);
CurrentItem->AttachToComponent(MeshComponent, FAttachmentTransformRules::SnapToTargetNotIncludingScale, "ItemSocket");
CurrentItem->SetActorEnableCollision(false);
ClosestItemActor->Destroy();
}
void ASeagullGameCharacter::DropItem()
{
if (!IsValid(CurrentItem)) return;
USkeletalMeshComponent* MeshComponent = GetMesh();
CurrentItem->DetachFromActor(FDetachmentTransformRules::KeepWorldTransform);
FVector DropLocation = MeshComponent->GetSocketLocation("ItemSocket");
DropLocation += GetActorForwardVector() * 100;
GetWorld()->SpawnActor(Cast<AItemActor>(CurrentItem)->ItemNoPhysics, &DropLocation);
CurrentItem->Destroy();
CurrentItem = nullptr;
}
void ASeagullGameCharacter::OnPickupBoxBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
}
void ASeagullGameCharacter::OnPickupBoxEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
if (!Cast<AItemActor>(OtherActor)) return;
if (IsValid(OtherActor))
{
if (OtherActor == ClosestItemActor)
{
Cast<UMeshComponent>(OtherActor->GetComponentByClass(UMeshComponent::StaticClass()))->SetRenderCustomDepth(false);
ClosestItemActor = nullptr;
}
}
}
void ASeagullGameCharacter::IncreaseJohnsHunger(const float HungerAmount)
{
JohnsCurrentHunger += HungerAmount;
Score += HungerAmount * 10;
if (JohnsCurrentHunger > JohnsMaxHunger)
{
JohnsCurrentHunger = JohnsMaxHunger;
}
}
void ASeagullGameCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
{
//Jumping
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
//Moving
EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ASeagullGameCharacter::Move);
//Looking
// EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ATP_ThirdPersonCharacter::Look);
//Pickup
EnhancedInputComponent->BindAction(PickupAction, ETriggerEvent::Started, this, &ASeagullGameCharacter::PickupItem);
}
}
void ASeagullGameCharacter::Move(const FInputActionValue& Value)
{
// input is a Vector2D
FVector2D MovementVector = Value.Get<FVector2D>();
if (Controller != nullptr)
{
// find out which way is forward
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
// get forward vector
const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
// get right vector
const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
// add movement
AddMovementInput(ForwardDirection, MovementVector.Y);
AddMovementInput(RightDirection, MovementVector.X);
}
}
void ASeagullGameCharacter::Look(const FInputActionValue& Value)
{
}