init
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RPGCore.Core;
|
||||
using RPGCore.Core.Objects;
|
||||
using RPGCore.ObjectModules.ActionObjectModule.Events;
|
||||
using RPGCore.ObjectModules.EventObjectModule;
|
||||
using RPGCoreCommon.Helpers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RPGCore.ObjectModules.ActionObjectModule
|
||||
{
|
||||
[Serializable]
|
||||
public class ActionModule : ObjectModule<UnitObject>
|
||||
{
|
||||
private List<BaseActionParallel> _actionParallels = new();
|
||||
private readonly List<BaseAction> _actionQueue = new();
|
||||
private BaseAction _actionCurrent;
|
||||
|
||||
public List<BaseActionParallel> actionParallels => _actionParallels.ToList();
|
||||
public List<BaseAction> actionQueue => _actionQueue.ToList();
|
||||
public BaseAction actionCurrent => _actionCurrent;
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (_actionCurrent?.state is not ActionState.Running) NextAction();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 1. Checks if the action can be executed outside the queue.<br/>
|
||||
/// 2. If allowed, executes the action and handles potential errors.
|
||||
/// </summary>
|
||||
public void Execute(BaseActionParallel action)
|
||||
{
|
||||
try
|
||||
{
|
||||
var actionExecuteEvent = new ActionExecuteEvent { action = action };
|
||||
parent.events.InvokeBefore(actionExecuteEvent);
|
||||
if (actionExecuteEvent.isPrevented) throw new ActionErrorException(action, "Action is prevented");
|
||||
parent.events.InvokeAfter(actionExecuteEvent);
|
||||
|
||||
_actionParallels.Add(action);
|
||||
action.unit = parent;
|
||||
action.OnEnd += () => _actionParallels.Remove(action);
|
||||
action.OnCancel += () => _actionParallels.Remove(action);
|
||||
action.DoIt();
|
||||
}
|
||||
catch (ActionErrorException e)
|
||||
{
|
||||
parent.events.Invoke(new ActionErrorEvent
|
||||
{
|
||||
unit = parent,
|
||||
action = e.action,
|
||||
message = e.Message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_actionParallels
|
||||
.Where(action => action.CanBeStopped())
|
||||
.ForEach(action => action.CancelIt())
|
||||
.ForEach(action => _actionParallels.Remove(action));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 1. Adds given action to queue
|
||||
/// 2. Starts it if queue is empty
|
||||
/// </summary>
|
||||
public void AddToQueue(BaseAction action) => AddToQueue(new List<BaseAction> { action });
|
||||
|
||||
/// <summary>
|
||||
/// 1. Adds given actions to queue
|
||||
/// 2. Runs only when previous action is finished successfully
|
||||
/// 3. Starts it if queue is empty
|
||||
/// </summary>
|
||||
public void AddToQueue(List<BaseAction> actions)
|
||||
{
|
||||
actions.ForEach(action => action.unit = parent);
|
||||
|
||||
actions.ForEach((index, action) =>
|
||||
{
|
||||
if (index != 0) action.runAfterAction = actions[index - 1];
|
||||
_actionQueue.Add(action);
|
||||
});
|
||||
|
||||
if (_actionCurrent == null) NextAction();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 1. Clear whole action queue
|
||||
/// 2. Cancel current action IF specified by argument
|
||||
/// 3. Some actions cant be stopped once fired by normal means, BUT we can force stopping it
|
||||
/// </summary>
|
||||
public void StopQueue(bool stopCurrent = true, bool stopForced = false)
|
||||
{
|
||||
_actionQueue.Clear();
|
||||
|
||||
if (!stopCurrent) return;
|
||||
if (!stopForced && _actionCurrent != null && !_actionCurrent.CanBeStopped()) return;
|
||||
|
||||
_actionCurrent?.CancelIt();
|
||||
_actionCurrent = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 1. Gets next action to do
|
||||
/// 2. If there is no more actions - do nothing
|
||||
/// 3. Proceed to execute it
|
||||
/// </summary>
|
||||
private void NextAction()
|
||||
{
|
||||
_actionCurrent = _actionQueue.FirstOrDefault();
|
||||
_actionQueue.Remove(_actionCurrent);
|
||||
|
||||
if (_actionCurrent == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
var actionExecuteEvent = new ActionExecuteEvent { action = _actionCurrent };
|
||||
parent.events.InvokeBefore(actionExecuteEvent);
|
||||
if (actionExecuteEvent.isPrevented) throw new ActionErrorException(_actionCurrent, "Action is prevented");
|
||||
parent.events.InvokeAfter(actionExecuteEvent);
|
||||
|
||||
_actionCurrent.DoIt();
|
||||
}
|
||||
catch (ActionErrorException e)
|
||||
{
|
||||
parent.events.Invoke(new ActionErrorEvent
|
||||
{
|
||||
unit = parent,
|
||||
action = e.action,
|
||||
message = e.Message
|
||||
});
|
||||
}
|
||||
|
||||
if (_actionCurrent.state is ActionState.Ready) Debug.LogWarning($"Action {_actionCurrent.GetType().Name} is still ready after starting. Skipping.");
|
||||
if (_actionCurrent.state is not ActionState.Running) NextAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user