// Purposefully ignore modifiers here - only 2 maps have them enabled and it doesn't make much sense to just filter to those two private static float GetHighestPP(IPreviewBeatmapLevel previewBeatmapLevel, bool ppGain) { float maxPP = 0; var id = SongDataUtils.GetHash(previewBeatmapLevel.levelID); // Check if in SDC if (SongDataCore.Plugin.Songs.Data.Songs.ContainsKey(id)) { // Loop through each diff foreach (var diff in SongDataCore.Plugin.Songs.Data.Songs[id].diffs) { var difficulty = SongDataUtils.GetBeatmapDifficulty(diff.diff); var songID = new SongID(id, difficulty); // Only go through ranked songs if (SongDataUtils.IsRankedSong(songID)) { float pp = PPUtils.CalculatePP(songID, AccLoader.instance.GetAcc(songID)); if (ppGain) { pp = PPUtils.GetPPGain(pp, songID); } maxPP = pp > maxPP ? pp : maxPP; } } return(maxPP); } return(0); }
public float GetAcc(SongID songID) { // First check for song specific accuracy if (_songSpecificAcc.ContainsKey(songID)) { return(RoundedAcc(_songSpecificAcc[songID])); } double bestAcc = 0; // Next check for max of current best acc and star acc if (ProfileDataLoader.instance.songDataInfo.ContainsKey(songID)) { bestAcc = ProfileDataLoader.instance.songDataInfo[songID].acc; } // Next check for star acc var star = SongDataUtils.GetRoundedStars(songID); if (_starAcc.ContainsKey(star)) { bestAcc = Math.Max(bestAcc, _starAcc[star]); } if (bestAcc > 0) { return(RoundedAcc(bestAcc)); } // Finally resort to default return(Config.defaultAcc); }
IEnumerator FindDifficultyBeatmap() { yield return(new WaitUntil(() => BS_Utils.Plugin.LevelData.IsSet)); _difficultyBeatmap = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap; _songID = new SongID(SongDataUtils.GetHash(_difficultyBeatmap.level.levelID), _difficultyBeatmap.difficulty); _rawPP = SongDataUtils.GetRawPP(_songID); // modifiers var gameplayModifiersModelSO = Resources.FindObjectsOfTypeAll <GameplayModifiersModelSO>().FirstOrDefault(); var gameplayModifiers = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.gameplayModifiers; _multiplier = gameplayModifiersModelSO.GetTotalMultiplier(gameplayModifiers); _multiplier = (Config.ignoreNoFail && gameplayModifiers.noFail) ? _multiplier + 0.5 : _multiplier; // Only update for ranked songs if (SongDataUtils.IsRankedSong(_songID)) { yield return(new WaitUntil(() => _beatmapObjectManager != null)); _beatmapObjectManager.noteWasCutEvent += OnNoteCut; _beatmapObjectManager.noteWasMissedEvent += OnNoteMissed; yield return(new WaitUntil(() => _scoreController != null)); _scoreController.scoreDidChangeEvent += OnScoreChange; if (!Config.hideOnStart) { UpdateCounter(); } } }
public void ModifiersChanged() { var gameplayModifiersPanelController = Resources.FindObjectsOfTypeAll <GameplayModifiersPanelController>().FirstOrDefault(); _modifiers = gameplayModifiersPanelController.GetPrivateField <GameplayModifiers>("_gameplayModifiers"); if (SongDataUtils.IsRankedSong(_id)) { SetPPText(PPUtils.AllowedModifiers(_id.id, _modifiers)); } }
public void LevelCleared(StandardLevelScenesTransitionSetupDataSO standardLevelScenesTransitionSetupDataSO, LevelCompletionResults levelCompletionResults) { Logger.log.Debug("Level cleared"); // Score submission disabled or using practice mode if (BS_Utils.Gameplay.ScoreSubmission.WasDisabled || BS_Utils.Gameplay.ScoreSubmission.ProlongedDisabled || ((GameplayCoreSceneSetupData)standardLevelScenesTransitionSetupDataSO.sceneSetupDataArray.First(x => x.GetType().Equals(typeof(GameplayCoreSceneSetupData)))).practiceSettings != null) { Logger.log.Debug("Practice mode or score disabled"); return; } var gameplayCoreSceneSetupData = ((GameplayCoreSceneSetupData)standardLevelScenesTransitionSetupDataSO.sceneSetupDataArray[1]); var difficultyBeatmap = gameplayCoreSceneSetupData.difficultyBeatmap; SongID songID = SongDataUtils.GetSongID(difficultyBeatmap); // I don't like putting play history here but until I do a refactor I'm gonna keep it here if (SongDataUtils.IsRankedSong(songID) || Config.playHistory) { Logger.log.Debug("Beat song"); GameplayModifiers modifiers = new GameplayModifiers(levelCompletionResults.gameplayModifiers); // Remove positive modifiers if not allowed if (!PPUtils.AllowedModifiers(songID.id, modifiers)) { Logger.log.Debug("Using invalid modifiers, removing from score"); modifiers = BeatSaberUtils.RemovePositiveModifiers(modifiers); } var multiplier = levelCompletionResults.gameplayModifiersModel.GetTotalMultiplier(modifiers); var score = levelCompletionResults.rawScore * multiplier; var maxScore = ScoreModel.MaxRawScoreForNumberOfNotes(difficultyBeatmap.beatmapData.notesCount); double acc = (double)score / (double)maxScore; Logger.log.Debug($"acc: {acc}"); if (SongDataUtils.IsRankedSong(songID)) { SubmitPlay(songID, acc); } else { PlayHistoryTracker.UpdatePlayHistory(songID, acc); } } }
// Loops through all songs and finds the highest star difficulty saved (rounded to nearest multiple of starRange) private static double CalculateMaxStarValue() { double maxStarValue = 0; foreach (var kvp in ProfileDataLoader.instance.songDataInfo) { if (SongDataCore.Plugin.Songs.Data.Songs.TryGetValue(kvp.Key.id, out var song)) { var difficultyStats = SongDataCore.Plugin.Songs.Data.Songs[kvp.Key.id].diffs; foreach (var difficultyStat in difficultyStats) { if (difficultyStat.diff.Equals(SongDataUtils.GetDifficultyAsString(kvp.Key.difficulty))) { var star = SongDataUtils.GetRoundedStars(difficultyStat.star); maxStarValue = star > maxStarValue ? star : maxStarValue; } } } } return(Math.Round(maxStarValue, 2)); }
public override void CounterInit() { var id = SongDataUtils.GetHash(difficultyBeatmap.level.levelID); songID = new SongID(id, difficultyBeatmap.difficulty); // Don't show anything for unranked songs or if data not initialized if (!ppUtils.DataInitialized() || !ppUtils.IsRanked(songID)) { return; } var gameplayModifiersModelSO = IPA.Utilities.FieldAccessor <RelativeScoreAndImmediateRankCounter, GameplayModifiersModelSO> .Get(relativeScoreAndImmediateRank, "_gameplayModifiersModel"); GameplayModifiers updatedModifiers = ppUtils.AllowedPositiveModifiers(songID) ? gameplayModifiers : GameplayModifierUtils.RemovePositiveModifiers(gameplayModifiers); _multiplier = GameplayModifierUtils.CalculateMultiplier(gameplayModifiersModelSO, updatedModifiers); counter = CanvasUtility.CreateTextFromSettings(Settings); counter.fontSize = 3; relativeScoreAndImmediateRank.relativeScoreOrImmediateRankDidChangeEvent += ScoreUpdated; UpdateCounterText(ppUtils.CalculatePP(songID, _multiplier, ppUtils.AllowedPositiveModifiers(songID))); if (PluginSettings.Instance.relativeGain) { var highScore = playerDataModel.playerData.GetPlayerLevelStatsData(difficultyBeatmap).highScore; if (highScore == 0) { _pbPP = 0; return; } var maxScore = ScoreModel.ComputeMaxMultipliedScoreForBeatmap(beatmapData); var acc = (float)highScore / maxScore; _pbPP = ppUtils.CalculatePP(songID, acc, ppUtils.AllowedPositiveModifiers(songID)); } }
internal void Refresh(string id) { if (!Config.showInfo) { _parentObject.SetActive(false); return; } try { IDifficultyBeatmap difficultyBeatmap = _standardLevelDetailView.selectedDifficultyBeatmap; var newId = new ProfileDataLoader.SongID(id, difficultyBeatmap.difficulty); if (SongDataUtils.IsRankedSong(newId)) { _parentObject.SetActive(true); _rawPP = SongDataUtils.GetRawPP(newId); // Only load the acc in when a new song is selected if (_id == null || !newId.Equals(_id)) { _id = newId; LoadAcc(); } SetPPText(PPUtils.AllowedModifiers(_id.id, _modifiers)); } else { _parentObject.SetActive(false); } } catch (Exception) { Logger.log.Debug($"error with difficulty for song {id}"); _parentObject.SetActive(false); } }
public static void CalculateAcc() { Logger.log.Debug("Calculating star acc"); var range = Config.starRange; Dictionary <double, double> acc = new Dictionary <double, double>(); Dictionary <double, int> counts = new Dictionary <double, int>(); // Need SongDataCore data if (!SongDataCore.Plugin.Songs.IsDataAvailable()) { return; } // Initialize some helper vars var numberOfScores = Config.starAccChoice.Equals(CalculationType.Max) ? 1 : Config.numberOfScores; var maxScores = new Dictionary <double, List <double> >(); var maxStarValue = CalculateMaxStarValue(); var averageAll = Config.starAccChoice.Equals(CalculationType.AverageOfAll); // Initialize dicts for (double star = 0.00; star <= maxStarValue + 2 * Config.starRange; star += Config.starRange) { star = SongDataUtils.GetRoundedStars(star); acc[star] = 0; counts[star] = 0; } foreach (var kvp in ProfileDataLoader.instance.songDataInfo) { // If star data not available for song, skip it double star; try { star = SongDataUtils.GetRoundedStars(kvp.Key); } catch (Exception e) { Logger.log.Debug($"Couldn't get star rating for {kvp.Key.id}"); continue; } // Will definitely be updating acc if (averageAll || counts[star] < numberOfScores) { acc[star] = ((acc[star] * counts[star]) + kvp.Value.acc) / (counts[star] + 1); counts[star] += 1; // update maxScores if (!averageAll) { // first score for given star rating if (!maxScores.ContainsKey(star)) { maxScores[star] = new List <double>(); } maxScores[star].Add(kvp.Value.acc); maxScores[star].Sort(); // List is small enough to not matter } } // Better than the lowest sore, update average acc else if (kvp.Value.acc > maxScores[star].First()) { var accWithoutLowerScore = acc[star] * counts[star] - maxScores[star].First(); acc[star] = (accWithoutLowerScore + kvp.Value.acc) / (counts[star]); // update maxScores maxScores[star].RemoveAt(0); maxScores[star].Add(kvp.Value.acc); maxScores[star].Sort(); } } if (Config.accOverride) { CleanupStarAcc(ref acc); } Logger.log.Debug("Finished calculating star acc"); SaveFile(acc); }
public void OnLevelSelected(LevelCollectionViewController levelCollectionViewController, IPreviewBeatmapLevel previewBeatmapLevel) { PP_HelperController.instance.setId(SongDataUtils.GetHash(previewBeatmapLevel.levelID)); }