367 lines
11 KiB
C++
367 lines
11 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "MyCharacter.h"
|
|
#include "EleriPlayerController.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "Interface/ZoneInteractableInterface.h"
|
|
#include "EleriSaveGame.h"
|
|
#include "EleriGameInstance.h"
|
|
#include "PaperFlipbookComponent.h"
|
|
#include "Kismet/KismetMathLibrary.h"
|
|
#include "../GameObjects/WaterBall.h"
|
|
#include "ProjectEleri/GameObjects/BookActor.h"
|
|
#include "TimeOfDayManager.h"
|
|
#include "Components/PostProcessComponent.h"
|
|
#include "GameFramework/PawnMovementComponent.h"
|
|
#include "ProjectEleri/GameObjects/BenchmarkActor.h"
|
|
#include "ProjectEleri/System/MainBlueprintFunctionLibrary.h"
|
|
#include "ProjectEleri/UI/InteractionWidget.h"
|
|
#include "ProjectEleri/GameObjects/BookActor.h"
|
|
#include "ProjectEleri/GameObjects/BroomActor.h"
|
|
#include "Components/CapsuleComponent.h"
|
|
#include "Components/StatForgeComponent.h"
|
|
#include "GameFramework/SpringArmComponent.h"
|
|
|
|
|
|
#if WITH_EDITOR
|
|
void AMyCharacter::DisplayDebug(UCanvas* Canvas, const FDebugDisplayInfo& DebugDisplay, float& YL, float& YPos) {
|
|
Super::DisplayDebug(Canvas, DebugDisplay, YL, YPos);
|
|
|
|
|
|
}
|
|
#endif
|
|
|
|
// Sets default values
|
|
AMyCharacter::AMyCharacter()
|
|
{
|
|
// 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;
|
|
|
|
InteractableOverlapMesh = CreateDefaultSubobject<UBoxComponent>(FName("Box Collision"));
|
|
InteractableOverlapMesh->SetupAttachment(RootComponent);
|
|
InteractableOverlapMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 33.33f));
|
|
InteractableOverlapMesh->SetRelativeScale3D(FVector(2.0f, 2.0f, 4.0f));
|
|
InteractableOverlapMesh->SetGenerateOverlapEvents(true);
|
|
|
|
StatForgeComponent = CreateDefaultSubobject<UStatForgeComponent>(TEXT("StatForgeComponent"));
|
|
}
|
|
|
|
bool AMyCharacter::IsEditor() const {
|
|
#if WITH_EDITOR
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
// Called when the game starts or when spawned
|
|
void AMyCharacter::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
if (GetCapsuleComponent()) {
|
|
CachedHalfHeight = GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight();
|
|
}
|
|
|
|
if (IsValid(GetWorld())) {
|
|
PlayerController = Cast<AEleriPlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
|
|
}
|
|
|
|
if (IsValid(InteractableOverlapMesh)) {
|
|
InteractableOverlapMesh->OnComponentBeginOverlap.AddDynamic(this, &AMyCharacter::OnEnteredInteractableObject);
|
|
InteractableOverlapMesh->OnComponentEndOverlap.AddDynamic(this, &AMyCharacter::OnLeftInteractableObject);
|
|
}
|
|
|
|
CameraRef = GetComponentByClass<UCameraComponent>();
|
|
SpringArmRef = GetComponentByClass<USpringArmComponent>();
|
|
PlayerController->SetViewTarget(this);
|
|
SpringArmRef->TargetArmLength = DefaultZoom;
|
|
|
|
TSet<UActorComponent*> CameraComponents = GetComponents();
|
|
for (auto Comp : CameraComponents)
|
|
{
|
|
if (UPaperFlipbookComponent* SpriteComp = Cast<UPaperFlipbookComponent>(Comp))
|
|
{
|
|
if (SpriteComp->ComponentTags.Contains("CharacterSprite"))
|
|
{
|
|
CharacterSpriteComponent = SpriteComp;
|
|
}
|
|
}
|
|
}
|
|
|
|
FTransform BookTransform;
|
|
BookTransform.SetLocation(FVector(0,0,0));
|
|
BookTransform.SetRotation(FRotator(0,0,0).Quaternion());
|
|
BookTransform.SetScale3D(FVector::OneVector);
|
|
BookActor = GetWorld()->SpawnActor<ABookActor>(BookActorClass, BookTransform);
|
|
BookActor->AttachToComponent(CameraRef.Get(), FAttachmentTransformRules::KeepRelativeTransform);
|
|
BookActor->SetActorRelativeLocation(FVector(300,0,0));
|
|
BookActor->SetActorRelativeRotation(FRotator(0,90,0).Quaternion());
|
|
|
|
FTransform BroomTransform;
|
|
BroomTransform.SetLocation(FVector(0, 0, 0));
|
|
BroomTransform.SetRotation(FRotator(0, 0, 0).Quaternion());
|
|
BroomTransform.SetScale3D(FVector::OneVector);
|
|
BroomActor = GetWorld()->SpawnActor<ABroomActor>(BroomActorClass, BroomTransform);
|
|
BroomActor->AttachToComponent(RootComponent, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
|
|
BroomActor->SetActorRelativeLocation(FVector(0, 0, -130));
|
|
SetNewCameraPitches(CameraPitchMin, CameraPitchMax);
|
|
}
|
|
|
|
bool AMyCharacter::ShouldSpawnFootprintVfx() const
|
|
{
|
|
bool bFlying = false;
|
|
bool bOnGround = false;
|
|
bool bBenchmarking = false;
|
|
|
|
if (PlayerController)
|
|
{
|
|
bFlying = PlayerController->IsFlying();
|
|
}
|
|
|
|
if (UPawnMovementComponent* MC = GetMovementComponent())
|
|
{
|
|
bOnGround = MC->Velocity.Z <= 0.1f && MC->Velocity.Z >= -0.1f;
|
|
}
|
|
|
|
if (ABenchmarkActor* BenchmarkActor = Cast<ABenchmarkActor>(UGameplayStatics::GetActorOfClass(GetWorld(), ABenchmarkActor::StaticClass())))
|
|
{
|
|
bBenchmarking = BenchmarkActor->bBenchmarkRunning;
|
|
}
|
|
|
|
return !bFlying && bOnGround && !bBenchmarking;
|
|
}
|
|
|
|
// Called every frame
|
|
void AMyCharacter::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
|
|
if (CurrentZoomTimer > 0.f) {
|
|
const float ZoomDelta = (NextZoomOffsetTarget * DeltaTime) / ZoomTime;
|
|
SpringArmRef->TargetArmLength += ZoomDelta;
|
|
CurrentZoomTimer -= DeltaTime;
|
|
UE_LOG(LogTemp, Warning, TEXT("Zooming in: ZoomDelta:%f"), ZoomDelta);
|
|
}
|
|
}
|
|
|
|
void AMyCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
Super::EndPlay(EndPlayReason);
|
|
}
|
|
|
|
void AMyCharacter::SetNewCameraPitches(float NewMinPitch, float NewMaxPitch)
|
|
{
|
|
PlayerCameraManager = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0);
|
|
if (IsValid(PlayerCameraManager))
|
|
{
|
|
PlayerCameraManager->ViewPitchMin = NewMinPitch;
|
|
PlayerCameraManager->ViewPitchMax = NewMaxPitch;
|
|
}
|
|
}
|
|
|
|
FVector AMyCharacter::GetCameraWorldPosition() {
|
|
FVector CameraLocation;
|
|
FRotator CameraRotation;
|
|
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(CameraLocation, CameraRotation);
|
|
return CameraLocation;
|
|
}
|
|
|
|
void AMyCharacter::ToggleBook(bool bOpen)
|
|
{
|
|
if (!IsValid(BookActor)) return;
|
|
float Aspect = 0.f;
|
|
if (GEngine && GEngine->GameViewport)
|
|
{
|
|
FVector2D Result = FVector2D(1, 1);
|
|
GEngine->GameViewport->GetViewportSize( Result);
|
|
Aspect = ((float)Result.X) / ((float)Result.Y);
|
|
}
|
|
|
|
if(Aspect == 0.f)
|
|
Aspect = ((float)GSystemResolution.ResX) / ((float)GSystemResolution.ResY);
|
|
BookActor->SetActorRelativeLocation(FVector(168.75f * Aspect, 0.f, 0.f));
|
|
|
|
BookActor->ToggleBook(bOpen);
|
|
/*if (UPostProcessComponent* PPComp = Cast<UPostProcessComponent>(FindComponentByTag(UPostProcessComponent::StaticClass(), FName("BookPP"))))
|
|
{
|
|
PPComp->bEnabled = bOpen;
|
|
}*/
|
|
}
|
|
|
|
|
|
// Called to bind functionality to input
|
|
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
|
{
|
|
Super::SetupPlayerInputComponent(PlayerInputComponent);
|
|
|
|
}
|
|
|
|
void AMyCharacter::OnHarvestSeed_Implementation(class UItem* HarvestedItem)
|
|
{
|
|
}
|
|
|
|
void AMyCharacter::ZoomCamera(float CameraZoomAmount, float Time)
|
|
{
|
|
CurrentZoomTimer = Time;
|
|
ZoomTime = Time;
|
|
NextZoomOffsetTarget = CameraZoomAmount;
|
|
}
|
|
|
|
void AMyCharacter::ZoomBack(float Time) {
|
|
ZoomCamera(SpringArmRef->TargetArmLength - DefaultZoom, Time);
|
|
}
|
|
|
|
void AMyCharacter::ReturnCameraToPlayer() {
|
|
SpringArmRef->TargetArmLength = DefaultZoom;
|
|
PlayerController->SetViewTargetWithBlend(this, 0.5f);
|
|
}
|
|
|
|
void AMyCharacter::SetSaveableTagData(FGameplayTag Tag, int32 NewValue) {
|
|
SaveableTagData.Add(Tag, NewValue);
|
|
}
|
|
|
|
int32 AMyCharacter::GetSavableTagData(FGameplayTag Tag) const {
|
|
if (const int32* TagValue = SaveableTagData.Find(Tag)) {
|
|
return *TagValue;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
FActorSaveData AMyCharacter::RequestSave() {
|
|
FActorSaveData ActorData;
|
|
ActorData.ActorName = GetFName();
|
|
ActorData.Transform = GetActorTransform();
|
|
ActorData.SaveableTagData = SaveableTagData;
|
|
|
|
return ActorData;
|
|
}
|
|
|
|
void AMyCharacter::RequestLoad(FActorSaveData& Data) {
|
|
if (Data.ActorName != GetFName()) return;
|
|
|
|
SetActorTransform(Data.Transform);
|
|
SaveableTagData = Data.SaveableTagData;
|
|
ISaveableObjectInterface::Execute_OnDataLoaded(this);
|
|
}
|
|
|
|
|
|
void AMyCharacter::AttemptLookUp(float val, bool controllerInput)
|
|
{
|
|
AddControllerPitchInput(val);
|
|
Pitch = GetControlRotation().Pitch;
|
|
}
|
|
|
|
void AMyCharacter::OnEnteredInteractableObject(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& Hit)
|
|
{
|
|
if (IsValid(PlayerController) && !PlayerController->IsPaused()) {
|
|
if (PlayerController->IsDialogueOpen()) {
|
|
OnInteractBasedOnDoing();
|
|
}
|
|
else {
|
|
PlayerController->AddInteractableObject(OtherActor);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AMyCharacter::OnLeftInteractableObject(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
|
|
{
|
|
PlayerController->RemoveInteractableObject(OtherActor);
|
|
}
|
|
|
|
void AMyCharacter::RotateTowardsCamera(FRotator CameraRot)
|
|
{
|
|
if (bIsWatering)
|
|
{
|
|
const FRotator ActorRot = GetActorRotation();
|
|
const FRotator FinalRot = FRotator(ActorRot.Pitch, CameraRot.Yaw, ActorRot.Roll);
|
|
SetActorRotation(UKismetMathLibrary::RInterpTo(ActorRot, FinalRot, UGameplayStatics::GetWorldDeltaSeconds(GetWorld()), 10.0f));
|
|
}
|
|
}
|
|
|
|
void AMyCharacter::HarvestSeed(class UItem* HarvestedItem)
|
|
{
|
|
}
|
|
|
|
AActor* AMyCharacter::GetClosestActor(TArray<AActor*> ActorSet) {
|
|
if (ActorSet.Num() <= 0) return nullptr;
|
|
|
|
AActor* Closest = ActorSet[0];
|
|
const float DistanceSqr = FVector::DistSquared(GetActorLocation(), Closest->GetActorLocation());
|
|
for (AActor* Actor : ActorSet) {
|
|
if (FVector::DistSquared(GetActorLocation(), Actor->GetActorLocation()) <= DistanceSqr) {
|
|
Closest = Actor;
|
|
}
|
|
}
|
|
return Closest;
|
|
}
|
|
|
|
void AMyCharacter::InitiateSave() {
|
|
if(UEleriGameInstance* GameInstance = Cast<UEleriGameInstance>(UGameplayStatics::GetGameInstance(GetWorld())))
|
|
GameInstance->SaveGame();
|
|
}
|
|
|
|
void AMyCharacter::InitiateLoad()
|
|
{
|
|
if (!IsValid(GetWorld())) return;
|
|
|
|
UEleriGameInstance* GameInstance = Cast<UEleriGameInstance>(UGameplayStatics::GetGameInstance(GetWorld()));
|
|
GameInstance->LoadGame();
|
|
}
|
|
|
|
void AMyCharacter::PlantSeed()
|
|
{
|
|
bIs_Planting = !bIs_Planting;
|
|
}
|
|
|
|
void AMyCharacter::BeginWatering()
|
|
{
|
|
if (!GetWorld()) return;
|
|
|
|
FActorSpawnParameters SpawnParams;
|
|
SpawnParams.Owner = this;
|
|
const FVector WaterBallSpawn = GetActorLocation();
|
|
WaterBallSpawned = Cast<AWaterBall>(GetWorld()->SpawnActor(WaterBallClass, &WaterBallSpawn, &FRotator::ZeroRotator, SpawnParams));
|
|
if (WaterBallSpawned)
|
|
{
|
|
const FAttachmentTransformRules AttachRules = FAttachmentTransformRules(EAttachmentRule::KeepRelative, false);
|
|
WaterBallSpawned->AttachToComponent(Cast<USceneComponent>(this->GetComponentByClass(USceneComponent::StaticClass())), AttachRules);
|
|
WaterBallSpawned->SetActorLocation(GetActorLocation() + (CameraRef->GetForwardVector() * 100.f) + (GetActorRightVector() * 200.f));
|
|
WaterBallSpawned->BeginAnimating();
|
|
}
|
|
}
|
|
|
|
void AMyCharacter::EndWatering() const
|
|
{
|
|
if (!GetWorld() || !WaterBallSpawned) return;
|
|
|
|
if (WaterBallSpawned)
|
|
{
|
|
WaterBallSpawned->EndAnimating();
|
|
}
|
|
}
|
|
|
|
void AMyCharacter::ThrowWaterBall() const
|
|
{
|
|
if (WaterBallSpawned)
|
|
{
|
|
WaterBallSpawned->ThrowBall();
|
|
}
|
|
}
|
|
|
|
void AMyCharacter::ToggleBroomActor(bool bActive)
|
|
{
|
|
bUseControllerRotationYaw = bActive;
|
|
if (GetCapsuleComponent()) {
|
|
GetCapsuleComponent()->SetCapsuleHalfHeight(bActive? CachedHalfHeight * 3 : CachedHalfHeight);
|
|
}
|
|
if (BroomActor) {
|
|
BroomActor->K2_BroomAnimationToggle(bActive);
|
|
}
|
|
}
|
|
|
|
|
|
|