/// <summary>
        /// Performs a character action.
        /// </summary>
        /// <param name="commandType">The type of command that is being performed, such as Attack or Spells.</param>
        /// <param name="category">The category of the action being performed, may be left blank if the action has no categories.</param>
        /// <param name="index">The index of the action being performed.</param>
        /// <param name="targetPosition">The target position of the action being performed.</param>
        public void StartAction(Commands commandType, string category, int index, int targetPosition)
        {
            bool                isInvalidAction = false;
            ActionBase          action;
            IReadOnlyList <int> targets;

            switch (commandType)
            {
            case Commands.Attack:
                action          = DisplayManager.GetActionsFromCategory <Attack>(commandType, category)[index];
                isInvalidAction = !IsValidTarget(action, targetPosition);
                if (!isInvalidAction)
                {
                    targets = CombatTargeter.GetTranslatedTargetPositions(action.TargetPositions,
                                                                          action.CenterOfTargetsPosition,
                                                                          action.CanSwitchTargetPosition,
                                                                          targetPosition);
                    _actionController.StartAction(CombatStateHandler.CurrentRoundOrder[0], action, targets);
                }
                break;

            case Commands.Spells:
                action          = DisplayManager.GetActionsFromCategory <Spell>(commandType, category)[index];
                isInvalidAction = !IsValidTarget(action, targetPosition);
                if (!isInvalidAction)
                {
                    targets = CombatTargeter.GetTranslatedTargetPositions(action.TargetPositions,
                                                                          action.CenterOfTargetsPosition,
                                                                          action.CanSwitchTargetPosition,
                                                                          targetPosition);
                    _actionController.StartAction(CombatStateHandler.CurrentRoundOrder[0], action, targets);
                }
                break;

            case Commands.Items:
                var item = DisplayManager.GetConsumablesFromCategory(category)[index];
                isInvalidAction = !IsValidTarget(item.ItemSpell, targetPosition);
                if (!isInvalidAction)
                {
                    targets = CombatTargeter.GetTranslatedTargetPositions(item.ItemSpell.TargetPositions,
                                                                          item.ItemSpell.CenterOfTargetsPosition,
                                                                          item.ItemSpell.CanSwitchTargetPosition,
                                                                          targetPosition);
                    _actionController.StartAction(CombatStateHandler.CurrentRoundOrder[0], item.ItemSpell, targets);
                    _consumablesHandler.UseConsumable(item, CombatStateHandler.CurrentRoundOrder[0]);
                }
                break;

            case Commands.Wait:
                if (CombatStateHandler.CurrentRoundOrder.Count() == 1)
                {
                    isInvalidAction = true;
                }
                else
                {
                    CombatStateHandler.BeginWait();
                    CharacterBeginWait?.Invoke(this, new CombatLoggableEventArgs()
                    {
                        LogMessage = CombatMessenger.GetBeginWaitMessage(CombatStateHandler.CurrentRoundOrder[0].Name)
                    });
                }
                break;

            default:
                isInvalidAction = true;
                break;
            }

            if (!isInvalidAction)
            {
                EndTurn();
            }
        }