예제 #1
0
        public override void ComputeAdditionalTargetData(Target target, ParsedLog log)
        {
            CombatReplay   replay = target.CombatReplay;
            List <CastLog> cls    = target.GetCastLogs(log, 0, log.FightData.FightDuration);

            (int, int)lifespan = ((int)target.CombatReplay.TimeOffsets.start, (int)target.CombatReplay.TimeOffsets.end);
            switch (target.ID)
            {
            case (ushort)ParseEnum.TargetIDS.ValeGuardian:
                List <CastLog> magicStorms = cls.Where(x => x.SkillId == 31419).ToList();
                foreach (CastLog c in magicStorms)
                {
                    replay.Actors.Add(new CircleActor(true, 0, 100, ((int)c.Time, (int)c.Time + c.ActualDuration), "rgba(0, 180, 255, 0.3)", new AgentConnector(target)));
                }
                int            distributedMagicDuration = 6700;
                int            arenaRadius           = 1600;
                int            impactDuration        = 110;
                List <CastLog> distributedMagicGreen = cls.Where(x => x.SkillId == 31750).ToList();
                foreach (CastLog c in distributedMagicGreen)
                {
                    int start = (int)c.Time;
                    int end   = start + distributedMagicDuration;
                    replay.Actors.Add(new PieActor(true, start + distributedMagicDuration, arenaRadius, 151, 120, (start, end), "rgba(0,255,0,0.1)", new PositionConnector(new Point3D(-4749.838867f, -20607.296875f, 0.0f, 0))));
                    replay.Actors.Add(new PieActor(true, 0, arenaRadius, 151, 120, (end, end + impactDuration), "rgba(0,255,0,0.3)", new PositionConnector(new Point3D(-4749.838867f, -20607.296875f, 0.0f, 0))));
                    replay.Actors.Add(new CircleActor(true, 0, 180, (start, end), "rgba(0,255,0,0.2)", new PositionConnector(new Point3D(-5449.0f, -20219.0f, 0.0f, 0))));
                }
                List <CastLog> distributedMagicBlue = cls.Where(x => x.SkillId == 31340).ToList();
                foreach (CastLog c in distributedMagicBlue)
                {
                    int start = (int)c.Time;
                    int end   = start + distributedMagicDuration;
                    replay.Actors.Add(new PieActor(true, start + distributedMagicDuration, arenaRadius, 31, 120, (start, end), "rgba(0,255,0,0.1)", new PositionConnector(new Point3D(-4749.838867f, -20607.296875f, 0.0f, 0))));
                    replay.Actors.Add(new PieActor(true, 0, arenaRadius, 31, 120, (end, end + impactDuration), "rgba(0,255,0,0.3)", new PositionConnector(new Point3D(-4749.838867f, -20607.296875f, 0.0f, 0))));
                    replay.Actors.Add(new CircleActor(true, 0, 180, (start, end), "rgba(0,255,0,0.2)", new PositionConnector(new Point3D(-4063.0f, -20195.0f, 0.0f, 0))));
                }
                List <CastLog> distributedMagicRed = cls.Where(x => x.SkillId == 31391).ToList();
                foreach (CastLog c in distributedMagicRed)
                {
                    int start = (int)c.Time;
                    int end   = start + distributedMagicDuration;
                    replay.Actors.Add(new PieActor(true, start + distributedMagicDuration, arenaRadius, 271, 120, (start, end), "rgba(0,255,0,0.1)", new PositionConnector(new Point3D(-4749.838867f, -20607.296875f, 0.0f, 0))));
                    replay.Actors.Add(new PieActor(true, 0, arenaRadius, 271, 120, (end, end + impactDuration), "rgba(0,255,0,0.3)", new PositionConnector(new Point3D(-4749.838867f, -20607.296875f, 0.0f, 0))));
                    replay.Actors.Add(new CircleActor(true, 0, 180, (start, end), "rgba(0,255,0,0.2)", new PositionConnector(new Point3D(-4735.0f, -21407.0f, 0.0f, 0))));
                }
                break;

            case (ushort)BlueGuardian:
                replay.Actors.Add(new CircleActor(false, 0, 1500, lifespan, "rgba(0, 0, 255, 0.5)", new AgentConnector(target)));
                break;

            case (ushort)GreenGuardian:
                replay.Actors.Add(new CircleActor(false, 0, 1500, lifespan, "rgba(0, 255, 0, 0.5)", new AgentConnector(target)));
                break;

            case (ushort)RedGuardian:
                replay.Actors.Add(new CircleActor(false, 0, 1500, lifespan, "rgba(255, 0, 0, 0.5)", new AgentConnector(target)));
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
예제 #2
0
 public virtual void SetSuccess(ParsedLog log)
 {
     SetSuccessByDeath(log);
 }
예제 #3
0
 public override void Sort(ParsedLog log, List <BoonStackItem> stacks)
 {
     // no sort
 }
예제 #4
0
 public abstract void ComputeAdditionalTargetData(Target target, ParsedLog log);
예제 #5
0
 public virtual int IsCM(ParsedLog log)
 {
     return(-1);
 }
예제 #6
0
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            long             start         = 0;
            long             end           = 0;
            long             fightDuration = log.FightData.FightDuration;
            List <PhaseData> phases        = GetInitialPhase(log);
            Target           mainTarget    = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Deimos);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // Determined + additional data on inst change
            CombatItem invulDei = log.CombatData.GetBoonData(762).Find(x => x.IsBuffRemove == ParseEnum.BuffRemove.None && x.DstInstid == mainTarget.InstID);

            if (invulDei != null)
            {
                end = log.FightData.ToFightSpace(invulDei.Time);
                phases.Add(new PhaseData(start, end));
                start = (_specialSplit > 0 ? log.FightData.ToFightSpace(_specialSplit) : fightDuration);
                //mainTarget.AddCustomCastLog(end, -6, (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));
            }
            string[] names = { "100% - 10%", "10% - 0%" };
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Name = names[i - 1];
                phases[i].Targets.Add(mainTarget);
            }
            foreach (Target tar in Targets)
            {
                if (tar.ID == (ushort)Thief || tar.ID == (ushort)Drunkard || tar.ID == (ushort)Gambler)
                {
                    string    name     = (tar.ID == (ushort)Thief ? "Thief" : (tar.ID == (ushort)Drunkard ? "Drunkard" : (tar.ID == (ushort)Gambler ? "Gambler" : "")));
                    PhaseData tarPhase = new PhaseData(log.FightData.ToFightSpace(tar.FirstAware) - 1000, log.FightData.ToFightSpace(tar.LastAware) + 1000);
                    tarPhase.Targets.Add(tar);
                    tarPhase.OverrideTimes(log);
                    // override first then add Deimos so that it does not disturb the override process
                    tarPhase.Targets.Add(mainTarget);
                    tarPhase.Name = name;
                    phases.Add(tarPhase);
                }
            }

            /*
             * List<CombatItem> signets = GetFilteredList(log, 38224, mainTarget, true);
             * long sigStart = 0;
             * long sigEnd = 0;
             * int burstID = 1;
             * for (int i = 0; i < signets.Count; i++)
             * {
             *  CombatItem signet = signets[i];
             *  if (signet.IsBuffRemove == ParseEnum.BuffRemove.None)
             *  {
             *      sigStart = log.FightData.ToFightSpace(signet.Time);
             *  }
             *  else
             *  {
             *      sigEnd = log.FightData.ToFightSpace(signet.Time);
             *      PhaseData burstPhase = new PhaseData(sigStart, sigEnd)
             *      {
             *          Name = "Burst " + burstID++
             *      };
             *      burstPhase.Targets.Add(mainTarget);
             *      phases.Add(burstPhase);
             *  }
             * }*/
            phases.Sort((x, y) => x.Start.CompareTo(y.Start));
            phases.RemoveAll(x => x.Targets.Count == 0);
            return(phases);
        }
예제 #7
0
 public override object GetConnectedTo(CombatReplayMap map, ParsedLog log)
 {
     return(_agent.GetCombatReplayID(log));
 }
예제 #8
0
        // Private Methods

        private void SetDeathRecaps(ParsedLog log)
        {
            List <DeathRecap> res       = _deathRecaps;
            List <CombatItem> deads     = log.CombatData.GetStatesData(InstID, ParseEnum.StateChange.ChangeDead, log.FightData.FightStart, log.FightData.FightEnd);
            List <CombatItem> downs     = log.CombatData.GetStatesData(InstID, ParseEnum.StateChange.ChangeDown, log.FightData.FightStart, log.FightData.FightEnd);
            long             lastTime   = log.FightData.FightStart;
            List <DamageLog> damageLogs = GetDamageTakenLogs(null, log, 0, log.FightData.FightDuration);

            foreach (CombatItem dead in deads)
            {
                DeathRecap recap = new DeathRecap()
                {
                    DeathTime = (int)(log.FightData.ToFightSpace(dead.Time))
                };
                CombatItem downed = downs.LastOrDefault(x => x.Time <= dead.Time && x.Time >= lastTime);
                if (downed != null)
                {
                    List <DamageLog> damageToDown = damageLogs.Where(x => x.Time < log.FightData.ToFightSpace(downed.Time) && x.Damage > 0 && x.Time > log.FightData.ToFightSpace(lastTime)).ToList();
                    recap.ToDown = damageToDown.Count > 0 ? new List <DeathRecap.DeathRecapDamageItem>() : null;
                    int damage = 0;
                    for (int i = damageToDown.Count - 1; i >= 0; i--)
                    {
                        DamageLog dl = damageToDown[i];
                        AgentItem ag = log.AgentData.GetAgentByInstID(dl.SrcInstId, log.FightData.ToLogSpace(dl.Time));
                        DeathRecap.DeathRecapDamageItem item = new DeathRecap.DeathRecapDamageItem()
                        {
                            Time    = (int)dl.Time,
                            IsCondi = dl.IsIndirectDamage,
                            ID      = dl.SkillId,
                            Damage  = dl.Damage,
                            Src     = ag != null?ag.Name.Replace("\u0000", "").Split(':')[0] : ""
                        };
                        damage += dl.Damage;
                        recap.ToDown.Add(item);
                        if (damage > 20000)
                        {
                            break;
                        }
                    }
                    List <DamageLog> damageToKill = damageLogs.Where(x => x.Time > log.FightData.ToFightSpace(downed.Time) && x.Time < log.FightData.ToFightSpace(dead.Time) && x.Damage > 0 && x.Time > log.FightData.ToFightSpace(lastTime)).ToList();
                    recap.ToKill = damageToKill.Count > 0 ? new List <DeathRecap.DeathRecapDamageItem>() : null;
                    for (int i = damageToKill.Count - 1; i >= 0; i--)
                    {
                        DamageLog dl = damageToKill[i];
                        AgentItem ag = log.AgentData.GetAgentByInstID(dl.SrcInstId, log.FightData.ToLogSpace(dl.Time));
                        DeathRecap.DeathRecapDamageItem item = new DeathRecap.DeathRecapDamageItem()
                        {
                            Time    = (int)dl.Time,
                            IsCondi = dl.IsIndirectDamage,
                            ID      = dl.SkillId,
                            Damage  = dl.Damage,
                            Src     = ag != null?ag.Name.Replace("\u0000", "").Split(':')[0] : ""
                        };
                        recap.ToKill.Add(item);
                    }
                }
                else
                {
                    recap.ToDown = null;
                    List <DamageLog> damageToKill = damageLogs.Where(x => x.Time < log.FightData.ToFightSpace(dead.Time) && x.Damage > 0 && x.Time > log.FightData.ToFightSpace(lastTime)).ToList();
                    recap.ToKill = damageToKill.Count > 0 ? new List <DeathRecap.DeathRecapDamageItem>() : null;
                    int damage = 0;
                    for (int i = damageToKill.Count - 1; i >= 0; i--)
                    {
                        DamageLog dl = damageToKill[i];
                        AgentItem ag = log.AgentData.GetAgentByInstID(dl.SrcInstId, log.FightData.ToLogSpace(dl.Time));
                        DeathRecap.DeathRecapDamageItem item = new DeathRecap.DeathRecapDamageItem()
                        {
                            Time    = (int)dl.Time,
                            IsCondi = dl.IsIndirectDamage,
                            ID      = dl.SkillId,
                            Damage  = dl.Damage,
                            Src     = ag != null?ag.Name.Replace("\u0000", "").Split(':')[0] : ""
                        };
                        damage += dl.Damage;
                        recap.ToKill.Add(item);
                        if (damage > 20000)
                        {
                            break;
                        }
                    }
                }
                lastTime = dead.Time;
                res.Add(recap);
            }
            if (_deathRecaps.Count == 0)
            {
                _deathRecaps = null;
            }
        }
예제 #9
0
        public override void ComputeAdditionalTargetData(Target target, ParsedLog log)
        {
            CombatReplay   replay = target.CombatReplay;
            List <CastLog> cls    = target.GetCastLogs(log, 0, log.FightData.FightDuration);

            switch (target.ID)
            {
            case (ushort)ParseEnum.TargetIDS.Gorseval:
                List <CastLog> blooms = cls.Where(x => x.SkillId == 31616).ToList();
                foreach (CastLog c in blooms)
                {
                    int start = (int)c.Time;
                    int end   = start + c.ActualDuration;
                    replay.Actors.Add(new CircleActor(true, c.ExpectedDuration + (int)c.Time, 600, (start, end), "rgba(255, 125, 0, 0.5)", new AgentConnector(target)));
                    replay.Actors.Add(new CircleActor(false, 0, 600, (start, end), "rgba(255, 125, 0, 0.5)", new AgentConnector(target)));
                }
                List <PhaseData> phases = log.FightData.GetPhases(log);
                if (phases.Count > 1)
                {
                    List <CastLog> rampage = cls.Where(x => x.SkillId == 31834).ToList();
                    Point3D        pos     = target.CombatReplay.Positions.First();
                    foreach (CastLog c in rampage)
                    {
                        int start = (int)c.Time;
                        int end   = start + c.ActualDuration;
                        replay.Actors.Add(new CircleActor(true, 0, 180, (start, end), "rgba(0, 125, 255, 0.3)", new AgentConnector(target)));
                        // or spawn -> 3 secs -> explosion -> 0.5 secs -> fade -> 0.5  secs-> next
                        int ticks = (int)Math.Min(Math.Ceiling(c.ActualDuration / 4000.0), 6);
                        int phaseIndex;
                        for (phaseIndex = 1; phaseIndex < phases.Count; phaseIndex++)
                        {
                            if (phases[phaseIndex].InInterval(start))
                            {
                                break;
                            }
                        }
                        if (pos == null)
                        {
                            break;
                        }
                        List <string> patterns;
                        switch (phaseIndex)
                        {
                        case 1:
                            patterns = new List <string>
                            {
                                "2+3+5",
                                "2+3+4",
                                "1+4+5",
                                "1+2+5",
                                "1+3+5",
                                "Full"
                            };
                            break;

                        case 3:
                            patterns = new List <string>
                            {
                                "2+3+4",
                                "1+4+5",
                                "1+3+4",
                                "1+2+5",
                                "1+2+3",
                                "Full"
                            };
                            break;

                        case 5:
                            patterns = new List <string>
                            {
                                "1+4+5",
                                "1+2+5",
                                "2+3+5",
                                "3+4+5",
                                "3+4+5",
                                "Full"
                            };
                            break;

                        default:
                            throw new Exception("how the f**k");
                        }
                        start += 2200;
                        for (int i = 0; i < ticks; i++)
                        {
                            int    tickStart = start + 4000 * i;
                            int    explosion = tickStart + 3000;
                            int    tickEnd   = tickStart + 3500;
                            string pattern   = patterns[i];
                            if (pattern.Contains("1"))
                            {
                                replay.Actors.Add(new CircleActor(true, explosion, 360, (tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos)));
                                replay.Actors.Add(new CircleActor(true, 0, 360, (tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos)));
                            }
                            if (pattern.Contains("2"))
                            {
                                replay.Actors.Add(new DoughnutActor(true, explosion, 360, 720, (tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos)));
                                replay.Actors.Add(new DoughnutActor(true, 0, 360, 720, (tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos)));
                            }
                            if (pattern.Contains("3"))
                            {
                                replay.Actors.Add(new DoughnutActor(true, explosion, 720, 1080, (tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos)));
                                replay.Actors.Add(new DoughnutActor(true, 0, 720, 1080, (tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos)));
                            }
                            if (pattern.Contains("4"))
                            {
                                replay.Actors.Add(new DoughnutActor(true, explosion, 1080, 1440, (tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos)));
                                replay.Actors.Add(new DoughnutActor(true, 0, 1080, 1440, (tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos)));
                            }
                            if (pattern.Contains("5"))
                            {
                                replay.Actors.Add(new DoughnutActor(true, explosion, 1440, 1800, (tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos)));
                                replay.Actors.Add(new DoughnutActor(true, 0, 1440, 1800, (tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos)));
                            }
                            if (pattern.Contains("Full"))
                            {
                                tickStart -= 1000;
                                explosion -= 1000;
                                tickEnd   -= 1000;
                                replay.Actors.Add(new CircleActor(true, explosion, 1800, (tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos)));
                                replay.Actors.Add(new CircleActor(true, 0, 1800, (tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos)));
                            }
                        }
                    }
                }
                List <CastLog> slam = cls.Where(x => x.SkillId == 31875).ToList();
                foreach (CastLog c in slam)
                {
                    int start       = (int)c.Time;
                    int impactPoint = 1185;
                    int impactTime  = start + impactPoint;
                    int end         = (int)Math.Min(start + c.ActualDuration, impactTime);
                    int radius      = 320;
                    replay.Actors.Add(new CircleActor(true, 0, radius, (start, end), "rgba(255, 0, 0, 0.2)", new AgentConnector(target)));
                    replay.Actors.Add(new CircleActor(true, 0, radius, (impactTime - 10, impactTime + 100), "rgba(255, 0, 0, 0.4)", new AgentConnector(target)));
                }
                List <CombatItem> protection = log.GetBoonData(31877).Where(x => x.IsBuffRemove != ParseEnum.BuffRemove.Manual).ToList();
                int protectionStart          = 0;
                foreach (CombatItem c in protection)
                {
                    if (c.IsBuffRemove == ParseEnum.BuffRemove.None)
                    {
                        protectionStart = (int)(log.FightData.ToFightSpace(c.Time));
                    }
                    else
                    {
                        int protectionEnd = (int)(log.FightData.ToFightSpace(c.Time));
                        replay.Actors.Add(new CircleActor(true, 0, 300, (protectionStart, protectionEnd), "rgba(0, 180, 255, 0.5)", new AgentConnector(target)));
                    }
                }
                break;

            case (ushort)ChargedSoul:
                (int, int)lifespan = ((int)replay.TimeOffsets.start, (int)replay.TimeOffsets.end);
                replay.Actors.Add(new CircleActor(false, 0, 220, lifespan, "rgba(255, 150, 0, 0.5)", new AgentConnector(target)));
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
 public override void SetBoonDistributionItem(BoonDistribution distribs, long start, long end, long boonid, ParsedLog log)
 {
     foreach (BoonSimulationItemDuration item in _stacks)
     {
         item.SetBoonDistributionItem(distribs, start, end, boonid, log);
     }
 }
예제 #11
0
 // Constructor
 public BoonSimulatorIntensity(int capacity, ParsedLog log, StackingLogic logic) : base(capacity, log, logic)
 {
 }
예제 #12
0
 public void SetSuccess(ParsedLog log)
 {
     Logic.SetSuccess(log);
 }
예제 #13
0
 public abstract void CheckMechanic(ParsedLog log, Dictionary <ushort, DummyActor> regroupedMobs);
예제 #14
0
        /// <summary>
        /// Calculate a statistic from a log
        /// </summary>
        /// <param name="log"></param>
        /// <param name="switches"></param>
        /// <returns></returns>
        public Statistics CalculateStatistics(ParsedLog log, Switches switches)
        {
            _statistics = new Statistics();

            _log = log;

            SetPresentBoons();
            _statistics.Phases = log.FightData.GetPhases(log);
            if (switches.CalculateCombatReplay && _settings.ParseCombatReplay)
            {
                foreach (Player p in log.PlayerList)
                {
                    if (p.Account == ":Conjured Sword")
                    {
                        continue;
                    }
                    p.InitCombatReplay(log, _settings.PollingRate, false, true);
                }
                foreach (Target target in log.FightData.Logic.Targets)
                {
                    target.InitCombatReplay(log, _settings.PollingRate, true, log.FightData.GetMainTargets(log).Contains(target));
                }
                log.FightData.Logic.InitTrashMobCombatReplay(log, _settings.PollingRate);

                // Ensuring all combat replays are initialized before extra data (and agent interaction) is computed
                foreach (Player p in log.PlayerList)
                {
                    if (p.Account == ":Conjured Sword")
                    {
                        continue;
                    }
                    p.ComputeAdditionalCombatReplayData(log);
                }
                foreach (Target target in log.FightData.Logic.Targets)
                {
                    target.ComputeAdditionalCombatReplayData(log);
                }

                foreach (Mob mob in log.FightData.Logic.TrashMobs)
                {
                    mob.ComputeAdditionalCombatReplayData(log);
                }
            }
            if (switches.CalculateDPS)
            {
                CalculateDPS();
            }
            if (switches.CalculateBoons)
            {
                CalculateBoons();
            }
            if (switches.CalculateStats)
            {
                CalculateStats();
            }
            if (switches.CalculateDefense)
            {
                CalculateDefenses();
            }
            if (switches.CalculateSupport)
            {
                CalculateSupport();
            }

            if (switches.CalculateConditions)
            {
                CalculateConditions();
            }
            if (switches.CalculateMechanics)
            {
                log.FightData.Logic.ComputeMechanics(log);
            }
            // target health
            _statistics.TargetsHealth = new Dictionary <Target, double[]> [_statistics.Phases.Count];
            for (int i = 0; i < _statistics.Phases.Count; i++)
            {
                _statistics.TargetsHealth[i] = new Dictionary <Target, double[]>();
            }
            foreach (Target target in _log.FightData.Logic.Targets)
            {
                List <double[]> hps = target.Get1SHealthGraph(_log, _statistics.Phases);
                for (int i = 0; i < hps.Count; i++)
                {
                    _statistics.TargetsHealth[i][target] = hps[i];
                }
            }
            //

            return(_statistics);
        }
        public override void ComputeAdditionalPlayerData(Player p, ParsedLog log)
        {
            // spirit transform
            CombatReplay      replay          = p.CombatReplay;
            List <CombatItem> spiritTransform = log.GetBoonData(46950).Where(x => x.DstInstid == p.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.None).ToList();
            Boss mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.BossIDS.Dhuum);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            foreach (CombatItem c in spiritTransform)
            {
                int duration = 15000;
                int start    = (int)(c.Time - log.FightData.FightStart);
                if (mainTarget.HealthOverTime.FirstOrDefault(x => x.X > start).Y < 1050)
                {
                    duration = 30000;
                }
                CombatItem removedBuff = log.GetBoonData(48281).FirstOrDefault(x => x.SrcInstid == p.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.All && x.Time > c.Time && x.Time < c.Time + duration);
                int        end         = start + duration;
                if (removedBuff != null)
                {
                    end = (int)(removedBuff.Time - log.FightData.FightStart);
                }
                replay.Actors.Add(new CircleActor(true, 0, 100, new Tuple <int, int>(start, end), "rgba(0, 50, 200, 0.3)", new AgentConnector(p)));
                replay.Actors.Add(new CircleActor(true, start + duration, 100, new Tuple <int, int>(start, end), "rgba(0, 50, 200, 0.5)", new AgentConnector(p)));
            }
            // bomb
            List <CombatItem> bombDhuum = GetFilteredList(log, 47646, p);
            int bombDhuumStart          = 0;

            foreach (CombatItem c in bombDhuum)
            {
                if (c.IsBuffRemove == ParseEnum.BuffRemove.None)
                {
                    bombDhuumStart = (int)(c.Time - log.FightData.FightStart);
                }
                else
                {
                    int bombDhuumEnd = (int)(c.Time - log.FightData.FightStart);
                    replay.Actors.Add(new CircleActor(true, 0, 100, new Tuple <int, int>(bombDhuumStart, bombDhuumEnd), "rgba(80, 180, 0, 0.3)", new AgentConnector(p)));
                    replay.Actors.Add(new CircleActor(true, bombDhuumStart + 13000, 100, new Tuple <int, int>(bombDhuumStart, bombDhuumEnd), "rgba(80, 180, 0, 0.5)", new AgentConnector(p)));
                }
            }
            // shackles connection
            List <CombatItem> shackles = GetFilteredList(log, 47335, p).Concat(GetFilteredList(log, 48591, p)).ToList();
            int    shacklesStart       = 0;
            Player shacklesTarget      = null;

            foreach (CombatItem c in shackles)
            {
                if (c.IsBuffRemove == ParseEnum.BuffRemove.None)
                {
                    shacklesStart  = (int)(c.Time - log.FightData.FightStart);
                    shacklesTarget = log.PlayerList.FirstOrDefault(x => x.Agent == c.SrcAgent);
                }
                else
                {
                    int shacklesEnd           = (int)(c.Time - log.FightData.FightStart);
                    Tuple <int, int> duration = new Tuple <int, int>(shacklesStart, shacklesEnd);
                    if (shacklesTarget != null)
                    {
                        replay.Actors.Add(new LineActor(0, 10, duration, "rgba(0, 255, 255, 0.5)", new AgentConnector(p), new AgentConnector(shacklesTarget)));
                    }
                }
            }
            // shackles damage (identical to the connection for now, not yet properly distinguishable from the pure connection, further investigation needed due to inconsistent behavior (triggering too early, not triggering the damaging skill though)
            // shackles start with buff 47335 applied from one player to the other, this is switched over to buff 48591 after mostly 2 seconds, sometimes later. This is switched to 48042 usually 4 seconds after initial application and the damaging skill 47164 starts to deal damage from that point on.
            // Before that point, 47164 is only logged when evaded/blocked, but doesn't deal damage. Further investigation needed.
            List <CombatItem> shacklesDmg = GetFilteredList(log, 48042, p);
            int    shacklesDmgStart       = 0;
            Player shacklesDmgTarget      = null;

            foreach (CombatItem c in shacklesDmg)
            {
                if (c.IsBuffRemove == ParseEnum.BuffRemove.None)
                {
                    shacklesDmgStart  = (int)(c.Time - log.FightData.FightStart);
                    shacklesDmgTarget = log.PlayerList.FirstOrDefault(x => x.Agent == c.SrcAgent);
                }
                else
                {
                    int shacklesDmgEnd        = (int)(c.Time - log.FightData.FightStart);
                    Tuple <int, int> duration = new Tuple <int, int>(shacklesDmgStart, shacklesDmgEnd);
                    if (shacklesDmgTarget != null)
                    {
                        replay.Actors.Add(new LineActor(0, 10, duration, "rgba(0, 255, 255, 0.5)", new AgentConnector(p), new AgentConnector(shacklesDmgTarget)));
                    }
                }
            }
        }
예제 #16
0
 public override void ComputeAdditionalPlayerData(Player p, ParsedLog log)
 {
 }
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            long             start         = 0;
            long             end           = 0;
            long             fightDuration = log.FightData.FightDuration;
            List <PhaseData> phases        = GetInitialPhase(log);
            Boss             mainTarget    = Targets.Find(x => x.ID == (ushort)ParseEnum.BossIDS.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);

            if (dhuumCast.Count > 0)
            {
                CastLog shield = castLogs.Find(x => x.SkillId == 47396);
                if (shield != null)
                {
                    end = shield.Time;
                    phases.Add(new PhaseData(start, end));
                    start = shield.Time + shield.ActualDuration;
                    if (start < fightDuration - 5000)
                    {
                        phases.Add(new PhaseData(start, fightDuration));
                    }
                }
                if (fightDuration - start > 5000 && start >= phases.Last().End)
                {
                    phases.Add(new PhaseData(start, fightDuration));
                }
                string[] namesDh = new [] { "Main Fight", "Ritual" };
                for (int i = 1; i < phases.Count; i++)
                {
                    phases[i].Name      = namesDh[i - 1];
                    phases[i].DrawArea  = true;
                    phases[i].DrawStart = i > 1;
                    phases[i].DrawEnd   = i < phases.Count - 1;
                    phases[i].Targets.Add(mainTarget);
                }
            }
            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)
                {
                    end = invulDhuum.Time - log.FightData.FightStart;
                    phases.Add(new PhaseData(start, end));
                    start = end + 1;
                    CastLog shield = castLogs.Find(x => x.SkillId == 47396);
                    if (shield != null)
                    {
                        end = shield.Time;
                        phases.Add(new PhaseData(start, end));
                        start = shield.Time + shield.ActualDuration;
                        if (start < fightDuration - 5000)
                        {
                            phases.Add(new PhaseData(start, fightDuration));
                        }
                    }
                }
                if (fightDuration - start > 5000 && start >= phases.Last().End)
                {
                    phases.Add(new PhaseData(start, fightDuration));
                }
                string[] namesDh = new [] { "Roleplay", "Main Fight", "Ritual" };
                for (int i = 1; i < phases.Count; i++)
                {
                    phases[i].Name      = namesDh[i - 1];
                    phases[i].DrawArea  = i > 1;
                    phases[i].DrawStart = i > 1;
                    phases[i].DrawEnd   = i == 2;
                    phases[i].Targets.Add(mainTarget);
                }
            }
            return(phases);
        }
예제 #18
0
 public virtual void ComputeAdditionalTargetData(Target target, ParsedLog log)
 {
 }
예제 #19
0
        public override void ComputeAdditionalTargetData(Target target, ParsedLog log)
        {
            CombatReplay   replay = target.CombatReplay;
            List <CastLog> cls    = target.GetCastLogs(log, 0, log.FightData.FightDuration);

            switch (target.ID)
            {
            case (ushort)ParseEnum.TargetIDS.Deimos:
                List <CastLog> mindCrush = cls.Where(x => x.SkillId == 37613).ToList();
                foreach (CastLog c in mindCrush)
                {
                    int start = (int)c.Time;
                    int end   = start + 5000;
                    replay.Actors.Add(new CircleActor(true, end, 180, (start, end), "rgba(255, 0, 0, 0.5)", new AgentConnector(target)));
                    replay.Actors.Add(new CircleActor(false, 0, 180, (start, end), "rgba(255, 0, 0, 0.5)", new AgentConnector(target)));
                    if (!log.FightData.IsCM)
                    {
                        replay.Actors.Add(new CircleActor(true, 0, 180, (start, end), "rgba(0, 0, 255, 0.3)", new PositionConnector(new Point3D(-8421.818f, 3091.72949f, -9.818082e8f, 216))));
                    }
                }
                List <CastLog> annihilate = cls.Where(x => (x.SkillId == 38208) || (x.SkillId == 37929)).ToList();
                foreach (CastLog c in annihilate)
                {
                    int     start    = (int)c.Time;
                    int     delay    = 1000;
                    int     end      = start + 2400;
                    int     duration = 120;
                    Point3D facing   = replay.Rotations.FirstOrDefault(x => x.Time >= start);
                    if (facing == null)
                    {
                        continue;
                    }
                    for (int i = 0; i < 6; i++)
                    {
                        replay.Actors.Add(new PieActor(true, 0, 900, (int)Math.Round(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI + i * 360 / 10), 360 / 10, (start + delay + i * duration, end + i * duration), "rgba(255, 200, 0, 0.5)", new AgentConnector(target)));
                        replay.Actors.Add(new PieActor(false, 0, 900, (int)Math.Round(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI + i * 360 / 10), 360 / 10, (start + delay + i * duration, end + i * 120), "rgba(255, 150, 0, 0.5)", new AgentConnector(target)));
                        if (i % 5 != 0)
                        {
                            replay.Actors.Add(new PieActor(true, 0, 900, (int)Math.Round(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI - i * 360 / 10), 360 / 10, (start + delay + i * duration, end + i * 120), "rgba(255, 200, 0, 0.5)", new AgentConnector(target)));
                            replay.Actors.Add(new PieActor(false, 0, 900, (int)Math.Round(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI - i * 360 / 10), 360 / 10, (start + delay + i * duration, end + i * 120), "rgba(255, 150, 0, 0.5)", new AgentConnector(target)));
                        }
                    }
                }
                List <CombatItem> signets = GetFilteredList(log, 38224, target, true);
                int sigStart = 0;
                int sigEnd   = 0;
                foreach (CombatItem signet in signets)
                {
                    if (signet.IsBuffRemove == ParseEnum.BuffRemove.None)
                    {
                        sigStart = (int)log.FightData.ToFightSpace(signet.Time);
                    }
                    else
                    {
                        sigEnd = (int)log.FightData.ToFightSpace(signet.Time);
                        replay.Actors.Add(new CircleActor(true, 0, 120, (sigStart, sigEnd), "rgba(0, 200, 200, 0.5)", new AgentConnector(target)));
                    }
                }
                break;

            case (ushort)Gambler:
            case (ushort)Thief:
            case (ushort)Drunkard:
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
예제 #20
0
 public virtual void ComputeAdditionalThrashMobData(Mob mob, ParsedLog log)
 {
 }
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            List <PhaseData> phases = GetInitialPhase(log);
            NPC ca = Targets.Find(x => x.ID == (int)ParseEnum.TargetID.ConjuredAmalgamate);

            if (ca == null)
            {
                throw new InvalidOperationException("Conjured Amalgamate not found");
            }
            phases[0].Targets.Add(ca);
            if (!requirePhases)
            {
                return(phases);
            }
            phases.AddRange(GetPhasesByInvul(log, 52255, ca, true, false));
            for (int i = 1; i < phases.Count; i++)
            {
                string    name;
                PhaseData phase = phases[i];
                if (i % 2 == 1)
                {
                    name = "Arm Phase";
                }
                else
                {
                    name = "Burn Phase";
                    phase.Targets.Add(ca);
                }
                phase.Name = name;
            }
            NPC leftArm = Targets.Find(x => x.ID == (int)ParseEnum.TargetID.CALeftArm);

            if (leftArm != null)
            {
                List <long> targetables = GetTargetableTimes(log, leftArm);
                for (int i = 1; i < phases.Count; i += 2)
                {
                    PhaseData phase = phases[i];
                    if (targetables.Exists(x => phase.InInterval(x)))
                    {
                        phase.Name = "Left " + phase.Name;
                        phase.Targets.Add(leftArm);
                    }
                }
            }
            NPC rightArm = Targets.Find(x => x.ID == (int)ParseEnum.TargetID.CARightArm);

            if (rightArm != null)
            {
                List <long> targetables = GetTargetableTimes(log, rightArm);
                for (int i = 1; i < phases.Count; i += 2)
                {
                    PhaseData phase = phases[i];
                    if (targetables.Exists(x => phase.InInterval(x)))
                    {
                        if (phase.Name.Contains("Left"))
                        {
                            phase.Name = "Both Arms Phase";
                        }
                        else
                        {
                            phase.Name = "Right " + phase.Name;
                        }
                        phase.Targets.Add(rightArm);
                    }
                }
            }
            return(phases);
        }
예제 #22
0
 public virtual void ComputeAdditionalPlayerData(Player p, ParsedLog log)
 {
 }
예제 #23
0
 public abstract void ComputeAdditionalThrashMobData(Mob mob, ParsedLog log);
예제 #24
0
        public static List <JsonDamageModifierData> GetDamageModifiers(Dictionary <string, List <DamageModifierStat> > damageModDict, ParsedLog log, Dictionary <string, JsonLog.DamageModDesc> damageModDesc)
        {
            var dict = new Dictionary <int, List <JsonDamageModifierItem> >();

            foreach (string key in damageModDict.Keys)
            {
                int    iKey = key.GetHashCode();
                string nKey = "d" + iKey;
                if (!damageModDesc.ContainsKey(nKey))
                {
                    damageModDesc[nKey] = new JsonLog.DamageModDesc(log.DamageModifiers.DamageModifiersByName[key]);
                }
                dict[iKey] = damageModDict[key].Select(x => new JsonDamageModifierItem(x)).ToList();
            }
            var res = new List <JsonDamageModifierData>();

            foreach (KeyValuePair <int, List <JsonDamageModifierItem> > pair in dict)
            {
                res.Add(new JsonDamageModifierData(pair.Key, pair.Value));
            }
            return(res);
        }
예제 #25
0
 public abstract void ComputeAdditionalPlayerData(Player p, ParsedLog log);
예제 #26
0
        public static List <JsonDamageModifierData>[] GetDamageModifiersTarget(Player player, ParsedLog log, Dictionary <string, JsonLog.DamageModDesc> damageModDesc)
        {
            var res = new List <JsonDamageModifierData> [log.FightData.Logic.Targets.Count];

            for (int i = 0; i < log.FightData.Logic.Targets.Count; i++)
            {
                NPC tar = log.FightData.Logic.Targets[i];
                res[i] = GetDamageModifiers(player.GetDamageModifierStats(log, tar), log, damageModDesc);
            }
            return(res);
        }
예제 #27
0
        public void ComputeMechanics(ParsedLog log)
        {
            MechanicData mechData   = log.MechanicData;
            CombatData   combatData = log.CombatData;

            Mechanic.CheckSpecialCondition condition;
            HashSet <ushort> playersIds = log.PlayerIDs;
            Dictionary <ushort, DummyActor> regroupedMobs = new Dictionary <ushort, DummyActor>();

            foreach (Mechanic mech in MechanicList)
            {
                switch (mech.MechanicType)
                {
                case Mechanic.MechType.PlayerStatus:
                    foreach (Player p in log.PlayerList)
                    {
                        List <CombatItem> cList = new List <CombatItem>();
                        switch (mech.SkillId)
                        {
                        case SkillItem.DeathId:
                            cList = combatData.GetStatesData(p.InstID, ParseEnum.StateChange.ChangeDead, log.FightData.FightStart, log.FightData.FightEnd);
                            break;

                        case SkillItem.DownId:
                            cList = combatData.GetStatesData(p.InstID, ParseEnum.StateChange.ChangeDown, log.FightData.FightStart, log.FightData.FightEnd);
                            List <CombatItem> downByVaporForm = combatData.GetBoonData(5620).Where(x => x.SrcInstid == p.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.All).ToList();
                            foreach (CombatItem c in downByVaporForm)
                            {
                                cList.RemoveAll(x => Math.Abs(x.Time - c.Time) < 20);
                            }
                            break;

                        case SkillItem.ResurrectId:
                            cList = log.GetCastData(p.InstID, log.FightData.FightStart, log.FightData.FightEnd).Where(x => x.SkillID == SkillItem.ResurrectId && x.IsActivation.StartCasting()).ToList();
                            break;
                        }
                        foreach (CombatItem mechItem in cList)
                        {
                            mechData[mech].Add(new MechanicLog(log.FightData.ToFightSpace(mechItem.Time), mech, p));
                        }
                    }
                    break;

                case Mechanic.MechType.SkillOnPlayer:
                    foreach (Player p in log.PlayerList)
                    {
                        List <DamageLog> dls = p.GetDamageTakenLogs(null, log, 0, log.FightData.FightDuration);
                        condition = mech.SpecialCondition;
                        foreach (DamageLog dLog in dls)
                        {
                            if (condition != null && !condition(new SpecialConditionItem(dLog)))
                            {
                                continue;
                            }
                            if (dLog.SkillId == mech.SkillId && dLog.Result.IsHit())
                            {
                                mechData[mech].Add(new MechanicLog(dLog.Time, mech, p));
                            }
                        }
                    }
                    break;

                case Mechanic.MechType.PlayerBoon:
                case Mechanic.MechType.PlayerOnPlayer:
                case Mechanic.MechType.PlayerBoonRemove:
                    foreach (Player p in log.PlayerList)
                    {
                        condition = mech.SpecialCondition;
                        foreach (CombatItem c in log.GetBoonData(mech.SkillId))
                        {
                            if (condition != null && !condition(new SpecialConditionItem(c)))
                            {
                                continue;
                            }
                            if (mech.MechanicType == Mechanic.MechType.PlayerBoonRemove)
                            {
                                if (c.IsBuffRemove == ParseEnum.BuffRemove.Manual && p.InstID == c.SrcInstid)
                                {
                                    mechData[mech].Add(new MechanicLog(log.FightData.ToFightSpace(c.Time), mech, p));
                                }
                            }
                            else
                            {
                                if (c.IsBuffRemove == ParseEnum.BuffRemove.None && p.InstID == c.DstInstid)
                                {
                                    mechData[mech].Add(new MechanicLog(log.FightData.ToFightSpace(c.Time), mech, p));
                                    if (mech.MechanicType == Mechanic.MechType.PlayerOnPlayer)
                                    {
                                        mechData[mech].Add(new MechanicLog(log.FightData.ToFightSpace(c.Time), mech, log.PlayerList.FirstOrDefault(x => x.InstID == c.SrcInstid)));
                                    }
                                }
                            }
                        }
                    }
                    break;

                case Mechanic.MechType.HitOnEnemy:
                    foreach (Player p in log.PlayerList)
                    {
                        condition = mech.SpecialCondition;
                        IEnumerable <AgentItem> agents = log.AgentData.GetAgentsByID((ushort)mech.SkillId);
                        foreach (AgentItem a in agents)
                        {
                            foreach (DamageLog dl in p.GetDamageLogs(null, log, 0, log.FightData.FightDuration))
                            {
                                if (dl.DstInstId != a.InstID || dl.IsIndirectDamage || dl.Time < log.FightData.ToFightSpace(a.FirstAware) || dl.Time > log.FightData.ToFightSpace(a.LastAware) || (condition != null && !condition(new SpecialConditionItem(dl))))
                                {
                                    continue;
                                }
                                mechData[mech].Add(new MechanicLog(dl.Time, mech, p));
                            }
                        }
                    }
                    break;

                case Mechanic.MechType.PlayerSkill:
                    foreach (Player p in log.PlayerList)
                    {
                        condition = mech.SpecialCondition;
                        foreach (CombatItem c in log.GetCastDataById(mech.SkillId))
                        {
                            if (condition != null && !condition(new SpecialConditionItem(c)))
                            {
                                continue;
                            }
                            if (c.IsActivation.StartCasting() && c.SrcInstid == p.InstID)
                            {
                                mechData[mech].Add(new MechanicLog(log.FightData.ToFightSpace(c.Time), mech, p));
                            }
                        }
                    }
                    break;

                case Mechanic.MechType.EnemyBoon:
                case Mechanic.MechType.EnemyBoonStrip:
                    condition = mech.SpecialCondition;
                    foreach (CombatItem c in log.GetBoonData(mech.SkillId))
                    {
                        if (condition != null && !condition(new SpecialConditionItem(c)))
                        {
                            continue;
                        }
                        DummyActor amp = null;
                        if (mech.MechanicType == Mechanic.MechType.EnemyBoon && c.IsBuffRemove == ParseEnum.BuffRemove.None)
                        {
                            Target target = Targets.Find(x => x.InstID == c.DstInstid && x.FirstAware <= c.Time && x.LastAware >= c.Time);
                            if (target != null)
                            {
                                amp = target;
                            }
                            else
                            {
                                AgentItem a = log.AgentData.GetAgent(c.DstAgent, c.Time);
                                if (playersIds.Contains(a.InstID))
                                {
                                    continue;
                                }
                                else if (a.MasterAgent != 0)
                                {
                                    AgentItem m = log.AgentData.GetAgent(a.MasterAgent, c.Time);
                                    if (playersIds.Contains(m.InstID))
                                    {
                                        continue;
                                    }
                                }
                                if (!regroupedMobs.TryGetValue(a.ID, out amp))
                                {
                                    amp = new DummyActor(a);
                                    regroupedMobs.Add(a.ID, amp);
                                }
                            }
                        }
                        else if (mech.MechanicType == Mechanic.MechType.EnemyBoonStrip && c.IsBuffRemove == ParseEnum.BuffRemove.Manual)
                        {
                            Target target = Targets.Find(x => x.InstID == c.SrcInstid && x.FirstAware <= c.Time && x.LastAware >= c.Time);
                            if (target != null)
                            {
                                amp = target;
                            }
                            else
                            {
                                AgentItem a = log.AgentData.GetAgent(c.SrcAgent, c.Time);
                                if (playersIds.Contains(a.InstID))
                                {
                                    continue;
                                }
                                else if (a.MasterAgent != 0)
                                {
                                    AgentItem m = log.AgentData.GetAgent(a.MasterAgent, c.Time);
                                    if (playersIds.Contains(m.InstID))
                                    {
                                        continue;
                                    }
                                }
                                if (!regroupedMobs.TryGetValue(a.ID, out amp))
                                {
                                    amp = new DummyActor(a);
                                    regroupedMobs.Add(a.ID, amp);
                                }
                            }
                        }
                        if (amp != null)
                        {
                            mechData[mech].Add(new MechanicLog(log.FightData.ToFightSpace(c.Time), mech, amp));
                        }
                    }
                    break;

                case Mechanic.MechType.EnemyCastEnd:
                case Mechanic.MechType.EnemyCastStart:
                    condition = mech.SpecialCondition;
                    foreach (CombatItem c in log.GetCastDataById(mech.SkillId))
                    {
                        if (condition != null && !condition(new SpecialConditionItem(c)))
                        {
                            continue;
                        }
                        DummyActor amp = null;
                        if ((mech.MechanicType == Mechanic.MechType.EnemyCastStart && c.IsActivation.StartCasting()) || (mech.MechanicType == Mechanic.MechType.EnemyCastEnd && !c.IsActivation.StartCasting()))
                        {
                            Target target = Targets.Find(x => x.InstID == c.SrcInstid && x.FirstAware <= c.Time && x.LastAware >= c.Time);
                            if (target != null)
                            {
                                amp = target;
                            }
                            else
                            {
                                AgentItem a = log.AgentData.GetAgent(c.SrcAgent, c.Time);
                                if (playersIds.Contains(a.InstID))
                                {
                                    continue;
                                }
                                else if (a.MasterAgent != 0)
                                {
                                    AgentItem m = log.AgentData.GetAgent(a.MasterAgent, c.Time);
                                    if (playersIds.Contains(m.InstID))
                                    {
                                        continue;
                                    }
                                }
                                if (!regroupedMobs.TryGetValue(a.ID, out amp))
                                {
                                    amp = new DummyActor(a);
                                    regroupedMobs.Add(a.ID, amp);
                                }
                            }
                        }
                        if (amp != null)
                        {
                            mechData[mech].Add(new MechanicLog(log.FightData.ToFightSpace(c.Time), mech, amp));
                        }
                    }
                    break;

                case Mechanic.MechType.Spawn:
                    foreach (AgentItem a in log.AgentData.GetAgentByType(AgentItem.AgentType.NPC).Where(x => x.ID == mech.SkillId))
                    {
                        if (!regroupedMobs.TryGetValue(a.ID, out DummyActor amp))
                        {
                            amp = new DummyActor(a);
                            regroupedMobs.Add(a.ID, amp);
                        }
                        mechData[mech].Add(new MechanicLog(log.FightData.ToFightSpace(a.FirstAware), mech, amp));
                    }
                    break;
                }
            }
            mechData.ComputePresentMechanics(log);
        }
        public override void ComputeAdditionalBossData(Boss boss, ParsedLog log)
        {
            // TODO: correct position
            CombatReplay   replay = boss.CombatReplay;
            List <CastLog> cls    = boss.GetCastLogs(log, 0, log.FightData.FightDuration);

            switch (boss.ID)
            {
            case (ushort)ParseEnum.BossIDS.Dhuum:
                List <CastLog> deathmark  = cls.Where(x => x.SkillId == 48176).ToList();
                CastLog        majorSplit = cls.Find(x => x.SkillId == 47396);
                foreach (CastLog c in deathmark)
                {
                    int start      = (int)c.Time;
                    int zoneActive = start + 1550;
                    int zoneDeadly = zoneActive + 6000;     //point where the zone becomes impossible to walk through unscathed
                    int zoneEnd    = zoneActive + 120000;
                    int radius     = 450;
                    if (majorSplit != null)
                    {
                        zoneEnd    = Math.Min(zoneEnd, (int)majorSplit.Time);
                        zoneDeadly = Math.Min(zoneDeadly, (int)majorSplit.Time);
                    }
                    int     spellCenterDistance = 200; //hitbox radius
                    Point3D facing       = replay.Rotations.LastOrDefault(x => x.Time <= start + 3000);
                    Point3D bossPosition = replay.Positions.LastOrDefault(x => x.Time <= start + 3000);
                    if (facing != null && bossPosition != null)
                    {
                        Point3D position = new Point3D(bossPosition.X + (facing.X * spellCenterDistance), bossPosition.Y + (facing.Y * spellCenterDistance), bossPosition.Z, bossPosition.Time);
                        replay.Actors.Add(new CircleActor(true, zoneActive, radius, new Tuple <int, int>(start, zoneActive), "rgba(200, 255, 100, 0.5)", new PositionConnector(position)));
                        replay.Actors.Add(new CircleActor(false, 0, radius, new Tuple <int, int>(start, zoneActive), "rgba(200, 255, 100, 0.5)", new PositionConnector(position)));
                        replay.Actors.Add(new CircleActor(true, 0, radius, new Tuple <int, int>(zoneActive, zoneDeadly), "rgba(200, 255, 100, 0.5)", new PositionConnector(position)));
                        replay.Actors.Add(new CircleActor(true, 0, radius, new Tuple <int, int>(zoneDeadly, zoneEnd), "rgba(255, 100, 0, 0.5)", new PositionConnector(position)));
                    }
                }
                List <CastLog> cataCycle = cls.Where(x => x.SkillId == 48398).ToList();
                foreach (CastLog c in cataCycle)
                {
                    int start = (int)c.Time;
                    int end   = start + c.ActualDuration;
                    replay.Actors.Add(new CircleActor(true, end, 300, new Tuple <int, int>(start, end), "rgba(255, 150, 0, 0.7)", new AgentConnector(boss)));
                    replay.Actors.Add(new CircleActor(true, 0, 300, new Tuple <int, int>(start, end), "rgba(255, 150, 0, 0.5)", new AgentConnector(boss)));
                }
                List <CastLog> slash = cls.Where(x => x.SkillId == 47561).ToList();
                foreach (CastLog c in slash)
                {
                    int     start  = (int)c.Time;
                    int     end    = start + c.ActualDuration;
                    Point3D facing = replay.Rotations.FirstOrDefault(x => x.Time >= start);
                    if (facing == null)
                    {
                        continue;
                    }
                    replay.Actors.Add(new PieActor(false, 0, 850, facing, 60, new Tuple <int, int>(start, end), "rgba(255, 150, 0, 0.5)", new AgentConnector(boss)));
                }

                if (majorSplit != null)
                {
                    int start = (int)majorSplit.Time;
                    int end   = (int)log.FightData.FightDuration;
                    replay.Actors.Add(new CircleActor(true, 0, 320, new Tuple <int, int>(start, end), "rgba(0, 180, 255, 0.2)", new AgentConnector(boss)));
                }
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
        public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases)
        {
            List <PhaseData> phases = GetInitialPhase(log);
            NPC fraenir             = Targets.Find(x => x.ID == (int)ParseEnum.TargetID.FraenirOfJormag);

            if (fraenir == null)
            {
                throw new InvalidOperationException("Fraenir of Jormag not found");
            }
            phases[0].Targets.Add(fraenir);
            NPC icebrood = Targets.Find(x => x.ID == (int)ParseEnum.TargetID.IcebroodConstructFraenir);

            if (icebrood != null)
            {
                phases[0].Targets.Add(icebrood);
            }
            if (!requirePhases)
            {
                return(phases);
            }
            AbstractBuffEvent invulApplyFraenir = log.CombatData.GetBuffData(762).Where(x => x.To == fraenir.AgentItem && x is BuffApplyEvent).FirstOrDefault();

            if (invulApplyFraenir != null)
            {
                // split happened
                phases.Add(new PhaseData(0, invulApplyFraenir.Time, "Fraenir 1"));
                if (icebrood != null)
                {
                    // icebrood enters combat
                    EnterCombatEvent enterCombatIce = log.CombatData.GetEnterCombatEvents(icebrood.AgentItem).LastOrDefault();
                    if (enterCombatIce != null)
                    {
                        // icebrood phasing
                        AbstractBuffEvent invulApplyIce  = log.CombatData.GetBuffData(757).Where(x => x.To == icebrood.AgentItem && x is BuffApplyEvent).FirstOrDefault();
                        AbstractBuffEvent invulRemoveIce = log.CombatData.GetBuffData(757).Where(x => x.To == icebrood.AgentItem && x is BuffRemoveAllEvent).FirstOrDefault();
                        long icebroodStart = enterCombatIce.Time;
                        long icebroodEnd   = log.FightData.FightEnd;
                        if (invulApplyIce != null && invulRemoveIce != null)
                        {
                            long icebrood2Start = invulRemoveIce.Time;
                            phases.Add(new PhaseData(icebroodStart + 1, invulApplyIce.Time, "Icebrood 1"));
                            AbstractBuffEvent invulRemoveFraenir = log.CombatData.GetBuffData(762).Where(x => x.To == fraenir.AgentItem && x is BuffRemoveAllEvent).FirstOrDefault();
                            if (invulRemoveFraenir != null)
                            {
                                // fraenir came back
                                DeadEvent deadIce = log.CombatData.GetDeadEvents(icebrood.AgentItem).LastOrDefault();
                                if (deadIce != null)
                                {
                                    icebroodEnd = deadIce.Time;
                                }
                                else
                                {
                                    icebroodEnd = invulRemoveFraenir.Time - 1;
                                }
                                phases.Add(new PhaseData(invulRemoveFraenir.Time, log.FightData.FightEnd, "Fraenir 2"));
                            }
                            phases.Add(new PhaseData(icebrood2Start, icebroodEnd, "Icebrood 2"));
                        }
                        phases.Add(new PhaseData(icebroodStart, icebroodEnd, "Icebrood"));
                    }
                }
            }
            phases.Sort((x, y) => x.Start.CompareTo(y.Start));
            for (int i = 1; i < phases.Count; i++)
            {
                PhaseData phase = phases[i];
                if (i == 1 || i == 5)
                {
                    phase.Targets.Add(fraenir);
                }
                else
                {
                    phase.Targets.Add(icebrood);
                }
            }
            return(phases);
        }
 public AgentItem TryFindSrc(AgentItem dst, long time, long extension, ParsedLog log, long buffID)
 {
     return(_buffSourceFinder.TryFindSrc(dst, time, extension, log, buffID));
 }