// Similar to ExecuteSkill but for running effects
        public static void ExecuteSkillRunning(ISimulationData data, SimulationSampleSet set)
        {
            int targetMax = GetSkillTargetCount(data);
            IList<IEntity> targets = data.PickRandomTargets(targetMax);
            for (int i = 0; i < targets.Count; i++)
            {
                IEntity target = targets[i];
                ApplySkillAttack(data, set, target, i == 0);
            }

            data.SelectedSkill.LastTrigger = data.CurrentTime;
        }
        public static ExecuteSkillResult ExecuteSkill(ISimulationData data, SimulationSampleSet set)
        {
            // try to perform action
            if (data.IsRunning(data.SelectedSkill))
            {
                return ExecuteSkillResult.Running;
            }

            if (data.IsOnCooldown(data.SelectedSkill))
            {
                return ExecuteSkillResult.Cooldown;
            }

            if (!CheckSufficientResource(data))
            {
                return ExecuteSkillResult.InsufficientResources;
            }

            if (!CanExecuteAction(data))
            {
                return ExecuteSkillResult.InsufficientTime;
            }

            int targetMax = GetSkillTargetCount(data);
            IList<IEntity> targets = data.PickRandomTargets(targetMax);
            for (int i = 0; i < targets.Count; i++)
            {
                IEntity target = targets[i];
                ApplySkillAttack(data, set, target, i == 0);
            }

            data.SelectedSkill.LastTrigger = data.CurrentTime;

            ApplySkillCooldown(data);
            ApplySkillRunning(data);

            // Cost is only once per action
            DeductSkillCost(data);
            FinalizeAction(data, set);
            return ExecuteSkillResult.Success;
        }