/// <summary> Returns an issue if this time is very close behind to a timing line which would modify objects. </summary> private IEnumerable <Issue> GetIssue(string type, double time, Beatmap beatmap) { double unsnap = beatmap.GetPracticalUnsnap(time); TimingLine curLine = beatmap.GetTimingLine(time); TimingLine nextLine = curLine.Next(skipConcurrent: true); if (nextLine != null) { double curEffectiveBPM = curLine.svMult * beatmap.GetTimingLine <UninheritedLine>(time).bpm; double nextEffectiveBPM = nextLine.svMult * beatmap.GetTimingLine <UninheritedLine>(nextLine.offset).bpm; double deltaEffectiveBPM = curEffectiveBPM - nextEffectiveBPM; double timeDiff = nextLine.offset - time; if (timeDiff > 0 && timeDiff <= 5 && Math.Abs(unsnap) <= 1 && Math.Abs(deltaEffectiveBPM) > 1) { yield return(new Issue(GetTemplate("Before"), beatmap, Timestamp.Get(time), type, $"{timeDiff:0.##}")); } if (beatmap.generalSettings.mode == Beatmap.Mode.Taiko && timeDiff < 0 && timeDiff >= -5 && Math.Abs(unsnap) <= 1 && Math.Abs(deltaEffectiveBPM) > 1) { yield return(new Issue(GetTemplate("After"), beatmap, Timestamp.Get(time), type, $"{timeDiff:0.##}")); } } }
/// <summary> Returns whether this section contains the respective hit object type. /// Only counts the start of objects. </summary> private bool SectionContainsObject <T>(Beatmap beatmap, TimingLine line) where T : HitObject { TimingLine nextLine = line.Next(skipConcurrent: true); double nextSectionEnd = nextLine?.offset ?? beatmap.GetPlayTime(); double objectTimeBeforeEnd = beatmap.GetPrevHitObject <T>(nextSectionEnd)?.time ?? 0; return(objectTimeBeforeEnd >= line.offset); }
/// <summary> Returns an issue if this time is very close behind to a timing line which would modify objects. </summary> private IEnumerable <Issue> GetIssue(string type, double time, Beatmap beatmap) { double unsnap = beatmap.GetPracticalUnsnap(time); TimingLine curLine = beatmap.GetTimingLine(time); TimingLine nextLine = curLine.Next(skipConcurrent: true); if (nextLine == null) { yield break; } double curEffectiveBPM = curLine.svMult * beatmap.GetTimingLine <UninheritedLine>(time).bpm; double nextEffectiveBPM = nextLine.svMult * beatmap.GetTimingLine <UninheritedLine>(nextLine.offset).bpm; double deltaEffectiveBPM = curEffectiveBPM - nextEffectiveBPM; double timeDiff = nextLine.offset - time; if (timeDiff > 0 && timeDiff <= 5 && Math.Abs(unsnap) <= 1 && Math.Abs(deltaEffectiveBPM) > 1) { yield return(new Issue(GetTemplate("Before"), beatmap, Timestamp.Get(time), type, $"{timeDiff:0.##}")); } // Modes where SV affects AR would be impacted even if the object was right after the line. if (IsSVAffectingAR(beatmap) && timeDiff < 0 && timeDiff >= -5 && Math.Abs(unsnap) <= 1 && Math.Abs(deltaEffectiveBPM) > 1) { yield return(new Issue(GetTemplate("After"), beatmap, Timestamp.Get(time), type, $"{timeDiff:0.##}")); } }