IsFollowupState flag and replace FollowupState with GetFollowupState

This commit is contained in:
Kevin Poretti 2024-01-31 21:59:28 -05:00
parent 50a3bd8a4b
commit b8ffa48b47
4 changed files with 38 additions and 18 deletions

View File

@ -57,7 +57,7 @@ bool UFFState::CanTransition(const FFFStateContext& InStateContext)
return false; return false;
} }
return OnCanTransition(InStateContext); return OnCanTransition(InStateContext) && !bIsFollowupState;
} }
@ -163,26 +163,24 @@ void UFFState::Finish(const FFFStateContext& InStateContext, EFFStateFinishReaso
// the appropriate flags are set. I think having this state finish reason is good but I may want // the appropriate flags are set. I think having this state finish reason is good but I may want
// to rethink the way we handle logic for ending a state and which class is in charge of handling // to rethink the way we handle logic for ending a state and which class is in charge of handling
// what // what
if(FollowupState != NAME_None)
if(GetFollowupState() != NAME_None)
{ {
InStateContext.Parent->GoToState(FollowupState, StateFinishReason); InStateContext.Parent->GoToState(GetFollowupState(), StateFinishReason);
} }
else else
{ {
InStateContext.Parent->GoToEntryState(StateFinishReason); InStateContext.Parent->GoToEntryState(StateFinishReason);
} }
} }
void UFFState::RegisterInputHandler(const FFFInputSequence& InRequiredSequence, FFFInputEventDelegate InDelegate) FName UFFState::GetFollowupState_Implementation()
{ {
FFFInputEventHandler TempHandler; return FollowupState;
TempHandler.RequiredSequence = InRequiredSequence;
TempHandler.Delegate = InDelegate;
InputHandlers.Add(TempHandler);
} }
void UFFState::PlayMontage(const FFFStateContext& InStateContext) void UFFState::PlayMontage(const FFFStateContext& InStateContext)
{ {
// TODO: think of a better way to handle optionally playing montages other than the one set as MontageToPlay // TODO: think of a better way to handle optionally playing montages other than the one set as MontageToPlay

View File

@ -126,6 +126,17 @@ public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
bool bCanTransitionToSelf = false; bool bCanTransitionToSelf = false;
/**
* Specifies whether a state is a followup state or not.
*
* Followup states are states that should only be transitioned into from another specific state
* but otherwise have no other specific conditions that need to be met to transition.
* Setting this flag to true when there are no other conditions prevents this state from
* constantly being transitioned into by the state machine.
*/
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
bool bIsFollowupState = false;
/** /**
* State to transition to when this state is finished. If left blank then the entry state * State to transition to when this state is finished. If left blank then the entry state
* of the state machine will be transitioned into. * of the state machine will be transitioned into.
@ -197,10 +208,12 @@ public:
EMovementMode NewMovementMode, uint8 NewCustomMode, const FFFStateContext& InStateContext); EMovementMode NewMovementMode, uint8 NewCustomMode, const FFFStateContext& InStateContext);
// TODO: document // TODO: document
// TODO: call this callback when the avatar is hit
// TODO: pass in hitdata struct as well // TODO: pass in hitdata struct as well
virtual void Hit(const FFFStateContext& InStateContext); virtual void Hit(const FFFStateContext& InStateContext);
// TODO: document // TODO: document
// TODO: call this callback when the avatar blocks a hit
// TODO: pass in hitdata struct as well // TODO: pass in hitdata struct as well
virtual void Block(const FFFStateContext& InStateContext); virtual void Block(const FFFStateContext& InStateContext);
@ -219,12 +232,7 @@ public:
*/ */
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
virtual void Finish(const FFFStateContext& InStateContext, EFFStateFinishReason StateFinishReason); virtual void Finish(const FFFStateContext& InStateContext, EFFStateFinishReason StateFinishReason);
// TODO: document
UFUNCTION(BlueprintCallable)
virtual void RegisterInputHandler(
const FFFInputSequence& InRequiredSequence, FFFInputEventDelegate InDelegate);
// TODO: document // TODO: document
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events") UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
void OnInit(const FFFStateContext& InStateContext); void OnInit(const FFFStateContext& InStateContext);
@ -255,16 +263,30 @@ public:
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events") UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnUpdate(float OneFrame, const FFFStateContext& InStateContext); void OnUpdate(float OneFrame, const FFFStateContext& InStateContext);
/**
* Returns the next state to transition into when this state finishes.
*
* This is called during the Finish function, either when the state duration is reached or the
* state is manually finished due to some other logic.
*
* By default this returns the name of the state specified by the FollowupState property or
* NAME_None if the FollowupState is not specified.
*/
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
FName GetFollowupState();
// TODO: Don't like this at all and needs to be refactored or redesigned
UFUNCTION(BlueprintCallable, Category="UFF|State|Animations") UFUNCTION(BlueprintCallable, Category="UFF|State|Animations")
void PlayMontage(const FFFStateContext& InStateContext); void PlayMontage(const FFFStateContext& InStateContext);
// TODO: Don't like this at all and needs to be refactored or redesigned
/** /**
* Blueprint hook for overriding the logic for when a anim montage plays at the start of a state * Blueprint hook for overriding the logic for when a anim montage plays at the start of a state
* @param InStateContext * @param InStateContext
*/ */
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events") UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
void OnPlayMontage(const FFFStateContext& InStateContext); void OnPlayMontage(const FFFStateContext& InStateContext);
// TODO: document // TODO: document
UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events") UFUNCTION(BlueprintImplementableEvent, Category="UFF|State|Events")
void OnLanded(const FHitResult& Hit, const FFFStateContext& InStateContext); void OnLanded(const FHitResult& Hit, const FFFStateContext& InStateContext);

View File

@ -224,7 +224,7 @@ UFFState* UFFStateMachineComponent::FindStateWithName(FName StateName)
} }
} }
UE_LOG(LogTemp, Warning, UE_LOG(LogTemp, Error,
TEXT("Could not find state in state machine with name %s"), *StateName.ToString()); TEXT("Could not find state in state machine with name %s"), *StateName.ToString());
return nullptr; return nullptr;

View File

@ -184,7 +184,7 @@ protected:
UPROPERTY() UPROPERTY()
UFFState* CurrentState; UFFState* CurrentState;
/** Current SubState label or NAME_None if there is no SubState label set for the current state*/ /** Current SubState label or NAME_None if there is no SubState label set for the current state */
FName CurrentSubStateLabel; FName CurrentSubStateLabel;
// TODO: should be a TMap // TODO: should be a TMap