protected static List <PhaseData> GetPhasesByHealthPercent(ParsedEvtcLog log, NPC mainTarget, List <double> thresholds) { var phases = new List <PhaseData>(); if (thresholds.Count == 0) { return(phases); } long fightDuration = log.FightData.FightEnd; long start = 0; double offset = 100.0 / thresholds.Count; IReadOnlyList <HealthUpdateEvent> hpUpdates = log.CombatData.GetHealthUpdateEvents(mainTarget.AgentItem); for (int i = 0; i < thresholds.Count; i++) { HealthUpdateEvent evt = hpUpdates.FirstOrDefault(x => x.HPPercent <= thresholds[i]); if (evt == null) { break; } var phase = new PhaseData(start, Math.Min(evt.Time, fightDuration), (offset + thresholds[i]) + "% - " + thresholds[i] + "%"); phase.AddTarget(mainTarget); phases.Add(phase); start = Math.Max(evt.Time, 0); } if (phases.Count > 0 && phases.Count < thresholds.Count) { var lastPhase = new PhaseData(start, fightDuration, (offset + thresholds[phases.Count]) + "% -" + thresholds[phases.Count] + "%"); lastPhase.AddTarget(mainTarget); phases.Add(lastPhase); } return(phases); }
internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); AbstractSingleActor maiTrin = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.MaiTrinStrike); if (maiTrin == null) { throw new MissingKeyActorsException("Mai Trin not found"); } phases[0].AddTarget(maiTrin); AbstractSingleActor echoOfScarlet = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.EchoOfScarletBriar); if (echoOfScarlet != null) { phases[0].AddTarget(echoOfScarlet); } if (!requirePhases) { return(phases); } if (log.CombatData.GetDamageTakenData(maiTrin.AgentItem).Any()) { HealthUpdateEvent lastHPUpdate = log.CombatData.GetHealthUpdateEvents(maiTrin.AgentItem).LastOrDefault(); long maiTrinEnd = lastHPUpdate.Time; long maiTrinStart = 0; BuffRemoveAllEvent buffRemove = log.CombatData.GetBuffData(895).OfType <BuffRemoveAllEvent>().Where(x => x.To == maiTrin.AgentItem).FirstOrDefault(); if (buffRemove != null) { maiTrinStart = buffRemove.Time; } var mainPhase = new PhaseData(0, maiTrinEnd, "Mai Trin"); mainPhase.AddTarget(maiTrin); phases.Add(mainPhase); List <PhaseData> maiPhases = GetPhasesByInvul(log, 38793, maiTrin, false, true, maiTrinStart, maiTrinEnd); for (int i = 0; i < maiPhases.Count; i++) { PhaseData subPhase = maiPhases[i]; subPhase.Name = "Mai Trin Phase " + (i + 1); subPhase.AddTarget(maiTrin); } phases.AddRange(maiPhases); } if (echoOfScarlet != null) { long echoStart = echoOfScarlet.FirstAware + 10000; var phase = new PhaseData(echoStart, log.FightData.FightEnd, "Echo of Scarlet Briar"); phase.AddTarget(echoOfScarlet); phases.Add(phase); List <PhaseData> echoPhases = GetPhasesByInvul(log, 38793, echoOfScarlet, false, true, echoStart, log.FightData.FightEnd); for (int i = 0; i < echoPhases.Count; i++) { PhaseData subPhase = echoPhases[i]; subPhase.Name = "Echo Phase " + (i + 1); subPhase.AddTarget(echoOfScarlet); } phases.AddRange(echoPhases); } return(phases); }
public virtual void Start() { if (healthUpdate == null) { healthUpdate = new HealthUpdateEvent(); } currentHP = maxHP.GetStat(); }
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); }
internal override void ComputeNPCCombatReplayActors(NPC target, ParsedEvtcLog log, CombatReplay replay) { switch (target.ID) { case (int)ArcDPSEnums.TargetID.MaiTrinStrike: HealthUpdateEvent lastHPUpdate = log.CombatData.GetHealthUpdateEvents(target.AgentItem).LastOrDefault(); long maiTrinEnd = lastHPUpdate.Time; replay.Trim(replay.TimeOffsets.start, maiTrinEnd); break; default: break; } }
internal override List <PhaseData> GetPhases(ParsedEvtcLog log, bool requirePhases) { List <PhaseData> phases = GetInitialPhase(log); AbstractSingleActor mainTarget = Targets.FirstOrDefault(x => x.ID == GenericTriggerID); if (mainTarget == null) { throw new MissingKeyActorsException("Golem not found"); } phases[0].Name = "Final Number"; phases[0].AddTarget(mainTarget); if (!requirePhases) { return(phases); } IReadOnlyList <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 }; string[] 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.AddTarget(mainTarget); phases.Add(phase); } } phases.AddRange(GetPhasesByHealthPercent(log, mainTarget, thresholds)); } return(phases); }
internal override void ComputePlayerCombatReplayActors(Player p, ParsedEvtcLog log, CombatReplay replay) { // spirit transform var spiritTransform = log.CombatData.GetBuffData(46950).Where(x => x.To == p.AgentItem && x is BuffApplyEvent).ToList(); NPC mainTarget = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.Dhuum); if (mainTarget == null) { throw new MissingKeyActorsException("Dhuum not found"); } foreach (AbstractBuffEvent c in spiritTransform) { int duration = 15000; HealthUpdateEvent hpUpdate = log.CombatData.GetHealthUpdateEvents(mainTarget.AgentItem).FirstOrDefault(x => x.Time > c.Time); if (hpUpdate != null && hpUpdate.HPPercent < 10.50) { duration = 30000; } AbstractBuffEvent removedBuff = log.CombatData.GetBuffRemoveAllData(48281).FirstOrDefault(x => x.To == p.AgentItem && x.Time > c.Time && x.Time < c.Time + duration); int start = (int)c.Time; int end = start + duration; if (removedBuff != null) { end = (int)removedBuff.Time; } replay.Decorations.Add(new CircleDecoration(true, 0, 100, (start, end), "rgba(0, 50, 200, 0.3)", new AgentConnector(p))); replay.Decorations.Add(new CircleDecoration(true, start + duration, 100, (start, end), "rgba(0, 50, 200, 0.5)", new AgentConnector(p))); } // bomb List <AbstractBuffEvent> bombDhuum = GetFilteredList(log.CombatData, 47646, p, true); int bombDhuumStart = 0; foreach (AbstractBuffEvent c in bombDhuum) { if (c is BuffApplyEvent) { bombDhuumStart = (int)c.Time; } else { int bombDhuumEnd = (int)c.Time; replay.Decorations.Add(new CircleDecoration(true, 0, 100, (bombDhuumStart, bombDhuumEnd), "rgba(80, 180, 0, 0.3)", new AgentConnector(p))); replay.Decorations.Add(new CircleDecoration(true, bombDhuumStart + 13000, 100, (bombDhuumStart, bombDhuumEnd), "rgba(80, 180, 0, 0.5)", new AgentConnector(p))); } } // shackles connection var shackles = GetFilteredList(log.CombatData, 47335, p, true).Concat(GetFilteredList(log.CombatData, 48591, p, true)).ToList(); int shacklesStart = 0; Player shacklesTarget = null; foreach (AbstractBuffEvent c in shackles) { if (c is BuffApplyEvent) { shacklesStart = (int)c.Time; shacklesTarget = log.PlayerList.FirstOrDefault(x => x.AgentItem == c.CreditedBy); } else { int shacklesEnd = (int)c.Time; if (shacklesTarget != null) { replay.Decorations.Add(new LineDecoration(0, (shacklesStart, shacklesEnd), "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 <AbstractBuffEvent> shacklesDmg = GetFilteredList(log.CombatData, 48042, p, true); int shacklesDmgStart = 0; Player shacklesDmgTarget = null; foreach (AbstractBuffEvent c in shacklesDmg) { if (c is BuffApplyEvent) { shacklesDmgStart = (int)c.Time; shacklesDmgTarget = log.PlayerList.FirstOrDefault(x => x.AgentItem == c.CreditedBy); } else { int shacklesDmgEnd = (int)c.Time; if (shacklesDmgTarget != null) { replay.Decorations.Add(new LineDecoration(0, (shacklesDmgStart, shacklesDmgEnd), "rgba(0, 255, 255, 0.5)", new AgentConnector(p), new AgentConnector(shacklesDmgTarget))); } } } }