public void UpdateGraph(CalculationOptionsMage calculationOptions) { DisplayCalculations calculations = calculationOptions.Calculations; Chart.Series.Clear(); Chart.Axes.Clear(); Chart.Text = null; if (calculationOptions.SequenceReconstruction == null) { Chart.Text = "Sequence reconstruction data is not available."; } else { List <EffectCooldown> cooldownList = calculationOptions.Calculations.CooldownList; /*brushSubPoints = new Brush[cooldownList.Count]; * colorSubPointsA = new Color[cooldownList.Count]; * colorSubPointsB = new Color[cooldownList.Count]; * for (int i = 0; i < cooldownList.Count; i++) * { * Color baseColor = cooldownList[i].Color; * brushSubPoints[i] = new SolidBrush(Color.FromArgb(baseColor.R / 2, baseColor.G / 2, baseColor.B / 2)); * colorSubPointsA[i] = Color.FromArgb(baseColor.A / 2, baseColor.R / 2, baseColor.G / 2, baseColor.B / 2); * colorSubPointsB[i] = Color.FromArgb(baseColor.A / 2, baseColor); * } * StringFormat formatSubPoint = new StringFormat(); * formatSubPoint.Alignment = StringAlignment.Center; * formatSubPoint.LineAlignment = StringAlignment.Center; * * int maxWidth = 1; * for (int i = 0; i < cooldownList.Count; i++) * { * string subPointName = cooldownList[i].Name; * int widthSubPoint = (int)Math.Ceiling(g.MeasureString(subPointName, fontLegend).Width + 2f); * if (widthSubPoint > maxWidth) maxWidth = widthSubPoint; * } * for (int i = 0; i < cooldownList.Count; i++) * { * string cooldownName = cooldownList[i].Name; * rectSubPoint = new Rectangle(2, legendY, maxWidth, 16); * blendSubPoint = new System.Drawing.Drawing2D.ColorBlend(3); * blendSubPoint.Colors = new Color[] { colorSubPointsA[i], colorSubPointsB[i], colorSubPointsA[i] }; * blendSubPoint.Positions = new float[] { 0f, 0.5f, 1f }; * brushSubPointFill = new System.Drawing.Drawing2D.LinearGradientBrush(rectSubPoint, colorSubPointsA[i], colorSubPointsB[i], 67f); * brushSubPointFill.InterpolationColors = blendSubPoint; * * g.FillRectangle(brushSubPointFill, rectSubPoint); * g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint); * g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint); * g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint); * * g.DrawString(cooldownName, fontLegend, brushSubPoints[i], rectSubPoint, formatSubPoint); * legendY += 16; * }*/ if (calculationOptions.AdviseAdvancedSolver) { Chart.Text = "Sequence Reconstruction was not fully successful, it is recommended that you enable more options in advanced solver (segment cooldowns, integral mana consumables, advanced constraints options)!"; } /*g.DrawLine(Pens.Aqua, new Point(maxWidth + 40, 10), new Point(maxWidth + 80, 10)); * g.DrawString("Mana", fontLegend, Brushes.Black, new Point(maxWidth + 90, 2)); * g.DrawLine(Pens.Red, new Point(maxWidth + 40, 26), new Point(maxWidth + 80, 26)); * g.DrawString("Dps", fontLegend, Brushes.Black, new Point(maxWidth + 90, 18));*/ List <SequenceItem> sequence = calculationOptions.SequenceReconstruction.sequence; List <TimeData> manaList = new List <TimeData>(); float mana = calculations.StartingMana; int gemCount = 0; float time = 0; Color manaFill = Color.FromArgb(50, 0, 0, 255); float maxMana = calculations.BaseStats.Mana; float maxDps = 100; DateTime baseTime = new DateTime(2000, 1, 1, 0, 0, 0); manaList.Add(new TimeData() { Time = baseTime, Value = mana }); for (int i = 0; i < sequence.Count; i++) { int index = sequence[i].Index; VariableType type = sequence[i].VariableType; float duration = (float)sequence[i].Duration; Cycle cycle = sequence[i].Cycle; CastingState state = sequence[i].CastingState; if (cycle != null) { float dps = (float)cycle.GetDamagePerSecond(state.ManaAdeptBonus, 1); if (dps > maxDps) { maxDps = dps; } } float mps = (float)sequence[i].Mps; if (sequence[i].IsManaPotionOrGem) { float value = duration; duration = 0; if (sequence[i].VariableType == VariableType.ManaGem) { mana += (float)((1 + calculations.BaseStats.BonusManaGem) * calculations.ManaGemValue * value); gemCount++; } else if (sequence[i].VariableType == VariableType.ManaPotion) { mana += (float)((1 + calculations.BaseStats.BonusManaPotionEffectMultiplier) * calculations.ManaPotionValue * value); } if (mana < 0) { mana = 0; } if (mana > maxMana) { mana = maxMana; } manaList.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time) + TimeSpan.FromTicks(1), Value = mana }); } else { /*if (sequence[i].IsEvocation) * { * switch (sequence[i].VariableType) * { * case VariableType.Evocation: * mps = -(float)calculationOptions.Calculations.EvocationRegen; * break; * case VariableType.EvocationIV: * mps = -(float)calculationOptions.Calculations.EvocationRegenIV; * break; * case VariableType.EvocationHero: * mps = -(float)calculationOptions.Calculations.EvocationRegenHero; * break; * case VariableType.EvocationIVHero: * mps = -(float)calculationOptions.Calculations.EvocationRegenIVHero; * break; * } * }*/ float partTime = duration; if (mana - mps * duration < 0) { partTime = mana / mps; } else if (mana - mps * duration > maxMana) { partTime = (mana - maxMana) / mps; } mana -= mps * duration; if (mana < 0) { mana = 0; } if (mana > maxMana) { mana = maxMana; } manaList.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time + partTime), Value = mana }); if (partTime < duration) { manaList.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time + duration), Value = mana }); } } time += duration; } Style dateTimeAxisLabelStyle = new Style(typeof(DateTimeAxisLabel)); dateTimeAxisLabelStyle.Setters.Add(new Setter(DateTimeAxisLabel.MinutesIntervalStringFormatProperty, "{0:m:ss}")); dateTimeAxisLabelStyle.Setters.Add(new Setter(DateTimeAxisLabel.SecondsIntervalStringFormatProperty, "{0:m:ss}")); DateTimeAxis timeAxis = new DateTimeAxis() { //Title = "Time", Minimum = baseTime, Maximum = baseTime + TimeSpan.FromSeconds(calculationOptions.FightDuration), IntervalType = DateTimeIntervalType.Seconds, AxisLabelStyle = dateTimeAxisLabelStyle, Orientation = AxisOrientation.X, ShowGridLines = true, Location = AxisLocation.Top, }; Style hiddenCategoryLabelStyle = new Style(typeof(AxisLabel)); hiddenCategoryLabelStyle.Setters.Add(new Setter(NumericAxisLabel.VisibilityProperty, Visibility.Collapsed)); CategoryAxis categoryAxis = new CategoryAxis() { AxisLabelStyle = hiddenCategoryLabelStyle, Orientation = AxisOrientation.Y, MajorTickMarkStyle = null, }; int barCount = 0; for (int cooldown = 0; cooldown < cooldownList.Count; cooldown++) { List <TimeIntervalData> data = new List <TimeIntervalData>(); //blendSubPoint = new System.Drawing.Drawing2D.ColorBlend(3); //blendSubPoint.Colors = new Color[] { colorSubPointsA[cooldown], colorSubPointsB[cooldown], colorSubPointsA[cooldown] }; //blendSubPoint.Positions = new float[] { 0f, 0.5f, 1f }; bool on = false; float timeOn = 0.0f; time = 0; for (int i = 0; i < sequence.Count; i++) { float duration = (float)sequence[i].Duration; if (sequence[i].IsManaPotionOrGem) { duration = 0; } if (on && !sequence[i].CastingState.EffectsActive(cooldownList[cooldown]) && !sequence[i].IsManaPotionOrGem) { on = false; if (time > timeOn) { data.Add(new TimeIntervalData() { Start = baseTime + TimeSpan.FromSeconds(timeOn), End = baseTime + TimeSpan.FromSeconds(time), Category = cooldownList[cooldown].Name }); } } else if (!on && sequence[i].CastingState.EffectsActive(cooldownList[cooldown])) { on = true; timeOn = time; } time += duration; } if (on) { if (time - timeOn > 0) { data.Add(new TimeIntervalData() { Start = baseTime + TimeSpan.FromSeconds(timeOn), End = baseTime + TimeSpan.FromSeconds(time), Category = cooldownList[cooldown].Name }); } } if (data.Count > 0) { barCount++; Style timeIntervalStyle = new Style(typeof(TimeIntervalDataPoint)); timeIntervalStyle.Setters.Add(new Setter(TimeIntervalDataPoint.BackgroundProperty, new SolidColorBrush(cooldownList[cooldown].Color))); Chart.Series.Add(new TimeIntervalSeries() { Title = cooldownList[cooldown].Name, ItemsSource = data, IndependentValuePath = "Category", DependentValuePath = "End", StartTimePath = "Start", EndTimePath = "End", DataPointStyle = timeIntervalStyle, DependentRangeAxis = timeAxis, IndependentAxis = categoryAxis }); } } if (calculationOptions.DisplaySegmentCooldowns && calculationOptions.BossHandler) { foreach (var buffState in calculationOptions.Character.BossOptions.BuffStates) { if (buffState.Chance > 0 && buffState.Stats.BonusDamageMultiplier > 0) { List <TimeIntervalData> data = new List <TimeIntervalData>(); foreach (var phase in buffState.PhaseTimes) { data.Add(new TimeIntervalData() { Start = baseTime + TimeSpan.FromSeconds(phase.Value[0]), End = baseTime + TimeSpan.FromSeconds(phase.Value[1]), Category = buffState.Name }); } if (data.Count > 0) { barCount++; Style timeIntervalStyle = new Style(typeof(TimeIntervalDataPoint)); timeIntervalStyle.Setters.Add(new Setter(TimeIntervalDataPoint.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 0, 0, 0)))); Chart.Series.Add(new TimeIntervalSeries() { Title = buffState.Name, ItemsSource = data, IndependentValuePath = "Category", DependentValuePath = "End", StartTimePath = "Start", EndTimePath = "End", DataPointStyle = timeIntervalStyle, DependentRangeAxis = timeAxis, IndependentAxis = categoryAxis }); } } } } Style hiddenNumericLabelStyle = new Style(typeof(NumericAxisLabel)); hiddenNumericLabelStyle.Setters.Add(new Setter(NumericAxisLabel.VisibilityProperty, Visibility.Collapsed)); Chart.Series.Add(new AreaSeries() { Title = "Mana", ItemsSource = manaList, IndependentValuePath = "Time", DependentValuePath = "Value", DataPointStyle = (Style)Resources["ManaStyle"], Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x00, 0xFF, 0xFF)), DependentRangeAxis = new OffsetLinearAxis() { Minimum = 0, Offset = barCount * 10.0, Orientation = AxisOrientation.Y, AxisLabelStyle = hiddenNumericLabelStyle, MajorTickMarkStyle = null, MinorTickMarkStyle = null, }, IndependentAxis = timeAxis, LegendItemStyle = null, }); maxDps *= 1.1f; List <TimeData> list = new List <TimeData>(); time = 0.0f; for (int i = 0; i < sequence.Count; i++) { int index = sequence[i].Index; VariableType type = sequence[i].VariableType; float duration = (float)sequence[i].Duration; Cycle cycle = sequence[i].Cycle; CastingState state = sequence[i].CastingState; float mps = (float)sequence[i].Mps; if (sequence[i].IsManaPotionOrGem) { duration = 0; } float dps = 0; if (cycle != null) { dps = (float)cycle.DamagePerSecond; } if (duration > 0) { if (calculations.ManaAdeptBonus > 0) { for (int t = 1; t < 10; t++) { DateTime timet = baseTime + TimeSpan.FromSeconds(time + 0.1f * t * duration); if (cycle != null) { dps = (float)cycle.GetDamagePerSecond(calculations.ManaAdeptBonus, GetManaAtTime(manaList, timet) / maxMana); } // apply state multipliers if (calculationOptions.DisplaySegmentCooldowns) { dps *= calculationOptions.GetDamageMultiplier(time, time + duration); } list.Add(new TimeData() { Time = timet, Value = dps }); } } else { // apply state multipliers if (calculationOptions.DisplaySegmentCooldowns) { dps *= calculationOptions.GetDamageMultiplier(time, time + duration); } list.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time + 0.1f * duration), Value = dps }); list.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time + 0.9f * duration), Value = dps }); } } time += duration; } Chart.Series.Add(new LineSeries() { Title = "Dps", ItemsSource = list, IndependentValuePath = "Time", DependentValuePath = "Value", DataPointStyle = (Style)Resources["DpsStyle"], DependentRangeAxis = new OffsetLinearAxis() { Offset = barCount * 10.0, Minimum = 0, Orientation = AxisOrientation.Y, AxisLabelStyle = hiddenNumericLabelStyle, MajorTickMarkStyle = null, MinorTickMarkStyle = null, }, IndependentAxis = timeAxis, }); if (zeroLineCanvas == null) { zeroLineCanvas = new ZeroLineCanvas(categoryAxis); zeroLineCanvas.BarCount = barCount; } else { zeroLineCanvas.BarCount = barCount; zeroLineCanvas.Axis = categoryAxis; } ISeriesHost host = (ISeriesHost)Chart; if (!host.BackgroundElements.Contains(zeroLineCanvas)) { host.BackgroundElements.Add(zeroLineCanvas); } } }
public void UpdateGraph(CalculationOptionsMage calculationOptions) { DisplayCalculations calculations = calculationOptions.Calculations; Chart.Series.Clear(); Chart.Axes.Clear(); Chart.Text = null; if (calculationOptions.SequenceReconstruction == null) { Chart.Text = "Sequence reconstruction data is not available."; } else { List<EffectCooldown> cooldownList = calculationOptions.Calculations.CooldownList; /*brushSubPoints = new Brush[cooldownList.Count]; colorSubPointsA = new Color[cooldownList.Count]; colorSubPointsB = new Color[cooldownList.Count]; for (int i = 0; i < cooldownList.Count; i++) { Color baseColor = cooldownList[i].Color; brushSubPoints[i] = new SolidBrush(Color.FromArgb(baseColor.R / 2, baseColor.G / 2, baseColor.B / 2)); colorSubPointsA[i] = Color.FromArgb(baseColor.A / 2, baseColor.R / 2, baseColor.G / 2, baseColor.B / 2); colorSubPointsB[i] = Color.FromArgb(baseColor.A / 2, baseColor); } StringFormat formatSubPoint = new StringFormat(); formatSubPoint.Alignment = StringAlignment.Center; formatSubPoint.LineAlignment = StringAlignment.Center; int maxWidth = 1; for (int i = 0; i < cooldownList.Count; i++) { string subPointName = cooldownList[i].Name; int widthSubPoint = (int)Math.Ceiling(g.MeasureString(subPointName, fontLegend).Width + 2f); if (widthSubPoint > maxWidth) maxWidth = widthSubPoint; } for (int i = 0; i < cooldownList.Count; i++) { string cooldownName = cooldownList[i].Name; rectSubPoint = new Rectangle(2, legendY, maxWidth, 16); blendSubPoint = new System.Drawing.Drawing2D.ColorBlend(3); blendSubPoint.Colors = new Color[] { colorSubPointsA[i], colorSubPointsB[i], colorSubPointsA[i] }; blendSubPoint.Positions = new float[] { 0f, 0.5f, 1f }; brushSubPointFill = new System.Drawing.Drawing2D.LinearGradientBrush(rectSubPoint, colorSubPointsA[i], colorSubPointsB[i], 67f); brushSubPointFill.InterpolationColors = blendSubPoint; g.FillRectangle(brushSubPointFill, rectSubPoint); g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint); g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint); g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint); g.DrawString(cooldownName, fontLegend, brushSubPoints[i], rectSubPoint, formatSubPoint); legendY += 16; }*/ if (calculationOptions.AdviseAdvancedSolver) { Chart.Text = "Sequence Reconstruction was not fully successful, it is recommended that you enable more options in advanced solver (segment cooldowns, integral mana consumables, advanced constraints options)!"; } /*g.DrawLine(Pens.Aqua, new Point(maxWidth + 40, 10), new Point(maxWidth + 80, 10)); g.DrawString("Mana", fontLegend, Brushes.Black, new Point(maxWidth + 90, 2)); g.DrawLine(Pens.Red, new Point(maxWidth + 40, 26), new Point(maxWidth + 80, 26)); g.DrawString("Dps", fontLegend, Brushes.Black, new Point(maxWidth + 90, 18));*/ List<SequenceItem> sequence = calculationOptions.SequenceReconstruction.sequence; List<TimeData> manaList = new List<TimeData>(); float mana = calculations.StartingMana; int gemCount = 0; float time = 0; Color manaFill = Color.FromArgb(50, 0, 0, 255); float maxMana = calculations.BaseStats.Mana; float maxDps = 100; DateTime baseTime = new DateTime(2000, 1, 1, 0, 0, 0); manaList.Add(new TimeData() { Time = baseTime, Value = mana }); for (int i = 0; i < sequence.Count; i++) { int index = sequence[i].Index; VariableType type = sequence[i].VariableType; float duration = (float)sequence[i].Duration; Cycle cycle = sequence[i].Cycle; CastingState state = sequence[i].CastingState; if (cycle != null) { float dps = (float)cycle.GetDamagePerSecond(state.ManaAdeptBonus, 1); if (dps > maxDps) maxDps = dps; } float mps = (float)sequence[i].Mps; if (sequence[i].IsManaPotionOrGem) { float value = duration; duration = 0; if (sequence[i].VariableType == VariableType.ManaGem) { mana += (float)((1 + calculations.BaseStats.BonusManaGem) * calculations.ManaGemValue * value); gemCount++; } else if (sequence[i].VariableType == VariableType.ManaPotion) { mana += (float)((1 + calculations.BaseStats.BonusManaPotionEffectMultiplier) * calculations.ManaPotionValue * value); } if (mana < 0) mana = 0; if (mana > maxMana) { mana = maxMana; } manaList.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time) + TimeSpan.FromTicks(1), Value = mana }); } else { /*if (sequence[i].IsEvocation) { switch (sequence[i].VariableType) { case VariableType.Evocation: mps = -(float)calculationOptions.Calculations.EvocationRegen; break; case VariableType.EvocationIV: mps = -(float)calculationOptions.Calculations.EvocationRegenIV; break; case VariableType.EvocationHero: mps = -(float)calculationOptions.Calculations.EvocationRegenHero; break; case VariableType.EvocationIVHero: mps = -(float)calculationOptions.Calculations.EvocationRegenIVHero; break; } }*/ float partTime = duration; if (mana - mps * duration < 0) partTime = mana / mps; else if (mana - mps * duration > maxMana) partTime = (mana - maxMana) / mps; mana -= mps * duration; if (mana < 0) mana = 0; if (mana > maxMana) { mana = maxMana; } manaList.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time + partTime), Value = mana }); if (partTime < duration) { manaList.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time + duration), Value = mana }); } } time += duration; } Style dateTimeAxisLabelStyle = new Style(typeof(DateTimeAxisLabel)); dateTimeAxisLabelStyle.Setters.Add(new Setter(DateTimeAxisLabel.MinutesIntervalStringFormatProperty, "{0:m:ss}")); dateTimeAxisLabelStyle.Setters.Add(new Setter(DateTimeAxisLabel.SecondsIntervalStringFormatProperty, "{0:m:ss}")); DateTimeAxis timeAxis = new DateTimeAxis() { //Title = "Time", Minimum = baseTime, Maximum = baseTime + TimeSpan.FromSeconds(calculationOptions.FightDuration), IntervalType = DateTimeIntervalType.Seconds, AxisLabelStyle = dateTimeAxisLabelStyle, Orientation = AxisOrientation.X, ShowGridLines = true, Location = AxisLocation.Top, }; Style hiddenCategoryLabelStyle = new Style(typeof(AxisLabel)); hiddenCategoryLabelStyle.Setters.Add(new Setter(NumericAxisLabel.VisibilityProperty, Visibility.Collapsed)); CategoryAxis categoryAxis = new CategoryAxis() { AxisLabelStyle = hiddenCategoryLabelStyle, Orientation = AxisOrientation.Y, MajorTickMarkStyle = null, }; int barCount = 0; for (int cooldown = 0; cooldown < cooldownList.Count; cooldown++) { List<TimeIntervalData> data = new List<TimeIntervalData>(); //blendSubPoint = new System.Drawing.Drawing2D.ColorBlend(3); //blendSubPoint.Colors = new Color[] { colorSubPointsA[cooldown], colorSubPointsB[cooldown], colorSubPointsA[cooldown] }; //blendSubPoint.Positions = new float[] { 0f, 0.5f, 1f }; bool on = false; float timeOn = 0.0f; time = 0; for (int i = 0; i < sequence.Count; i++) { float duration = (float)sequence[i].Duration; if (sequence[i].IsManaPotionOrGem) duration = 0; if (on && !sequence[i].CastingState.EffectsActive(cooldownList[cooldown]) && !sequence[i].IsManaPotionOrGem) { on = false; if (time > timeOn) { data.Add(new TimeIntervalData() { Start = baseTime + TimeSpan.FromSeconds(timeOn), End = baseTime + TimeSpan.FromSeconds(time), Category = cooldownList[cooldown].Name }); } } else if (!on && sequence[i].CastingState.EffectsActive(cooldownList[cooldown])) { on = true; timeOn = time; } time += duration; } if (on) { if (time - timeOn > 0) { data.Add(new TimeIntervalData() { Start = baseTime + TimeSpan.FromSeconds(timeOn), End = baseTime + TimeSpan.FromSeconds(time), Category = cooldownList[cooldown].Name }); } } if (data.Count > 0) { barCount++; Style timeIntervalStyle = new Style(typeof(TimeIntervalDataPoint)); timeIntervalStyle.Setters.Add(new Setter(TimeIntervalDataPoint.BackgroundProperty, new SolidColorBrush(cooldownList[cooldown].Color))); Chart.Series.Add(new TimeIntervalSeries() { Title = cooldownList[cooldown].Name, ItemsSource = data, IndependentValuePath = "Category", DependentValuePath = "End", StartTimePath = "Start", EndTimePath = "End", DataPointStyle = timeIntervalStyle, DependentRangeAxis = timeAxis, IndependentAxis = categoryAxis }); } } if (calculationOptions.DisplaySegmentCooldowns && calculationOptions.BossHandler) { foreach (var buffState in calculationOptions.Character.BossOptions.BuffStates) { if (buffState.Chance > 0 && buffState.Stats.BonusDamageMultiplier > 0) { List<TimeIntervalData> data = new List<TimeIntervalData>(); foreach (var phase in buffState.PhaseTimes) { data.Add(new TimeIntervalData() { Start = baseTime + TimeSpan.FromSeconds(phase.Value[0]), End = baseTime + TimeSpan.FromSeconds(phase.Value[1]), Category = buffState.Name }); } if (data.Count > 0) { barCount++; Style timeIntervalStyle = new Style(typeof(TimeIntervalDataPoint)); timeIntervalStyle.Setters.Add(new Setter(TimeIntervalDataPoint.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 0, 0, 0)))); Chart.Series.Add(new TimeIntervalSeries() { Title = buffState.Name, ItemsSource = data, IndependentValuePath = "Category", DependentValuePath = "End", StartTimePath = "Start", EndTimePath = "End", DataPointStyle = timeIntervalStyle, DependentRangeAxis = timeAxis, IndependentAxis = categoryAxis }); } } } } Style hiddenNumericLabelStyle = new Style(typeof(NumericAxisLabel)); hiddenNumericLabelStyle.Setters.Add(new Setter(NumericAxisLabel.VisibilityProperty, Visibility.Collapsed)); Chart.Series.Add(new AreaSeries() { Title = "Mana", ItemsSource = manaList, IndependentValuePath = "Time", DependentValuePath = "Value", DataPointStyle = (Style)Resources["ManaStyle"], Background = new SolidColorBrush(Color.FromArgb(0xFF, 0x00, 0xFF, 0xFF)), DependentRangeAxis = new OffsetLinearAxis() { Minimum = 0, Offset = barCount * 10.0, Orientation = AxisOrientation.Y, AxisLabelStyle = hiddenNumericLabelStyle, MajorTickMarkStyle = null, MinorTickMarkStyle = null, }, IndependentAxis = timeAxis, LegendItemStyle = null, }); maxDps *= 1.1f; List<TimeData> list = new List<TimeData>(); time = 0.0f; for (int i = 0; i < sequence.Count; i++) { int index = sequence[i].Index; VariableType type = sequence[i].VariableType; float duration = (float)sequence[i].Duration; Cycle cycle = sequence[i].Cycle; CastingState state = sequence[i].CastingState; float mps = (float)sequence[i].Mps; if (sequence[i].IsManaPotionOrGem) duration = 0; float dps = 0; if (cycle != null) { dps = (float)cycle.DamagePerSecond; } if (duration > 0) { if (calculations.ManaAdeptBonus > 0) { for (int t = 1; t < 10; t++) { DateTime timet = baseTime + TimeSpan.FromSeconds(time + 0.1f * t * duration); if (cycle != null) { dps = (float)cycle.GetDamagePerSecond(calculations.ManaAdeptBonus, GetManaAtTime(manaList, timet) / maxMana); } // apply state multipliers if (calculationOptions.DisplaySegmentCooldowns) { dps *= calculationOptions.GetDamageMultiplier(time, time + duration); } list.Add(new TimeData() { Time = timet, Value = dps }); } } else { // apply state multipliers if (calculationOptions.DisplaySegmentCooldowns) { dps *= calculationOptions.GetDamageMultiplier(time, time + duration); } list.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time + 0.1f * duration), Value = dps }); list.Add(new TimeData() { Time = baseTime + TimeSpan.FromSeconds(time + 0.9f * duration), Value = dps }); } } time += duration; } Chart.Series.Add(new LineSeries() { Title = "Dps", ItemsSource = list, IndependentValuePath = "Time", DependentValuePath = "Value", DataPointStyle = (Style)Resources["DpsStyle"], DependentRangeAxis = new OffsetLinearAxis() { Offset = barCount * 10.0, Minimum = 0, Orientation = AxisOrientation.Y, AxisLabelStyle = hiddenNumericLabelStyle, MajorTickMarkStyle = null, MinorTickMarkStyle = null, }, IndependentAxis = timeAxis, }); if (zeroLineCanvas == null) { zeroLineCanvas = new ZeroLineCanvas(categoryAxis); zeroLineCanvas.BarCount = barCount; } else { zeroLineCanvas.BarCount = barCount; zeroLineCanvas.Axis = categoryAxis; } ISeriesHost host = (ISeriesHost)Chart; if (!host.BackgroundElements.Contains(zeroLineCanvas)) { host.BackgroundElements.Add(zeroLineCanvas); } } }