/// <summary> /// Override times in a manner that the phase englobes the targets present in the phase (if possible) /// </summary> /// <param name="log"></param> internal void OverrideTimes(ParsedEvtcLog log) { if (Targets.Count > 0) { long end = long.MinValue; long start = long.MaxValue; foreach (AbstractSingleActor target in Targets) { long startTime = target.FirstAware; SpawnEvent spawned = log.CombatData.GetSpawnEvents(target.AgentItem).FirstOrDefault(); if (spawned != null) { startTime = spawned.Time; } EnterCombatEvent enterCombat = log.CombatData.GetEnterCombatEvents(target.AgentItem).FirstOrDefault(); if (enterCombat != null) { startTime = enterCombat.Time; } long deadTime = target.LastAware; DeadEvent died = log.CombatData.GetDeadEvents(target.AgentItem).FirstOrDefault(); if (died != null) { deadTime = died.Time; } start = Math.Min(start, startTime); end = Math.Max(end, deadTime); } Start = Math.Max(Math.Max(Start, start), 0); End = Math.Min(Math.Min(End, end), log.FightData.FightEnd); } DurationInM = (End - Start) / 60000; DurationInMS = (End - Start); DurationInS = (End - Start) / 1000; }
public override List <PhaseData> GetPhases(ParsedLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); NPC voice = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.ClawOfTheFallen); NPC claw = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.VoiceOfTheFallen); if (voice == null || claw == null) { throw new InvalidOperationException("Error Encountered: Claw or Voice not found"); } phases[0].Targets.Add(voice); phases[0].Targets.Add(claw); var fightEnd = log.FightData.FightEnd; if (!requirePhases) { return(phases); } // List <PhaseData> unmergedPhases = GetPhasesByInvul(log, 762, claw, false, true); for (int i = 0; i < unmergedPhases.Count; i++) { unmergedPhases[i].Name = "Phase " + (i + 1); unmergedPhases[i].Targets.Add(claw); unmergedPhases[i].Targets.Add(voice); } phases.AddRange(unmergedPhases); // int voiceAndClawCount = 0; var offset = 1; foreach (NPC voiceAndClaw in Targets.Where(x => x.ID == (int)ParseEnum.TargetIDS.VoiceAndClaw)) { EnterCombatEvent enterCombat = log.CombatData.GetEnterCombatEvents(voiceAndClaw.AgentItem).FirstOrDefault(); PhaseData nextUnmergedPhase = unmergedPhases.Count > offset + 1 ? unmergedPhases[offset] : null; if (enterCombat != null) { var phase = new PhaseData(enterCombat.Time, nextUnmergedPhase != null ? nextUnmergedPhase.Start : Math.Min(fightEnd, voiceAndClaw.LastAware), "Voice and Claw " + ++voiceAndClawCount); phase.Targets.Add(voiceAndClaw); phases.Add(phase); offset++; } } // AbstractBuffEvent enrage = log.CombatData.GetBuffData(58619).FirstOrDefault(x => x is BuffApplyEvent); if (enrage != null) { var phase = new PhaseData(enrage.Time, log.FightData.FightEnd, "Enrage"); phase.Targets.Add(claw.AgentItem == enrage.To ? claw : voice); phases.Add(phase); } phases.Sort((x, y) => x.Start.CompareTo(y.Start)); return(phases); }
internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); NPC voice = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.ClawOfTheFallen); NPC claw = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.VoiceOfTheFallen); if (voice == null || claw == null) { throw new MissingKeyActorsException("Claw or Voice not found"); } phases[0].AddTarget(voice); phases[0].AddTarget(claw); long fightEnd = log.FightData.FightEnd; if (!requirePhases) { return(phases); } // List <PhaseData> unmergedPhases = GetPhasesByInvul(log, 762, claw, false, true); for (int i = 0; i < unmergedPhases.Count; i++) { unmergedPhases[i].Name = "Phase " + (i + 1); unmergedPhases[i].AddTarget(claw); unmergedPhases[i].AddTarget(voice); } phases.AddRange(unmergedPhases); // int voiceAndClawCount = 0; int offset = 1; foreach (NPC voiceAndClaw in Targets.Where(x => x.ID == (int)ArcDPSEnums.TargetID.VoiceAndClaw)) { EnterCombatEvent enterCombat = log.CombatData.GetEnterCombatEvents(voiceAndClaw.AgentItem).FirstOrDefault(); PhaseData nextUnmergedPhase = unmergedPhases.Count > offset + 1 ? unmergedPhases[offset] : null; if (enterCombat != null) { var phase = new PhaseData(enterCombat.Time, nextUnmergedPhase != null ? nextUnmergedPhase.Start : Math.Min(fightEnd, voiceAndClaw.LastAware), "Voice and Claw " + ++voiceAndClawCount); phase.AddTarget(voiceAndClaw); phases.Add(phase); offset++; } } // AbstractBuffEvent enrage = log.CombatData.GetBuffData(58619).FirstOrDefault(x => x is BuffApplyEvent); if (enrage != null) { var phase = new PhaseData(enrage.Time, log.FightData.FightEnd, "Enrage"); phase.AddTarget(claw.AgentItem == enrage.To ? claw : voice); phases.Add(phase); } return(phases); }
protected static void SetSuccessByCombatExit(List <NPC> targets, CombatData combatData, FightData fightData, HashSet <AgentItem> playerAgents) { if (targets.Count == 0) { return; } var playerExits = new List <ExitCombatEvent>(); var targetExits = new List <ExitCombatEvent>(); var lastTargetDamages = new List <AbstractDamageEvent>(); foreach (AgentItem a in playerAgents) { playerExits.AddRange(combatData.GetExitCombatEvents(a)); } foreach (NPC t in targets) { EnterCombatEvent enterCombat = combatData.GetEnterCombatEvents(t.AgentItem).LastOrDefault(); if (enterCombat != null) { targetExits.AddRange(combatData.GetExitCombatEvents(t.AgentItem).Where(x => x.Time > enterCombat.Time)); } else { targetExits.AddRange(combatData.GetExitCombatEvents(t.AgentItem)); } AbstractDamageEvent lastDamage = combatData.GetDamageTakenData(t.AgentItem).LastOrDefault(x => (x.Damage > 0) && playerAgents.Contains(x.From.GetFinalMaster())); if (lastDamage != null) { lastTargetDamages.Add(lastDamage); } } ExitCombatEvent lastPlayerExit = playerExits.Count > 0 ? playerExits.MaxBy(x => x.Time) : null; ExitCombatEvent lastTargetExit = targetExits.Count > 0 ? targetExits.MaxBy(x => x.Time) : null; AbstractDamageEvent lastDamageTaken = lastTargetDamages.Count > 0 ? lastTargetDamages.MaxBy(x => x.Time) : null; if (lastTargetExit != null && lastDamageTaken != null) { if (lastPlayerExit != null) { fightData.SetSuccess(lastPlayerExit.Time > lastTargetExit.Time + 1000, lastDamageTaken.Time); } else if (fightData.FightEnd > targets.Max(x => x.LastAware) + 2000) { fightData.SetSuccess(true, lastDamageTaken.Time); } } }
protected static void SetSuccessByCombatExit(List <AbstractSingleActor> targets, CombatData combatData, FightData fightData, IReadOnlyCollection <AgentItem> playerAgents) { if (targets.Count == 0) { return; } var targetExits = new List <ExitCombatEvent>(); var lastTargetDamages = new List <AbstractHealthDamageEvent>(); foreach (AbstractSingleActor t in targets) { EnterCombatEvent enterCombat = combatData.GetEnterCombatEvents(t.AgentItem).LastOrDefault(); ExitCombatEvent exitCombat; if (enterCombat != null) { exitCombat = combatData.GetExitCombatEvents(t.AgentItem).Where(x => x.Time > enterCombat.Time).LastOrDefault(); } else { exitCombat = combatData.GetExitCombatEvents(t.AgentItem).LastOrDefault(); } AbstractHealthDamageEvent lastDamage = combatData.GetDamageTakenData(t.AgentItem).LastOrDefault(x => (x.HealthDamage > 0) && playerAgents.Contains(x.From.GetFinalMaster())); if (exitCombat == null || lastDamage == null || combatData.GetAnimatedCastData(t.AgentItem).Any(x => x.Time > exitCombat.Time + ParserHelper.ServerDelayConstant) || combatData.GetDamageData(t.AgentItem).Any(x => x.Time > exitCombat.Time + ParserHelper.ServerDelayConstant && playerAgents.Contains(x.To))) { return; } targetExits.Add(exitCombat); lastTargetDamages.Add(lastDamage); } ExitCombatEvent lastTargetExit = targetExits.Count > 0 ? targetExits.MaxBy(x => x.Time) : null; AbstractHealthDamageEvent lastDamageTaken = lastTargetDamages.Count > 0 ? lastTargetDamages.MaxBy(x => x.Time) : null; // Make sure the last damage has been done before last combat exit if (lastTargetExit != null && lastDamageTaken != null && lastTargetExit.Time + 150 >= lastDamageTaken.Time) { if (!AtLeastOnePlayerAlive(combatData, fightData, lastTargetExit.Time, playerAgents)) { return; } fightData.SetSuccess(true, lastDamageTaken.Time); } }
public static void SetPhasePerTarget(NPC target, List <PhaseData> phases, ParsedLog log) { long fightDuration = log.FightData.FightEnd; EnterCombatEvent phaseStart = log.CombatData.GetEnterCombatEvents(target.AgentItem).LastOrDefault(); if (phaseStart != null) { long start = phaseStart.Time; DeadEvent phaseEnd = log.CombatData.GetDeadEvents(target.AgentItem).LastOrDefault(); long end = fightDuration; if (phaseEnd != null) { end = phaseEnd.Time; } var phase = new PhaseData(start, Math.Min(end, log.FightData.FightEnd)); phase.Targets.Add(target); phases.Add(phase); } }
protected static void SetSuccessByCombatExit(List <NPC> targets, CombatData combatData, FightData fightData, HashSet <AgentItem> playerAgents) { if (targets.Count == 0) { return; } var targetExits = new List <ExitCombatEvent>(); var lastTargetDamages = new List <AbstractHealthDamageEvent>(); foreach (NPC t in targets) { EnterCombatEvent enterCombat = combatData.GetEnterCombatEvents(t.AgentItem).LastOrDefault(); if (enterCombat != null) { targetExits.AddRange(combatData.GetExitCombatEvents(t.AgentItem).Where(x => x.Time > enterCombat.Time)); } else { targetExits.AddRange(combatData.GetExitCombatEvents(t.AgentItem)); } AbstractHealthDamageEvent lastDamage = combatData.GetDamageTakenData(t.AgentItem).LastOrDefault(x => (x.HealthDamage > 0) && playerAgents.Contains(x.From.GetFinalMaster())); if (lastDamage != null) { lastTargetDamages.Add(lastDamage); } } ExitCombatEvent lastTargetExit = targetExits.Count > 0 ? targetExits.MaxBy(x => x.Time) : null; AbstractHealthDamageEvent lastDamageTaken = lastTargetDamages.Count > 0 ? lastTargetDamages.MaxBy(x => x.Time) : null; // Make sure the last damage has been done before last combat exit if (lastTargetExit != null && lastDamageTaken != null && lastTargetExit.Time + 100 >= lastDamageTaken.Time) { if (!AtLeastOnePlayerAlive(combatData, fightData, lastTargetExit.Time, playerAgents)) { return; } fightData.SetSuccess(true, lastDamageTaken.Time); } }
private static void AddSplitPhase(List <PhaseData> phases, IReadOnlyList <AbstractSingleActor> targets, AbstractSingleActor ministerLi, ParsedEvtcLog log, int phaseID) { if (targets.All(x => x != null)) { EnterCombatEvent cbtEnter = null; foreach (NPC target in targets) { cbtEnter = log.CombatData.GetEnterCombatEvents(target.AgentItem).LastOrDefault(); if (cbtEnter != null) { break; } } if (cbtEnter != null) { AbstractBuffEvent nextPhaseStartEvt = log.CombatData.GetBuffData(ministerLi.AgentItem).FirstOrDefault(x => x is BuffRemoveAllEvent && x.BuffID == 762 && x.Time > cbtEnter.Time); long phaseEnd = nextPhaseStartEvt != null ? nextPhaseStartEvt.Time : log.FightData.FightEnd; var addPhase = new PhaseData(cbtEnter.Time, phaseEnd, "Split Phase " + phaseID); addPhase.AddTargets(targets); phases.Add(addPhase); } } }
public static void SetPhasePerTarget(NPC target, List <PhaseData> phases, ParsedEvtcLog log) { long fightDuration = log.FightData.FightEnd; EnterCombatEvent phaseStart = log.CombatData.GetEnterCombatEvents(target.AgentItem).LastOrDefault(); if (phaseStart != null) { long start = phaseStart.Time; DeadEvent phaseEnd = log.CombatData.GetDeadEvents(target.AgentItem).LastOrDefault(); long end = fightDuration; if (phaseEnd != null) { end = phaseEnd.Time; } var phase = new PhaseData(start, Math.Min(end, log.FightData.FightEnd)); phase.Targets.Add(target); switch (target.ID) { case (int)ArcDPSEnums.TargetID.Narella: phase.Name = "Narella"; break; case (int)ArcDPSEnums.TargetID.Berg: phase.Name = "Berg"; break; case (int)ArcDPSEnums.TargetID.Zane: phase.Name = "Zane"; break; default: throw new InvalidOperationException("Unknown target in Bandit Trio"); } phases.Add(phase); } }
internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); AbstractSingleActor fraenir = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.FraenirOfJormag); if (fraenir == null) { throw new MissingKeyActorsException("Fraenir of Jormag not found"); } phases[0].AddTarget(fraenir); AbstractSingleActor icebrood = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.IcebroodConstructFraenir); if (icebrood != null) { phases[0].AddTarget(icebrood); } if (!requirePhases) { return(phases); } AbstractBuffEvent invulApplyFraenir = log.CombatData.GetBuffData(762).Where(x => x.To == fraenir.AgentItem && x is BuffApplyEvent).FirstOrDefault(); if (invulApplyFraenir != null) { // split happened phases.Add(new PhaseData(0, invulApplyFraenir.Time, "Fraenir 1")); if (icebrood != null) { // icebrood enters combat EnterCombatEvent enterCombatIce = log.CombatData.GetEnterCombatEvents(icebrood.AgentItem).LastOrDefault(); if (enterCombatIce != null) { // icebrood phasing AbstractBuffEvent invulApplyIce = log.CombatData.GetBuffData(757).Where(x => x.To == icebrood.AgentItem && x is BuffApplyEvent).FirstOrDefault(); AbstractBuffEvent invulRemoveIce = log.CombatData.GetBuffData(757).Where(x => x.To == icebrood.AgentItem && x is BuffRemoveAllEvent).FirstOrDefault(); long icebroodStart = enterCombatIce.Time; long icebroodEnd = log.FightData.FightEnd; if (invulApplyIce != null && invulRemoveIce != null) { long icebrood2Start = invulRemoveIce.Time; phases.Add(new PhaseData(icebroodStart + 1, invulApplyIce.Time, "Icebrood 1")); AbstractBuffEvent invulRemoveFraenir = log.CombatData.GetBuffData(762).Where(x => x.To == fraenir.AgentItem && x is BuffRemoveAllEvent).FirstOrDefault(); if (invulRemoveFraenir != null) { // fraenir came back DeadEvent deadIce = log.CombatData.GetDeadEvents(icebrood.AgentItem).LastOrDefault(); if (deadIce != null) { icebroodEnd = deadIce.Time; } else { icebroodEnd = invulRemoveFraenir.Time - 1; } phases.Add(new PhaseData(invulRemoveFraenir.Time, log.FightData.FightEnd, "Fraenir 2")); } phases.Add(new PhaseData(icebrood2Start, icebroodEnd, "Icebrood 2")); } phases.Add(new PhaseData(icebroodStart, icebroodEnd, "Icebrood")); } } } phases.Sort((x, y) => x.Start.CompareTo(y.Start)); for (int i = 1; i < phases.Count; i++) { PhaseData phase = phases[i]; if (i == 1 || i == 5) { phase.AddTarget(fraenir); } else { phase.AddTarget(icebrood); } } return(phases); }
internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); AbstractSingleActor voice = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.ClawOfTheFallen); AbstractSingleActor claw = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.VoiceOfTheFallen); if (voice == null || claw == null) { throw new MissingKeyActorsException("Claw or Voice not found"); } phases[0].AddTarget(voice); phases[0].AddTarget(claw); long fightEnd = log.FightData.FightEnd; if (!requirePhases) { return(phases); } // List <PhaseData> unmergedPhases = GetPhasesByInvul(log, 762, claw, false, true); for (int i = 0; i < unmergedPhases.Count; i++) { unmergedPhases[i].Name = "Phase " + (i + 1); unmergedPhases[i].AddTarget(claw); unmergedPhases[i].AddTarget(voice); } phases.AddRange(unmergedPhases); // int voiceAndClawCount = 0; foreach (AbstractSingleActor voiceAndClaw in Targets.Where(x => x.ID == (int)ArcDPSEnums.TargetID.VoiceAndClaw)) { EnterCombatEvent enterCombat = log.CombatData.GetEnterCombatEvents(voiceAndClaw.AgentItem).FirstOrDefault(); long phaseStart = 0; if (enterCombat != null) { phaseStart = enterCombat.Time; } else { phaseStart = voiceAndClaw.FirstAware; } PhaseData nextUnmergedPhase = unmergedPhases.FirstOrDefault(x => x.Start > phaseStart); long phaseEnd = Math.Min(fightEnd, voiceAndClaw.LastAware); if (nextUnmergedPhase != null) { phaseEnd = nextUnmergedPhase.Start - 1; } var phase = new PhaseData(phaseStart, phaseEnd, "Voice and Claw " + ++voiceAndClawCount); phase.AddTarget(voiceAndClaw); phases.Add(phase); } // var teleports = voice.GetCastEvents(log, 0, log.FightData.FightDuration).Where(x => x.SkillId == 58382).ToList(); long tpCount = 0; long preTPPhaseStart = 0; foreach (AbstractCastEvent teleport in teleports) { long preTPPhaseEnd = Math.Min(teleport.Time, log.FightData.FightDuration); AbstractSingleActor voiceAndClaw = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.VoiceAndClaw && x.FirstAware >= preTPPhaseStart); if (voiceAndClaw != null) { long oldEnd = preTPPhaseEnd; preTPPhaseEnd = Math.Min(preTPPhaseEnd, voiceAndClaw.FirstAware); // To handle position phase after merge phase end if (oldEnd != preTPPhaseEnd) { PhaseData nextUnmergedPhase = unmergedPhases.FirstOrDefault(x => x.Start > voiceAndClaw.LastAware); if (nextUnmergedPhase != null) { long postMergedStart = nextUnmergedPhase.Start + 1; long postMergedEnd = oldEnd; var phase = new PhaseData(postMergedStart, postMergedEnd, "Position " + (++tpCount)); phase.AddTarget(claw); phase.AddTarget(voice); phases.Add(phase); } } } if (preTPPhaseEnd - preTPPhaseStart > 2000) { var phase = new PhaseData(preTPPhaseStart, preTPPhaseEnd, "Position " + (++tpCount)); phase.AddTarget(claw); phase.AddTarget(voice); phases.Add(phase); } preTPPhaseStart = teleport.EndTime; } // AbstractBuffEvent enrage = log.CombatData.GetBuffData(SkillIDs.EnragedVC).FirstOrDefault(x => x is BuffApplyEvent); if (enrage != null) { var phase = new PhaseData(enrage.Time, log.FightData.FightEnd, "Enrage"); phase.AddTarget(claw.AgentItem == enrage.To ? claw : voice); phases.Add(phase); } // Missing final position event { PhaseData nextUnmergedPhase = unmergedPhases.FirstOrDefault(x => x.Start > preTPPhaseStart); long finalStart = preTPPhaseStart; long finalPositionEnd = log.FightData.FightDuration; if (nextUnmergedPhase != null) { finalStart = nextUnmergedPhase.Start + 1; } if (enrage != null) { finalPositionEnd = enrage.Time; } if (finalPositionEnd - finalStart > 2000) { var phase = new PhaseData(finalStart, finalPositionEnd, "Position " + (++tpCount)); phase.AddTarget(claw); phase.AddTarget(voice); phases.Add(phase); } } return(phases); }