public void BindProcessor(ScoreProcessor processor) { //bind processor bindables to combocounter, score display etc. processor.TotalScore.ValueChanged += delegate { ScoreCounter?.Set((ulong)processor.TotalScore.Value); }; processor.Accuracy.ValueChanged += delegate { AccuracyCounter?.Set((float)processor.Accuracy.Value); }; processor.Combo.ValueChanged += delegate { ComboCounter?.Set((ulong)processor.Combo.Value); }; processor.Health.ValueChanged += delegate { HealthDisplay?.Set(processor.Health.Value); }; }
public void BindProcessor(ScoreProcessor processor) { info.AccuracyDisplay.Current.BindTo(processor.Accuracy); info.GradeDisplay.Current.BindTo(processor.Rank); }
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { Applied = true; }
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { scoreProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); }; }
private void load(OsuColour colours, ScoreProcessor scoreProcessor) { Colour = colours.BlueLighter; Current.BindTo(scoreProcessor.Combo); }
private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuGameBase game, OsuConfigManager config) { dimLevel = config.GetBindable <int>(OsuConfig.DimLevel); try { if (Beatmap == null) { Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true); } if ((Beatmap?.Beatmap?.HitObjects.Count ?? 0) == 0) { throw new Exception("No valid objects were found!"); } } catch (Exception e) { Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error); //couldn't load, hard abort! Exit(); return; } Track track = Beatmap.Track; if (track != null) { audio.Track.SetExclusive(track); sourceClock = track; } sourceClock = (IAdjustableClock)track ?? new StopwatchClock(); Schedule(() => { sourceClock.Reset(); }); var beatmap = Beatmap.Beatmap; if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu) { //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. Exit(); return; } PlayMode usablePlayMode = beatmap.BeatmapInfo?.Mode > PlayMode.Osu ? beatmap.BeatmapInfo.Mode : PreferredPlayMode; ruleset = Ruleset.GetRuleset(usablePlayMode); scoreOverlay = ruleset.CreateScoreOverlay(); scoreOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor(beatmap.HitObjects.Count)); pauseOverlay = new PauseOverlay { Depth = -1, OnResume = delegate { Delay(400); Schedule(Resume); }, OnRetry = Restart, OnQuit = Exit }; hitRenderer = ruleset.CreateHitRendererWith(beatmap); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) hitRenderer.OnJudgement += scoreProcessor.AddJudgement; hitRenderer.OnAllJudged += onPass; //bind ScoreProcessor to ourselves (for a fail situation) scoreProcessor.Failed += onFail; if (Autoplay) { hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); } Children = new Drawable[] { playerInputManager = new PlayerInputManager(game.Host) { Clock = new InterpolatingFramedClock(sourceClock), PassThrough = false, Children = new Drawable[] { hitRenderer, skipButton = new SkipButton { Alpha = 0 }, } }, scoreOverlay, pauseOverlay }; }
public HUDOverlay(ScoreProcessor scoreProcessor, HealthProcessor healthProcessor, DrawableRuleset drawableRuleset, IReadOnlyList <Mod> mods) { this.scoreProcessor = scoreProcessor; this.healthProcessor = healthProcessor; this.drawableRuleset = drawableRuleset; this.mods = mods; RelativeSizeAxes = Axes.Both; Children = new Drawable[] { FailingLayer = CreateFailingLayer(), visibilityContainer = new Container { RelativeSizeAxes = Axes.Both, Child = new GridContainer { RelativeSizeAxes = Axes.Both, Content = new[] { new Drawable[] { mainUIElements = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { HealthDisplay = CreateHealthDisplay(), AccuracyCounter = CreateAccuracyCounter(), ScoreCounter = CreateScoreCounter(), ComboCounter = CreateComboCounter(), HitErrorDisplay = CreateHitErrorDisplayOverlay(), } }, }, new Drawable[] { Progress = CreateProgress(), } }, RowDimensions = new[] { new Dimension(), new Dimension(GridSizeMode.AutoSize) } }, }, topRightElements = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Margin = new MarginPadding(10), Spacing = new Vector2(10), AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Children = new Drawable[] { ModDisplay = CreateModsContainer(), PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), } }, bottomRightElements = new FillFlowContainer { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding(10), Spacing = new Vector2(10), AutoSizeAxes = Axes.Both, LayoutDuration = FADE_DURATION / 2, LayoutEasing = FADE_EASING, Direction = FillDirection.Vertical, Children = new Drawable[] { KeyCounter = CreateKeyCounter(), HoldToQuit = CreateHoldForMenuButton(), } } }; }
private void load(AudioManager audio, OsuConfigManager config, OsuGame game) { Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) { return; } IBeatmap playableBeatmap = loadPlayableBeatmap(); if (playableBeatmap == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); if (game != null) { LocalUserPlaying.BindTo(game.LocalUserPlaying); } DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime); AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); dependencies.CacheAs(gameplayBeatmap); var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation // full access to all skin sources. var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap)); // load the skinning hierarchy first. // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. GameplayClockContainer.Add(beatmapSkinProvider.WithChild(rulesetSkinProvider)); rulesetSkinProvider.AddRange(new[] { // underlay and gameplay should have access the to skinning sources. createUnderlayComponents(), createGameplayComponents(Beatmap.Value, playableBeatmap) }); // also give the HUD a ruleset container to allow rulesets to potentially override HUD elements (used to disable combo counters etc.) // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there. var hudRulesetContainer = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap)); // add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components. GameplayClockContainer.Add(hudRulesetContainer.WithChild(createOverlayComponents(Beatmap.Value))); if (!DrawableRuleset.AllowGameplayOverlays) { HUDOverlay.ShowHud.Value = false; HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); skipOverlay.Hide(); } DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => { if (waiting.NewValue) { GameplayClockContainer.Stop(); } else { GameplayClockContainer.Start(); } }); DrawableRuleset.IsPaused.BindValueChanged(paused => { updateGameplayState(); updateSampleDisabledState(); }); DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState()); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); DrawableRuleset.OnNewResult += r => { HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); gameplayBeatmap.ApplyResult(r); }; DrawableRuleset.OnRevertResult += r => { HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; // Bind the judgement processors to ourselves ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState; HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } foreach (var mod in Mods.Value.OfType <IApplicableToHealthProcessor>()) { mod.ApplyToHealthProcessor(HealthProcessor); } IsBreakTime.BindTo(breakTracker.IsBreakTime); IsBreakTime.BindValueChanged(onBreakTimeChanged, true); }
/// <summary> /// Run any recording / playback setup for replays. /// </summary> protected virtual void PrepareReplay() { DrawableRuleset.SetRecordTarget(recordingScore = new Score()); ScoreProcessor.NewJudgement += result => ScoreProcessor.PopulateScore(recordingScore.ScoreInfo); }
public SpectatingTrackedUserData(int userId, ScoreProcessor scoreProcessor) : base(userId, scoreProcessor) { }
protected override TrackedUserData CreateUserData(int userId, ScoreProcessor scoreProcessor) => new SpectatingTrackedUserData(userId, scoreProcessor);
public MultiSpectatorLeaderboard([NotNull] ScoreProcessor scoreProcessor, int[] userIds) : base(scoreProcessor, userIds) { }
protected virtual bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Combo.Value == 0 && result.Judgement.AffectsCombo;
private void load(ScoreProcessor scoreProcessor) { Current.BindTo(scoreProcessor.Accuracy); }
private void load(AudioManager audio, OsuConfigManager config) { Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) { return; } IBeatmap playableBeatmap = loadPlayableBeatmap(); if (playableBeatmap == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime); AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); dependencies.CacheAs(gameplayBeatmap); addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, Beatmap.Value, playableBeatmap); addOverlayComponents(GameplayClockContainer, Beatmap.Value); if (!DrawableRuleset.AllowGameplayOverlays) { HUDOverlay.ShowHud.Value = false; HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); skipOverlay.Hide(); } DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); DrawableRuleset.OnNewResult += r => { HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); gameplayBeatmap.ApplyResult(r); }; DrawableRuleset.OnRevertResult += r => { HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; // Bind the judgement processors to ourselves ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState; HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } foreach (var mod in Mods.Value.OfType <IApplicableToHealthProcessor>()) { mod.ApplyToHealthProcessor(HealthProcessor); } breakTracker.IsBreakTime.BindValueChanged(onBreakTimeChanged, true); }
/// <summary> /// Handles all key presses in the current replay frame. /// </summary> private void HandleKeyPressesInFrame() { // Retrieve a list of the key press states in integer form. var currentFramePressed = Replay.KeyPressStateToLanes(Replay.Frames[CurrentFrame].Keys); var previousFramePressed = CurrentFrame > 0 ? Replay.KeyPressStateToLanes(Replay.Frames[CurrentFrame - 1].Keys) : new List <int>(); // Update the key press state in the store. for (var i = 0; i < InputKeyStore.Count; i++) { InputKeyStore[i].Pressed = currentFramePressed.Contains(i); } // Check the difference in key press states for the current and previous frames. var keyDifferences = currentFramePressed.Except(previousFramePressed) .Concat(previousFramePressed.Except(currentFramePressed)) .ToList(); // Go through each frame and handle key presses/releases. foreach (var key in keyDifferences) { // This key was uniquely pressed during this frame. if (currentFramePressed.Contains(key)) { // Find the nearest object in the lane that the user has pressed. var nearestObjectIndex = GetIndexOfNearestLaneObject(key + 1, Time); if (nearestObjectIndex == -1) { continue; } // Grab the actual HitObject instance. var hitObject = ActiveHitObjects[nearestObjectIndex]; // Calculate the hit difference. var hitDifference = hitObject.StartTime - Time; // Calculate Score. var judgement = ScoreProcessor.CalculateScore(hitDifference, KeyPressType.Press); switch (judgement) { // Don't handle ghost key presses, so just continue further. case Judgement.Ghost: continue; // Object needs to be removed completely if it's a miss. case Judgement.Miss: // Add another miss for an LN (head and tail) if (hitObject.IsLongNote) { ScoreProcessor.CalculateScore(Judgement.Miss); ScoreProcessor.Stats.Add(new HitStat(HitStatType.Miss, KeyPressType.Press, hitObject, Time, Judgement.Miss, int.MinValue, ScoreProcessor.Accuracy, ScoreProcessor.Health)); } break; default: // Long notes need to be changed to a held status. if (hitObject.IsLongNote) { ActiveHeldLongNotes.Add(hitObject); } break; } // Add a new hit stat to the score processor. var stat = new HitStat(HitStatType.Hit, KeyPressType.Press, hitObject, Time, judgement, hitDifference, ScoreProcessor.Accuracy, ScoreProcessor.Health); ScoreProcessor.Stats.Add(stat); // Object needs to be removed from ActiveObjects. ActiveHitObjectsToRemove.Add(hitObject); } // This key was uniquely released during this frame. else if (previousFramePressed.Contains(key)) { // Find the index of the actual closest LN and handle the key release // if so. foreach (var hitObject in ActiveHeldLongNotes) { // Handle the release of the note. if (hitObject.Lane != key + 1) { continue; } // Calculate the hit difference. var hitDifference = hitObject.EndTime - Time; // Calculate Score var judgement = ScoreProcessor.CalculateScore(hitDifference, KeyPressType.Release); // LN was released during a hit window. if (judgement != Judgement.Ghost) { // Add a new hit stat to the score processor. var stat = new HitStat(HitStatType.Hit, KeyPressType.Release, hitObject, Time, judgement, hitDifference, ScoreProcessor.Accuracy, ScoreProcessor.Health); ScoreProcessor.Stats.Add(stat); } // The LN was released too early (miss) else { ScoreProcessor.CalculateScore(Judgement.Miss); // Add a new stat to ScoreProcessor. var stat = new HitStat(HitStatType.Hit, KeyPressType.Release, hitObject, Time, Judgement.Miss, hitDifference, ScoreProcessor.Accuracy, ScoreProcessor.Health); ScoreProcessor.Stats.Add(stat); } // Remove the object from its held state. ActiveHeldLongNotesToRemove.Add(hitObject); } } } // Remove all active objects after handling key presses/releases. ActiveHitObjectsToRemove.ForEach(x => ActiveHitObjects.Remove(x)); ActiveHeldLongNotesToRemove.ForEach(x => ActiveHeldLongNotes.Remove(x)); }
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { scoreProcessor.FailConditions += FailCondition; }
private void load(AudioManager audio, OsuConfigManager config, OsuGameBase game) { var gameplayMods = Mods.Value.Select(m => m.DeepClone()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) { return; } IBeatmap playableBeatmap = loadPlayableBeatmap(gameplayMods); if (playableBeatmap == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); if (game != null) { gameActive.BindTo(game.IsActive); } if (game is OsuGame osuGame) { LocalUserPlaying.BindTo(osuGame.LocalUserPlaying); } DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, gameplayMods); dependencies.CacheAs(DrawableRuleset); ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.Value = gameplayMods; dependencies.CacheAs(ScoreProcessor); HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); dependencies.CacheAs(HealthProcessor); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); Score = CreateScore(playableBeatmap); // ensure the score is in a consistent state with the current player. Score.ScoreInfo.BeatmapInfo = Beatmap.Value.BeatmapInfo; Score.ScoreInfo.Ruleset = ruleset.RulesetInfo; if (ruleset.RulesetInfo.ID != null) { Score.ScoreInfo.RulesetID = ruleset.RulesetInfo.ID.Value; } Score.ScoreInfo.Mods = gameplayMods; dependencies.CacheAs(GameplayState = new GameplayState(playableBeatmap, ruleset, gameplayMods, Score)); var rulesetSkinProvider = new RulesetSkinProvidingContainer(ruleset, playableBeatmap, Beatmap.Value.Skin); // load the skinning hierarchy first. // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. GameplayClockContainer.Add(rulesetSkinProvider); rulesetSkinProvider.AddRange(new Drawable[] { failAnimationLayer = new FailAnimation(DrawableRuleset) { OnComplete = onFailComplete, Children = new[] { // underlay and gameplay should have access to the skinning sources. createUnderlayComponents(), createGameplayComponents(Beatmap.Value, playableBeatmap) } }, FailOverlay = new FailOverlay { OnRetry = Restart, OnQuit = () => PerformExit(true), }, new HotkeyExitOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); PerformExit(false); }, }, }); if (Configuration.AllowRestart) { rulesetSkinProvider.Add(new HotkeyRetryOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); Restart(); }, }); } // add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components. // also give the overlays the ruleset skin provider to allow rulesets to potentially override HUD elements (used to disable combo counters etc.) // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there. failAnimationLayer.Add(createOverlayComponents(Beatmap.Value)); if (!DrawableRuleset.AllowGameplayOverlays) { HUDOverlay.ShowHud.Value = false; HUDOverlay.ShowHud.Disabled = true; BreakOverlay.Hide(); } DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => { if (waiting.NewValue) { GameplayClockContainer.Stop(); } else { GameplayClockContainer.Start(); } }); DrawableRuleset.IsPaused.BindValueChanged(paused => { updateGameplayState(); updateSampleDisabledState(); }); DrawableRuleset.FrameStableClock.IsCatchingUp.BindValueChanged(_ => updateSampleDisabledState()); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updateGameplayState()); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); DrawableRuleset.NewResult += r => { HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); GameplayState.ApplyResult(r); }; DrawableRuleset.RevertResult += r => { HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; DimmableStoryboard.HasStoryboardEnded.ValueChanged += storyboardEnded => { if (storyboardEnded.NewValue) { progressToResults(true); } }; // Bind the judgement processors to ourselves ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged); HealthProcessor.Failed += onFail; // Provide judgement processors to mods after they're loaded so that they're on the gameplay clock, // this is required for mods that apply transforms to these processors. ScoreProcessor.OnLoadComplete += _ => { foreach (var mod in gameplayMods.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } }; HealthProcessor.OnLoadComplete += _ => { foreach (var mod in gameplayMods.OfType <IApplicableToHealthProcessor>()) { mod.ApplyToHealthProcessor(HealthProcessor); } }; IsBreakTime.BindTo(breakTracker.IsBreakTime); IsBreakTime.BindValueChanged(onBreakTimeChanged, true); }
protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0;
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { // Default value of ScoreProcessor's Rank in Hidden Mod should be SS+ scoreProcessor.Rank.Value = ScoreRank.XH; }
protected virtual void PrepareScoreForResults() { // perform one final population to ensure everything is up-to-date. ScoreProcessor.PopulateScore(Score.ScoreInfo); }
public BreakOverlay(bool letterboxing, ScoreProcessor scoreProcessor) : this(letterboxing) { bindProcessor(scoreProcessor); }
public BreakTracker(double gameplayStartTime = 0, ScoreProcessor scoreProcessor = null) { this.gameplayStartTime = gameplayStartTime; this.scoreProcessor = scoreProcessor; }
private void load(AudioManager audio, APIAccess api, OsuConfigManager config) { this.api = api; WorkingBeatmap working = Beatmap.Value; if (working is DummyWorkingBeatmap) { return; } sampleRestart = audio.Sample.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); userAudioOffset = config.GetBindable <double>(OsuSetting.AudioOffset); Beatmap beatmap; try { beatmap = working.Beatmap; if (beatmap == null) { throw new InvalidOperationException("Beatmap was not loaded"); } ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; var rulesetInstance = ruleset.CreateInstance(); try { RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working, ruleset.ID == beatmap.BeatmapInfo.Ruleset.ID); } catch (BeatmapInvalidForRulesetException) { // we may fail to create a RulesetContainer if the beatmap cannot be loaded with the user's preferred ruleset // let's try again forcing the beatmap's ruleset. ruleset = beatmap.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap, true); } if (!RulesetContainer.Objects.Any()) { Logger.Error(new InvalidOperationException("Beatmap contains no hit objects!"), "Beatmap contains no hit objects!"); return; } } catch (Exception e) { Logger.Error(e, "Could not load beatmap sucessfully!"); //couldn't load, hard abort! return; } sourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock(); adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; var firstObjectTime = RulesetContainer.Objects.First().StartTime; adjustableClock.Seek(AllowLeadIn ? Math.Min(0, firstObjectTime - Math.Max(beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, beatmap.BeatmapInfo.AudioLeadIn)) : firstObjectTime); adjustableClock.ProcessFrame(); // the final usable gameplay clock with user-set offsets applied. var offsetClock = new FramedOffsetClock(adjustableClock); userAudioOffset.ValueChanged += v => offsetClock.Offset = v; userAudioOffset.TriggerChange(); scoreProcessor = RulesetContainer.CreateScoreProcessor(); Children = new Drawable[] { pauseContainer = new PauseContainer(offsetClock, adjustableClock) { OnRetry = Restart, OnQuit = Exit, CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, OnPause = () => { pauseContainer.Retries = RestartCount; hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused; }, OnResume = () => hudOverlay.KeyCounter.IsCounting = true, Children = new Drawable[] { storyboardContainer = new Container { RelativeSizeAxes = Axes.Both, Alpha = 0, }, new LocalSkinOverrideContainer(working.Skin) { RelativeSizeAxes = Axes.Both, Child = RulesetContainer }, new SkipOverlay(firstObjectTime) { Clock = Clock, // skip button doesn't want to use the audio clock directly ProcessCustomClock = false, AdjustableClock = adjustableClock, FramedClock = offsetClock, }, hudOverlay = new HUDOverlay(scoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) { Clock = Clock, // hud overlay doesn't want to use the audio clock directly ProcessCustomClock = false, Anchor = Anchor.Centre, Origin = Anchor.Centre }, new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, scoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, ProcessCustomClock = false, Breaks = beatmap.Breaks } } }, failOverlay = new FailOverlay { OnRetry = Restart, OnQuit = Exit, }, new HotkeyRetryOverlay { Action = () => { if (!IsCurrentScreen) { return; } //we want to hide the hitrenderer immediately (looks better). //we may be able to remove this once the mouse cursor trail is improved. RulesetContainer?.Hide(); Restart(); }, } }; if (ShowStoryboard) { initializeStoryboard(false); } // Bind ScoreProcessor to ourselves scoreProcessor.AllJudged += onCompletion; scoreProcessor.Failed += onFail; foreach (var mod in Beatmap.Value.Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(scoreProcessor); } }
protected override async Task PrepareScoreForResultsAsync(Score score) { await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false); Score.ScoreInfo.TotalScore = (int)Math.Round(ScoreProcessor.GetStandardisedScore()); }
private void load(AudioManager audio, IAPIProvider api, OsuConfigManager config) { this.api = api; Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) { return; } IBeatmap playableBeatmap = loadPlayableBeatmap(); if (playableBeatmap == null) { return; } sampleRestart = audio.Samples.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); ScoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, Beatmap.Value); addOverlayComponents(GameplayClockContainer, Beatmap.Value); DrawableRuleset.HasReplayLoaded.BindValueChanged(_ => updatePauseOnFocusLostState(), true); // bind clock into components that require it DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); DrawableRuleset.OnNewResult += r => { HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); }; DrawableRuleset.OnRevertResult += r => { HealthProcessor.RevertResult(r); ScoreProcessor.RevertResult(r); }; // Bind the judgement processors to ourselves ScoreProcessor.AllJudged += onCompletion; HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } foreach (var mod in Mods.Value.OfType <IApplicableToHealthProcessor>()) { mod.ApplyToHealthProcessor(HealthProcessor); } BreakOverlay.IsBreakTime.ValueChanged += _ => updatePauseOnFocusLostState(); }
protected virtual TrackedUserData CreateUserData(MultiplayerRoomUser user, RulesetInfo ruleset, ScoreProcessor scoreProcessor) => new TrackedUserData(user, ruleset, scoreProcessor);
public ComboEffects(ScoreProcessor processor) { this.processor = processor; }
private void load(AudioManager audio, OsuConfigManager config, OsuGame osu) { dimLevel = config.GetBindable <double>(OsuSetting.DimLevel); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); sampleRestart = audio.Sample.Get(@"Gameplay/restart"); Ruleset rulesetInstance; try { if (Beatmap.Value.Beatmap == null) { throw new InvalidOperationException("Beatmap was not loaded"); } ruleset = osu?.Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); try { HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap, ruleset.ID == Beatmap.Value.BeatmapInfo.Ruleset.ID); } catch (BeatmapInvalidForRulesetException) { // we may fail to create a HitRenderer if the beatmap cannot be loaded with the user's preferred ruleset // let's try again forcing the beatmap's ruleset. ruleset = Beatmap.Value.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap, true); } if (!HitRenderer.Objects.Any()) { throw new InvalidOperationException("Beatmap contains no hit objects!"); } } catch (Exception e) { Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error); //couldn't load, hard abort! Exit(); return; } Track track = Beatmap.Value.Track; if (track != null) { adjustableSourceClock = track; } adjustableSourceClock = (IAdjustableClock)track ?? new StopwatchClock(); decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; var firstObjectTime = HitRenderer.Objects.First().StartTime; decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, Beatmap.Value.BeatmapInfo.AudioLeadIn))); decoupledClock.ProcessFrame(); offsetClock = new FramedOffsetClock(decoupledClock); userAudioOffset = config.GetBindable <double>(OsuSetting.AudioOffset); userAudioOffset.ValueChanged += v => offsetClock.Offset = v; userAudioOffset.TriggerChange(); Schedule(() => { adjustableSourceClock.Reset(); foreach (var mod in Beatmap.Value.Mods.Value.OfType <IApplicableToClock>()) { mod.ApplyToClock(adjustableSourceClock); } decoupledClock.ChangeSource(adjustableSourceClock); }); Children = new Drawable[] { pauseContainer = new PauseContainer { AudioClock = decoupledClock, FramedClock = offsetClock, OnRetry = Restart, OnQuit = Exit, CheckCanPause = () => ValidForResume && !HasFailed && !HitRenderer.HasReplayLoaded, Retries = RestartCount, OnPause = () => { hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused; }, OnResume = () => { hudOverlay.KeyCounter.IsCounting = true; }, Children = new Drawable[] { new SkipButton(firstObjectTime) { AudioClock = decoupledClock }, new Container { RelativeSizeAxes = Axes.Both, Clock = offsetClock, Children = new Drawable[] { HitRenderer, } }, hudOverlay = new HUDOverlay { Anchor = Anchor.Centre, Origin = Anchor.Centre }, } }, failOverlay = new FailOverlay { OnRetry = Restart, OnQuit = Exit, }, new HotkeyRetryOverlay { Action = () => { //we want to hide the hitrenderer immediately (looks better). //we may be able to remove this once the mouse cursor trail is improved. HitRenderer?.Hide(); Restart(); }, } }; scoreProcessor = HitRenderer.CreateScoreProcessor(); hudOverlay.KeyCounter.AddRange(rulesetInstance.CreateGameplayKeys()); hudOverlay.BindProcessor(scoreProcessor); hudOverlay.BindHitRenderer(HitRenderer); hudOverlay.Progress.Objects = HitRenderer.Objects; hudOverlay.Progress.AudioClock = decoupledClock; hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded; hudOverlay.Progress.OnSeek = pos => decoupledClock.Seek(pos); hudOverlay.ModDisplay.Current.BindTo(Beatmap.Value.Mods); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) HitRenderer.OnAllJudged += onCompletion; //bind ScoreProcessor to ourselves (for a fail situation) scoreProcessor.Failed += onFail; }
private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config) { var beatmap = Beatmap.Beatmap; if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu) { //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. Exit(); return; } dimLevel = config.GetBindable <int>(OsuConfig.DimLevel); mouseWheelDisabled = config.GetBindable <bool>(OsuConfig.MouseDisableWheel); try { if (Beatmap == null) { Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true); } if ((Beatmap?.Beatmap?.HitObjects.Count ?? 0) == 0) { throw new Exception("No valid objects were found!"); } if (Beatmap == null) { throw new Exception("Beatmap was not loaded"); } } catch (Exception e) { Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error); //couldn't load, hard abort! Exit(); return; } Track track = Beatmap.Track; if (track != null) { audio.Track.SetExclusive(track); sourceClock = track; } sourceClock = (IAdjustableClock)track ?? new StopwatchClock(); interpolatedSourceClock = new InterpolatingFramedClock(sourceClock); Schedule(() => { sourceClock.Reset(); }); ruleset = Ruleset.GetRuleset(Beatmap.PlayMode); hudOverlay = new StandardHudOverlay(); hudOverlay.KeyCounter.Add(ruleset.CreateGameplayKeys()); hudOverlay.BindProcessor(scoreProcessor = ruleset.CreateScoreProcessor(beatmap.HitObjects.Count)); pauseOverlay = new PauseOverlay { Depth = -1, OnResume = delegate { Delay(400); Schedule(Resume); }, OnRetry = Restart, OnQuit = Exit }; hitRenderer = ruleset.CreateHitRendererWith(Beatmap); if (ReplayInputHandler != null) { hitRenderer.InputManager.ReplayInputHandler = ReplayInputHandler; } hudOverlay.BindHitRenderer(hitRenderer); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) hitRenderer.OnJudgement += scoreProcessor.AddJudgement; hitRenderer.OnAllJudged += onPass; //bind ScoreProcessor to ourselves (for a fail situation) scoreProcessor.Failed += onFail; Children = new Drawable[] { new Container { RelativeSizeAxes = Axes.Both, Clock = interpolatedSourceClock, Children = new Drawable[] { hitRenderer, skipButton = new SkipButton { Alpha = 0 }, } }, hudOverlay, pauseOverlay }; }
private void load(AudioManager audio, APIAccess api, OsuConfigManager config) { this.api = api; WorkingBeatmap working = Beatmap.Value; if (working is DummyWorkingBeatmap) { return; } sampleRestart = audio.Sample.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable <bool>(OsuSetting.MouseDisableWheel); userAudioOffset = config.GetBindable <double>(OsuSetting.AudioOffset); IBeatmap beatmap; try { beatmap = working.Beatmap; if (beatmap == null) { throw new InvalidOperationException("Beatmap was not loaded"); } ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; var rulesetInstance = ruleset.CreateInstance(); try { RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working); } catch (BeatmapInvalidForRulesetException) { // we may fail to create a RulesetContainer if the beatmap cannot be loaded with the user's preferred ruleset // let's try again forcing the beatmap's ruleset. ruleset = beatmap.BeatmapInfo.Ruleset; rulesetInstance = ruleset.CreateInstance(); RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap.Value); } if (!RulesetContainer.Objects.Any()) { Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Error); return; } } catch (Exception e) { Logger.Error(e, "Could not load beatmap sucessfully!"); //couldn't load, hard abort! return; } sourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock(); adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; adjustableClock.Seek(AllowLeadIn ? Math.Min(0, RulesetContainer.GameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn) : RulesetContainer.GameplayStartTime); adjustableClock.ProcessFrame(); // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited. // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck. var platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0 }; // the final usable gameplay clock with user-set offsets applied. var offsetClock = new FramedOffsetClock(platformOffsetClock); userAudioOffset.ValueChanged += v => offsetClock.Offset = v; userAudioOffset.TriggerChange(); ScoreProcessor = RulesetContainer.CreateScoreProcessor(); if (!ScoreProcessor.Mode.Disabled) { config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); } InternalChildren = new Drawable[] { pauseContainer = new PauseContainer(offsetClock, adjustableClock) { Retries = RestartCount, OnRetry = Restart, OnQuit = performUserRequestedExit, CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, Children = new[] { storyboardContainer = new Container { RelativeSizeAxes = Axes.Both, Alpha = 0, }, new ScalingContainer(ScalingMode.Gameplay) { Child = new LocalSkinOverrideContainer(working.Skin) { RelativeSizeAxes = Axes.Both, Child = RulesetContainer } }, new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, ProcessCustomClock = false, Breaks = beatmap.Breaks }, new ScalingContainer(ScalingMode.Gameplay) { Child = RulesetContainer.Cursor?.CreateProxy() ?? new Container(), }, HUDOverlay = new HUDOverlay(ScoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) { Clock = Clock, // hud overlay doesn't want to use the audio clock directly ProcessCustomClock = false, Anchor = Anchor.Centre, Origin = Anchor.Centre }, new SkipOverlay(RulesetContainer.GameplayStartTime) { Clock = Clock, // skip button doesn't want to use the audio clock directly ProcessCustomClock = false, AdjustableClock = adjustableClock, FramedClock = offsetClock, }, } }, failOverlay = new FailOverlay { OnRetry = Restart, OnQuit = performUserRequestedExit, }, new HotkeyRetryOverlay { Action = () => { if (!this.IsCurrentScreen()) { return; } fadeOut(true); Restart(); }, } }; HUDOverlay.HoldToQuit.Action = performUserRequestedExit; HUDOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded); RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused); if (ShowStoryboard) { initializeStoryboard(false); } // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; ScoreProcessor.Failed += onFail; foreach (var mod in Beatmap.Value.Mods.Value.OfType <IApplicableToScoreProcessor>()) { mod.ApplyToScoreProcessor(ScoreProcessor); } }