Example #1
0
        public static void WriteCastingItemIcon(StreamWriter sw, CastLog cl, SkillData skillList, PhaseData phase, bool last)
        {
            SkillItem   skill    = skillList.Get(cl.SkillId);
            GW2APISkill skillApi = skill?.ApiSkill;
            float       offset   = (cl.Time - phase.Start) / 1000f;

            if ((skillApi != null && skillApi.slot != "Weapon_1") || skillApi == null)
            {
                sw.Write("{" +
                         "source: '" + skill.Icon + "'," +
                         "xref: 'x'," +
                         "yref: 'y'," +
                         "x: " + Math.Max(offset, 0.0f) + "," +
                         "y: 0," +
                         "sizex: 1.1," +
                         "sizey: 1.1," +
                         "xanchor: 'left'," +
                         "yanchor: 'bottom'" +
                         "}");
            }

            if (!last)
            {
                sw.Write(",");
            }
        }
        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.Matthias);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // Special buff cast check
            CombatItem heatWave = log.CombatData.GetBoonData(34526).FirstOrDefault();

            if (heatWave != null)
            {
                phases.Add(new PhaseData(0, log.FightData.ToFightSpace(heatWave.Time) - 1));
                CombatItem downPour = log.CombatData.GetDamageData(mainTarget.InstID, mainTarget.FirstAware, mainTarget.LastAware).Find(x => x.SkillID == 34554);
                if (downPour != null)
                {
                    phases.Add(new PhaseData(log.FightData.ToFightSpace(heatWave.Time), log.FightData.ToFightSpace(downPour.Time) - 1));
                    List <CastLog> castLogs = mainTarget.GetCastLogs(log, 0, log.FightData.FightEnd);
                    CastLog        abo      = castLogs.Find(x => x.SkillId == 34427);
                    if (abo != null)
                    {
                        phases.Add(new PhaseData(log.FightData.ToFightSpace(downPour.Time), abo.Time - 1));
                        CombatItem invulRemove = log.CombatData.GetBoonDataByDst(mainTarget.InstID, log.FightData.ToLogSpace(abo.Time), log.FightData.ToLogSpace(abo.Time) + 10000).FirstOrDefault(x => x.SkillID == 757 && x.IsBuffRemove != ParseEnum.BuffRemove.None);
                        if (invulRemove != null)
                        {
                            phases.Add(new PhaseData(log.FightData.ToFightSpace(invulRemove.Time), fightDuration));
                        }
                    }
                    else
                    {
                        phases.Add(new PhaseData(log.FightData.ToFightSpace(downPour.Time), fightDuration));
                    }
                }
                else
                {
                    phases.Add(new PhaseData(log.FightData.ToFightSpace(heatWave.Time), fightDuration));
                }
            }
            else
            {
                phases.Add(new PhaseData(0, fightDuration));
            }
            string[] namesMat = new [] { "Ice Phase", "Fire Phase", "Storm Phase", "Abomination Phase" };
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Name      = namesMat[i - 1];
                phases[i].DrawStart = i > 1;
                phases[i].Targets.Add(mainTarget);
            }
            return(phases);
        }
        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.Matthias);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // Special buff cast check
            CombatItem  heatWave    = log.GetBoonData(34526).FirstOrDefault();
            List <long> phaseStarts = new List <long>();

            if (heatWave != null)
            {
                phaseStarts.Add(heatWave.Time - log.FightData.FightStart);
                CombatItem downPour = log.GetDamageData(mainTarget.InstID).Find(x => x.SkillID == 34554);
                if (downPour != null)
                {
                    phaseStarts.Add(downPour.Time - log.FightData.FightStart);
                    List <CastLog> castLogs = mainTarget.GetCastLogs(log, 0, log.FightData.FightEnd);
                    CastLog        abo      = castLogs.Find(x => x.SkillId == 34427);
                    if (abo != null)
                    {
                        phaseStarts.Add(abo.Time);
                    }
                }
            }
            foreach (long t in phaseStarts)
            {
                end = t;
                phases.Add(new PhaseData(start, end));
                // make sure stuff from the precedent phase mix witch each other
                start = t + 1;
            }
            if (fightDuration - start > 5000 && start >= phases.Last().End)
            {
                phases.Add(new PhaseData(start, fightDuration));
            }
            string[] namesMat = new [] { "Ice Phase", "Fire Phase", "Storm Phase", "Abomination Phase" };
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Name      = namesMat[i - 1];
                phases[i].DrawStart = i > 1;
                phases[i].Targets.Add(mainTarget);
            }
            return(phases);
        }
Example #4
0
        // helpers

        public static object[] GetSkillData(CastLog cl, long phaseStart)
        {
            object[] rotEntry = new object[5];
            double   offset   = 0.0;
            double   start    = (cl.Time - phaseStart) / 1000.0;

            rotEntry[0] = start;
            if (start < 0.0)
            {
                offset      = -1000.0 * start;
                rotEntry[0] = 0;
            }
            rotEntry[1] = cl.SkillId;
            rotEntry[2] = cl.ActualDuration - offset;;
            rotEntry[3] = EncodeEndActivation(cl.EndActivation);
            rotEntry[4] = cl.StartActivation == ParseEnum.Activation.Quickness ? 1 : 0;
            return(rotEntry);
        }
Example #5
0
        private void ComputeFightPhases(Target mainTarget, List <PhaseData> phases, ParsedLog log, List <CastLog> castLogs, long fightDuration, long start)
        {
            CastLog shield = castLogs.Find(x => x.SkillId == 47396);

            if (shield != null)
            {
                long end = shield.Time;
                phases.Add(new PhaseData(start, end));
                CastLog firstDamage = castLogs.FirstOrDefault(x => x.SkillId == 47304 && x.Time >= end);
                if (firstDamage != null)
                {
                    phases.Add(new PhaseData(firstDamage.Time, fightDuration));
                }
            }
            else
            {
                phases.Add(new PhaseData(start, fightDuration));
            }
        }
Example #6
0
        private List <PhaseData> GetInBetweenSoulSplits(ParsedLog log, Target dhuum, long mainStart, long mainEnd)
        {
            List <CastLog> cls        = dhuum.GetCastLogs(log, 0, log.FightData.FightDuration);
            List <CastLog> cataCycle  = cls.Where(x => x.SkillId == 48398).ToList();
            List <CastLog> gDeathmark = cls.Where(x => x.SkillId == 48210).ToList();

            if (gDeathmark.Count < cataCycle.Count)
            {
                return(new List <PhaseData>());
            }
            List <PhaseData> phases = new List <PhaseData>();
            long             start  = mainStart;
            long             end    = 0;
            int i = 1;

            foreach (CastLog cl in cataCycle)
            {
                CastLog clDeathmark = gDeathmark[i - 1];
                end = Math.Min(clDeathmark.Time, mainEnd);
                phases.Add(new PhaseData(start, end)
                {
                    Name = "Pre-Soulsplit " + i++
                });
                start = cl.Time + cl.ActualDuration;
            }
            phases.Add(new PhaseData(start, mainEnd)
            {
                Name = "Pre-Ritual"
            });
            foreach (PhaseData phase in phases)
            {
                phase.Targets.Add(dhuum);
            }
            phases.RemoveAll(x => x.DurationInMS <= 2200);
            return(phases);
        }
Example #7
0
        public override void ComputeAdditionalTargetData(Target target, ParsedLog log)
        {
            // TODO: correct position
            CombatReplay   replay = target.CombatReplay;
            List <CastLog> cls    = target.GetCastLogs(log, 0, log.FightData.FightDuration);

            switch (target.ID)
            {
            case (ushort)ParseEnum.TargetIDS.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 targetPosition = replay.Positions.LastOrDefault(x => x.Time <= start + 3000);
                    if (facing != null && targetPosition != null)
                    {
                        Point3D position = new Point3D(targetPosition.X + (facing.X * spellCenterDistance), targetPosition.Y + (facing.Y * spellCenterDistance), targetPosition.Z, targetPosition.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(target)));
                    replay.Actors.Add(new CircleActor(true, 0, 300, new Tuple <int, int>(start, end), "rgba(255, 150, 0, 0.5)", new AgentConnector(target)));
                }
                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(target)));
                }

                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(target)));
                }
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
        public override void ComputeAdditionalBossData(Boss boss, ParsedLog log)
        {
            CombatReplay   replay = boss.CombatReplay;
            List <CastLog> cls    = boss.GetCastLogs(log, 0, log.FightData.FightDuration);

            switch (boss.ID)
            {
            case (ushort)ParseEnum.BossIDS.KeepConstruct:
                List <CastLog> magicCharge  = cls.Where(x => x.SkillId == 35048).ToList();
                List <CastLog> magicExplode = cls.Where(x => x.SkillId == 34894).ToList();
                for (var i = 0; i < magicCharge.Count; i++)
                {
                    CastLog charge = magicCharge[i];
                    if (i < magicExplode.Count)
                    {
                        CastLog fire  = magicExplode[i];
                        int     start = (int)charge.Time;
                        int     end   = (int)fire.Time + fire.ActualDuration;
                        replay.Actors.Add(new CircleActor(false, 0, 300, new Tuple <int, int>(start, end), "rgba(255, 0, 0, 0.5)", new AgentConnector(boss)));
                        replay.Actors.Add(new CircleActor(true, end, 300, new Tuple <int, int>(start, end), "rgba(255, 0, 0, 0.5)", new AgentConnector(boss)));
                    }
                }
                List <CastLog> towerDrop = cls.Where(x => x.SkillId == 35086).ToList();
                foreach (CastLog c in towerDrop)
                {
                    int     start     = (int)c.Time;
                    int     end       = start + c.ActualDuration;
                    int     skillCast = end - 1000;
                    Point3D next      = replay.Positions.FirstOrDefault(x => x.Time >= end);
                    Point3D prev      = replay.Positions.LastOrDefault(x => x.Time <= end);
                    if (prev != null || next != null)
                    {
                        replay.Actors.Add(new CircleActor(false, 0, 400, new Tuple <int, int>(start, skillCast), "rgba(255, 150, 0, 0.5)", new InterpolatedPositionConnector(prev, next, end)));
                        replay.Actors.Add(new CircleActor(true, skillCast, 400, new Tuple <int, int>(start, skillCast), "rgba(255, 150, 0, 0.5)", new InterpolatedPositionConnector(prev, next, end)));
                    }
                }
                List <CastLog> blades1    = cls.Where(x => x.SkillId == 35064).ToList();
                List <CastLog> blades2    = cls.Where(x => x.SkillId == 35137).ToList();
                List <CastLog> blades3    = cls.Where(x => x.SkillId == 34971).ToList();
                int            bladeDelay = 150;
                int            duration   = 1000;
                foreach (CastLog c in blades1)
                {
                    int     ticks  = (int)Math.Max(0, Math.Min(Math.Ceiling((c.ActualDuration - 1150) / 1000.0), 9));
                    int     start  = (int)c.Time + bladeDelay;
                    Point3D facing = replay.Rotations.LastOrDefault(x => x.Time < start + 1000);
                    if (facing == null)
                    {
                        continue;
                    }
                    replay.Actors.Add(new CircleActor(true, 0, 200, new Tuple <int, int>(start, start + (ticks + 1) * 1000), "rgba(255,0,0,0.4)", new AgentConnector(boss)));
                    replay.Actors.Add(new PieActor(true, 0, 1600, facing, 360 * 3 / 32, new Tuple <int, int>(start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss)));    // First blade lasts twice as long
                    for (int i = 1; i < ticks; i++)
                    {
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI + i * 360 / 8), 360 * 3 / 32, new Tuple <int, int>(start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss)));    // First blade lasts longer
                    }
                }
                foreach (CastLog c in blades2)
                {
                    int     ticks  = (int)Math.Max(0, Math.Min(Math.Ceiling((c.ActualDuration - 1150) / 1000.0), 9));
                    int     start  = (int)c.Time + bladeDelay;
                    Point3D facing = replay.Rotations.LastOrDefault(x => x.Time < start + 1000);
                    if (facing == null)
                    {
                        continue;
                    }
                    replay.Actors.Add(new CircleActor(true, 0, 200, new Tuple <int, int>(start, start + (ticks + 1) * 1000), "rgba(255,0,0,0.4)", new AgentConnector(boss)));
                    replay.Actors.Add(new PieActor(true, 0, 1600, facing, 360 * 3 / 32, new Tuple <int, int>(start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss)));                                                            // First blade lasts twice as long
                    replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI), 360 * 3 / 32, new Tuple <int, int>(start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss))); // First blade lasts twice as long
                    for (int i = 1; i < ticks; i++)
                    {
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI + i * 360 / 8), 360 * 3 / 32, new Tuple <int, int>(start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss)));    // First blade lasts longer
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + i * 360 / 8), 360 * 3 / 32, new Tuple <int, int>(start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss)));  // First blade lasts longer
                    }
                }
                foreach (CastLog c in blades3)
                {
                    int     ticks  = (int)Math.Max(0, Math.Min(Math.Ceiling((c.ActualDuration - 1150) / 1000.0), 9));
                    int     start  = (int)c.Time + bladeDelay;
                    Point3D facing = replay.Rotations.LastOrDefault(x => x.Time < start + 1000);
                    if (facing == null)
                    {
                        continue;
                    }
                    replay.Actors.Add(new CircleActor(true, 0, 200, new Tuple <int, int>(start, start + (ticks + 1) * 1000), "rgba(255,0,0,0.4)", new AgentConnector(boss)));
                    replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI), 360 * 3 / 32, new Tuple <int, int>(start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss)));       // First blade lasts twice as long
                    replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + 120), 360 * 3 / 32, new Tuple <int, int>(start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss))); // First blade lasts twice as long
                    replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI - 120), 360 * 3 / 32, new Tuple <int, int>(start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss))); // First blade lasts twice as long
                    for (int i = 1; i < ticks; i++)
                    {
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + i * 360 / 8), 360 * 3 / 32, new Tuple <int, int>(start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss)));       // First blade lasts longer
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + i * 360 / 8 + 120), 360 * 3 / 32, new Tuple <int, int>(start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss))); // First blade lasts longer
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + i * 360 / 8 - 120), 360 * 3 / 32, new Tuple <int, int>(start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(boss))); // First blade lasts longer
                    }
                }
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }
        public static void WriteCastingItem(StreamWriter sw, CastLog cl, SkillData skillList, PhaseData phase)
        {
            GW2APISkill skill     = skillList.Get(cl.SkillId)?.ApiSkill;
            string      skillName = skill == null?skillList.GetName(cl.SkillId) : skill.name;

            float dur;

            if (skillName == "Dodge")
            {
                dur = 0.5f;
            }
            else if (cl.SkillId == SkillItem.WeaponSwapId)
            {
                skillName = "Weapon Swap";
                dur       = 0.1f;
            }
            else
            {
                dur = cl.ActualDuration / 1000f;
            }
            skillName = skillName.Replace("\"", "");
            float offset = (cl.Time - phase.Start) / 1000f;
            float xVal   = dur;

            if (offset < 0.0f)
            {
                xVal += offset;
            }
            xVal = Math.Min(xVal, (phase.End - cl.Time) / 1000f);
            sw.Write("{");
            {
                sw.Write(cl.SkillId == -5 ? "y: ['1']," : "y: ['1.5'],");

                sw.Write(
                    "x: ['" + xVal + "']," +
                    "base:'" + Math.Max(offset, 0.0f) + "'," +
                    "name: \"" + skillName + " " + dur + "s\"," +   //get name should be handled by api
                    "orientation:'h'," +
                    "mode: 'markers'," +
                    "type: 'bar',");
                if (skill != null)
                {
                    sw.Write(skill.slot == "Weapon_1" ? "width:'0.5'," : "width:'1',");
                }
                else
                {
                    sw.Write("width:'1',");
                }
                sw.Write("hoverinfo: 'name'," +
                         "hoverlabel:{namelength:'-1'},");
                sw.Write("marker: {");
                {
                    if (cl.EndActivation == ParseEnum.Activation.CancelFire)
                    {
                        sw.Write("color: 'rgb(40,40,220)',");
                    }
                    else if (cl.EndActivation == ParseEnum.Activation.CancelCancel)
                    {
                        sw.Write("color: 'rgb(220,40,40)',");
                    }
                    else if (cl.EndActivation == ParseEnum.Activation.Reset)
                    {
                        sw.Write("color: 'rgb(40,220,40)',");
                    }
                    else
                    {
                        sw.Write("color: 'rgb(220,220,0)',");
                    }
                    sw.Write("width: '5',");
                    sw.Write("line:{");
                    {
                        if (cl.StartActivation == ParseEnum.Activation.Normal)
                        {
                            sw.Write("color: 'rgb(20,20,20)',");
                        }
                        else if (cl.StartActivation == ParseEnum.Activation.Quickness)
                        {
                            sw.Write("color: 'rgb(220,40,220)',");
                        }
                        sw.Write("width: '1'");
                    }
                    sw.Write("}");
                }
                sw.Write("},");
                sw.Write("showlegend: false");
            }
            sw.Write(" },");
        }
        public static void WriteCastingItemIcon(StreamWriter sw, CastLog cl, SkillData skillList, PhaseData phase, bool last)
        {
            string      skillIcon = "";
            GW2APISkill skill     = skillList.Get(cl.SkillId)?.ApiSkill;

            if (skill != null && cl.SkillId != -2)
            {
                float offset = (cl.Time - phase.Start) / 1000f;
                if (skill.slot != "Weapon_1")
                {
                    skillIcon = skill.icon;
                    sw.Write("{" +
                             "source: '" + skillIcon + "'," +
                             "xref: 'x'," +
                             "yref: 'y'," +
                             "x: " + Math.Max(offset, 0.0f) + "," +
                             "y: 0," +
                             "sizex: 1.1," +
                             "sizey: 1.1," +
                             "xanchor: 'left'," +
                             "yanchor: 'bottom'" +
                             "}");
                }
            }
            else
            {
                string skillName = cl.SkillId == SkillItem.WeaponSwapId ? "Weapon Swap" : skillList.GetName(cl.SkillId);
                if (skillName == "Dodge")
                {
                    skillIcon = GetLink("Dodge");
                }
                else if (skillName == "Resurrect")
                {
                    skillIcon = GetLink("Resurrect");
                }
                else if (skillName == "Bandage")
                {
                    skillIcon = GetLink("Bandage");
                }
                else if (cl.SkillId == SkillItem.WeaponSwapId)
                {
                    skillIcon = GetLink("Swap");
                }

                sw.Write("{" +
                         "source: '" + skillIcon + "'," +
                         "xref: 'x'," +
                         "yref: 'y'," +
                         "x: " + (cl.Time - phase.Start) / 1000f + "," +
                         "y: 0," +
                         "sizex: 1.1," +
                         "sizey: 1.1," +
                         "xanchor: 'left'," +
                         "yanchor: 'bottom'" +
                         "}");
            }
            if (!last)
            {
                sw.Write(",");
            }
        }
Example #11
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.KeepConstruct);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // Main phases 34894
            List <CastLog> castLogs    = mainTarget.GetCastLogs(log, 0, log.FightData.FightEnd);
            List <CastLog> magicCharge = castLogs.Where(x => x.SkillId == 35048).ToList();
            List <CastLog> magicBlast  = castLogs.Where(x => x.SkillId == 34894).ToList();

            foreach (CastLog cl in magicCharge)
            {
                end = cl.Time;
                phases.Add(new PhaseData(start, end));
                CastLog blast = magicBlast.FirstOrDefault(x => x.Time >= cl.Time);
                if (blast != null)
                {
                    start = blast.Time + blast.ActualDuration;
                }
                else
                {
                    start = end + cl.ActualDuration;
                }
            }
            if (fightDuration - start > 5000 && start >= phases.Last().End)
            {
                phases.Add(new PhaseData(start, fightDuration));
                start = fightDuration;
            }
            string[] mainPhaseNames = { "100% - 66%", "66% - 33%", "33% - 0%" };
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Name = mainPhaseNames[i - 1];
                phases[i].Targets.Add(mainTarget);
            }
            // add burn phases
            int offset = phases.Count;
            List <CombatItem> orbItems = log.GetBoonData(35096).Where(x => x.DstInstid == mainTarget.InstID).ToList();

            // Get number of orbs and filter the list
            start = 0;
            int orbCount = 0;
            List <BoonsGraphModel.Segment> segments = new List <BoonsGraphModel.Segment>();

            foreach (CombatItem c in orbItems)
            {
                if (c.IsBuffRemove == ParseEnum.BuffRemove.None)
                {
                    if (start == 0)
                    {
                        start = log.FightData.ToFightSpace(c.Time);
                    }
                    orbCount++;
                }
                else if (start != 0)
                {
                    segments.Add(new BoonsGraphModel.Segment(start, Math.Min(log.FightData.ToFightSpace(c.Time), fightDuration), orbCount));
                    orbCount = 0;
                    start    = 0;
                }
            }
            int burnCount = 1;

            foreach (var seg in segments)
            {
                var phase = new PhaseData(seg.Start, seg.End)
                {
                    Name = "Burn " + burnCount++ + " (" + seg.Value + " orbs)",
                };
                phase.Targets.Add(mainTarget);
                phases.Add(phase);
            }
            phases.Sort((x, y) => x.Start.CompareTo(y.Start));
            // pre burn phases
            int preBurnCount = 1;
            List <PhaseData>  preBurnPhase = new List <PhaseData>();
            List <CombatItem> kcInvuls     = GetFilteredList(log, 762, mainTarget, true);

            foreach (CombatItem invul in kcInvuls)
            {
                if (invul.IsBuffRemove == ParseEnum.BuffRemove.None)
                {
                    end = log.FightData.ToFightSpace(invul.Time);
                    PhaseData prevPhase = phases.LastOrDefault(x => x.Start <= end || x.End <= end);
                    if (prevPhase != null)
                    {
                        start = (prevPhase.End >= end ? prevPhase.Start : prevPhase.End) + 1;
                        if (end - start > 5000)
                        {
                            var phase = new PhaseData(start, end)
                            {
                                Name = "Pre-Burn " + preBurnCount++,
                            };
                            phase.Targets.Add(mainTarget);
                            preBurnPhase.Add(phase);
                        }
                    }
                }
            }
            phases.AddRange(preBurnPhase);
            phases.Sort((x, y) => x.Start.CompareTo(y.Start));
            // add leftover phases
            PhaseData        cur            = null;
            int              leftOverCount  = 1;
            List <PhaseData> leftOverPhases = new List <PhaseData>();

            for (int i = 0; i < phases.Count; i++)
            {
                PhaseData phase = phases[i];
                if (phase.Name.Contains("%"))
                {
                    cur = phase;
                }
                else if (phase.Name.Contains("orbs"))
                {
                    if (cur != null)
                    {
                        if (cur.End >= phase.End + 5000 && (i == phases.Count - 1 || phases[i + 1].Name.Contains("Phase")))
                        {
                            PhaseData leftOverPhase = new PhaseData(phase.End + 1, cur.End)
                            {
                                Name = "Leftover " + leftOverCount++,
                            };
                            leftOverPhase.Targets.Add(mainTarget);
                            leftOverPhases.Add(leftOverPhase);
                        }
                    }
                }
            }
            phases.AddRange(leftOverPhases);
            phases.Sort((x, y) => x.Start.CompareTo(y.Start));
            return(phases);
        }
Example #12
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.KeepConstruct);

            if (mainTarget == null)
            {
                throw new InvalidOperationException("Main target of the fight not found");
            }
            phases[0].Targets.Add(mainTarget);
            if (!requirePhases)
            {
                return(phases);
            }
            // Main phases 34894
            List <CastLog> castLogs    = mainTarget.GetCastLogs(log, 0, log.FightData.FightEnd);
            List <CastLog> magicCharge = castLogs.Where(x => x.SkillId == 35048).ToList();
            List <CastLog> magicBlast  = castLogs.Where(x => x.SkillId == 34894).ToList();

            foreach (CastLog cl in magicCharge)
            {
                end = cl.Time;
                phases.Add(new PhaseData(start, end));
                CastLog blast = magicBlast.FirstOrDefault(x => x.Time >= cl.Time);
                if (blast != null)
                {
                    start = blast.Time + blast.ActualDuration;
                }
                else
                {
                    start = end + cl.ActualDuration;
                }
            }
            if (fightDuration - start > 5000 && start >= phases.Last().End)
            {
                phases.Add(new PhaseData(start, fightDuration));
                start = fightDuration;
            }
            for (int i = 1; i < phases.Count; i++)
            {
                phases[i].Name = "Phase " + i;
                phases[i].Targets.Add(mainTarget);
            }
            // add burn phases
            int offset = phases.Count;
            List <CombatItem> orbItems = log.GetBoonData(35096).Where(x => x.DstInstid == mainTarget.InstID).ToList();

            // Get number of orbs and filter the list
            start = 0;
            int orbCount = 0;
            List <BoonsGraphModel.Segment> segments = new List <BoonsGraphModel.Segment>();

            foreach (CombatItem c in orbItems)
            {
                if (c.IsBuffRemove == ParseEnum.BuffRemove.None)
                {
                    if (start == 0)
                    {
                        start = log.FightData.ToFightSpace(c.Time);
                    }
                    orbCount++;
                }
                else if (start != 0)
                {
                    segments.Add(new BoonsGraphModel.Segment(start, Math.Min(log.FightData.ToFightSpace(c.Time), fightDuration), orbCount));
                    orbCount = 0;
                    start    = 0;
                }
            }
            int burnCount = 1;

            foreach (var seg in segments)
            {
                var phase = new PhaseData(seg.Start, seg.End)
                {
                    Name = "Burn " + burnCount++ + " (" + seg.Value + " orbs)",
                };
                phase.Targets.Add(mainTarget);
                phases.Add(phase);
            }
            phases.Sort((x, y) => (x.Start < y.Start) ? -1 : 1);
            return(phases);
        }
        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);
        }
        public override void ComputeTargetCombatReplayActors(Target target, ParsedLog log, CombatReplay replay)
        {
            List <CastLog> cls = target.GetCastLogs(log, 0, log.FightData.FightDuration);

            switch (target.ID)
            {
            case (ushort)ParseEnum.TargetIDS.KeepConstruct:
                List <CastLog> magicCharge  = cls.Where(x => x.SkillId == 35048).ToList();
                List <CastLog> magicExplode = cls.Where(x => x.SkillId == 34894).ToList();
                for (var i = 0; i < magicCharge.Count; i++)
                {
                    CastLog charge = magicCharge[i];
                    if (i < magicExplode.Count)
                    {
                        CastLog fire  = magicExplode[i];
                        int     start = (int)charge.Time;
                        int     end   = (int)fire.Time + fire.ActualDuration;
                        replay.Actors.Add(new CircleActor(false, 0, 300, (start, end), "rgba(255, 0, 0, 0.5)", new AgentConnector(target)));
                        replay.Actors.Add(new CircleActor(true, end, 300, (start, end), "rgba(255, 0, 0, 0.5)", new AgentConnector(target)));
                    }
                }
                List <CastLog> towerDrop = cls.Where(x => x.SkillId == 35086).ToList();
                foreach (CastLog c in towerDrop)
                {
                    int     start     = (int)c.Time;
                    int     end       = start + c.ActualDuration;
                    int     skillCast = end - 1000;
                    Point3D next      = replay.Positions.FirstOrDefault(x => x.Time >= end);
                    Point3D prev      = replay.Positions.LastOrDefault(x => x.Time <= end);
                    if (prev != null || next != null)
                    {
                        replay.Actors.Add(new CircleActor(false, 0, 400, (start, skillCast), "rgba(255, 150, 0, 0.5)", new InterpolatedPositionConnector(prev, next, end)));
                        replay.Actors.Add(new CircleActor(true, skillCast, 400, (start, skillCast), "rgba(255, 150, 0, 0.5)", new InterpolatedPositionConnector(prev, next, end)));
                    }
                }
                List <CastLog> blades1    = cls.Where(x => x.SkillId == 35064).ToList();
                List <CastLog> blades2    = cls.Where(x => x.SkillId == 35137).ToList();
                List <CastLog> blades3    = cls.Where(x => x.SkillId == 34971).ToList();
                int            bladeDelay = 150;
                int            duration   = 1000;
                foreach (CastLog c in blades1)
                {
                    int     ticks  = (int)Math.Max(0, Math.Min(Math.Ceiling((c.ActualDuration - 1150) / 1000.0), 9));
                    int     start  = (int)c.Time + bladeDelay;
                    Point3D facing = replay.Rotations.LastOrDefault(x => x.Time < start + 1000);
                    if (facing == null)
                    {
                        continue;
                    }
                    replay.Actors.Add(new CircleActor(true, 0, 200, (start, start + (ticks + 1) * 1000), "rgba(255,0,0,0.4)", new AgentConnector(target)));
                    replay.Actors.Add(new PieActor(true, 0, 1600, facing, 360 * 3 / 32, (start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(target)));     // First blade lasts twice as long
                    for (int i = 1; i < ticks; i++)
                    {
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI + i * 360 / 8), 360 * 3 / 32, (start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(target)));     // First blade lasts longer
                    }
                }
                foreach (CastLog c in blades2)
                {
                    int     ticks  = (int)Math.Max(0, Math.Min(Math.Ceiling((c.ActualDuration - 1150) / 1000.0), 9));
                    int     start  = (int)c.Time + bladeDelay;
                    Point3D facing = replay.Rotations.LastOrDefault(x => x.Time < start + 1000);
                    if (facing == null)
                    {
                        continue;
                    }
                    replay.Actors.Add(new CircleActor(true, 0, 200, (start, start + (ticks + 1) * 1000), "rgba(255,0,0,0.4)", new AgentConnector(target)));
                    replay.Actors.Add(new PieActor(true, 0, 1600, facing, 360 * 3 / 32, (start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(target)));                                                            // First blade lasts twice as long
                    replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI), 360 * 3 / 32, (start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(target))); // First blade lasts twice as long
                    for (int i = 1; i < ticks; i++)
                    {
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI + i * 360 / 8), 360 * 3 / 32, (start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(target)));     // First blade lasts longer
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + i * 360 / 8), 360 * 3 / 32, (start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(target)));   // First blade lasts longer
                    }
                }
                foreach (CastLog c in blades3)
                {
                    int     ticks  = (int)Math.Max(0, Math.Min(Math.Ceiling((c.ActualDuration - 1150) / 1000.0), 9));
                    int     start  = (int)c.Time + bladeDelay;
                    Point3D facing = replay.Rotations.LastOrDefault(x => x.Time < start + 1000);
                    if (facing == null)
                    {
                        continue;
                    }
                    replay.Actors.Add(new CircleActor(true, 0, 200, (start, start + (ticks + 1) * 1000), "rgba(255,0,0,0.4)", new AgentConnector(target)));
                    replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI), 360 * 3 / 32, (start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(target)));       // First blade lasts twice as long
                    replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + 120), 360 * 3 / 32, (start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(target))); // First blade lasts twice as long
                    replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI - 120), 360 * 3 / 32, (start, start + 2 * duration), "rgba(255,200,0,0.5)", new AgentConnector(target))); // First blade lasts twice as long
                    for (int i = 1; i < ticks; i++)
                    {
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + i * 360 / 8), 360 * 3 / 32, (start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(target)));       // First blade lasts longer
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + i * 360 / 8 + 120), 360 * 3 / 32, (start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(target))); // First blade lasts longer
                        replay.Actors.Add(new PieActor(true, 0, 1600, (int)Math.Round(Math.Atan2(-facing.Y, -facing.X) * 180 / Math.PI + i * 360 / 8 - 120), 360 * 3 / 32, (start + 1000 + i * duration, start + 1000 + (i + 1) * duration), "rgba(255,200,0,0.5)", new AgentConnector(target))); // First blade lasts longer
                    }
                }
                // phantasms locations
                HashSet <ushort> phantasmsID = new HashSet <ushort>
                {
                    (ushort)Jessica,
                    (ushort)Olson,
                    (ushort)Engul,
                    (ushort)Faerla,
                    (ushort)Caulle,
                    (ushort)Henley,
                    (ushort)Galletta,
                    (ushort)Ianim,
                };
                foreach (Mob m in TrashMobs)
                {
                    if (phantasmsID.Contains(m.ID))
                    {
                        int     start = (int)log.FightData.ToFightSpace(m.FirstAware);
                        Point3D pos   = m.GetCombatReplayPositions(log).FirstOrDefault();
                        if (pos != null)
                        {
                            replay.Actors.Add(new CircleActor(true, 0, 300, (start - 5000, start), "rgba(220, 50, 0, 0.5)", new PositionConnector(pos)));
                            replay.Actors.Add(new CircleActor(true, start, 300, (start - 5000, start), "rgba(220, 50, 0, 0.5)", new PositionConnector(pos)));
                        }
                    }
                }
                break;

            default:
                throw new InvalidOperationException("Unknown ID in ComputeAdditionalData");
            }
        }