#nullable enable using System.Collections.Generic; using Godot; namespace Cirno.Scripts.Components.FSM; public abstract partial class IsoStateMachineBase : Node, IStateMachine where TKey : notnull where TType : Node { public Dictionary> States { get; set; } = new(); public TKey CurrentStateIndex { get; set; } = default!; public IState CurrentState => States[CurrentStateIndex]; public abstract TKey InitialState { get; protected set; } private TType _mainObject = default!; public TType MainObject => _mainObject; private bool _hasState; public override void _Ready() { _mainObject = this.GetParent(); var children = GetChildren(); foreach (var child in children) { if (child is IState state) { States.Add(state.StateId, state); state.Init(this); } } SetState(InitialState); } public TKey GetState() { return CurrentState.StateId; } public void SetState(TKey stateId) { if (_hasState) { // Keep track of previous state and exit it // PreviousStateIndex is not part of this base; derived classes may add it if needed CurrentState.ExitState(); } CurrentStateIndex = stateId; CurrentState.EnterState(); _hasState = true; } // Implement the GetModule() helper so this base class satisfies the IStateMachine interface public T? GetModule() where T : Node { if (MainObject is null) return default; foreach (var child in MainObject.GetChildren()) { if (child is T t) return t; } return default; } public override void _Process(double delta) { if (!_hasState) return; CurrentState.ProcessState(delta); } public override void _PhysicsProcess(double delta) { if (!_hasState) return; CurrentState.PhysicsProcessState(delta); } }