Initial push to repo

This commit is contained in:
2026-07-03 19:56:31 +02:00
commit 4cf4176d57
1305 changed files with 43455 additions and 0 deletions

15
Source/Faye.Target.cs Normal file
View File

@@ -0,0 +1,15 @@
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
using System.Collections.Generic;
public class FayeTarget : TargetRules
{
public FayeTarget(TargetInfo Target) : base(Target)
{
Type = TargetType.Game;
DefaultBuildSettings = BuildSettingsVersion.V6;
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_7;
ExtraModuleNames.Add("Faye");
}
}

View 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;
}

View 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;
};

View 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);
}

View 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;
};

View 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>();
}

View 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;
};

View 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();
}

View 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---
};

View 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();
}

View 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();
};

View 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);
}

View 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;
};

View 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);
}

View 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;
};

View 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();
}

View 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;
};

View 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);
}));
}

View 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();
};

View 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;
}

View 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;
};

View File

@@ -0,0 +1,4 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "OrderSettingsDataAsset.h"

View 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;
};

View File

@@ -0,0 +1,4 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "ShopListDataAsset.h"

View 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;
};

View 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
View 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
View 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
View File

@@ -0,0 +1,6 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"

View 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);
}

View 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;
};

View 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);
}

View 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;
};

View 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();
}

View 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;
};

View 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;
}

View 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;
};

View 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));
}
}

View 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;
};

View 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;
}

View 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;
};

View 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);
}
}

View 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;
};

View 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;
}

View 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;
};

View 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);
}

View 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;
};

View 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);
}
}

View 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);
};

View 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.

View 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;
};

View 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;
}

View 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;
};

View File

@@ -0,0 +1,4 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "CoffeeItem.h"

View 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;
};

View 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;
}

View 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;
};

View File

@@ -0,0 +1,5 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Item.h"

View 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;
};

View 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;
}

View 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;
};

View File

@@ -0,0 +1 @@
#include "BookDataStruct.h"

View 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;
};

View File

@@ -0,0 +1 @@
#include "CommonStructs.h"

View File

@@ -0,0 +1,12 @@
#pragma once
#include "CommonStructs.generated.h"
USTRUCT()
struct FObjectContainer
{
GENERATED_BODY()
UPROPERTY()
TArray<UObject*> Objects;
};

View File

@@ -0,0 +1 @@
#include "ItemDataStruct.h"

View 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;
};

View 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);
}

View 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;
};

View 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;
}

View 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(); }
};

View File

@@ -0,0 +1,4 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "FayeFunctionLibrary.h"

View 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(); }
};

View File

@@ -0,0 +1,9 @@
#include "FayeGameplayTags.h"
namespace Event
{
namespace TimeOfDay
{
UE_DEFINE_GAMEPLAY_TAG(TimePassed, TEXT("Event.TimeOfDay.TimePassed"))
}
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "NativeGameplayTags.h"
namespace Event
{
namespace TimeOfDay
{
FAYE_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TimePassed)
}
}

View 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;
}

View 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);
};

View 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;
}

View 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;
};

View 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;
}

View 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;
};

View 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;
}
}

View 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);
};

View File

@@ -0,0 +1,5 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "DialogueWidget.h"

View 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:
};

View 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();
}

View 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;
};

View File

@@ -0,0 +1,4 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "InteractionDisplayWidget.h"

View 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);
};

View 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);
}

View 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;
};

View File

@@ -0,0 +1,15 @@
// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
using System.Collections.Generic;
public class FayeEditorTarget : TargetRules
{
public FayeEditorTarget( TargetInfo Target) : base(Target)
{
Type = TargetType.Editor;
DefaultBuildSettings = BuildSettingsVersion.V6;
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_7;
ExtraModuleNames.Add("Faye");
}
}