public override void CheckSuccess(CombatData combatData, AgentData agentData, FightData fightData, HashSet <AgentItem> playerAgents) { base.CheckSuccess(combatData, agentData, fightData, playerAgents); if (!fightData.Success) { NPC desmina = Targets.Find(x => x.ID == (int)ParseEnum.TargetIDS.Desmina); if (desmina == null) { throw new InvalidOperationException("Error Encountered: Desmina not found"); } ExitCombatEvent ooc = combatData.GetExitCombatEvents(desmina.AgentItem).LastOrDefault(); if (ooc != null) { long time = 0; foreach (NPC mob in TrashMobs.Where(x => x.ID == (int)SpiritHorde3)) { DespawnEvent dspwnHorde = combatData.GetDespawnEvents(mob.AgentItem).LastOrDefault(); if (dspwnHorde != null) { time = Math.Max(dspwnHorde.Time, time); } } DespawnEvent dspwn = combatData.GetDespawnEvents(desmina.AgentItem).LastOrDefault(); if (time != 0 && dspwn == null && time <= desmina.LastAware) { fightData.SetSuccess(true, time); } } } }
protected virtual void ComputeFightTargets(AgentData agentData, List <CombatItem> combatItems) { foreach (int id in GetUniqueTargetIDs()) { RegroupTargetsByID(id, agentData, combatItems); } List <int> ids = GetFightTargetsIDs(); foreach (int id in ids) { List <AgentItem> agents = agentData.GetNPCsByID(id); foreach (AgentItem agentItem in agents) { Targets.Add(new NPC(agentItem)); } } List <ParseEnum.TrashIDS> ids2 = GetTrashMobsIDS(); var aList = agentData.GetAgentByType(AgentItem.AgentType.NPC).Where(x => ids2.Contains(ParseEnum.GetTrashIDS(x.ID))).ToList(); //aList.AddRange(agentData.GetAgentByType(AgentItem.AgentType.Gadget).Where(x => ids2.Contains(ParseEnum.GetTrashIDS(x.ID)))); foreach (AgentItem a in aList) { var mob = new NPC(a); TrashMobs.Add(mob); } }
protected void ComputeFightTargets(AgentData agentData, List <CombatItem> combatItems) { foreach (ushort id in GetUniqueTargetIDs()) { RegroupTargetsByID(id, agentData, combatItems); } List <ushort> ids = GetFightTargetsIDs(); foreach (ushort id in ids) { List <AgentItem> agents = agentData.GetAgentsByID(id); foreach (AgentItem agentItem in agents) { Targets.Add(new Target(agentItem)); } } List <ParseEnum.TrashIDS> ids2 = GetTrashMobsIDS(); List <AgentItem> aList = agentData.GetAgentByType(AgentItem.AgentType.NPC).Where(x => ids2.Contains(ParseEnum.GetTrashIDS(x.ID))).ToList(); foreach (AgentItem a in aList) { Mob mob = new Mob(a); TrashMobs.Add(mob); } }
public void InitTrashMobCombatReplay(ParsedLog log, int pollingRate) { List <ParseEnum.TrashIDS> ids = GetTrashMobsIDS(); List <AgentItem> aList = log.AgentData.GetAgentByType(AgentItem.AgentType.NPC).Where(x => ids.Contains(ParseEnum.GetTrashIDS(x.ID))).ToList(); foreach (AgentItem a in aList) { Mob mob = new Mob(a); mob.InitCombatReplay(log, pollingRate, true, false); TrashMobs.Add(mob); } }
public override void ComputeAdditionalPlayerData(Player p, ParsedLog log) { // Bombs CombatReplay replay = p.CombatReplay; List <CombatItem> xeraFury = GetFilteredList(log, 35103, p); int xeraFuryStart = 0; foreach (CombatItem c in xeraFury) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { xeraFuryStart = (int)(c.Time - log.FightData.FightStart); } else { int xeraFuryEnd = (int)(c.Time - log.FightData.FightStart); replay.Actors.Add(new CircleActor(true, 0, 550, new Tuple <int, int>(xeraFuryStart, xeraFuryEnd), "rgba(200, 150, 0, 0.2)", new AgentConnector(p))); replay.Actors.Add(new CircleActor(true, xeraFuryEnd, 550, new Tuple <int, int>(xeraFuryStart, xeraFuryEnd), "rgba(200, 150, 0, 0.4)", new AgentConnector(p))); } } //fixated Statue List <CombatItem> fixatedStatue = GetFilteredList(log, 34912, p).Concat(GetFilteredList(log, 34925, p)).ToList(); int fixationStatueStart = 0; Mob statue = null; foreach (CombatItem c in fixatedStatue) { if (c.IsBuffRemove == ParseEnum.BuffRemove.None) { fixationStatueStart = (int)(c.Time - log.FightData.FightStart); statue = TrashMobs.FirstOrDefault(x => x.Agent == c.SrcAgent); } else { int fixationStatueEnd = (int)(c.Time - log.FightData.FightStart); Tuple <int, int> duration = new Tuple <int, int>(fixationStatueStart, fixationStatueEnd); if (statue != null) { replay.Actors.Add(new LineActor(0, 10, duration, "rgba(255, 0, 255, 0.5)", new AgentConnector(p), new AgentConnector(statue))); } } } }
public override void ComputePlayerCombatReplayActors(Player p, ParsedLog log, CombatReplay replay) { // Bombs List <AbstractBuffEvent> xeraFury = GetFilteredList(log.CombatData, 35103, p, true); int xeraFuryStart = 0; foreach (AbstractBuffEvent c in xeraFury) { if (c is BuffApplyEvent) { xeraFuryStart = (int)c.Time; } else { int xeraFuryEnd = (int)c.Time; replay.Decorations.Add(new CircleDecoration(true, 0, 550, (xeraFuryStart, xeraFuryEnd), "rgba(200, 150, 0, 0.2)", new AgentConnector(p))); replay.Decorations.Add(new CircleDecoration(true, xeraFuryEnd, 550, (xeraFuryStart, xeraFuryEnd), "rgba(200, 150, 0, 0.4)", new AgentConnector(p))); } } //fixated Statue var fixatedStatue = GetFilteredList(log.CombatData, 34912, p, true).Concat(GetFilteredList(log.CombatData, 34925, p, true)).ToList(); int fixationStatueStart = 0; NPC statue = null; foreach (AbstractBuffEvent c in fixatedStatue) { if (c is BuffApplyEvent) { fixationStatueStart = (int)c.Time; statue = TrashMobs.FirstOrDefault(x => x.AgentItem == c.By); } else { int fixationStatueEnd = (int)c.Time; if (statue != null) { replay.Decorations.Add(new LineDecoration(0, (fixationStatueStart, fixationStatueEnd), "rgba(255, 0, 255, 0.5)", new AgentConnector(p), new AgentConnector(statue))); } } } }
protected FightLogic(ushort triggerID, AgentData agentData) { TriggerID = triggerID; HasCombatReplayMap = GetCombatMap() != null; MechanicList = new List <Mechanic>() { new PlayerStatusMechanic(SkillItem.DeathId, "Dead", new MechanicPlotlySetting("x", "rgb(0,0,0)"), "Dead", 0), new PlayerStatusMechanic(SkillItem.DownId, "Downed", new MechanicPlotlySetting("cross", "rgb(255,0,0)"), "Downed", 0), new PlayerStatusMechanic(SkillItem.ResurrectId, "Resurrect", new MechanicPlotlySetting("cross-open", "rgb(0,255,255)"), "Res", 0), new PlayerStatusMechanic(SkillItem.AliveId, "Got up", new MechanicPlotlySetting("cross", "rgb(0,255,0)"), "Got up", 0), new PlayerStatusMechanic(SkillItem.DCId, "Disconnected", new MechanicPlotlySetting("x", "rgb(120,120,120)"), "DC", 0), new PlayerStatusMechanic(SkillItem.RespawnId, "Respawn", new MechanicPlotlySetting("cross", "rgb(120,120,255)"), "Resp", 0) }; _basicMechanicsCount = MechanicList.Count; List <ParseEnum.TrashIDS> ids = GetTrashMobsIDS(); List <AgentItem> aList = agentData.GetAgentByType(AgentItem.AgentType.NPC).Where(x => ids.Contains(ParseEnum.GetTrashIDS(x.ID))).ToList(); foreach (AgentItem a in aList) { Mob mob = new Mob(a); TrashMobs.Add(mob); } }
internal override void ComputePlayerCombatReplayActors(AbstractPlayer p, ParsedEvtcLog log, CombatReplay replay) { // fixated List <AbstractBuffEvent> fixated = GetFilteredList(log.CombatData, FixatedQadimThePeerless, p, true, true); int fixatedStart = 0; foreach (AbstractBuffEvent c in fixated) { if (c is BuffApplyEvent) { fixatedStart = Math.Max((int)c.Time, 0); } else { int fixatedEnd = (int)c.Time; replay.Decorations.Add(new CircleDecoration(true, 0, 120, (fixatedStart, fixatedEnd), "rgba(255, 80, 255, 0.3)", new AgentConnector(p))); } } // Chaos Corrosion List <AbstractBuffEvent> chaosCorrosion = GetFilteredList(log.CombatData, ChaosCorrosion, p, true, true); int corrosionStart = 0; foreach (AbstractBuffEvent c in chaosCorrosion) { if (c is BuffApplyEvent) { corrosionStart = (int)c.Time; } else { int corrosionEnd = (int)c.Time; replay.Decorations.Add(new CircleDecoration(true, 0, 100, (corrosionStart, corrosionEnd), "rgba(80, 80, 80, 0.3)", new AgentConnector(p))); } } // Critical Mass, debuff while carrying an orb List <AbstractBuffEvent> criticalMass = GetFilteredList(log.CombatData, CriticalMass, p, true, true); int criticalMassStart = 0; foreach (AbstractBuffEvent c in criticalMass) { if (c is BuffApplyEvent) { criticalMassStart = (int)c.Time; } else { int criticalMassEnd = (int)c.Time; replay.Decorations.Add(new CircleDecoration(false, 0, 200, (criticalMassStart, criticalMassEnd), "rgba(255, 0, 0, 0.3)", new AgentConnector(p))); } } // Magma drop List <AbstractBuffEvent> magmaDrop = GetFilteredList(log.CombatData, MagmaDrop, p, true, true); int magmaDropStart = 0; int magmaRadius = 420; int magmaOffset = 4000; string[] magmaColors = { "255, 215, 0", "255, 130, 50" }; int magmaColor = 0; foreach (AbstractBuffEvent c in magmaDrop) { if (c is BuffApplyEvent) { magmaDropStart = (int)c.Time; } else { int magmaDropEnd = (int)c.Time; replay.Decorations.Add(new CircleDecoration(true, 0, magmaRadius, (magmaDropStart, magmaDropEnd), "rgba(255, 50, 0, 0.15)", new AgentConnector(p))); replay.Decorations.Add(new CircleDecoration(true, magmaDropEnd, magmaRadius, (magmaDropStart, magmaDropEnd), "rgba(255, 50, 0, 0.25)", new AgentConnector(p))); Point3D magmaNextPos = replay.PolledPositions.FirstOrDefault(x => x.Time >= magmaDropEnd); Point3D magmaPrevPos = replay.PolledPositions.LastOrDefault(x => x.Time <= magmaDropEnd); if (magmaNextPos != null || magmaPrevPos != null) { string colorToUse = magmaColors[magmaColor]; magmaColor = (magmaColor + 1) % 2; replay.Decorations.Add(new CircleDecoration(true, 0, magmaRadius, (magmaDropEnd, magmaDropEnd + magmaOffset), "rgba(" + colorToUse + ", 0.15)", new InterpolatedPositionConnector(magmaPrevPos, magmaNextPos, magmaDropEnd))); replay.Decorations.Add(new CircleDecoration(true, magmaDropEnd + magmaOffset, magmaRadius, (magmaDropEnd, magmaDropEnd + magmaOffset), "rgba(" + colorToUse + ", 0.25)", new InterpolatedPositionConnector(magmaPrevPos, magmaNextPos, magmaDropEnd))); replay.Decorations.Add(new CircleDecoration(true, 0, magmaRadius, (magmaDropEnd + magmaOffset, (int)log.FightData.FightEnd), "rgba(" + colorToUse + ", 0.5)", new InterpolatedPositionConnector(magmaPrevPos, magmaNextPos, magmaDropEnd))); } } } //sapping surge, bad red tether List <AbstractBuffEvent> sappingSurge = GetFilteredList(log.CombatData, SappingSurge, p, true, true); int surgeStart = 0; AbstractSingleActor source = null; foreach (AbstractBuffEvent c in sappingSurge) { if (c is BuffApplyEvent) { AbstractSingleActor qadim = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.PeerlessQadim); surgeStart = (int)c.Time; source = (AbstractSingleActor)log.PlayerList.FirstOrDefault(x => x.AgentItem == c.CreditedBy) ?? qadim; } else { int surgeEnd = (int)c.Time; if (source != null) { replay.Decorations.Add(new LineDecoration(0, (surgeStart, surgeEnd), "rgba(255, 0, 0, 0.4)", new AgentConnector(p), new AgentConnector(source))); } } } // kinetic abundance, good (blue) tether List <AbstractBuffEvent> kineticAbundance = GetFilteredList(log.CombatData, KineticAbundance, p, true, true); int kinStart = 0; AbstractSingleActor kinSource = null; foreach (AbstractBuffEvent c in kineticAbundance) { if (c is BuffApplyEvent) { kinStart = (int)c.Time; //kinSource = log.PlayerList.FirstOrDefault(x => x.AgentItem == c.By); kinSource = (AbstractSingleActor)log.PlayerList.FirstOrDefault(x => x.AgentItem == c.CreditedBy) ?? TrashMobs.FirstOrDefault(x => x.AgentItem == c.CreditedBy); } else { int kinEnd = (int)c.Time; if (kinSource != null) { replay.Decorations.Add(new LineDecoration(0, (kinStart, kinEnd), "rgba(0, 0, 255, 0.4)", new AgentConnector(p), new AgentConnector(kinSource))); } } } }
internal override void ComputeNPCCombatReplayActors(NPC target, ParsedEvtcLog log, CombatReplay replay) { IReadOnlyList <AbstractCastEvent> cls = target.GetCastEvents(log, 0, log.FightData.FightEnd); int start = (int)replay.TimeOffsets.start; int end = (int)replay.TimeOffsets.end; switch (target.ID) { case (int)ArcDPSEnums.TargetID.PeerlessQadim: var cataCycle = cls.Where(x => x.SkillId == 56329).ToList(); var forceOfHavoc = cls.Where(x => x.SkillId == 56017).ToList(); var forceOfRetal = cls.Where(x => x.SkillId == ForceOfRetaliationCast).ToList(); var etherStrikes = cls.Where(x => x.SkillId == 56012 || x.SkillId == 56653).ToList(); var causticChaos = cls.Where(x => x.SkillId == 56332).ToList(); var expoReperc = cls.Where(x => x.SkillId == 56223).ToList(); foreach (AbstractCastEvent c in cataCycle) { int magmaRadius = 850; start = (int)c.Time; end = (int)c.EndTime; Point3D pylonPosition = replay.PolledPositions.LastOrDefault(x => x.Time <= end); replay.Decorations.Add(new CircleDecoration(true, 0, magmaRadius, (start, end), "rgba(255, 50, 50, 0.15)", new PositionConnector(pylonPosition))); replay.Decorations.Add(new CircleDecoration(true, end, magmaRadius, (start, end), "rgba(255, 50, 50, 0.25)", new PositionConnector(pylonPosition))); replay.Decorations.Add(new CircleDecoration(true, 0, magmaRadius, (end, (int)log.FightData.FightEnd), "rgba(255, 50, 0, 0.5)", new PositionConnector(pylonPosition))); } foreach (AbstractCastEvent c in forceOfHavoc) { int roadLength = 2400; int roadWidth = 360; int hitboxOffset = 200; int subdivisions = 100; int rollOutTime = 3250; start = (int)c.Time; int preCastTime = 1500; int duration = 22500; Point3D facing = replay.Rotations.LastOrDefault(x => x.Time <= start + 1000); Point3D position = replay.Positions.LastOrDefault(x => x.Time <= start + 1000); if (facing != null && position != null) { float direction = ParserHelper.RadianToDegreeF(Math.Atan2(facing.Y, facing.X)); replay.Decorations.Add(new RotatedRectangleDecoration(true, 0, roadLength, roadWidth, direction, roadLength / 2 + 200, (start, start + preCastTime), "rgba(255, 0, 0, 0.1)", new PositionConnector(position))); for (int i = 0; i < subdivisions; i++) { replay.Decorations.Add(new RotatedRectangleDecoration(true, 0, roadLength / subdivisions, roadWidth, direction, (int)((i + 0.5) * roadLength / subdivisions + hitboxOffset), (start + preCastTime + i * (rollOutTime / subdivisions), start + preCastTime + i * (rollOutTime / subdivisions) + duration), "rgba(143, 0, 179, 0.6)", new PositionConnector(position))); } } } foreach (AbstractCastEvent c in forceOfRetal) { int radius = 650; double radiusIncrement = 433.3; int preCastTime = 1800; int timeBetweenCascades = 200; int cascades = 5; start = (int)c.Time + 1400; Point3D position = replay.Positions.LastOrDefault(x => x.Time <= start + 1000); replay.Decorations.Add(new CircleDecoration(true, 0, radius, (start, start + preCastTime), "rgba(255, 220, 50, 0.15)", new PositionConnector(position))); replay.Decorations.Add(new CircleDecoration(true, start + preCastTime, radius, (start, start + preCastTime), "rgba(255, 220, 50, 0.25)", new PositionConnector(position))); for (int i = 0; i < cascades; i++) { replay.Decorations.Add(new DoughnutDecoration(true, 0, radius + (int)(radiusIncrement * i), radius + (int)(radiusIncrement * (i + 1)), (start + preCastTime + timeBetweenCascades * i, start + preCastTime + timeBetweenCascades * (i + 1)), "rgba(30, 30, 30, 0.5)", new PositionConnector(position))); replay.Decorations.Add(new DoughnutDecoration(true, 0, radius + (int)(radiusIncrement * i), radius + (int)(radiusIncrement * (i + 1)), (start + preCastTime + timeBetweenCascades * (i + 1), start + preCastTime + timeBetweenCascades * (i + 2)), "rgba(50, 20, 50, 0.25)", new PositionConnector(position))); } } foreach (AbstractCastEvent c in etherStrikes) { int coneRadius = 2600; int coneAngle = 60; start = (int)c.Time; end = start + 250; Point3D facing = replay.Rotations.LastOrDefault(x => x.Time <= start + 300); replay.Decorations.Add(new PieDecoration(false, 0, coneRadius, facing, coneAngle, (start, end), "rgba(255, 100, 0, 0.30)", new AgentConnector(target))); replay.Decorations.Add(new PieDecoration(true, 0, coneRadius, facing, coneAngle, (start, end), "rgba(255, 100, 0, 0.1)", new AgentConnector(target))); } foreach (AbstractCastEvent c in causticChaos) { double acceleration = c.Acceleration; double ratio = 1.0; if (acceleration > 0) { ratio = acceleration * 0.5 + 1; } else { ratio = acceleration * 0.6 + 1; } int chaosLength = 2600; int chaosWidth = 100; start = (int)c.Time; end = (int)c.EndTime; int aimTime = (int)((double)c.ExpectedDuration * ratio); replay.Decorations.Add(new FacingDecoration((0, end), new AgentConnector(target), replay.PolledRotations)); replay.Decorations.Add(new FacingRectangleDecoration((start, end), new AgentConnector(target), replay.PolledRotations, chaosLength, chaosWidth, chaosLength / 2, "rgba(255,100,0,0.3)")); if (end > start + aimTime) { replay.Decorations.Add(new FacingRectangleDecoration((start + aimTime, end), new AgentConnector(target), replay.PolledRotations, chaosLength, chaosWidth, chaosLength / 2, "rgba(100,100,100,0.7)")); } } foreach (AbstractCastEvent c in expoReperc) { int radius = 650; start = (int)c.Time; end = (int)c.EndTime; Point3D position = replay.Positions.LastOrDefault(x => x.Time <= start + 1000); replay.Decorations.Add(new CircleDecoration(true, 0, radius, (start, end), "rgba(255, 220, 0, 0.15)", new PositionConnector(position))); replay.Decorations.Add(new CircleDecoration(true, end, radius, (start, end), "rgba(255, 220, 50, 0.25)", new PositionConnector(position))); foreach (NPC pylon in TrashMobs.Where(x => x.ID == 21962)) { replay.Decorations.Add(new CircleDecoration(true, 0, radius, (start, end), "rgba(255, 220, 0, 0.15)", new AgentConnector(pylon))); replay.Decorations.Add(new CircleDecoration(true, end, radius, (start, end), "rgba(255, 220, 50, 0.25)", new AgentConnector(pylon))); } } break; case (int)ArcDPSEnums.TrashID.EntropicDistortion: //sapping surge, red tether List <AbstractBuffEvent> sappingSurge = GetFilteredList(log.CombatData, SappingSurge, target, true, true); int surgeStart = 0; AbstractSingleActor source = null; foreach (AbstractBuffEvent c in sappingSurge) { if (c is BuffApplyEvent) { AbstractSingleActor qadim = Targets.FirstOrDefault(x => x.ID == (int)ArcDPSEnums.TargetID.PeerlessQadim); surgeStart = (int)c.Time; source = (AbstractSingleActor)log.PlayerList.FirstOrDefault(x => x.AgentItem == c.CreditedBy) ?? qadim; } else { int surgeEnd = (int)c.Time; if (source != null) { replay.Decorations.Add(new LineDecoration(0, (surgeStart, surgeEnd), "rgba(255, 0, 0, 0.3)", new AgentConnector(target), new AgentConnector(source))); } } } Point3D firstEntropicPosition = replay.PolledPositions.FirstOrDefault(); if (firstEntropicPosition != null) { replay.Decorations.Add(new CircleDecoration(true, 0, 300, (start - 5000, start), "rgba(255, 0, 0, 0.4)", new PositionConnector(firstEntropicPosition))); replay.Decorations.Add(new CircleDecoration(true, start, 300, (start - 5000, start), "rgba(255, 0, 0, 0.4)", new PositionConnector(firstEntropicPosition))); } break; case (int)ArcDPSEnums.TrashID.BigKillerTornado: replay.Decorations.Add(new CircleDecoration(true, 0, 450, (start, end), "rgba(255, 150, 0, 0.4)", new AgentConnector(target))); break; case (int)ArcDPSEnums.TrashID.Pylon1: break; case (int)ArcDPSEnums.TrashID.Pylon2: break; case (int)ArcDPSEnums.TrashID.EnergyOrb: replay.Decorations.Add(new CircleDecoration(true, 0, 200, (start, end), "rgba(0, 255, 0, 0.3)", new AgentConnector(target))); break; default: break; } }
public override void ComputePlayerCombatReplayActors(Player p, ParsedLog log, CombatReplay replay) { // fixated List <AbstractBuffEvent> fixated = GetFilteredList(log.CombatData, 56510, p, true); int fixatedStart = 0; foreach (AbstractBuffEvent c in fixated) { if (c is BuffApplyEvent) { fixatedStart = Math.Max((int)c.Time, 0); } else { int fixatedEnd = (int)c.Time; replay.Decorations.Add(new CircleDecoration(true, 0, 120, (fixatedStart, fixatedEnd), "rgba(255, 80, 255, 0.3)", new AgentConnector(p))); } } // Magma drop List <AbstractBuffEvent> magmaDrop = GetFilteredList(log.CombatData, 56475, p, true); int magmaDropStart = 0; int magmaRadius = 420; int magmaOffset = 4000; foreach (AbstractBuffEvent c in magmaDrop) { if (c is BuffApplyEvent) { magmaDropStart = (int)c.Time; } else { int magmaDropEnd = (int)c.Time; replay.Decorations.Add(new CircleDecoration(true, 0, magmaRadius, (magmaDropStart, magmaDropEnd), "rgba(255, 150, 0, 0.15)", new AgentConnector(p))); replay.Decorations.Add(new CircleDecoration(true, magmaDropEnd, magmaRadius, (magmaDropStart, magmaDropEnd), "rgba(255, 150, 0, 0.25)", new AgentConnector(p))); Point3D magmaNextPos = replay.PolledPositions.FirstOrDefault(x => x.Time >= magmaDropEnd); Point3D magmaPrevPos = replay.PolledPositions.LastOrDefault(x => x.Time <= magmaDropEnd); if (magmaNextPos != null || magmaPrevPos != null) { replay.Decorations.Add(new CircleDecoration(true, 0, magmaRadius, (magmaDropEnd, magmaDropEnd + magmaOffset), "rgba(255, 220, 50, 0.15)", new InterpolatedPositionConnector(magmaPrevPos, magmaNextPos, magmaDropEnd))); replay.Decorations.Add(new CircleDecoration(true, magmaDropEnd + magmaOffset, magmaRadius, (magmaDropEnd, magmaDropEnd + magmaOffset), "rgba(255, 220, 50, 0.25)", new InterpolatedPositionConnector(magmaPrevPos, magmaNextPos, magmaDropEnd))); replay.Decorations.Add(new CircleDecoration(true, 0, magmaRadius, (magmaDropEnd + magmaOffset, (int)log.FightData.FightEnd), "rgba(255, 220, 50, 0.5)", new InterpolatedPositionConnector(magmaPrevPos, magmaNextPos, magmaDropEnd))); } } } //sapping surge, bad red tether List <AbstractBuffEvent> sappingSurge = GetFilteredList(log.CombatData, 56118, p, true); int surgeStart = 0; AbstractSingleActor source = null; foreach (AbstractBuffEvent c in sappingSurge) { if (c is BuffApplyEvent) { NPC qadim = Targets.Find(x => x.ID == (int)ParseEnum.TargetID.PeerlessQadim); surgeStart = (int)c.Time; source = (AbstractSingleActor)log.PlayerList.FirstOrDefault(x => x.AgentItem == c.By) ?? qadim; } else { int surgeEnd = (int)c.Time; if (source != null) { replay.Decorations.Add(new LineDecoration(0, (surgeStart, surgeEnd), "rgba(255, 0, 0, 0.4)", new AgentConnector(p), new AgentConnector(source))); } } } // kinetic abundance, good (blue) tether List <AbstractBuffEvent> kineticAbundance = GetFilteredList(log.CombatData, 56609, p, true); int kinStart = 0; AbstractSingleActor kinSource = null; foreach (AbstractBuffEvent c in kineticAbundance) { if (c is BuffApplyEvent) { kinStart = (int)c.Time; //kinSource = log.PlayerList.FirstOrDefault(x => x.AgentItem == c.By); kinSource = (AbstractSingleActor)log.PlayerList.FirstOrDefault(x => x.AgentItem == c.By) ?? TrashMobs.FirstOrDefault(x => x.AgentItem == c.By); } else { int kinEnd = (int)c.Time; if (kinSource != null) { replay.Decorations.Add(new LineDecoration(0, (kinStart, kinEnd), "rgba(0, 0, 255, 0.4)", new AgentConnector(p), new AgentConnector(kinSource))); } } } }