Add FSM components for player and enemy state management, including initialization and module resolution

This commit is contained in:
MaddoScientisto 2026-02-26 23:13:57 +01:00
commit b6cc5a00e8
57 changed files with 526 additions and 506 deletions

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
#nullable enable
using System.Collections.Generic;
using Godot;
namespace Cirno.Scripts.Components.FSM;
@ -8,12 +9,14 @@ public abstract partial class IsoStateMachineBase<TKey, TType> : Node, IStateMac
where TType : Node
{
public Dictionary<TKey, IState<TKey, TType>> States { get; set; } = new();
public TKey CurrentStateIndex { get; set; }
public TKey CurrentStateIndex { get; set; } = default!;
public IState<TKey, TType> CurrentState => States[CurrentStateIndex];
public abstract TKey InitialState { get; protected set; }
private TType _mainObject;
private TType _mainObject = default!;
public TType MainObject => _mainObject;
private bool _hasState;
public override void _Ready()
{
@ -38,23 +41,38 @@ public abstract partial class IsoStateMachineBase<TKey, TType> : Node, IStateMac
public void SetState(TKey stateId)
{
if (CurrentStateIndex is not null)
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<T>() helper so this base class satisfies the IStateMachine interface
public T? GetModule<T>() 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 (CurrentStateIndex is null) return;
if (!_hasState) return;
CurrentState.ProcessState(delta);
}
public override void _PhysicsProcess(double delta)
{
if (CurrentStateIndex is null) return;
if (!_hasState) return;
CurrentState.PhysicsProcessState(delta);
}
}