private static List <PhaseData> GetInBetweenSoulSplits(ParsedEvtcLog log, AbstractSingleActor dhuum, long mainStart, long mainEnd, bool hasRitual)
        {
            IReadOnlyList <AbstractCastEvent> cls = dhuum.GetCastEvents(log, 0, log.FightData.FightEnd);
            var cataCycles  = cls.Where(x => x.SkillId == 48398).ToList();
            var gDeathmarks = cls.Where(x => x.SkillId == 48210).ToList();

            if (gDeathmarks.Count < cataCycles.Count)
            {
                // anomaly, don't do sub phases
                return(new List <PhaseData>());
            }
            var  phases = new List <PhaseData>();
            long start  = mainStart;
            long end    = 0;
            int  i      = 0;

            foreach (AbstractCastEvent cataCycle in cataCycles)
            {
                AbstractCastEvent gDeathmark = gDeathmarks[i];
                end = Math.Min(gDeathmark.Time, mainEnd);
                long soulsplitEnd = Math.Min(cataCycle.EndTime, mainEnd);
                ++i;
                phases.Add(new PhaseData(start, end, "Pre-Soulsplit " + i));
                phases.Add(new PhaseData(end, soulsplitEnd, "Soulsplit " + i)
                {
                    CanBeSubPhase = false
                });;
                start = cataCycle.EndTime;
            }
            phases.Add(new PhaseData(start, mainEnd, hasRitual ? "Pre-Ritual" : "Pre-Wipe"));
            return(phases);
        }
Exemple #2
0
        /*internal override List<AbstractBuffEvent> SpecialBuffEventProcess(Dictionary<AgentItem, List<AbstractBuffEvent>> buffsByDst, Dictionary<long, List<AbstractBuffEvent>> buffsById, SkillData skillData)
         * {
         *  var res = new List<AbstractBuffEvent>();
         *  // Necrosis adjust
         *  AdjustTimeRefreshBuff(buffsByDst, buffsById, 47414);
         *  return res;
         * }*/

        internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases)
        {
            long                fightDuration = log.FightData.FightEnd;
            List <PhaseData>    phases        = GetInitialPhase(log);
            AbstractSingleActor mainTarget    = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.SoullessHorror);

            if (mainTarget == null)
            {
                throw new MissingKeyActorsException("Soulless Horror not found");
            }
            phases[0].AddTarget(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            var  howling = mainTarget.GetCastEvents(log, 0, log.FightData.FightEnd).Where(x => x.SkillId == 48662).ToList();
            long start   = 0;
            int  i       = 1;

            foreach (AbstractCastEvent c in howling)
            {
                var phase = new PhaseData(start, Math.Min(c.Time, fightDuration), "Pre-Breakbar " + i++);
                phase.AddTarget(mainTarget);
                start = c.EndTime;
                phases.Add(phase);
            }
            if (fightDuration - start > 3000)
            {
                var lastPhase = new PhaseData(start, fightDuration, "Final");
                lastPhase.AddTarget(mainTarget);
                phases.Add(lastPhase);
            }
            return(phases);
        }
Exemple #3
0
        internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases)
        {
            List <PhaseData>    phases     = GetInitialPhase(log);
            AbstractSingleActor mainTarget = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.Sabir);

            if (mainTarget == null)
            {
                throw new MissingKeyActorsException("Sabir not found");
            }
            phases[0].AddTarget(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            IReadOnlyList <AbstractCastEvent> cls = mainTarget.GetCastEvents(log, 0, log.FightData.FightEnd);
            var  wallopingWinds = cls.Where(x => x.SkillId == 56094).ToList();
            long start = 0, end = 0;

            for (int i = 0; i < wallopingWinds.Count; i++)
            {
                AbstractCastEvent wallopinbWind = wallopingWinds[i];
                end = wallopinbWind.Time;
                var phase = new PhaseData(start, end, "Phase " + (i + 1));
                phase.AddTarget(mainTarget);
                phases.Add(phase);
                AbstractCastEvent nextAttack = cls.FirstOrDefault(x => x.Time >= wallopinbWind.EndTime && (x.SkillId == 56620 || x.SkillId == 56629 || x.SkillId == 56307));
                if (nextAttack == null)
                {
                    break;
                }
                start = nextAttack.Time;
                if (i == wallopingWinds.Count - 1)
                {
                    phase = new PhaseData(start, log.FightData.FightEnd, "Phase " + (i + 2));
                    phase.AddTarget(mainTarget);
                    phases.Add(phase);
                }
            }

            return(phases);
        }
        internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases)
        {
            long                fightDuration = log.FightData.FightEnd;
            List <PhaseData>    phases        = GetInitialPhase(log);
            AbstractSingleActor dhuum         = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.Dhuum);

            if (dhuum == null)
            {
                throw new MissingKeyActorsException("Dhuum not found");
            }
            phases[0].AddTarget(dhuum);
            if (!requirePhases)
            {
                return(phases);
            }
            // Sometimes the pre event is not in the evtc
            IReadOnlyList <AbstractCastEvent> castLogs  = dhuum.GetCastEvents(log, 0, log.FightData.FightEnd);
            IReadOnlyList <AbstractCastEvent> dhuumCast = dhuum.GetCastEvents(log, 0, 20000);

            if (dhuumCast.Any(x => !(x is InstantCastEvent)))
            {
                // full fight does not contain the pre event
                ComputeFightPhases(phases, castLogs, fightDuration, 0);
                _isBugged = true;
            }
            else
            {
                // full fight contains the pre event
                AbstractBuffEvent invulDhuum = log.CombatData.GetBuffData(762).FirstOrDefault(x => x is BuffRemoveManualEvent && x.To == dhuum.AgentItem && x.Time > 115000);
                // pre event done
                if (invulDhuum != null)
                {
                    long end = invulDhuum.Time;
                    phases.Add(new PhaseData(0, end, "Pre Event"));
                    phases.Add(new PhaseData(end + 1, fightDuration, "Main Fight")
                    {
                        CanBeSubPhase = false
                    });
                    ComputeFightPhases(phases, castLogs, fightDuration, end + 1);
                }
            }
            bool hasRitual = phases.Last().Name == "Ritual";
            // present if not bugged and pre-event done
            PhaseData mainFight = phases.Find(x => x.Name == "Main Fight");
            // if present, Dhuum was at least at 10%
            PhaseData dhuumFight = phases.Find(x => x.Name == "Dhuum Fight");

            if (mainFight != null)
            {
                mainFight.CanBeSubPhase = dhuumFight == null;
                // from pre event end to 10% or fight end if 10% not achieved
                phases.AddRange(GetInBetweenSoulSplits(log, dhuum, mainFight.Start, dhuumFight != null ? dhuumFight.End : mainFight.End, hasRitual));
            }
            else if (_isBugged)
            {
                // from start to 10% or fight end if 10% not achieved
                phases.AddRange(GetInBetweenSoulSplits(log, dhuum, 0, dhuumFight != null ? dhuumFight.End : fightDuration, hasRitual));
            }
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].AddTarget(dhuum);
            }
            return(phases);
        }
        internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases)
        {
            List <PhaseData>    phases     = GetInitialPhase(log);
            AbstractSingleActor mainTarget = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.Adina);

            if (mainTarget == null)
            {
                throw new MissingKeyActorsException("Adina not found");
            }
            phases[0].AddTarget(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // Split phases
            List <AbstractBuffEvent> invuls = GetFilteredList(log.CombatData, 762, mainTarget, true, true);
            long start          = 0;
            var  splitPhases    = new List <PhaseData>();
            var  splitPhaseEnds = new List <long>();

            for (int i = 0; i < invuls.Count; i++)
            {
                PhaseData         splitPhase;
                AbstractBuffEvent be = invuls[i];
                if (be is BuffApplyEvent)
                {
                    start = be.Time;
                    if (i == invuls.Count - 1)
                    {
                        splitPhase = new PhaseData(start, log.FightData.FightEnd, "Split " + (i / 2 + 1));
                        splitPhaseEnds.Add(log.FightData.FightEnd);
                        AddTargetsToPhaseAndFit(splitPhase, new List <int> {
                            (int)ArcDPSEnums.TrashID.HandOfErosion, (int)ArcDPSEnums.TrashID.HandOfEruption
                        }, log);
                        splitPhases.Add(splitPhase);
                    }
                }
                else
                {
                    long end = be.Time;
                    splitPhase = new PhaseData(start, end, "Split " + (i / 2 + 1));
                    splitPhaseEnds.Add(end);
                    AddTargetsToPhaseAndFit(splitPhase, new List <int> {
                        (int)ArcDPSEnums.TrashID.HandOfErosion, (int)ArcDPSEnums.TrashID.HandOfEruption
                    }, log);
                    splitPhases.Add(splitPhase);
                }
            }
            // Main phases
            var mainPhases    = new List <PhaseData>();
            var pillarApplies = log.CombatData.GetBuffData(56204).OfType <BuffApplyEvent>().Where(x => x.To == mainTarget.AgentItem).ToList();
            Dictionary <long, List <BuffApplyEvent> > pillarAppliesGroupByTime = ParserHelper.GroupByTime(pillarApplies);
            var mainPhaseEnds = new List <long>();

            foreach (KeyValuePair <long, List <BuffApplyEvent> > pair in pillarAppliesGroupByTime)
            {
                if (pair.Value.Count == 6)
                {
                    mainPhaseEnds.Add(pair.Key);
                }
            }
            AbstractCastEvent boulderBarrage = mainTarget.GetCastEvents(log, 0, log.FightData.FightEnd).FirstOrDefault(x => x.SkillId == 56648 && x.Time < 6000);

            start = boulderBarrage == null ? 0 : boulderBarrage.EndTime;
            if (mainPhaseEnds.Any())
            {
                int phaseIndex = 1;
                foreach (long quantumQake in mainPhaseEnds)
                {
                    var curPhaseStart = splitPhaseEnds.LastOrDefault(x => x < quantumQake);
                    if (curPhaseStart == 0)
                    {
                        curPhaseStart = start;
                    }
                    long nextPhaseStart = splitPhaseEnds.FirstOrDefault(x => x > quantumQake);
                    if (nextPhaseStart != 0)
                    {
                        start      = nextPhaseStart;
                        phaseIndex = splitPhaseEnds.IndexOf(start) + 1;
                    }
                    mainPhases.Add(new PhaseData(curPhaseStart, quantumQake, "Phase " + phaseIndex));
                }
                if (start != mainPhases.Last().Start)
                {
                    mainPhases.Add(new PhaseData(start, log.FightData.FightEnd, "Phase " + (phaseIndex + 1)));
                }
            }
            else if (start > 0 && !invuls.Any())
            {
                // no split
                mainPhases.Add(new PhaseData(start, log.FightData.FightEnd, "Phase 1"));
            }

            foreach (PhaseData phase in mainPhases)
            {
                phase.AddTarget(mainTarget);
            }
            phases.AddRange(mainPhases);
            phases.AddRange(splitPhases);
            phases.Sort((x, y) => x.Start.CompareTo(y.Start));
            //
            try
            {
                var splitPhasesMap = new List <string>()
                {
                    "https://i.imgur.com/gJ55jKy.png",
                    "https://i.imgur.com/c2Oz5bj.png",
                    "https://i.imgur.com/P4SGbrc.png",
                };
                var mainPhasesMap = new List <string>()
                {
                    "https://i.imgur.com/IQn2RJV.png",
                    "https://i.imgur.com/3pO7eCB.png",
                    "https://i.imgur.com/ZFw590w.png",
                    "https://i.imgur.com/2P7UE8q.png"
                };
                var crMaps          = new List <string>();
                int mainPhaseIndex  = 0;
                int splitPhaseIndex = 0;
                for (int i = 1; i < phases.Count; i++)
                {
                    PhaseData phaseData = phases[i];
                    if (mainPhases.Contains(phaseData))
                    {
                        if (mainPhasesMap.Contains(crMaps.LastOrDefault()))
                        {
                            splitPhaseIndex++;
                        }
                        crMaps.Add(mainPhasesMap[mainPhaseIndex++]);
                    }
                    else
                    {
                        if (splitPhasesMap.Contains(crMaps.LastOrDefault()))
                        {
                            mainPhaseIndex++;
                        }
                        crMaps.Add(splitPhasesMap[splitPhaseIndex++]);
                    }
                }
                GetCombatReplayMap(log).MatchMapsToPhases(crMaps, phases, log.FightData.FightEnd);
            }
            catch (Exception)
            {
                log.UpdateProgressWithCancellationCheck("Failed to associate Adina Combat Replay maps");
            }

            //
            return(phases);
        }
        internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases)
        {
            List <PhaseData>    phases = GetInitialPhase(log);
            AbstractSingleActor voice  = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.ClawOfTheFallen);
            AbstractSingleActor claw   = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.VoiceOfTheFallen);

            if (voice == null || claw == null)
            {
                throw new MissingKeyActorsException("Claw or Voice not found");
            }
            phases[0].AddTarget(voice);
            phases[0].AddTarget(claw);
            long fightEnd = log.FightData.FightEnd;

            if (!requirePhases)
            {
                return(phases);
            }
            //
            List <PhaseData> unmergedPhases = GetPhasesByInvul(log, 762, claw, false, true);

            for (int i = 0; i < unmergedPhases.Count; i++)
            {
                unmergedPhases[i].Name = "Phase " + (i + 1);
                unmergedPhases[i].AddTarget(claw);
                unmergedPhases[i].AddTarget(voice);
            }
            phases.AddRange(unmergedPhases);
            //
            int voiceAndClawCount = 0;

            foreach (AbstractSingleActor voiceAndClaw in Targets.Where(x => x.ID == (int)ArcDPSEnums.TargetID.VoiceAndClaw))
            {
                EnterCombatEvent enterCombat = log.CombatData.GetEnterCombatEvents(voiceAndClaw.AgentItem).FirstOrDefault();
                long             phaseStart  = 0;
                if (enterCombat != null)
                {
                    phaseStart = enterCombat.Time;
                }
                else
                {
                    phaseStart = voiceAndClaw.FirstAware;
                }
                PhaseData nextUnmergedPhase = unmergedPhases.FirstOrDefault(x => x.Start > phaseStart);
                long      phaseEnd          = Math.Min(fightEnd, voiceAndClaw.LastAware);
                if (nextUnmergedPhase != null)
                {
                    phaseEnd = nextUnmergedPhase.Start - 1;
                }
                var phase = new PhaseData(phaseStart, phaseEnd, "Voice and Claw " + ++voiceAndClawCount);
                phase.AddTarget(voiceAndClaw);
                phases.Add(phase);
            }
            //
            var  teleports       = voice.GetCastEvents(log, 0, log.FightData.FightDuration).Where(x => x.SkillId == 58382).ToList();
            long tpCount         = 0;
            long preTPPhaseStart = 0;

            foreach (AbstractCastEvent teleport in teleports)
            {
                long preTPPhaseEnd = Math.Min(teleport.Time, log.FightData.FightDuration);
                AbstractSingleActor voiceAndClaw = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.VoiceAndClaw && x.FirstAware >= preTPPhaseStart);
                if (voiceAndClaw != null)
                {
                    long oldEnd = preTPPhaseEnd;
                    preTPPhaseEnd = Math.Min(preTPPhaseEnd, voiceAndClaw.FirstAware);
                    // To handle position phase after merge phase end
                    if (oldEnd != preTPPhaseEnd)
                    {
                        PhaseData nextUnmergedPhase = unmergedPhases.FirstOrDefault(x => x.Start > voiceAndClaw.LastAware);
                        if (nextUnmergedPhase != null)
                        {
                            long postMergedStart = nextUnmergedPhase.Start + 1;
                            long postMergedEnd   = oldEnd;
                            var  phase           = new PhaseData(postMergedStart, postMergedEnd, "Position " + (++tpCount));
                            phase.AddTarget(claw);
                            phase.AddTarget(voice);
                            phases.Add(phase);
                        }
                    }
                }
                if (preTPPhaseEnd - preTPPhaseStart > 2000)
                {
                    var phase = new PhaseData(preTPPhaseStart, preTPPhaseEnd, "Position " + (++tpCount));
                    phase.AddTarget(claw);
                    phase.AddTarget(voice);
                    phases.Add(phase);
                }
                preTPPhaseStart = teleport.EndTime;
            }

            //
            AbstractBuffEvent enrage = log.CombatData.GetBuffData(SkillIDs.EnragedVC).FirstOrDefault(x => x is BuffApplyEvent);

            if (enrage != null)
            {
                var phase = new PhaseData(enrage.Time, log.FightData.FightEnd, "Enrage");
                phase.AddTarget(claw.AgentItem == enrage.To ? claw : voice);
                phases.Add(phase);
            }
            // Missing final position event
            {
                PhaseData nextUnmergedPhase = unmergedPhases.FirstOrDefault(x => x.Start > preTPPhaseStart);
                long      finalStart        = preTPPhaseStart;
                long      finalPositionEnd  = log.FightData.FightDuration;
                if (nextUnmergedPhase != null)
                {
                    finalStart = nextUnmergedPhase.Start + 1;
                }
                if (enrage != null)
                {
                    finalPositionEnd = enrage.Time;
                }
                if (finalPositionEnd - finalStart > 2000)
                {
                    var phase = new PhaseData(finalStart, finalPositionEnd, "Position " + (++tpCount));
                    phase.AddTarget(claw);
                    phase.AddTarget(voice);
                    phases.Add(phase);
                }
            }
            return(phases);
        }