Пример #1
0
        protected override void CheckForResult(bool userTriggered, double timeOffset)
        {
            if (userTriggered || Time.Current < slider.EndTime)
            {
                return;
            }

            ApplyResult(r =>
            {
                var judgementsCount = NestedHitObjects.Count();
                var judgementsHit   = NestedHitObjects.Count(h => h.IsHit);

                var hitFraction = (double)judgementsHit / judgementsCount;

                if (hitFraction == 1 && HeadCircle.Result.Type == HitResult.Great)
                {
                    r.Type = HitResult.Great;
                }
                else if (hitFraction >= 0.5 && HeadCircle.Result.Type >= HitResult.Good)
                {
                    r.Type = HitResult.Good;
                }
                else if (hitFraction > 0)
                {
                    r.Type = HitResult.Meh;
                }
                else
                {
                    r.Type = HitResult.Miss;
                }
            });
        }
Пример #2
0
        protected override void CheckForJudgements(bool userTriggered, double timeOffset)
        {
            if (!userTriggered && Time.Current >= slider.EndTime)
            {
                var judgementsCount = NestedHitObjects.Count;
                var judgementsHit   = NestedHitObjects.Count(h => h.IsHit);

                var hitFraction = (double)judgementsHit / judgementsCount;
                if (hitFraction == 1 && HeadCircle.Judgements.Any(j => j.Result == HitResult.Great))
                {
                    AddJudgement(new OsuJudgement {
                        Result = HitResult.Great
                    });
                }
                else if (hitFraction >= 0.5 && HeadCircle.Judgements.Any(j => j.Result >= HitResult.Good))
                {
                    AddJudgement(new OsuJudgement {
                        Result = HitResult.Good
                    });
                }
                else if (hitFraction > 0)
                {
                    AddJudgement(new OsuJudgement {
                        Result = HitResult.Meh
                    });
                }
                else
                {
                    AddJudgement(new OsuJudgement {
                        Result = HitResult.Miss
                    });
                }
            }
        }
Пример #3
0
        protected override void CheckForJudgements(bool userTriggered, double timeOffset)
        {
            if (userTriggered)
            {
                return;
            }

            if (timeOffset < 0)
            {
                return;
            }

            int countHit = NestedHitObjects.Count(o => o.AllJudged);

            if (countHit > HitObject.RequiredGoodHits)
            {
                AddJudgement(new TaikoJudgement {
                    Result = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good
                });
                if (HitObject.IsStrong)
                {
                    AddJudgement(new TaikoStrongHitJudgement());
                }
            }
            else
            {
                AddJudgement(new TaikoJudgement {
                    Result = HitResult.Miss
                });
            }
        }
Пример #4
0
        protected override void LoadAsyncComplete()
        {
            base.LoadAsyncComplete();

            var nestedStrongHit = (DrawableStrongNestedHit)NestedHitObjects.Single();

            nestedStrongHit.Result.Type = hitBoth ? Type : HitResult.Miss;
        }
Пример #5
0
 protected override void CheckForResult(bool userTriggered, double timeOffset)
 {
     // We also make sure all transforms have finished to avoid jank
     if (NestedHitObjects.All(n => n.Result.HasResult && Time.Current >= n.LatestTransformEndTime))
     {
         ApplyResult(Result.Judgement.MaxResult);
     }
 }
Пример #6
0
 protected override void CheckForJudgements(bool userTriggered, double timeOffset)
 {
     if (timeOffset >= 0)
     {
         AddJudgement(new Judgement {
             Result = NestedHitObjects.Cast <DrawableCatchHitObject>().Any(n => n.Judgements.Any(j => j.IsHit)) ? HitResult.Perfect : HitResult.Miss
         });
     }
 }
Пример #7
0
        protected override void CheckForResult(bool userTriggered, double timeOffset)
        {
            if (userTriggered || Time.Current < HitObject.EndTime)
            {
                return;
            }

            ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
        }
        protected override void CheckForResult(bool userTriggered, double timeOffset)
        {
            if (userTriggered)
                return;

            if (timeOffset < 0)
                return;

            int countHit = NestedHitObjects.Count(o => o.IsHit);
            if (countHit >= HitObject.RequiredGoodHits)
                ApplyResult(r => r.Type = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good);
            else
                ApplyResult(r => r.Type = HitResult.Miss);
        }
Пример #9
0
        protected override void CheckForResult(bool userTriggered, double timeOffset)
        {
            if (userTriggered)
            {
                return;
            }

            if (timeOffset < 0)
            {
                return;
            }

            int countHit = NestedHitObjects.Count(o => o.IsHit);

            if (countHit >= HitObject.RequiredGoodHits)
            {
                ApplyResult(r => r.Type = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Ok);
            }
            else
            {
                ApplyResult(r => r.Type = r.Judgement.MinResult);
            }
        }
Пример #10
0
        protected override void CheckJudgement(bool userTriggered)
        {
            if (userTriggered)
            {
                return;
            }

            if (Judgement.TimeOffset < 0)
            {
                return;
            }

            int countHit = NestedHitObjects.Count(o => o.Judgement.Result == HitResult.Hit);

            if (countHit > HitObject.RequiredGoodHits)
            {
                Judgement.Result      = HitResult.Hit;
                Judgement.TaikoResult = countHit >= HitObject.RequiredGreatHits ? TaikoHitResult.Great : TaikoHitResult.Good;
            }
            else
            {
                Judgement.Result = HitResult.Miss;
            }
        }
Пример #11
0
        protected override void CheckForResult(bool userTriggered, double timeOffset)
        {
            if (userTriggered || Time.Current < HitObject.EndTime)
            {
                return;
            }

            // If only the nested hitobjects are judged, then the slider's own judgement is ignored for scoring purposes.
            // But the slider needs to still be judged with a reasonable hit/miss result for visual purposes (hit/miss transforms, etc).
            if (HitObject.OnlyJudgeNestedObjects)
            {
                ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
                return;
            }

            // Otherwise, if this slider also needs to be judged, apply judgement proportionally to the number of nested hitobjects hit. This is the classic osu!stable scoring.
            ApplyResult(r =>
            {
                int totalTicks = NestedHitObjects.Count;
                int hitTicks   = NestedHitObjects.Count(h => h.IsHit);

                if (hitTicks == totalTicks)
                {
                    r.Type = HitResult.Great;
                }
                else if (hitTicks == 0)
                {
                    r.Type = HitResult.Miss;
                }
                else
                {
                    double hitFraction = (double)hitTicks / totalTicks;
                    r.Type             = hitFraction >= 0.5 ? HitResult.Ok : HitResult.Meh;
                }
            });
        }
Пример #12
0
        private void createTicks()
        {
            if (TickDistance == 0)
            {
                return;
            }

            var length       = Curve.Distance;
            var tickDistance = Math.Min(TickDistance, length);
            var spanDuration = length / Velocity;

            var minDistanceFromEnd = Velocity * 0.01;

            AddNested(new Fruit
            {
                Samples   = Samples,
                StartTime = StartTime,
                X         = X
            });

            double lastDropletTime = StartTime;

            for (int span = 0; span < this.SpanCount(); span++)
            {
                var spanStartTime = StartTime + span * spanDuration;
                var reversed      = span % 2 == 1;

                for (double d = 0; d <= length; d += tickDistance)
                {
                    var timeProgress     = d / length;
                    var distanceProgress = reversed ? 1 - timeProgress : timeProgress;

                    double time = spanStartTime + timeProgress * spanDuration;

                    double tinyTickInterval = time - lastDropletTime;
                    while (tinyTickInterval > 100)
                    {
                        tinyTickInterval /= 2;
                    }

                    for (double t = lastDropletTime + tinyTickInterval; t < time; t += tinyTickInterval)
                    {
                        double progress = reversed ? 1 - (t - spanStartTime) / spanDuration : (t - spanStartTime) / spanDuration;

                        AddNested(new TinyDroplet
                        {
                            StartTime = t,
                            X         = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
                            Samples   = new List <SampleInfo>(Samples.Select(s => new SampleInfo
                            {
                                Bank   = s.Bank,
                                Name   = @"slidertick",
                                Volume = s.Volume
                            }))
                        });
                    }

                    if (d > minDistanceFromEnd && Math.Abs(d - length) > minDistanceFromEnd)
                    {
                        AddNested(new Droplet
                        {
                            StartTime = time,
                            X         = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
                            Samples   = new List <SampleInfo>(Samples.Select(s => new SampleInfo
                            {
                                Bank   = s.Bank,
                                Name   = @"slidertick",
                                Volume = s.Volume
                            }))
                        });
                    }

                    lastDropletTime = time;
                }

                AddNested(new Fruit
                {
                    Samples   = Samples,
                    StartTime = spanStartTime + spanDuration,
                    X         = X + Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH
                });
            }

            if (NestedHitObjects.LastOrDefault() is IHasComboInformation lastNested)
            {
                lastNested.LastInCombo = LastInCombo;
            }
        }