1306 lines
42 KiB
C++
1306 lines
42 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
#include "EleriPlayerController.h"
|
|
#include "EnhancedInputComponent.h"
|
|
#include "GameFramework/Character.h"
|
|
#include "EnhancedInputSubsystems.h"
|
|
#include "GameFramework/CharacterMovementComponent.h"
|
|
#include "ProjectEleri/System/MainBlueprintFunctionLibrary.h"
|
|
#include "ProjectEleri/Components/MoveActorsComponent.h"
|
|
#include "../GameObjects/RemovableStaticMeshActor.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "BookOfAlchemyManager.h"
|
|
#include "AlchemyManager.h"
|
|
#include "TimerManager.h"
|
|
#include "ProjectEleri/UI/CalendarScreen.h"
|
|
#include "ProjectEleri/UI/InteractionWidget.h"
|
|
#include "UI/AlchemyWidget.h"
|
|
#include "UI/EleriBaseWidget.h"
|
|
#include "ProjectEleri/GameObjects/BookActor.h"
|
|
#include "UI/TradeWidget.h"
|
|
#include "ProjectEleri/Public/UI/SelectionManager.h"
|
|
#include "ProjectEleri/DialogueSystem/DialogueWidget.h"
|
|
#include "Subsystem/InteractionSubsystem.h"
|
|
#include "Interface/InteractableActorInterface.h"
|
|
#include "EngineUtils.h"
|
|
#include "Components/StatForgeComponent.h"
|
|
#include "Helpers/StatForgeFunctionLibrary.h"
|
|
#include "ProjectEleri/Data/StatDefinitions.h"
|
|
#include "ProjectEleri/Items/SeedBedActor.h"
|
|
#include "ProjectEleri/Settings/EleriGameSettings.h"
|
|
#include "ProjectEleri/System/EleriGameplayTags.h"
|
|
|
|
AEleriPlayerController::AEleriPlayerController(const FObjectInitializer &ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
{
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
PrimaryActorTick.bTickEvenWhenPaused = true;
|
|
}
|
|
|
|
void AEleriPlayerController::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
PlayerCharacter = Cast<AMyCharacter>(GetCharacter());
|
|
MoveActorsComp = PlayerCharacter->GetComponentByClass<UMoveActorsComponent>();
|
|
|
|
MainGameUI = CreateWidget<UMainGameWidget>(this, MainGameWidgetBlueprint);
|
|
MainGameUI->AddToViewport();
|
|
|
|
if (UCharacterMovementComponent *CharMovement = PlayerCharacter->GetCharacterMovement())
|
|
{
|
|
CharMovement->MaxWalkSpeed = MinMovementSpeed;
|
|
}
|
|
|
|
MovementComponent = PlayerCharacter->GetComponentByClass<UCharacterMovementComponent>();
|
|
MovementDirection = FVector2D(0, -1);
|
|
bFlying = false;
|
|
BookOfAlchemyManager = Cast<ABookOfAlchemyManager>(UGameplayStatics::GetActorOfClass(GetWorld(), ABookOfAlchemyManager::StaticClass()));
|
|
AlchemyManager = Cast<AAlchemyManager>(UGameplayStatics::GetActorOfClass(GetWorld(), AAlchemyManager::StaticClass()));
|
|
|
|
SelectionManagerInventorySlots = NewObject<USelectionManager>();
|
|
ToggleMovement(true);
|
|
}
|
|
|
|
void AEleriPlayerController::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
ToggleMovement(true);
|
|
|
|
Super::EndPlay(EndPlayReason);
|
|
}
|
|
|
|
void AEleriPlayerController::ToggleMovement(bool bActive)
|
|
{
|
|
UStatForgeComponent* StatForgeComponent = UMainBlueprintFunctionLibrary::GetStatForgeComponentFromPlayer(this);
|
|
if (!StatForgeComponent) return;
|
|
|
|
if (bActive)
|
|
{
|
|
StatForgeComponent->RemoveGameplayStatEffect(MovementDisabledEffect);
|
|
return;
|
|
}
|
|
|
|
const UEleriGameSettings* GameSettings = UEleriGameSettings::GetEleriGameSettings();
|
|
ensure(GameSettings);
|
|
MovementDisabledEffect = StatForgeComponent->ApplyGameplayStatEffect(GameSettings->MovementDisableEffectClass, TMap<FName, float>());
|
|
}
|
|
|
|
void AEleriPlayerController::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
if (ACharacter *Char = GetCharacter())
|
|
{
|
|
if (UCharacterMovementComponent *CharMovement = Char->GetCharacterMovement())
|
|
{
|
|
if (CharMovement->IsFalling())
|
|
{
|
|
CharMovement->GravityScale = 25;
|
|
}
|
|
else
|
|
{
|
|
CharMovement->GravityScale = 3;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!ActorsOverlappingWith.IsEmpty())
|
|
{
|
|
for (int32 i = 0; i < ActorsOverlappingWith.Num(); i++)
|
|
{
|
|
if (!ActorsOverlappingWith[i]->Implements<UInteractableActorInterface>() || !IInteractableActorInterface::Execute_IsInteractable(ActorsOverlappingWith[i]))
|
|
{
|
|
RemoveInteractableObject(ActorsOverlappingWith[i]);
|
|
i--;
|
|
}
|
|
}
|
|
if (!IsInMenu() && !bIsInteractionMenuVisible)
|
|
{
|
|
ToggleInteractionMenu(true);
|
|
}
|
|
else if (IsInMenu() && bIsInteractionMenuVisible)
|
|
{
|
|
ToggleInteractionMenu(false);
|
|
}
|
|
}
|
|
|
|
if (TickBookAnimating)
|
|
{
|
|
TickBookTimer -= DeltaTime;
|
|
if (TickBookTimer <= 0.f)
|
|
{
|
|
DisableBookAnimating();
|
|
}
|
|
}
|
|
}
|
|
|
|
// BIND INPUT
|
|
void AEleriPlayerController::SetupInputComponent()
|
|
{
|
|
Super::SetupInputComponent();
|
|
|
|
// Make sure that we are using a UEnhancedInputComponent; if not, the project is not configured correctly.
|
|
if (UEnhancedInputComponent *PlayerEnhancedInputComponent = Cast<UEnhancedInputComponent>(InputComponent))
|
|
{
|
|
if (MoveAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AEleriPlayerController::OnMove);
|
|
}
|
|
if (StartFlyingAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(StartFlyingAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnStartFlyingAction);
|
|
}
|
|
if (SprintAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnSprint);
|
|
PlayerEnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &AEleriPlayerController::OnStopSprint);
|
|
|
|
PlayerEnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Triggered, this, &AEleriPlayerController::OnFlyDownwardsAction);
|
|
}
|
|
if (JumpAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnJump);
|
|
PlayerEnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &AEleriPlayerController::OnStopJump);
|
|
|
|
PlayerEnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &AEleriPlayerController::OnFlyUpwardsAction);
|
|
}
|
|
if (LookAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AEleriPlayerController::OnLook);
|
|
}
|
|
if (ToggleCameraLook)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(ToggleCameraLook, ETriggerEvent::Started, this, &AEleriPlayerController::OnLookEnable);
|
|
PlayerEnhancedInputComponent->BindAction(ToggleCameraLook, ETriggerEvent::Completed, this, &AEleriPlayerController::OnLookDisable);
|
|
}
|
|
if (WateringAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(WateringAction, ETriggerEvent::Started, this,
|
|
&AEleriPlayerController::OnWateringActionStart);
|
|
PlayerEnhancedInputComponent->BindAction(WateringAction, ETriggerEvent::Completed, this,
|
|
&AEleriPlayerController::OnWateringActionEnd);
|
|
}
|
|
if (WateringThrowAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(WateringThrowAction, ETriggerEvent::Started, this,
|
|
&AEleriPlayerController::OnWateringThrowAction);
|
|
}
|
|
|
|
if (OpenMainMenuAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(OpenMainMenuAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnMainMenuToggle);
|
|
}
|
|
if (InventoryAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(InventoryAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnInventoryToggle);
|
|
}
|
|
if (BookAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(BookAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnBookToggle);
|
|
}
|
|
if (OrdersAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(OrdersAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnOrdersToggle);
|
|
}
|
|
if (CalendarAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(CalendarAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnCalendarToggle);
|
|
}
|
|
|
|
if (InteractAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnInteract);
|
|
}
|
|
if (InteractExitAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(InteractExitAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnInteractExit);
|
|
}
|
|
|
|
if (WaterSeedAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(WaterSeedAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnHarvestSeed);
|
|
}
|
|
|
|
if (UiBackAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(UiBackAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnControllerBackAction);
|
|
}
|
|
|
|
if (UiTabLeftAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(UiTabLeftAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnControllerTabLeftAction);
|
|
}
|
|
|
|
if (UiTabRightAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(UiTabRightAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnControllerTabRightAction);
|
|
}
|
|
|
|
//---------------------
|
|
// OBJECT REMOVAL INPUTS
|
|
//---------------------
|
|
|
|
if (StartObjectRemovalModeAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(StartObjectRemovalModeAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnStartObjectRemovalAction);
|
|
}
|
|
if (RemoveAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(RemoveAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnRemoveAction);
|
|
}
|
|
if (ExitRemoveModeAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(ExitRemoveModeAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnExitRemoveModeAction);
|
|
}
|
|
if (StartMovingAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(StartMovingAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnStartMovingAction);
|
|
}
|
|
if (PlaceObjectAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(PlaceObjectAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnPlaceObjectAction);
|
|
}
|
|
if (RotateObjectAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(RotateObjectAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnRotateObjectAction);
|
|
}
|
|
if (ToggleGridAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(ToggleGridAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnToggleGridAction);
|
|
}
|
|
|
|
//---------------------
|
|
// BOOK INPUTS
|
|
//---------------------
|
|
if (BookNextPageAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(BookNextPageAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnBookNextPage);
|
|
}
|
|
if (BookPreviousPageAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(BookPreviousPageAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnBookPreviousPage);
|
|
}
|
|
if (BookItemTabAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(BookItemTabAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnBookItemTab);
|
|
}
|
|
if (BookPotionTabAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(BookPotionTabAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnBookPotionTab);
|
|
}
|
|
if (BookNextLetterAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(BookNextLetterAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnBookNextLetter);
|
|
}
|
|
if (BookPreviousLetterAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(BookPreviousLetterAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnBookPreviousLetter);
|
|
}
|
|
if (BookExitAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(BookExitAction, ETriggerEvent::Started, this, &AEleriPlayerController::OnBookExit);
|
|
}
|
|
|
|
//---------------------
|
|
// ALCHEMY INPUTS
|
|
//---------------------
|
|
if (AlchemyStirringDirectionalInput)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(AlchemyStirringDirectionalInput, ETriggerEvent::Triggered, this,
|
|
&AEleriPlayerController::OnAlchemyStirringDirectionInput);
|
|
}
|
|
if (AlchemyConfirmInput)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(AlchemyConfirmInput, ETriggerEvent::Started, this,
|
|
&AEleriPlayerController::OnAlchemyConfirmInput);
|
|
}
|
|
|
|
//---------------------
|
|
// INTERACTION MENU INPUTS
|
|
//---------------------
|
|
if (InteractionMenuSelectAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(InteractionMenuSelectAction, ETriggerEvent::Started, this,
|
|
&AEleriPlayerController::OnInteractionMenuSelectAction);
|
|
}
|
|
if (InteractionMenuUpAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(InteractionMenuUpAction, ETriggerEvent::Started, this,
|
|
&AEleriPlayerController::OnInteractionMenuUpAction);
|
|
}
|
|
if (InteractionMenuDownAction)
|
|
{
|
|
PlayerEnhancedInputComponent->BindAction(InteractionMenuDownAction, ETriggerEvent::Started, this,
|
|
&AEleriPlayerController::OnInteractionMenuDownAction);
|
|
}
|
|
}
|
|
}
|
|
|
|
// INIT
|
|
|
|
void AEleriPlayerController::ClientRestart_Implementation(APawn *NewPawn)
|
|
{
|
|
Super::ClientRestart_Implementation(NewPawn);
|
|
|
|
// Get the Enhanced Input Local Player Subsystem from the Local Player related to our Player Controller.
|
|
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
|
{
|
|
// PawnClientRestart can run more than once in an Actor's lifetime, so start by clearing out any leftover mappings.
|
|
Subsystem->ClearAllMappings();
|
|
|
|
// Add each mapping context, along with their priority values. Higher values outprioritize lower values.
|
|
Subsystem->AddMappingContext(MovementContext, 1);
|
|
// Subsystem->AddMappingContext(MainUiContext, 2);
|
|
Subsystem->AddMappingContext(UiContext, 3);
|
|
Subsystem->AddMappingContext(ActionContext, 4);
|
|
}
|
|
}
|
|
|
|
// LOCOMOTION INPUT
|
|
|
|
void AEleriPlayerController::OnMove(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu())
|
|
return;
|
|
|
|
const FVector2D AnalogueValue = Value.Get<FInputActionValue::Axis2D>();
|
|
MovementDirection = AnalogueValue;
|
|
|
|
if (PlayerCharacter)
|
|
{
|
|
if (UStatForgeFunctionLibrary::HasTag(CharacterState::MovementDisabled, PlayerCharacter))
|
|
{
|
|
return;
|
|
}
|
|
|
|
const float AppliedMovementVelocity = UStatForgeFunctionLibrary::GetStatValue(FStat::MovementSpeedMultiplier, PlayerCharacter);
|
|
|
|
const FVector ForwardVec = PlayerCharacter->GetPlayerCamera()->GetForwardVector();
|
|
const FVector RightVec = PlayerCharacter->GetPlayerCamera()->GetRightVector();
|
|
|
|
PlayerCharacter->AddMovementInput(ForwardVec, MovementDirection.Y * AppliedMovementVelocity);
|
|
PlayerCharacter->AddMovementInput(RightVec, MovementDirection.X * AppliedMovementVelocity);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnSprint(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu() || Watering)
|
|
return;
|
|
|
|
ACharacter *Char = GetCharacter();
|
|
if (Char != nullptr && !bFlying)
|
|
{
|
|
MovementVelocity = 13.0f;
|
|
if (UCharacterMovementComponent *CharMovement = Char->GetCharacterMovement())
|
|
{
|
|
CharMovement->MaxWalkSpeed = MaxMovementSpeed;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnStopSprint(const FInputActionValue &Value)
|
|
{
|
|
ACharacter *Char = GetCharacter();
|
|
if (Char != nullptr)
|
|
{
|
|
MovementVelocity = 1.0f;
|
|
if (UCharacterMovementComponent *CharMovement = Char->GetCharacterMovement())
|
|
{
|
|
CharMovement->MaxWalkSpeed = MinMovementSpeed;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnJump(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu() || Watering)
|
|
return;
|
|
|
|
ACharacter *Char = GetCharacter();
|
|
if (Char != nullptr && !bFlying)
|
|
{
|
|
Char->Jump();
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnStopJump(const FInputActionValue &Value)
|
|
{
|
|
ACharacter *Char = GetCharacter();
|
|
if (Char != nullptr)
|
|
{
|
|
Char->StopJumping();
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnLook(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu())
|
|
return;
|
|
|
|
FVector2D AnalogueValue = Value.Get<FInputActionValue::Axis2D>();
|
|
|
|
if (PlayerCharacter != nullptr)
|
|
{
|
|
AddYawInput(AnalogueValue.X);
|
|
AddPitchInput(AnalogueValue.Y);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnLookEnable(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu())
|
|
return;
|
|
|
|
AMyCharacter *Char = Cast<AMyCharacter>(GetCharacter());
|
|
if (Char != nullptr)
|
|
{
|
|
Char->RotateCam = true;
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnLookDisable(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu())
|
|
return;
|
|
|
|
AMyCharacter *Char = Cast<AMyCharacter>(GetCharacter());
|
|
if (Char != nullptr)
|
|
{
|
|
Char->RotateCam = false;
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnWateringActionStart(const FInputActionValue &Value)
|
|
{
|
|
if (!PlayerCharacter ||
|
|
PlayerCharacter->CurrentlyDoing != ECurrentlyDoing::NOTHING ||
|
|
MainGameUI->IsAlchemyOpen() ||
|
|
IsInMenu())
|
|
return;
|
|
|
|
Watering = true;
|
|
PlayerCharacter->BeginWatering();
|
|
OnWatering.Broadcast(Watering);
|
|
OnChangeInputContext.Broadcast(2);
|
|
|
|
ToggleMovement(false);
|
|
}
|
|
|
|
void AEleriPlayerController::OnWateringActionEnd(const FInputActionValue &Value)
|
|
{
|
|
if (!PlayerCharacter ||
|
|
PlayerCharacter->CurrentlyDoing != ECurrentlyDoing::NOTHING ||
|
|
!Watering)
|
|
return;
|
|
|
|
Watering = false;
|
|
PlayerCharacter->EndWatering();
|
|
OnWatering.Broadcast(Watering);
|
|
OnChangeInputContext.Broadcast(1);
|
|
|
|
ToggleMovement(true);
|
|
}
|
|
|
|
void AEleriPlayerController::OnWateringThrowAction(const FInputActionValue &Value)
|
|
{
|
|
if (!PlayerCharacter ||
|
|
!Watering ||
|
|
PlayerCharacter->CurrentlyDoing != ECurrentlyDoing::NOTHING)
|
|
return;
|
|
|
|
PlayerCharacter->ThrowWaterBall();
|
|
OnChangeInputContext.Broadcast(1);
|
|
}
|
|
|
|
void AEleriPlayerController::OnStartFlyingAction(const FInputActionValue &Value)
|
|
{
|
|
if (bAnimatingFlying)
|
|
return;
|
|
|
|
bAnimatingFlying = true;
|
|
bFlying = !bFlying;
|
|
if (bFlying)
|
|
{
|
|
MovementComponent->AddImpulse(FVector::UpVector * 400000.f, false);
|
|
FTimerHandle FlyTimerHandle;
|
|
GetWorld()->GetTimerManager().SetTimer(FlyTimerHandle, FTimerDelegate::CreateLambda([this]
|
|
{
|
|
if (bFlying)
|
|
{
|
|
MovementComponent->Velocity = FVector::ZeroVector;
|
|
MovementComponent->SetMovementMode(EMovementMode::MOVE_Flying);
|
|
} }),
|
|
0.25f, false);
|
|
}
|
|
else
|
|
{
|
|
MovementComponent->SetMovementMode(EMovementMode::MOVE_Walking);
|
|
}
|
|
|
|
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
|
{
|
|
// PawnClientRestart can run more than once in an Actor's lifetime, so start by clearing out any leftover mappings.
|
|
if (bFlying)
|
|
{
|
|
Subsystem->RemoveMappingContext(MovementContext);
|
|
Subsystem->AddMappingContext(FlyingContext, 1);
|
|
}
|
|
else
|
|
{
|
|
Subsystem->RemoveMappingContext(FlyingContext);
|
|
Subsystem->AddMappingContext(MovementContext, 1);
|
|
}
|
|
}
|
|
if (PlayerCharacter)
|
|
{
|
|
PlayerCharacter->ToggleBroomActor(bFlying);
|
|
PlayerCharacter->SetNewCameraPitches(bFlying ? -30 : PlayerCharacter->CameraPitchMin, bFlying ? 30 : PlayerCharacter->CameraPitchMax);
|
|
PlayerCharacter->OnToggleFlying(bFlying);
|
|
}
|
|
OnPlayerToggleFlying.Broadcast(bFlying);
|
|
}
|
|
|
|
void AEleriPlayerController::OnFlyUpwardsAction(const FInputActionValue &Value)
|
|
{
|
|
ACharacter *Char = GetCharacter();
|
|
if (bFlying)
|
|
{
|
|
float AnalogueValue = Value.Get<FInputActionValue::Axis1D>();
|
|
Char->AddMovementInput(Char->GetActorUpVector(), AnalogueValue);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnFlyDownwardsAction(const FInputActionValue &Value)
|
|
{
|
|
ACharacter *Char = GetCharacter();
|
|
if (bFlying)
|
|
{
|
|
float AnalogueValue = Value.Get<FInputActionValue::Axis1D>();
|
|
Char->AddMovementInput(Char->GetActorUpVector(), -AnalogueValue);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnStartObjectRemovalAction(const FInputActionValue &Value)
|
|
{
|
|
if (MoveActorsComp->MovingActor)
|
|
{
|
|
ExitRemoveMode();
|
|
return;
|
|
}
|
|
|
|
if (IsInMenu() || Paused)
|
|
return;
|
|
|
|
MoveActorsComp->StartObjectRemoval(!MoveActorsComp->IsRemovingMode());
|
|
PlacingStuff = !MoveActorsComp->IsRemovingMode();
|
|
// Get the Enhanced Input Local Player Subsystem from the Local Player related to our Player Controller.
|
|
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
|
{
|
|
Subsystem->AddMappingContext(RemoveModeContext, 8);
|
|
}
|
|
|
|
OnRemovalModeToggle.Broadcast(true);
|
|
}
|
|
|
|
void AEleriPlayerController::OnRemoveAction(const FInputActionValue &Value)
|
|
{
|
|
if (MoveActorsComp->MovingActor)
|
|
{
|
|
MoveActorsComp->PlaceableActionUsed(ERemovalAction::REMOVE);
|
|
MoveActorsComp->MovingActor = nullptr;
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::ExitRemoveMode()
|
|
{
|
|
if (MoveActorsComp->MovingActor)
|
|
{
|
|
MoveActorsComp->PlaceableActionUsed(ERemovalAction::EXIT);
|
|
MoveActorsComp->StartObjectRemoval(false);
|
|
if (IsValid(MoveActorsComp->MovingActor))
|
|
{
|
|
MoveActorsComp->MovingActor->Place(true);
|
|
}
|
|
MoveActorsComp->RemoveObjectForPlacing();
|
|
}
|
|
else
|
|
{
|
|
MoveActorsComp->StartObjectRemoval(false);
|
|
}
|
|
PlayerCharacter->bAlreadyInteracting = false;
|
|
PlayerCharacter->CurrentlyDoing = ECurrentlyDoing::NOTHING;
|
|
PlacingStuff = false;
|
|
OnRemovalModeToggle.Broadcast(false);
|
|
}
|
|
|
|
void AEleriPlayerController::OnExitRemoveModeAction(const FInputActionValue &Value)
|
|
{
|
|
ExitRemoveMode();
|
|
}
|
|
|
|
void AEleriPlayerController::OnStartMovingAction(const FInputActionValue &Value)
|
|
{
|
|
if (MoveActorsComp->MovingActor)
|
|
{
|
|
MoveActorsComp->PlaceableActionUsed(ERemovalAction::START_MOVE);
|
|
MoveActorsComp->StartObjectRemoval(false);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnPlaceObjectAction(const FInputActionValue &Value)
|
|
{
|
|
if (MoveActorsComp->MovingActor && !MoveActorsComp->MovingActor->CanPlace())
|
|
return;
|
|
|
|
if (MoveActorsComp->MovingActor)
|
|
{
|
|
UItemDatabase* ItemDatabase = UGameplayStatics::GetGameInstance(GetWorld())->GetSubsystem<UItemDatabase>();
|
|
UInventoryComponent *Inventory = UMainBlueprintFunctionLibrary::GetPlayerInventory(this);
|
|
UItemDataAsset* DataAsset = MoveActorsComp->MovingActor->ItemDataAsset;
|
|
|
|
if (!MoveActorsComp->PlaceableActionUsed(ERemovalAction::PLACE))
|
|
return;
|
|
|
|
int32 StackCount = Inventory->GetStackForItem(DataAsset->GetPrimaryAssetId(), false);
|
|
if (StackCount > 0)
|
|
{
|
|
ensure(ItemDatabase);
|
|
ItemDatabase->SpawnDecorationItem(DataAsset);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OnInteract(Value);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnRotateObjectAction(const FInputActionValue &Value)
|
|
{
|
|
float RotateForward = Value.Get<FInputActionValue::Axis1D>();
|
|
if (MoveActorsComp->MovingActor)
|
|
MoveActorsComp->MovingActor->Rotate(RotateForward > 0);
|
|
}
|
|
|
|
void AEleriPlayerController::OnToggleGridAction(const FInputActionValue &Value)
|
|
{
|
|
if (MoveActorsComp)
|
|
{
|
|
MoveActorsComp->ToggleGridMovement();
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::AddInteractableObject(UObject *ObjectToAdd)
|
|
{
|
|
if (IsValid(ObjectToAdd) && ObjectToAdd->Implements<UInteractableActorInterface>() && IInteractableActorInterface::Execute_IsInteractable(ObjectToAdd))
|
|
{
|
|
FText InteractableText = IInteractableActorInterface::Execute_GetInteractionText(ObjectToAdd);
|
|
if (UMainGameWidget *MainWidget = UMainBlueprintFunctionLibrary::GetMainGameWidget(this))
|
|
{
|
|
if (UInteractionWidget *InteractionWidget = MainWidget->GetInteractionWidget())
|
|
{
|
|
InteractionWidget->PushInteractableObject(ObjectToAdd, InteractableText);
|
|
}
|
|
}
|
|
ActorsOverlappingWith.Add(ObjectToAdd);
|
|
}
|
|
if (!ActorsOverlappingWith.IsEmpty())
|
|
{
|
|
ToggleInteractionMenu(true);
|
|
}
|
|
if (ActorsOverlappingWith.Num() == 1)
|
|
{
|
|
SelectedInteractable = ActorsOverlappingWith[0];
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::RemoveInteractableObject(UObject *ObjectToAdd)
|
|
{
|
|
if (IsPaused())
|
|
return;
|
|
|
|
if (IsValid(ObjectToAdd) && ObjectToAdd->Implements<UInteractableActorInterface>())
|
|
{
|
|
FText InteractableText = IInteractableActorInterface::Execute_GetInteractionText(ObjectToAdd);
|
|
if (UMainGameWidget *MainWidget = UMainBlueprintFunctionLibrary::GetMainGameWidget(this))
|
|
{
|
|
if (UInteractionWidget *InteractionWidget = MainWidget->GetInteractionWidget())
|
|
{
|
|
InteractionWidget->PopInteractableObject(ObjectToAdd);
|
|
}
|
|
}
|
|
}
|
|
ActorsOverlappingWith.Remove(ObjectToAdd);
|
|
if (SelectedInteractable == ObjectToAdd)
|
|
{
|
|
SelectedInteractable = nullptr;
|
|
if (!ActorsOverlappingWith.IsEmpty())
|
|
{
|
|
SelectedInteractable = ActorsOverlappingWith[ActorsOverlappingWith.Num() - 1];
|
|
}
|
|
}
|
|
if (ActorsOverlappingWith.IsEmpty())
|
|
{
|
|
ToggleInteractionMenu(true);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::ToggleInteractionMenu(bool bActive)
|
|
{
|
|
bIsInteractionMenuVisible = bActive;
|
|
if (UMainGameWidget *MainWidget = UMainBlueprintFunctionLibrary::GetMainGameWidget(this))
|
|
{
|
|
if (UInteractionWidget *InteractionWidget = MainWidget->GetInteractionWidget())
|
|
{
|
|
InteractionWidget->OnDisplayInteractionMenu.Broadcast(bActive);
|
|
}
|
|
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
|
{
|
|
// if (bActive)
|
|
// Subsystem->AddMappingContext(InteractionMenuContext, 15);
|
|
// else
|
|
// Subsystem->RemoveMappingContext(InteractionMenuContext);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnInteractionMenuSelectAction(const FInputActionValue &Value)
|
|
{
|
|
|
|
}
|
|
|
|
void AEleriPlayerController::OnInteractionMenuUpAction(const FInputActionValue &Value)
|
|
{
|
|
if (UMainGameWidget *MainWidget = UMainBlueprintFunctionLibrary::GetMainGameWidget(this))
|
|
{
|
|
if (UInteractionWidget *InteractionWidget = MainWidget->GetInteractionWidget())
|
|
{
|
|
SelectedInteractable = InteractionWidget->SelectInteractableObject(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnInteractionMenuDownAction(const FInputActionValue &Value)
|
|
{
|
|
if (UMainGameWidget *MainWidget = UMainBlueprintFunctionLibrary::GetMainGameWidget(this))
|
|
{
|
|
if (UInteractionWidget *InteractionWidget = MainWidget->GetInteractionWidget())
|
|
{
|
|
SelectedInteractable = InteractionWidget->SelectInteractableObject(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnControllerUpAction(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu())
|
|
{
|
|
OnUiButtonPressed.Broadcast(UiInputType::UP);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnControllerDownAction(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu())
|
|
{
|
|
OnUiButtonPressed.Broadcast(UiInputType::DOWN);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnControllerLeftAction(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu())
|
|
{
|
|
OnUiButtonPressed.Broadcast(UiInputType::LEFT);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnControllerRightAction(const FInputActionValue &Value)
|
|
{
|
|
if (IsInMenu())
|
|
{
|
|
OnUiButtonPressed.Broadcast(UiInputType::RIGHT);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnControllerConfirmAction(const FInputActionValue &Value)
|
|
{
|
|
if (MainGameUI->GetWidgetStack().IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
MainGameUI->GetWidgetStack()[MainGameUI->GetWidgetStack().Num() - 1]->HandleUiInputAction(EEleriUIInputAction::Select);
|
|
}
|
|
|
|
void AEleriPlayerController::OnControllerBackAction(const FInputActionValue &Value)
|
|
{
|
|
OnUiButtonPressed.Broadcast(UiInputType::BACK);
|
|
if (MainGameUI->GetWidgetStack().IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
MainGameUI->GetWidgetStack()[MainGameUI->GetWidgetStack().Num() - 1]->HandleUiInputAction(EEleriUIInputAction::Back);
|
|
}
|
|
|
|
void AEleriPlayerController::OnControllerTabLeftAction(const FInputActionValue &Value)
|
|
{
|
|
if (MainGameUI->GetWidgetStack().IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
MainGameUI->GetWidgetStack()[MainGameUI->GetWidgetStack().Num() - 1]->HandleUiInputAction(EEleriUIInputAction::TabLeft);
|
|
}
|
|
|
|
void AEleriPlayerController::OnControllerTabRightAction(const FInputActionValue &Value)
|
|
{
|
|
if (MainGameUI->GetWidgetStack().IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
MainGameUI->GetWidgetStack()[MainGameUI->GetWidgetStack().Num() - 1]->HandleUiInputAction(EEleriUIInputAction::TabRight);
|
|
}
|
|
|
|
// UI BIND
|
|
|
|
void AEleriPlayerController::OnMainMenuToggle(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(MainGameUI))
|
|
return;
|
|
|
|
if (MainGameUI->IsMainMenuOpen())
|
|
{
|
|
CloseMainMenu();
|
|
}
|
|
else
|
|
{
|
|
OpenMainMenu();
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnInventoryToggle(const FInputActionValue &Value)
|
|
{
|
|
if (Paused || (IsInMenu() && !MainGameUI->IsInventoryOpen()) || !MoveActorsComp || MoveActorsComp->IsRemovingMode())
|
|
return;
|
|
|
|
OpenInventory(false, false, nullptr, TArray<EInventoryTabType>());
|
|
}
|
|
|
|
void AEleriPlayerController::OnBookToggle(const FInputActionValue &Value)
|
|
{
|
|
if (Paused || IsDialogueOpen() || (IsInMenu() && !MainGameUI->IsBookOpen()) || !MoveActorsComp || MoveActorsComp->IsRemovingMode())
|
|
return;
|
|
|
|
OpenBookOfAlchemy(nullptr);
|
|
}
|
|
|
|
void AEleriPlayerController::OnOrdersToggle(const FInputActionValue &Value)
|
|
{
|
|
if (Paused || IsDialogueOpen() || IsInMenu() || !MoveActorsComp || MoveActorsComp->IsRemovingMode())
|
|
return;
|
|
|
|
if (OrdersOpen)
|
|
{
|
|
CloseOrdersUI();
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::OnCalendarToggle(const FInputActionValue &Value)
|
|
{
|
|
if (Paused || IsDialogueOpen() || (IsInMenu() && !MainGameUI->IsCalendarOpen()) || !MoveActorsComp || MoveActorsComp->IsRemovingMode())
|
|
return;
|
|
|
|
OpenCalendarWindow();
|
|
}
|
|
|
|
void AEleriPlayerController::OnBookNextPage(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(BookOfAlchemyManager))
|
|
return;
|
|
|
|
BookOfAlchemyManager->FlipPage(true);
|
|
}
|
|
|
|
void AEleriPlayerController::OnBookPreviousPage(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(BookOfAlchemyManager))
|
|
return;
|
|
|
|
BookOfAlchemyManager->FlipPage(false);
|
|
}
|
|
|
|
void AEleriPlayerController::OnBookItemTab(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(BookOfAlchemyManager))
|
|
return;
|
|
|
|
BookOfAlchemyManager->SwitchTab(0);
|
|
}
|
|
|
|
void AEleriPlayerController::OnBookPotionTab(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(BookOfAlchemyManager))
|
|
return;
|
|
|
|
BookOfAlchemyManager->SwitchTab(1);
|
|
}
|
|
|
|
void AEleriPlayerController::OnBookNextLetter(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(BookOfAlchemyManager))
|
|
return;
|
|
|
|
BookOfAlchemyManager->SelectLetter(BookOfAlchemyManager->GetNextPreviousLetter(BookOfAlchemyManager->CurrentlySelectedLetter, true));
|
|
}
|
|
|
|
void AEleriPlayerController::OnBookPreviousLetter(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(BookOfAlchemyManager))
|
|
return;
|
|
|
|
BookOfAlchemyManager->SelectLetter(BookOfAlchemyManager->GetNextPreviousLetter(BookOfAlchemyManager->CurrentlySelectedLetter, false));
|
|
}
|
|
|
|
void AEleriPlayerController::OnBookExit(const FInputActionValue &Value)
|
|
{
|
|
// CloseBookOfAlchemy();
|
|
}
|
|
|
|
void AEleriPlayerController::OnAlchemyStirringDirectionInput(const FInputActionValue &Value)
|
|
{
|
|
if (!PlayerCharacter)
|
|
return;
|
|
|
|
AlchemyManager->SetStirringDirection(Value.Get<FInputActionValue::Axis2D>());
|
|
}
|
|
|
|
void AEleriPlayerController::OnAlchemyConfirmInput(const FInputActionValue &Value)
|
|
{
|
|
if (!PlayerCharacter)
|
|
return;
|
|
|
|
AlchemyManager->MinigameConfirmInput();
|
|
}
|
|
|
|
UUserWidget *AEleriPlayerController::OpenInventory(bool JustSelecting, bool Shop, UInventoryComponent *Inventory, TArray<EInventoryTabType> RestrictTabs, bool bSelectMultiple, bool bShowDescription, bool bShowPropertyMap)
|
|
{
|
|
UInventoryComponent *PlayerInventory = Cast<UInventoryComponent>(PlayerCharacter->GetComponentByClass(UInventoryComponent::StaticClass()));
|
|
if (!IsValid(PlayerInventory))
|
|
return nullptr;
|
|
|
|
// If we pass nothing into this function we're opening the player inventory
|
|
// If we pass something we're opening a shop/trade and the other inventory is the npc inventory
|
|
UInventoryComponent *MainInv = PlayerInventory;
|
|
UInventoryComponent *OtherInv = IsValid(Inventory) ? Inventory : nullptr;
|
|
MainGameUI->OpenWidget(MainGameUI->GetInventoryWidget());
|
|
//MainGameUI->GetInventoryWidget()->ToggleWidget(true);
|
|
MainGameUI->GetInventoryWidget()->Setup(MainInv, OtherInv, Shop, JustSelecting, RestrictTabs, bSelectMultiple, bShowDescription, bShowPropertyMap);
|
|
|
|
return MainGameUI->GetInventoryWidget();
|
|
}
|
|
|
|
void AEleriPlayerController::CloseInventory()
|
|
{
|
|
MainGameUI->CloseWidget(MainGameUI->GetInventoryWidget());
|
|
}
|
|
|
|
UUserWidget *AEleriPlayerController::OpenBookOfAlchemy(UItemDataAsset *ItemToPresent)
|
|
{
|
|
if (!IsValid(PlayerCharacter->GetBook()) || bBookAnimating)
|
|
return nullptr;
|
|
|
|
bBookAnimating = true;
|
|
MainGameUI->GetBookWidget()->Setup(ItemToPresent, false);
|
|
PlayerCharacter->ToggleBook(true);
|
|
MainGameUI->OpenWidget(MainGameUI->GetBookWidget());
|
|
|
|
MainGameUI->ToggleGameMenu(false);
|
|
|
|
// Get the Enhanced Input Local Player Subsystem from the Local Player related to our Player Controller.
|
|
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
|
{
|
|
// If for whatever reason...
|
|
Subsystem->RemoveMappingContext(BookModeContext);
|
|
// Add each mapping context, along with their priority values. Higher values outprioritize lower values.
|
|
Subsystem->AddMappingContext(BookModeContext, 98);
|
|
}
|
|
|
|
TickBookAnimating = true;
|
|
|
|
return MainGameUI->GetBookWidget();
|
|
}
|
|
|
|
void AEleriPlayerController::CloseBookOfAlchemy()
|
|
{
|
|
if (bBookAnimating)
|
|
return;
|
|
|
|
bBookAnimating = true;
|
|
|
|
// for the animation of closing
|
|
FTimerHandle TimerHandle;
|
|
GetWorld()->GetTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda([this]()
|
|
{
|
|
MainGameUI->ToggleGameMenu(true);
|
|
}), 0.5f, false);
|
|
|
|
// Get the Enhanced Input Local Player Subsystem from the Local Player related to our Player Controller.
|
|
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
|
{
|
|
Subsystem->RemoveMappingContext(BookModeContext);
|
|
}
|
|
|
|
TickBookAnimating = true;
|
|
}
|
|
|
|
void AEleriPlayerController::DisableBookAnimating()
|
|
{
|
|
bBookAnimating = false;
|
|
TickBookAnimating = false;
|
|
TickBookTimer = 0.6f;
|
|
}
|
|
|
|
void AEleriPlayerController::CloseOrdersUI()
|
|
{
|
|
OrdersOpen = false;
|
|
|
|
OrdersUI->RemoveFromParent();
|
|
if (MenuStack.Num() == 0)
|
|
{
|
|
SetShowMouseCursor(false);
|
|
SetInputMode(FInputModeGameOnly());
|
|
}
|
|
}
|
|
|
|
UMainMenuWidget *AEleriPlayerController::OpenMainMenu()
|
|
{
|
|
if (!IsValid(MainGameUI))
|
|
return nullptr;
|
|
|
|
MainGameUI->OpenWidget(MainGameUI->GetMainMenuWidget());
|
|
|
|
return MainGameUI->GetMainMenuWidget();
|
|
}
|
|
|
|
void AEleriPlayerController::CloseMainMenu()
|
|
{
|
|
MainGameUI->CloseWidget(MainGameUI->GetMainMenuWidget());
|
|
}
|
|
|
|
UEleriBaseWidget *AEleriPlayerController::ToggleAlchemyMenu(bool bOpen)
|
|
{
|
|
if (MainGameUI->AnyWidgetOpen())
|
|
return nullptr;
|
|
|
|
MainGameUI->OpenWidget(MainGameUI->GetAlchemyWidget());
|
|
|
|
return MainGameUI->GetAlchemyWidget();
|
|
}
|
|
|
|
UEleriBaseWidget *AEleriPlayerController::ToggleDialogueWindow(bool bOpen)
|
|
{
|
|
if (!IsValid(MainGameUI->GetDialogueWidget()))
|
|
return nullptr;
|
|
|
|
bOpen? MainGameUI->OpenWidget(MainGameUI->GetDialogueWidget()) : MainGameUI->CloseWidget(MainGameUI->GetDialogueWidget());
|
|
return MainGameUI->GetDialogueWidget();
|
|
}
|
|
|
|
UEleriBaseWidget *AEleriPlayerController::ToggleNotificationWindow(bool bOpen)
|
|
{
|
|
if (!IsValid(MainGameUI->GetBigNotificationWidget()))
|
|
return nullptr;
|
|
|
|
if (MainGameUI->IsBigNotificationOpen())
|
|
{
|
|
MainGameUI->CloseWidget(MainGameUI->GetBigNotificationWidget());
|
|
}
|
|
else
|
|
{
|
|
MainGameUI->OpenWidget(MainGameUI->GetBigNotificationWidget());
|
|
}
|
|
return MainGameUI->GetBigNotificationWidget();
|
|
}
|
|
|
|
UTradeWidget *AEleriPlayerController::OpenTradeWindow(UInventoryComponent *Inventory, const TArray<EInventoryTabType>& InRestrictTabs)
|
|
{
|
|
if (!IsValid(PlayerCharacter))
|
|
return nullptr;
|
|
|
|
if (UMainGameWidget *MainWidget = GetMainGameWidget())
|
|
{
|
|
MainWidget->OpenTradeWidget(Inventory, InRestrictTabs);
|
|
return MainGameUI->GetTradeWidget();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
UCalendarScreen* AEleriPlayerController::OpenCalendarWindow()
|
|
{
|
|
MainGameUI->OpenWidget(MainGameUI->GetCalendarWidget());
|
|
return MainGameUI->GetCalendarWidget();
|
|
}
|
|
|
|
UEleriBaseWidget* AEleriPlayerController::OpenBazarWindow() {
|
|
MainGameUI->OpenWidget(MainGameUI->GetBazarWidget());
|
|
return MainGameUI->GetBazarWidget();
|
|
}
|
|
|
|
void AEleriPlayerController::ToggleBazarInput(bool bActive)
|
|
{
|
|
|
|
}
|
|
|
|
void AEleriPlayerController::OnInteract(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(PlayerCharacter))
|
|
return;
|
|
|
|
if (PlayerCharacter->GetIsPlanting())
|
|
{
|
|
TryPlantSelectedSeed();
|
|
return;
|
|
}
|
|
|
|
// Ask the InteractionSystem plugin's subsystem for the closest valid interactable
|
|
// and fire the interaction on it if we have one.
|
|
if (AActor *ClosestInteractable = UInteractionSubsystem::GetClosestInteractable(this))
|
|
{
|
|
IInteractableActorInterface::Execute_Interact(ClosestInteractable, PlayerCharacter);
|
|
}
|
|
|
|
PlayerCharacter->OnInteract.Broadcast();
|
|
}
|
|
|
|
void AEleriPlayerController::OnInteractExit(const FInputActionValue &Value)
|
|
{
|
|
if (!IsValid(PlayerCharacter))
|
|
return;
|
|
|
|
if (PlayerCharacter->GetIsPlanting())
|
|
{
|
|
ClearSeedToPlant();
|
|
return;
|
|
}
|
|
|
|
PlayerCharacter->OnInteractExit.Broadcast();
|
|
OnChangeInputContext.Broadcast(1);
|
|
}
|
|
|
|
void AEleriPlayerController::OnHarvestSeed(const FInputActionValue &Value)
|
|
{
|
|
}
|
|
|
|
// PLANTING
|
|
|
|
void AEleriPlayerController::SetSeedToPlant(UItemDataAsset *SeedData, bool bHighQuality)
|
|
{
|
|
// Anything that is not a seed that fits into a seed bed is rejected, the UI cannot leave us in a bad state
|
|
SeedToPlant = ASeedBedActor::IsPlantableSeedData(SeedData) ? SeedData : nullptr;
|
|
bSeedToPlantHighQuality = IsValid(SeedToPlant) && bHighQuality;
|
|
|
|
// Selecting a seed is what starts the planting, the beds in range light up for it right away
|
|
if (IsValid(SeedToPlant))
|
|
{
|
|
SetPlantingMode(true);
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::ClearSeedToPlant()
|
|
{
|
|
if (!IsValid(SeedToPlant) && !bSeedToPlantHighQuality)
|
|
return;
|
|
|
|
SeedToPlant = nullptr;
|
|
bSeedToPlantHighQuality = false;
|
|
|
|
// Nothing is being planted anymore, so the beds stop being highlighted
|
|
if (IsPlantingModeActive())
|
|
{
|
|
SetPlantingMode(false);
|
|
}
|
|
}
|
|
|
|
bool AEleriPlayerController::IsPlantingModeActive() const
|
|
{
|
|
return IsValid(PlayerCharacter) && PlayerCharacter->GetIsPlanting();
|
|
}
|
|
|
|
void AEleriPlayerController::SetPlantingMode(bool bActive)
|
|
{
|
|
if (!IsValid(PlayerCharacter))
|
|
return;
|
|
|
|
PlayerCharacter->SetPlanting(bActive);
|
|
}
|
|
|
|
void AEleriPlayerController::TryPlantSelectedSeed()
|
|
{
|
|
if (!IsValid(PlayerCharacter))
|
|
return;
|
|
|
|
// A seed that is not plantable anymore, for example when the inventory was emptied, drops out of planting
|
|
if (!ASeedBedActor::IsPlantableSeedData(SeedToPlant))
|
|
{
|
|
ClearSeedToPlant();
|
|
return;
|
|
}
|
|
|
|
ASeedBedActor *SeedBed = PlayerCharacter->GetClosestSeedBedActor();
|
|
if (!IsValid(SeedBed))
|
|
return;
|
|
|
|
const FVector PlayerLocation = PlayerCharacter->GetActorLocation();
|
|
|
|
FIntVector2 SlotCoordinate = SeedBed->GetHighlightedSlotIndex();
|
|
if (SlotCoordinate == FIntVector2::NoneValue)
|
|
return;
|
|
|
|
UInventoryComponent *Inventory = UMainBlueprintFunctionLibrary::GetPlayerInventory(this);
|
|
if (!IsValid(Inventory))
|
|
return;
|
|
|
|
// The seed is paid for before it is planted, so a slot can never hold a seed the inventory never had
|
|
const FPrimaryAssetId SeedAssetId = SeedToPlant->GetPrimaryAssetId();
|
|
if (Inventory->HasItem(SeedAssetId, true) <= 0)
|
|
return;
|
|
|
|
if (!SeedBed->PlantSeedInSlot(SlotCoordinate, SeedToPlant, bSeedToPlantHighQuality))
|
|
return;
|
|
|
|
Inventory->RemoveItemFromInventory(SeedAssetId, 1, true);
|
|
|
|
if (Inventory->HasItem(SeedAssetId, true) == INDEX_NONE)
|
|
{
|
|
ClearSeedToPlant();
|
|
}
|
|
}
|
|
|
|
void AEleriPlayerController::StartMinigame(EMinigameType MinigameType, const TSoftObjectPtr<UBaseMinigameDataAsset> &DataAsset)
|
|
{
|
|
if (!IsValid(PlayerCharacter) ||
|
|
!IsValid(MainGameUI) ||
|
|
MainGameUI->IsAnyMinigameOpen() ||
|
|
MinigameType == EMinigameType::NONE)
|
|
return;
|
|
|
|
MainGameUI->ToggleMinigamesWidget(MinigameType, DataAsset);
|
|
}
|
|
|
|
void AEleriPlayerController::CloseMinigame(int32 Score)
|
|
{
|
|
if (!IsValid(PlayerCharacter) || !IsValid(MainGameUI) || !MainGameUI->IsAnyMinigameOpen())
|
|
return;
|
|
|
|
MainGameUI->ToggleMinigamesWidget(EMinigameType::NONE, nullptr);
|
|
if (OnMinigameComplete.IsBound())
|
|
{
|
|
OnMinigameComplete.Execute(Score);
|
|
}
|
|
}
|