115 lines
4.8 KiB
C++
115 lines
4.8 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "GameplayTagContainer.h"
|
|
#include "Components/InteractionWidgetComponent.h"
|
|
#include "GameFramework/Pawn.h"
|
|
#include "Interface/InteractableActorInterface.h"
|
|
#include "NpcBaseCharacter.generated.h"
|
|
|
|
class UCapsuleComponent;
|
|
class UEleriFlipbookComponent;
|
|
class UExtendedPawnMovement;
|
|
class UInventoryComponent;
|
|
class UNpcScheduleComponent;
|
|
class UNpcStateMachineComponent;
|
|
|
|
USTRUCT(BlueprintType)
|
|
struct FNpcCharacterData
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Categories = "NpcTags"))
|
|
FGameplayTag NpcTag;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
|
FText NpcName;
|
|
};
|
|
|
|
/**
|
|
* A scheduled NPC: a plain APawn with a capsule, a flipbook and nothing else, so that a town full
|
|
* of them stays affordable next to the player's ACharacter.
|
|
*
|
|
* It deliberately has no skeletal mesh, no character movement and no physics. Movement comes from
|
|
* UExtendedPawnMovement, which is a UFloatingPawnMovement rather than a UCharacterMovementComponent,
|
|
* and the pawn is possessed by an ABaseAIController: the state machine hands a destination to the
|
|
* movement component, which hands it on to the controller, and the path across the navmesh, the route
|
|
* around whatever stands in the way and the walking of it are all the engine's default path
|
|
* following. What the movement component does itself is keep the pawn on the floor and turn it to
|
|
* face the way it is going.
|
|
*
|
|
* Everything else it owns is a component and each one stands on its own, so the pawn is usable with
|
|
* any of them removed. The schedule decides what it should be doing and freezes it while the player
|
|
* is far away, the state machine walks it there and keeps it there, the inventory holds whatever it
|
|
* carries, and the interaction widget shows its prompt.
|
|
*/
|
|
UCLASS(BlueprintType)
|
|
class PROJECTELERI_API ANpcBaseCharacter : public APawn, public IInteractableActorInterface
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
protected:
|
|
ANpcBaseCharacter();
|
|
|
|
public:
|
|
|
|
// Called when the game starts or when spawned
|
|
virtual void BeginPlay() override;
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Components")
|
|
UCapsuleComponent* GetCapsuleComponent() const { return Capsule; }
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Components")
|
|
UEleriFlipbookComponent* GetFlipbookComponent() const { return FlipbookComponent; }
|
|
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Components")
|
|
UInventoryComponent* GetInventoryComponent() const { return InventoryComponent; }
|
|
|
|
/** The schedule driving this NPC, null when it is not scheduled. The save layer walks this
|
|
* to store and restore where an NPC stood and what it was doing. */
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Schedule")
|
|
UNpcScheduleComponent* GetScheduleComponent() const { return ScheduleComponent; }
|
|
|
|
/** The state machine running this NPC's behaviour: where it walks to and what it does once it is
|
|
* there. Handed its assignment by the schedule component and driven by nothing else. */
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Components")
|
|
UNpcStateMachineComponent* GetNpcStateMachine() const { return StateMachineComponent; }
|
|
|
|
virtual void ToggleInteractableUI_Implementation(bool bActive) override;
|
|
|
|
protected:
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Components")
|
|
TObjectPtr<UCapsuleComponent> Capsule;
|
|
|
|
/** Everything this NPC is drawn with. No mesh is created at all, so there is no skeleton, no
|
|
* anim blueprint and no bone work to pay for. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Components")
|
|
TObjectPtr<UEleriFlipbookComponent> FlipbookComponent;
|
|
|
|
/** Walks the NPC wherever its StateTree sends it. Configure the speed on the component or on the
|
|
* task that did the sending. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement")
|
|
TObjectPtr<UExtendedPawnMovement> MovementComponent;
|
|
|
|
/** Drives this NPC from its schedule and freezes it while the player is far away. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Components")
|
|
TObjectPtr<UNpcScheduleComponent> ScheduleComponent;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Components")
|
|
TObjectPtr<UInventoryComponent> InventoryComponent;
|
|
|
|
/** Runs this NPC's behaviour: walks it to whatever the schedule assigned and does the action
|
|
* once it is there. Nothing is assigned to it, because everything it needs arrives from the
|
|
* schedule component on this NPC's first unfreeze. */
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Components")
|
|
TObjectPtr<UNpcStateMachineComponent> StateMachineComponent;
|
|
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
|
TObjectPtr<UInteractionWidgetComponent> WidgetComponent;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
|
FNpcCharacterData NpcCharacterData;
|
|
};
|