Initial push to repo
This commit is contained in:
130
Source/Faye/AI/CustomerCrowdAvoidanceComponent.cpp
Normal file
130
Source/Faye/AI/CustomerCrowdAvoidanceComponent.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "CustomerCrowdAvoidanceComponent.h"
|
||||
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "Faye/Components/NpcPawnMovement.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
TArray<TWeakObjectPtr<UCustomerCrowdAvoidanceComponent>> UCustomerCrowdAvoidanceComponent::AllAgents;
|
||||
|
||||
UCustomerCrowdAvoidanceComponent::UCustomerCrowdAvoidanceComponent()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void UCustomerCrowdAvoidanceComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
PlayerPawn = GetWorld()->GetFirstPlayerController()->GetPawn();
|
||||
NpcPawnMovement = GetOwner()->FindComponentByClass<UNpcPawnMovement>();
|
||||
CapsuleRadius = GetOwner()->FindComponentByClass<UCapsuleComponent>()->GetScaledCapsuleRadius();
|
||||
AllAgents.Add(this);
|
||||
}
|
||||
|
||||
void UCustomerCrowdAvoidanceComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
AllAgents.Remove(this);
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
||||
|
||||
void UCustomerCrowdAvoidanceComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
if (!NpcPawnMovement) return;
|
||||
|
||||
FVector SeparationForce = ComputeSeparation();
|
||||
SeparationForce = SeparationForce.GetClampedToMaxSize(MaxSeparationForce);
|
||||
NpcPawnMovement->AddInputVector(SeparationForce, true);
|
||||
}
|
||||
|
||||
FVector UCustomerCrowdAvoidanceComponent::ComputeSeparation() const
|
||||
{
|
||||
// Cache current position and velocity
|
||||
const FVector MyLocation = GetOwner()->GetActorLocation();
|
||||
const FVector MyVelocity = NpcPawnMovement? NpcPawnMovement->Velocity : FVector::ZeroVector;
|
||||
|
||||
//Accumulate all avoidance forces for this frame
|
||||
FVector Force = FVector::ZeroVector;
|
||||
|
||||
for (int32 i = AllAgents.Num() - 1; i >= 0; --i)
|
||||
{
|
||||
if (!AllAgents[i].IsValid())
|
||||
{
|
||||
AllAgents.RemoveAtSwap(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
UCustomerCrowdAvoidanceComponent* OtherComp = AllAgents[i].Get();
|
||||
if (!OtherComp || OtherComp == this) continue;
|
||||
|
||||
//Compute distance and direction to the other pawn
|
||||
const FVector OtherLocation = OtherComp->GetOwner()->GetActorLocation();
|
||||
const FVector Delta = MyLocation - OtherLocation;
|
||||
const float Distance = Delta.Size();
|
||||
|
||||
//Ignore if outside of avoidance radius or too close to normalize safely
|
||||
if (Distance > AvoidanceRadius || Distance < 1.f) continue;
|
||||
|
||||
FVector ToOther = Delta.GetSafeNormal();
|
||||
|
||||
//Are we moving towards each other
|
||||
FVector OtherVelocity = OtherComp->NpcPawnMovement? OtherComp->NpcPawnMovement->Velocity : FVector::ZeroVector;
|
||||
FVector RelativeVelocity = MyVelocity - OtherVelocity;
|
||||
|
||||
//Positive value = we are closing distance to the other pawn
|
||||
float ClosingSpeed = FVector::DotProduct(RelativeVelocity, ToOther);
|
||||
|
||||
const float Normalized = 1.f - (Distance - AvoidanceRadius);
|
||||
const float Strength = FMath::Pow(Normalized, 3.5f);
|
||||
if (ClosingSpeed > 0.f)
|
||||
{
|
||||
FVector SideStep = FVector::CrossProduct(ToOther, FVector::UpVector);
|
||||
SideStep.Normalize();
|
||||
Force += SideStep * Strength;
|
||||
|
||||
if (bDebug)
|
||||
{
|
||||
DrawDebugDirectionalArrow(GetWorld(), MyLocation, MyLocation + ToOther * 100.f, 30.f, FColor::Blue, false, 0.f, 0, 2.f);
|
||||
DrawDebugDirectionalArrow(GetWorld(), MyLocation, MyLocation + SideStep * 100.f, 30.f, FColor::Yellow, false, 0.f, 0, 2.f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Force += ToOther * Strength * 0.3f;
|
||||
|
||||
if (bDebug)
|
||||
{
|
||||
DrawDebugDirectionalArrow(GetWorld(), MyLocation, MyLocation + ToOther * 100.f, 30.f, FColor::Cyan, false, 0.f, 0, 2.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const FVector PlayerLocation = PlayerPawn->GetActorLocation();
|
||||
FVector Delta = PlayerLocation - MyLocation;
|
||||
float Distance = Delta.Size();
|
||||
|
||||
if (Distance > 1.f && Distance < AvoidanceRadius)
|
||||
{
|
||||
FVector ToPlayer = Delta.GetSafeNormal();
|
||||
FVector SideStep = FVector::CrossProduct(ToPlayer, FVector::UpVector);
|
||||
const float Normalized = 1.f - (Distance - AvoidanceRadius);
|
||||
const float Strength = FMath::Pow(Normalized, 4.5f);
|
||||
|
||||
Force += SideStep * Strength * SeparationStrength;
|
||||
}
|
||||
|
||||
if (bDebug)
|
||||
{
|
||||
// Avoidance radius
|
||||
DrawDebugSphere(GetWorld(), MyLocation, AvoidanceRadius,24,FColor::Green,false,0.f,0,1.5f);
|
||||
|
||||
// Final applied force
|
||||
DrawDebugDirectionalArrow(GetWorld(),MyLocation,MyLocation + Force * 50.f,40.f, FColor::Red,false,0.f,0,3.f);
|
||||
}
|
||||
|
||||
return Force * SeparationStrength;
|
||||
}
|
||||
|
||||
49
Source/Faye/AI/CustomerCrowdAvoidanceComponent.h
Normal file
49
Source/Faye/AI/CustomerCrowdAvoidanceComponent.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "CustomerCrowdAvoidanceComponent.generated.h"
|
||||
|
||||
class UNpcPawnMovement;
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class FAYE_API UCustomerCrowdAvoidanceComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UCustomerCrowdAvoidanceComponent();
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
FVector ComputeSeparation() const;
|
||||
|
||||
private:
|
||||
|
||||
static TArray<TWeakObjectPtr<UCustomerCrowdAvoidanceComponent>> AllAgents;
|
||||
|
||||
UPROPERTY()
|
||||
UNpcPawnMovement* NpcPawnMovement = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
APawn* PlayerPawn = nullptr;
|
||||
|
||||
float CapsuleRadius = 0.f;
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, Category = "Crowd")
|
||||
bool bDebug = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Crowd")
|
||||
float AvoidanceRadius = 150.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Crowd")
|
||||
float SeparationStrength = 2.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Crowd")
|
||||
float MaxSeparationForce = 1.f;
|
||||
};
|
||||
35
Source/Faye/AI/Tasks/SeekInteractableTask.cpp
Normal file
35
Source/Faye/AI/Tasks/SeekInteractableTask.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
#include "SeekInteractableTask.h"
|
||||
#include "StateTreeExecutionContext.h"
|
||||
|
||||
EStateTreeRunStatus FSeekInteractableTask::EnterState(
|
||||
FStateTreeExecutionContext& Context,
|
||||
const FStateTreeTransitionResult&) const
|
||||
{
|
||||
// auto& Data = Context.GetInstanceData<APawn>(*this);
|
||||
// Data.bMoveFinished = false;
|
||||
//
|
||||
// AAIController* AI = Context.GetOwner<AAIController>();
|
||||
// if (!AI)
|
||||
// return EStateTreeRunStatus::Failed;
|
||||
//
|
||||
// FPathFollowingRequestResult Result = AI->MoveToLocation(TargetLocation);
|
||||
//
|
||||
// if (Result.Code == EPathFollowingRequestResult::Failed)
|
||||
// return EStateTreeRunStatus::Failed;
|
||||
//
|
||||
// Data.RequestID = Result.MoveId;
|
||||
return EStateTreeRunStatus::Running;
|
||||
}
|
||||
|
||||
EStateTreeRunStatus FSeekInteractableTask::Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const
|
||||
{
|
||||
return FStateTreeTaskBase::Tick(Context, DeltaTime);
|
||||
}
|
||||
|
||||
void FSeekInteractableTask::ExitState(FStateTreeExecutionContext& Context,
|
||||
const FStateTreeTransitionResult& Transition) const
|
||||
{
|
||||
FStateTreeTaskBase::ExitState(Context, Transition);
|
||||
}
|
||||
|
||||
38
Source/Faye/AI/Tasks/SeekInteractableTask.h
Normal file
38
Source/Faye/AI/Tasks/SeekInteractableTask.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "StateTreeTaskBase.h"
|
||||
#include "Navigation/PathFollowingComponent.h"
|
||||
#include "AIController.h"
|
||||
#include "SeekInteractableTask.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct FSTTask_SeekInteractableInstanceData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FAIRequestID RequestID;
|
||||
bool bMoveFinished = false;
|
||||
EPathFollowingResult::Type Result;
|
||||
};
|
||||
|
||||
USTRUCT(meta = (DisplayName = "Seek interactable"))
|
||||
struct FSeekInteractableTask : public FStateTreeTaskBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
using FInstanceDataType = FSTTask_SeekInteractableInstanceData;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input")
|
||||
FVector TargetLocation;
|
||||
|
||||
virtual EStateTreeRunStatus EnterState(
|
||||
FStateTreeExecutionContext& Context,
|
||||
const FStateTreeTransitionResult& Transition) const override;
|
||||
|
||||
virtual EStateTreeRunStatus Tick(
|
||||
FStateTreeExecutionContext& Context,
|
||||
const float DeltaTime) const override;
|
||||
|
||||
virtual void ExitState(
|
||||
FStateTreeExecutionContext& Context,
|
||||
const FStateTreeTransitionResult& Transition) const override;
|
||||
};
|
||||
43
Source/Faye/Base/FayeCameraManager.cpp
Normal file
43
Source/Faye/Base/FayeCameraManager.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "FayeCameraManager.h"
|
||||
|
||||
#include "EngineUtils.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "GameFramework/SpringArmComponent.h"
|
||||
|
||||
void AFayeCameraManager::ToggleClassRendering(UClass* Class, bool bActive)
|
||||
{
|
||||
if (HiddenActors.IsEmpty())
|
||||
{
|
||||
for (TActorIterator<AActor> It(GetWorld()); It; ++It)
|
||||
{
|
||||
if (It && It->IsA(Class))
|
||||
{
|
||||
HiddenActors.Add(*It);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (AActor* Actor : HiddenActors)
|
||||
{
|
||||
if (Actor)
|
||||
{
|
||||
Actor->SetActorHiddenInGame(!bActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AFayeCameraManager::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
ACharacter* PlayerCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
|
||||
ensure(PlayerCharacter);
|
||||
|
||||
SpringArm = PlayerCharacter->GetComponentByClass<USpringArmComponent>();
|
||||
Camera = PlayerCharacter->GetComponentByClass<UCameraComponent>();
|
||||
}
|
||||
39
Source/Faye/Base/FayeCameraManager.h
Normal file
39
Source/Faye/Base/FayeCameraManager.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Camera/PlayerCameraManager.h"
|
||||
#include "FayeCameraManager.generated.h"
|
||||
|
||||
class USpringArmComponent;
|
||||
class UCameraComponent;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API AFayeCameraManager : public APlayerCameraManager
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent)
|
||||
void ZoomIn(float Amount);
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void ToggleClassRendering(UClass* Class, bool bActive);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = true))
|
||||
USpringArmComponent* SpringArm;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = true))
|
||||
UCameraComponent* Camera;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<AActor*> HiddenActors;
|
||||
};
|
||||
262
Source/Faye/Base/FayePlayerController.cpp
Normal file
262
Source/Faye/Base/FayePlayerController.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "FayePlayerController.h"
|
||||
#include "EnhancedInputComponent.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Faye/GameObjects/PlayerCharacter.h"
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
#include "FayeCameraManager.h"
|
||||
#include "SUDSLibrary.h"
|
||||
#include "Faye/UI/MainGameWidget.h"
|
||||
#include "Faye/GameObjects/ShelfActor.h"
|
||||
#include "Faye/UI/Controller/ShelvesStackingController.h"
|
||||
|
||||
void AFayePlayerController::SetupInputComponent()
|
||||
{
|
||||
Super::SetupInputComponent();
|
||||
|
||||
if (UEnhancedInputComponent *PlayerEnhancedInputComponent = Cast<UEnhancedInputComponent>(InputComponent))
|
||||
{
|
||||
if (MoveInputAction)
|
||||
{
|
||||
PlayerEnhancedInputComponent->BindAction(MoveInputAction, ETriggerEvent::Triggered, this, &AFayePlayerController::OnMove);
|
||||
}
|
||||
if (LookInputAction)
|
||||
{
|
||||
PlayerEnhancedInputComponent->BindAction(LookInputAction, ETriggerEvent::Triggered, this, &AFayePlayerController::OnLook);
|
||||
}
|
||||
if (ZoomInputAction)
|
||||
{
|
||||
PlayerEnhancedInputComponent->BindAction(ZoomInputAction, ETriggerEvent::Triggered, this, &AFayePlayerController::OnZoom);
|
||||
}
|
||||
if (InteractInputAction)
|
||||
{
|
||||
PlayerEnhancedInputComponent->BindAction(InteractInputAction, ETriggerEvent::Started, this, &AFayePlayerController::OnInteract);
|
||||
}
|
||||
|
||||
if (PhoneInputAction)
|
||||
{
|
||||
PlayerEnhancedInputComponent->BindAction(PhoneInputAction, ETriggerEvent::Started, this, &AFayePlayerController::OnPhoneToggle);
|
||||
}
|
||||
if (OptionsInputAction)
|
||||
{
|
||||
PlayerEnhancedInputComponent->BindAction(OptionsInputAction, ETriggerEvent::Started, this, &AFayePlayerController::OnOptionsToggle);
|
||||
}
|
||||
|
||||
if (ShelveStackingBookConfirmAction)
|
||||
{
|
||||
PlayerEnhancedInputComponent->BindAction(ShelveStackingBookConfirmAction, ETriggerEvent::Started, this, &AFayePlayerController::OnShelveBookPlacementConfirm);
|
||||
}
|
||||
|
||||
if (CoffeeMakingGrabAction)
|
||||
{
|
||||
PlayerEnhancedInputComponent->BindAction(CoffeeMakingGrabAction, ETriggerEvent::Started, this, &AFayePlayerController::OnCoffeeMakingGrabActionPress);
|
||||
PlayerEnhancedInputComponent->BindAction(CoffeeMakingGrabAction, ETriggerEvent::Completed, this, &AFayePlayerController::OnCoffeeMakingGrabActionRelease);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AFayePlayerController::ClientRestart_Implementation(class APawn* NewPawn)
|
||||
{
|
||||
Super::ClientRestart_Implementation(NewPawn);
|
||||
|
||||
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
||||
{
|
||||
Subsystem->ClearAllMappings();
|
||||
|
||||
Subsystem->AddMappingContext(MovementInputMappingContext, 1);
|
||||
Subsystem->AddMappingContext(UiInputMappingContext, 2);
|
||||
//Subsystem->AddMappingContext(UiInputMappingContext, 3);
|
||||
//Subsystem->AddMappingContext(ActionContext, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void AFayePlayerController::CloseWidget(UFayeBaseWidget* Widget)
|
||||
{
|
||||
Widget->ToggleWidget(false);
|
||||
ActiveWidgets.Remove(Widget);
|
||||
if (ActiveWidgets.IsEmpty())
|
||||
{
|
||||
SetShowMouseCursor(false);
|
||||
SetInputMode(FInputModeGameOnly());
|
||||
bInMenu = false;
|
||||
SetPause(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AFayePlayerController::ToggleCoffeeMaking(bool bActive)
|
||||
{
|
||||
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
||||
{
|
||||
if (bActive)
|
||||
{
|
||||
Subsystem->AddMappingContext(CoffeeMakingMappingContext, 12);
|
||||
}
|
||||
else
|
||||
{
|
||||
Subsystem->RemoveMappingContext(CoffeeMakingMappingContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AFayePlayerController::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
PlayerCharacter = Cast<APlayerCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
|
||||
FayeCameraManager = Cast<AFayeCameraManager>(PlayerCameraManager);
|
||||
|
||||
MainGameWidget = CreateWidget<UMainGameWidget>(this, MainWidgetClass, "MainGameWidget");
|
||||
MainGameWidget->AddToViewport();
|
||||
}
|
||||
|
||||
void AFayePlayerController::OpenGenericWidget(UFayeBaseWidget* Widget)
|
||||
{
|
||||
ActiveWidgets.Add(Widget);
|
||||
SetShowMouseCursor(true);
|
||||
SetInputMode(FInputModeGameAndUI());
|
||||
bInMenu = true;
|
||||
}
|
||||
|
||||
void AFayePlayerController::StartDialogueFromScript(UObject* DialogueParticipant, USUDSScript* Script)
|
||||
{
|
||||
USUDSDialogue* DialogueObject = USUDSLibrary::CreateDialogueWithParticipant(DialogueParticipant, Script, DialogueParticipant, true);
|
||||
StartDialogue(DialogueParticipant, DialogueObject);
|
||||
}
|
||||
|
||||
void AFayePlayerController::StartDialogue(UObject* DialogueParticipant, USUDSDialogue* Dialogue)
|
||||
{
|
||||
MainGameWidget->ToggleDialogueWidget(true, FDialogueWidgetPayload(Dialogue));
|
||||
FInputModeGameAndUI InputMode;
|
||||
InputMode.SetHideCursorDuringCapture(false);
|
||||
SetInputMode(InputMode);
|
||||
SetShowMouseCursor(true);
|
||||
}
|
||||
|
||||
void AFayePlayerController::EndDialogue()
|
||||
{
|
||||
MainGameWidget->ToggleDialogueWidget(false, nullptr);
|
||||
SetInputMode(FInputModeGameOnly());
|
||||
SetShowMouseCursor(false);
|
||||
}
|
||||
|
||||
void AFayePlayerController::OpenOptionsWidget()
|
||||
{
|
||||
OpenGenericWidget(MainGameWidget->GetOptionsWidget());
|
||||
MainGameWidget->ToggleOptionsWidget(true);
|
||||
}
|
||||
|
||||
void AFayePlayerController::CloseOptionsWidget()
|
||||
{
|
||||
MainGameWidget->ToggleOptionsWidget(false);
|
||||
CloseWidget(MainGameWidget->GetOptionsWidget());
|
||||
}
|
||||
|
||||
void AFayePlayerController::ClosePhoneWidget()
|
||||
{
|
||||
MainGameWidget->TogglePhoneWidget(false);
|
||||
CloseWidget(MainGameWidget->GetPhoneWidget());
|
||||
}
|
||||
|
||||
void AFayePlayerController::OpenShelvesStackingWidget(AShelfActor* ShelfActorRef)
|
||||
{
|
||||
OpenGenericWidget(MainGameWidget->GetShelvesStackingWidget());
|
||||
FShelvesStackingSetupPayload Payload;
|
||||
Payload.ShelfActorRef = ShelfActorRef;
|
||||
MainGameWidget->ToggleShelvesStackingWidget(true, Payload);
|
||||
OnToggleShelveStacking.Broadcast(true);
|
||||
|
||||
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
||||
{
|
||||
Subsystem->AddMappingContext(ShelveStackingMappingContext, 99);
|
||||
}
|
||||
ShelfRef = ShelfActorRef;
|
||||
}
|
||||
|
||||
void AFayePlayerController::CloseShelvesStackingWidget()
|
||||
{
|
||||
MainGameWidget->ToggleShelvesStackingWidget(false, FShelvesStackingSetupPayload());
|
||||
CloseWidget(MainGameWidget->GetShelvesStackingWidget());
|
||||
OnToggleShelveStacking.Broadcast(false);
|
||||
|
||||
if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
||||
{
|
||||
Subsystem->RemoveMappingContext(ShelveStackingMappingContext);
|
||||
}
|
||||
ShelfRef = nullptr;
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnMove(const FInputActionValue& Value)
|
||||
{
|
||||
const FVector2D AnalogueValue = Value.Get<FInputActionValue::Axis2D>();
|
||||
|
||||
const FVector ForwardVec = PlayerCharacter->GetActorForwardVector();
|
||||
const FVector RightVec = PlayerCharacter->GetActorRightVector();
|
||||
|
||||
PlayerCharacter->AddMovementInput(ForwardVec, AnalogueValue.Y);
|
||||
PlayerCharacter->AddMovementInput(RightVec, AnalogueValue.X);
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnLook(const FInputActionValue& Value)
|
||||
{
|
||||
FVector2D AnalogueValue = Value.Get<FInputActionValue::Axis2D>();
|
||||
|
||||
GetPawn()->AddControllerYawInput(AnalogueValue.X);
|
||||
GetPawn()->AddControllerPitchInput(AnalogueValue.Y);
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnZoom(const FInputActionValue& Value)
|
||||
{
|
||||
float AnalogueValue = Value.Get<FInputActionValue::Axis1D>();
|
||||
FayeCameraManager->ZoomIn(AnalogueValue);
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnInteract(const FInputActionValue& Value)
|
||||
{
|
||||
PlayerCharacter->InteractWithObject();
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnPhoneToggle(const FInputActionValue& Value)
|
||||
{
|
||||
if (!MainGameWidget->IsPhoneOpen())
|
||||
{
|
||||
OpenGenericWidget(MainGameWidget->GetPhoneWidget());
|
||||
MainGameWidget->TogglePhoneWidget(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
void ClosePhoneWidget();
|
||||
}
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnOptionsToggle(const FInputActionValue& Value)
|
||||
{
|
||||
if (!MainGameWidget->IsOptionsOpen())
|
||||
{
|
||||
OpenOptionsWidget();
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseOptionsWidget();
|
||||
}
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnShelveBookPlacementConfirm(const FInputActionValue& Value)
|
||||
{
|
||||
if (ShelfRef)
|
||||
{
|
||||
ShelfRef->PlaceBook();
|
||||
}
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnCoffeeMakingGrabActionPress(const FInputActionValue& Value)
|
||||
{
|
||||
OnCoffeeMakingAction_GrabStarted.Broadcast();
|
||||
}
|
||||
|
||||
void AFayePlayerController::OnCoffeeMakingGrabActionRelease(const FInputActionValue& Value)
|
||||
{
|
||||
OnCoffeeMakingAction_GrabRelease.Broadcast();
|
||||
}
|
||||
|
||||
137
Source/Faye/Base/FayePlayerController.h
Normal file
137
Source/Faye/Base/FayePlayerController.h
Normal file
@@ -0,0 +1,137 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Faye/UI/FayeBaseWidget.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "InputActionValue.h"
|
||||
#include "EnhancedActionKeyMapping.h"
|
||||
#include "InputMappingContext.h"
|
||||
#include "FayePlayerController.generated.h"
|
||||
|
||||
class USUDSScript;
|
||||
class USUDSDialogue;
|
||||
class AFayeCameraManager;
|
||||
class AShelfActor;
|
||||
class UMainGameWidget;
|
||||
class APlayerCharacter;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnToggleShelveStacking, bool, bActive);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCoffeeMakingAction);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API AFayePlayerController : public APlayerController
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
TSubclassOf<UMainGameWidget> MainWidgetClass;
|
||||
|
||||
virtual void SetupInputComponent() override;
|
||||
virtual void ClientRestart_Implementation(class APawn* NewPawn) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void CloseWidget(UFayeBaseWidget* Widget);
|
||||
void ToggleCoffeeMaking(bool bActive);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
UMainGameWidget* GetMainGameWidget() const { return MainGameWidget; }
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnToggleShelveStacking OnToggleShelveStacking;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnCoffeeMakingAction OnCoffeeMakingAction_GrabStarted;
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnCoffeeMakingAction OnCoffeeMakingAction_GrabRelease;
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY()
|
||||
APlayerCharacter* PlayerCharacter;
|
||||
|
||||
UPROPERTY()
|
||||
AFayeCameraManager* FayeCameraManager;
|
||||
|
||||
UPROPERTY()
|
||||
bool bInMenu = false;
|
||||
UPROPERTY()
|
||||
UMainGameWidget* MainGameWidget;
|
||||
UPROPERTY()
|
||||
TArray<UFayeBaseWidget*> ActiveWidgets;
|
||||
|
||||
UPROPERTY()
|
||||
AShelfActor* ShelfRef = nullptr;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
void OpenGenericWidget(UFayeBaseWidget* Widget);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Faye Player Controller")
|
||||
void StartDialogueFromScript(UObject* DialogueParticipant, USUDSScript* Script);
|
||||
UFUNCTION(BlueprintCallable, Category = "Faye Player Controller")
|
||||
void StartDialogue(UObject* DialogueParticipant, USUDSDialogue* Dialogue);
|
||||
|
||||
// Only call from Dialogue UI
|
||||
UFUNCTION(BlueprintCallable, Category = "Faye Player Controller")
|
||||
void EndDialogue();
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void OpenOptionsWidget();
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void CloseOptionsWidget();
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void ClosePhoneWidget();
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void OpenShelvesStackingWidget(AShelfActor* ShelfActorRef);
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void CloseShelvesStackingWidget();
|
||||
|
||||
|
||||
// ---INPUT STUFF START---
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputMappingContext* MovementInputMappingContext;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputAction* MoveInputAction;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputAction* LookInputAction;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputAction* ZoomInputAction;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputAction* InteractInputAction;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputMappingContext* UiInputMappingContext;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputAction* PhoneInputAction;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputAction* OptionsInputAction;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputMappingContext* ShelveStackingMappingContext;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputAction* ShelveStackingBookConfirmAction;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputMappingContext* CoffeeMakingMappingContext;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UInputAction* CoffeeMakingGrabAction;
|
||||
|
||||
void OnMove(const FInputActionValue& Value);
|
||||
void OnLook(const FInputActionValue& Value);
|
||||
void OnZoom(const FInputActionValue& Value);
|
||||
void OnInteract(const FInputActionValue& Value);
|
||||
|
||||
//UI
|
||||
void OnPhoneToggle(const FInputActionValue& Value);
|
||||
void OnOptionsToggle(const FInputActionValue& Value);
|
||||
|
||||
void OnShelveBookPlacementConfirm(const FInputActionValue& Value);
|
||||
|
||||
void OnCoffeeMakingGrabActionPress(const FInputActionValue& Value);
|
||||
void OnCoffeeMakingGrabActionRelease(const FInputActionValue& Value);
|
||||
// ---INPUT STUFF END---
|
||||
};
|
||||
263
Source/Faye/Components/CoffeeMachineController.cpp
Normal file
263
Source/Faye/Components/CoffeeMachineController.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "CoffeeMachineController.h"
|
||||
|
||||
#include "HoverableBoxComponent.h"
|
||||
#include "Faye/Base/FayePlayerController.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
|
||||
UCoffeeMachineController::UCoffeeMachineController()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
if (!bCoffeeMakingActive) return;
|
||||
|
||||
if (InputType == EInputControllerType::Mouse)
|
||||
{
|
||||
PerformMouseHover();
|
||||
|
||||
if (CurrentSelectedMeshComponent)
|
||||
{
|
||||
MoveHeldObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::ToggleCoffeeMaking(bool bActive)
|
||||
{
|
||||
bCoffeeMakingActive = bActive;
|
||||
PlayerController->ToggleCoffeeMaking(bActive);
|
||||
|
||||
if (bCoffeeMakingActive)
|
||||
{
|
||||
PlayerController->OnCoffeeMakingAction_GrabStarted.AddUniqueDynamic(this, &UCoffeeMachineController::OnInputGrab);
|
||||
PlayerController->OnCoffeeMakingAction_GrabRelease.AddUniqueDynamic(this, &UCoffeeMachineController::OnInputRelease);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerController->OnCoffeeMakingAction_GrabStarted.RemoveDynamic(this, &UCoffeeMachineController::OnInputGrab);
|
||||
PlayerController->OnCoffeeMakingAction_GrabRelease.RemoveDynamic(this, &UCoffeeMachineController::OnInputRelease);
|
||||
}
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::SetCoffeeMakingStage(ECoffeeMachineMakingState NewStage)
|
||||
{
|
||||
CurrentCoffeeMakingStage = NewStage;
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
PlayerController = Cast<AFayePlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::PerformMouseHover()
|
||||
{
|
||||
float MouseX, MouseY;
|
||||
if (!PlayerController->GetMousePosition(MouseX, MouseY)) return;
|
||||
|
||||
FVector WorldOrigin, WorldDirection;
|
||||
if (!PlayerController->DeprojectScreenPositionToWorld(MouseX, MouseY, WorldOrigin, WorldDirection)) return;
|
||||
|
||||
FVector TraceEnd = WorldOrigin + (WorldDirection * 300.f);
|
||||
|
||||
TArray<FHitResult> HitResults;
|
||||
FCollisionQueryParams Params;
|
||||
Params.AddIgnoredComponent(CurrentSelectedBoxComponent);
|
||||
const bool bHit = GetWorld()->LineTraceMultiByChannel(HitResults, WorldOrigin, TraceEnd, ECC_GameTraceChannel1, Params);
|
||||
|
||||
|
||||
|
||||
HoverBox(bHit? Cast<UHoverableBoxComponent>(HitResults[0].Component) : nullptr);
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::MoveHeldObject()
|
||||
{
|
||||
float MouseX, MouseY;
|
||||
if (!PlayerController->GetMousePosition(MouseX, MouseY)) return;
|
||||
|
||||
FVector WorldOrigin, WorldDirection;
|
||||
if (!PlayerController->DeprojectScreenPositionToWorld(MouseX, MouseY, WorldOrigin, WorldDirection)) return;
|
||||
|
||||
APlayerCameraManager* CameraManager = PlayerController->PlayerCameraManager;
|
||||
FVector CameraForward = CameraManager->GetActorForwardVector();
|
||||
FPlane MovementPlane(CurrentSelectedMeshComponent->GetComponentLocation(), CameraForward);
|
||||
|
||||
FVector IntersectPoint = FMath::RayPlaneIntersection(WorldOrigin, WorldDirection, MovementPlane);
|
||||
|
||||
switch (CurrentGrabbedObjectMovementMode)
|
||||
{
|
||||
case ECoffeeMachinePropMovementMode::PlaneYZ:
|
||||
break;
|
||||
case ECoffeeMachinePropMovementMode::ZOnly:
|
||||
{
|
||||
IntersectPoint.X = CurrentGrabbedObjectStartPos.X;
|
||||
IntersectPoint.Y = CurrentGrabbedObjectStartPos.Y;
|
||||
|
||||
IntersectPoint.Z = FMath::Clamp(IntersectPoint.Z, CurrentGrabbedObjectStartPos.Z - 14.f, CurrentGrabbedObjectStartPos.Z);
|
||||
|
||||
// if (GEngine)
|
||||
// {
|
||||
// GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Red, FString::Printf(TEXT("Intersection point: %s"), *IntersectPoint.ToString()));
|
||||
// }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CurrentSelectedMeshComponent->SetWorldLocation(IntersectPoint);
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::HoverBox(UHoverableBoxComponent* InBox)
|
||||
{
|
||||
if (InBox == CurrentHoverableComponent)
|
||||
{
|
||||
if (CanHover(InBox))
|
||||
return;
|
||||
}
|
||||
|
||||
if (CurrentHoverableComponent)
|
||||
{
|
||||
CurrentHoverableComponent->OnUnhovered.Broadcast();
|
||||
CurrentHoverableComponent = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (CanHover(InBox))
|
||||
{
|
||||
CurrentHoverableComponent = InBox;
|
||||
CurrentHoverableComponent->OnHovered.Broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
bool UCoffeeMachineController::GrabObject(UHoverableBoxComponent* InBox)
|
||||
{
|
||||
if (CurrentCoffeeMakingStage != ECoffeeMachineMakingState::Start &&
|
||||
CurrentCoffeeMakingStage != ECoffeeMachineMakingState::PortafilterPressing) return false;
|
||||
|
||||
if (InBox && InBox->GetAttachParent() && CanGrab(InBox))
|
||||
{
|
||||
CurrentSelectedBoxComponent = InBox;
|
||||
CurrentSelectedMeshComponent = Cast<UStaticMeshComponent>(InBox->GetAttachParent());
|
||||
CurrentSelectedBoxComponent->OnSelected.Broadcast();
|
||||
|
||||
CurrentGrabbedObjectStartPos = CurrentSelectedMeshComponent->GetComponentLocation();
|
||||
|
||||
if (InBox->ComponentHasTag(OBJECT_TYPE_PORTAFILTER) && CurrentCoffeeMakingStage == ECoffeeMachineMakingState::Start)
|
||||
{
|
||||
SetCoffeeMakingStage(ECoffeeMachineMakingState::PortafilterDragging);
|
||||
CurrentGrabbedObjectMovementMode = ECoffeeMachinePropMovementMode::PlaneYZ;
|
||||
}
|
||||
else if (InBox->ComponentHasTag(OBJECT_TYPE_TAMPER) && CurrentCoffeeMakingStage == ECoffeeMachineMakingState::PortafilterPressing)
|
||||
{
|
||||
CurrentGrabbedObjectMovementMode = ECoffeeMachinePropMovementMode::ZOnly;
|
||||
CurrentGrabbedObjectStartPos = TamperLiftStartingPos;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::ReleaseObject()
|
||||
{
|
||||
OnObjectReleased.Broadcast();
|
||||
|
||||
if (CurrentSelectedBoxComponent)
|
||||
{
|
||||
CurrentSelectedBoxComponent->OnUnselected.Broadcast();
|
||||
}
|
||||
|
||||
CurrentSelectedMeshComponent = nullptr;
|
||||
CurrentSelectedBoxComponent = nullptr;
|
||||
}
|
||||
|
||||
bool UCoffeeMachineController::CanGrab(const UHoverableBoxComponent* InBox) const
|
||||
{
|
||||
return InBox &&
|
||||
((InBox->ComponentHasTag(OBJECT_TYPE_PORTAFILTER) && CurrentCoffeeMakingStage == ECoffeeMachineMakingState::Start) ||
|
||||
(InBox->ComponentHasTag(OBJECT_TYPE_TAMPER) && CurrentCoffeeMakingStage == ECoffeeMachineMakingState::PortafilterPressing));
|
||||
}
|
||||
|
||||
bool UCoffeeMachineController::CanHover(const UHoverableBoxComponent* InBox) const
|
||||
{
|
||||
if (!InBox) return false;
|
||||
|
||||
switch (CurrentCoffeeMakingStage)
|
||||
{
|
||||
case ECoffeeMachineMakingState::Start:
|
||||
{
|
||||
if (!InBox->ComponentHasTag(OBJECT_TYPE_PORTAFILTER) && !InBox->ComponentHasTag(OBJECT_TYPE_COFFEE_MUG)) return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case ECoffeeMachineMakingState::PortafilterDragging:
|
||||
{
|
||||
if (!InBox->ComponentHasTag(OBJECT_TYPE_GRINDER)) return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case ECoffeeMachineMakingState::PortafilterFilling:
|
||||
{
|
||||
if (!InBox->ComponentHasTag(OBJECT_TYPE_GRINDER_BUTTON)) return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case ECoffeeMachineMakingState::PortafilterPressing:
|
||||
{
|
||||
if (!InBox->ComponentHasTag(OBJECT_TYPE_TAMPER)) return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case ECoffeeMachineMakingState::CoffeeLoaded:
|
||||
{
|
||||
if (!InBox->ComponentHasTag(OBJECT_TYPE_MAIN_MACHINE_BUTTON) && !InBox->ComponentHasTag(OBJECT_TYPE_COFFEE_MUG)) return false;
|
||||
|
||||
// Cannot press button if cup not placed
|
||||
if (InBox->ComponentHasTag(OBJECT_TYPE_MAIN_MACHINE_BUTTON) && !bCupPlaced) return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case ECoffeeMachineMakingState::CoffeeFilling:
|
||||
{
|
||||
if (!InBox->ComponentHasTag(OBJECT_TYPE_MAIN_MACHINE_BUTTON)) return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case ECoffeeMachineMakingState::CoffeeReady:
|
||||
{
|
||||
if (!InBox->ComponentHasTag(OBJECT_TYPE_COFFEE_MUG)) return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case ECoffeeMachineMakingState::WaitingAction:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::OnInputGrab()
|
||||
{
|
||||
if (!GrabObject(CurrentHoverableComponent))
|
||||
{
|
||||
OnObjectClicked.Broadcast();
|
||||
}
|
||||
}
|
||||
|
||||
void UCoffeeMachineController::OnInputRelease()
|
||||
{
|
||||
ReleaseObject();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
127
Source/Faye/Components/CoffeeMachineController.h
Normal file
127
Source/Faye/Components/CoffeeMachineController.h
Normal file
@@ -0,0 +1,127 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "CoffeeMachineController.generated.h"
|
||||
|
||||
class UHoverableBoxComponent;
|
||||
class AFayePlayerController;
|
||||
|
||||
const FName OBJECT_TYPE_PORTAFILTER("Portafilter");
|
||||
const FName OBJECT_TYPE_TAMPER("Tamper");
|
||||
const FName OBJECT_TYPE_GRINDER("Grinder");
|
||||
const FName OBJECT_TYPE_MAIN_COFFEE_MACHINE("MainCoffeeMachine");
|
||||
const FName OBJECT_TYPE_GRINDER_BUTTON("GrinderButton");
|
||||
const FName OBJECT_TYPE_MAIN_MACHINE_BUTTON("MainMachineButton");
|
||||
const FName OBJECT_TYPE_COFFEE_MUG("CoffeeMug");
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnObjectReleased);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnObjectClicked);
|
||||
|
||||
UENUM()
|
||||
enum class EInputControllerType : uint8
|
||||
{
|
||||
Mouse,
|
||||
Touch,
|
||||
Gamepad
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ECoffeeMachineMakingState : uint8
|
||||
{
|
||||
Start,
|
||||
PortafilterDragging,
|
||||
PortafilterFilling,
|
||||
PortafilterPressing,
|
||||
CoffeeLoaded,
|
||||
CoffeeFilling,
|
||||
CoffeeReady,
|
||||
WaitingAction UMETA(ToolTip = "Use when you don't wanna be able to hover anythig")
|
||||
};
|
||||
|
||||
UENUM()
|
||||
enum class ECoffeeMachinePropMovementMode : uint8
|
||||
{
|
||||
PlaneYZ,
|
||||
ZOnly
|
||||
};
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent), Blueprintable)
|
||||
class FAYE_API UCoffeeMachineController : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCoffeeMachineController();
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
void ToggleCoffeeMaking(bool bActive);
|
||||
bool IsCoffeeMakingActive() const { return bCoffeeMakingActive; }
|
||||
|
||||
UFUNCTION(BLueprintPure)
|
||||
UHoverableBoxComponent* GetCurrentHoverableComponent() const { return CurrentHoverableComponent; }
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
UStaticMeshComponent* GetCurrentSelectedMeshComponent() const { return CurrentSelectedMeshComponent; }
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
UHoverableBoxComponent* GetCurrentSelectedBoxComponent() const { return CurrentSelectedBoxComponent; }
|
||||
|
||||
// Currently selected object will be nulled so cache if you need
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnObjectReleased OnObjectReleased;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnObjectClicked OnObjectClicked;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
bool bCupPlaced = false;
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SetCoffeeMakingStage(ECoffeeMachineMakingState NewStage);
|
||||
UFUNCTION(BlueprintPure)
|
||||
ECoffeeMachineMakingState GetCoffeeMakingStage() const { return CurrentCoffeeMakingStage; }
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SetTamperLiftStartingPos(FVector NewPos) { TamperLiftStartingPos = NewPos; }
|
||||
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY()
|
||||
AFayePlayerController* PlayerController;
|
||||
|
||||
ECoffeeMachineMakingState CurrentCoffeeMakingStage = ECoffeeMachineMakingState::Start;
|
||||
bool bCoffeeMakingActive = false;
|
||||
bool bHoldingPortafilter = false;
|
||||
|
||||
ECoffeeMachinePropMovementMode CurrentGrabbedObjectMovementMode;
|
||||
FVector CurrentGrabbedObjectStartPos;
|
||||
FVector TamperLiftStartingPos;
|
||||
|
||||
UPROPERTY()
|
||||
UHoverableBoxComponent* CurrentHoverableComponent = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
UStaticMeshComponent* CurrentSelectedMeshComponent = nullptr;
|
||||
UPROPERTY()
|
||||
UHoverableBoxComponent* CurrentSelectedBoxComponent = nullptr;
|
||||
|
||||
EInputControllerType InputType = EInputControllerType::Mouse;
|
||||
|
||||
void PerformMouseHover();
|
||||
void MoveHeldObject();
|
||||
|
||||
void HoverBox(UHoverableBoxComponent* InBox);
|
||||
bool GrabObject(UHoverableBoxComponent* InBox);
|
||||
void ReleaseObject();
|
||||
bool CanGrab(const UHoverableBoxComponent* InBox) const;
|
||||
bool CanHover(const UHoverableBoxComponent* InBox) const;
|
||||
|
||||
UFUNCTION()
|
||||
void OnInputGrab();
|
||||
UFUNCTION()
|
||||
void OnInputRelease();
|
||||
};
|
||||
14
Source/Faye/Components/HoverableBoxComponent.cpp
Normal file
14
Source/Faye/Components/HoverableBoxComponent.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "HoverableBoxComponent.h"
|
||||
|
||||
|
||||
UHoverableBoxComponent::UHoverableBoxComponent()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = false;
|
||||
UPrimitiveComponent::SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||
UPrimitiveComponent::SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||
UPrimitiveComponent::SetCollisionResponseToChannel(ECC_GameTraceChannel1, ECR_Block);
|
||||
}
|
||||
|
||||
33
Source/Faye/Components/HoverableBoxComponent.h
Normal file
33
Source/Faye/Components/HoverableBoxComponent.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/BoxComponent.h"
|
||||
#include "HoverableBoxComponent.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnHoveredSignature);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSelectedSignature);
|
||||
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class FAYE_API UHoverableBoxComponent : public UBoxComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UHoverableBoxComponent();
|
||||
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="Collision")
|
||||
FOnHoveredSignature OnHovered;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="Collision")
|
||||
FOnHoveredSignature OnUnhovered;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="Collision")
|
||||
FOnSelectedSignature OnSelected;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="Collision")
|
||||
FOnSelectedSignature OnUnselected;
|
||||
};
|
||||
82
Source/Faye/Components/NpcPawnMovement.cpp
Normal file
82
Source/Faye/Components/NpcPawnMovement.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "NpcPawnMovement.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Engine/World.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
|
||||
UNpcPawnMovement::UNpcPawnMovement()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
NavMovementProperties.bUseFixedBrakingDistanceForPaths = true;
|
||||
NavMovementProperties.bUseAccelerationForPaths = true;
|
||||
NavAgentProps.bCanWalk = true;
|
||||
NavAgentProps.bCanFly = false;
|
||||
NavAgentProps.bCanSwim = false;
|
||||
}
|
||||
|
||||
void UNpcPawnMovement::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
OwnerCapsuleComp = GetOwner()->GetComponentByClass<UCapsuleComponent>();
|
||||
}
|
||||
|
||||
void UNpcPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
SnapToGround();
|
||||
}
|
||||
|
||||
void UNpcPawnMovement::SnapToGround()
|
||||
{
|
||||
if (!UpdatedComponent || !OwnerCapsuleComp)
|
||||
return;
|
||||
|
||||
const FVector Start = UpdatedComponent->GetComponentLocation();
|
||||
const FVector End = Start - FVector(0, 0, GroundTraceDistance);
|
||||
|
||||
FHitResult Hit;
|
||||
FCollisionQueryParams TraceParams;
|
||||
TraceParams.AddIgnoredActor(GetOwner());
|
||||
|
||||
bool bHit = GetWorld()->LineTraceSingleByChannel(
|
||||
Hit,
|
||||
Start,
|
||||
End,
|
||||
ECC_WorldStatic,
|
||||
TraceParams);
|
||||
|
||||
if (bHit)
|
||||
{
|
||||
FVector NewLocation = Hit.Location;
|
||||
NewLocation.Z += OwnerCapsuleComp->GetScaledCapsuleHalfHeight();
|
||||
UpdatedComponent->SetWorldLocation(NewLocation);
|
||||
}
|
||||
}
|
||||
|
||||
void UNpcPawnMovement::RequestDirectMove(const FVector& MoveVelocity, bool bForceMaxSpeed)
|
||||
{
|
||||
//Super::RequestDirectMove(MoveVelocity, bForceMaxSpeed);
|
||||
FVector LineEnd = GetOwner()->GetActorLocation() + (MoveVelocity * 100.f);
|
||||
DrawDebugLine(GetWorld(), GetOwner()->GetActorLocation(), LineEnd ,FColor::Red, false, 1, 0, 1);
|
||||
FVector DesiredMovement = MoveVelocity;
|
||||
DesiredMovement.Z = 0.0f;
|
||||
AddInputVector(DesiredMovement.GetSafeNormal());
|
||||
}
|
||||
|
||||
bool UNpcPawnMovement::CanStartPathFollowing() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UNpcPawnMovement::CanStopPathFollowing() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void UNpcPawnMovement::RequestPathMove(const FVector& MoveInput)
|
||||
{
|
||||
AddInputVector(MoveInput, true);
|
||||
}
|
||||
31
Source/Faye/Components/NpcPawnMovement.h
Normal file
31
Source/Faye/Components/NpcPawnMovement.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/FloatingPawnMovement.h"
|
||||
#include "NpcPawnMovement.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(ClassGroup=Movement, meta=(BlueprintSpawnableComponent))
|
||||
class FAYE_API UNpcPawnMovement : public UFloatingPawnMovement
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UNpcPawnMovement();
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
void SnapToGround();
|
||||
virtual void RequestDirectMove(const FVector& MoveVelocity, bool bForceMaxSpeed) override;
|
||||
virtual bool CanStartPathFollowing() const override;
|
||||
virtual bool CanStopPathFollowing() const override;
|
||||
virtual void RequestPathMove(const FVector& MoveInput) override;
|
||||
|
||||
float GroundTraceDistance = 200000.f;
|
||||
|
||||
UPROPERTY()
|
||||
UCapsuleComponent* OwnerCapsuleComp = nullptr;
|
||||
};
|
||||
43
Source/Faye/Components/OrdersComponent.cpp
Normal file
43
Source/Faye/Components/OrdersComponent.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "OrdersComponent.h"
|
||||
|
||||
|
||||
UOrdersComponent::UOrdersComponent()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = false;
|
||||
}
|
||||
|
||||
void UOrdersComponent::AddOrder(UCoffeeFilter* Filter, ANpcPawn* InNpcPawn)
|
||||
{
|
||||
FOrderData OrderData;
|
||||
OrderData.Filter = Filter;
|
||||
OrderData.NpcPawn = InNpcPawn;
|
||||
OrderList.Add(OrderData);
|
||||
}
|
||||
|
||||
|
||||
UCoffeeFilter* UOrdersComponent::GetOrderForNpc(ANpcPawn* InNpcPawn) const
|
||||
{
|
||||
if (!InNpcPawn) return nullptr;
|
||||
|
||||
const FOrderData* FoundOrderData = OrderList.FindByPredicate([InNpcPawn](const FOrderData& OrderData)
|
||||
{
|
||||
return OrderData.NpcPawn == InNpcPawn;
|
||||
});
|
||||
|
||||
if (FoundOrderData)
|
||||
{
|
||||
return FoundOrderData->Filter;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UOrdersComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
}
|
||||
|
||||
|
||||
47
Source/Faye/Components/OrdersComponent.h
Normal file
47
Source/Faye/Components/OrdersComponent.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "OrdersComponent.generated.h"
|
||||
|
||||
class ANpcPawn;
|
||||
class UCoffeeFilter;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FOrderData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
UCoffeeFilter* Filter;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ANpcPawn* NpcPawn;
|
||||
};
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class FAYE_API UOrdersComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UOrdersComponent();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Orders")
|
||||
void AddOrder(UCoffeeFilter* Filter, ANpcPawn* InNpcPawn);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Orders")
|
||||
const TArray<FOrderData>& GetOrders() const { return OrderList; }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Orders")
|
||||
UCoffeeFilter* GetOrderForNpc(ANpcPawn* InNpcPawn) const;
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
TArray<FOrderData> OrderList;
|
||||
|
||||
};
|
||||
136
Source/Faye/Components/ShelfComponent.cpp
Normal file
136
Source/Faye/Components/ShelfComponent.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "ShelfComponent.h"
|
||||
|
||||
#include "Engine/StaticMeshActor.h"
|
||||
#include "Faye/System/FayeDeveloperSettings.h"
|
||||
|
||||
|
||||
UShelfComponent::UShelfComponent()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void UShelfComponent::GenerateBookRow()
|
||||
{
|
||||
if (!TransparentBookMaterial || TransparentBookMaterial_Highlighted)
|
||||
{
|
||||
LoadMaterials();
|
||||
}
|
||||
|
||||
const UFayeDeveloperSettings* DeveloperSettings = GetDefault<UFayeDeveloperSettings>();
|
||||
check(DeveloperSettings);
|
||||
|
||||
float ShelfWidth = GetScaledBoxExtent().X * 2;
|
||||
const float BookOffset = 1.f;
|
||||
|
||||
for (int32 i = ShelfStaticMeshes.Num() - 1; i > 0; --i)
|
||||
{
|
||||
ShelfStaticMeshes[i]->Destroy();
|
||||
}
|
||||
ShelfStaticMeshes.Empty();
|
||||
ShelfSizesStack.Empty();
|
||||
// while (ShelfWidth >= DeveloperSettings->BookShelfVariations[1].BookWidth)
|
||||
// {
|
||||
// int32 ChosenSize;
|
||||
// if (ShelfWidth <= DeveloperSettings->BookShelfVariations[2].BookWidth && ShelfWidth > DeveloperSettings->BookShelfVariations[1].BookWidth)
|
||||
// {
|
||||
// ChosenSize = FMath::RandBool() + 1;
|
||||
// ShelfWidth -= (DeveloperSettings->BookShelfVariations[ChosenSize].BookWidth * FinalScale) - BookOffset;
|
||||
// ShelfSizesStack.Add(ChosenSize);
|
||||
// continue;
|
||||
// }
|
||||
// if (ShelfWidth <= DeveloperSettings->BookShelfVariations[1].BookWidth)
|
||||
// {
|
||||
// ChosenSize = 1;
|
||||
// ShelfWidth -= (DeveloperSettings->BookShelfVariations[1].BookWidth * FinalScale) - BookOffset;
|
||||
// ShelfSizesStack.Add(ChosenSize);
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// ChosenSize = FMath::RandRange(1, 3);
|
||||
// ShelfWidth -= (DeveloperSettings->BookShelfVariations[ChosenSize].BookWidth * FinalScale) - BookOffset;
|
||||
// ShelfSizesStack.Add(ChosenSize);
|
||||
// }
|
||||
|
||||
const float xStart = GetScaledBoxExtent().X;
|
||||
float xPos = xStart;
|
||||
const int32 NumBooks = ShelfWidth / ((DeveloperSettings->BookShelfVariations[1].BookWidth * FinalScale) + BookOffset);
|
||||
for (int32 i = 0; i < NumBooks; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
xPos -= (DeveloperSettings->BookShelfVariations[1].BookWidth * FinalScale) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
xPos -= (DeveloperSettings->BookShelfVariations[1].BookWidth * FinalScale) + BookOffset;
|
||||
}
|
||||
UE_LOG(LogTemp, Warning, TEXT("Generate xPos: %f"), xPos);
|
||||
|
||||
AStaticMeshActor* MeshActor = Cast<AStaticMeshActor>(GetWorld()->SpawnActor(DeveloperSettings->DefaultBookStaticMeshClass));
|
||||
MeshActor->SetMobility(EComponentMobility::Type::Movable);
|
||||
MeshActor->AttachToActor(GetOwner(), FAttachmentTransformRules::KeepRelativeTransform);
|
||||
|
||||
const float FinalZScale = FMath::RandRange(FinalScale * 0.8f, FinalScale * 1.2f);
|
||||
FVector BookPosition = GetComponentLocation();
|
||||
MeshActor->SetActorScale3D(FVector(FinalScale, FinalScale, FinalScale));
|
||||
|
||||
//const FBoxSphereBounds NewBounds = MeshComp->Bounds;
|
||||
//const float HalfHeight = NewBounds.BoxExtent.Z;
|
||||
//BookPosition.Z += HalfHeight;
|
||||
BookPosition.Y += xPos;
|
||||
BookPosition.Z -= 5;
|
||||
MeshActor->SetActorLocation(BookPosition);
|
||||
MeshActor->SetActorRelativeRotation(FRotator(0, 90, 0));
|
||||
UE_LOG(LogTemp, Warning, TEXT("Spawn mesh xPos: %f"), xPos);
|
||||
}
|
||||
}
|
||||
|
||||
void UShelfComponent::SpawnStaticMesh(const FSoftObjectPath& Path, UObject* Object, float BookXOffset)
|
||||
{
|
||||
if (UStaticMesh* Mesh = Cast<UStaticMesh>(Object))
|
||||
{
|
||||
AStaticMeshActor* MeshActor = Cast<AStaticMeshActor>(GetWorld()->SpawnActor(AStaticMeshActor::StaticClass()));
|
||||
MeshActor->SetMobility(EComponentMobility::Type::Movable);
|
||||
MeshActor->AttachToActor(GetOwner(), FAttachmentTransformRules::KeepRelativeTransform);
|
||||
MeshActor->GetStaticMeshComponent()->SetStaticMesh(Mesh);
|
||||
MeshActor->GetStaticMeshComponent()->SetMaterial(0, TransparentBookMaterial);
|
||||
|
||||
const UFayeDeveloperSettings* DeveloperSettings = GetDefault<UFayeDeveloperSettings>();
|
||||
check(DeveloperSettings);
|
||||
|
||||
const float FinalZScale = FMath::RandRange(FinalScale * 0.8f, FinalScale * 1.2f);
|
||||
FVector BookPosition = GetComponentLocation();
|
||||
MeshActor->SetActorScale3D(FVector(FinalScale, FinalScale, FinalScale));
|
||||
|
||||
//const FBoxSphereBounds NewBounds = MeshComp->Bounds;
|
||||
//const float HalfHeight = NewBounds.BoxExtent.Z;
|
||||
//BookPosition.Z += HalfHeight;
|
||||
BookPosition.Y += BookXOffset;
|
||||
BookPosition.Z -= 5;
|
||||
MeshActor->SetActorLocation(BookPosition);
|
||||
UE_LOG(LogTemp, Warning, TEXT("Spawn mesh xPos: %f"), BookXOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void UShelfComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
LoadMaterials();
|
||||
}
|
||||
|
||||
void UShelfComponent::LoadMaterials()
|
||||
{
|
||||
const UFayeDeveloperSettings* DeveloperSettings = GetDefault<UFayeDeveloperSettings>();
|
||||
check(DeveloperSettings);
|
||||
|
||||
DeveloperSettings->TransparentBookMaterial.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateLambda([&](const FSoftObjectPath& Path, UObject* Object)
|
||||
{
|
||||
TransparentBookMaterial = Cast<UMaterialInterface>(Object);
|
||||
}));
|
||||
DeveloperSettings->TransparentBookMaterial_Highlighted.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateLambda([&](const FSoftObjectPath& Path, UObject* Object)
|
||||
{
|
||||
TransparentBookMaterial_Highlighted = Cast<UMaterialInterface>(Object);
|
||||
}));
|
||||
}
|
||||
44
Source/Faye/Components/ShelfComponent.h
Normal file
44
Source/Faye/Components/ShelfComponent.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/BoxComponent.h"
|
||||
#include "Engine/StaticMeshActor.h"
|
||||
|
||||
#include "ShelfComponent.generated.h"
|
||||
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class FAYE_API UShelfComponent : public UBoxComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UShelfComponent();
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UMaterialInterface* TransparentBookMaterial = nullptr;
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UMaterialInterface* TransparentBookMaterial_Highlighted = nullptr;
|
||||
|
||||
UFUNCTION(CallInEditor, BlueprintCallable)
|
||||
void GenerateBookRow();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TArray<AStaticMeshActor*> ShelfStaticMeshes;
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY()
|
||||
TArray<int32> ShelfSizesStack;
|
||||
|
||||
const float FinalScale = 0.65f;
|
||||
|
||||
UFUNCTION()
|
||||
void SpawnStaticMesh(const FSoftObjectPath& Path, UObject* Object, float BookXOffset);
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
void LoadMaterials();
|
||||
};
|
||||
68
Source/Faye/Data/Filters/ItemFilters.cpp
Normal file
68
Source/Faye/Data/Filters/ItemFilters.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
#include "ItemFilters.h"
|
||||
#include "Faye/Inventory/BookItem.h"
|
||||
#include "Faye/Inventory/CoffeeItem.h"
|
||||
|
||||
bool UItemFilter::Pass(const UItem* Item) const
|
||||
{
|
||||
if (!Item) return false;
|
||||
|
||||
if (!ItemName.IsEmpty() && !Item->ItemName.CompareToCaseIgnored(ItemName))
|
||||
return false;
|
||||
|
||||
if (ItemCategory != EItemCategory::None && Item->ItemCategory != ItemCategory)
|
||||
return false;
|
||||
|
||||
if ((PriceStart > -1 && PriceEnd > -1) && (Item->Price < PriceStart || Item->Price > PriceEnd))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UBookFilter::Pass(const UItem* Item) const
|
||||
{
|
||||
const UBookItem* Book = Cast<UBookItem>(Item);
|
||||
|
||||
if (!UItemFilter::Pass(Item)) return false;
|
||||
|
||||
if (BookCategory != EBookCategory::None && BookCategory != Book->BookCategory)
|
||||
return false;
|
||||
|
||||
if (BookSubCategory != EBookSubCategory::None && BookSubCategory != Book->BookSubCategory)
|
||||
return false;
|
||||
|
||||
if ((PublicationDateStart > -1 && PublicationDateEnd > -1) && (Book->PublicationDate < PublicationDateStart || Book->PublicationDate > PublicationDateEnd))
|
||||
return false;
|
||||
|
||||
if (!Author.IsEmpty() && !Book->Author.CompareToCaseIgnored(Author))
|
||||
return false;
|
||||
|
||||
if ((PageNumberStart > -1 && PageNumberEnd > -1) && (Book->PageNumber < PageNumberStart || Book->PageNumber > PageNumberEnd))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UCoffeeFilter::Pass(const UItem* Item) const
|
||||
{
|
||||
const UCoffeeItem* CoffeeItem = Cast<UCoffeeItem>(Item);
|
||||
|
||||
if (!Super::Pass(Item)) return false;
|
||||
|
||||
if (CoffeeType != ECoffeeType::None && CoffeeType != CoffeeItem->CoffeeType)
|
||||
return false;
|
||||
|
||||
if (CoffeeSize != ECoffeeSize::None && CoffeeSize != CoffeeItem->CoffeeSize)
|
||||
return false;
|
||||
|
||||
if (CoffeeAddition != ECoffeeAddition::None && CoffeeAddition != CoffeeItem->CoffeeAddition)
|
||||
return false;
|
||||
|
||||
if (bIced != CoffeeItem->bIced)
|
||||
return false;
|
||||
|
||||
if (bWhippedCream != CoffeeItem->bWhippedCream)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
77
Source/Faye/Data/Filters/ItemFilters.h
Normal file
77
Source/Faye/Data/Filters/ItemFilters.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include "Faye/Enums/CoffeeTypes.h"
|
||||
#include "Faye/Structs/BookDataStruct.h"
|
||||
#include "Faye/Structs/ItemDataStruct.h"
|
||||
#include "ItemFilters.generated.h"
|
||||
|
||||
class UItem;
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable, EditInlineNew, DefaultToInstanced)
|
||||
class FAYE_API UItemFilter: public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText ItemName = FText();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EItemCategory ItemCategory = EItemCategory::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PriceStart = -1;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PriceEnd = -1;
|
||||
|
||||
virtual bool Pass(const UItem* Item) const;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API UBookFilter : public UItemFilter
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EBookCategory BookCategory = EBookCategory::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EBookSubCategory BookSubCategory = EBookSubCategory::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PublicationDateStart = -1;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PublicationDateEnd = -1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText Author = FText();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PageNumberStart = -1;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PageNumberEnd = -1;
|
||||
|
||||
virtual bool Pass(const UItem* Item) const override;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API UCoffeeFilter : public UItemFilter
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ECoffeeType CoffeeType = ECoffeeType::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ECoffeeSize CoffeeSize = ECoffeeSize::Small;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
bool bIced = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ECoffeeAddition CoffeeAddition = ECoffeeAddition::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
bool bWhippedCream = false;
|
||||
|
||||
virtual bool Pass(const UItem* Item) const override;
|
||||
};
|
||||
4
Source/Faye/Data/OrderSettingsDataAsset.cpp
Normal file
4
Source/Faye/Data/OrderSettingsDataAsset.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "OrderSettingsDataAsset.h"
|
||||
48
Source/Faye/Data/OrderSettingsDataAsset.h
Normal file
48
Source/Faye/Data/OrderSettingsDataAsset.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Conditions/StateTreeGameplayTagConditions.h"
|
||||
#include "Engine/DataAsset.h"
|
||||
#include "OrderSettingsDataAsset.generated.h"
|
||||
|
||||
class USUDSScript;
|
||||
|
||||
UENUM(BlueprintType, meta = (BitFlags))
|
||||
enum class ECoffeeFilterFlags : uint8
|
||||
{
|
||||
SizeAndType,
|
||||
Iced,
|
||||
CoffeeAddition,
|
||||
WhippedCream
|
||||
};
|
||||
ENUM_CLASS_FLAGS(ECoffeeFilterFlags)
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FCoffeeFilterFlagsSet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Flags", meta = (Bitmask, BitmaskEnum = "/Script/Faye.ECoffeeFilterFlags"))
|
||||
uint8 Flags = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FGameplayTagQuery TagQuery;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TArray<USUDSScript*> ScriptsArray;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UOrderSettingsDataAsset : public UDataAsset
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||
TArray<FCoffeeFilterFlagsSet> FilterSettings;
|
||||
};
|
||||
4
Source/Faye/Data/ShopListDataAsset.cpp
Normal file
4
Source/Faye/Data/ShopListDataAsset.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "ShopListDataAsset.h"
|
||||
43
Source/Faye/Data/ShopListDataAsset.h
Normal file
43
Source/Faye/Data/ShopListDataAsset.h
Normal file
@@ -0,0 +1,43 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DataAsset.h"
|
||||
#include "ShopListDataAsset.generated.h"
|
||||
|
||||
enum class EBookCategory : uint8;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FItemSaleDataStruct
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText SaleItemName = FText();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText SaleItemDescription = FText();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 BaseCost = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TMap<EBookCategory, int32> CategoryDropWeight;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 DropAmount = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UShopListDataAsset : public UDataAsset
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TArray<FItemSaleDataStruct> SalesItemsList;
|
||||
};
|
||||
37
Source/Faye/Enums/CoffeeTypes.h
Normal file
37
Source/Faye/Enums/CoffeeTypes.h
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoffeeTypes.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ECoffeeType : uint8
|
||||
{
|
||||
None,
|
||||
Water,
|
||||
Espresso,
|
||||
Americano,
|
||||
Macchiato,
|
||||
Latte,
|
||||
Cappuccino,
|
||||
Max UMETA(Hidden)
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ECoffeeSize: uint8
|
||||
{
|
||||
None,
|
||||
Small,
|
||||
Medium,
|
||||
Large
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ECoffeeAddition : uint8
|
||||
{
|
||||
None,
|
||||
Muffin,
|
||||
Biscuit,
|
||||
Donut,
|
||||
Croissant,
|
||||
Max UMETA(Hidden)
|
||||
};
|
||||
55
Source/Faye/Faye.Build.cs
Normal file
55
Source/Faye/Faye.Build.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class Faye : ModuleRules
|
||||
{
|
||||
private string PluginsPath
|
||||
{
|
||||
get { return Path.GetFullPath( Path.Combine( ModuleDirectory, "../../Plugins/" ) ); }
|
||||
}
|
||||
|
||||
protected void AddSUDS() {
|
||||
// Linker
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { "SUDS" });
|
||||
// Headers
|
||||
PublicIncludePaths.Add(Path.Combine( PluginsPath, "SUDS", "Source", "SUDS", "Public"));
|
||||
}
|
||||
|
||||
public Faye(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "UMG",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"Niagara",
|
||||
"StateTreeModule",
|
||||
"DaySequence",
|
||||
"DeveloperSettings",
|
||||
"AIModule",
|
||||
"NavigationSystem",
|
||||
"StructUtils"
|
||||
});
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new string[]
|
||||
{
|
||||
"InteractionSystem",
|
||||
"GameplayStateTreeModule",
|
||||
"StatForge",
|
||||
"AsyncMessageSystem",
|
||||
"GameplayTags"
|
||||
});
|
||||
|
||||
AddSUDS();
|
||||
|
||||
// Uncomment if you are using Slate UI
|
||||
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
|
||||
|
||||
// Uncomment if you are using online features
|
||||
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
|
||||
|
||||
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
|
||||
}
|
||||
}
|
||||
6
Source/Faye/Faye.cpp
Normal file
6
Source/Faye/Faye.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "Faye.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, Faye, "Faye" );
|
||||
6
Source/Faye/Faye.h
Normal file
6
Source/Faye/Faye.h
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
26
Source/Faye/GameObjects/BookOnShelfActor.cpp
Normal file
26
Source/Faye/GameObjects/BookOnShelfActor.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "BookOnShelfActor.h"
|
||||
|
||||
|
||||
// Sets default values
|
||||
ABookOnShelfActor::ABookOnShelfActor()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Called when the game starts or when spawned
|
||||
void ABookOnShelfActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
void ABookOnShelfActor::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
31
Source/Faye/GameObjects/BookOnShelfActor.h
Normal file
31
Source/Faye/GameObjects/BookOnShelfActor.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/StaticMeshActor.h"
|
||||
#include "BookOnShelfActor.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API ABookOnShelfActor : public AStaticMeshActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this actor's properties
|
||||
ABookOnShelfActor();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable)
|
||||
void Select();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable)
|
||||
void Deselect();
|
||||
|
||||
protected:
|
||||
// Called when the game starts or when spawned
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
public:
|
||||
// Called every frame
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
};
|
||||
26
Source/Faye/GameObjects/CashRegisterActor.cpp
Normal file
26
Source/Faye/GameObjects/CashRegisterActor.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "CashRegisterActor.h"
|
||||
|
||||
|
||||
// Sets default values
|
||||
ACashRegisterActor::ACashRegisterActor()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Called when the game starts or when spawned
|
||||
void ACashRegisterActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
void ACashRegisterActor::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
25
Source/Faye/GameObjects/CashRegisterActor.h
Normal file
25
Source/Faye/GameObjects/CashRegisterActor.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NpcUsableActor.h"
|
||||
#include "CashRegisterActor.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API ACashRegisterActor : public ANpcUsableActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this actor's properties
|
||||
ACashRegisterActor();
|
||||
|
||||
protected:
|
||||
// Called when the game starts or when spawned
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
public:
|
||||
// Called every frame
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
};
|
||||
49
Source/Faye/GameObjects/CoffeeMachineActor.cpp
Normal file
49
Source/Faye/GameObjects/CoffeeMachineActor.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "CoffeeMachineActor.h"
|
||||
|
||||
#include "Components/InteractionWidgetComponent.h"
|
||||
#include "Faye/Components/CoffeeMachineController.h"
|
||||
|
||||
|
||||
ACoffeeMachineActor::ACoffeeMachineActor()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
|
||||
SetRootComponent(RootComponent);
|
||||
|
||||
WidgetComponent = CreateDefaultSubobject<UInteractionWidgetComponent>(TEXT("WidgetComponent"));
|
||||
WidgetComponent->SetupAttachment(RootComponent);
|
||||
|
||||
CoffeeMachineController = CreateDefaultSubobject<UCoffeeMachineController>(TEXT("CoffeeMachineController"));
|
||||
}
|
||||
|
||||
void ACoffeeMachineActor::ToggleInteractableUI_Implementation(bool bActive)
|
||||
{
|
||||
if (bActive && !IInteractableActorInterface::Execute_IsInteractable(this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IInteractableActorInterface::ToggleInteractableUI_Implementation(bActive);
|
||||
|
||||
if (WidgetComponent)
|
||||
{
|
||||
WidgetComponent->ToggleWidget(bActive);
|
||||
}
|
||||
}
|
||||
|
||||
void ACoffeeMachineActor::Interact_Implementation(AActor* InteractionInstigator)
|
||||
{
|
||||
IInteractableActorInterface::Interact_Implementation(InteractionInstigator);
|
||||
|
||||
CoffeeMachineController->ToggleCoffeeMaking(true);
|
||||
}
|
||||
|
||||
void ACoffeeMachineActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
}
|
||||
|
||||
|
||||
44
Source/Faye/GameObjects/CoffeeMachineActor.h
Normal file
44
Source/Faye/GameObjects/CoffeeMachineActor.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Faye/Components/CoffeeMachineController.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Interface/InteractableActorInterface.h"
|
||||
#include "CoffeeMachineActor.generated.h"
|
||||
|
||||
class UCoffeeMachineController;
|
||||
class UInteractionWidgetComponent;
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API ACoffeeMachineActor : public AActor, public IInteractableActorInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
ACoffeeMachineActor();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Coffee Machine")
|
||||
UCoffeeMachineController* GetCoffeeMachineController() const { return CoffeeMachineController; }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Coffee Machine")
|
||||
bool IsCoffeeMakingActive() const { return CoffeeMachineController? CoffeeMachineController->IsCoffeeMakingActive() : false; }
|
||||
|
||||
/*--- INTERACTION START ---*/
|
||||
|
||||
virtual FText GetInteractionText_Implementation() const override { return NSLOCTEXT("Faye", "CoffeeMachineInteract", "Make Coffee"); }
|
||||
virtual bool IsInteractable_Implementation() const override { return true; }
|
||||
virtual void ToggleInteractableUI_Implementation(bool bActive) override;
|
||||
virtual void Interact_Implementation(AActor* InteractionInstigator) override;
|
||||
/*--- INTERACTION END ---*/
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
UInteractionWidgetComponent* WidgetComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
UCoffeeMachineController* CoffeeMachineController;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
};
|
||||
257
Source/Faye/GameObjects/NpcPawn.cpp
Normal file
257
Source/Faye/GameObjects/NpcPawn.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "NpcPawn.h"
|
||||
|
||||
#include "StateTree.h"
|
||||
#include "SUDSDialogue.h"
|
||||
#include "Components/StateTreeComponent.h"
|
||||
#include "Components/StatForgeComponent.h"
|
||||
#include "Faye/Data/OrderSettingsDataAsset.h"
|
||||
#include "Faye/Inventory/ItemDatabase.h"
|
||||
#include "Faye/Data/Filters/ItemFilters.h"
|
||||
#include "Faye/System/FayeDeveloperSettings.h"
|
||||
#include "Faye/Structs/CommonStructs.h"
|
||||
|
||||
ANpcPawn::ANpcPawn()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
CapsuleComponent = CreateDefaultSubobject<UCapsuleComponent>("Capsule Component");
|
||||
RootComponent = CapsuleComponent;
|
||||
|
||||
MovementComponent = CreateDefaultSubobject<UNpcPawnMovement>("Movement Component");
|
||||
MovementComponent->UpdatedComponent = CapsuleComponent;
|
||||
|
||||
StateTreeComponent = CreateDefaultSubobject<UStateTreeComponent>("StateTreeComponent");
|
||||
StateTreeComponent->SetStartLogicAutomatically(false);
|
||||
|
||||
StatForgeComponent = CreateDefaultSubobject<UStatForgeComponent>("Stat Forge Component");
|
||||
|
||||
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
|
||||
}
|
||||
|
||||
void ANpcPawn::OnDialogueStarting_Implementation(USUDSDialogue* Dialogue, FName AtLabel)
|
||||
{
|
||||
ISUDSParticipant::OnDialogueStarting_Implementation(Dialogue, AtLabel);
|
||||
|
||||
if (Dialogue)
|
||||
{
|
||||
Dialogue->SetVariableText(FName("SpeakerName.NPCName"), GetNpcBaseData().NpcDisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
void ANpcPawn::GenerateBookFilter()
|
||||
{
|
||||
const UFayeDeveloperSettings* DeveloperSettings = GetDefault<UFayeDeveloperSettings>();
|
||||
FBookFilterFlagsSet FlagSet = DeveloperSettings->BookFilterVariations[FMath::RandRange(0, DeveloperSettings->BookFilterVariations.Num() - 1)];
|
||||
int32 Flag = FlagSet.Flags;
|
||||
|
||||
UItemDatabase* ItemDatabase = UItemDatabase::Get(this);
|
||||
UBookFilter* BookFilter = NewObject<UBookFilter>(this);
|
||||
TArray<UItem*> AllBooks = UItemDatabase::GetAllBooks(this);
|
||||
bool bFilterPasses = false;
|
||||
|
||||
if (Flag & (1 << static_cast<uint8>(EBookFilterFlags::Author)))
|
||||
{
|
||||
const TArray<FText>& AuthorList = UItemDatabase::GetAuthorList(this);
|
||||
while (!bFilterPasses)
|
||||
{
|
||||
BookFilter->Author = AuthorList[FMath::RandRange(0, AuthorList.Num() - 1)];
|
||||
TArray<UItem*> TempBooks = AllBooks;
|
||||
UItemDatabase::FilterItemArray(BookFilter, TempBooks);
|
||||
if (!TempBooks.IsEmpty())
|
||||
{
|
||||
bFilterPasses = true;
|
||||
AllBooks = TempBooks;
|
||||
}
|
||||
}
|
||||
BookFilter->Author = FText();
|
||||
}
|
||||
|
||||
if (Flag & (1 << static_cast<uint8>(EBookFilterFlags::PublicationYear)))
|
||||
{
|
||||
TMap<int32, FObjectContainer> BookByDecadesMap;
|
||||
for (auto Book : AllBooks)
|
||||
{
|
||||
if (UBookItem* BookItem = Cast<UBookItem>(Book))
|
||||
{
|
||||
int32 Decade = FMath::Floor((float)BookItem->PublicationDate / 10.f);
|
||||
if (auto FoundDecade = BookByDecadesMap.Find(Decade))
|
||||
{
|
||||
FoundDecade->Objects.Add(BookItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
FObjectContainer Container;
|
||||
Container.Objects.Add(BookItem);
|
||||
BookByDecadesMap.Add(Decade, Container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TArray<int32> Keys;
|
||||
BookByDecadesMap.GetKeys(Keys);
|
||||
bFilterPasses = false;
|
||||
|
||||
for (int32 i = 0; i < 10 && !bFilterPasses; i++)
|
||||
{
|
||||
int32 RandIndex = FMath::RandRange(0, Keys.Num() - 1);
|
||||
BookFilter->PublicationDateStart = Keys[RandIndex] * 10;
|
||||
BookFilter->PublicationDateEnd = (Keys[RandIndex] * 10) + 9;
|
||||
|
||||
TArray<UItem*> TempBooks = AllBooks;
|
||||
UItemDatabase::FilterItemArray(BookFilter, TempBooks);
|
||||
|
||||
if (!TempBooks.IsEmpty())
|
||||
{
|
||||
bFilterPasses = true;
|
||||
AllBooks = TempBooks;
|
||||
}
|
||||
}
|
||||
BookFilter->PublicationDateStart = INDEX_NONE;
|
||||
BookFilter->PublicationDateEnd = INDEX_NONE;
|
||||
}
|
||||
|
||||
if (Flag & (1 << static_cast<int32>(EBookFilterFlags::PageNumber)))
|
||||
{
|
||||
bFilterPasses = false;
|
||||
TArray<EPageNumberCategorisation> Keys;
|
||||
DeveloperSettings->BookLengthLimits.GetKeys(Keys);
|
||||
|
||||
for (int32 i = 0; i < 10 && !bFilterPasses; i++)
|
||||
{
|
||||
int32 RandIndex = FMath::RandRange(0, Keys.Num() - 1);
|
||||
BookFilter->PageNumberStart = 0;
|
||||
BookFilter->PageNumberEnd = DeveloperSettings->BookLengthLimits[Keys[RandIndex]];
|
||||
|
||||
TArray<UItem*> TempBooks = AllBooks;
|
||||
UItemDatabase::FilterItemArray(BookFilter, TempBooks);
|
||||
|
||||
if (!TempBooks.IsEmpty())
|
||||
{
|
||||
bFilterPasses = true;
|
||||
AllBooks = TempBooks;
|
||||
}
|
||||
}
|
||||
BookFilter->PageNumberStart = INDEX_NONE;
|
||||
BookFilter->PageNumberEnd = INDEX_NONE;
|
||||
}
|
||||
|
||||
if (Flag & (1 << static_cast<uint8>(EBookFilterFlags::BookCategory)))
|
||||
{
|
||||
bFilterPasses = false;
|
||||
for (int32 i = 0; i < 10 && !bFilterPasses; i++)
|
||||
{
|
||||
EBookCategory BookCategory = static_cast<EBookCategory>(FMath::RandRange(1, static_cast<int32>(EBookCategory::ChildrenAndYoungAdult)));
|
||||
BookFilter->BookCategory = BookCategory;
|
||||
|
||||
TArray<UItem*> TempBooks = AllBooks;
|
||||
UItemDatabase::FilterItemArray(BookFilter, TempBooks);
|
||||
|
||||
if (!TempBooks.IsEmpty())
|
||||
{
|
||||
bFilterPasses = true;
|
||||
AllBooks = TempBooks;
|
||||
}
|
||||
}
|
||||
BookFilter->BookCategory = EBookCategory::None;
|
||||
}
|
||||
|
||||
if (Flag & (1 << static_cast<uint8>(EBookFilterFlags::BookSubcategory)))
|
||||
{
|
||||
bFilterPasses = false;
|
||||
for (int32 i = 0; i < 10 && !bFilterPasses; i++)
|
||||
{
|
||||
EBookSubCategory BookSubCategory = static_cast<EBookSubCategory>(FMath::RandRange(1, static_cast<int32>(EBookSubCategory::YoungAdult)));
|
||||
BookFilter->BookSubCategory = BookSubCategory;
|
||||
|
||||
TArray<UItem*> TempBooks = AllBooks;
|
||||
UItemDatabase::FilterItemArray(BookFilter, TempBooks);
|
||||
|
||||
if (!TempBooks.IsEmpty())
|
||||
{
|
||||
bFilterPasses = true;
|
||||
AllBooks = TempBooks;
|
||||
}
|
||||
}
|
||||
BookFilter->BookSubCategory = EBookSubCategory::None;
|
||||
}
|
||||
|
||||
int32 Num = AllBooks.Num();
|
||||
UE_LOG(LogTemp, Warning, TEXT("Found books with filter: %d, bitmask: %d"), Num, Flag);
|
||||
|
||||
ChosenBookFilter = BookFilter;
|
||||
}
|
||||
|
||||
void ANpcPawn::GenerateCoffeeFilter()
|
||||
{
|
||||
const UFayeDeveloperSettings* DeveloperSettings = GetDefault<UFayeDeveloperSettings>();
|
||||
FCoffeeFilterFlagsSet FlagSet;
|
||||
|
||||
if (CustomOrderSettings)
|
||||
{
|
||||
FlagSet = CustomOrderSettings->FilterSettings[FMath::RandRange(0, CustomOrderSettings->FilterSettings.Num() - 1)];
|
||||
}
|
||||
else
|
||||
{
|
||||
FlagSet = DeveloperSettings->GetOrderSettingDataAsset()->FilterSettings[FMath::RandRange(0, DeveloperSettings->GetOrderSettingDataAsset()->FilterSettings.Num() - 1)];
|
||||
}
|
||||
|
||||
int32 Flag = FlagSet.Flags;
|
||||
|
||||
UCoffeeFilter* CoffeeFilter = NewObject<UCoffeeFilter>(this);
|
||||
|
||||
if (Flag & (1 << static_cast<uint8>(ECoffeeFilterFlags::SizeAndType)))
|
||||
{
|
||||
CoffeeFilter->CoffeeSize = static_cast<ECoffeeSize>(FMath::RandRange(static_cast<int32>(ECoffeeSize::Small), static_cast<int32>(ECoffeeSize::Large)));
|
||||
CoffeeFilter->CoffeeType = static_cast<ECoffeeType>(FMath::RandRange(static_cast<int32>(ECoffeeType::Water), static_cast<int32>(ECoffeeType::Max) - 1));
|
||||
}
|
||||
|
||||
if (Flag & (1 << static_cast<uint8>(ECoffeeFilterFlags::Iced)))
|
||||
{
|
||||
CoffeeFilter->bIced = false; //FMath::RandBool();
|
||||
}
|
||||
|
||||
if (Flag & (1 << static_cast<uint8>(ECoffeeFilterFlags::CoffeeAddition)))
|
||||
{
|
||||
CoffeeFilter->CoffeeAddition = ECoffeeAddition::None; //static_cast<ECoffeeAddition>(FMath::RandRange(static_cast<int32>(ECoffeeAddition::Muffin), static_cast<int32>(ECoffeeAddition::Max) - 1));
|
||||
}
|
||||
|
||||
if (Flag & (1 << static_cast<uint8>(ECoffeeFilterFlags::WhippedCream)))
|
||||
{
|
||||
CoffeeFilter->bWhippedCream = false; //FMath::RandBool();
|
||||
}
|
||||
|
||||
ChosenCoffeeFilter = CoffeeFilter;
|
||||
}
|
||||
|
||||
void ANpcPawn::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
if (!StateTree.IsNull())
|
||||
{
|
||||
StateTree.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this](const FSoftObjectPath& Path, UObject* Object)
|
||||
{
|
||||
if (!StateTreeComponent) return;
|
||||
|
||||
if (UStateTree* LoadedStateTree = Cast<UStateTree>(Object))
|
||||
{
|
||||
StateTreeComponent->SetStateTree(LoadedStateTree);
|
||||
StateTreeComponent->StartLogic();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void ANpcPawn::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
UPawnMovementComponent* ANpcPawn::GetMovementComponent() const
|
||||
{
|
||||
return MovementComponent;
|
||||
}
|
||||
|
||||
95
Source/Faye/GameObjects/NpcPawn.h
Normal file
95
Source/Faye/GameObjects/NpcPawn.h
Normal file
@@ -0,0 +1,95 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "SUDSParticipant.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "Faye/Components/NpcPawnMovement.h"
|
||||
#include "NpcPawn.generated.h"
|
||||
|
||||
class UOrderSettingsDataAsset;
|
||||
class UCoffeeFilter;
|
||||
class UStatForgeComponent;
|
||||
class UStateTree;
|
||||
class UBookFilter;
|
||||
class AShelfActor;
|
||||
class UStateTreeComponent;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FNpcBaseData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC")
|
||||
FName NpcName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NPC")
|
||||
FText NpcDisplayName;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API ANpcPawn : public APawn, public ISUDSParticipant
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ANpcPawn();
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
virtual UPawnMovementComponent* GetMovementComponent() const override;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "NPC")
|
||||
FName GetNpcName() const { return NpcBaseData.NpcName; }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "NPC")
|
||||
FNpcBaseData GetNpcBaseData() const { return NpcBaseData; }
|
||||
|
||||
//DIALOGUE
|
||||
virtual void OnDialogueStarting_Implementation(USUDSDialogue* Dialogue, FName AtLabel) override;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "NPC")
|
||||
UStateTreeComponent* GetStateTreeComponent() const { return StateTreeComponent; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "NPC")
|
||||
void GenerateBookFilter();
|
||||
UFUNCTION(BlueprintPure, Category = "NPC")
|
||||
UBookFilter* GetChosenBookFilter() const { return ChosenBookFilter; }
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void GenerateCoffeeFilter();
|
||||
UFUNCTION(BlueprintPure, Category = "NPC")
|
||||
UCoffeeFilter* GetChosenCoffeeFilter() const { return ChosenCoffeeFilter; }
|
||||
|
||||
TObjectPtr<UOrderSettingsDataAsset> GetCustomOrderSettings() const { return CustomOrderSettings; }
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FNpcBaseData NpcBaseData;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
TSoftObjectPtr<UStateTree> StateTree;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
TObjectPtr<UOrderSettingsDataAsset> CustomOrderSettings;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
TObjectPtr<UCapsuleComponent> CapsuleComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
TObjectPtr<UNpcPawnMovement> MovementComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
TObjectPtr<UStateTreeComponent> StateTreeComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta=(AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UStatForgeComponent> StatForgeComponent;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<UBookFilter> ChosenBookFilter = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<UCoffeeFilter> ChosenCoffeeFilter = nullptr;
|
||||
};
|
||||
70
Source/Faye/GameObjects/NpcUsableActor.cpp
Normal file
70
Source/Faye/GameObjects/NpcUsableActor.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "NpcUsableActor.h"
|
||||
#include "NpcPawn.h"
|
||||
#include "PlayerCharacter.h"
|
||||
#include "Components/InteractionWidgetComponent.h"
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "Components/StatForgeComponent.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
ANpcUsableActor::ANpcUsableActor()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
|
||||
SetRootComponent(RootComponent);
|
||||
|
||||
WidgetComponent = CreateDefaultSubobject<UInteractionWidgetComponent>(TEXT("WidgetComponent"));
|
||||
WidgetComponent->SetupAttachment(RootComponent);
|
||||
|
||||
StatForgeComponent = CreateDefaultSubobject<UStatForgeComponent>("Stat Forge Component");
|
||||
|
||||
NpcArriveOverlap = CreateDefaultSubobject<USphereComponent>("Npc Arrive Overlap");
|
||||
NpcArriveOverlap->SetupAttachment(RootComponent);
|
||||
NpcArriveOverlap->SetSphereRadius(50.f);
|
||||
NpcArriveOverlap->SetCollisionEnabled(ECollisionEnabled::Type::QueryOnly);
|
||||
NpcArriveOverlap->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||
NpcArriveOverlap->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
|
||||
NpcArriveOverlap->OnComponentBeginOverlap.AddUniqueDynamic(this, &ANpcUsableActor::OnNpcOverlap);
|
||||
}
|
||||
|
||||
void ANpcUsableActor::Occupy(ANpcPawn* InNpc)
|
||||
{
|
||||
if (GetMaxNumOfOccupants() <= UsedByNpcList.Num())
|
||||
return;
|
||||
|
||||
UsedByNpcList.Add(InNpc);
|
||||
}
|
||||
|
||||
void ANpcUsableActor::ToggleInteractableUI_Implementation(bool bActive)
|
||||
{
|
||||
if (bActive && !IInteractableActorInterface::Execute_IsInteractable(this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IInteractableActorInterface::ToggleInteractableUI_Implementation(bActive);
|
||||
|
||||
if (WidgetComponent)
|
||||
{
|
||||
WidgetComponent->ToggleWidget(bActive);
|
||||
}
|
||||
}
|
||||
|
||||
void ANpcUsableActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
PlayerCharRef = Cast<APlayerCharacter>(UGameplayStatics::GetPlayerCharacter(this, 0));
|
||||
ensure(PlayerCharRef);
|
||||
}
|
||||
|
||||
void ANpcUsableActor::OnNpcOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
|
||||
{
|
||||
if (OtherActor && UsedByNpcList.Contains(OtherActor) && !ArrivedNpcs.Contains(OtherActor))
|
||||
{
|
||||
ArrivedNpcs.AddUnique(Cast<ANpcPawn>(OtherActor));
|
||||
}
|
||||
}
|
||||
|
||||
92
Source/Faye/GameObjects/NpcUsableActor.h
Normal file
92
Source/Faye/GameObjects/NpcUsableActor.h
Normal file
@@ -0,0 +1,92 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Interface/InteractableActorInterface.h"
|
||||
#include "NpcUsableActor.generated.h"
|
||||
|
||||
class APlayerCharacter;
|
||||
class USphereComponent;
|
||||
class UStatForgeComponent;
|
||||
class ANpcPawn;
|
||||
class UInteractionWidgetComponent;
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EInteractAnimAction : uint8
|
||||
{
|
||||
Idle,
|
||||
Sitting
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API ANpcUsableActor : public AActor, public IInteractableActorInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ANpcUsableActor();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Usable Actor")
|
||||
void Occupy(ANpcPawn* InNpc);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Usable Actor")
|
||||
bool IsOccupied() const { return UsedByNpcList.Num() >= GetMaxNumOfOccupants(); }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Usable Actor")
|
||||
int32 GetNumOfOccupants() const { return UsedByNpcList.Num(); }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Usable Actor")
|
||||
ANpcPawn* GetNextOccupant() const { return UsedByNpcList.IsEmpty()? nullptr : UsedByNpcList.Last(); }
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
|
||||
FVector GetNpcArriveLocation();
|
||||
virtual FVector GetNpcArriveLocation_Implementation() { return FVector(); }
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
|
||||
EInteractAnimAction GetInteractAnimAction();
|
||||
virtual EInteractAnimAction GetInteractAnimAction_Implementation() { return EInteractAnimAction::Idle; }
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
|
||||
int32 GetMaxNumOfOccupants() const;
|
||||
virtual int32 GetMaxNumOfOccupants_Implementation() const { return 1; }
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable)
|
||||
bool DidAllOccupantsArrive() const {return UsedByNpcList.Num() == ArrivedNpcs.Num();}
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCallable)
|
||||
APlayerCharacter* GetCachedPlayerCharacter() const { return PlayerCharRef; }
|
||||
|
||||
/*--- INTERACTION START ---*/
|
||||
|
||||
virtual FText GetInteractionText_Implementation() const override { return NSLOCTEXT("Faye", "UsableActorInteract", "Interact"); }
|
||||
virtual bool IsInteractable_Implementation() const override { return true; }
|
||||
virtual void ToggleInteractableUI_Implementation(bool bActive) override;
|
||||
|
||||
/*--- INTERACTION END ---*/
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY()
|
||||
TArray<ANpcPawn*> UsedByNpcList;
|
||||
UPROPERTY()
|
||||
TArray<ANpcPawn*> ArrivedNpcs;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<APlayerCharacter> PlayerCharRef = nullptr;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UFUNCTION()
|
||||
void OnNpcOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
UInteractionWidgetComponent* WidgetComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta=(AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UStatForgeComponent> StatForgeComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta=(AllowPrivateAccess = "true"))
|
||||
TObjectPtr<USphereComponent> NpcArriveOverlap;
|
||||
};
|
||||
26
Source/Faye/GameObjects/Phone.cpp
Normal file
26
Source/Faye/GameObjects/Phone.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "Phone.h"
|
||||
#include "Faye/Inventory/Inventory.h"
|
||||
|
||||
APhone::APhone()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void APhone::BeginPlay()
|
||||
{
|
||||
Inventory = NewObject<UInventory>(this);
|
||||
Super::BeginPlay();
|
||||
}
|
||||
|
||||
void APhone::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
UInventory* APhone::GetInventory_Implementation() const
|
||||
{
|
||||
return Inventory;
|
||||
}
|
||||
|
||||
26
Source/Faye/GameObjects/Phone.h
Normal file
26
Source/Faye/GameObjects/Phone.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Faye/Interfaces/InventoryInterface.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Phone.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API APhone : public AActor, public IInventoryInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
APhone();
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
virtual UInventory* GetInventory_Implementation() const override;
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY()
|
||||
UInventory* Inventory = nullptr;
|
||||
};
|
||||
60
Source/Faye/GameObjects/PlayerCharacter.cpp
Normal file
60
Source/Faye/GameObjects/PlayerCharacter.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "PlayerCharacter.h"
|
||||
|
||||
#include "Components/StatForgeComponent.h"
|
||||
#include "Faye/Components/OrdersComponent.h"
|
||||
#include "Faye/Inventory/Inventory.h"
|
||||
#include "Interface/InteractableActorInterface.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Subsystem/InteractionSubsystem.h"
|
||||
|
||||
|
||||
// Sets default values
|
||||
APlayerCharacter::APlayerCharacter()
|
||||
{
|
||||
// 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;
|
||||
|
||||
StatForgeComponent = CreateDefaultSubobject<UStatForgeComponent>("Stat Forge Component");
|
||||
OrdersComponent = CreateDefaultSubobject<UOrdersComponent>("Orders Component");
|
||||
}
|
||||
|
||||
// Called when the game starts or when spawned
|
||||
void APlayerCharacter::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
Inventory = NewObject<UInventory>(this);
|
||||
Inventory->ModifyGold(100);
|
||||
|
||||
PlayerController = Cast<AFayePlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
void APlayerCharacter::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
// Called to bind functionality to input
|
||||
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||||
{
|
||||
Super::SetupPlayerInputComponent(PlayerInputComponent);
|
||||
|
||||
}
|
||||
|
||||
UInventory* APlayerCharacter::GetInventory_Implementation() const
|
||||
{
|
||||
return Inventory;
|
||||
}
|
||||
|
||||
void APlayerCharacter::InteractWithObject()
|
||||
{
|
||||
if (AActor* ClosestInteractable = UInteractionSubsystem::GetClosestInteractable(this))
|
||||
{
|
||||
IInteractableActorInterface::Execute_Interact(ClosestInteractable, this);
|
||||
}
|
||||
}
|
||||
|
||||
55
Source/Faye/GameObjects/PlayerCharacter.h
Normal file
55
Source/Faye/GameObjects/PlayerCharacter.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "SUDSParticipant.h"
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "Faye/Base/FayePlayerController.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Faye/Interfaces/InventoryInterface.h"
|
||||
#include "PlayerCharacter.generated.h"
|
||||
|
||||
|
||||
class UOrdersComponent;
|
||||
class UStatForgeComponent;
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API APlayerCharacter :
|
||||
public ACharacter,
|
||||
public IInventoryInterface,
|
||||
public ISUDSParticipant
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
APlayerCharacter();
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
|
||||
|
||||
// INVENTORY
|
||||
virtual UInventory* GetInventory_Implementation() const override;
|
||||
|
||||
//DIALOGUE
|
||||
|
||||
void InteractWithObject();
|
||||
|
||||
protected:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
USphereComponent* InteractionOverlapComponent = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<AFayePlayerController> PlayerController;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY()
|
||||
UInventory* Inventory = nullptr;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta=(AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UStatForgeComponent> StatForgeComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta=(AllowPrivateAccess = "true"))
|
||||
TObjectPtr<UOrdersComponent> OrdersComponent;
|
||||
};
|
||||
43
Source/Faye/GameObjects/ShelfActor.cpp
Normal file
43
Source/Faye/GameObjects/ShelfActor.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "ShelfActor.h"
|
||||
|
||||
#include "Components/InteractionWidgetComponent.h"
|
||||
#include "Faye/Components/ShelfComponent.h"
|
||||
#include "Faye/Inventory/Inventory.h"
|
||||
|
||||
AShelfActor::AShelfActor()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void AShelfActor::BeginPlay()
|
||||
{
|
||||
Inventory = NewObject<UInventory>(this);
|
||||
Super::BeginPlay();
|
||||
|
||||
GenerateBookRow();
|
||||
}
|
||||
|
||||
void AShelfActor::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
void AShelfActor::GenerateBookRow()
|
||||
{
|
||||
for (auto Component : GetComponents())
|
||||
{
|
||||
if (UShelfComponent* ShelfComponent = Cast<UShelfComponent>(Component))
|
||||
{
|
||||
ShelfComponent->GenerateBookRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UInventory* AShelfActor::GetInventory_Implementation() const
|
||||
{
|
||||
return Inventory;
|
||||
}
|
||||
|
||||
47
Source/Faye/GameObjects/ShelfActor.h
Normal file
47
Source/Faye/GameObjects/ShelfActor.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NpcUsableActor.h"
|
||||
#include "Faye/Interfaces/InventoryInterface.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Interface/InteractableActorInterface.h"
|
||||
#include "ShelfActor.generated.h"
|
||||
|
||||
class UInteractionWidgetComponent;
|
||||
class ABookOnShelfActor;
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API AShelfActor : public ANpcUsableActor, public IInventoryInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
AShelfActor();
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
virtual UInventory* GetInventory_Implementation() const override;
|
||||
|
||||
/*--- INTERACTION START ---*/
|
||||
|
||||
virtual FText GetInteractionText_Implementation() const override { return NSLOCTEXT("Faye", "ShelfInteract", "Interact"); }
|
||||
|
||||
/*--- INTERACTION END ---*/
|
||||
|
||||
UFUNCTION(CallInEditor, BlueprintCallable)
|
||||
void GenerateBookRow();
|
||||
|
||||
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable)
|
||||
void PlaceBook();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ABookOnShelfActor* SelectedBook = nullptr;
|
||||
protected:
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
UInventory* Inventory;
|
||||
|
||||
};
|
||||
20
Source/Faye/GameObjects/TableActor.cpp
Normal file
20
Source/Faye/GameObjects/TableActor.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "TableActor.h"
|
||||
|
||||
ATableActor::ATableActor()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void ATableActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
}
|
||||
|
||||
void ATableActor::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
}
|
||||
|
||||
21
Source/Faye/GameObjects/TableActor.h
Normal file
21
Source/Faye/GameObjects/TableActor.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "NpcUsableActor.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "TableActor.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API ATableActor : public ANpcUsableActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ATableActor();
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
};
|
||||
54
Source/Faye/GameObjects/TimeOfDayActor.cpp
Normal file
54
Source/Faye/GameObjects/TimeOfDayActor.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "TimeOfDayActor.h"
|
||||
|
||||
#include "AsyncMessageSystemBase.h"
|
||||
#include "AsyncMessageWorldSubsystem.h"
|
||||
#include "DaySequenceActor.h"
|
||||
#include "Components/VolumetricCloudComponent.h"
|
||||
#include "Faye/System/FayeGameplayTags.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
ATimeOfDayActor::ATimeOfDayActor(const FObjectInitializer& Init)
|
||||
: Super(Init)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
VolumetricCloudComponent->SetVisibility(false);
|
||||
}
|
||||
|
||||
void ATimeOfDayActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
TimeDef.AddTime((24 + 8) * HOURS_TO_SECONDS);
|
||||
}
|
||||
|
||||
void ATimeOfDayActor::AddTime(float Seconds)
|
||||
{
|
||||
AccumulatedSeconds += (Seconds * RealTimeSpeed);
|
||||
if (AccumulatedSeconds >= 1.f)
|
||||
{
|
||||
int32 AccSecRounded = static_cast<int32>(AccumulatedSeconds);
|
||||
TimeDef.AddTime(AccSecRounded);
|
||||
AccumulatedSeconds -= static_cast<float>(AccSecRounded);
|
||||
}
|
||||
SetTimeOfDay(TimeDef.GetTimeOfDayInHours());
|
||||
|
||||
FTimeChangedPayload Payload;
|
||||
Payload.SecondsPassed = AccumulatedSeconds;
|
||||
OnTimeChanged.Broadcast(Payload);
|
||||
if (TSharedPtr<FAsyncMessageSystemBase> Sys = UAsyncMessageWorldSubsystem::GetSharedMessageSystem(GetWorld()))
|
||||
{
|
||||
Sys->QueueMessageForBroadcast(FAsyncMessageId(::Event::TimeOfDay::TimePassed), FConstStructView::Make(Payload));
|
||||
}
|
||||
}
|
||||
|
||||
void ATimeOfDayActor::Tick(float DeltaTime)
|
||||
{
|
||||
Super::Tick(DeltaTime);
|
||||
|
||||
if (bTimeActive && GetWorld() && GetWorld()->IsGameWorld())
|
||||
{
|
||||
AddTime(DeltaTime);
|
||||
}
|
||||
}
|
||||
57
Source/Faye/GameObjects/TimeOfDayActor.h
Normal file
57
Source/Faye/GameObjects/TimeOfDayActor.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Actors/SunMoonDaySequenceActor.h"
|
||||
#include "Faye/Structs/TimeOfDayDef.h"
|
||||
|
||||
#include "TimeOfDayActor.generated.h"
|
||||
|
||||
class ADaySequenceActor;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FTimeChangedPayload
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Time")
|
||||
float SecondsPassed = 0.f;
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTimeChanged, FTimeChangedPayload, Payload);
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API ATimeOfDayActor : public ASunMoonDaySequenceActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
// Real life second = how many in game seconds
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Time")
|
||||
float RealTimeSpeed = 10.f;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnTimeChanged OnTimeChanged;
|
||||
|
||||
ATimeOfDayActor(const FObjectInitializer& Init);
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
const FTimeOfDayDef& GetTime() const { return TimeDef; }
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Time")
|
||||
bool bTimeActive = true;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Time")
|
||||
FTimeOfDayDef TimeDef;
|
||||
|
||||
UPROPERTY()
|
||||
float AccumulatedSeconds = 0.f;
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
void AddTime(float Seconds);
|
||||
};
|
||||
7
Source/Faye/Interfaces/InventoryInterface.cpp
Normal file
7
Source/Faye/Interfaces/InventoryInterface.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "InventoryInterface.h"
|
||||
|
||||
|
||||
// Add default functionality here for any IInventoryInterface functions that are not pure virtual.
|
||||
28
Source/Faye/Interfaces/InventoryInterface.h
Normal file
28
Source/Faye/Interfaces/InventoryInterface.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Interface.h"
|
||||
#include "InventoryInterface.generated.h"
|
||||
|
||||
class UInventory;
|
||||
|
||||
UINTERFACE(BlueprintType)
|
||||
class UInventoryInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class FAYE_API IInventoryInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Inventory")
|
||||
UInventory* GetInventory() const;
|
||||
};
|
||||
18
Source/Faye/Inventory/BookItem.cpp
Normal file
18
Source/Faye/Inventory/BookItem.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "BookItem.h"
|
||||
|
||||
void UBookItem::SetupBook(const FBookDataStructRow& Row, int32 InID)
|
||||
{
|
||||
ItemCategory = EItemCategory::Book;
|
||||
ItemId = InID;
|
||||
ItemName = Row.ItemName;
|
||||
ItemDescription = Row.ItemDescription;
|
||||
BookCategory = Row.BookCategory;
|
||||
BookSubCategory = Row.BookSubCategory;
|
||||
Price = Row.Price;
|
||||
PublicationDate = Row.PublicationDate;
|
||||
Author = Row.Author;
|
||||
PageNumber = Row.PageNumber;
|
||||
}
|
||||
36
Source/Faye/Inventory/BookItem.h
Normal file
36
Source/Faye/Inventory/BookItem.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Item.h"
|
||||
#include "Faye/Structs/BookDataStruct.h"
|
||||
#include "BookItem.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UBookItem : public UItem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
void SetupBook(const FBookDataStructRow& Row, int32 InID);
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EBookCategory BookCategory = EBookCategory::NonFiction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EBookSubCategory BookSubCategory = EBookSubCategory::Biography;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PublicationDate = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText Author= FText();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PageNumber = 0;
|
||||
};
|
||||
4
Source/Faye/Inventory/CoffeeItem.cpp
Normal file
4
Source/Faye/Inventory/CoffeeItem.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "CoffeeItem.h"
|
||||
50
Source/Faye/Inventory/CoffeeItem.h
Normal file
50
Source/Faye/Inventory/CoffeeItem.h
Normal file
@@ -0,0 +1,50 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Item.h"
|
||||
#include "Faye/Enums/CoffeeTypes.h"
|
||||
#include "CoffeeItem.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FCoffeeItemTranslations
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TMap<ECoffeeType, FText> CoffeeTypeTranslations;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TMap<ECoffeeSize, FText> CoffeeSizeTranslations;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TMap<ECoffeeAddition, FText> CoffeeAdditionsTranslations;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UCoffeeItem : public UItem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ECoffeeType CoffeeType = ECoffeeType::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ECoffeeSize CoffeeSize = ECoffeeSize::Small;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
bool bIced = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ECoffeeAddition CoffeeAddition = ECoffeeAddition::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
bool bWhippedCream = false;
|
||||
|
||||
};
|
||||
119
Source/Faye/Inventory/Inventory.cpp
Normal file
119
Source/Faye/Inventory/Inventory.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Inventory.h"
|
||||
#include "Faye/Inventory/Item.h"
|
||||
#include "Faye/Data/Filters/ItemFilters.h"
|
||||
|
||||
void UInventory::AddItem(UItem* InItem, int32 Stack)
|
||||
{
|
||||
if (!InItem || Stack <= 0)
|
||||
return;
|
||||
|
||||
if (FItemStack* ItemStack = GetItemStack_Internal(InItem))
|
||||
{
|
||||
ItemStack->Stack += Stack;
|
||||
}
|
||||
else
|
||||
{
|
||||
FItemStack ItemStackNew;
|
||||
ItemStackNew.Stack = Stack;
|
||||
ItemStackNew.ItemPtr = InItem;
|
||||
ItemStacks.Add(ItemStackNew);
|
||||
}
|
||||
}
|
||||
|
||||
bool UInventory::RemoveItem(const UItem* InItem, int32 Stacks)
|
||||
{
|
||||
for (int32 i = 0; i < ItemStacks.Num(); ++i)
|
||||
{
|
||||
if (ItemStacks[i].ItemPtr == InItem)
|
||||
{
|
||||
if (Stacks == -1)
|
||||
{
|
||||
ItemStacks.RemoveAt(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemStacks[i].Stack -= Stacks;
|
||||
if (ItemStacks[i].Stack <= 0)
|
||||
{
|
||||
ItemStacks.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UInventory::GetItemStack(const UItem* Item, FItemStack& OutItemStack) const
|
||||
{
|
||||
if (!Item)
|
||||
return false;
|
||||
|
||||
for (const FItemStack& Stack : ItemStacks)
|
||||
{
|
||||
if (Stack.ItemPtr == Item)
|
||||
{
|
||||
OutItemStack = Stack;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TArray<UItem*> UInventory::FilterItems(UItemFilter* Filter) const
|
||||
{
|
||||
TArray<UItem*> FilteredItems;
|
||||
for (const FItemStack Stack : ItemStacks)
|
||||
{
|
||||
if (Filter->Pass(Stack.ItemPtr))
|
||||
FilteredItems.Add(Stack.ItemPtr);
|
||||
}
|
||||
return FilteredItems;
|
||||
}
|
||||
|
||||
int32 UInventory::CountStacksForItems(const TArray<UItem*>& Items) const
|
||||
{
|
||||
int32 Count = 0;
|
||||
for (const UItem* Item : Items)
|
||||
{
|
||||
FItemStack Stack;
|
||||
if (GetItemStack(Item, Stack))
|
||||
{
|
||||
Count += Stack.Stack;
|
||||
}
|
||||
}
|
||||
return Count;
|
||||
}
|
||||
|
||||
bool UInventory::ModifyGold(int32 Amount)
|
||||
{
|
||||
if (Amount < 0 && FMath::Abs(Amount) > Gold)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Gold += Amount;
|
||||
OnGoldChanged.Broadcast(Amount, Gold);
|
||||
return true;
|
||||
}
|
||||
|
||||
FItemStack* UInventory::GetItemStack_Internal(const UItem* Item)
|
||||
{
|
||||
if (!Item)
|
||||
return nullptr;
|
||||
|
||||
for (FItemStack& Stack : ItemStacks)
|
||||
{
|
||||
if (Stack.ItemPtr == Item)
|
||||
{
|
||||
return &Stack;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
74
Source/Faye/Inventory/Inventory.h
Normal file
74
Source/Faye/Inventory/Inventory.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "StructUtils/InstancedStruct.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "Inventory.generated.h"
|
||||
|
||||
class UItemFilter;
|
||||
struct FItemFilter;
|
||||
class UItem;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FItemStack
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 Stack = 1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
UItem* ItemPtr = nullptr;
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnGoldChanged, int32, ChangeAmount, int32, CurrentGold);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class FAYE_API UInventory : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Inventory")
|
||||
void AddItem(UItem* InItem, int32 Stack = 1);
|
||||
|
||||
// -1 to remove all
|
||||
UFUNCTION(BlueprintCallable, Category = "Inventory")
|
||||
bool RemoveItem(const UItem* InItem, int32 Stacks = -1);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Inventory")
|
||||
bool GetItemStack(const UItem* Item, FItemStack& OutItemStack) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Inventory")
|
||||
TArray<UItem*> FilterItems(UItemFilter* Filter) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Inventory")
|
||||
int32 CountStacksForItems(const TArray<UItem*>& Items) const;
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Inventory|Gold")
|
||||
bool ModifyGold(int32 Amount);
|
||||
UFUNCTION(BlueprintPure, Category = "Inventory|Gold")
|
||||
int32 GetGold() const { return Gold; }
|
||||
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnGoldChanged OnGoldChanged;
|
||||
|
||||
protected:
|
||||
|
||||
FItemStack* GetItemStack_Internal(const UItem* Item);
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FItemStack> ItemStacks;
|
||||
|
||||
UPROPERTY()
|
||||
int32 Gold = 0;
|
||||
|
||||
};
|
||||
5
Source/Faye/Inventory/Item.cpp
Normal file
5
Source/Faye/Inventory/Item.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Item.h"
|
||||
|
||||
34
Source/Faye/Inventory/Item.h
Normal file
34
Source/Faye/Inventory/Item.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "Faye/Structs/ItemDataStruct.h"
|
||||
|
||||
#include "Item.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class FAYE_API UItem : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
int32 ItemId = -1;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FText ItemName = FText();
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FText ItemDescription = FText();
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
EItemCategory ItemCategory = EItemCategory::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 Price = 0;
|
||||
};
|
||||
135
Source/Faye/Inventory/ItemDatabase.cpp
Normal file
135
Source/Faye/Inventory/ItemDatabase.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "ItemDatabase.h"
|
||||
|
||||
#include "Faye/Data/Filters/ItemFilters.h"
|
||||
#include "Faye/System/FayeDeveloperSettings.h"
|
||||
#include "Kismet/KismetStringLibrary.h"
|
||||
|
||||
void UItemDatabase::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
|
||||
Authors.Empty();
|
||||
if (const UFayeDeveloperSettings* Settings = GetDefault<UFayeDeveloperSettings>())
|
||||
{
|
||||
if (const UDataTable* DataTable = Cast<UDataTable>(Settings->BooksDataTable.LoadSynchronous()))
|
||||
{
|
||||
DataTable->ForeachRow<FBookDataStructRow>(TEXT(""), [&](const FName& RowName, const FBookDataStructRow& Row)
|
||||
{
|
||||
if (!Row.ItemName.IsEmpty())
|
||||
{
|
||||
UBookItem* BookItem = NewObject<UBookItem>(this);
|
||||
int32 ID = UKismetStringLibrary::Conv_StringToInt(RowName.ToString());
|
||||
BookItem->SetupBook(Row, ID);
|
||||
check(!LoadedBooksMap.Contains(BookItem->ItemId));
|
||||
LoadedBooksMap.Add(BookItem->ItemId, BookItem);
|
||||
|
||||
if (FBookCategoryMap* MapEntry = BooksByCategoryMap.Find(BookItem->BookCategory))
|
||||
{
|
||||
MapEntry->Books.Add(BookItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
FBookCategoryMap NewMapEntry;
|
||||
NewMapEntry.Books.Add(BookItem);
|
||||
BooksByCategoryMap.Add(BookItem->BookCategory, NewMapEntry);
|
||||
}
|
||||
Authors.Add(BookItem->Author);
|
||||
AllBooks.Add(BookItem);
|
||||
if (BookItem->PublicationDate <= EarliestPublicationDate)
|
||||
{
|
||||
EarliestPublicationDate = BookItem->PublicationDate;
|
||||
}
|
||||
if (BookItem->PublicationDate >= LatestPublicationDate)
|
||||
{
|
||||
LatestPublicationDate = BookItem->PublicationDate;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UItemDatabase* UItemDatabase::Get(const UObject* WorldContext)
|
||||
{
|
||||
if (!WorldContext || !WorldContext->GetWorld())
|
||||
return nullptr;
|
||||
|
||||
return WorldContext->GetWorld()->GetGameInstance()->GetSubsystem<UItemDatabase>();
|
||||
}
|
||||
|
||||
UBookItem* UItemDatabase::GetBook(const UObject* WorldContext, int32 Id)
|
||||
{
|
||||
if (!WorldContext || !WorldContext->GetWorld() || Id <= -1)
|
||||
return nullptr;
|
||||
|
||||
if (UItemDatabase* ItemDb = WorldContext->GetWorld()->GetGameInstance()->GetSubsystem<UItemDatabase>())
|
||||
{
|
||||
if (ItemDb->LoadedBooksMap.Contains(Id))
|
||||
{
|
||||
return ItemDb->LoadedBooksMap[Id];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TArray<UBookItem*> UItemDatabase::GetBooksFromCategory(const UObject* WorldContext, EBookCategory Category)
|
||||
{
|
||||
TArray<UBookItem*> GatheredBooks;
|
||||
if (!WorldContext || !WorldContext->GetWorld() || Category == EBookCategory::None)
|
||||
return GatheredBooks;
|
||||
|
||||
if (UItemDatabase* ItemDb = WorldContext->GetWorld()->GetGameInstance()->GetSubsystem<UItemDatabase>())
|
||||
{
|
||||
if (const FBookCategoryMap* MapEntry = ItemDb->BooksByCategoryMap.Find(Category))
|
||||
{
|
||||
return MapEntry->Books;
|
||||
}
|
||||
}
|
||||
return GatheredBooks;
|
||||
}
|
||||
|
||||
TArray<FText> UItemDatabase::GetAuthorList(const UObject* WorldContext)
|
||||
{
|
||||
if (!WorldContext || !WorldContext->GetWorld())
|
||||
return TArray<FText>();
|
||||
|
||||
if (UItemDatabase* ItemDb = WorldContext->GetWorld()->GetGameInstance()->GetSubsystem<UItemDatabase>())
|
||||
{
|
||||
return ItemDb->Authors;
|
||||
}
|
||||
|
||||
return TArray<FText>();
|
||||
}
|
||||
|
||||
TArray<UItem*> UItemDatabase::FilterItems(const UObject* WorldContext, const UItemFilter* Filter)
|
||||
{
|
||||
TArray<UItem*> Temp;
|
||||
if (!WorldContext || !WorldContext->GetWorld())
|
||||
return Temp;
|
||||
|
||||
if (UItemDatabase* ItemDb = WorldContext->GetWorld()->GetGameInstance()->GetSubsystem<UItemDatabase>())
|
||||
{
|
||||
Temp = ItemDb->AllBooks;
|
||||
FilterItemArray(Filter, Temp);
|
||||
}
|
||||
|
||||
return Temp;
|
||||
}
|
||||
|
||||
void UItemDatabase::FilterItemArray(const UItemFilter* Filter, TArray<UItem*>& ItemList)
|
||||
{
|
||||
for (auto It = ItemList.CreateIterator(); It; ++It)
|
||||
{
|
||||
if (!Filter->Pass(*It))
|
||||
It.RemoveCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
const TArray<UItem*>& UItemDatabase::GetAllBooks(const UObject* WorldContext)
|
||||
{
|
||||
return Get(WorldContext)->AllBooks;
|
||||
}
|
||||
|
||||
68
Source/Faye/Inventory/ItemDatabase.h
Normal file
68
Source/Faye/Inventory/ItemDatabase.h
Normal file
@@ -0,0 +1,68 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "Faye/Inventory/BookItem.h"
|
||||
#include "ItemDatabase.generated.h"
|
||||
|
||||
class UItemFilter;
|
||||
|
||||
USTRUCT()
|
||||
struct FBookCategoryMap
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
TArray<UBookItem*> Books;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UItemDatabase : public UGameInstanceSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
|
||||
static UItemDatabase* Get(const UObject* WorldContext);
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintPure, meta=(WorldContext="WorldContext"))
|
||||
static UBookItem* GetBook(const UObject* WorldContext, int32 Id);
|
||||
|
||||
UFUNCTION(BlueprintPure, meta=(WorldContext="WorldContext"))
|
||||
static TArray<UBookItem*> GetBooksFromCategory(const UObject* WorldContext, EBookCategory Category);
|
||||
|
||||
static TArray<FText> GetAuthorList(const UObject* WorldContext);
|
||||
|
||||
static TArray<UItem*> FilterItems(const UObject* WorldContext, const UItemFilter* Filter);
|
||||
static void FilterItemArray(const UItemFilter* Filter, TArray<UItem*>& ItemList);
|
||||
|
||||
static const TArray<UItem*>& GetAllBooks(const UObject* WorldContext);
|
||||
|
||||
int32 GetEarliestPublicationDate() const { return EarliestPublicationDate; }
|
||||
int32 GetLatestPublicationDate() const { return LatestPublicationDate; }
|
||||
protected:
|
||||
|
||||
UPROPERTY()
|
||||
TMap<int32, UBookItem*> LoadedBooksMap;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<UItem*> AllBooks;
|
||||
|
||||
UPROPERTY()
|
||||
TMap<EBookCategory, FBookCategoryMap> BooksByCategoryMap;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FText> Authors;
|
||||
|
||||
UPROPERTY()
|
||||
int32 EarliestPublicationDate = 0;
|
||||
UPROPERTY()
|
||||
int32 LatestPublicationDate = 0;
|
||||
};
|
||||
1
Source/Faye/Structs/BookDataStruct.cpp
Normal file
1
Source/Faye/Structs/BookDataStruct.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "BookDataStruct.h"
|
||||
78
Source/Faye/Structs/BookDataStruct.h
Normal file
78
Source/Faye/Structs/BookDataStruct.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DataTable.h"
|
||||
#include "ItemDataStruct.h"
|
||||
#include "BookDataStruct.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EBookCategory : uint8
|
||||
{
|
||||
None,
|
||||
NonFiction,
|
||||
SpeculativeFiction,
|
||||
MysteryAndCrime,
|
||||
Fiction,
|
||||
ClassicsAndArt,
|
||||
VisualNovel,
|
||||
ChildrenAndYoungAdult
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EBookSubCategory : uint8
|
||||
{
|
||||
None,
|
||||
Biography,
|
||||
ArtAndPhilosophy,
|
||||
SelfHelp,
|
||||
ScienceAndBusiness,
|
||||
Fantasy,
|
||||
SciFi,
|
||||
Horror,
|
||||
Crime,
|
||||
Thriller,
|
||||
TrueCrime,
|
||||
Experimental,
|
||||
HistoricalFiction,
|
||||
Romance,
|
||||
Contemporary,
|
||||
Classic,
|
||||
Poetry,
|
||||
Drama,
|
||||
GraphicNovels,
|
||||
Manga,
|
||||
Comic,
|
||||
PictureBook,
|
||||
YoungAdult
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FBookDataStructRow : public FTableRowBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText ItemName = FText::GetEmpty();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText ItemDescription= FText::GetEmpty();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EBookCategory BookCategory = EBookCategory::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EBookSubCategory BookSubCategory = EBookSubCategory::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 Price = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PublicationDate = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText Author= FText::GetEmpty();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
int32 PageNumber = 0;
|
||||
};
|
||||
1
Source/Faye/Structs/CommonStructs.cpp
Normal file
1
Source/Faye/Structs/CommonStructs.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "CommonStructs.h"
|
||||
12
Source/Faye/Structs/CommonStructs.h
Normal file
12
Source/Faye/Structs/CommonStructs.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "CommonStructs.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct FObjectContainer
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
TArray<UObject*> Objects;
|
||||
};
|
||||
1
Source/Faye/Structs/ItemDataStruct.cpp
Normal file
1
Source/Faye/Structs/ItemDataStruct.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "ItemDataStruct.h"
|
||||
33
Source/Faye/Structs/ItemDataStruct.h
Normal file
33
Source/Faye/Structs/ItemDataStruct.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DataTable.h"
|
||||
#include "ItemDataStruct.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EItemCategory : uint8
|
||||
{
|
||||
None,
|
||||
Book,
|
||||
MAX UMETA(Hidden)
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FItemDataStruct : public FTableRowBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
int32 ItemId = 0;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FText ItemName = FText();
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FText ItemDescription= FText();
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
EItemCategory ItemCategory = EItemCategory::None;
|
||||
};
|
||||
|
||||
41
Source/Faye/Structs/TimeOfDayDef.cpp
Normal file
41
Source/Faye/Structs/TimeOfDayDef.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "TimeOfDayDef.h"
|
||||
|
||||
void FTimeOfDayDef::AddTime(int32 InSeconds)
|
||||
{
|
||||
int32 days = InSeconds / DAYS_TO_SECONDS;
|
||||
InSeconds %= DAYS_TO_SECONDS;
|
||||
|
||||
int32 hours = InSeconds / HOURS_TO_SECONDS;
|
||||
InSeconds %= HOURS_TO_SECONDS;
|
||||
|
||||
int32 minutes = InSeconds / MINUTES_TO_SECONDS;
|
||||
InSeconds %= MINUTES_TO_SECONDS;
|
||||
|
||||
Days += days;
|
||||
Hours += hours;
|
||||
Minutes += minutes;
|
||||
Seconds += InSeconds;
|
||||
|
||||
if (Seconds >= 60)
|
||||
{
|
||||
Minutes += Seconds / MINUTES_TO_SECONDS;
|
||||
Seconds %= MINUTES_TO_SECONDS;
|
||||
}
|
||||
if (Minutes >= 60)
|
||||
{
|
||||
Hours += Minutes / 60;
|
||||
Minutes %= 60;
|
||||
}
|
||||
if (Hours >= 24)
|
||||
{
|
||||
Days += Hours / 24;
|
||||
Hours %= 24;
|
||||
}
|
||||
uint8 DaysEnum = static_cast<uint8>(Days % 7) + 1;
|
||||
Weekday = static_cast<EWeekday>(DaysEnum);
|
||||
}
|
||||
|
||||
float FTimeOfDayDef::GetTimeOfDayInHours() const
|
||||
{
|
||||
return Hours + (Minutes / 60.f) + (Seconds / 3600.f);
|
||||
}
|
||||
50
Source/Faye/Structs/TimeOfDayDef.h
Normal file
50
Source/Faye/Structs/TimeOfDayDef.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "TimeOfDayDef.generated.h"
|
||||
|
||||
static constexpr int32 DAYS_TO_SECONDS = 86400;
|
||||
static constexpr int32 HOURS_TO_SECONDS = 3600;
|
||||
static constexpr int32 MINUTES_TO_SECONDS = 60;
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EWeekday: uint8
|
||||
{
|
||||
None = 0 UMETA(Hidden),
|
||||
Monday = 1,
|
||||
Tuesday = 2,
|
||||
Wednesday = 3,
|
||||
Thursday = 4,
|
||||
Friday = 5,
|
||||
Saturday = 6,
|
||||
Sunday = 7,
|
||||
MAX UMETA(Hidden)
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FAYE_API FTimeOfDayDef
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Adds seconds
|
||||
void AddTime(int32 InSeconds);
|
||||
int32 GetSeconds() const { return Seconds; }
|
||||
int32 GetMinutes() const { return Minutes; }
|
||||
int32 GetHours() const { return Hours; }
|
||||
int32 GetDays() const { return Days; }
|
||||
EWeekday GetWeekday() const { return Weekday; }
|
||||
|
||||
float GetTimeOfDayInHours() const;
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Time Of Day")
|
||||
int32 Seconds = 0;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Time Of Day")
|
||||
int32 Minutes = 0;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Time Of Day")
|
||||
int32 Hours = 0;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Time Of Day")
|
||||
int32 Days = 0;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Time Of Day")
|
||||
EWeekday Weekday = EWeekday::Monday;
|
||||
};
|
||||
9
Source/Faye/System/FayeDeveloperSettings.cpp
Normal file
9
Source/Faye/System/FayeDeveloperSettings.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "FayeDeveloperSettings.h"
|
||||
|
||||
const TMap<EBookCategory, FLinearColor>& UFayeDeveloperSettings::GetBookCategoryColorMap()
|
||||
{
|
||||
return GetDefault<UFayeDeveloperSettings>()->BookCategoryColorMap;
|
||||
}
|
||||
103
Source/Faye/System/FayeDeveloperSettings.h
Normal file
103
Source/Faye/System/FayeDeveloperSettings.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/DeveloperSettings.h"
|
||||
#include "Engine/StaticMeshActor.h"
|
||||
#include "Faye/Data/OrderSettingsDataAsset.h"
|
||||
#include "Faye/Inventory/CoffeeItem.h"
|
||||
#include "FayeDeveloperSettings.generated.h"
|
||||
|
||||
class USUDSScript;
|
||||
class UShopListDataAsset;
|
||||
enum class EBookCategory : uint8;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FBookShelfVariation
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "BookShelf")
|
||||
TArray<TSoftObjectPtr<UStaticMesh>> StaticMeshVariations;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "BookShelf")
|
||||
float BookWidth = 0.f;
|
||||
|
||||
};
|
||||
|
||||
UENUM(BlueprintType, meta = (BitFlags))
|
||||
enum class EBookFilterFlags : uint8
|
||||
{
|
||||
Author,
|
||||
PublicationYear,
|
||||
BookCategory,
|
||||
BookSubcategory,
|
||||
PageNumber
|
||||
};
|
||||
ENUM_CLASS_FLAGS(EBookFilterFlags)
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FBookFilterFlagsSet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Flags", meta = (Bitmask, BitmaskEnum = "/Script/Faye.EBookFilterFlags"))
|
||||
int32 Flags = 0;
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EPageNumberCategorisation : uint8
|
||||
{
|
||||
Short,
|
||||
Medium,
|
||||
Long
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Config = Game, defaultconfig, meta = (DisplayName = "Faye Settings"))
|
||||
class FAYE_API UFayeDeveloperSettings : public UDeveloperSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Books")
|
||||
TMap<EBookCategory, FLinearColor> BookCategoryColorMap;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Items")
|
||||
TSoftObjectPtr<UDataTable> BooksDataTable;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Items")
|
||||
TSoftObjectPtr<UShopListDataAsset> ShopListDataAsset;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Coffee")
|
||||
TSoftObjectPtr<UOrderSettingsDataAsset> GenericCoffeeOrderSettingsAsset;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Coffee")
|
||||
FCoffeeItemTranslations CoffeeTranslations;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Shelves")
|
||||
TMap<int32, FBookShelfVariation> BookShelfVariations;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Shelves")
|
||||
TSoftObjectPtr<UMaterialInterface> TransparentBookMaterial;
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Shelves")
|
||||
TSoftObjectPtr<UMaterialInterface> TransparentBookMaterial_Highlighted;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Shelves")
|
||||
TSubclassOf<AStaticMeshActor> DefaultBookStaticMeshClass;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Faye Settings")
|
||||
TArray<FBookFilterFlagsSet> BookFilterVariations;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Faye Settings")
|
||||
TMap<EPageNumberCategorisation, int32> BookLengthLimits;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Faye Settings")
|
||||
static const TMap<EBookCategory, FLinearColor>& GetBookCategoryColorMap();
|
||||
|
||||
const UOrderSettingsDataAsset* GetOrderSettingDataAsset() const { return GenericCoffeeOrderSettingsAsset.LoadSynchronous(); }
|
||||
};
|
||||
4
Source/Faye/System/FayeFunctionLibrary.cpp
Normal file
4
Source/Faye/System/FayeFunctionLibrary.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "FayeFunctionLibrary.h"
|
||||
39
Source/Faye/System/FayeFunctionLibrary.h
Normal file
39
Source/Faye/System/FayeFunctionLibrary.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "Faye/GameObjects/TimeOfDayActor.h"
|
||||
|
||||
#include "FayeFunctionLibrary.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UFayeFunctionLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Time Of Day")
|
||||
static void AddTime(FTimeOfDayDef& TimeOfDayDef, int32 InSeconds) { TimeOfDayDef.AddTime(InSeconds); }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Time Of Day")
|
||||
static int32 SecondsFromMinutes(int32 Minutes) { return Minutes * MINUTES_TO_SECONDS; }
|
||||
UFUNCTION(BlueprintPure, Category = "Time Of Day")
|
||||
static int32 SecondsFromHours(int32 Hours) { return Hours * HOURS_TO_SECONDS; }
|
||||
UFUNCTION(BlueprintPure, Category = "Time Of Day")
|
||||
static int32 SecondsFromDays(int32 Days) { return Days * DAYS_TO_SECONDS; }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Time Of Day")
|
||||
static int32 GetSeconds(const FTimeOfDayDef& TimeOfDayDef) { return TimeOfDayDef.GetSeconds(); }
|
||||
UFUNCTION(BlueprintPure, Category = "Time Of Day")
|
||||
static int32 GetMinutes(const FTimeOfDayDef& TimeOfDayDef) { return TimeOfDayDef.GetMinutes(); }
|
||||
UFUNCTION(BlueprintPure, Category = "Time Of Day")
|
||||
static int32 GetHours(const FTimeOfDayDef& TimeOfDayDef) { return TimeOfDayDef.GetHours(); }
|
||||
UFUNCTION(BlueprintPure, Category = "Time Of Day")
|
||||
static int32 GetDays(const FTimeOfDayDef& TimeOfDayDef) { return TimeOfDayDef.GetDays(); }
|
||||
UFUNCTION(BlueprintPure, Category = "Time Of Day")
|
||||
static EWeekday GetWeekday(const FTimeOfDayDef& TimeOfDayDef) { return TimeOfDayDef.GetWeekday(); }
|
||||
};
|
||||
9
Source/Faye/System/FayeGameplayTags.cpp
Normal file
9
Source/Faye/System/FayeGameplayTags.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "FayeGameplayTags.h"
|
||||
|
||||
namespace Event
|
||||
{
|
||||
namespace TimeOfDay
|
||||
{
|
||||
UE_DEFINE_GAMEPLAY_TAG(TimePassed, TEXT("Event.TimeOfDay.TimePassed"))
|
||||
}
|
||||
}
|
||||
11
Source/Faye/System/FayeGameplayTags.h
Normal file
11
Source/Faye/System/FayeGameplayTags.h
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
#pragma once
|
||||
#include "NativeGameplayTags.h"
|
||||
|
||||
namespace Event
|
||||
{
|
||||
namespace TimeOfDay
|
||||
{
|
||||
FAYE_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TimePassed)
|
||||
}
|
||||
}
|
||||
61
Source/Faye/System/OrderTranslationManager.cpp
Normal file
61
Source/Faye/System/OrderTranslationManager.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
#include "OrderTranslationManager.h"
|
||||
|
||||
#include "FayeDeveloperSettings.h"
|
||||
#include "SUDSDialogue.h"
|
||||
#include "SUDSLibrary.h"
|
||||
#include "Faye/Data/OrderSettingsDataAsset.h"
|
||||
#include "Faye/Data/Filters/ItemFilters.h"
|
||||
#include "Faye/GameObjects/NpcPawn.h"
|
||||
|
||||
USUDSDialogue* UOrderTranslationManager::GetCoffeeOrderDialogue(UCoffeeFilter* InFilter, ANpcPawn* Npc)
|
||||
{
|
||||
if (!InFilter ||!Npc) return nullptr;
|
||||
|
||||
const UFayeDeveloperSettings* DeveloperSettings = GetDefault<UFayeDeveloperSettings>();
|
||||
auto ToFlag = [](ECoffeeFilterFlags Flag) -> uint8
|
||||
{
|
||||
return 1 << static_cast<uint8>(Flag);
|
||||
};
|
||||
|
||||
uint8 ChosenFlag = ToFlag(ECoffeeFilterFlags::SizeAndType);
|
||||
|
||||
if (InFilter->bIced)
|
||||
{
|
||||
ChosenFlag |= ToFlag(ECoffeeFilterFlags::Iced);
|
||||
}
|
||||
|
||||
if (InFilter->CoffeeAddition != ECoffeeAddition::None)
|
||||
{
|
||||
ChosenFlag |= ToFlag(ECoffeeFilterFlags::CoffeeAddition);
|
||||
}
|
||||
|
||||
if (InFilter->bWhippedCream)
|
||||
{
|
||||
ChosenFlag |= ToFlag(ECoffeeFilterFlags::WhippedCream);
|
||||
}
|
||||
|
||||
const UOrderSettingsDataAsset* DataAsset = Npc->GetCustomOrderSettings()? Npc->GetCustomOrderSettings() : DeveloperSettings->GetOrderSettingDataAsset();
|
||||
const FCoffeeFilterFlagsSet* CoffeeFlagSet = DataAsset->FilterSettings.FindByPredicate([ChosenFlag](const FCoffeeFilterFlagsSet& FlagSet)
|
||||
{
|
||||
return FlagSet.Flags == ChosenFlag;
|
||||
});
|
||||
ensure(CoffeeFlagSet);
|
||||
|
||||
USUDSScript* ChosenScript = CoffeeFlagSet->ScriptsArray[FMath::RandRange(0, CoffeeFlagSet->ScriptsArray.Num() - 1)];
|
||||
ensure(ChosenScript);
|
||||
|
||||
USUDSDialogue* Dialogue = USUDSLibrary::CreateDialogueWithParticipant(Npc, ChosenScript, Npc, true);
|
||||
ensure(Dialogue);
|
||||
|
||||
const FText* CoffeeTypeText = DeveloperSettings->CoffeeTranslations.CoffeeTypeTranslations.Find(InFilter->CoffeeType);
|
||||
ensure(CoffeeTypeText);
|
||||
|
||||
const FText* CoffeeSizeText = DeveloperSettings->CoffeeTranslations.CoffeeSizeTranslations.Find(InFilter->CoffeeSize);
|
||||
ensure(CoffeeSizeText);
|
||||
|
||||
Dialogue->SetVariableText("CoffeeType", *CoffeeTypeText);
|
||||
Dialogue->SetVariableText("CoffeeSize", *CoffeeSizeText);
|
||||
|
||||
return Dialogue;
|
||||
}
|
||||
19
Source/Faye/System/OrderTranslationManager.h
Normal file
19
Source/Faye/System/OrderTranslationManager.h
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "OrderTranslationManager.generated.h"
|
||||
|
||||
class ANpcPawn;
|
||||
class UCoffeeFilter;
|
||||
class USUDSDialogue;
|
||||
|
||||
UCLASS()
|
||||
class FAYE_API UOrderTranslationManager : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Translation Manger")
|
||||
static USUDSDialogue* GetCoffeeOrderDialogue(UCoffeeFilter* InFilter, ANpcPawn* Npc);
|
||||
|
||||
};
|
||||
128
Source/Faye/UI/Controller/PhoneWidgetController.cpp
Normal file
128
Source/Faye/UI/Controller/PhoneWidgetController.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "PhoneWidgetController.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Faye/GameObjects/TimeOfDayActor.h"
|
||||
#include "Faye/Interfaces/InventoryInterface.h"
|
||||
#include "Faye/Inventory/BookItem.h"
|
||||
#include "Faye/Inventory/Inventory.h"
|
||||
#include "Faye/Inventory/Item.h"
|
||||
#include "Faye/Inventory/ItemDatabase.h"
|
||||
#include "Faye/Structs/BookDataStruct.h"
|
||||
#include "Faye/System/FayeDeveloperSettings.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
void UPhoneWidgetController::InitializeController_Implementation()
|
||||
{
|
||||
Super::InitializeController_Implementation();
|
||||
|
||||
TimeOfDayActor = Cast<ATimeOfDayActor>(UGameplayStatics::GetActorOfClass(GetWorld(), ATimeOfDayActor::StaticClass()));
|
||||
TimeOfDayActor->OnTimeChanged.AddUniqueDynamic(this, &UPhoneWidgetController::OnTimeChanged);
|
||||
LastDayChecked = -1;
|
||||
|
||||
const UFayeDeveloperSettings* DeveloperSettings = GetDefault<UFayeDeveloperSettings>();
|
||||
check(DeveloperSettings);
|
||||
ShopItemsData = DeveloperSettings->ShopListDataAsset.LoadSynchronous();
|
||||
|
||||
GenerateShop();
|
||||
}
|
||||
|
||||
bool UPhoneWidgetController::PurchaseSlot(int32 slotIndex)
|
||||
{
|
||||
if (slotIndex < 0 || slotIndex > ItemsForSale.Num() - 1)
|
||||
return false;
|
||||
|
||||
if (UInventory* Inventory = IInventoryInterface::Execute_GetInventory(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0)))
|
||||
{
|
||||
if (Inventory->ModifyGold(-ItemsForSale[slotIndex]->ItemSaleRowData.BaseCost))
|
||||
{
|
||||
ItemsForSale[slotIndex]->bSold = true;
|
||||
TArray<UItem*> Drops = GetBookDropsForSlot(ItemsForSale[slotIndex]);
|
||||
for (UItem* Drop : Drops)
|
||||
{
|
||||
Inventory->AddItem(Drop, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UPhoneWidgetController::OnTimeChanged(FTimeChangedPayload TimeChangedPayload)
|
||||
{
|
||||
// Refresh shop
|
||||
if (TimeOfDayActor->GetTime().GetDays() != LastDayChecked)
|
||||
{
|
||||
GenerateShop();
|
||||
}
|
||||
}
|
||||
|
||||
void UPhoneWidgetController::GenerateShop()
|
||||
{
|
||||
ItemsForSale.Empty();
|
||||
LastDayChecked = TimeOfDayActor->GetTime().GetDays();
|
||||
|
||||
for (int32 i = 0; i < 8; i++)
|
||||
{
|
||||
int32 RandIndex = FMath::RandRange(0, ShopItemsData->SalesItemsList.Num() - 1);
|
||||
UItemSaleSlot* SlotObject = NewObject<UItemSaleSlot>();
|
||||
SlotObject->ItemSaleRowData = ShopItemsData->SalesItemsList[RandIndex];
|
||||
|
||||
ItemsForSale.Add(SlotObject);
|
||||
}
|
||||
}
|
||||
|
||||
TArray<UItem*> UPhoneWidgetController::GetBookDropsForSlot(const UItemSaleSlot* Slot) const
|
||||
{
|
||||
TArray<UItem*> Drops;
|
||||
for (int32 i = 0; i < Slot->ItemSaleRowData.DropAmount; i++)
|
||||
{
|
||||
EBookCategory ChosenCategory = GetWeightedCategory(Slot->ItemSaleRowData.CategoryDropWeight);
|
||||
TArray<UBookItem*> BooksFromCategory = UItemDatabase::GetBooksFromCategory(GetWorld(), ChosenCategory);
|
||||
if (!BooksFromCategory.IsEmpty())
|
||||
{
|
||||
int32 RandIndex = FMath::RandRange(0, BooksFromCategory.Num() - 1);
|
||||
Drops.Add(BooksFromCategory[RandIndex]);
|
||||
}
|
||||
}
|
||||
return Drops;
|
||||
}
|
||||
|
||||
EBookCategory UPhoneWidgetController::GetWeightedCategory(const TMap<EBookCategory, int32>& Weights)
|
||||
{
|
||||
int32 TotalWeight = 0;
|
||||
|
||||
for (const TPair<EBookCategory, int32>& Pair : Weights)
|
||||
{
|
||||
if (Pair.Value > 0)
|
||||
{
|
||||
TotalWeight += Pair.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
if (TotalWeight <= 0)
|
||||
{
|
||||
return EBookCategory::None;
|
||||
}
|
||||
|
||||
int32 RandomValue = FMath::RandRange(1, TotalWeight);
|
||||
int32 RunningWeight = 0;
|
||||
for (const TPair<EBookCategory, int32>& Pair : Weights)
|
||||
{
|
||||
if (Pair.Value <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RunningWeight += Pair.Value;
|
||||
|
||||
if (RandomValue <= RunningWeight)
|
||||
{
|
||||
return Pair.Key;
|
||||
}
|
||||
}
|
||||
return EBookCategory::None;
|
||||
}
|
||||
60
Source/Faye/UI/Controller/PhoneWidgetController.h
Normal file
60
Source/Faye/UI/Controller/PhoneWidgetController.h
Normal file
@@ -0,0 +1,60 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WidgetControllerBase.h"
|
||||
#include "Faye/Data/ShopListDataAsset.h"
|
||||
#include "PhoneWidgetController.generated.h"
|
||||
|
||||
struct FTimeChangedPayload;
|
||||
class UItem;
|
||||
class ATimeOfDayActor;
|
||||
|
||||
UCLASS(BlueprintType)
|
||||
class FAYE_API UItemSaleSlot: public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FItemSaleDataStruct ItemSaleRowData;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
bool bSold = false;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UPhoneWidgetController : public UWidgetControllerBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
virtual void InitializeController_Implementation() override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Faye Widget Controller")
|
||||
TArray<UItemSaleSlot*> GetItemsForSale() const { return ItemsForSale; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Faye Widget Controller")
|
||||
bool PurchaseSlot(int32 slotIndex);
|
||||
|
||||
protected:
|
||||
|
||||
UFUNCTION()
|
||||
void OnTimeChanged(FTimeChangedPayload TimeChangedPayload);
|
||||
|
||||
void GenerateShop();
|
||||
TArray<UItem*> GetBookDropsForSlot(const UItemSaleSlot* Slot) const;
|
||||
static EBookCategory GetWeightedCategory(const TMap<EBookCategory, int32>& Weights);
|
||||
|
||||
UPROPERTY()
|
||||
ATimeOfDayActor* TimeOfDayActor = nullptr;
|
||||
int32 LastDayChecked = -1;
|
||||
|
||||
UPROPERTY()
|
||||
UShopListDataAsset* ShopItemsData = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<UItemSaleSlot*> ItemsForSale;
|
||||
};
|
||||
41
Source/Faye/UI/Controller/ShelvesStackingController.cpp
Normal file
41
Source/Faye/UI/Controller/ShelvesStackingController.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "ShelvesStackingController.h"
|
||||
|
||||
#include "Faye/Interfaces/InventoryInterface.h"
|
||||
#include "Faye/Inventory/BookItem.h"
|
||||
#include "Faye/Inventory/Inventory.h"
|
||||
#include "Faye/Data/Filters/ItemFilters.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Faye/GameObjects/ShelfActor.h"
|
||||
|
||||
UBookItem* UShelvesStackingController::PlaceBookIntoShelf()
|
||||
{
|
||||
FShelvesStackingSetupPayload MutablePayload = Payload.GetMutable<FShelvesStackingSetupPayload>();
|
||||
if (!MutablePayload.ShelfActorRef)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UInventory* PlayerInventory = IInventoryInterface::Execute_GetInventory(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
|
||||
check(PlayerInventory);
|
||||
|
||||
UBookFilter* BookFilter = NewObject<UBookFilter>(this);
|
||||
BookFilter->BookCategory = SelectedCategory;
|
||||
TArray<UItem*> FilteredBooks = PlayerInventory->FilterItems(BookFilter);
|
||||
if (FilteredBooks.IsEmpty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
int32 RandIndex = FMath::RandRange(0, FilteredBooks.Num() - 1);
|
||||
UBookItem* SelectedBook = Cast<UBookItem>(FilteredBooks[RandIndex]);
|
||||
PlayerInventory->RemoveItem(SelectedBook, 1);
|
||||
|
||||
UInventory* ShelfInventory = IInventoryInterface::Execute_GetInventory(MutablePayload.ShelfActorRef);
|
||||
check(ShelfInventory);
|
||||
|
||||
ShelfInventory->AddItem(SelectedBook, 1);
|
||||
return SelectedBook;
|
||||
}
|
||||
39
Source/Faye/UI/Controller/ShelvesStackingController.h
Normal file
39
Source/Faye/UI/Controller/ShelvesStackingController.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WidgetControllerBase.h"
|
||||
#include "ShelvesStackingController.generated.h"
|
||||
|
||||
enum class EBookCategory : uint8;
|
||||
class UBookItem;
|
||||
class AShelfActor;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FShelvesStackingSetupPayload
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FShelvesStackingSetupPayload() = default;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TObjectPtr<AShelfActor> ShelfActorRef = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UShelvesStackingController : public UWidgetControllerBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
UBookItem* PlaceBookIntoShelf();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EBookCategory SelectedCategory;
|
||||
};
|
||||
16
Source/Faye/UI/Controller/WidgetControllerBase.cpp
Normal file
16
Source/Faye/UI/Controller/WidgetControllerBase.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "WidgetControllerBase.h"
|
||||
|
||||
void UWidgetControllerBase::InitializeController_Implementation()
|
||||
{
|
||||
}
|
||||
|
||||
void UWidgetControllerBase::PassPayload(const FInstancedStruct& DataPayload)
|
||||
{
|
||||
if (DataPayload.IsValid())
|
||||
{
|
||||
Payload = DataPayload;
|
||||
}
|
||||
}
|
||||
27
Source/Faye/UI/Controller/WidgetControllerBase.h
Normal file
27
Source/Faye/UI/Controller/WidgetControllerBase.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "StructUtils/InstancedStruct.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "WidgetControllerBase.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable)
|
||||
class FAYE_API UWidgetControllerBase : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, EditAnywhere)
|
||||
FInstancedStruct Payload;
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent)
|
||||
void InitializeController();
|
||||
virtual void InitializeController_Implementation();
|
||||
|
||||
void PassPayload(const FInstancedStruct& DataPayload);
|
||||
};
|
||||
5
Source/Faye/UI/DialogueWidget.cpp
Normal file
5
Source/Faye/UI/DialogueWidget.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "DialogueWidget.h"
|
||||
|
||||
35
Source/Faye/UI/DialogueWidget.h
Normal file
35
Source/Faye/UI/DialogueWidget.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "FayeBaseWidget.h"
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "DialogueWidget.generated.h"
|
||||
|
||||
class USUDSDialogue;
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FDialogueWidgetPayload
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FDialogueWidgetPayload() {}
|
||||
FDialogueWidgetPayload(USUDSDialogue* InDialogueObject)
|
||||
: DialogueObject(InDialogueObject) {}
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TObjectPtr<USUDSDialogue> DialogueObject = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UDialogueWidget : public UFayeBaseWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
73
Source/Faye/UI/FayeBaseWidget.cpp
Normal file
73
Source/Faye/UI/FayeBaseWidget.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "FayeBaseWidget.h"
|
||||
|
||||
#include "Controller/WidgetControllerBase.h"
|
||||
|
||||
UFayeBaseWidget::UFayeBaseWidget()
|
||||
{
|
||||
bIsBackHandler = true;
|
||||
ActivatedVisibility = ESlateVisibility::Visible;
|
||||
DeactivatedVisibility = ESlateVisibility::Hidden;
|
||||
SetIsFocusable(true);
|
||||
bIsModal = true;
|
||||
}
|
||||
|
||||
bool UFayeBaseWidget::Initialize()
|
||||
{
|
||||
if (IsDesignTime())
|
||||
{
|
||||
return Super::Initialize();
|
||||
}
|
||||
|
||||
TSubclassOf<UWidgetControllerBase> WidgetControllerClass = UWidgetControllerBase::StaticClass();
|
||||
if (ControllerClass)
|
||||
{
|
||||
WidgetControllerClass = ControllerClass;
|
||||
}
|
||||
|
||||
WidgetController = NewObject<UWidgetControllerBase>(this, WidgetControllerClass);
|
||||
WidgetController->InitializeController();
|
||||
|
||||
return Super::Initialize();
|
||||
}
|
||||
|
||||
void UFayeBaseWidget::ToggleWidget_Implementation(bool bActive)
|
||||
{
|
||||
if (bActive)
|
||||
{
|
||||
ActivateWidget();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeactivateWidget();
|
||||
}
|
||||
}
|
||||
|
||||
void UFayeBaseWidget::SetupWidget(const FInstancedStruct& DataPayload)
|
||||
{
|
||||
WidgetController->PassPayload(DataPayload);
|
||||
K2_SetupWidget(DataPayload);
|
||||
}
|
||||
|
||||
void UFayeBaseWidget::NativeOnActivated()
|
||||
{
|
||||
Super::NativeOnActivated();
|
||||
|
||||
SetVisibility(ActivatedVisibility);
|
||||
SetFocus();
|
||||
}
|
||||
|
||||
void UFayeBaseWidget::NativeOnDeactivated()
|
||||
{
|
||||
Super::NativeOnDeactivated();
|
||||
|
||||
SetVisibility(DeactivatedVisibility);
|
||||
}
|
||||
|
||||
bool UFayeBaseWidget::NativeOnHandleBackAction()
|
||||
{
|
||||
DeactivateWidget();
|
||||
return Super::NativeOnHandleBackAction();
|
||||
}
|
||||
45
Source/Faye/UI/FayeBaseWidget.h
Normal file
45
Source/Faye/UI/FayeBaseWidget.h
Normal file
@@ -0,0 +1,45 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CommonActivatableWidget.h"
|
||||
#include "StructUtils/InstancedStruct.h"
|
||||
#include "FayeBaseWidget.generated.h"
|
||||
|
||||
class UWidgetControllerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UFayeBaseWidget : public UCommonActivatableWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFayeBaseWidget();
|
||||
virtual bool Initialize() override;
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Faye Base Widget")
|
||||
void ToggleWidget(bool bActive);
|
||||
virtual void ToggleWidget_Implementation(bool bActive);
|
||||
|
||||
UFUNCTION(Category = "Faye Base Widget")
|
||||
virtual void SetupWidget(const FInstancedStruct& DataPayload);
|
||||
UFUNCTION(BlueprintImplementableEvent, Category = "Faye Base Widget")
|
||||
void K2_SetupWidget(const FInstancedStruct& DataPayload);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Faye Base Widget")
|
||||
UWidgetControllerBase* GetWidgetController() const { return WidgetController; }
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
TSubclassOf<UWidgetControllerBase> ControllerClass;
|
||||
|
||||
protected:
|
||||
virtual void NativeOnActivated() override;
|
||||
virtual void NativeOnDeactivated() override;
|
||||
virtual bool NativeOnHandleBackAction() override;
|
||||
|
||||
UPROPERTY()
|
||||
UWidgetControllerBase* WidgetController = nullptr;
|
||||
};
|
||||
4
Source/Faye/UI/InteractionDisplayWidget.cpp
Normal file
4
Source/Faye/UI/InteractionDisplayWidget.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "InteractionDisplayWidget.h"
|
||||
20
Source/Faye/UI/InteractionDisplayWidget.h
Normal file
20
Source/Faye/UI/InteractionDisplayWidget.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "FayeBaseWidget.h"
|
||||
#include "InteractionDisplayWidget.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UInteractionDisplayWidget : public UFayeBaseWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintImplementableEvent)
|
||||
void DisplayInteractionText(const FText& Text);
|
||||
};
|
||||
41
Source/Faye/UI/MainGameWidget.cpp
Normal file
41
Source/Faye/UI/MainGameWidget.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "MainGameWidget.h"
|
||||
|
||||
#include "Controller/ShelvesStackingController.h"
|
||||
#include "Faye/GameObjects/PlayerCharacter.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
void UMainGameWidget::ToggleOptionsWidget(bool bActive)
|
||||
{
|
||||
OptionsOpen = bActive;
|
||||
Options_Widget->SetupWidget(FInstancedStruct{});
|
||||
Options_Widget->ToggleWidget(bActive);
|
||||
}
|
||||
|
||||
void UMainGameWidget::TogglePhoneWidget(bool bActive)
|
||||
{
|
||||
PhoneOpen = bActive;
|
||||
Phone_Widget->SetupWidget(FInstancedStruct{});
|
||||
Phone_Widget->ToggleWidget(bActive);
|
||||
}
|
||||
|
||||
void UMainGameWidget::ToggleShelvesStackingWidget(bool bActive, FShelvesStackingSetupPayload Payload)
|
||||
{
|
||||
FInstancedStruct StructPayload = FInstancedStruct::Make(Payload);
|
||||
Shelves_Stacking_Widget->SetupWidget(StructPayload);
|
||||
Shelves_Stacking_Widget->ToggleWidget(bActive);
|
||||
}
|
||||
|
||||
void UMainGameWidget::ToggleDialogueWidget(bool bActive, FDialogueWidgetPayload DialoguePayload)
|
||||
{
|
||||
DialogueOpen = bActive;
|
||||
if (DialogueOpen)
|
||||
{
|
||||
check(StaticStruct<FDialogueWidgetPayload>() != nullptr);
|
||||
FInstancedStruct StructPayload = FInstancedStruct::Make(DialoguePayload);
|
||||
Dialogue_Widget->SetupWidget(StructPayload);
|
||||
}
|
||||
Dialogue_Widget->ToggleWidget(bActive);
|
||||
}
|
||||
77
Source/Faye/UI/MainGameWidget.h
Normal file
77
Source/Faye/UI/MainGameWidget.h
Normal file
@@ -0,0 +1,77 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DialogueWidget.h"
|
||||
#include "FayeBaseWidget.h"
|
||||
#include "MainGameWidget.generated.h"
|
||||
|
||||
struct FShelvesStackingSetupPayload;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class FAYE_API UMainGameWidget : public UFayeBaseWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
// Options widget
|
||||
UFUNCTION(BlueprintPure)
|
||||
UFayeBaseWidget *GetOptionsWidget() const { return Options_Widget; }
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void ToggleOptionsWidget(bool bActive);
|
||||
UFUNCTION(BlueprintPure)
|
||||
bool IsOptionsOpen() const { return OptionsOpen; }
|
||||
|
||||
// Phone widget
|
||||
UFUNCTION(BlueprintPure)
|
||||
UFayeBaseWidget *GetPhoneWidget() const { return Phone_Widget; }
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void TogglePhoneWidget(bool bActive);
|
||||
UFUNCTION(BlueprintPure)
|
||||
bool IsPhoneOpen() const { return PhoneOpen; }
|
||||
|
||||
// Shelve Stacking widget
|
||||
UFUNCTION(BlueprintPure)
|
||||
UFayeBaseWidget *GetShelvesStackingWidget() const { return Shelves_Stacking_Widget; }
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void ToggleShelvesStackingWidget(bool bActive, FShelvesStackingSetupPayload Payload);
|
||||
UFUNCTION(BlueprintPure)
|
||||
bool IsShelvesStackingOpen() const { return ShelvesStackingOpen; }
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
UDialogueWidget* GetDialogueWidget() const { return Dialogue_Widget; }
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void ToggleDialogueWidget(bool bActive, FDialogueWidgetPayload DialoguePayload);
|
||||
UFUNCTION(BlueprintPure)
|
||||
bool IsDialogueOpen() const { return DialogueOpen; }
|
||||
|
||||
protected:
|
||||
|
||||
// Options
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
UFayeBaseWidget* Options_Widget;
|
||||
UPROPERTY()
|
||||
bool OptionsOpen = false;
|
||||
|
||||
// Phone
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
UFayeBaseWidget* Phone_Widget;
|
||||
UPROPERTY()
|
||||
bool PhoneOpen = false;
|
||||
|
||||
// Shelve Stacking UI
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
UFayeBaseWidget* Shelves_Stacking_Widget;
|
||||
UPROPERTY()
|
||||
bool ShelvesStackingOpen = false;
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
UDialogueWidget* Dialogue_Widget;
|
||||
UPROPERTY()
|
||||
bool DialogueOpen = false;
|
||||
};
|
||||
Reference in New Issue
Block a user