// protected static List <CombatItem> GetFilteredList(ParsedLog log, long skillID, AbstractMasterPlayer target) { bool needStart = true; List <CombatItem> main = log.GetBoonData(skillID).Where(x => ((x.DstInstid == target.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.None) || (x.SrcInstid == target.InstID && x.IsBuffRemove != ParseEnum.BuffRemove.None)) && x.Time >= target.FirstAware && x.Time <= target.LastAware).ToList(); List <CombatItem> filtered = new List <CombatItem>(); for (int i = 0; i < main.Count; i++) { CombatItem c = main[i]; if (needStart && c.IsBuffRemove == ParseEnum.BuffRemove.None) { needStart = false; filtered.Add(c); } else if (!needStart && c.IsBuffRemove != ParseEnum.BuffRemove.None) { // consider only last remove event before another application if ((i == main.Count - 1) || (i < main.Count - 1 && main[i + 1].IsBuffRemove == ParseEnum.BuffRemove.None)) { needStart = true; filtered.Add(c); } } } return(filtered); }
public override void ComputeAdditionalTargetData(Target target, ParsedLog log) { // TODO: facing information (shock wave) CombatReplay replay = target.CombatReplay; List <CastLog> cls = target.GetCastLogs(log, 0, log.FightData.FightDuration); switch (target.ID) { case (ushort)ParseEnum.TargetIDS.Samarog: List <CombatItem> brutalize = log.GetBoonData(38226).Where(x => x.IsBuffRemove != ParseEnum.BuffRemove.Manual).ToList(); int brutStart = 0; foreach (CombatItem c in brutalize) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { brutStart = (int)(log.FightData.ToFightSpace(c.Time)); } else { int brutEnd = (int)(log.FightData.ToFightSpace(c.Time)); replay.Actors.Add(new CircleActor(true, 0, 120, (brutStart, brutEnd), "rgba(0, 180, 255, 0.3)", new AgentConnector(target))); } } break; case (ushort)Rigom: case (ushort)Guldhem: break; default: throw new InvalidOperationException("Unknown ID in ComputeAdditionalData"); } }
private void SetConsumablesList(ParsedLog log) { List <Boon> consumableList = Boon.GetConsumableList(); long timeStart = log.FightData.FightStart; long fightDuration = log.FightData.FightEnd - timeStart; foreach (Boon consumable in consumableList) { foreach (CombatItem c in log.GetBoonData(consumable.ID)) { if (c.IsBuffRemove != ParseEnum.BuffRemove.None || (c.IsBuff != 18 && c.IsBuff != 1) || AgentItem.InstID != c.DstInstid) { continue; } long time = 0; if (c.IsBuff != 18) { time = c.Time - timeStart; } if (time <= fightDuration) { _consumeList.Add(new Tuple <Boon, long, int>(consumable, time, c.Value)); } } } _consumeList.Sort((x, y) => x.Item2.CompareTo(y.Item2)); }
public override void ComputeAdditionalPlayerData(Player p, ParsedLog log) { // timed bombs CombatReplay replay = p.CombatReplay; List <CombatItem> timedBombs = log.GetBoonData(31485).Where(x => x.DstInstid == p.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.None).ToList(); foreach (CombatItem c in timedBombs) { int start = (int)(c.Time - log.FightData.FightStart); int end = start + 3000; replay.Actors.Add(new CircleActor(false, 0, 280, new Tuple <int, int>(start, end), "rgba(255, 150, 0, 0.5)", new AgentConnector(p))); replay.Actors.Add(new CircleActor(true, end, 280, new Tuple <int, int>(start, end), "rgba(255, 150, 0, 0.5)", new AgentConnector(p))); } // Sapper bombs List <CombatItem> sapperBombs = GetFilteredList(log, 31473, p); int sapperStart = 0; foreach (CombatItem c in sapperBombs) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { sapperStart = (int)(c.Time - log.FightData.FightStart); } else { int sapperEnd = (int)(c.Time - log.FightData.FightStart); replay.Actors.Add(new CircleActor(false, 0, 180, new Tuple <int, int>(sapperStart, sapperEnd), "rgba(200, 255, 100, 0.5)", new AgentConnector(p))); replay.Actors.Add(new CircleActor(true, sapperStart + 5000, 180, new Tuple <int, int>(sapperStart, sapperEnd), "rgba(200, 255, 100, 0.5)", new AgentConnector(p))); } } }
private void SetConsumablesList(ParsedLog log) { List <Boon> consumableList = Boon.GetConsumableList(); long fightDuration = log.FightData.FightDuration; foreach (Boon consumable in consumableList) { foreach (CombatItem c in log.GetBoonData(consumable.ID)) { if (c.IsBuffRemove != ParseEnum.BuffRemove.None || (c.IsBuff != 18 && c.IsBuff != 1) || AgentItem.InstID != c.DstInstid) { continue; } long time = 0; if (c.IsBuff != 18) { time = log.FightData.ToFightSpace(c.Time); } if (time <= fightDuration) { Consumable existing = _consumeList.Find(x => x.Time == time && x.Item.ID == consumable.ID); if (existing != null) { existing.Stack++; } else { _consumeList.Add(new Consumable(consumable, time, c.Value)); } } } } _consumeList.Sort((x, y) => x.Time.CompareTo(y.Time)); }
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.GetBoonData(34526).FirstOrDefault(); if (heatWave != null) { phases.Add(new PhaseData(0, log.FightData.ToFightSpace(heatWave.Time) - 1)); CombatItem downPour = log.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.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 fightDuration = log.FightData.FightDuration; List <PhaseData> phases = GetInitialPhase(log); Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Dhuum); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } // Sometimes the preevent is not in the evtc List <CastLog> castLogs = mainTarget.GetCastLogs(log, 0, log.FightData.FightEnd); List <CastLog> dhuumCast = mainTarget.GetCastLogs(log, 0, 20000); string[] namesDh; if (dhuumCast.Count > 0) { namesDh = new[] { "Main Fight", "Ritual" }; ComputeFightPhases(mainTarget, phases, log, castLogs, fightDuration, 0); } else { CombatItem invulDhuum = log.GetBoonData(762).FirstOrDefault(x => x.IsBuffRemove != ParseEnum.BuffRemove.None && x.SrcInstid == mainTarget.InstID && x.Time > 115000 + log.FightData.FightStart); if (invulDhuum != null) { long end = log.FightData.ToFightSpace(invulDhuum.Time); phases.Add(new PhaseData(0, end)); ComputeFightPhases(mainTarget, phases, log, castLogs, fightDuration, end + 1); } else { phases.Add(new PhaseData(0, fightDuration)); } namesDh = new[] { "Roleplay", "Main Fight", "Ritual" }; } for (int i = 1; i < phases.Count; i++) { phases[i].Name = namesDh[i - 1]; phases[i].Targets.Add(mainTarget); } if (dhuumCast.Count > 0 && phases.Count > 1) { phases.AddRange(GetInBetweenSoulSplits(log, mainTarget, phases[1].Start, phases[1].End)); phases.Sort((x, y) => x.Start.CompareTo(y.Start)); } else if (phases.Count > 2) { phases.AddRange(GetInBetweenSoulSplits(log, mainTarget, phases[2].Start, phases[2].End)); phases.Sort((x, y) => x.Start.CompareTo(y.Start)); } 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); }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { long start = 0; long fightDuration = log.FightData.FightDuration; List <PhaseData> phases = GetInitialPhase(log); Boss mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.BossIDS.Xera); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } // split happened if (log.FightData.PhaseData.Count == 1) { CombatItem invulXera = log.GetBoonData(762).Find(x => x.DstInstid == mainTarget.InstID); if (invulXera == null) { invulXera = log.GetBoonData(34113).Find(x => x.DstInstid == mainTarget.InstID); } long end = invulXera.Time - log.FightData.FightStart; phases.Add(new PhaseData(start, end)); start = log.FightData.PhaseData[0] - log.FightData.FightStart; mainTarget.AddCustomCastLog(new CastLog(end, -5, (int)(start - end), ParseEnum.Activation.None, (int)(start - end), ParseEnum.Activation.None), log); } if (fightDuration - start > 5000 && start >= phases.Last().End) { phases.Add(new PhaseData(start, fightDuration)); } for (int i = 1; i < phases.Count; i++) { phases[i].Name = "Phase " + i; phases[i].DrawArea = true; phases[i].DrawStart = i > 1; phases[i].DrawEnd = i < phases.Count - 1; phases[i].Targets.Add(mainTarget); } return(phases); }
public override void ComputeAdditionalPlayerData(Player p, ParsedLog log) { // shared agony List <CombatItem> agony = log.GetBoonData(38049).Where(x => (x.DstInstid == p.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.None)).ToList(); CombatReplay replay = p.CombatReplay; foreach (CombatItem c in agony) { int agonyStart = (int)log.FightData.ToFightSpace(c.Time); int agonyEnd = agonyStart + 62000; replay.Actors.Add(new CircleActor(false, 0, 220, (agonyStart, agonyEnd), "rgba(255, 0, 0, 0.5)", new AgentConnector(p))); } }
private ushort TryFindSrc(List <CastLog> castsToCheck, long time, long extension, ParsedLog log) { HashSet <long> idsToCheck = new HashSet <long>(); switch (extension) { // SoI case 5000: idsToCheck.Add(10236); break; // Treated True Nature case 3000: idsToCheck.Add(51696); break; // Sand Squall, True Nature, Soulbeast trait case 2000: if (Prof == "Soulbeast") { if (log.PlayerListBySpec.ContainsKey("Herald") || log.PlayerListBySpec.ContainsKey("Tempest")) { return(0); } // if not herald or tempest in squad then can only be the trait return(InstID); } idsToCheck.Add(51696); idsToCheck.Add(29453); break; } List <CastLog> cls = castsToCheck.Where(x => idsToCheck.Contains(x.SkillId) && x.Time <= time && time <= x.Time + x.ActualDuration + 10 && x.EndActivation.NoInterruptEndCasting()).ToList(); if (cls.Count == 1) { CastLog item = cls.First(); if (extension == 2000 && log.PlayerListBySpec.TryGetValue("Tempest", out List <Player> tempests)) { List <CombatItem> magAuraApplications = log.GetBoonData(5684).Where(x => x.IsBuffRemove == ParseEnum.BuffRemove.None && x.IsOffcycle == 0).ToList(); foreach (Player tempest in tempests) { if (magAuraApplications.FirstOrDefault(x => x.SrcInstid == tempest.InstID && Math.Abs(x.Time - time) < 50) != null) { return(0); } } } return(item.SrcInstId); } return(0); }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { long start = 0; long fightDuration = log.FightData.FightDuration; List <PhaseData> phases = GetInitialPhase(log); Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Xera); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } long end = 0; CombatItem invulXera = log.GetBoonData(762).Find(x => x.DstInstid == mainTarget.InstID) ?? log.GetBoonData(34113).Find(x => x.DstInstid == mainTarget.InstID); if (invulXera != null) { end = log.FightData.ToFightSpace(invulXera.Time); phases.Add(new PhaseData(start, end)); // split happened if (_specialSplit > 0) { start = log.FightData.ToFightSpace(_specialSplit); //mainTarget.AddCustomCastLog(end, -5, (int)(start - end), ParseEnum.Activation.None, (int)(start - end), ParseEnum.Activation.None, log); phases.Add(new PhaseData(start, fightDuration)); } } for (int i = 1; i < phases.Count; i++) { phases[i].Name = "Phase " + i; phases[i].Targets.Add(mainTarget); } return(phases); }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { long start = 0; long end = 0; List <PhaseData> phases = GetInitialPhase(log); Target ca = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.ConjuredAmalgamate); if (ca == null) { throw new InvalidOperationException("Conjurate Amalgamate not found"); } phases[0].Targets.Add(ca); if (!requirePhases) { return(phases); } List <CombatItem> CAInvul = GetFilteredList(log, 52255, ca, false); for (int i = 0; i < CAInvul.Count; i++) { CombatItem invul = CAInvul[i]; if (invul.IsBuffRemove != ParseEnum.BuffRemove.None) { end = Math.Min(log.FightData.ToFightSpace(invul.Time), log.FightData.FightDuration); phases.Add(new PhaseData(start, end)); if (i == CAInvul.Count - 1) { phases.Add(new PhaseData(end, log.FightData.FightDuration)); } } else { start = Math.Min(log.FightData.ToFightSpace(invul.Time), log.FightData.FightDuration); phases.Add(new PhaseData(end, start)); if (i == CAInvul.Count - 1) { phases.Add(new PhaseData(start, log.FightData.FightDuration)); } } } phases.RemoveAll(x => x.GetDuration() < 1000); 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; } Target leftArm = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.CALeftArm); if (leftArm != null) { List <long> leftArmDown = log.GetBoonData(52430).Where(x => x.IsBuffRemove == ParseEnum.BuffRemove.All && x.SrcInstid == leftArm.InstID).Select(x => log.FightData.ToFightSpace(x.Time)).ToList(); for (int i = 1; i < phases.Count; i += 2) { PhaseData phase = phases[i]; if (leftArmDown.Exists(x => phase.InInterval(x))) { phase.Name = "Left " + phase.Name; phase.Targets.Add(leftArm); } } } Target rightArm = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.CARightArm); if (rightArm != null) { List <long> rightArmDown = log.GetBoonData(52430).Where(x => x.IsBuffRemove == ParseEnum.BuffRemove.All && x.SrcInstid == rightArm.InstID).Select(x => log.FightData.ToFightSpace(x.Time)).ToList(); for (int i = 1; i < phases.Count; i += 2) { PhaseData phase = phases[i]; if (rightArmDown.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); }
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(); Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.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)(log.FightData.ToFightSpace(c.Time)); 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)(log.FightData.ToFightSpace(removedBuff.Time)); } 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)(log.FightData.ToFightSpace(c.Time)); } else { int bombDhuumEnd = (int)(log.FightData.ToFightSpace(c.Time)); 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)(log.FightData.ToFightSpace(c.Time)); shacklesTarget = log.PlayerList.FirstOrDefault(x => x.Agent == c.SrcAgent); } else { int shacklesEnd = (int)(log.FightData.ToFightSpace(c.Time)); 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)(log.FightData.ToFightSpace(c.Time)); shacklesDmgTarget = log.PlayerList.FirstOrDefault(x => x.Agent == c.SrcAgent); } else { int shacklesDmgEnd = (int)(log.FightData.ToFightSpace(c.Time)); 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))); } } } }
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.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.GetBoonData(762).Find(x => x.IsBuffRemove == ParseEnum.BuffRemove.None && x.DstInstid == mainTarget.InstID); if (invulDei != null) { end = invulDei.Time - log.FightData.FightStart; phases.Add(new PhaseData(start, end)); start = (log.FightData.PhaseData.Count == 1 ? log.FightData.PhaseData[0] - log.FightData.FightStart : fightDuration); mainTarget.AddCustomCastLog(new CastLog(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)); } for (int i = 1; i < phases.Count; i++) { phases[i].Name = "Phase " + i; phases[i].Targets.Add(mainTarget); if (i == 2) { phases[i].DrawArea = true; } } int offsetDei = phases.Count; CombatItem teleport = log.GetBoonData(38169).FirstOrDefault(x => x.Time > log.FightData.FightStart); int splits = 0; while (teleport != null && splits < 3) { start = teleport.Time - log.FightData.FightStart; CombatItem teleportBack = log.GetBoonData(38169).FirstOrDefault(x => x.Time - log.FightData.FightStart > start + 10000); if (teleportBack != null) { end = Math.Min(teleportBack.Time - log.FightData.FightStart, fightDuration); } else { end = fightDuration; } phases.Add(new PhaseData(start, end)); splits++; teleport = log.GetBoonData(38169).FirstOrDefault(x => x.Time - log.FightData.FightStart > end + 10000); } string[] namesDeiSplit = new [] { "Thief", "Gambler", "Drunkard" }; for (int i = offsetDei; i < phases.Count; i++) { PhaseData phase = phases[i]; phase.Name = namesDeiSplit[i - offsetDei]; phase.DrawArea = true; List <ushort> ids = new List <ushort> { (ushort)Thief, (ushort)Drunkard, (ushort)Gambler, }; AddTargetsToPhase(phase, ids, log); } phases.Sort((x, y) => (x.Start < y.Start) ? -1 : 1); foreach (PhaseData phase in phases) { phase.DrawStart = true; phase.DrawEnd = true; } phases.RemoveAll(x => x.Targets.Count == 0); return(phases); }
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, new Tuple <int, int>(start, end), "rgba(255, 125, 0, 0.5)", new AgentConnector(target))); replay.Actors.Add(new CircleActor(false, 0, 600, new Tuple <int, int>(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, new Tuple <int, int>(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, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos))); replay.Actors.Add(new CircleActor(true, 0, 360, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos))); } if (pattern.Contains("2")) { replay.Actors.Add(new DoughnutActor(true, explosion, 360, 720, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos))); replay.Actors.Add(new DoughnutActor(true, 0, 360, 720, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos))); } if (pattern.Contains("3")) { replay.Actors.Add(new DoughnutActor(true, explosion, 720, 1080, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos))); replay.Actors.Add(new DoughnutActor(true, 0, 720, 1080, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos))); } if (pattern.Contains("4")) { replay.Actors.Add(new DoughnutActor(true, explosion, 1080, 1440, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos))); replay.Actors.Add(new DoughnutActor(true, 0, 1080, 1440, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.4)", new PositionConnector(pos))); } if (pattern.Contains("5")) { replay.Actors.Add(new DoughnutActor(true, explosion, 1440, 1800, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos))); replay.Actors.Add(new DoughnutActor(true, 0, 1440, 1800, new Tuple <int, int>(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, new Tuple <int, int>(tickStart, tickEnd), "rgba(25,25,112, 0.2)", new PositionConnector(pos))); replay.Actors.Add(new CircleActor(true, 0, 1800, new Tuple <int, int>(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, new Tuple <int, int>(start, end), "rgba(255, 0, 0, 0.2)", new AgentConnector(target))); replay.Actors.Add(new CircleActor(true, 0, radius, new Tuple <int, int>(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, new Tuple <int, int>(protectionStart, protectionEnd), "rgba(0, 180, 255, 0.5)", new AgentConnector(target))); } } break; case (ushort)ChargedSoul: Tuple <int, int> lifespan = new Tuple <int, int>((int)replay.TimeOffsets.Item1, (int)replay.TimeOffsets.Item2); 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 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.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 List <CastLog> castLogs = mainTarget.GetCastLogs(log, 0, log.FightData.FightEnd); List <CastLog> clsKC = castLogs.Where(x => x.SkillId == 35048).ToList(); foreach (CastLog cl in clsKC) { end = cl.Time; phases.Add(new PhaseData(start, end)); 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 = c.Time - log.FightData.FightStart; } orbCount++; } else if (start != 0) { segments.Add(new BoonsGraphModel.Segment(start, Math.Min(c.Time - log.FightData.FightStart, 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)", DrawArea = true, DrawStart = true, DrawEnd = true }; phase.Targets.Add(mainTarget); phases.Add(phase); } phases.Sort((x, y) => (x.Start < y.Start) ? -1 : 1); phases.Last().DrawEnd = false; return(phases); }
public void ComputeMechanics(ParsedLog log) { MechanicData mechData = log.MechanicData; FightData fightData = log.FightData; CombatData combatData = log.CombatData; long start = fightData.FightStart; long end = fightData.FightEnd; Mechanic.CheckSpecialCondition condition; HashSet <ushort> playersIds = new HashSet <ushort>(log.PlayerList.Select(x => x.InstID)); Dictionary <ushort, AbstractMasterPlayer> regroupedMobs = new Dictionary <ushort, AbstractMasterPlayer>(); 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.GetStates(p.InstID, ParseEnum.StateChange.ChangeDead, start, end); break; case SkillItem.DownId: cList = combatData.GetStates(p.InstID, ParseEnum.StateChange.ChangeDown, start, end); break; case SkillItem.ResurrectId: cList = log.GetCastData(p.InstID).Where(x => x.SkillID == SkillItem.ResurrectId && x.IsActivation.IsCasting()).ToList(); break; } foreach (CombatItem mechItem in cList) { mechData[mech].Add(new MechanicLog(mechItem.Time - start, mech, p)); } } break; case Mechanic.MechType.SkillOnPlayer: foreach (Player p in log.PlayerList) { List <DamageLog> dls = p.GetDamageTakenLogs(log, 0, 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(c.Time - start, mech, p)); } } else { if (c.IsBuffRemove == ParseEnum.BuffRemove.None && p.InstID == c.DstInstid) { mechData[mech].Add(new MechanicLog(c.Time - start, mech, p)); if (mech.MechanicType == Mechanic.MechType.PlayerOnPlayer) { mechData[mech].Add(new MechanicLog(c.Time - start, 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.IsCondi > 0 || dl.Time < a.FirstAware - start || dl.Time > a.LastAware - start || (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.IsCasting() && c.SrcInstid == p.InstID) { mechData[mech].Add(new MechanicLog(c.Time - fightData.FightStart, 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; } AbstractMasterPlayer amp = null; if (mech.MechanicType == Mechanic.MechType.EnemyBoon && c.IsBuffRemove == ParseEnum.BuffRemove.None) { Boss 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); if (playersIds.Contains(a.InstID)) { continue; } else if (a.MasterAgent != 0) { AgentItem m = log.AgentData.GetAgent(a.MasterAgent); if (playersIds.Contains(m.InstID)) { continue; } } if (!regroupedMobs.TryGetValue(a.ID, out amp)) { amp = new DummyPlayer(a); regroupedMobs.Add(a.ID, amp); } } } else if (mech.MechanicType == Mechanic.MechType.EnemyBoonStrip && c.IsBuffRemove == ParseEnum.BuffRemove.Manual) { Boss 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); if (playersIds.Contains(a.InstID)) { continue; } else if (a.MasterAgent != 0) { AgentItem m = log.AgentData.GetAgent(a.MasterAgent); if (playersIds.Contains(m.InstID)) { continue; } } if (!regroupedMobs.TryGetValue(a.ID, out amp)) { amp = new DummyPlayer(a); regroupedMobs.Add(a.ID, amp); } } } if (amp != null) { mechData[mech].Add(new MechanicLog(c.Time - fightData.FightStart, 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; } AbstractMasterPlayer amp = null; if ((mech.MechanicType == Mechanic.MechType.EnemyCastStart && c.IsActivation.IsCasting()) || (mech.MechanicType == Mechanic.MechType.EnemyCastEnd && !c.IsActivation.IsCasting())) { Boss 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); if (playersIds.Contains(a.InstID)) { continue; } else if (a.MasterAgent != 0) { AgentItem m = log.AgentData.GetAgent(a.MasterAgent); if (playersIds.Contains(m.InstID)) { continue; } } if (!regroupedMobs.TryGetValue(a.ID, out amp)) { amp = new DummyPlayer(a); regroupedMobs.Add(a.ID, amp); } } } if (amp != null) { mechData[mech].Add(new MechanicLog(c.Time - fightData.FightStart, 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 AbstractMasterPlayer amp)) { amp = new DummyPlayer(a); regroupedMobs.Add(a.ID, amp); } mechData[mech].Add(new MechanicLog(a.FirstAware - fightData.FightStart, mech, amp)); } break; } } mechData.ComputePresentMechanics(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.Gorseval); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return phases; } // Ghostly protection check List<CombatItem> invulsGorse = log.GetBoonData(31790).Where(x => x.IsBuffRemove != ParseEnum.BuffRemove.Manual).ToList(); for (int i = 0; i < invulsGorse.Count; i++) { CombatItem c = invulsGorse[i]; if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { end = c.Time - log.FightData.FightStart; phases.Add(new PhaseData(start, end)); if (i == invulsGorse.Count - 1) { mainTarget.AddCustomCastLog(new CastLog(end, -5, (int)(fightDuration - end), ParseEnum.Activation.None, (int)(fightDuration - end), ParseEnum.Activation.None), log); } } else { start = c.Time - log.FightData.FightStart; phases.Add(new PhaseData(end, start)); mainTarget.AddCustomCastLog(new CastLog(end, -5, (int)(start - end), ParseEnum.Activation.None, (int)(start - end), ParseEnum.Activation.None), log); } } if (fightDuration - start > 5000 && start >= phases.Last().End) { phases.Add(new PhaseData(start, fightDuration)); } string[] namesGorse = new [] { "Phase 1", "Split 1", "Phase 2", "Split 2", "Phase 3" }; for (int i = 1; i < phases.Count; i++) { PhaseData phase = phases[i]; phase.Name = namesGorse[i - 1]; phase.DrawArea = i == 1 || i == 3 || i == 5; phase.DrawStart = i == 3 || i == 5; phase.DrawEnd = i == 1 || i == 3; if (i == 1 || i == 3 || i == 5) { phase.Targets.Add(mainTarget); } else { List<ushort> ids = new List<ushort> { (ushort) ChargedSoul }; AddTargetsToPhase(phase, ids, log); } } 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 ComputeAdditionalPlayerData(Player p, ParsedLog log) { // big bomb CombatReplay replay = p.CombatReplay; List <CombatItem> bigbomb = log.GetBoonData(37966).Where(x => (x.DstInstid == p.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.None)).ToList(); foreach (CombatItem c in bigbomb) { int bigStart = (int)(log.FightData.ToFightSpace(c.Time)); int bigEnd = bigStart + 6000; replay.Actors.Add(new CircleActor(true, 0, 300, (bigStart, bigEnd), "rgba(150, 80, 0, 0.2)", new AgentConnector(p))); replay.Actors.Add(new CircleActor(true, bigEnd, 300, (bigStart, bigEnd), "rgba(150, 80, 0, 0.2)", new AgentConnector(p))); } // small bomb List <CombatItem> smallbomb = log.GetBoonData(38247).Where(x => (x.DstInstid == p.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.None)).ToList(); foreach (CombatItem c in smallbomb) { int smallStart = (int)(log.FightData.ToFightSpace(c.Time)); int smallEnd = smallStart + 6000; replay.Actors.Add(new CircleActor(true, 0, 80, (smallStart, smallEnd), "rgba(80, 150, 0, 0.3)", new AgentConnector(p))); } // fixated List <CombatItem> fixatedSam = GetFilteredList(log, 37868, p, true); int fixatedSamStart = 0; foreach (CombatItem c in fixatedSam) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { fixatedSamStart = Math.Max((int)(log.FightData.ToFightSpace(c.Time)), 0); } else { int fixatedSamEnd = (int)(log.FightData.ToFightSpace(c.Time)); replay.Actors.Add(new CircleActor(true, 0, 80, (fixatedSamStart, fixatedSamEnd), "rgba(255, 80, 255, 0.3)", new AgentConnector(p))); } } //fixated Ghuldem List <CombatItem> fixatedGuldhem = GetFilteredList(log, 38223, p, true); int fixationGuldhemStart = 0; Target guldhem = null; foreach (CombatItem c in fixatedGuldhem) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { fixationGuldhemStart = (int)(log.FightData.ToFightSpace(c.Time)); guldhem = Targets.FirstOrDefault(x => x.ID == (ushort)ParseEnum.TrashIDS.Guldhem && c.Time >= x.FirstAware && c.Time <= x.LastAware); } else { int fixationGuldhemEnd = (int)(log.FightData.ToFightSpace(c.Time)); if (guldhem != null) { replay.Actors.Add(new LineActor(0, (fixationGuldhemStart, fixationGuldhemEnd), "rgba(255, 100, 0, 0.3)", new AgentConnector(p), new AgentConnector(guldhem))); } } } //fixated Rigom List <CombatItem> fixatedRigom = GetFilteredList(log, 37693, p, true); int fixationRigomStart = 0; Target rigom = null; foreach (CombatItem c in fixatedRigom) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { fixationRigomStart = (int)(log.FightData.ToFightSpace(c.Time)); rigom = Targets.FirstOrDefault(x => x.ID == (ushort)ParseEnum.TrashIDS.Rigom && c.Time >= x.FirstAware && c.Time <= x.LastAware); } else { int fixationRigomEnd = (int)(log.FightData.ToFightSpace(c.Time)); if (rigom != null) { replay.Actors.Add(new LineActor(0, (fixationRigomStart, fixationRigomEnd), "rgba(255, 0, 0, 0.3)", new AgentConnector(p), new AgentConnector(rigom))); } } } }
public override void ComputeAdditionalBossData(Boss boss, ParsedLog log) { // TODO: needs facing information for hadouken CombatReplay replay = boss.CombatReplay; List <CastLog> cls = boss.GetCastLogs(log, 0, log.FightData.FightDuration); switch (boss.ID) { case (ushort)ParseEnum.BossIDS.Matthias: List <CastLog> humanShield = cls.Where(x => x.SkillId == 34468).ToList(); List <int> humanShieldRemoval = log.GetBoonData(34518).Where(x => x.IsBuffRemove == ParseEnum.BuffRemove.All).Select(x => (int)(x.Time - log.FightData.FightStart)).Distinct().ToList(); for (var i = 0; i < humanShield.Count; i++) { var shield = humanShield[i]; if (i < humanShieldRemoval.Count) { int removal = humanShieldRemoval[i]; replay.Actors.Add(new CircleActor(true, 0, 250, new Tuple <int, int>((int)shield.Time, removal), "rgba(255, 0, 255, 0.5)", new AgentConnector(boss))); } else { replay.Actors.Add(new CircleActor(true, 0, 250, new Tuple <int, int>((int)shield.Time, (int)log.FightData.FightDuration), "rgba(255, 0, 255, 0.5)", new AgentConnector(boss))); } } List <CastLog> aboShield = cls.Where(x => x.SkillId == 34510).ToList(); List <int> aboShieldRemoval = log.GetBoonData(34376).Where(x => x.IsBuffRemove == ParseEnum.BuffRemove.All).Select(x => (int)(x.Time - log.FightData.FightStart)).Distinct().ToList(); for (var i = 0; i < aboShield.Count; i++) { var shield = aboShield[i]; if (i < aboShieldRemoval.Count) { int removal = aboShieldRemoval[i]; replay.Actors.Add(new CircleActor(true, 0, 250, new Tuple <int, int>((int)shield.Time, removal), "rgba(255, 0, 255, 0.5)", new AgentConnector(boss))); } else { replay.Actors.Add(new CircleActor(true, 0, 250, new Tuple <int, int>((int)shield.Time, (int)log.FightData.FightDuration), "rgba(255, 0, 255, 0.5)", new AgentConnector(boss))); } } List <CastLog> rageShards = cls.Where(x => x.SkillId == 34404 || x.SkillId == 34411).ToList(); foreach (CastLog c in rageShards) { int start = (int)c.Time; int end = start + c.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> hadouken = cls.Where(x => x.SkillId == 34371 || x.SkillId == 34380).ToList(); foreach (CastLog c in hadouken) { int start = (int)c.Time; int preCastTime = 1000; int duration = 750; int width = 4000; int height = 130; Point3D facing = replay.Rotations.LastOrDefault(x => x.Time <= start + 1000); if (facing != null) { int direction = (int)(Math.Atan2(facing.Y, facing.X) * 180 / Math.PI); replay.Actors.Add(new RotatedRectangleActor(true, 0, width, height, direction, width / 2, new Tuple <int, int>(start, start + preCastTime), "rgba(255, 0, 0, 0.1)", new AgentConnector(boss))); replay.Actors.Add(new RotatedRectangleActor(true, 0, width, height, direction, width / 2, new Tuple <int, int>(start + preCastTime, start + preCastTime + duration), "rgba(255, 0, 0, 0.7)", new AgentConnector(boss))); } } break; default: throw new InvalidOperationException("Unknown ID in ComputeAdditionalData"); } }
public override void ComputeAdditionalPlayerData(Player p, ParsedLog log) { // Corruption CombatReplay replay = p.CombatReplay; List <CombatItem> corruptedMatthias = GetFilteredList(log, 34416, p); corruptedMatthias.AddRange(GetFilteredList(log, 34473, p)); int corruptedMatthiasStart = 0; foreach (CombatItem c in corruptedMatthias) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { corruptedMatthiasStart = (int)(c.Time - log.FightData.FightStart); } else { int corruptedMatthiasEnd = (int)(c.Time - log.FightData.FightStart); replay.Actors.Add(new CircleActor(true, 0, 180, new Tuple <int, int>(corruptedMatthiasStart, corruptedMatthiasEnd), "rgba(255, 150, 0, 0.5)", new AgentConnector(p))); Point3D wellNextPosition = replay.Positions.FirstOrDefault(x => x.Time >= corruptedMatthiasEnd); Point3D wellPrevPosition = replay.Positions.LastOrDefault(x => x.Time <= corruptedMatthiasEnd); if (wellNextPosition != null || wellPrevPosition != null) { replay.Actors.Add(new CircleActor(true, 0, 180, new Tuple <int, int>(corruptedMatthiasEnd, corruptedMatthiasEnd + 100000), "rgba(0, 0, 0, 0.3)", new InterpolatedPositionConnector(wellPrevPosition, wellNextPosition, corruptedMatthiasEnd))); replay.Actors.Add(new CircleActor(true, corruptedMatthiasEnd + 100000, 180, new Tuple <int, int>(corruptedMatthiasEnd, corruptedMatthiasEnd + 100000), "rgba(0, 0, 0, 0.3)", new InterpolatedPositionConnector(wellPrevPosition, wellNextPosition, corruptedMatthiasEnd))); } } } // Well of profane List <CombatItem> wellMatthias = GetFilteredList(log, 34450, p); int wellMatthiasStart = 0; foreach (CombatItem c in wellMatthias) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { wellMatthiasStart = (int)(c.Time - log.FightData.FightStart); } else { int wellMatthiasEnd = (int)(c.Time - log.FightData.FightStart); replay.Actors.Add(new CircleActor(false, 0, 120, new Tuple <int, int>(wellMatthiasStart, wellMatthiasEnd), "rgba(150, 255, 80, 0.5)", new AgentConnector(p))); replay.Actors.Add(new CircleActor(true, wellMatthiasStart + 9000, 120, new Tuple <int, int>(wellMatthiasStart, wellMatthiasEnd), "rgba(150, 255, 80, 0.5)", new AgentConnector(p))); Point3D wellNextPosition = replay.Positions.FirstOrDefault(x => x.Time >= wellMatthiasEnd); Point3D wellPrevPosition = replay.Positions.LastOrDefault(x => x.Time <= wellMatthiasEnd); if (wellNextPosition != null || wellPrevPosition != null) { replay.Actors.Add(new CircleActor(true, 0, 300, new Tuple <int, int>(wellMatthiasEnd, wellMatthiasEnd + 90000), "rgba(255, 0, 50, 0.5)", new InterpolatedPositionConnector(wellPrevPosition, wellNextPosition, wellMatthiasEnd))); } } } // Sacrifice List <CombatItem> sacrificeMatthias = GetFilteredList(log, 34442, p); int sacrificeMatthiasStart = 0; foreach (CombatItem c in sacrificeMatthias) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { sacrificeMatthiasStart = (int)(c.Time - log.FightData.FightStart); } else { int sacrificeMatthiasEnd = (int)(c.Time - log.FightData.FightStart); replay.Actors.Add(new CircleActor(true, 0, 120, new Tuple <int, int>(sacrificeMatthiasStart, sacrificeMatthiasEnd), "rgba(0, 150, 250, 0.2)", new AgentConnector(p))); replay.Actors.Add(new CircleActor(true, sacrificeMatthiasStart + 10000, 120, new Tuple <int, int>(sacrificeMatthiasStart, sacrificeMatthiasEnd), "rgba(0, 150, 250, 0.35)", new AgentConnector(p))); } } // Bombs List <CombatItem> zealousBenediction = log.GetBoonData(34511).Where(x => (x.DstInstid == p.InstID && x.IsBuffRemove == ParseEnum.BuffRemove.None)).ToList(); foreach (CombatItem c in zealousBenediction) { int zealousStart = (int)(c.Time - log.FightData.FightStart); int zealousEnd = zealousStart + 5000; replay.Actors.Add(new CircleActor(true, 0, 180, new Tuple <int, int>(zealousStart, zealousEnd), "rgba(200, 150, 0, 0.2)", new AgentConnector(p))); replay.Actors.Add(new CircleActor(true, zealousEnd, 180, new Tuple <int, int>(zealousStart, zealousEnd), "rgba(200, 150, 0, 0.4)", new AgentConnector(p))); } }
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.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.Targets.Add(mainTarget); tarPhase.OverrideTimes(log); 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); }
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); }