public override int IsCM(ParsedLog log)
        {
            Target target = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.MursaatOverseer);

            if (target == null)
            {
                throw new InvalidOperationException("Target for CM detection not found");
            }
            OverrideMaxHealths(log);
            return((target.Health > 25e6) ? 1 : 0);
        }
        public override int IsCM(ParsedLog log)
        {
            Boss target = Targets.Find(x => x.ID == (ushort)ParseEnum.BossIDS.Deimos);

            if (target == null)
            {
                throw new InvalidOperationException("Target for CM detection not found");
            }
            OverrideMaxHealths(log);
            return((target.Health > 40e6) ? 1 : 0);
        }
예제 #3
0
        public override int IsCM(ParsedEvtcContainer evtcContainer)
        {
            Target target = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Dhuum);

            if (target == null)
            {
                throw new InvalidOperationException("Target for CM detection not found");
            }
            OverrideMaxHealths(evtcContainer);
            return((target.Health > 35e6) ? 1 : 0);
        }
        public virtual List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            List <PhaseData> phases = GetInitialPhase(log);
            NPC mainTarget          = Targets.Find(x => x.ID == GenericTriggerID);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            return(phases);
        }
        public override void ComputeAdditionalTrashMobData(Mob mob, ParsedLog log)
        {
            CombatReplay replay = mob.CombatReplay;
            int          start  = (int)replay.TimeOffsets.start;
            int          end    = (int)replay.TimeOffsets.end;

            switch (mob.ID)
            {
            case (ushort)Core:
                break;

            case (ushort)Jessica:
            case (ushort)Olson:
            case (ushort)Engul:
            case (ushort)Faerla:
            case (ushort)Caulle:
            case (ushort)Henley:
            case (ushort)Galletta:
            case (ushort)Ianim:
                Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.KeepConstruct);
                if (mainTarget == null)
                {
                    throw new InvalidOperationException("Main target of the fight not found");
                }
                CombatReplay mtCR = mainTarget.CombatReplay;
                replay.Actors.Add(new CircleActor(false, 0, 600, (start, end), "rgba(255, 0, 0, 0.5)", new AgentConnector(mob)));
                replay.Actors.Add(new CircleActor(true, 0, 400, (start, end), "rgba(0, 125, 255, 0.5)", new AgentConnector(mob)));
                Point3D pos = replay.Positions.FirstOrDefault();
                if (pos != null)
                {
                    mtCR.Actors.Add(new CircleActor(true, 0, 300, (start - 5000, start), "rgba(220, 50, 0, 0.5)", new PositionConnector(pos)));
                    mtCR.Actors.Add(new CircleActor(true, start, 300, (start - 5000, start), "rgba(220, 50, 0, 0.5)", new PositionConnector(pos)));
                }
                break;

            case (ushort)GreenPhantasm:
                int lifetime = 8000;
                replay.Actors.Add(new CircleActor(true, 0, 210, (start, start + lifetime), "rgba(0,255,0,0.2)", new AgentConnector(mob)));
                replay.Actors.Add(new CircleActor(true, start + lifetime, 210, (start, start + lifetime), "rgba(0,255,0,0.3)", new AgentConnector(mob)));
                break;

            case (ushort)RetrieverProjection:
            case (ushort)InsidiousProjection:
            case (ushort)UnstableLeyRift:
            case (ushort)RadiantPhantasm:
            case (ushort)CrimsonPhantasm:
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
예제 #6
0
        public override void SpecialParse(FightData fightData, AgentData agentData, List <CombatItem> combatData)
        {
            ComputeFightTargets(agentData, combatData);
            // Find target
            Target target = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Deimos);

            if (target == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            // enter combat
            CombatItem enterCombat = combatData.FirstOrDefault(x => x.SrcInstid == target.InstID && x.IsStateChange == ParseEnum.StateChange.EnterCombat && x.SrcInstid == target.InstID && x.LogTime <= target.LastAwareLogTime && x.LogTime >= target.FirstAwareLogTime);

            if (enterCombat != null)
            {
                fightData.OverrideStart(enterCombat.LogTime);
            }
            // Remove deimos despawn events as they are useless and mess with combat replay
            combatData.RemoveAll(x => x.IsStateChange == ParseEnum.StateChange.Despawn && x.SrcAgent == target.Agent);
            // invul correction
            CombatItem invulApp = combatData.FirstOrDefault(x => x.DstInstid == target.InstID && x.IsBuff != 0 && x.BuffDmg == 0 && x.Value > 0 && x.SkillID == 762);

            if (invulApp != null)
            {
                invulApp.OverrideValue((int)(target.LastAwareLogTime - invulApp.LogTime));
            }
            // Deimos gadgets
            CombatItem      targetable   = combatData.LastOrDefault(x => x.IsStateChange == ParseEnum.StateChange.Targetable && x.LogTime > combatData.First().LogTime&& x.DstAgent > 0);
            HashSet <ulong> gadgetAgents = new HashSet <ulong>();
            long            firstAware   = AttackTargetSpecialParse(targetable, agentData, combatData, gadgetAgents);

            // legacy method
            if (firstAware == 0)
            {
                CombatItem armDeimosDamageEvent = combatData.FirstOrDefault(x => x.LogTime >= target.LastAwareLogTime && (x.SkillID == 37980 || x.SkillID == 37982 || x.SkillID == 38046) && x.SrcAgent != 0 && x.SrcInstid != 0);
                if (armDeimosDamageEvent != null)
                {
                    List <AgentItem> deimosGadgets = agentData.GetAgentByType(AgentItem.AgentType.Gadget).Where(x => x.Name.Contains("Deimos") && x.LastAwareLogTime > armDeimosDamageEvent.LogTime).ToList();
                    if (deimosGadgets.Count > 0)
                    {
                        firstAware   = deimosGadgets.Max(x => x.FirstAwareLogTime);
                        gadgetAgents = new HashSet <ulong>(deimosGadgets.Select(x => x.Agent));
                    }
                }
            }
            if (gadgetAgents.Count > 0)
            {
                _specialSplitLogTime = (firstAware >= target.LastAwareLogTime ? firstAware : target.LastAwareLogTime);
                SetUniqueID(target.AgentItem, gadgetAgents, agentData, combatData);
            }
            target.AgentItem.LastAwareLogTime = combatData.Last().LogTime;
        }
예제 #7
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            long             fightDuration = log.FightData.FightDuration;
            List <PhaseData> phases        = GetInitialPhase(log);
            Target           mainTarget    = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.MursaatOverseer);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            List <int> limit = new List <int>()
            {
                75,
                50,
                25,
                0
            };
            long start = 0;
            int  i     = 0;
            List <HealthUpdateEvent> hpUpdates = log.CombatData.GetHealthUpdateEvents(mainTarget.AgentItem);

            for (i = 0; i < limit.Count; i++)
            {
                HealthUpdateEvent evt = hpUpdates.FirstOrDefault(x => x.HPPercent <= limit[i]);
                if (evt == null)
                {
                    break;
                }
                PhaseData phase = new PhaseData(start, Math.Min(evt.Time, fightDuration))
                {
                    Name = (25 + limit[i]) + "% - " + limit[i] + "%"
                };
                phase.Targets.Add(mainTarget);
                phases.Add(phase);
                start = evt.Time;
            }
            if (i < 4)
            {
                PhaseData lastPhase = new PhaseData(start, fightDuration)
                {
                    Name = (25 + limit[i]) + "% -" + limit[i] + "%"
                };
                lastPhase.Targets.Add(mainTarget);
                phases.Add(lastPhase);
            }
            return(phases);
        }
예제 #8
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            long             fightDuration = log.FightData.FightDuration;
            List <PhaseData> phases        = GetInitialPhase(log);
            Target           mainTarget    = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.MursaatOverseer);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            List <int> limit = new List <int>()
            {
                75,
                50,
                25,
                0
            };
            long start = 0;
            int  i     = 0;

            for (i = 0; i < limit.Count; i++)
            {
                (long logTime, int hp) = mainTarget.HealthOverTime.FirstOrDefault(x => x.hp / 100.0 <= limit[i]);
                if (logTime == 0)
                {
                    break;
                }
                PhaseData phase = new PhaseData(start, Math.Min(log.FightData.ToFightSpace(logTime), fightDuration))
                {
                    Name = (25 + limit[i]) + "% - " + limit[i] + "%"
                };
                phase.Targets.Add(mainTarget);
                phases.Add(phase);
                start = log.FightData.ToFightSpace(logTime);
            }
            if (i < 4)
            {
                PhaseData lastPhase = new PhaseData(start, fightDuration)
                {
                    Name = (25 + limit[i]) + "% -" + limit[i] + "%"
                };
                lastPhase.Targets.Add(mainTarget);
                phases.Add(lastPhase);
            }
            return(phases);
        }
예제 #9
0
        public override void SpecialParse(FightData fightData, AgentData agentData, List <CombatItem> combatData)
        {
            Boss boss = Targets.Find(x => x.ID == TriggerID);

            foreach (CombatItem c in combatData)
            {
                // redirect all attacks to the main golem
                if (c.DstAgent == 0 && c.DstInstid == 0 && c.IsStateChange == ParseEnum.StateChange.Normal && c.IFF == ParseEnum.IFF.Foe && c.IsActivation == ParseEnum.Activation.None)
                {
                    c.DstAgent  = boss.Agent;
                    c.DstInstid = boss.InstID;
                }
            }
        }
예제 #10
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            // generic method for fractals
            long             start         = 0;
            long             end           = 0;
            long             fightDuration = log.FightData.FightDuration;
            List <PhaseData> phases        = GetInitialPhase(log);
            Target           mainTarget    = Targets.Find(x => x.ID == TriggerID);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            List <CombatItem> invulsTarget = GetFilteredList(log, 762, mainTarget);

            for (int i = 0; i < invulsTarget.Count; i++)
            {
                CombatItem c = invulsTarget[i];
                if (c.IsBuffRemove == ParseEnum.BuffRemove.None)
                {
                    end = log.FightData.ToFightSpace(c.Time);
                    phases.Add(new PhaseData(start, end));
                    if (i == invulsTarget.Count - 1)
                    {
                        mainTarget.AddCustomCastLog(new CastLog(end, -5, (int)(fightDuration - end), ParseEnum.Activation.None, (int)(fightDuration - end), ParseEnum.Activation.None), log);
                    }
                }
                else
                {
                    start = log.FightData.ToFightSpace(c.Time);
                    mainTarget.AddCustomCastLog(new CastLog(end, -5, (int)(start - end), ParseEnum.Activation.None, (int)(start - end), ParseEnum.Activation.None), log);
                }
            }
            if (fightDuration - start > 5000 && start >= phases.Last().End)
            {
                phases.Add(new PhaseData(start, fightDuration));
            }
            phases.RemoveAll(x => x.GetDuration() < 1000);
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Name = "Phase " + i;
                phases[i].Targets.Add(mainTarget);
            }
            return(phases);
        }
예제 #11
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            List <PhaseData> phases = GetInitialPhase(log);
            NPC eye1 = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.EyeOfFate);
            NPC eye2 = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.EyeOfJudgement);

            if (eye2 == null || eye1 == null)
            {
                throw new InvalidOperationException("Eyes not found");
            }
            phases[0].Targets.Add(eye2);
            phases[0].Targets.Add(eye1);
            return(phases);
        }
예제 #12
0
        public override void ComputeMobCombatReplayActors(Mob mob, ParsedLog log, CombatReplay replay)
        {
            int start = (int)replay.TimeOffsets.start;
            int end   = (int)replay.TimeOffsets.end;

            switch (mob.ID)
            {
            case (ushort)EntropicDistortion:
                //sapping surge, red tether
                List <AbstractBuffEvent> sappingSurge = GetFilteredList(log.CombatData, 56118, mob, true);
                int surgeStart             = 0;
                AbstractMasterActor source = null;
                foreach (AbstractBuffEvent c in sappingSurge)
                {
                    if (c is BuffApplyEvent)
                    {
                        Target qadim = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.PeerlessQadim);
                        surgeStart = (int)c.Time;
                        source     = (AbstractMasterActor)log.PlayerList.FirstOrDefault(x => x.AgentItem == c.By) ?? qadim;
                    }
                    else
                    {
                        int surgeEnd = (int)c.Time;
                        if (source != null)
                        {
                            replay.Actors.Add(new LineActor(0, (surgeStart, surgeEnd), "rgba(255, 0, 0, 0.3)", new AgentConnector(mob), new AgentConnector(source)));
                        }
                    }
                }
                break;

            case (ushort)BigKillerTornado:
                replay.Actors.Add(new CircleActor(true, 0, 450, (start, end), "rgba(255, 150, 0, 0.4)", new AgentConnector(mob)));
                break;

            case (ushort)Pylon1:
                break;

            case (ushort)Pylon2:
                break;

            case (ushort)EnergyOrb:
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
예제 #13
0
        public override int IsCM(CombatData combatData, AgentData agentData, FightData fightData)
        {
            NPC target = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Deimos);

            if (target == null)
            {
                throw new InvalidOperationException("Deimos not found");
            }
            int res = (target.GetHealth(combatData) > 40e6) ? 1 : 0;

            if (_specialSplit > 0)
            {
                target.SetManualHealth(res > 0 ? 42804900 : 37388210);
            }
            return(res);
        }
예제 #14
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            long             fightDuration = log.FightData.FightDuration;
            List <PhaseData> phases        = GetInitialPhase(log);
            Target           mainTarget    = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Dhuum);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // Sometimes the preevent is not in the evtc
            List <CastLog> castLogs  = mainTarget.GetCastLogs(log, 0, log.FightData.FightEnd);
            List <CastLog> dhuumCast = mainTarget.GetCastLogs(log, 0, 20000);

            string[] namesDh;
            if (dhuumCast.Count > 0)
            {
                namesDh = new[] { "Main Fight", "Ritual" };
                ComputeFightPhases(mainTarget, phases, log, castLogs, fightDuration, 0);
            }
            else
            {
                CombatItem invulDhuum = log.GetBoonData(762).FirstOrDefault(x => x.IsBuffRemove != ParseEnum.BuffRemove.None && x.SrcInstid == mainTarget.InstID && x.Time > 115000 + log.FightData.FightStart);
                if (invulDhuum != null)
                {
                    long end = log.FightData.ToFightSpace(invulDhuum.Time);
                    phases.Add(new PhaseData(0, end));
                    ComputeFightPhases(mainTarget, phases, log, castLogs, fightDuration, end + 1);
                }
                else
                {
                    phases.Add(new PhaseData(0, fightDuration));
                }
                namesDh = new[] { "Roleplay", "Main Fight", "Ritual" };
            }
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Name = namesDh[i - 1];
                phases[i].Targets.Add(mainTarget);
            }
            return(phases);
        }
예제 #15
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            List <PhaseData> phases     = GetInitialPhase(log);
            Target           mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Sabir);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            List <AbstractCastEvent> cls = mainTarget.GetCastLogs(log, 0, log.FightData.FightDuration);
            List <AbstractCastEvent> wallopingWinds = cls.Where(x => x.SkillId == 56094).ToList();
            long start = 0, end = 0;

            for (int i = 0; i < wallopingWinds.Count; i++)
            {
                AbstractCastEvent wW = wallopingWinds[i];
                end = wW.Time;
                PhaseData phase = new PhaseData(start, end)
                {
                    Name = "Phase " + (i + 1)
                };
                phase.Targets.Add(mainTarget);
                phases.Add(phase);
                AbstractCastEvent nextAttack = cls.FirstOrDefault(x => x.Time >= end + wW.ActualDuration && (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.FightDuration)
                    {
                        Name = "Phase " + (i + 2)
                    };
                    phase.Targets.Add(mainTarget);
                    phases.Add(phase);
                }
            }

            return(phases);
        }
예제 #16
0
        public override List <AbstractBuffEvent> SpecialBuffEventProcess(Dictionary <AgentItem, List <AbstractBuffEvent> > buffsByDst, Dictionary <long, List <AbstractBuffEvent> > buffsById, long offset, SkillData skillData)
        {
            Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Xera);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            List <AbstractBuffEvent> res = new List <AbstractBuffEvent>();

            if (_specialSplitLogTime != 0)
            {
                res.Add(new BuffRemoveAllEvent(mainTarget.AgentItem, mainTarget.AgentItem, _specialSplitLogTime - offset, int.MaxValue, skillData.Get(762), 1, int.MaxValue));
                res.Add(new BuffRemoveManualEvent(mainTarget.AgentItem, mainTarget.AgentItem, _specialSplitLogTime - offset, int.MaxValue, skillData.Get(762)));
            }
            return(res);
        }
예제 #17
0
        public override void SpecialParse(FightData fightData, AgentData agentData, List <CombatItem> combatData)
        {
            Boss boss = Targets.Find(x => x.ID == (ushort)ParseEnum.BossIDS.Deimos);

            if (boss == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            CombatItem enterCombat = combatData.FirstOrDefault(x => x.SrcInstid == boss.InstID && x.IsStateChange == ParseEnum.StateChange.EnterCombat);

            if (enterCombat != null)
            {
                fightData.FightStart = enterCombat.Time;
            }
            List <AgentItem> deimosGadgets = agentData.GetAgentByType(AgentItem.AgentType.Gadget).Where(x => x.Name.Contains("Deimos")).OrderBy(x => x.LastAware).ToList();

            if (deimosGadgets.Count > 0)
            {
                long            firstAware    = deimosGadgets.Max(x => x.FirstAware);
                HashSet <ulong> deimos2Agents = new HashSet <ulong>(deimosGadgets.Select(x => x.Agent));
                CombatItem      targetable    = combatData.LastOrDefault(x => x.IsStateChange == ParseEnum.StateChange.Targetable && x.Time > combatData.First().Time&& x.DstAgent > 0);
                if (targetable != null)
                {
                    firstAware = targetable.Time;
                }
                long oldAware = boss.LastAware;
                fightData.PhaseData.Add(firstAware >= oldAware ? firstAware : oldAware);
                boss.AgentItem.LastAware = deimosGadgets.Max(x => x.LastAware);
                foreach (CombatItem c in combatData)
                {
                    if (c.Time > oldAware)
                    {
                        if (deimos2Agents.Contains(c.SrcAgent))
                        {
                            c.SrcInstid = boss.InstID;
                            c.SrcAgent  = boss.Agent;
                        }
                        if (deimos2Agents.Contains(c.DstAgent))
                        {
                            c.DstInstid = boss.InstID;
                            c.DstAgent  = boss.Agent;
                        }
                    }
                }
            }
        }
예제 #18
0
        public override void SpecialParse(FightData fightData, AgentData agentData, List <CombatItem> combatData)
        {
            // Find target
            Target target = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Ensolyss);

            if (target == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            // enter combat
            CombatItem invulLost = combatData.FirstOrDefault(x => x.DstInstid == target.InstID && x.IsStateChange == ParseEnum.StateChange.Normal && x.IsBuffRemove != ParseEnum.BuffRemove.None && x.SkillID == 762);

            if (invulLost != null && invulLost.Time - fightData.FightStart < 5000)
            {
                fightData.FightStart = invulLost.Time;
            }
        }
 public override void CheckSuccess(CombatData combatData, AgentData agentData, FightData fightData, HashSet <AgentItem> playerAgents)
 {
     base.CheckSuccess(combatData, agentData, fightData, playerAgents);
     if (!fightData.Success)
     {
         NPC mainTarget = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.SoullessHorror);
         if (mainTarget == null)
         {
             throw new InvalidOperationException("Soulless Horror not found");
         }
         AbstractBuffEvent buffOnDeath = combatData.GetBuffData(895).Where(x => x.To == mainTarget.AgentItem && x is BuffApplyEvent).LastOrDefault();
         if (buffOnDeath != null)
         {
             fightData.SetSuccess(true, buffOnDeath.Time);
         }
     }
 }
예제 #20
0
        public override List <AbstractBuffEvent> SpecialBuffEventProcess(Dictionary <AgentItem, List <AbstractBuffEvent> > buffsByDst, Dictionary <long, List <AbstractBuffEvent> > buffsById, SkillData skillData)
        {
            NPC mainTarget = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Xera);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Error Encountered: Xera not found");
            }
            var res = new List <AbstractBuffEvent>();

            if (_specialSplit != 0)
            {
                res.Add(new BuffRemoveAllEvent(mainTarget.AgentItem, mainTarget.AgentItem, _specialSplit, int.MaxValue, skillData.Get(762), 1, int.MaxValue));
                res.Add(new BuffRemoveManualEvent(mainTarget.AgentItem, mainTarget.AgentItem, _specialSplit, int.MaxValue, skillData.Get(762)));
            }
            return(res);
        }
예제 #21
0
        public override void EIEvtcParse(FightData fightData, AgentData agentData, List <CombatItem> combatData, List <Player> playerList)
        {
            ComputeFightTargets(agentData, combatData);
            // Find target
            NPC target = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Deimos);

            if (target == null)
            {
                throw new InvalidOperationException("Deimos not found");
            }
            // Remove deimos despawn events as they are useless and mess with combat replay
            combatData.RemoveAll(x => x.IsStateChange == ParseEnum.StateChange.Despawn && x.SrcAgent == target.Agent);
            // invul correction
            CombatItem invulApp = combatData.FirstOrDefault(x => x.DstAgent == target.Agent && x.IsBuff != 0 && x.BuffDmg == 0 && x.Value > 0 && x.SkillID == 762 && x.IsStateChange == ParseEnum.StateChange.None);

            if (invulApp != null)
            {
                invulApp.OverrideValue((int)(target.LastAware - invulApp.Time));
            }
            // Deimos gadgets
            CombatItem targetable   = combatData.LastOrDefault(x => x.IsStateChange == ParseEnum.StateChange.Targetable && x.DstAgent > 0);
            var        gadgetAgents = new HashSet <ulong>();
            long       firstAware   = AttackTargetSpecialParse(targetable, agentData, combatData, gadgetAgents);

            // legacy method
            if (firstAware == 0)
            {
                CombatItem armDeimosDamageEvent = combatData.FirstOrDefault(x => x.Time >= target.LastAware && (x.SkillID == 37980 || x.SkillID == 37982 || x.SkillID == 38046) && x.SrcAgent != 0 && x.SrcInstid != 0);
                if (armDeimosDamageEvent != null)
                {
                    var deimosGadgets = agentData.GetAgentByType(AgentItem.AgentType.Gadget).Where(x => x.Name.Contains("Deimos") && x.LastAware > armDeimosDamageEvent.Time).ToList();
                    if (deimosGadgets.Count > 0)
                    {
                        firstAware   = deimosGadgets.Max(x => x.FirstAware);
                        gadgetAgents = new HashSet <ulong>(deimosGadgets.Select(x => x.Agent));
                    }
                }
            }
            if (gadgetAgents.Count > 0)
            {
                _specialSplit = (firstAware >= target.LastAware ? firstAware : target.LastAware);
                MergeWithGadgets(target.AgentItem, gadgetAgents, agentData, combatData);
            }
            target.AgentItem.OverrideAwareTimes(target.FirstAware, fightData.FightEnd);
            target.OverrideName("Deimos");
        }
예제 #22
0
        private void HPCheck(CombatData combatData, FightData fightData)
        {
            NPC eye1 = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.EyeOfFate);
            NPC eye2 = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.EyeOfJudgement);

            if (eye2 == null || eye1 == null)
            {
                throw new InvalidOperationException("Eyes not found");
            }
            List <HealthUpdateEvent> eye1HPs = combatData.GetHealthUpdateEvents(eye1.AgentItem);
            List <HealthUpdateEvent> eye2HPs = combatData.GetHealthUpdateEvents(eye2.AgentItem);

            if (eye1HPs.Count == 0 || eye2HPs.Count == 0)
            {
                return;
            }
            double lastEye1Hp = eye1HPs.LastOrDefault().HPPercent;
            double lastEye2Hp = eye2HPs.LastOrDefault().HPPercent;
            double margin1    = Math.Min(0.80, lastEye1Hp);
            double margin2    = Math.Min(0.80, lastEye2Hp);

            if (lastEye1Hp <= margin1 && lastEye2Hp <= margin2)
            {
                int lastIEye1;
                for (lastIEye1 = eye1HPs.Count - 1; lastIEye1 >= 0; lastIEye1--)
                {
                    if (eye1HPs[lastIEye1].HPPercent > margin1)
                    {
                        lastIEye1++;
                        break;
                    }
                }
                int lastIEye2;
                for (lastIEye2 = eye2HPs.Count - 1; lastIEye2 >= 0; lastIEye2--)
                {
                    if (eye2HPs[lastIEye2].HPPercent > margin2)
                    {
                        lastIEye2++;
                        break;
                    }
                }
                fightData.SetSuccess(true, Math.Max(eye1HPs[lastIEye1].Time, eye2HPs[lastIEye2].Time));
            }
        }
예제 #23
0
        public override void ComputeAdditionalTrashMobData(Mob mob, ParsedLog log)
        {
            Target desmina = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Desmina);

            if (desmina == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            CombatReplay replay = mob.CombatReplay;
            int          start  = (int)replay.TimeOffsets.start;
            int          end    = (int)replay.TimeOffsets.end;

            switch (mob.ID)
            {
            case (ushort)HollowedBomber:
                List <CastLog> bomberman = mob.GetCastLogs(log, 0, log.FightData.FightDuration).Where(x => x.SkillId == 48272).ToList();
                foreach (CastLog bomb in bomberman)
                {
                    int startCast   = (int)bomb.Time;
                    int endCast     = startCast + bomb.ActualDuration;
                    int expectedEnd = Math.Max(startCast + bomb.ExpectedDuration, endCast);
                    replay.Actors.Add(new CircleActor(true, 0, 480, (startCast, endCast), "rgba(180,250,0,0.3)", new AgentConnector(mob)));
                    replay.Actors.Add(new CircleActor(true, expectedEnd, 480, (startCast, endCast), "rgba(180,250,0,0.3)", new AgentConnector(mob)));
                }
                break;

            case (ushort)RiverOfSouls:
                if (replay.Rotations.Count > 0)
                {
                    replay.Actors.Add(new FacingRectangleActor((start, end), new AgentConnector(mob), replay.PolledRotations, 160, 390, "rgba(255,100,0,0.5)"));
                }
                break;

            case (ushort)Enervator:
            // TODO Line actor between desmina and enervator. Missing skillID
            case (ushort)SpiritHorde1:
            case (ushort)SpiritHorde2:
            case (ushort)SpiritHorde3:
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
예제 #24
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            long             start         = 0;
            long             fightDuration = log.FightData.FightDuration;
            List <PhaseData> phases        = GetInitialPhase(log);
            Boss             mainTarget    = Targets.Find(x => x.ID == (ushort)ParseEnum.BossIDS.Xera);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // split happened
            if (log.FightData.PhaseData.Count == 1)
            {
                CombatItem invulXera = log.GetBoonData(762).Find(x => x.DstInstid == mainTarget.InstID);
                if (invulXera == null)
                {
                    invulXera = log.GetBoonData(34113).Find(x => x.DstInstid == mainTarget.InstID);
                }
                long end = invulXera.Time - log.FightData.FightStart;
                phases.Add(new PhaseData(start, end));
                start = log.FightData.PhaseData[0] - log.FightData.FightStart;
                mainTarget.AddCustomCastLog(new CastLog(end, -5, (int)(start - end), ParseEnum.Activation.None, (int)(start - end), ParseEnum.Activation.None), log);
            }
            if (fightDuration - start > 5000 && start >= phases.Last().End)
            {
                phases.Add(new PhaseData(start, fightDuration));
            }
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Name      = "Phase " + i;
                phases[i].DrawArea  = true;
                phases[i].DrawStart = i > 1;
                phases[i].DrawEnd   = i < phases.Count - 1;
                phases[i].Targets.Add(mainTarget);
            }
            return(phases);
        }
예제 #25
0
        internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases)
        {
            List <PhaseData> phases = GetInitialPhase(log);
            NPC mainTarget          = Targets.Find(x => x.ID == (int)ArcDPSEnums.TargetID.MursaatOverseer);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Mursaat Overseer not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            phases.AddRange(GetPhasesByHealthPercent(log, mainTarget, new List <double> {
                75, 50, 25, 0
            }));
            return(phases);
        }
        internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases)
        {
            List <PhaseData> phases = GetInitialPhase(log);
            NPC varinia             = Targets.Find(x => x.ID == (int)ArcDPSEnums.TargetID.VariniaStormsounder);

            if (varinia == null)
            {
                throw new InvalidOperationException("Varinia Stormsounder not found");
            }
            phases[0].Targets.Add(varinia);
            //
            // TODO - add phases if applicable
            //
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Targets.Add(varinia);
            }
            return(phases);
        }
예제 #27
0
        public override void ComputeNPCCombatReplayActors(NPC target, ParsedLog log, CombatReplay replay)
        {
            NPC desmina = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Desmina);

            if (desmina == null)
            {
                throw new InvalidOperationException("Error Encountered: Desmina not found");
            }
            int start = (int)replay.TimeOffsets.start;
            int end   = (int)replay.TimeOffsets.end;

            switch (target.ID)
            {
            case (int)HollowedBomber:
                var bomberman = target.GetCastLogs(log, 0, log.FightData.FightEnd).Where(x => x.SkillId == 48272).ToList();
                foreach (AbstractCastEvent bomb in bomberman)
                {
                    int startCast   = (int)bomb.Time;
                    int endCast     = startCast + bomb.ActualDuration;
                    int expectedEnd = Math.Max(startCast + bomb.ExpectedDuration, endCast);
                    replay.Decorations.Add(new CircleDecoration(true, 0, 480, (startCast, endCast), "rgba(180,250,0,0.3)", new AgentConnector(target)));
                    replay.Decorations.Add(new CircleDecoration(true, expectedEnd, 480, (startCast, endCast), "rgba(180,250,0,0.3)", new AgentConnector(target)));
                }
                break;

            case (int)RiverOfSouls:
                if (replay.Rotations.Count > 0)
                {
                    replay.Decorations.Add(new FacingRectangleDecoration((start, end), new AgentConnector(target), replay.PolledRotations, 160, 390, "rgba(255,100,0,0.5)"));
                }
                break;

            case (int)Enervator:
            // TODO Line actor between desmina and enervator. Missing skillID
            case (int)SpiritHorde1:
            case (int)SpiritHorde2:
            case (int)SpiritHorde3:
                break;

            default:
                break;
            }
        }
예제 #28
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            List <PhaseData> phases = GetInitialPhase(log);
            NPC mainTarget          = Targets.Find(x => x.ID == GenericTriggerID);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Golem not found");
            }
            phases[0].Name = "Final Number";
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            List <HealthUpdateEvent> hpUpdates = log.CombatData.GetHealthUpdateEvents(mainTarget.AgentItem);

            if (hpUpdates.Count > 0)
            {
                long fightDuration = log.FightData.FightEnd;
                var  thresholds    = new List <double> {
                    80, 60, 40, 20, 0
                };
                var numberNames = new string[] { "First Number", "Second Number", "Third Number", "Fourth Number" };
                // Fifth number would the equivalent of full fight phase
                for (int j = 0; j < thresholds.Count - 1; j++)
                {
                    HealthUpdateEvent hpUpdate = hpUpdates.FirstOrDefault(x => x.HPPercent <= thresholds[j]);
                    if (hpUpdate != null)
                    {
                        var phase = new PhaseData(0, hpUpdate.Time, numberNames[j])
                        {
                            CanBeSubPhase = false
                        };
                        phase.Targets.Add(mainTarget);
                        phases.Add(phase);
                    }
                }
                phases.AddRange(GetPhasesByHealthPercent(log, mainTarget, thresholds));
            }

            return(phases);
        }
예제 #29
0
        public override void SetSuccess(ParsedEvtcContainer evtcContainer)
        {
            Target mainTarget = Targets.Find(x => x.ID == TriggerID);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            CombatItem lastDamageTaken = evtcContainer.CombatData.GetDamageTakenData(mainTarget.InstID, mainTarget.FirstAware, mainTarget.LastAware).LastOrDefault(x => x.Value > 0 || x.BuffDmg > 0);

            if (lastDamageTaken != null)
            {
                evtcContainer.FightData.FightEnd = lastDamageTaken.Time;
            }
            if (mainTarget.HealthOverTime.Count > 0)
            {
                evtcContainer.FightData.Success = mainTarget.HealthOverTime.Last().hp < 200;
            }
        }
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            List <PhaseData> phases = GetInitialPhase(log);
            NPC mainTarget          = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.ValeGuardian);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Error Encountered: Vale Guardian not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // Invul check
            phases.AddRange(GetPhasesByInvul(log, 757, mainTarget, true, true));
            string[] namesVG = new[] { "Phase 1", "Split 1", "Phase 2", "Split 2", "Phase 3" };
            for (int i = 1; i < phases.Count; i++)
            {
                PhaseData phase = phases[i];
                phase.Name = namesVG[i - 1];
                if (i == 2 || i == 4)
                {
                    var ids = new List <int>
                    {
                        (int)BlueGuardian,
                        (int)GreenGuardian,
                        (int)RedGuardian
                    };
                    AddTargetsToPhase(phase, ids, log);
                    foreach (NPC t in phase.Targets)
                    {
                        t.OverrideName(t.Character + " " + Math.Log(i, 2));
                    }
                }
                else
                {
                    phase.Targets.Add(mainTarget);
                }
            }
            return(phases);
        }