private bool ValidateDifficulty(StandardLevelInfoSaveData.DifficultyBeatmap diffBeatmap, SongCore.Data.ExtraSongData data, BeatmapCharacteristicSO characteristic, BeatmapDifficulty beatmapDifficulty) { var diffData = data._difficulties.FirstOrDefault(x => x._beatmapCharacteristicName == characteristic.serializedName && x._difficulty == beatmapDifficulty); if (diffData == null) { return(false); } var requirements = diffData.additionalDifficultyData._requirements; if (requirements.Length > 0) { foreach (string req in requirements) { //Make sure requirement is actually present if (!SongCore.Collections.capabilities.Contains(req)) { Plugin.Log($"Missing difficulty requirement {req}"); return(false); } switch (req) { case "Mapping Extensions": MappingExtensions.Plugin.ForceActivateForSong(); break; //Don't allow difficulties with requirements that we aren't sure how to handle to be played default: Plugin.Log($"Unsure how to handle difficulty requirement {req}"); return(false); } } } //Add Option to allow 360 in endless mode that forces 360 UI and allows characteristics with rotation events if (characteristic.containsRotationEvents && !_allow360) { Plugin.Log("360 maps not enabled."); return(false); } return(true); }
private IEnumerator DelayedSetup() { //Slight delay before grabbing needed objects yield return(new WaitForSeconds(0.1f)); _timeSync = Resources.FindObjectsOfTypeAll <AudioTimeSyncController>().LastOrDefault(x => x.isActiveAndEnabled); _songAudio = _timeSync.GetField <AudioSource>("_audioSource"); _levelLoader = Resources.FindObjectsOfTypeAll <CustomLevelLoader>().First(); _spawnController = Resources.FindObjectsOfTypeAll <BeatmapObjectSpawnController>().LastOrDefault(x => x.isActiveAndEnabled); _originalSpawnMovementData = _spawnController.GetField <BeatmapObjectSpawnMovementData>("_beatmapObjectSpawnMovementData"); _pauseController = Resources.FindObjectsOfTypeAll <PauseController>().LastOrDefault(x => x.isActiveAndEnabled); _callbackController = Resources.FindObjectsOfTypeAll <BeatmapObjectCallbackController>().LastOrDefault(x => x.isActiveAndEnabled); _seManager = Resources.FindObjectsOfTypeAll <NoteCutSoundEffectManager>().LastOrDefault(x => x.isActiveAndEnabled); _beatmapObjectManager = _seManager.GetField <BeatmapObjectManager>("_beatmapObjectManager"); _cancelSource = new CancellationTokenSource(); var level = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap.level; if (!(level is CustomPreviewBeatmapLevel)) { yield break; } _currentLevel = level as CustomPreviewBeatmapLevel; //Get DifficultyBeatmap BeatmapDifficulty levelDiff = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap.difficulty; BeatmapCharacteristicSO levelCharacteristic = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic; _currentDiffBeatmap = _currentLevel.standardLevelInfoSaveData.difficultyBeatmapSets.First( x => x.beatmapCharacteristicName == levelCharacteristic.serializedName).difficultyBeatmaps.First( x => x.difficulty == levelDiff.ToString()); _originalInitData = _timeSync.GetField <AudioTimeSyncController.InitData>("_initData"); _songStartTime = _originalInitData.startSongTime; //Initialize if everything successfully grabbed _init = true; }
private bool IsValid(IPreviewBeatmapLevel testLevel, out StandardLevelInfoSaveData.DifficultyBeatmap nextDiff) { nextDiff = null; if (testLevel.levelID == nextSongInfo?.levelID) { return(false); } if (!(testLevel is CustomPreviewBeatmapLevel)) { return(false); } CustomPreviewBeatmapLevel level = testLevel as CustomPreviewBeatmapLevel; var extraData = SongCore.Collections.RetrieveExtraSongData(level.levelID, level.customLevelPath); if (extraData == null) { Plugin.Log("Null Extra Data"); return(false); } // Add To Config BeatmapDifficulty preferredDiff = Config.EndlessPrefDifficulty; BeatmapDifficulty minDiff = Config.EndlessMinDifficulty; BeatmapDifficulty maxDiff = Config.EndlessMaxDifficulty; // Randomly Choose Characteristic? // BeatmapCharacteristicSO selectedCharacteristic = level.previewDifficultyBeatmapSets.First().beatmapCharacteristic; BeatmapCharacteristicSO selectedCharacteristic = level.previewDifficultyBeatmapSets[ UnityEngine.Random.Range(0, level.previewDifficultyBeatmapSets.Length - 1)].beatmapCharacteristic; foreach (var set in level.standardLevelInfoSaveData.difficultyBeatmapSets) { if (set.beatmapCharacteristicName != selectedCharacteristic.serializedName) { continue; } foreach (var diff in set.difficultyBeatmaps) { BeatmapDifficulty difficulty = (BeatmapDifficulty)Enum.Parse(typeof(BeatmapDifficulty), diff.difficulty); if ((difficulty == preferredDiff)) { if (ValidateDifficulty(diff, extraData, selectedCharacteristic, difficulty)) { nextDiff = diff; return(true); } } } foreach (var diff in set.difficultyBeatmaps) { BeatmapDifficulty difficulty = (BeatmapDifficulty)Enum.Parse(typeof(BeatmapDifficulty), diff.difficulty); if ((int)difficulty <= (int)minDiff || (int)difficulty >= (int)maxDiff) { continue; } if (ValidateDifficulty(diff, extraData, selectedCharacteristic, difficulty)) { nextDiff = diff; nextDifficulty = difficulty; nextCharacteristic = selectedCharacteristic; return(true); } } } return(false); }
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter private static void Postfix(BeatmapData __result, string difficultyFileName, StandardLevelInfoSaveData standardLevelInfoSaveData) #pragma warning restore SA1313 // Parameter names should begin with lower-case letter { if (__result != null && __result is CustomBeatmapData customBeatmapData) { // heck you beat games for not passing StandardLevelInfoSaveData.DifficultyBeatmap down to this method StandardLevelInfoSaveData.DifficultyBeatmap difficultyBeatmap = null; int iCount = standardLevelInfoSaveData.difficultyBeatmapSets.Length; for (int i = 0; i < iCount; i++) { StandardLevelInfoSaveData.DifficultyBeatmapSet difficultyBeatmapSet = standardLevelInfoSaveData.difficultyBeatmapSets[i]; int jCount = difficultyBeatmapSet.difficultyBeatmaps.Length; for (int j = 0; j < jCount; j++) { StandardLevelInfoSaveData.DifficultyBeatmap difficultyBeatmaps = difficultyBeatmapSet.difficultyBeatmaps[j]; if (difficultyBeatmaps.beatmapFilename == difficultyFileName) { difficultyBeatmap = difficultyBeatmaps; } } } if (difficultyBeatmap != null) { // there is some ambiguity with these variables but who frikkin cares float startHalfJumpDurationInBeats = 4; float maxHalfJumpDistance = 18; float moveDuration = 0.5f; foreach (BeatmapLineData beatmapLineData in __result.beatmapLinesData) { foreach (BeatmapObjectData beatmapObjectData in beatmapLineData.beatmapObjectsData) { dynamic customData; if (beatmapObjectData is CustomObstacleData || beatmapObjectData is CustomNoteData) { customData = beatmapObjectData; } else { return; } dynamic dynData = customData.customData; float noteJumpMovementSpeed = (float?)Trees.at(dynData, NOTEJUMPSPEED) ?? difficultyBeatmap.noteJumpMovementSpeed; float noteJumpStartBeatOffset = (float?)Trees.at(dynData, NOTESPAWNOFFSET) ?? difficultyBeatmap.noteJumpStartBeatOffset; // how do i not repeat this in a reasonable way float num = 60f / (float)Trees.at(dynData, "bpm"); float num2 = startHalfJumpDurationInBeats; while (noteJumpMovementSpeed * num * num2 > maxHalfJumpDistance) { num2 /= 2f; } num2 += noteJumpStartBeatOffset; if (num2 < 1f) { num2 = 1f; } float jumpDuration = num * num2 * 2f; dynData.aheadTime = moveDuration + (jumpDuration * 0.5f); } beatmapLineData.beatmapObjectsData = beatmapLineData.beatmapObjectsData.OrderBy(n => n.time - (float)((dynamic)n).customData.aheadTime).ToArray(); } } } }