Ejemplo n.º 1
0
        protected virtual void runComposeRules()
        {
            circleRadius = (float)(512 / 8f * (1f - 0.7f * hitObjectManager.AdjustDifficulty(BeatmapManager.Current.DifficultyCircleSize)) / 2f) - 1;

            runSanityRules();

            List <HitObjectBase> hitObjects = hitObjectManager.GetHitObjects();

            bool   lastWasSpinner    = false;
            double slowestBeatlength = 0;

            for (int i = 0; i < hitObjects.Count; i++)
            {
                bool          isLast = i == hitObjects.Count - 1;
                HitObjectBase h      = hitObjects[i];
                HitObjectBase h1     = isLast ? null : hitObjects[i + 1];

                //check offscreen
                if (testOffScreen(h.Position))
                {
                    Reports.Add(new AiReportOneObject(h, h.StartTime, delegate { return(testOffScreen(h.Position)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_ObjectOffscreen), 0));
                }

                if (h.EndPosition != h.Position && testOffScreen(h.EndPosition))
                {
                    Reports.Add(new AiReportOneObject(h, h.EndTime, delegate { return(testOffScreen(h.EndPosition)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_ObjectEndOffscreen), 0));
                }

                //Check for combos over 24
                if (h.ComboNumber > 24)
                {
                    Reports.Add(new AiReportOneObject(h, h.EndTime, delegate { return(h.ComboNumber <= 24); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_LongCombo), -1));
                }

                if (i > 0 && !isLast)
                {
                    if (hitObjects[i].StartTime == hitObjects[i + 1].StartTime)
                    {
                        HitObjectBase last = hitObjects[i - 1];
                        Reports.Add(new AiReportTwoObjects(last, h, delegate { return(last.StartTime != h.StartTime); }, Severity.Error, LocalisationManager.GetString(OsuString.AICompose_SimultaneousObjects), -1));
                    }
                }

                if (lastWasSpinner && !(h is Spinner))
                {
                    Spinner spinner = (Spinner)hitObjects[i - 1];
                    if (spinner.StartTime > h.StartTime - hitObjectManager.PreEmpt + HitObjectManager.FadeIn)
                    {
                        Reports.Add(new AiReportTwoObjects(spinner, h, delegate() { return(spinner.StartTime <= h.StartTime - hitObjectManager.PreEmpt + HitObjectManager.FadeIn); }, Severity.Error, LocalisationManager.GetString(OsuString.AICompose_NinjaSpinner), -1));
                    }
                }

                lastWasSpinner = (h is Spinner);

                if (h is SliderOsu)
                {
                    // curve stuff is only defined for osu!mode, but happily enough, the editor is always in osu!mode.
                    SliderOsu s2 = h as SliderOsu;
                    if (s2.IsRetarded())
                    {
                        Reports.Add(new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AICompose_AbnormalSlider), -1));
                    }

                    // if the mapper sets a broken tick rate but never has long enough sliders to notice it, don't warn
                    if (s2.EndTime - 1000 > s2.StartTime)
                    {
                        slowestBeatlength = Math.Max(slowestBeatlength, AudioEngine.BeatLengthAt(s2.StartTime));
                    }
                }

                //spinner length
                if (h.IsType(HitObjectType.Spinner))
                {
                    if (!h.IsType(HitObjectType.NewCombo))
                    {
                        Reports.Add(new AiReportOneObject(h, h.StartTime, null, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_SpinnerNoNewCombo), -1));
                    }

                    //look at SpinnerOsu.cs for these numbers.
                    double autoCanSpin = 0.05 * (double)(h.EndTime - h.StartTime) / Math.PI;
                    double require     = ((double)(h.EndTime - h.StartTime) / 1000 * hitObjectManager.SpinnerRotationRatio);
                    if (autoCanSpin - require < 5)
                    {
                        Reports.Add(new AiReportOneObject(h, h.StartTime, null, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_ShortSpinner), -1));
                    }
                }

                checkDistanceSpacing(h, h1, hitObjectManager);
            }
        }
Ejemplo n.º 2
0
        protected virtual void runTimingRules()
        {
            List <HitObjectBase> hitObjects = hitObjectManager.GetHitObjects();

            int mapEndTime  = 0;
            int drainLength = 0;

            if (hitObjects.Count > 0)
            {
                mapEndTime  = hitObjects[hitObjects.Count - 1].EndTime;
                drainLength = mapEndTime - hitObjects[0].StartTime;

                if (drainLength > 6 * 60 * 1000)
                {
                    Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_BeatmapTooLong), -1, null));
                }
                else if (drainLength < 45000)
                {
                    Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_BeatmapTooShort), -1, null));
                }
                if (drainLength * 1.0 / (AudioEngine.AudioLength - hitObjects[0].StartTime) < 0.8)
                {
                    Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_Mp3LongerThanMap), -1, null));
                }
            }

            List <ControlPoint> points = AudioEngine.ControlPoints;

            int          kiaiToggleCount   = 0;
            int          kiaiLength        = 0;
            List <float> SliderMultipliers = new List <float>();
            bool         kiaiOn            = false;
            double       lastKiaiEndTime   = 0;
            int          lowVolumeCount    = 0;
            int          stackedPointCount = 0;

            for (int i = 0; i < points.Count; i++)
            {
                ControlPoint p = points[i];

                //overlap
                int startOffset = (int)p.Offset;
                int endOffset   = i == points.Count - 1 ? mapEndTime : (int)points[i + 1].Offset;

                int timingLength = endOffset - startOffset;

                if (timingLength > 0)
                {
                    if (p.KiaiMode)
                    {
                        kiaiLength += timingLength;
                        if (i > 0 && !points[i - 1].KiaiMode)
                        {
                            kiaiToggleCount++;
                        }
                    }
                }

                //Check for duplicate control points
                if (i > 0 && startOffset == (int)points[i - 1].Offset)
                {
                    stackedPointCount++;
                    for (int z = 1; z <= stackedPointCount; z++)
                    {
                        if (p.TimingChange == points[i - z].TimingChange)
                        {
                            Reports.Add(new AiReport(startOffset, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_OverlappingTimingPoints), 0, null));
                            break;
                        }
                    }
                }
                else
                {
                    stackedPointCount = 0;
                }

                //snap
                if (p.KiaiMode && !kiaiOn)
                {
                    kiaiOn = true;
                    if (AiMod.TestBeatSnap(startOffset, false))
                    {
                        Reports.Add(new AiReport(startOffset, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_UnsnappedKiai), 0, null));
                    }
                    if (p.Offset - lastKiaiEndTime < 15000 && p.Offset - lastKiaiEndTime > 10)
                    {
                        Reports.Add(new AiReport(startOffset, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_KiaiTooShort), -1, null));
                    }
                }
                else if (!p.KiaiMode && kiaiOn)
                {
                    kiaiOn = false;
                    if (AiMod.TestBeatSnap(startOffset, false))
                    {
                        Reports.Add(new AiReport(startOffset, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_UnsnappedKiaiEnd), 0, null));
                    }
                    lastKiaiEndTime = p.Offset;
                }

                //volume
                if (p.Volume < 5)
                {
                    lowVolumeCount++;
                }
            }

            //zero volume
            if (lowVolumeCount == points.Count)
            {
                Reports.Add(new AiReport(Severity.Error, LocalisationManager.GetString(OsuString.AITiming_AllTimingSectionsQuiet)));
            }
            else if (lowVolumeCount > 0)
            {
                Reports.Add(new AiReport(Severity.Warning, string.Format(LocalisationManager.GetString(OsuString.AITiming_SomeTimingSectionsQuiet), lowVolumeCount, points.Count)));
            }

            //KIAI
            if (drainLength > 3 * 60 * 1000 && kiaiLength > drainLength / 3)
            {
                Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_TooMuchKiai), -1, null));
            }
            else if (drainLength < 90 * 1000 && kiaiLength > drainLength / 2)
            {
                Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_TooMuchKiaiTvSize), -1, null));
            }

            if (BeatmapManager.Current.PreviewTime < 0)
            {
                Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_NoPreviewPoint), -1, null));
            }
            if (kiaiOn)
            {
                Reports.Add(new AiReport(-1, Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_NoKiaiEnd), -1, null));
            }

            //audio quality
            TAG_INFO info = AudioEngine.GetAudioTagInfo();

            if (info != null)
            {
                if (info.bitrate < 128)
                {
                    Reports.Add(new AiReport(Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_LowAudioBitrate)));
                }
                else if (info.bitrate > 192)
                {
                    Reports.Add(new AiReport(Severity.Warning, LocalisationManager.GetString(OsuString.AITiming_HighAudioBitrate)));
                }
            }
        }