コード例 #1
0
        public AiReportOneObject(HitObjectBase h, int time, BeenCorrectedDelegate corrected, Severity severity, string information, int weblink)
            : base(time, severity, information, weblink, corrected)
        {
            this.h1 = h;

            RelatedHitObjects.Add(h);
        }
コード例 #2
0
        public AiReportTwoObjects(HitObjectBase h1, HitObjectBase h2, BeenCorrectedDelegate corrected, Severity severity, string information, int weblink)
            : base((h1.EndTime - h2.StartTime) / 2 + h2.StartTime, severity, information, weblink, corrected)
        {
            this.h1 = h1;
            this.h2 = h2;

            RelatedHitObjects.Add(h1);
            RelatedHitObjects.Add(h2);
        }
コード例 #3
0
ファイル: AICompose.cs プロジェクト: notperry1234567890/osu
        private static float getSpacingFactor(HitObjectBase h1, HitObjectBase h2, HitObjectManagerBase hitObjectManager)
        {
            int   lastSelectedTime = h1.EndTime;
            int   nextSelectedTime = h2.StartTime;
            int   time             = nextSelectedTime - lastSelectedTime;
            float mul = (float)hitObjectManager.SliderVelocityAt(nextSelectedTime);

            return(1000.0f * (h2.Position - h1.EndPosition).Length() / (mul * time));
        }
コード例 #4
0
ファイル: AICompose.cs プロジェクト: notperry1234567890/osu
        protected virtual void checkDistanceSpacing(HitObjectBase h, HitObjectBase h2, HitObjectManagerBase hitObjectManager)
        {
            //check combo distance
            if (!CheckDistanceSnap)
            {
                return;
            }

            if (h2 == null || h2.NewCombo || h2 is Spinner)
            {
                return;
            }

            float thisSpacingFactor = getSpacingFactor(h, h2, hitObjectManager);

            //If the current hitobject is a new combo, get a new distance factor from the current and next object.
            if (h.NewCombo || comboSpacingFactor < MIN_SPACING_FACTOR)
            {
                comboSpacingFactor  = thisSpacingFactor;
                comboSpacingObject1 = h;
                comboSpacingObject2 = h2;

                return;
            }

            if (comboSpacingFactor > MIN_SPACING_FACTOR &&
                thisSpacingFactor > MIN_SPACING_FACTOR &&
                (thisSpacingFactor - comboSpacingFactor > comboSpacingFactor * 0.1 * spacingFactor ||
                 comboSpacingFactor - thisSpacingFactor > comboSpacingFactor * 0.2 * spacingFactor))
            {
                HitObjectBase object1 = comboSpacingObject1;
                HitObjectBase object2 = comboSpacingObject2;

                AiReportTwoObjects report = new AiReportTwoObjects(
                    h,
                    h2,
                    delegate { return(Math.Abs(getSpacingFactor(h, h2, hitObjectManager) - getSpacingFactor(object1, object2, hitObjectManager)) < ERROR_FACTOR); },
                    Severity.Warning,
                    thisSpacingFactor < comboSpacingFactor ? LocalisationManager.GetString(OsuString.AICompose_ObjectTooClose) : LocalisationManager.GetString(OsuString.AICompose_ObjectTooFar), 82809);
                Reports.Add(report);
            }
        }
コード例 #5
0
ファイル: AICompose.cs プロジェクト: notperry1234567890/osu
        protected virtual void runSanityRules()
        {
            List <HitObjectBase> hitObjects = hitObjectManager.GetHitObjects();

            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 for hitobjects which share the same startTime...
                if (i > 0 && !isLast)
                {
                    if (hitObjects[i].StartTime != hitObjects[i + 1].StartTime && hitObjects[i].StartTime < hitObjects[i - 1].EndTime + 10)
                    {
                        HitObjectBase last = hitObjects[i - 1];
                        Reports.Add(new AiReportTwoObjects(last, h, delegate { return(Math.Abs(last.StartTime - h.StartTime) > 10); }, Severity.Error, LocalisationManager.GetString(OsuString.AICompose_ObjectsTooClose), -1));
                    }
                }

                //check snap
                if (AiMod.TestBeatSnap(h.StartTime, true))
                {
                    int      index  = i;
                    AiReport report = new AiReportOneObject(h, h.StartTime, delegate { return(AiMod.TestBeatSnap(h.StartTime, true)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_UnsnappedObject), 0);
                    Reports.Add(report);
                }

                if (h.EndTime != h.StartTime)
                {
                    if (AiMod.TestBeatSnap(h.EndTime, true)) //Need to account for slider velocity buffer.
                    {
                        int      index  = i;
                        AiReport report = new AiReportOneObject(h, h.EndTime, delegate { return(AiMod.TestBeatSnap(h.EndTime, true)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_UnsnappedObjectEnd), 0);
                        Reports.Add(report);
                    }
                }
            }
        }
コード例 #6
0
 /// <summary>
 /// Naive matching of cloned HitObjectBase to HitObject
 /// </summary>
 private HitObject matchObject(HitObjectBase match)
 {
     return(editor.hitObjectManager.hitObjects.Find(h => h.StartTime == match.StartTime));
 }
コード例 #7
0
        protected override void runComposeRules()
        {
            HitObjectManager     hom        = hitObjectManager as HitObjectManager;
            List <HitObjectBase> hitObjects = hitObjectManager.GetHitObjects();

            int column = (int)Math.Round(BeatmapManager.Current.DifficultyCircleSize);
            List <Dictionary <int, int> > columns = new List <Dictionary <int, int> >(column);

            int[] pressArr         = new int[column];
            int[] lastNoteInColumn = new int[column]; // used to check distance between notes on the same column
            for (int i = 0; i < column; i++)
            {
                columns.Add(new Dictionary <int, int>());
            }

            for (int i = 0; i < hitObjects.Count; i++)
            {
                HitObjectBase h   = hitObjects[i];
                int           col = hom.ManiaStage.ColumnAt(h.Position);

                //check snap
                if (AiMod.TestBeatSnap(h.StartTime, false))
                {
                    AiReport report = new AiReportOneObject(h, h.StartTime, delegate { return(AiMod.TestBeatSnap(h.StartTime, false)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_UnsnappedObject), 0);
                    Reports.Add(report);
                }

                if (h.IsType(HitObjectType.Hold))
                {
                    if (h.EndTime - h.StartTime < 10)
                    {
                        Reports.Add(new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AIComposeMania_HoldNoteTooShort), 0));
                    }

                    if (AiMod.TestBeatSnap(h.EndTime, false))
                    {
                        AiReport report = new AiReportOneObject(h, h.EndTime, delegate { return(AiMod.TestBeatSnap(h.EndTime, false)); }, Severity.Warning, LocalisationManager.GetString(OsuString.AICompose_UnsnappedObjectEnd), 0);
                        Reports.Add(report);
                    }
                }

                if (h.StartTime != lastNoteInColumn[col] && lastNoteInColumn[col] != 0 && h.StartTime < lastNoteInColumn[col] + 10)
                {
                    Reports.Add(new AiReportOneObject(h, h.StartTime, delegate { return(Math.Abs(lastNoteInColumn[col] - h.StartTime) > 10); }, Severity.Error, LocalisationManager.GetString(OsuString.AICompose_ObjectsTooClose), -1));
                }

                //check for 7 notes simultaneously
                int existCount = 1;
                for (int j = 0; j < column; j++)
                {
                    if (pressArr[j] >= h.StartTime)
                    {
                        existCount++;
                    }
                }
                //pressArr[col] = h.EndTime;
                if (h.StartTime == h.EndTime)
                {
                    pressArr[col] = h.StartTime;
                }
                else
                {
                    pressArr[col] = h.EndTime - 2;//hack, holds' end are not counted here.
                }
                if (existCount >= 7)
                {
                    AiReportOneObject report = new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AIComposeMania_TooManyNotes), 0);
                    Reports.Add(report);
                }
                //note stack on another note's startTime
                if (columns[col].ContainsKey(h.StartTime) || columns[col].ContainsKey(h.EndTime))
                {
                    AiReportOneObject report = new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AIComposeMania_StackedObjects), 0);
                    Reports.Add(report);
                    continue;
                }
                bool needReport = false;
                foreach (KeyValuePair <int, int> pair in columns[col])
                {
                    //normal note, already checked above
                    if (pair.Key == pair.Value)
                    {
                        continue;
                    }
                    if (h.StartTime <= pair.Key && h.EndTime >= pair.Key)
                    {
                        needReport = true;
                        break;
                    }
                    if (h.StartTime <= pair.Value && h.EndTime >= pair.Value)
                    {
                        needReport = true;
                        break;
                    }
                    if (h.StartTime >= pair.Key && h.EndTime <= pair.Value)
                    {
                        needReport = true;
                        break;
                    }
                    if (h.StartTime < pair.Key && h.EndTime > pair.Value)
                    {
                        needReport = true;
                        break;
                    }
                }
                if (needReport)
                {
                    AiReportOneObject report = new AiReportOneObject(h, h.StartTime, null, Severity.Error, LocalisationManager.GetString(OsuString.AIComposeMania_OverlappingObject), 0);
                    Reports.Add(report);
                    continue;
                }
                else
                {
                    columns[col][h.StartTime] = h.EndTime;
                }

                // we don't want to mark this note as the previous note in the column until it's been processed
                lastNoteInColumn[col] = h.StartTime;
            }
        }
コード例 #8
0
 public AiReportDifficultyTwoObjects(BeatmapDifficulty difficulty, string condition, HitObjectBase h1, HitObjectBase h2)
     : base(h1, h2, null, Severity.Info, difficulty + " criteria: " + condition, 0)
 {
 }
コード例 #9
0
        public tpHitObject(HitObjectBase BaseHitObject, float CircleRadius)
        {
            this.BaseHitObject = BaseHitObject;

            // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
            float ScalingFactor = (52.0f / CircleRadius);

            NormalizedStartPosition = BaseHitObject.Position * ScalingFactor;


            // Calculate approximation of lazy movement on the slider
            if ((BaseHitObject.Type & HitObjectType.Slider) > 0)
            {
                float SliderFollowCircleRadius = CircleRadius * 3; // Not sure if this is correct, but here we do not need 100% exact values. This comes pretty darn close in my tests.

                int SegmentLength  = BaseHitObject.Length / BaseHitObject.SegmentCount;
                int SegmentEndTime = BaseHitObject.StartTime + SegmentLength;

                // For simplifying this step we use actual osu! coordinates and simply scale the length, that we obtain by the ScalingFactor later
                Vector2 CursorPos = BaseHitObject.Position; //

                // Actual computation of the first lazy curve
                for (int Time = BaseHitObject.StartTime + LAZY_SLIDER_STEP_LENGTH; Time < SegmentEndTime; Time += LAZY_SLIDER_STEP_LENGTH)
                {
                    Vector2 Difference = BaseHitObject.PositionAtTime(Time) - CursorPos;
                    float   Distance   = Difference.Length();

                    // Did we move away too far?
                    if (Distance > SliderFollowCircleRadius)
                    {
                        // Yep, we need to move the cursor
                        Difference.Normalize();                         // Obtain the direction of difference. We do no longer need the actual difference
                        Distance              -= SliderFollowCircleRadius;
                        CursorPos             += Difference * Distance; // We move the cursor just as far as needed to stay in the follow circle
                        LazySliderLengthFirst += Distance;
                    }
                }

                LazySliderLengthFirst *= ScalingFactor;
                // If we have an odd amount of repetitions the current position will be the end of the slider. Note that this will -always- be triggered if
                // BaseHitObject.SegmentCount <= 1, because BaseHitObject.SegmentCount can not be smaller than 1. Therefore NormalizedEndPosition will always be initialized
                if (BaseHitObject.SegmentCount % 2 == 1)
                {
                    NormalizedEndPosition = CursorPos * ScalingFactor;
                }

                // If we have more than one segment, then we also need to compute the length ob subsequent lazy curves. They are different from the first one, since the first
                // one starts right at the beginning of the slider.
                if (BaseHitObject.SegmentCount > 1)
                {
                    // Use the next segment
                    SegmentEndTime += SegmentLength;

                    for (int Time = SegmentEndTime - SegmentLength + LAZY_SLIDER_STEP_LENGTH; Time < SegmentEndTime; Time += LAZY_SLIDER_STEP_LENGTH)
                    {
                        Vector2 Difference = BaseHitObject.PositionAtTime(Time) - CursorPos;
                        float   Distance   = Difference.Length();

                        // Did we move away too far?
                        if (Distance > SliderFollowCircleRadius)
                        {
                            // Yep, we need to move the cursor
                            Difference.Normalize();             // Obtain the direction of difference. We do no longer need the actual difference
                            Distance  -= SliderFollowCircleRadius;
                            CursorPos += Difference * Distance; // We move the cursor just as far as needed to stay in the follow circle
                            LazySliderLengthSubsequent += Distance;
                        }
                    }

                    LazySliderLengthSubsequent *= ScalingFactor;
                    // If we have an even amount of repetitions the current position will be the end of the slider
                    if (BaseHitObject.SegmentCount % 2 == 1)
                    {
                        NormalizedEndPosition = CursorPos * ScalingFactor;
                    }
                }
            }
            // We have a normal HitCircle or a spinner
            else
            {
                NormalizedEndPosition = BaseHitObject.EndPosition * ScalingFactor;
            }
        }
コード例 #10
0
ファイル: AICompose.cs プロジェクト: notperry1234567890/osu
        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);
            }
        }
コード例 #11
0
 public AiReportDifficultyOneObject(BeatmapDifficulty difficulty, string condition, HitObjectBase h1)
     : base(h1, h1.StartTime, null, Severity.Info, difficulty + " criteria: " + condition, 0)
 {
 }