using System; using System.Threading.Tasks; using Babushka.scripts.CSharp.Common.Util; using Godot; namespace Babushka.scripts.CSharp.Common.Fight; public abstract class FighterAction { // enum has explicit values, because they are set in godot signals as integers // e.g. here: BabushkaSceneFightHappening => ActionSelect/BottomPanel/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer/AttackButton public enum AllyActionButton { None, Attack = 1, Summon = 2, Talk = 3, Flee = 4, } public class TargetSelection { // ReSharper disable once MemberHidesStaticFromOuterClass public static readonly TargetSelection Skip = new() { skipTargetSelection = () => true }; public Func skipTargetSelection = () => false; } public abstract class FighterActionDetail { public abstract bool DetailComplete(); } #region Shortcuts protected static FightWorld.FightHappeningData HappeningData => FightWorld.Instance.fightHappeningData ?? throw new NoFightHappeningException(); #endregion /// /// Executes the data modification for the action. This must happen instantly and not via a coroutines or callbacks. /// To get a multiple hit effect for one action, use appropriate Visual Manipulation functions in AnimateAction. /// public virtual void ExecuteAction() { } /// /// Returns a way to determine, when an action animation is done /// /// /// A variant that can be float or Func<bool>.
/// When the return type is float, the animation will take the return value amount of seconds.
/// When the return type is Func<bool>, the animation will be done, when the function returns true. ///
public abstract Variant> GetAnimationEnd(); /// /// Animates the action. /// /// public virtual async Task AnimateAction(AllFightersVisual allFightersVisual) { } public virtual bool ShouldAbort() => false; /// /// Returns the FighterActionDetail, that is currently handled. /// /// public virtual FighterActionDetail CurrentDetail() { throw new Exception("Action has no details to handle"); } /// /// Sets the next Detail to be handled. Returns false, when there are no more details to handle. /// /// public abstract bool NextDetail(); /// /// Returns the action point cost of this action. /// Right now, only the values 1 and 0 make sense. /// /// public virtual int GetActionPointCost() { return 1; } /// /// Will be called right after the action is selected by the player. Can be used to reset the state of the details /// public virtual void Reset() { } /// /// If this action should be bound to an action button in the UI, return the corresponding enum value here. /// /// public virtual AllyActionButton BindToActionButton() { return AllyActionButton.None; } public class Skip : FighterAction { public override Variant> GetAnimationEnd() { return 0f; } public override bool NextDetail() { return false; } } }