public override void DoWork()
        {
            try
            {
                //Perform required items for logging
                this.Progressing();

                //Your code goes here
                //To log note
                this.ScheduleHistoryItem.AddLogNote("STARTING JOB");
                stopwatch.Start();

                // determine what skirmish to process
                if (Skirmish_PK == -1)
                {
                    // get today's skirmishes
                    globalSkirmishes = controller.GetCurrentSkirmishes();
                }
                else
                {
                    // process a specific skirmish
                    globalSkirmishes = controller.GetSkirmishData(Skirmish_PK);
                }

                // get accolades
                globalAccolades = controller.GetAccolades();

                foreach (Skirmish skirmish in globalSkirmishes)
                {
                    #region Skirmish Initialization
                    // create log file for skirmish
                    this.ScheduleHistoryItem.AddLogNote("CREATE LOG FILE");
                    logger = File.CreateText(HttpRuntime.AppDomainAppPath + "/DesktopModules/BattleFrameworkModule/logs/" + skirmish.Skirmish_PK + ".txt");

                    _GAMESTATE.Skirmish_FK = skirmish.Skirmish_PK;

                    // get all data for data warehouse object arrays
                    globalCharacters = controller.GetSkirmishCharacters(skirmish.Skirmish_PK);
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms DATA globalCharacters: " + Json.Serialize(globalCharacters));
                    globalSkills = controller.GetSkillDataFromSkirmishCharacters(skirmish.Skirmish_PK);
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms DATA globalSkills: " + Json.Serialize(globalSkills));
                    globalInitTrack = controller.GetInitiativeTrackFromSkirmish(skirmish.Skirmish_PK);
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms DATA globalInitTrack: " + Json.Serialize(globalInitTrack));
                    globalVotes = controller.GetVoteDataFromSkirmish(skirmish.Skirmish_PK, null);
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms DATA globalVotes: " + Json.Serialize(globalVotes));

                    // reset warehouses
                    globalCombatLog.Clear();
                    globalCharacterTrackLog.Clear();
                    skirmishPreparedSkills.Clear();

                    logger.WriteLine("");
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms BEGIN CHARACTER INITIALIZATION");
                    // initialize characters
                    foreach(var character in globalCharacters)
                    {
                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SETTING [" + character.Character_Name + "] Max_Health to " + character.Health);
                        character.Max_Health = character.Health;
                        character.Conditions = new Conditions();
                        character.Conditions.Shield_Enchanters_Character_PK = new List<int>();
                        character.Conditions.DamageBonus_Enchanters_Character_PK = new List<int>();
                        character.Conditions.Guarded_Characters_PK = new List<int>();

                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Creating character track log for character ...");
                        globalCharacterTrackLog.Add(new Character_Track_Log(){ Character_FK = character.Character_PK });
                    }
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms END CHARACTER INITIALIZATION");
                    logger.WriteLine("");
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms BEGIN SKILL INITIALIZATION");
                    // initialize passive skills
                    foreach (var skill in globalSkills)
                    {
                        if (skill.bIsPassive)
                        {
                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms PREPARING [" + skill.Skill_Name + "](pk=" + skill.Skill_PK + ") | Preparer: [" + GetCharacter(skill.Character_FK).Character_Name + "] | Exec_Track_Step: " + skill.Exec_Track_Step);
                            skirmishPreparedSkills.Add(new Prepared_Skills()
                            {
                                Skill_PK = skill.Skill_PK,
                                Preparer_Character_FK = skill.Character_FK,
                                Exec_Track_Step = skill.Exec_Track_Step
                            });
                        }
                    }
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms END SKILL INITIALIZATION");
                    #endregion

                    // perform skills following initiatve track (should already be sorted from SQL)
                    logger.WriteLine("");
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms BEGIN SKIRMISH(pk=" + skirmish.Skirmish_PK + ")");
                    foreach (var currAct in globalInitTrack)
                    {
                        _GAMESTATE.Current_Act_Order = currAct.Act_Order;

                        // setup turn track
                        #region TURN TRACK OVERVIEW
                        /**
                         *
                         * TURN TRACK STEPS
                         * Begin Turn
                         *      1 - set active character to this character
                         *      2 - is character stunned?
                         *      3 - special character skills
                         * Determine Skill
                         *      4 - find favored skill
                         *      5 - find favored targets for skill
                         * Preliminary Skill Execution
                         *      6 - target legibility (Invisiblity, Knocked Out, Charmed, ect)
                         *      7 - special character skills
                         * Perform Attack Roll
                         *      8 - determine if skill instantly resolves
                         *      9 - determine if attack has advantage or disadvantage
                         *      10 - roll attack dice for attack and add base modifier
                         * Perform Damage Roll
                         *      11 - determine if attacks are successful and determine damage
                         *      12 - special character skills (pre-damage)
                         *      13 - inflict damage on target
                         *      14 - special character skills (post-damage)
                         * Target Conditions
                         *      15 - determine if target receives any afflictions
                         *      16 - special character skills
                         * End Turn
                         *
                         * */
                        #endregion

                        // interface
                        Skill FavoredSkill = new Skill();
                        List<Character> FavoredSkillFavoredTargets = new List<Character>();
                        var lastTrackStep = 17;

                        #region TURN TRACK
                        // cycle through turn track
                        var currChar = GetCharacter(currAct.Character_FK);
                        for (var currTrackStep = 1; currTrackStep <= lastTrackStep; currTrackStep++)
                        {
                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms BEGIN TRACK STEP [" + currTrackStep + "] for [" + currChar.Character_Name + "]");
                            _GAMESTATE.Current_Track_Step = currTrackStep;

                            switch (currTrackStep)
                            {
                                #region BEGIN TURN
                                case 1:
                                    // 1 - set active character to this character
                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SETTING [" + currChar.Character_Name + "](pk=" + currChar.Character_PK + ") as active character");
                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM active character:" + Json.Serialize(currChar));
                                    _GAMESTATE.Active_Character = currChar;
                                    break;
                                case 2:
                                    // 2 - is character stunned?
                                    if (currChar.Conditions.bStunned)
                                    {
                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Character is stunned, skip to end turn step");
                                        currTrackStep = lastTrackStep;
                                    }
                                    break;
                                case 3:
                                    // 3 - special character skills
                                    CheckSpecialSkills();
                                    break;
                                #endregion
                                #region DETERMINE SKILL
                                case 4:
                                    // 4 - find favored skill
                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Finding favored skill for character to perform ...");
                                    //FavoredSkill = GetSkill(globalVotes.OrderByDescending(x => x.Vote_Count).FirstOrDefault(x => x.Character_FK == currChar.Character_PK).Skill_FK);
                                    FavoredSkill = GetFavoredSkill(currChar.Character_PK);
                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Found favored skill. Skill_Name: [" + FavoredSkill.Skill_Name + "](pk=" + FavoredSkill.Skill_PK + ") | Skill:" + Json.Serialize(FavoredSkill));
                                    _GAMESTATE.Pending_Skill = FavoredSkill;
                                    break;
                                case 5:
                                    // 5 - find favored targets for skill
                                    // targets are separated by commas
                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Finding favored targets for skill ...");
                                    if (!globalVotes.Any(x => x.Skill_FK == FavoredSkill.Skill_PK && x.Character_FK == currChar.Character_PK))
                                    {
                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM No targets for this skill, find random target");

                                        if (FavoredSkill.Skill_Type.Contains("Attack") ||
                                            FavoredSkill.Skill_Type.Contains("Affliction") ||
                                            FavoredSkill.Skill_Type.Contains("Taunt"))
                                        {
                                            // skill type is hostile, find random enemy targets
                                            for (var i = 1; i < FavoredSkill.Max_Targets; i++)
                                            {
                                                FavoredSkillFavoredTargets.Add(globalCharacters.FirstOrDefault(x => x.Guild_FK != currChar.Guild_FK && !FavoredSkillFavoredTargets.Contains(x)));
                                            }
                                        }
                                        else
                                        {
                                            // skill type is friendly, find random friendly targets
                                            if (FavoredSkill.Skill_Type == "Blessing,Advantage" ||
                                                FavoredSkill.Skill_Type == "Blessing,Disadvantage" ||
                                                FavoredSkill.Skill_Type == "Blessing,Damage" ||
                                                FavoredSkill.Skill_Type.Contains("Guard"))
                                            {
                                                // skill cannot target self
                                                FavoredSkillFavoredTargets.OrderBy(x => Guid.NewGuid()).FirstOrDefault(x => x.Guild_FK == currChar.Guild_FK && x.Character_PK != currChar.Character_PK && !FavoredSkillFavoredTargets.Contains(x));
                                            }
                                            else if (FavoredSkill.Skill_Type == "Blessing,AllStats" ||
                                                      FavoredSkill.Skill_Type == "Blessing,Dodge" ||
                                                      FavoredSkill.Skill_Type == "Blessing,Finesse" ||
                                                      FavoredSkill.Skill_Type == "Blessing,Agility" ||
                                                      FavoredSkill.Skill_Type == "Blessing,Senses" ||
                                                      FavoredSkill.Skill_Type == "Blessing,Mana" ||
                                                      FavoredSkill.Skill_Type == "Blessing,Shield" ||
                                                      FavoredSkill.Skill_Type == "Heal")
                                            {
                                                // skill can target self
                                                FavoredSkillFavoredTargets.OrderBy(x => Guid.NewGuid()).FirstOrDefault(x => x.Guild_FK == currChar.Guild_FK && !FavoredSkillFavoredTargets.Contains(x));
                                            }
                                        }
                                    }
                                    else
                                    {
                                        var tmpTargets = Array.ConvertAll(globalVotes.FirstOrDefault(x =>
                                            x.Skill_FK == FavoredSkill.Skill_PK &&
                                            x.Character_FK == currChar.Character_PK).Targets.Split(','), int.Parse);
                                        FavoredSkillFavoredTargets.AddRange(
                                            tmpTargets.Select(target => GetCharacter(target)));

                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Found favored targets [" + Json.Serialize(FavoredSkillFavoredTargets) + "]");
                                    }
                                    _GAMESTATE.Pending_Targets = FavoredSkillFavoredTargets;
                                    break;
                                #endregion
                                #region PRELIMINARY SKILL EXECUTION
                                case 6:
                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Determine target legibility");
                                    // 6 - target legibility (Invisiblity, Knocked Out, Charmed, ect)

                                    // no targets acquired during voting, determine random targets
                                    if (!FavoredSkillFavoredTargets.Any())
                                    {
                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM no targets were acquired in Voting, determine random targets ...");

                                        for (var i = 0; i < FavoredSkill.Max_Targets; i++)
                                        {
                                            Character newTarget = new Character();
                                            if (FavoredSkill.Skill_Type == "Attack" ||
                                                FavoredSkill.Skill_Type == "Taunt" ||
                                                FavoredSkill.Skill_Type.Contains("Affliction"))
                                            {
                                                // assign target to random enemy
                                                newTarget = globalCharacters.FirstOrDefault(x => x.Guild_FK != currChar.Guild_FK &&
                                                                                                !x.Conditions.bKnockedOut &&
                                                                                                !x.Conditions.bInvisible &&
                                                                                                !FavoredSkillFavoredTargets.Exists(y => y.Character_PK == x.Character_PK));
                                            }

                                            if (FavoredSkill.Skill_Type == "Heal")
                                            {
                                                // assign target to random friendly character (can include self)
                                                newTarget = globalCharacters.FirstOrDefault(x => x.Guild_FK == currChar.Guild_FK &&
                                                                                                !x.Conditions.bKnockedOut &&
                                                                                                !x.Conditions.bInvisible &&
                                                                                                !FavoredSkillFavoredTargets.Exists(y => y.Character_PK == x.Character_PK));
                                            }

                                            if (FavoredSkill.Skill_Type.Contains("Blessing") ||
                                                FavoredSkill.Skill_Type.Contains("Guard"))
                                            {
                                                // assign target to random ally
                                                newTarget = globalCharacters.FirstOrDefault(x => x.Guild_FK == currChar.Guild_FK &&
                                                                                                x.Character_PK != currChar.Character_PK &&
                                                                                                !x.Conditions.bKnockedOut &&
                                                                                                !x.Conditions.bInvisible &&
                                                                                                !FavoredSkillFavoredTargets.Exists(y => y.Character_PK == x.Character_PK));
                                            }

                                            if(newTarget != null) FavoredSkillFavoredTargets.Add(newTarget);
                                        }

                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM new targets: " + Json.Serialize(FavoredSkillFavoredTargets));
                                    }

                                    foreach (var target in FavoredSkillFavoredTargets.ToList())
                                    {
                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM target=[" + target.Character_Name + "] |" +
                                                                        " bInvisible:" + target.Conditions.bInvisible + " | bKnockedOut:" + target.Conditions.bKnockedOut +
                                                                        " | bCharmed:" + target.Conditions.bCharmed + " | bTaunted:" + target.Conditions.bTaunted +
                                                                        " | bBlinded:" + target.Conditions.bBlinded + " | bGuarded:" + target.Conditions.bGuarded);

                                        // check if character has skills to bypass normal targetting rules
                                        CheckSpecialSkills();

                                        // target is either Invisible or Knocked Out, reassign to random enemy
                                        if (target.Conditions.bInvisible || target.Conditions.bKnockedOut)
                                        {
                                            // remove old target from target list
                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM target is invisible or knocked out, remove target from favored target list | Skill_Type:" + FavoredSkill.Skill_Type);
                                            FavoredSkillFavoredTargets.Remove(target);

                                            // ignore target reassignment if skill is an AoE attack that targets the entire team
                                            if (FavoredSkill.Max_Targets < 12)
                                            {
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM assign a new target | Skill_Type:" + FavoredSkill.Skill_Type);
                                                Character newTarget = new Character();
                                                switch (FavoredSkill.Skill_Type)
                                                {
                                                    case "Attack":
                                                    case "Taunt":
                                                    case "Affliction,Stunned":
                                                    case "Affliction,Blinded":
                                                    case "Affliction,Disadvantage":
                                                    case "Affliction,Advantage":
                                                    case "Affliction,StatDebuff":
                                                        // find new target not on this character's team
                                                        newTarget =
                                                            globalCharacters.OrderBy(x => Guid.NewGuid())
                                                                .FirstOrDefault(
                                                                    x =>
                                                                        x.Guild_FK != currChar.Guild_FK &&
                                                                        !FavoredSkillFavoredTargets.Exists(
                                                                            y => y.Character_PK == x.Character_PK) &&
                                                                        !x.Conditions.bInvisible &&
                                                                        !x.Conditions.bKnockedOut);
                                                        logger.WriteLine(DateTime.Today + " " +
                                                                         stopwatch.ElapsedMilliseconds +
                                                                         "ms SYSTEM New target found | {" +
                                                                         Json.Serialize(newTarget) + "}");
                                                        break;
                                                    case "Heal":
                                                        // find new target that is on this character's team that has less than full health
                                                        newTarget =
                                                            globalCharacters.OrderBy(x => Guid.NewGuid())
                                                                .FirstOrDefault(
                                                                    x =>
                                                                        x.Guild_FK == currChar.Guild_FK &&
                                                                        x.Health < x.Max_Health &&
                                                                        !FavoredSkillFavoredTargets.Exists(
                                                                            y => y.Character_PK == x.Character_PK) &&
                                                                        !x.Conditions.bInvisible &&
                                                                        !x.Conditions.bKnockedOut);
                                                        logger.WriteLine(DateTime.Today + " " +
                                                                         stopwatch.ElapsedMilliseconds +
                                                                         "ms SYSTEM New target found | {" +
                                                                         Json.Serialize(newTarget) + "}");
                                                        break;
                                                    case "Blessing,Disadvantage":
                                                    case "Blessing,Advantage":
                                                    case "Blessing,Damage":
                                                        // find new target on this character's team
                                                        newTarget =
                                                            globalCharacters.OrderBy(x => Guid.NewGuid())
                                                                .FirstOrDefault(
                                                                    x =>
                                                                        x.Guild_FK == currChar.Guild_FK &&
                                                                        !FavoredSkillFavoredTargets.Exists(
                                                                            y => y.Character_PK == x.Character_PK) &&
                                                                        !x.Conditions.bInvisible &&
                                                                        !x.Conditions.bKnockedOut);
                                                        logger.WriteLine(DateTime.Today + " " +
                                                                         stopwatch.ElapsedMilliseconds +
                                                                         "ms SYSTEM New target found | {" +
                                                                         Json.Serialize(newTarget) + "}");
                                                        break;
                                                    case "Blessing,StatBuff":
                                                    case "Blessing,Shield":
                                                        // find new target on this character's team that is NOT this character
                                                        newTarget =
                                                            globalCharacters.OrderBy(x => Guid.NewGuid())
                                                                .FirstOrDefault(
                                                                    x =>
                                                                        x.Guild_FK == currChar.Guild_FK &&
                                                                        !FavoredSkillFavoredTargets.Exists(
                                                                            y => y.Character_PK == x.Character_PK) &&
                                                                        !x.Conditions.bInvisible &&
                                                                        !x.Conditions.bKnockedOut &&
                                                                        x.Character_PK != currChar.Character_PK);
                                                        logger.WriteLine(DateTime.Today + " " +
                                                                         stopwatch.ElapsedMilliseconds +
                                                                         "ms SYSTEM New target found | {" +
                                                                         Json.Serialize(newTarget) + "}");
                                                        break;
                                                }

                                                if (FavoredSkill.Skill_Type.Contains("Guard"))
                                                {
                                                    newTarget =
                                                        globalCharacters.OrderBy(x => Guid.NewGuid())
                                                            .FirstOrDefault(
                                                                x =>
                                                                    x.Guild_FK == currChar.Guild_FK &&
                                                                    !FavoredSkillFavoredTargets.Exists(
                                                                        y => y.Character_PK == x.Character_PK) &&
                                                                    !x.Conditions.bInvisible &&
                                                                    !x.Conditions.bKnockedOut &&
                                                                    x.Character_PK != currChar.Character_PK);
                                                    logger.WriteLine(DateTime.Today + " " +
                                                                     stopwatch.ElapsedMilliseconds +
                                                                     "ms SYSTEM New target found | {" +
                                                                     Json.Serialize(newTarget) + "}");
                                                }

                                                // ensure a target was found, then add it
                                                if (newTarget != null)
                                                {
                                                    if (newTarget.Character_PK != 0)
                                                    {
                                                        logger.WriteLine(DateTime.Today + " " +
                                                                         stopwatch.ElapsedMilliseconds +
                                                                         "ms SYSTEM adding new target to favored targets | " +
                                                                         Json.Serialize(newTarget));
                                                        FavoredSkillFavoredTargets.Add(newTarget);
                                                    }
                                                }
                                            }
                                        }

                                        // if character is Charmed
                                        if (currChar.Conditions.bCharmed)
                                        {
                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM target is charmed, reassign target to random ally");

                                            // remove old target from target list
                                            FavoredSkillFavoredTargets.Remove(target);
                                            Character newTarget = new Character();

                                            // assign new target to random ally
                                            newTarget = globalCharacters.OrderBy(x => Guid.NewGuid()).FirstOrDefault(x => x.Guild_FK == currChar.Guild_FK && currChar.Conditions.Charm_Character_PK != x.Character_PK && !FavoredSkillFavoredTargets.Exists(y => y.Character_PK == x.Character_PK && x.Conditions.bInvisible && x.Conditions.bKnockedOut));

                                            // ensure a target was found, then add it
                                            if (newTarget != null)
                                            {
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM target acquired, add to favored targets | newTarget:" + Json.Serialize(newTarget));
                                                FavoredSkillFavoredTargets.Add(newTarget);
                                            }
                                        }

                                        // if character is Taunted - ignore Blessing, Heal, and Guard skill types when Taunted
                                        if (currChar.Conditions.bTaunted &&
                                            FavoredSkill.Max_Targets < 12 &&
                                            !FavoredSkill.Skill_Type.Contains("Blessing") &&
                                            !FavoredSkill.Skill_Type.Contains("Heal") &&
                                            !FavoredSkill.Skill_Type.Contains("Guard"))
                                        {
                                            // ensure taunter is still a legal target - otherwise maintain favored targets
                                            Boolean bTaunterTargettable = globalCharacters.Contains(globalCharacters.FirstOrDefault(x =>
                                                            x.Character_PK == currChar.Conditions.Taunted_Character_PK &&
                                                            !x.Conditions.bInvisible &&
                                                            !x.Conditions.bKnockedOut));

                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM character is taunted, reassign target to taunter if able | TaunterCharPK:" + target.Conditions.Taunted_Character_PK + " | bTaunterTargettable:" + bTaunterTargettable);

                                            if (bTaunterTargettable)
                                            {
                                                // remove old target from target list
                                                FavoredSkillFavoredTargets.Remove(target);
                                                Character newTarget = new Character();

                                                // assign new target to taunter
                                                newTarget = globalCharacters.FirstOrDefault(x => x.Character_PK == currChar.Conditions.Taunted_Character_PK);

                                                // ensure a target was found, then add it
                                                if (newTarget != null)
                                                {
                                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM taunter is targettable, add to favored targets | newTarget:{" + Json.Serialize(newTarget) + "}");
                                                    FavoredSkillFavoredTargets.Add(newTarget);
                                                }
                                            }
                                        }

                                        // if character is Blinded
                                        if (currChar.Conditions.bBlinded)
                                        {
                                            Character newTarget = new Character();
                                            if (FavoredSkill.Skill_Type.Contains("Guard"))
                                            {
                                                // blinded character is attempting to guard, must reassign to random ally
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM character is blinded and attempting to guard, reassign target to random ally");

                                                // remove old target from target list
                                                FavoredSkillFavoredTargets.Remove(target);

                                                // assign new target to random character (even ally)
                                                newTarget = globalCharacters.OrderBy(x => Guid.NewGuid()).FirstOrDefault(x => x.Guild_FK == currChar.Guild_FK && !x.Conditions.bInvisible && !x.Conditions.bKnockedOut && x.Character_PK != currChar.Character_PK);
                                            }
                                            else
                                            {
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM character is blinded, reassign target to random character");

                                                // remove old target from target list
                                                FavoredSkillFavoredTargets.Remove(target);

                                                // assign new target to random character (even ally)
                                                newTarget = globalCharacters.OrderBy(x => Guid.NewGuid()).FirstOrDefault(x => !x.Conditions.bInvisible && !x.Conditions.bKnockedOut && x.Character_PK != currChar.Character_PK);
                                            }
                                            // ensure a target was found, then add it
                                            if (newTarget != null)
                                            {
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM target acquired, add to favored targets | newTarget:{" + Json.Serialize(newTarget) + "}");
                                                FavoredSkillFavoredTargets.Add(newTarget);
                                            }
                                            else
                                            {
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM no new target could be found");
                                            }
                                        }

                                        // if target is Guarded - ignore Blessing, Heal, and Guard skill types when Guarded
                                        if (target.Conditions.bGuarded &&
                                            !FavoredSkill.Skill_Type.Contains("Blessing") &&
                                            !FavoredSkill.Skill_Type.Contains("Heal") &&
                                            !FavoredSkill.Skill_Type.Contains("Guard"))
                                        {
                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM target is guarded, reassign target to guard character");

                                            // remove old target from target list
                                            FavoredSkillFavoredTargets.Remove(target);
                                            Character newTarget = new Character();

                                            // assign new target to guard
                                            newTarget = globalCharacters.FirstOrDefault(x => x.Character_PK == target.Conditions.Guarded_Characters_PK.OrderByDescending(y => y).FirstOrDefault());

                                            // ensure a target was found, then add it
                                            if (newTarget != null)
                                            {
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM target acquired, add to favored targets | newTarget:{" + Json.Serialize(newTarget) + "}");
                                                FavoredSkillFavoredTargets.Add(newTarget);
                                            }
                                        }
                                    }

                                    // ensure at least one target exists after validation, unless skill is a prepared skill
                                    if (FavoredSkillFavoredTargets.Count == 0)
                                    {
                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM no valid targets available - end the turn");
                                        currTrackStep = lastTrackStep;
                                    }
                                    break;
                                case 7:
                                    // 7 - special character skills
                                    CheckSpecialSkills();
                                    break;
                                #endregion
                                #region PERFORM ATTACK ROLL
                                case 8:
                                    // 8 - determine if skill instantly resolves

                                    // skip this step if skill is hostile and won't instantly resolve
                                    if (!FavoredSkill.Skill_Type.Contains("Blessing") &&
                                        !FavoredSkill.Skill_Type.Contains("Guard"))
                                        continue;

                                    var bEndTheTurn = false;

                                    foreach (var target in FavoredSkillFavoredTargets)
                                    {
                                        Combat_Log newCombatLogEntry = new Combat_Log();
                                        newCombatLogEntry.Action_Order = currAct.Act_Order;
                                        //newCombatLogEntry.Conditions
                                        newCombatLogEntry.Assailant_Character_FK = currChar.Character_PK;
                                        newCombatLogEntry.Skill_FK = FavoredSkill.Skill_PK;
                                        newCombatLogEntry.Target_Character_FK = target.Character_PK;
                                        newCombatLogEntry.Skirmish_FK = skirmish.Skirmish_PK;
                                        newCombatLogEntry.tmpDamage_Final_Result = new List<int>();
                                        newCombatLogEntry.Skirmish_FK = skirmish.Skirmish_PK;

                                        switch (FavoredSkill.Skill_Type)
                                        {
                                            case "Blessing,Advantage":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Advantage on [" + target.Character_Name + "]");
                                                target.Conditions.bAttackAdvantage = true;

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Stat_Buff", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,Disadvantage":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Disadvantage on [" + target.Character_Name + "]");
                                                target.Conditions.bDefendAdvantage = true;

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Stat_Buff", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,Shield":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Shield(" + FavoredSkill.Damage_Roll + ") on [" + target.Character_Name + "]");
                                                target.Conditions.bShielded = true;
                                                target.Conditions.Shield += Int32.Parse(FavoredSkill.Damage_Roll);
                                                target.Conditions.Shield_Enchanters_Character_PK.Add(currChar.Character_PK);

                                                newCombatLogEntry.Damage_Final_Result = Int32.Parse(FavoredSkill.Damage_Roll);

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Bestow", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,Damage":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Damage(" + FavoredSkill.Damage_Roll + ") on [" + target.Character_Name + "]");
                                                target.Conditions.bDamageBonus = true;
                                                target.Conditions.DamageBonus += Int32.Parse(FavoredSkill.Damage_Roll);
                                                target.Conditions.DamageBonus_Enchanters_Character_PK.Add(currChar.Character_PK);

                                                newCombatLogEntry.Damage_Final_Result = Int32.Parse(FavoredSkill.Damage_Roll);

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Bestow", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,AllStats":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,AllStats(" + FavoredSkill.Damage_Roll + ") on [" + target.Character_Name + "]");
                                                target.Finesse += Int32.Parse(FavoredSkill.Damage_Roll);
                                                target.Agility += Int32.Parse(FavoredSkill.Damage_Roll);
                                                target.Senses += Int32.Parse(FavoredSkill.Damage_Roll);
                                                target.Mana += Int32.Parse(FavoredSkill.Damage_Roll);
                                                target.Dodge += Int32.Parse(FavoredSkill.Damage_Roll);

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Stat_Buff", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,Finesse":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Finesse(" + FavoredSkill.Damage_Roll + ") on [" + target.Character_Name + "]");
                                                target.Finesse += Int32.Parse(FavoredSkill.Damage_Roll);

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Stat_Buff", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,Agility":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Agility(" + FavoredSkill.Damage_Roll + ") on [" + target.Character_Name + "]");
                                                target.Agility += Int32.Parse(FavoredSkill.Damage_Roll);

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Stat_Buff", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,Senses":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Senses(" + FavoredSkill.Damage_Roll + ") on [" + target.Character_Name + "]");
                                                target.Senses += Int32.Parse(FavoredSkill.Damage_Roll);

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Stat_Buff", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,Mana":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Mana(" + FavoredSkill.Damage_Roll + ") on [" + target.Character_Name + "]");
                                                target.Mana += Int32.Parse(FavoredSkill.Damage_Roll);

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Stat_Buff", 1);
                                                bEndTheTurn = true;
                                                break;
                                            case "Blessing,Dodge":
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM casting Blessing,Dodge(" + FavoredSkill.Damage_Roll + ") on [" + target.Character_Name + "]");
                                                target.Dodge += Int32.Parse(FavoredSkill.Damage_Roll);

                                                // record accolade
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Blessing_Stat_Buff", 1);
                                                bEndTheTurn = true;
                                                break;
                                        }

                                        // dynamic skill types
                                        if (FavoredSkill.Skill_Type.Contains("Guard"))
                                        {
                                            // determine how many guard this character can perform
                                            var amtOfGuard = Int32.Parse(FavoredSkill.Skill_Type.Split(',')[1]);

                                            for (var i = 1; i <= amtOfGuard; i++)
                                            {
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM guarding [" + target.Character_Name + "]");
                                                target.Conditions.bGuarded = true;
                                                target.Conditions.Guarded_Characters_PK.Add(currChar.Character_PK);
                                            }
                                            bEndTheTurn = true;
                                        }

                                        // record entry
                                        globalCombatLog.Add(newCombatLogEntry);
                                    }

                                    // end the turn
                                    if (bEndTheTurn) currTrackStep = lastTrackStep;
                                    break;
                                case 9:
                                    // 9 - determine if attack is rolled with advantage or disadvantage
                                    // REMOVE THIS TRACK STEP
                                    break;
                                case 10:
                                    // 10 - roll attack dice for attack and add base modifier

                                    // loop through all targets and perform attacks
                                    foreach (var target in FavoredSkillFavoredTargets)
                                    {
                                        // create new combat log entry
                                        Combat_Log newCombatLogEntry = new Combat_Log();
                                        newCombatLogEntry.Action_Order = globalInitTrack.FirstOrDefault(x => x.Character_FK == currChar.Character_PK).Act_Order;
                                        //newCombatLogEntry.Conditions
                                        newCombatLogEntry.Assailant_Character_FK = currChar.Character_PK;
                                        newCombatLogEntry.Skill_FK = FavoredSkill.Skill_PK;
                                        newCombatLogEntry.Target_Character_FK = target.Character_PK;
                                        newCombatLogEntry.Skirmish_FK = skirmish.Skirmish_PK;
                                        newCombatLogEntry.tmpDamage_Final_Result = new List<int>();

                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM preliminary attack calculation | (bAttackAdvantage:" + currChar.Conditions.bAttackAdvantage + " | bAttackDisadvantage:" + currChar.Conditions.bAttackDisadvantage + ") | TARGET (bAttackAdvantage:" + target.Conditions.bAttackAdvantage + " | bAttackDisadvantage:" + target.Conditions.bAttackDisadvantage + ")");
                                        if (currChar.Conditions.bAttackAdvantage || currChar.Conditions.bAttackDisadvantage)
                                        {
                                            var finalAdvDis = 0; // 0 = roll normally. -1 = roll disadvantage. 1 = roll advantage

                                            if (currChar.Conditions.bAttackAdvantage) finalAdvDis++;
                                            if (currChar.Conditions.bAttackDisadvantage) finalAdvDis--;
                                            if (target.Conditions.bDefendAdvantage) finalAdvDis++;
                                            if (target.Conditions.bDefendDisadvantage) finalAdvDis--;

                                            // determine final result (coded this way because character could have both advantage & disadvantage)
                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM final preliminary attack calculation | finalAdvDis:" + finalAdvDis);

                                            if (finalAdvDis == 0)
                                            {
                                                currChar.Conditions.bAttackAdvantage = false;
                                                currChar.Conditions.bAttackDisadvantage = false;
                                            }
                                            else if (finalAdvDis > 0)
                                            {
                                                currChar.Conditions.bAttackAdvantage = true;
                                                currChar.Conditions.bAttackDisadvantage = false;
                                            }
                                            else if (finalAdvDis < 0)
                                            {
                                                currChar.Conditions.bAttackAdvantage = false;
                                                currChar.Conditions.bAttackDisadvantage = true;
                                            }
                                        }

                                        // don't roll if the attack is auto successful or the skill is a heal
                                        if (!FavoredSkill.bAutoSuccess)
                                        {
                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM rolling attack against [" + target.Character_Name + "] ...");

                                            // perform roll with a d20
                                            Int32 rollDiceRoll = 0;

                                            // reroll if character has advantage or disadvantage
                                            if (currChar.Conditions.bAttackAdvantage)
                                            {
                                                // perform roll with two d20's, taking the higher roll
                                                Int32 rollDiceReroll = rand.Next(1, 21);

                                                // record roll data
                                                newCombatLogEntry.Attack_Values = rollDiceRoll + "," + rollDiceReroll;

                                                if (rollDiceReroll > rollDiceRoll) rollDiceRoll = rollDiceReroll;
                                            }
                                            else if (currChar.Conditions.bAttackDisadvantage)
                                            {
                                                // perform roll with two d20's, taking the lower roll
                                                Int32 rollDiceReroll = rand.Next(1, 21);

                                                // record roll data
                                                newCombatLogEntry.Attack_Values = rollDiceRoll + "," + rollDiceReroll;

                                                if (rollDiceReroll < rollDiceRoll) rollDiceRoll = rollDiceReroll;
                                            }
                                            else
                                            {
                                                // perform roll with a d20
                                                rollDiceRoll = rand.Next(1, 21);

                                                // record roll data
                                                newCombatLogEntry.Attack_Values = rollDiceRoll.ToString();
                                            }

                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM roll(s) achieved | Attack_Values:" +
                                                             newCombatLogEntry.Attack_Values);

                                            // record accolades
                                            if (rollDiceRoll == 1)
                                            {
                                                // critical failure achieved
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Critical_Fails", 1);
                                            }
                                            else if (rollDiceRoll == 20)
                                            {
                                                // critical success achieved
                                                UpdateCharacterTrackLog(currChar.Character_PK, "Critical_Successes", 1);
                                            }

                                            // add base modifiers
                                            switch (FavoredSkill.Attribute_FK)
                                            {
                                                case "Finesse":
                                                    rollDiceRoll += currChar.Finesse;
                                                    break;
                                                case "Agility":
                                                    rollDiceRoll += currChar.Agility;
                                                    break;
                                                case "Senses":
                                                    rollDiceRoll += currChar.Senses;
                                                    break;
                                                case "Mana":
                                                    rollDiceRoll += currChar.Mana;
                                                    break;
                                            }

                                            // record roll result
                                            newCombatLogEntry.Attack_Final_Result = rollDiceRoll;
                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM final attack result with modifier[" +
                                                             FavoredSkill.Attribute_FK + "] | Attack_Final_Result:" +
                                                             rollDiceRoll);
                                        }

                                        // record new combat log
                                        globalCombatLog.Add(newCombatLogEntry);

                                        // check for special character skills after rolling attack
                                        CheckSpecialSkills();
                                    }
                                    break;
                                #endregion
                                #region PERFORM DAMAGE ROLL
                                case 11:
                                    // 11 - determine if attacks are successful and determine damage

                                    // get combat logs regarding this character performed favored skill - it is possible this attack targets multiple targets
                                    var relativeAttackCombatLogs = globalCombatLog.Where(x => x.Action_Order == globalInitTrack.FirstOrDefault(y => y.Character_FK == currChar.Character_PK).Act_Order && !x.bInterrupt);

                                    foreach (var log in relativeAttackCombatLogs)
                                    {
                                        Character targetChar = GetCharacter(log.Target_Character_FK);

                                        // determine if attack is successful
                                        logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM calculating if attack was successful ... | Attack_Final_Result:" + log.Attack_Final_Result + " | Target's Dodge:" + targetChar.Dodge + " | bAutoSuccess:" + FavoredSkill.bAutoSuccess);
                                        log.bAttackSuccessful = (log.Attack_Final_Result >= targetChar.Dodge || FavoredSkill.bAutoSuccess);
                                        if (log.bAttackSuccessful)
                                        {
                                            // attack is successful - roll damage
                                            List<string> rollArray = FavoredSkill.Damage_Roll.Split(',').ToList();
                                            List<int> damageRolls = new List<int>(); // stores all damage rolls

                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds +
                                                             "ms SYSTEM attack successful, rolling damage ...");
                                            foreach (var roll in rollArray)
                                            {
                                                if (roll == "0d0+0")
                                                {
                                                    // don't perform a real roll on 0d0+0
                                                    log.tmpDamage_Final_Result.Add(0);
                                                    log.Damage_Types = FavoredSkill.Damage_Types;
                                                    continue;
                                                }
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds +
                                                                 "ms SYSTEM rolling [" + roll + "]");
                                                string rollSet = roll.Substring(0, roll.IndexOf("+"));
                                                    // extract "XdX" from "XdX+X"
                                                Int32 rollDiceAmt =
                                                    Int32.Parse(rollSet.Substring(0, rollSet.IndexOf("d")));
                                                Int32 rollDiceType =
                                                    Int32.Parse(rollSet.Substring(rollSet.IndexOf("d") + 1));
                                                Int32 rollModifier = Int32.Parse(roll.Substring(roll.IndexOf("+") + 1));
                                                    // extract "+X" from "XdX+X"
                                                Int32 rollFinalResult = 0;

                                                // roll dice for each amount required
                                                for (var x = 1; x <= rollDiceAmt; x++)
                                                {
                                                    Int32 rollResult = rand.Next(1, rollDiceType + 1);

                                                    // record damage roll
                                                    damageRolls.Add(rollResult);

                                                    // accumulate results
                                                    rollFinalResult += rollResult;
                                                }

                                                // add modifiers
                                                switch (FavoredSkill.Attribute_FK)
                                                {
                                                    case "Finesse":
                                                        rollFinalResult += currChar.Finesse;
                                                        break;
                                                    case "Agility":
                                                        rollFinalResult += currChar.Agility;
                                                        break;
                                                    case "Senses":
                                                        rollFinalResult += currChar.Senses;
                                                        break;
                                                    case "Mana":
                                                        rollFinalResult += currChar.Mana;
                                                        break;
                                                }
                                                rollFinalResult += rollModifier;

                                                log.tmpDamage_Final_Result.Add(rollFinalResult);
                                                log.Damage_Types = FavoredSkill.Damage_Types;

                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds +
                                                                 "ms SYSTEM final damage calculation | Damage_Final_Result:" +
                                                                 rollFinalResult + " | Damage_Types:" +
                                                                 FavoredSkill.Damage_Types);
                                            }

                                            // THIS IS PERFORMED IN STEP 13
                                            // check if character has pending bonus damage
                                            //if (currChar.Conditions.bDamageBonus)
                                            //{
                                            //    log.Damage_Final_Result += currChar.Conditions.DamageBonus;
                                            //    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM bonus damage awarded | DamageBonus:" + currChar.Conditions.DamageBonus);
                                            //    foreach (var enchanter in currChar.Conditions.DamageBonus_Enchanters_Character_PK)
                                            //    {
                                            //        // award each enchanter bonus accolades on how much bonus damage current character was granted
                                            //        var enchantSkill = globalCombatLog.FirstOrDefault(x => x.Target_Character_FK == currChar.Character_PK && x.Assailant_Character_FK == enchanter).Skill_FK;

                                            //        UpdateCharacterTrackLog(enchanter, "Blessing_Bonus_Damage", Int32.Parse(globalSkills.FirstOrDefault(x => x.Skill_PK == enchantSkill).Damage_Roll));
                                            //    }

                                            //    // clear out damage bonus
                                            //    currChar.Conditions.bDamageBonus
                                            //}
                                        }
                                        else
                                        {
                                            // target dodged attack
                                            UpdateCharacterTrackLog(targetChar.Character_PK, "Attacks_Dodged", 1);
                                        }
                                    }
                                    break;
                                case 12:
                                    // 12 - special character skills (pre-damage)
                                    CheckSpecialSkills();
                                    break;
                                case 13:
                                    // 13 - inflict damage on target

                                    // get combat logs regarding this character performed favored skill - it is possible this attack targets multiple targets
                                    var relativeDamageCombatLogs = globalCombatLog.Where(x => x.Action_Order == currAct.Act_Order && x.bAttackSuccessful);

                                    foreach (var log in relativeDamageCombatLogs)
                                    {
                                        List<int> tmpDamageResults = log.tmpDamage_Final_Result;
                                        List<int> tmpDamageValues = new List<int>();
                                        List<string> tmpDamageTypes = log.Damage_Types.Split(',').ToList();
                                        Character target = GetCharacter(log.Target_Character_FK);
                                        Character assailant = GetCharacter(log.Assailant_Character_FK);
                                        Int32 overallDamageResult = 0;

                                        foreach (var dmgRoll in tmpDamageResults)
                                        {
                                            var finalDamageResult = dmgRoll;

                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM inflict damage on target | finalDamageResult:" + dmgRoll + " | Vulnerabilities:[" + target.Vulnerabilities + "] | Resistances:[" + target.Resistances + "] | Immunities:[" + target.Immunities + "] | " + Json.Serialize(target));

                                            if (target.Vulnerabilities != null)
                                            {
                                                // consider target vulnerabilities
                                                List<string> vulnerabilities = target.Vulnerabilities.Split(',').ToList();
                                                var bVulnerableToAttack = vulnerabilities.Exists(x => x == tmpDamageTypes[tmpDamageResults.IndexOf(dmgRoll)]);

                                                // target is vulnerable to damage - deal double damage
                                                if (bVulnerableToAttack) finalDamageResult += dmgRoll;
                                            }

                                            if (target.Resistances != null)
                                            {
                                                // consider target resistances
                                                List<string> resistances = target.Resistances.Split(',').ToList();
                                                var bResistantToAttack = resistances.Exists(x => x == tmpDamageTypes[tmpDamageResults.IndexOf(dmgRoll)]);

                                                // target is resistance to damage - deal half damage, rounded up
                                                if (bResistantToAttack) finalDamageResult -= (int)Math.Ceiling((double)dmgRoll / 2);
                                            }

                                            if (target.Immunities != null)
                                            {
                                                // consider target immunities
                                                List<string> immunities = target.Immunities.Split(',').ToList();
                                                var bImmuneToAttack = immunities.Exists(x => x == tmpDamageTypes[tmpDamageResults.IndexOf(dmgRoll)]);

                                                // target is immune to damage - negate all damage
                                                if (bImmuneToAttack) finalDamageResult = 0;
                                            }

                                            // inflict damage on target
                                            if (FavoredSkill.Skill_Type != "Heal")
                                            {
                                                // check for bonus damage
                                                if (assailant.Conditions.bDamageBonus)
                                                {
                                                    foreach (var enchanter in assailant.Conditions.DamageBonus_Enchanters_Character_PK.OrderByDescending(x => x))
                                                    {
                                                        // find relative combat log
                                                        var relativeCombatLog = globalCombatLog.FirstOrDefault(x => x.Target_Character_FK == assailant.Character_PK && x.Assailant_Character_FK == enchanter);
                                                        // determine how much damage bonus enchanter granted
                                                        Int32 grantedBonusDamage = Int32.Parse(globalSkills.FirstOrDefault(x => x.Skill_PK == relativeCombatLog.Skill_FK).Damage_Roll);

                                                        // buff damage
                                                        finalDamageResult += grantedBonusDamage;

                                                        tmpDamageValues.Add(grantedBonusDamage);
                                                        log.Damage_Types += ",True";

                                                        // record accolades
                                                        UpdateCharacterTrackLog(enchanter, "Blessing_Bonus_Damage", grantedBonusDamage);
                                                    }
                                                    // clear out character bonus damage
                                                    assailant.Conditions.bDamageBonus = false;
                                                    assailant.Conditions.DamageBonus = 0;
                                                    assailant.Conditions.DamageBonus_Enchanters_Character_PK.Clear();
                                                }

                                                // skill type inflicts damage
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM [" + target.Character_Name + "] taking " + finalDamageResult + " " + tmpDamageTypes[tmpDamageResults.IndexOf(dmgRoll)] + " damage");

                                                // check for shield
                                                if (target.Conditions.bShielded)
                                                {
                                                    target.Conditions.Shield -= finalDamageResult;

                                                    if (target.Conditions.Shield < 0)
                                                    {
                                                        target.TakeDamage(target.Conditions.Shield * -1);
                                                        target.Conditions.Shield = 0;
                                                        target.Conditions.bShielded = false;
                                                        target.Conditions.Shield_Enchanters_Character_PK.Clear();
                                                    }

                                                    // record accolades for enchanter who granted shield
                                                    var tmpAttackDmg = finalDamageResult;
                                                    foreach (var enchanter in target.Conditions.Shield_Enchanters_Character_PK.OrderByDescending(x => x))
                                                    {
                                                        // find relative combat log where enchanter shielded target
                                                        var relativeCombatLog = globalCombatLog.FirstOrDefault(x => x.Target_Character_FK == target.Character_PK && x.Assailant_Character_FK == enchanter);

                                                        // determine how much shield the enchanter provided
                                                        Int32 shieldAmtGranted = Int32.Parse(globalSkills.FirstOrDefault(x => x.Skill_PK == relativeCombatLog.Skill_FK).Damage_Roll);

                                                        // accumulate how much damage the target has taken prior to this attack
                                                        int previousDamage = globalCombatLog.Where(x => x.Target_Character_FK == target.Character_PK && x.Action_Order < currAct.Act_Order).Sum(x => x.Damage_Final_Result);

                                                        // perform calculations
                                                        tmpAttackDmg -= (shieldAmtGranted - previousDamage);
                                                        if (tmpAttackDmg > 0)
                                                        {
                                                            if (GetCharacter(enchanter).Archetype.Contains("Enchanter") || GetCharacter(enchanter).Archetype.Contains("Hunter"))
                                                                UpdateCharacterTrackLog(enchanter, "Blessing_Shield_Absorb", shieldAmtGranted);
                                                            // shield did not absorb all damage
                                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM [" + globalCharacters.FirstOrDefault(x => x.Character_PK == enchanter).Character_Name + "] shielded [" + target.Character_Name + "] for " + shieldAmtGranted + " damage");
                                                            target.Conditions.Shield_Enchanters_Character_PK.Remove(enchanter);
                                                        }
                                                        else
                                                        {
                                                            if (GetCharacter(enchanter).Archetype.Contains("Enchanter") || GetCharacter(enchanter).Archetype.Contains("Hunter"))
                                                                UpdateCharacterTrackLog(enchanter, "Blessing_Shield_Absorb", finalDamageResult);
                                                            // shield absorbed all damage
                                                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM [" + globalCharacters.FirstOrDefault(x => x.Character_PK == enchanter).Character_Name + "] shielded [" + target.Character_Name + "] for " + finalDamageResult + " damage");
                                                            break;
                                                        }
                                                    }

                                                    // reduce total shield
                                                    target.Conditions.Shield -= tmpAttackDmg;
                                                    if (target.Conditions.Shield <= 0)
                                                    {
                                                        // clear out shield data if reduced to 0
                                                        target.Conditions.Shield = 0;
                                                        target.Conditions.bShielded = false;
                                                        target.Conditions.Shield_Enchanters_Character_PK.Clear();
                                                    }

                                                    // take damage if remaining damage after shield calculations
                                                    if (tmpAttackDmg > 0)
                                                    {
                                                        target.TakeDamage(finalDamageResult);
                                                    }
                                                }
                                                else
                                                {
                                                    // take damage
                                                    target.TakeDamage(finalDamageResult);
                                                }
                                            }
                                            else
                                            {
                                                // skill type heals health
                                                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM [" + target.Character_Name + "] healing (" + finalDamageResult + ") health");
                                                target.Heal(finalDamageResult);
                                            }

                                            // accumulate overall damage for combat log
                                            overallDamageResult += finalDamageResult;
                                            tmpDamageValues.Add(finalDamageResult);
                                        }

                                        // record overall damage
                                        log.Damage_Final_Result = overallDamageResult;
                                        log.Damage_Values = tmpDamageValues.ToJson();

                                        // record accolade
                                        if (target.Conditions.bKnockedOut)
                                        {
                                            UpdateCharacterTrackLog(assailant.Character_PK, "Opponent_Knock_Outs", 1);
                                            List<Character> Accolade_Assist_Awarded = new List<Character>();
                                            foreach (var assistant in globalCombatLog.Where(x => x.Target_Character_FK == target.Character_PK && x.Damage_Final_Result > 0 && x.Damage_Types != null && !x.Damage_Types.Contains("Healing") && x.Assailant_Character_FK != assailant.Character_PK))
                                            {
                                                if (!Accolade_Assist_Awarded.Exists(x => x.Character_PK == assistant.Assailant_Character_FK))
                                                {
                                                    UpdateCharacterTrackLog(assistant.Assailant_Character_FK, "Assist_Knock_Outs", 1);
                                                    Accolade_Assist_Awarded.Add(GetCharacter(assistant.Assailant_Character_FK));
                                                }

                                            }
                                        }
                                    }
                                    break;
                                case 14:
                                    // 14 - special character skills (post-damage)
                                    CheckSpecialSkills();
                                    break;
                                #endregion
                                #region TARGET CONDITIONS
                                case 15:
                                    // 15 - determine if target receives any afflictions

                                    // get combat logs regarding this character performed favored skill - it is possible this attack targets multiple targets
                                    var relativeConditionCombatLogs = globalCombatLog.Where(x => x.Action_Order == globalInitTrack.FirstOrDefault(y => y.Character_FK == currChar.Character_PK).Act_Order);

                                    foreach (var log in relativeConditionCombatLogs)
                                    {
                                        // ignore passives that interrupted current action when inflicting conditions
                                        if (log.bInterrupt) continue;

                                        Character targetChar = GetCharacter(log.Target_Character_FK);

                                        // determine conditions if attack was successful
                                        if (log.bAttackSuccessful)
                                        {
                                            bool bSpecialRuleInflictCondition = true;

                                            // skill requires a minimum attack result to inflict condition
                                            if (FavoredSkill.Special_Min_Roll != null)
                                            {
                                                // check if minimum result required was met
                                                // IMPORTANT - always inflict condition if min roll equals 0
                                                if (log.Attack_Final_Result < FavoredSkill.Special_Min_Roll && FavoredSkill.Special_Min_Roll != 0) bSpecialRuleInflictCondition = false;
                                            }

                                            if (bSpecialRuleInflictCondition)
                                            {
                                                // inflict afflictions
                                                if (FavoredSkill.Skill_Type.Contains("Affliction"))
                                                {
                                                    var affliction = FavoredSkill.Skill_Type.Substring(FavoredSkill.Skill_Type.IndexOf(',') + 1);

                                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM inflict Affliction(" + affliction + ") on target ");

                                                    switch (affliction)
                                                    {
                                                        case "Stunned":
                                                            targetChar.Conditions.bStunned = true;
                                                            log.Conditions = 1;
                                                            break;
                                                        case "Blinded":
                                                            targetChar.Conditions.bBlinded = true;
                                                            log.Conditions = 2;
                                                            break;
                                                        case "Charmed":
                                                            targetChar.Conditions.bCharmed = true;
                                                            log.Conditions = 6;
                                                            targetChar.Conditions.Charm_Character_PK = currChar.Character_PK;
                                                            break;
                                                    }

                                                    // dynamic afflictions
                                                    if (affliction.Contains("AllStats") || affliction.Contains("Finesse") ||
                                                        affliction.Contains("Agility") || affliction.Contains("Senses") ||
                                                        affliction.Contains("Mana") || affliction.Contains("Dodge"))
                                                    {
                                                        var debuff = affliction.Split('-'); // [0] = type | [1] = amount

                                                        switch (debuff[0])
                                                        {
                                                            case "AllStats":
                                                                targetChar.Finesse -= Int32.Parse(debuff[1]);
                                                                targetChar.Agility -= Int32.Parse(debuff[1]);
                                                                targetChar.Senses -= Int32.Parse(debuff[1]);
                                                                targetChar.Mana -= Int32.Parse(debuff[1]);
                                                                targetChar.Dodge -= Int32.Parse(debuff[1]);
                                                                break;
                                                            case "Finesse":
                                                                targetChar.Finesse -= Int32.Parse(debuff[1]);
                                                                break;
                                                            case "Agility":
                                                                targetChar.Agility -= Int32.Parse(debuff[1]);
                                                                break;
                                                            case "Senses":
                                                                targetChar.Senses -= Int32.Parse(debuff[1]);
                                                                break;
                                                            case "Mana":
                                                                targetChar.Mana -= Int32.Parse(debuff[1]);
                                                                break;
                                                            case "Dodge":
                                                                targetChar.Dodge -= Int32.Parse(debuff[1]);
                                                                break;
                                                        }

                                                        // ensure no stat goes below 0
                                                        if (targetChar.Finesse < 0) targetChar.Finesse = 0;
                                                        if (targetChar.Agility < 0) targetChar.Agility = 0;
                                                        if (targetChar.Senses < 0) targetChar.Senses = 0;
                                                        if (targetChar.Mana < 0) targetChar.Mana = 0;
                                                        if (targetChar.Dodge < 0) targetChar.Dodge = 0;
                                                    }

                                                    // record accolade
                                                    if(currChar.Archetype.Contains("Enchanter") || currChar.Archetype.Contains("Hunter"))
                                                        UpdateCharacterTrackLog(currChar.Character_PK, "Afflictions_Inflicted", 1);
                                                }

                                                // inflict taunt
                                                if (FavoredSkill.Skill_Type == "Taunt")
                                                {
                                                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM inflict Taunt on [" + targetChar.Character_Name + "]");
                                                    targetChar.Conditions.bTaunted = true;
                                                    targetChar.Conditions.Taunted_Character_PK = currChar.Character_PK;
                                                    log.Conditions = 8;
                                                }
                                            }
                                        }
                                    }
                                    break;
                                case 16:
                                    //// 16 - check if skill can perform multiple attacks
                                    //if (FavoredSkill.Skill_Type.Contains("MultiAttack"))
                                    //{
                                    //    var relativeCombatLog = globalCombatLog.FirstOrDefault(x => x.Assailant_Character_FK == currChar.Character_PK && x.Skill_FK == FavoredSkill.Skill_PK);

                                    //    // perform another turn if attack was successful or attack result equals or exceeds minimum roll required
                                    //    if(relativeCombatLog.bAttackSuccessful && (relativeCombatLog.Attack_Final_Result > FavoredSkill.Special_Min_Roll || FavoredSkill.Special_Min_Roll == 0))
                                    //        currTrackStep = 1;

                                    //    // EXCEPTION
                                    //    // Cannot perform additional turns if skill type is a single target multi attack and the target has been knocked out
                                    //    if (FavoredSkill.Skill_Type == "MultiAttack,Single" &&
                                    //        globalCharacters.FirstOrDefault(
                                    //            x => x.Character_PK == relativeCombatLog.Target_Character_FK)
                                    //            .Conditions.bKnockedOut)
                                    //        currTrackStep = 16;
                                    //}
                                    break;
                                case 17:
                                    // 17 - special character skills
                                    CheckSpecialSkills();
                                    break;
                                #endregion
                            }

                            logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms END TRACK STEP [" + currTrackStep + "] for [" + currChar.Character_Name + "]");
                        }
                        #endregion
                    }
                    #region COMBAT LOG MANAGEMENT
                    // push combat log to server
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Push combat log to server ...");
                    controller.CreateCombatLogForSkirmish(globalCombatLog);
                    #endregion
                    #region ACCOLADE MANAGEMENT
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Recording character accolades ...");
                    foreach (var log in globalCombatLog)
                    {
                        Skill performedSkill = globalSkills.FirstOrDefault(x => x.Skill_PK == log.Skill_FK);
                        Character assailantCharacter = globalCharacters.FirstOrDefault(x => x.Character_PK == log.Assailant_Character_FK);
                        Character targetCharacter = globalCharacters.FirstOrDefault(x => x.Character_PK == log.Target_Character_FK);
                        switch (performedSkill.Skill_Type)
                        {
                            // special skills need to track accolades in their own way
                            case "Taunt":
                            case "Affliction,Disadvantage":
                            case "Affliction,Advantage":
                            case "Affliction,Blinded":
                            case "Affliction,Charmed":
                            case "Affliction,Stunned":
                            case "Attack":
                                if (log.bAttackSuccessful)
                                {
                                    UpdateCharacterTrackLog(assailantCharacter.Character_PK, "Damage_Dealt", log.Damage_Final_Result);

                                    if (targetCharacter.Archetype.Contains("Tank") ||
                                        targetCharacter.Archetype.Contains("Bruiser"))
                                        UpdateCharacterTrackLog(targetCharacter.Character_PK, "Damage_Taken",
                                            log.Damage_Final_Result);
                                }
                                break;
                            case "Heal":
                                UpdateCharacterTrackLog(assailantCharacter.Character_PK, "Health_Regained", log.Damage_Final_Result);
                                break;

                        }
                    }

                    logger.WriteLine("");
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms END SKIRMISH");

                    // check for all who survived
                    foreach (var character in globalCharacters)
                    {
                        if (!character.Conditions.bKnockedOut)
                        {
                            UpdateCharacterTrackLog(character.Character_PK, "Skirmishes_Survived", 1);
                        }
                        else
                        {
                            UpdateCharacterTrackLog(character.Character_PK, "Self_Knock_Outs", 1);
                        }
                    }

                    // accolade for character that acted first
                    UpdateCharacterTrackLog(
                        globalInitTrack.OrderBy(x => x.Act_Order).FirstOrDefault().Character_FK,
                        "Initiative_Acted_First", 1);

                    // check for guild win
                    foreach (var accoladeLog in globalCharacterTrackLog)
                    {
                        var charAccoladeTotal =
                            accoladeLog.Damage_Dealt +
                            accoladeLog.Damage_Taken +
                            accoladeLog.Opponent_Knock_Outs +
                            accoladeLog.Self_Knock_Outs +
                            accoladeLog.Assist_Knock_Outs +
                            accoladeLog.Attacks_Dodged +
                            accoladeLog.Critical_Successes +
                            accoladeLog.Critical_Fails +
                            accoladeLog.Health_Regained +
                            accoladeLog.Skirmishes_Survived +
                            accoladeLog.Afflictions_Inflicted +
                            accoladeLog.Initiative_Acted_First +
                            accoladeLog.Blessing_Bestow +
                            accoladeLog.Blessing_Shield_Absorb +
                            accoladeLog.Blessing_Bonus_Damage +
                            accoladeLog.Blessing_Stat_Buff;

                        if (GetCharacter(accoladeLog.Character_FK).Guild_FK == skirmish.Guild_1_FK)
                        {
                            skirmish.Guild_1_Accolade_Points += charAccoladeTotal;
                        }
                        else if (GetCharacter(accoladeLog.Character_FK).Guild_FK == skirmish.Guild_2_FK)
                        {
                            skirmish.Guild_2_Accolade_Points += charAccoladeTotal;
                        }
                    }

                    // check for victory
                    var victorGuildFK = (skirmish.Guild_1_Accolade_Points > skirmish.Guild_2_Accolade_Points ? skirmish.Guild_1_FK : skirmish.Guild_2_FK);
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Guild Winner: " + victorGuildFK + " | Guild1(pk=" + skirmish.Guild_1_FK + ") : " + skirmish.Guild_1_Accolade_Points + " - Guild2(pk=" + skirmish.Guild_2_FK + "): " + skirmish.Guild_2_Accolade_Points);

                    // update guild win bonus for each character track log
                    foreach (var character in globalCharacters.Where(x => x.Guild_FK == victorGuildFK)) UpdateCharacterTrackLog(character.Character_PK, "Guild_Win_Bonus", 1);

                     logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Push character track log to server ...");
                    // push character track log to server
                    controller.CreateCharacterTrackLogForSkirmish(globalCharacterTrackLog);

                     logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Push accolades to server ...");
                    // update user accolades on server
                    controller.UpdateUserAccolades(skirmish.Skirmish_PK);
                    #endregion
                    #region CHARACTER MANAGEMENT
                    // update character energy for each character that performed a skill in the skirmish
                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Updating all character energy ...");
                    List<Energy_Consumption> newEnergyValues = globalCombatLog.Select(log => new Energy_Consumption
                    {
                        Character_FK = log.Assailant_Character_FK,
                        Campaign_FK = skirmish.Campaign_FK,
                        Consume_Energy = globalSkills.FirstOrDefault(x => x.Skill_PK == log.Skill_FK).Energy_Cost
                    }).ToList();
                    // UNCOMMENT LATER
                    // logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM Push energy costs to server ...");
                    //controller.UpdateCharacterEnergy(newEnergyValues);
                    #endregion
                    #region USER EXPERIENCE MANAGEMENT
                    // record user experience
                    controller.UpdateUserSkirmishExperience(skirmish.Skirmish_PK);
                    #endregion

                    // update skirmish
                    controller.UpdateSkirmish(skirmish.Skirmish_PK, skirmish.Guild_1_Accolade_Points, skirmish.Guild_2_Accolade_Points);

                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM End Skirmish Combat Log:");
                    logger.WriteLine(Json.Serialize(globalCombatLog));

                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM End Skirmish State of all characters:");
                    logger.WriteLine(Json.Serialize(globalCharacters));

                    logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms SYSTEM End Skirmish accolade for all characters:");
                    logger.WriteLine(Json.Serialize(globalCharacterTrackLog));

                    stopwatch.Stop();
                    logger.Close();
                }

                //Show success
                this.ScheduleHistoryItem.Succeeded = true;
            }
            catch (Exception ex)
            {
                this.ScheduleHistoryItem.Succeeded = false;
                this.ScheduleHistoryItem.AddLogNote(" ERROR: " + ex.Message);
                logger.WriteLine(DateTime.Today + " " + stopwatch.ElapsedMilliseconds + "ms CRITICAL ERROR: " + ex.Message);
                logger.Close();
                this.Errored(ref ex);
                DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
            }
        }
        public Skill GetFavoredSkill(int Character_PK)
        {
            //FavoredSkill = GetSkill(globalVotes.OrderByDescending(x => x.Vote_Count).FirstOrDefault(x => x.Character_FK == currChar.Character_PK).Skill_FK);
            var relativeVotes = globalVotes.Where(x => x.Character_FK == Character_PK);
            Skill FavoredSkill = new Skill();

            if (!relativeVotes.Any())
            {
                // nobody voted for this character, perform 0 energy skill
                FavoredSkill = GetSkill(globalSkills.FirstOrDefault(x => x.Energy_Cost == 0 && x.Character_FK == Character_PK && !x.bIsPassive).Skill_PK);
            }
            else
            {
                IList<int> relativeSkills = new List<int>();
                foreach (var vote in relativeVotes)
                {

                    if (!relativeSkills.Any(x => x == vote.Skill_FK)) relativeSkills.Add(vote.Skill_FK);
                }

                var favoredSkill = -1;
                var favoredSkillCount = 0;

                foreach (var skill in relativeSkills)
                {
                    var skillCount = globalVotes.Count(x => x.Skill_FK == skill);
                    if (skillCount > favoredSkillCount)
                    {
                        favoredSkill = skill;
                        favoredSkillCount = skillCount;
                    }
                }

                FavoredSkill = GetSkill(favoredSkill);
            }

            return FavoredSkill;
        }