UnrealFightingFramework/Source/UnrealFightingFramework/State/FFState.h

280 lines
9.0 KiB
C++

// Unreal Fighting Framework by Kevin Poretti
#pragma once
// FF includes
#include "Input/FFInputBufferComponent.h"
// UE includes
#include "CoreMinimal.h"
#include "FFState.generated.h"
USTRUCT(BlueprintType)
struct FFFStateContext
{
GENERATED_BODY()
/** Actor that owns the avatar. Typically a player controller. */
UPROPERTY(BlueprintReadOnly)
AActor* Owner;
/**
* Actor that represents the player's avatar or an object associated with the player's avatar.
* This is typically a character or a weapon.
*/
UPROPERTY(BlueprintReadOnly)
AActor* Avatar;
/**
* Parent state machine that controls this state
*/
UPROPERTY(BlueprintReadOnly)
class UFFStateMachineComponent* Parent;
};
DECLARE_DYNAMIC_DELEGATE_OneParam(FFFInputEventDelegate, const FFFStateContext&, InStateContext);
USTRUCT(BlueprintType)
struct FFFInputEventHandler
{
GENERATED_BODY()
// TODO: document
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
FFFInputSequence RequiredSequence;
// TODO: document
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
FFFInputEventDelegate Delegate;
};
UENUM(BlueprintType)
enum class EFFStateFinishReason : uint8
{
// TODO: document
SFT_Interrupted UMETA(DisplayName="Interrupted"),
SFT_DurationMetOrExceeded UMETA(DisplayName="Duration Reached"),
SFT_NotInReqMovementMode UMETA(DisplayName="Not In Required Movement Mode"),
SFT_MAX UMETA(Hidden)
};
/**
* A state is an object that provides rules and conditions for when a state can be transitioned into
* and logic to run when the state is entered, exited, and active.
*/
UCLASS(Blueprintable)
class UNREALFIGHTINGFRAMEWORK_API UFFState : public UObject
{
GENERATED_BODY()
public:
// State parameters (should be read-only)
/** Name of this state behavior */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
FName Name;
/**
* True if this state has some duration where it should return to the entry state
* if this state is not cancelled out of by other means.
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
bool bStateHasDuration;
// TODO: this should only be editable if bStateHasDuration is true
/**
* How long this state will be active before finishing if this state is not cancelled out of
* by other means.
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="UFF State Properties")
int64 StateDuration;
/**
* What stance the object this state represents must be in.
* For example this is usually an enumerated value that signifies if a character needs to be
* crouching, standing, or airborne for this state to be eligible for transitioning.
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
int32 StanceRequired;
/**
* What is this state's category.
* Used for determining what types of state can prematurely cancel this one.
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
int32 StateType;
/**
* Input sequences that needs to be present in the controlling player's input buffer for this
* state to be eligible for transitioning.
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
TArray<FFFInputSequence> InputSequences;
/**
* If true the state can transition from itself into itself without having to go through
* another state like Idle
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
bool bCanTransitionToSelf = false;
/**
* Animation to begin playing when this state is entered
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
UAnimMontage* MontageToPlay;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
bool bStopMontageOnStateEnd;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
bool bStopMontageOnMovementModeChange;
/**
* Event delegates to call when a certain input condition is detected in the Owner's input buffer
*/
UPROPERTY(BlueprintReadOnly, Category="UFF State Events")
TArray<FFFInputEventHandler> InputHandlers;
/**
* Called when state is first created.
*/
virtual void Init(const FFFStateContext& InStateContext);
/**
* Returns true if Avatar's is in the correct stance AND
* the state type is enabled (or the state can be hit or whiff cancelled from the current state) AND
* all state entry conditions were met AND
* at least one input sequence is present in the Owner's input buffer
*/
virtual bool CanTransition(const FFFStateContext& InStateContext);
/**
* Called whenever this state is transitioned into.
*
* Calls appropriate Blueprint hooks.
*/
virtual void Enter(const FFFStateContext& InStateContext);
/**
* Called whenever this state is transitioned out of into a new state.
*
* Calls appropriate Blueprint hooks.
*
* TODO: document StateFinishReason
*/
virtual void Exit(const FFFStateContext& InStateContext, EFFStateFinishReason StateFinishReason);
/**
* Called whenever this state is active and the game logic ticks.
*
* Calls appropriate Blueprint hooks.
*
* @param OneFrame the time that elapses during one fixed tick
*/
virtual void Update(float OneFrame, const FFFStateContext& InStateContext);
// TODO: document
virtual void Landed(const FHitResult& Hit, const FFFStateContext& InStateContext);
// TODO: document
virtual void MovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode,
EMovementMode NewMovementMode, uint8 NewCustomMode, const FFFStateContext& InStateContext);
// TODO: document
// TODO: pass in hitdata struct as well
virtual void Hit(const FFFStateContext& InStateContext);
// TODO: document
// TODO: pass in hitdata struct as well
virtual void Block(const FFFStateContext& InStateContext);
/**
* Called when you want to exit from this state but no eligible transitions exist to other states,
* usually due to a lack of player input.
*
* By default this will transition to the owning state machine's entry state, which is usually
* an idle state.
*
* This function will get called automatically when the ticks in this state reaches the
* threshold set by the StateDuration member, but you can call it whenever you wish to return
* to the entry state.
*
* @param InStateContext
*/
UFUNCTION(BlueprintCallable)
virtual void Finish(const FFFStateContext& InStateContext, EFFStateFinishReason StateFinishReason);
// TODO: document
UFUNCTION(BlueprintCallable)
virtual void RegisterInputHandler(
const FFFInputSequence& InRequiredSequence, FFFInputEventDelegate InDelegate);
// TODO: document
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
void OnInit(const FFFStateContext& InStateContext);
/**
* Blueprint hook for overriding the CanTransition logic
*/
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
bool OnCanTransition(const FFFStateContext& InStateContext);
/**
* Blueprint hook for whenever this state is transitioned into
*/
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnEnter(const FFFStateContext& InStateContext);
/**
* Blueprint hook for whenever this state is transitioned out of into a new state
*/
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnExit(const FFFStateContext& InStateContext);
/**
* Blueprint hook for whenever this state is active and the game logic ticks.
*
* @param OneFrame the time that elapses during one fixed tick
*/
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnUpdate(float OneFrame, const FFFStateContext& InStateContext);
UFUNCTION(BlueprintCallable, Category="UFF|State|Animations")
void PlayMontage(const FFFStateContext& InStateContext);
/**
* Blueprint hook for overriding the logic for when a anim montage plays at the start of a state
* @param InStateContext
*/
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
void OnPlayMontage(const FFFStateContext& InStateContext);
// TODO: document
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnLanded(const FHitResult& Hit, const FFFStateContext& InStateContext);
// TODO: document
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode,
EMovementMode NewMovementMode, uint8 NewCustomMode, const FFFStateContext& InStateContext);
// TODO: document
// TODO: pass in hitdata struct as well
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnHit(const FFFStateContext& InStateContext);
// TODO: document
// TODO: pass in hitdata struct as well
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnBlock(const FFFStateContext& InStateContext);
// UObject interface
virtual UWorld* GetWorld() const override;
// End of UObject interface
private:
void StopCurrentAnimMontage(const FFFStateContext& InStateContext);
};