/// <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);
        }
示例#3
0
        /// <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.##}"));
            }
        }