#pragma once #include "character/CharacterActionLibrary.h" #include "character/CharacterDataLoader.h" #include "character/states/CharacterStateBase.h" #include #include namespace frostbite2D { class CharacterObject; class CharacterStateMachine { public: using StateRegistry = std::unordered_map>; CharacterStateMachine() = default; void Configure(const character::CharacterConfig& config); void Reset(); void Update(CharacterObject& owner, CharacterCommandBuffer& commandBuffer, const CharacterIntent& intent, float deltaTime); void ForceHurt(CharacterObject& owner, const CharacterActionDefinition* hurtAction); CharacterStateId GetState() const { return currentState_; } const std::string& GetCurrentActionId() const { return currentActionId_; } const CharacterActionDefinition* GetCurrentActionDefinition() const { return currentAction_; } bool CanAcceptGroundActions() const; bool CanBeInterrupted() const; bool IsMovementLocked() const; bool CanTurn() const; void RegisterState(std::unique_ptr stateNode); void ClearRegisteredStates(); ICharacterStateNode* FindStateNode(CharacterStateId stateId) const; private: void ChangeState(CharacterObject& owner, CharacterStateId nextState); void EnterAction(CharacterObject& owner, const CharacterActionDefinition* action); void InvokeStateHook(CharacterObject& owner, const CharacterActionDefinition* action, const char* phase) const; bool TryStartAction(CharacterObject& owner, CharacterCommandBuffer& commandBuffer, const std::string& requestedActionId, const std::string& actionId); bool StartAction(CharacterObject& owner, const std::string& requestedActionId, const std::string& actionId); bool TryStartRegisteredAction(CharacterStateContext& context); CharacterStateId currentState_ = CharacterStateId::Idle; std::string currentActionId_; const CharacterActionDefinition* currentAction_ = nullptr; float stateTime_ = 0.0f; StateRegistry stateRegistry_; friend class CharacterStateBase; }; } // namespace frostbite2D