public override int IsCM(ParsedLog log) { Target target = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.MursaatOverseer); if (target == null) { throw new InvalidOperationException("Target for CM detection not found"); } OverrideMaxHealths(log); return((target.Health > 25e6) ? 1 : 0); }
public override int IsCM(ParsedLog log) { Boss target = Targets.Find(x => x.ID == (ushort)ParseEnum.BossIDS.Deimos); if (target == null) { throw new InvalidOperationException("Target for CM detection not found"); } OverrideMaxHealths(log); return((target.Health > 40e6) ? 1 : 0); }
public override int IsCM(ParsedEvtcContainer evtcContainer) { Target target = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Dhuum); if (target == null) { throw new InvalidOperationException("Target for CM detection not found"); } OverrideMaxHealths(evtcContainer); return((target.Health > 35e6) ? 1 : 0); }
public virtual List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); NPC mainTarget = Targets.Find(x => x.ID == GenericTriggerID); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); return(phases); }
public override void ComputeAdditionalTrashMobData(Mob mob, ParsedLog log) { CombatReplay replay = mob.CombatReplay; int start = (int)replay.TimeOffsets.start; int end = (int)replay.TimeOffsets.end; switch (mob.ID) { case (ushort)Core: break; case (ushort)Jessica: case (ushort)Olson: case (ushort)Engul: case (ushort)Faerla: case (ushort)Caulle: case (ushort)Henley: case (ushort)Galletta: case (ushort)Ianim: Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.KeepConstruct); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } CombatReplay mtCR = mainTarget.CombatReplay; replay.Actors.Add(new CircleActor(false, 0, 600, (start, end), "rgba(255, 0, 0, 0.5)", new AgentConnector(mob))); replay.Actors.Add(new CircleActor(true, 0, 400, (start, end), "rgba(0, 125, 255, 0.5)", new AgentConnector(mob))); Point3D pos = replay.Positions.FirstOrDefault(); if (pos != null) { mtCR.Actors.Add(new CircleActor(true, 0, 300, (start - 5000, start), "rgba(220, 50, 0, 0.5)", new PositionConnector(pos))); mtCR.Actors.Add(new CircleActor(true, start, 300, (start - 5000, start), "rgba(220, 50, 0, 0.5)", new PositionConnector(pos))); } break; case (ushort)GreenPhantasm: int lifetime = 8000; replay.Actors.Add(new CircleActor(true, 0, 210, (start, start + lifetime), "rgba(0,255,0,0.2)", new AgentConnector(mob))); replay.Actors.Add(new CircleActor(true, start + lifetime, 210, (start, start + lifetime), "rgba(0,255,0,0.3)", new AgentConnector(mob))); break; case (ushort)RetrieverProjection: case (ushort)InsidiousProjection: case (ushort)UnstableLeyRift: case (ushort)RadiantPhantasm: case (ushort)CrimsonPhantasm: break; default: throw new InvalidOperationException("Unknown ID in ComputeAdditionalData"); } }
public override void SpecialParse(FightData fightData, AgentData agentData, List <CombatItem> combatData) { ComputeFightTargets(agentData, combatData); // Find target Target target = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Deimos); if (target == null) { throw new InvalidOperationException("Main target of the fight not found"); } // enter combat CombatItem enterCombat = combatData.FirstOrDefault(x => x.SrcInstid == target.InstID && x.IsStateChange == ParseEnum.StateChange.EnterCombat && x.SrcInstid == target.InstID && x.LogTime <= target.LastAwareLogTime && x.LogTime >= target.FirstAwareLogTime); if (enterCombat != null) { fightData.OverrideStart(enterCombat.LogTime); } // Remove deimos despawn events as they are useless and mess with combat replay combatData.RemoveAll(x => x.IsStateChange == ParseEnum.StateChange.Despawn && x.SrcAgent == target.Agent); // invul correction CombatItem invulApp = combatData.FirstOrDefault(x => x.DstInstid == target.InstID && x.IsBuff != 0 && x.BuffDmg == 0 && x.Value > 0 && x.SkillID == 762); if (invulApp != null) { invulApp.OverrideValue((int)(target.LastAwareLogTime - invulApp.LogTime)); } // Deimos gadgets CombatItem targetable = combatData.LastOrDefault(x => x.IsStateChange == ParseEnum.StateChange.Targetable && x.LogTime > combatData.First().LogTime&& x.DstAgent > 0); HashSet <ulong> gadgetAgents = new HashSet <ulong>(); long firstAware = AttackTargetSpecialParse(targetable, agentData, combatData, gadgetAgents); // legacy method if (firstAware == 0) { CombatItem armDeimosDamageEvent = combatData.FirstOrDefault(x => x.LogTime >= target.LastAwareLogTime && (x.SkillID == 37980 || x.SkillID == 37982 || x.SkillID == 38046) && x.SrcAgent != 0 && x.SrcInstid != 0); if (armDeimosDamageEvent != null) { List <AgentItem> deimosGadgets = agentData.GetAgentByType(AgentItem.AgentType.Gadget).Where(x => x.Name.Contains("Deimos") && x.LastAwareLogTime > armDeimosDamageEvent.LogTime).ToList(); if (deimosGadgets.Count > 0) { firstAware = deimosGadgets.Max(x => x.FirstAwareLogTime); gadgetAgents = new HashSet <ulong>(deimosGadgets.Select(x => x.Agent)); } } } if (gadgetAgents.Count > 0) { _specialSplitLogTime = (firstAware >= target.LastAwareLogTime ? firstAware : target.LastAwareLogTime); SetUniqueID(target.AgentItem, gadgetAgents, agentData, combatData); } target.AgentItem.LastAwareLogTime = combatData.Last().LogTime; }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { long fightDuration = log.FightData.FightDuration; List <PhaseData> phases = GetInitialPhase(log); Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.MursaatOverseer); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } List <int> limit = new List <int>() { 75, 50, 25, 0 }; long start = 0; int i = 0; List <HealthUpdateEvent> hpUpdates = log.CombatData.GetHealthUpdateEvents(mainTarget.AgentItem); for (i = 0; i < limit.Count; i++) { HealthUpdateEvent evt = hpUpdates.FirstOrDefault(x => x.HPPercent <= limit[i]); if (evt == null) { break; } PhaseData phase = new PhaseData(start, Math.Min(evt.Time, fightDuration)) { Name = (25 + limit[i]) + "% - " + limit[i] + "%" }; phase.Targets.Add(mainTarget); phases.Add(phase); start = evt.Time; } if (i < 4) { PhaseData lastPhase = new PhaseData(start, fightDuration) { Name = (25 + limit[i]) + "% -" + limit[i] + "%" }; lastPhase.Targets.Add(mainTarget); phases.Add(lastPhase); } return(phases); }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { long fightDuration = log.FightData.FightDuration; List <PhaseData> phases = GetInitialPhase(log); Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.MursaatOverseer); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } List <int> limit = new List <int>() { 75, 50, 25, 0 }; long start = 0; int i = 0; for (i = 0; i < limit.Count; i++) { (long logTime, int hp) = mainTarget.HealthOverTime.FirstOrDefault(x => x.hp / 100.0 <= limit[i]); if (logTime == 0) { break; } PhaseData phase = new PhaseData(start, Math.Min(log.FightData.ToFightSpace(logTime), fightDuration)) { Name = (25 + limit[i]) + "% - " + limit[i] + "%" }; phase.Targets.Add(mainTarget); phases.Add(phase); start = log.FightData.ToFightSpace(logTime); } if (i < 4) { PhaseData lastPhase = new PhaseData(start, fightDuration) { Name = (25 + limit[i]) + "% -" + limit[i] + "%" }; lastPhase.Targets.Add(mainTarget); phases.Add(lastPhase); } return(phases); }
public override void SpecialParse(FightData fightData, AgentData agentData, List <CombatItem> combatData) { Boss boss = Targets.Find(x => x.ID == TriggerID); foreach (CombatItem c in combatData) { // redirect all attacks to the main golem if (c.DstAgent == 0 && c.DstInstid == 0 && c.IsStateChange == ParseEnum.StateChange.Normal && c.IFF == ParseEnum.IFF.Foe && c.IsActivation == ParseEnum.Activation.None) { c.DstAgent = boss.Agent; c.DstInstid = boss.InstID; } } }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { // generic method for fractals long start = 0; long end = 0; long fightDuration = log.FightData.FightDuration; List <PhaseData> phases = GetInitialPhase(log); Target mainTarget = Targets.Find(x => x.ID == TriggerID); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } List <CombatItem> invulsTarget = GetFilteredList(log, 762, mainTarget); for (int i = 0; i < invulsTarget.Count; i++) { CombatItem c = invulsTarget[i]; if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { end = log.FightData.ToFightSpace(c.Time); phases.Add(new PhaseData(start, end)); if (i == invulsTarget.Count - 1) { mainTarget.AddCustomCastLog(new CastLog(end, -5, (int)(fightDuration - end), ParseEnum.Activation.None, (int)(fightDuration - end), ParseEnum.Activation.None), log); } } else { start = log.FightData.ToFightSpace(c.Time); mainTarget.AddCustomCastLog(new CastLog(end, -5, (int)(start - end), ParseEnum.Activation.None, (int)(start - end), ParseEnum.Activation.None), log); } } if (fightDuration - start > 5000 && start >= phases.Last().End) { phases.Add(new PhaseData(start, fightDuration)); } phases.RemoveAll(x => x.GetDuration() < 1000); for (int i = 1; i < phases.Count; i++) { phases[i].Name = "Phase " + i; phases[i].Targets.Add(mainTarget); } return(phases); }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); NPC eye1 = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.EyeOfFate); NPC eye2 = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.EyeOfJudgement); if (eye2 == null || eye1 == null) { throw new InvalidOperationException("Eyes not found"); } phases[0].Targets.Add(eye2); phases[0].Targets.Add(eye1); return(phases); }
public override void ComputeMobCombatReplayActors(Mob mob, ParsedLog log, CombatReplay replay) { int start = (int)replay.TimeOffsets.start; int end = (int)replay.TimeOffsets.end; switch (mob.ID) { case (ushort)EntropicDistortion: //sapping surge, red tether List <AbstractBuffEvent> sappingSurge = GetFilteredList(log.CombatData, 56118, mob, true); int surgeStart = 0; AbstractMasterActor source = null; foreach (AbstractBuffEvent c in sappingSurge) { if (c is BuffApplyEvent) { Target qadim = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.PeerlessQadim); surgeStart = (int)c.Time; source = (AbstractMasterActor)log.PlayerList.FirstOrDefault(x => x.AgentItem == c.By) ?? qadim; } else { int surgeEnd = (int)c.Time; if (source != null) { replay.Actors.Add(new LineActor(0, (surgeStart, surgeEnd), "rgba(255, 0, 0, 0.3)", new AgentConnector(mob), new AgentConnector(source))); } } } break; case (ushort)BigKillerTornado: replay.Actors.Add(new CircleActor(true, 0, 450, (start, end), "rgba(255, 150, 0, 0.4)", new AgentConnector(mob))); break; case (ushort)Pylon1: break; case (ushort)Pylon2: break; case (ushort)EnergyOrb: break; default: throw new InvalidOperationException("Unknown ID in ComputeAdditionalData"); } }
public override int IsCM(CombatData combatData, AgentData agentData, FightData fightData) { NPC target = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Deimos); if (target == null) { throw new InvalidOperationException("Deimos not found"); } int res = (target.GetHealth(combatData) > 40e6) ? 1 : 0; if (_specialSplit > 0) { target.SetManualHealth(res > 0 ? 42804900 : 37388210); } return(res); }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { long fightDuration = log.FightData.FightDuration; List <PhaseData> phases = GetInitialPhase(log); Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Dhuum); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } // Sometimes the preevent is not in the evtc List <CastLog> castLogs = mainTarget.GetCastLogs(log, 0, log.FightData.FightEnd); List <CastLog> dhuumCast = mainTarget.GetCastLogs(log, 0, 20000); string[] namesDh; if (dhuumCast.Count > 0) { namesDh = new[] { "Main Fight", "Ritual" }; ComputeFightPhases(mainTarget, phases, log, castLogs, fightDuration, 0); } else { CombatItem invulDhuum = log.GetBoonData(762).FirstOrDefault(x => x.IsBuffRemove != ParseEnum.BuffRemove.None && x.SrcInstid == mainTarget.InstID && x.Time > 115000 + log.FightData.FightStart); if (invulDhuum != null) { long end = log.FightData.ToFightSpace(invulDhuum.Time); phases.Add(new PhaseData(0, end)); ComputeFightPhases(mainTarget, phases, log, castLogs, fightDuration, end + 1); } else { phases.Add(new PhaseData(0, fightDuration)); } namesDh = new[] { "Roleplay", "Main Fight", "Ritual" }; } for (int i = 1; i < phases.Count; i++) { phases[i].Name = namesDh[i - 1]; phases[i].Targets.Add(mainTarget); } return(phases); }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Sabir); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } List <AbstractCastEvent> cls = mainTarget.GetCastLogs(log, 0, log.FightData.FightDuration); List <AbstractCastEvent> wallopingWinds = cls.Where(x => x.SkillId == 56094).ToList(); long start = 0, end = 0; for (int i = 0; i < wallopingWinds.Count; i++) { AbstractCastEvent wW = wallopingWinds[i]; end = wW.Time; PhaseData phase = new PhaseData(start, end) { Name = "Phase " + (i + 1) }; phase.Targets.Add(mainTarget); phases.Add(phase); AbstractCastEvent nextAttack = cls.FirstOrDefault(x => x.Time >= end + wW.ActualDuration && (x.SkillId == 56620 || x.SkillId == 56629 || x.SkillId == 56307)); if (nextAttack == null) { break; } start = nextAttack.Time; if (i == wallopingWinds.Count - 1) { phase = new PhaseData(start, log.FightData.FightDuration) { Name = "Phase " + (i + 2) }; phase.Targets.Add(mainTarget); phases.Add(phase); } } return(phases); }
public override List <AbstractBuffEvent> SpecialBuffEventProcess(Dictionary <AgentItem, List <AbstractBuffEvent> > buffsByDst, Dictionary <long, List <AbstractBuffEvent> > buffsById, long offset, SkillData skillData) { Target mainTarget = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Xera); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } List <AbstractBuffEvent> res = new List <AbstractBuffEvent>(); if (_specialSplitLogTime != 0) { res.Add(new BuffRemoveAllEvent(mainTarget.AgentItem, mainTarget.AgentItem, _specialSplitLogTime - offset, int.MaxValue, skillData.Get(762), 1, int.MaxValue)); res.Add(new BuffRemoveManualEvent(mainTarget.AgentItem, mainTarget.AgentItem, _specialSplitLogTime - offset, int.MaxValue, skillData.Get(762))); } return(res); }
public override void SpecialParse(FightData fightData, AgentData agentData, List <CombatItem> combatData) { Boss boss = Targets.Find(x => x.ID == (ushort)ParseEnum.BossIDS.Deimos); if (boss == null) { throw new InvalidOperationException("Main target of the fight not found"); } CombatItem enterCombat = combatData.FirstOrDefault(x => x.SrcInstid == boss.InstID && x.IsStateChange == ParseEnum.StateChange.EnterCombat); if (enterCombat != null) { fightData.FightStart = enterCombat.Time; } List <AgentItem> deimosGadgets = agentData.GetAgentByType(AgentItem.AgentType.Gadget).Where(x => x.Name.Contains("Deimos")).OrderBy(x => x.LastAware).ToList(); if (deimosGadgets.Count > 0) { long firstAware = deimosGadgets.Max(x => x.FirstAware); HashSet <ulong> deimos2Agents = new HashSet <ulong>(deimosGadgets.Select(x => x.Agent)); CombatItem targetable = combatData.LastOrDefault(x => x.IsStateChange == ParseEnum.StateChange.Targetable && x.Time > combatData.First().Time&& x.DstAgent > 0); if (targetable != null) { firstAware = targetable.Time; } long oldAware = boss.LastAware; fightData.PhaseData.Add(firstAware >= oldAware ? firstAware : oldAware); boss.AgentItem.LastAware = deimosGadgets.Max(x => x.LastAware); foreach (CombatItem c in combatData) { if (c.Time > oldAware) { if (deimos2Agents.Contains(c.SrcAgent)) { c.SrcInstid = boss.InstID; c.SrcAgent = boss.Agent; } if (deimos2Agents.Contains(c.DstAgent)) { c.DstInstid = boss.InstID; c.DstAgent = boss.Agent; } } } } }
public override void SpecialParse(FightData fightData, AgentData agentData, List <CombatItem> combatData) { // Find target Target target = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Ensolyss); if (target == null) { throw new InvalidOperationException("Main target of the fight not found"); } // enter combat CombatItem invulLost = combatData.FirstOrDefault(x => x.DstInstid == target.InstID && x.IsStateChange == ParseEnum.StateChange.Normal && x.IsBuffRemove != ParseEnum.BuffRemove.None && x.SkillID == 762); if (invulLost != null && invulLost.Time - fightData.FightStart < 5000) { fightData.FightStart = invulLost.Time; } }
public override void CheckSuccess(CombatData combatData, AgentData agentData, FightData fightData, HashSet <AgentItem> playerAgents) { base.CheckSuccess(combatData, agentData, fightData, playerAgents); if (!fightData.Success) { NPC mainTarget = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.SoullessHorror); if (mainTarget == null) { throw new InvalidOperationException("Soulless Horror not found"); } AbstractBuffEvent buffOnDeath = combatData.GetBuffData(895).Where(x => x.To == mainTarget.AgentItem && x is BuffApplyEvent).LastOrDefault(); if (buffOnDeath != null) { fightData.SetSuccess(true, buffOnDeath.Time); } } }
public override List <AbstractBuffEvent> SpecialBuffEventProcess(Dictionary <AgentItem, List <AbstractBuffEvent> > buffsByDst, Dictionary <long, List <AbstractBuffEvent> > buffsById, SkillData skillData) { NPC mainTarget = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Xera); if (mainTarget == null) { throw new InvalidOperationException("Error Encountered: Xera not found"); } var res = new List <AbstractBuffEvent>(); if (_specialSplit != 0) { res.Add(new BuffRemoveAllEvent(mainTarget.AgentItem, mainTarget.AgentItem, _specialSplit, int.MaxValue, skillData.Get(762), 1, int.MaxValue)); res.Add(new BuffRemoveManualEvent(mainTarget.AgentItem, mainTarget.AgentItem, _specialSplit, int.MaxValue, skillData.Get(762))); } return(res); }
public override void EIEvtcParse(FightData fightData, AgentData agentData, List <CombatItem> combatData, List <Player> playerList) { ComputeFightTargets(agentData, combatData); // Find target NPC target = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Deimos); if (target == null) { throw new InvalidOperationException("Deimos not found"); } // Remove deimos despawn events as they are useless and mess with combat replay combatData.RemoveAll(x => x.IsStateChange == ParseEnum.StateChange.Despawn && x.SrcAgent == target.Agent); // invul correction CombatItem invulApp = combatData.FirstOrDefault(x => x.DstAgent == target.Agent && x.IsBuff != 0 && x.BuffDmg == 0 && x.Value > 0 && x.SkillID == 762 && x.IsStateChange == ParseEnum.StateChange.None); if (invulApp != null) { invulApp.OverrideValue((int)(target.LastAware - invulApp.Time)); } // Deimos gadgets CombatItem targetable = combatData.LastOrDefault(x => x.IsStateChange == ParseEnum.StateChange.Targetable && x.DstAgent > 0); var gadgetAgents = new HashSet <ulong>(); long firstAware = AttackTargetSpecialParse(targetable, agentData, combatData, gadgetAgents); // legacy method if (firstAware == 0) { CombatItem armDeimosDamageEvent = combatData.FirstOrDefault(x => x.Time >= target.LastAware && (x.SkillID == 37980 || x.SkillID == 37982 || x.SkillID == 38046) && x.SrcAgent != 0 && x.SrcInstid != 0); if (armDeimosDamageEvent != null) { var deimosGadgets = agentData.GetAgentByType(AgentItem.AgentType.Gadget).Where(x => x.Name.Contains("Deimos") && x.LastAware > armDeimosDamageEvent.Time).ToList(); if (deimosGadgets.Count > 0) { firstAware = deimosGadgets.Max(x => x.FirstAware); gadgetAgents = new HashSet <ulong>(deimosGadgets.Select(x => x.Agent)); } } } if (gadgetAgents.Count > 0) { _specialSplit = (firstAware >= target.LastAware ? firstAware : target.LastAware); MergeWithGadgets(target.AgentItem, gadgetAgents, agentData, combatData); } target.AgentItem.OverrideAwareTimes(target.FirstAware, fightData.FightEnd); target.OverrideName("Deimos"); }
private void HPCheck(CombatData combatData, FightData fightData) { NPC eye1 = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.EyeOfFate); NPC eye2 = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.EyeOfJudgement); if (eye2 == null || eye1 == null) { throw new InvalidOperationException("Eyes not found"); } List <HealthUpdateEvent> eye1HPs = combatData.GetHealthUpdateEvents(eye1.AgentItem); List <HealthUpdateEvent> eye2HPs = combatData.GetHealthUpdateEvents(eye2.AgentItem); if (eye1HPs.Count == 0 || eye2HPs.Count == 0) { return; } double lastEye1Hp = eye1HPs.LastOrDefault().HPPercent; double lastEye2Hp = eye2HPs.LastOrDefault().HPPercent; double margin1 = Math.Min(0.80, lastEye1Hp); double margin2 = Math.Min(0.80, lastEye2Hp); if (lastEye1Hp <= margin1 && lastEye2Hp <= margin2) { int lastIEye1; for (lastIEye1 = eye1HPs.Count - 1; lastIEye1 >= 0; lastIEye1--) { if (eye1HPs[lastIEye1].HPPercent > margin1) { lastIEye1++; break; } } int lastIEye2; for (lastIEye2 = eye2HPs.Count - 1; lastIEye2 >= 0; lastIEye2--) { if (eye2HPs[lastIEye2].HPPercent > margin2) { lastIEye2++; break; } } fightData.SetSuccess(true, Math.Max(eye1HPs[lastIEye1].Time, eye2HPs[lastIEye2].Time)); } }
public override void ComputeAdditionalTrashMobData(Mob mob, ParsedLog log) { Target desmina = Targets.Find(x => x.ID == (ushort)ParseEnum.TargetIDS.Desmina); if (desmina == null) { throw new InvalidOperationException("Main target of the fight not found"); } CombatReplay replay = mob.CombatReplay; int start = (int)replay.TimeOffsets.start; int end = (int)replay.TimeOffsets.end; switch (mob.ID) { case (ushort)HollowedBomber: List <CastLog> bomberman = mob.GetCastLogs(log, 0, log.FightData.FightDuration).Where(x => x.SkillId == 48272).ToList(); foreach (CastLog bomb in bomberman) { int startCast = (int)bomb.Time; int endCast = startCast + bomb.ActualDuration; int expectedEnd = Math.Max(startCast + bomb.ExpectedDuration, endCast); replay.Actors.Add(new CircleActor(true, 0, 480, (startCast, endCast), "rgba(180,250,0,0.3)", new AgentConnector(mob))); replay.Actors.Add(new CircleActor(true, expectedEnd, 480, (startCast, endCast), "rgba(180,250,0,0.3)", new AgentConnector(mob))); } break; case (ushort)RiverOfSouls: if (replay.Rotations.Count > 0) { replay.Actors.Add(new FacingRectangleActor((start, end), new AgentConnector(mob), replay.PolledRotations, 160, 390, "rgba(255,100,0,0.5)")); } break; case (ushort)Enervator: // TODO Line actor between desmina and enervator. Missing skillID case (ushort)SpiritHorde1: case (ushort)SpiritHorde2: case (ushort)SpiritHorde3: break; default: throw new InvalidOperationException("Unknown ID in ComputeAdditionalData"); } }
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); }
internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); NPC mainTarget = Targets.Find(x => x.ID == (int)ArcDPSEnums.TargetID.MursaatOverseer); if (mainTarget == null) { throw new InvalidOperationException("Mursaat Overseer not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } phases.AddRange(GetPhasesByHealthPercent(log, mainTarget, new List <double> { 75, 50, 25, 0 })); return(phases); }
internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); NPC varinia = Targets.Find(x => x.ID == (int)ArcDPSEnums.TargetID.VariniaStormsounder); if (varinia == null) { throw new InvalidOperationException("Varinia Stormsounder not found"); } phases[0].Targets.Add(varinia); // // TODO - add phases if applicable // for (int i = 1; i < phases.Count; i++) { phases[i].Targets.Add(varinia); } return(phases); }
public override void ComputeNPCCombatReplayActors(NPC target, ParsedLog log, CombatReplay replay) { NPC desmina = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Desmina); if (desmina == null) { throw new InvalidOperationException("Error Encountered: Desmina not found"); } int start = (int)replay.TimeOffsets.start; int end = (int)replay.TimeOffsets.end; switch (target.ID) { case (int)HollowedBomber: var bomberman = target.GetCastLogs(log, 0, log.FightData.FightEnd).Where(x => x.SkillId == 48272).ToList(); foreach (AbstractCastEvent bomb in bomberman) { int startCast = (int)bomb.Time; int endCast = startCast + bomb.ActualDuration; int expectedEnd = Math.Max(startCast + bomb.ExpectedDuration, endCast); replay.Decorations.Add(new CircleDecoration(true, 0, 480, (startCast, endCast), "rgba(180,250,0,0.3)", new AgentConnector(target))); replay.Decorations.Add(new CircleDecoration(true, expectedEnd, 480, (startCast, endCast), "rgba(180,250,0,0.3)", new AgentConnector(target))); } break; case (int)RiverOfSouls: if (replay.Rotations.Count > 0) { replay.Decorations.Add(new FacingRectangleDecoration((start, end), new AgentConnector(target), replay.PolledRotations, 160, 390, "rgba(255,100,0,0.5)")); } break; case (int)Enervator: // TODO Line actor between desmina and enervator. Missing skillID case (int)SpiritHorde1: case (int)SpiritHorde2: case (int)SpiritHorde3: break; default: break; } }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); NPC mainTarget = Targets.Find(x => x.ID == GenericTriggerID); if (mainTarget == null) { throw new InvalidOperationException("Golem not found"); } phases[0].Name = "Final Number"; phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } List <HealthUpdateEvent> hpUpdates = log.CombatData.GetHealthUpdateEvents(mainTarget.AgentItem); if (hpUpdates.Count > 0) { long fightDuration = log.FightData.FightEnd; var thresholds = new List <double> { 80, 60, 40, 20, 0 }; var numberNames = new string[] { "First Number", "Second Number", "Third Number", "Fourth Number" }; // Fifth number would the equivalent of full fight phase for (int j = 0; j < thresholds.Count - 1; j++) { HealthUpdateEvent hpUpdate = hpUpdates.FirstOrDefault(x => x.HPPercent <= thresholds[j]); if (hpUpdate != null) { var phase = new PhaseData(0, hpUpdate.Time, numberNames[j]) { CanBeSubPhase = false }; phase.Targets.Add(mainTarget); phases.Add(phase); } } phases.AddRange(GetPhasesByHealthPercent(log, mainTarget, thresholds)); } return(phases); }
public override void SetSuccess(ParsedEvtcContainer evtcContainer) { Target mainTarget = Targets.Find(x => x.ID == TriggerID); if (mainTarget == null) { throw new InvalidOperationException("Main target of the fight not found"); } CombatItem lastDamageTaken = evtcContainer.CombatData.GetDamageTakenData(mainTarget.InstID, mainTarget.FirstAware, mainTarget.LastAware).LastOrDefault(x => x.Value > 0 || x.BuffDmg > 0); if (lastDamageTaken != null) { evtcContainer.FightData.FightEnd = lastDamageTaken.Time; } if (mainTarget.HealthOverTime.Count > 0) { evtcContainer.FightData.Success = mainTarget.HealthOverTime.Last().hp < 200; } }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); NPC mainTarget = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.ValeGuardian); if (mainTarget == null) { throw new InvalidOperationException("Error Encountered: Vale Guardian not found"); } phases[0].Targets.Add(mainTarget); if (!requirePhases) { return(phases); } // Invul check phases.AddRange(GetPhasesByInvul(log, 757, mainTarget, true, true)); string[] namesVG = new[] { "Phase 1", "Split 1", "Phase 2", "Split 2", "Phase 3" }; for (int i = 1; i < phases.Count; i++) { PhaseData phase = phases[i]; phase.Name = namesVG[i - 1]; if (i == 2 || i == 4) { var ids = new List <int> { (int)BlueGuardian, (int)GreenGuardian, (int)RedGuardian }; AddTargetsToPhase(phase, ids, log); foreach (NPC t in phase.Targets) { t.OverrideName(t.Character + " " + Math.Log(i, 2)); } } else { phase.Targets.Add(mainTarget); } } return(phases); }