public IEnumerator DoOnLevelStart() { yield return(new WaitUntil(() => standardLevelGameplayManager.GetField <StandardLevelGameplayManager.GameState>("_gameState") == StandardLevelGameplayManager.GameState.Playing)); yield return(new WaitUntil(() => Resources.FindObjectsOfTypeAll <GameEnergyCounter>().Any())); gameSongController = standardLevelGameplayManager.GetField <GameSongController>("_gameSongController"); gameEnergyCounter = Resources.FindObjectsOfTypeAll <GameEnergyCounter>().First(); //Prevent the gameEnergyCounter from invoking death by obstacle _oldObstacleEnergyDrainPerSecond = gameEnergyCounter.GetField <float>("_obstacleEnergyDrainPerSecond"); gameEnergyCounter.SetField("_obstacleEnergyDrainPerSecond", 0f); //Unhook the functions in the energy counter that watch note events, so we can peek inside the process beatmapObjectManager = gameEnergyCounter.GetField <BeatmapObjectManager>("_beatmapObjectManager"); beatmapObjectManager.noteWasMissedEvent -= gameEnergyCounter.HandleNoteWasMissedEvent; beatmapObjectManager.noteWasMissedEvent += beatmapObjectManager_noteWasMissedEvent; beatmapObjectManager.noteWasCutEvent -= gameEnergyCounter.HandleNoteWasCutEvent; beatmapObjectManager.noteWasCutEvent += beatmapObjectManager_noteWasCutEvent; //Unhook the level end event so we can reset everything before the level ends gameSongController.songDidFinishEvent -= standardLevelGameplayManager.HandleSongDidFinish; gameSongController.songDidFinishEvent += gameSongController_songDidFinishEvent; }
internal override void Init(CountersData data, Vector3 position) { beatmapObjectManager = data.BOM; TextHelper.CreateText(out missedText, position - new Vector3(0, 0.4f, 0)); missedText.text = "0"; missedText.fontSize = 4; missedText.color = Color.white; missedText.alignment = TextAlignmentOptions.Center; GameObject labelGO = new GameObject("Counters+ | Missed Label"); labelGO.transform.parent = transform; TextHelper.CreateText(out label, position); label.text = "Misses"; label.fontSize = 3; label.color = Color.white; label.alignment = TextAlignmentOptions.Center; if (settings.CustomMissTextIntegration && PluginUtility.IsPluginPresent("CustomMissText")) { UpdateCustomMissText(); } else if (!PluginUtility.IsPluginPresent("CustomMissText")) { settings.CustomMissTextIntegration = false; settings.Save(); } if (beatmapObjectManager != null) { beatmapObjectManager.noteWasMissedEvent += OnNoteMiss; beatmapObjectManager.noteWasCutEvent += OnNoteCut; } }
internal override void Init(CountersData data, Vector3 position) { beatmapObjectManager = data.BOM; beatmapObjectManager.noteWasCutEvent += OnNoteCut; beatmapObjectManager.noteWasMissedEvent += OnNoteMiss; notesLeft = data.GCSSD.difficultyBeatmap.beatmapData.notesCount; TextHelper.CreateText(out counter, position - new Vector3(0, 0.4f, 0)); counter.text = $"Notes Remaining {notesLeft}"; counter.fontSize = 3f; counter.color = Color.white; counter.alignment = TextAlignmentOptions.Center; if (settings.LabelAboveCount) { counter.fontSize = 4; counter.text = notesLeft.ToString(); GameObject labelGO = new GameObject("Counters+ | Notes Left Label"); labelGO.transform.parent = transform; TextHelper.CreateText(out TMP_Text label, position); label.text = "Notes Remaining"; label.fontSize = 3; label.color = Color.white; label.alignment = TextAlignmentOptions.Center; } }
internal static IEnumerator DelayedStart(BeatmapObjectSpawnController beatmapObjectSpawnController) { yield return(new WaitForEndOfFrame()); BeatmapObjectSpawnController = beatmapObjectSpawnController; // prone to breaking if anything else implements these interfaces BeatmapObjectManager beatmapObjectManager = _beatmapObjectSpawnAccessor(ref beatmapObjectSpawnController) as BeatmapObjectManager; BeatmapObjectCallbackController coreSetup = _callbackControllerAccessor(ref beatmapObjectSpawnController) as BeatmapObjectCallbackController; IAudioTimeSource = _audioTimeSourceAccessor(ref coreSetup); IReadonlyBeatmapData beatmapData = _beatmapDataAccessor(ref coreSetup); beatmapObjectManager.noteWasCutEvent -= NoteColorizer.ColorizeSaber; beatmapObjectManager.noteWasCutEvent += NoteColorizer.ColorizeSaber; if (Harmony.HasAnyPatches(HARMONYID)) { if (beatmapData is CustomBeatmapData customBeatmap) { if (ChromaConfig.Instance.EnvironmentEnhancementsEnabled) { EnvironmentEnhancementManager.Init(customBeatmap, beatmapObjectSpawnController.noteLinesDistance); } } // please let me kill legacy LegacyLightHelper.Activate(beatmapData.beatmapEventsData); } }
private void gameSongController_songDidFinishEvent() { //Reset the gameEnergyCounter death by obstacle value _oldObstacleEnergyDrainPerSecond = gameEnergyCounter.GetField <float>("_obstacleEnergyDrainPerSecond"); gameEnergyCounter.SetField("_obstacleEnergyDrainPerSecond", 0f); //Rehook the functions in the energy counter that watch note events beatmapObjectManager = gameEnergyCounter.GetField <BeatmapObjectManager>("_beatmapObjectManager"); beatmapObjectManager.noteWasMissedEvent += gameEnergyCounter.HandleNoteWasMissedEvent; beatmapObjectManager.noteWasMissedEvent -= beatmapObjectManager_noteWasMissedEvent; beatmapObjectManager.noteWasCutEvent += gameEnergyCounter.HandleNoteWasCutEvent; beatmapObjectManager.noteWasCutEvent -= beatmapObjectManager_noteWasCutEvent; //Rehook the level end event gameSongController.songDidFinishEvent += standardLevelGameplayManager.HandleSongDidFinish; gameSongController.songDidFinishEvent -= gameSongController_songDidFinishEvent; if (_wouldHaveFailed) { standardLevelGameplayManager.HandleGameEnergyDidReach0(); } standardLevelGameplayManager.HandleSongDidFinish(); }
public NsvController(BeatmapObjectManager beatmapObjectManager, Factories.NsvBlockFactory blockFactory, SiraLog logger) { _config = PluginConfig.Instance; _logger = logger; _beatmapObjectManager = beatmapObjectManager; _slicedBlockPool = new NsvSlicedBlock[MaxItems]; _blockFactory = blockFactory; }
private static bool GetHiddenForType(BeatmapObjectManager beatmapObjectManager) { if (beatmapObjectManager is BasicBeatmapObjectManager) { return(true); } return(beatmapObjectManager.spawnHidden); }
public void GetControllers() { DismissGraph(null); levelOk = false; averageHitValue = 0.0f; averageHitValueSize = 0; secondaryAverageHitValue = 0.0f; secondaryAverageHitValueSize = 0; energyList.Clear(); secondaryEnergyList.Clear(); misses.Clear(); if (PluginConfig.Instance.mode == PluginConfig.MeasurementMode.Energy) { energyList.Add(new Pair <float, float>(0.0f, 0.5f)); } if (PluginConfig.Instance.secondaryMode == PluginConfig.MeasurementMode.Energy) { secondaryEnergyList.Add(new Pair <float, float>(0.0f, 0.5f)); } scoreController = Resources.FindObjectsOfTypeAll <ScoreController>().LastOrDefault(); ComboUIController comboUIController = Resources.FindObjectsOfTypeAll <ComboUIController>().LastOrDefault(); energyCounter = Resources.FindObjectsOfTypeAll <GameEnergyCounter>().LastOrDefault(); rankCounter = Resources.FindObjectsOfTypeAll <RelativeScoreAndImmediateRankCounter>().LastOrDefault(); audioController = Resources.FindObjectsOfTypeAll <AudioTimeSyncController>().LastOrDefault(); endActions = Resources.FindObjectsOfTypeAll <StandardLevelGameplayManager>().LastOrDefault(); if (endActions == null) { endActions = Resources.FindObjectsOfTypeAll <MissionLevelGameplayManager>().LastOrDefault(); } if (endActions != null && scoreController != null && energyCounter != null && rankCounter != null && audioController != null && comboUIController != null) { objectManager = (BeatmapObjectManager)_beatmapObjectManager.GetValue(scoreController); comboController = (ComboController)_comboController.GetValue(comboUIController); objectManager.noteWasCutEvent += NoteHit; objectManager.noteWasMissedEvent += NoteMiss; comboController.comboBreakingEventHappenedEvent += ComboBreak; endActions.levelFinishedEvent += LevelFinished; endActions.levelFailedEvent += LevelFinished; Logger.log.Debug("PerformanceMeter reloaded successfully"); } else { Logger.log.Error("Could not reload PerformanceMeter. This may occur when playing online - if so, disregard this message."); scoreController = null; objectManager = null; comboController = null; energyCounter = null; rankCounter = null; audioController = null; endActions = null; } }
void GameSceneLeft() { if (beatmapObjectManager) { beatmapObjectManager.noteWasSpawnedEvent -= OnNoteSpawned; beatmapObjectManager = null; } HarmonyPatches.GameNoteController_HandleCut.sabers = null; HarmonyPatches.GameNoteController_HandleCut.spawner = null; }
public BSEvents([InjectOptional] ILevelEndActions levelEndActions, IReadonlyBeatmapData beatmapData, ObstacleSaberSparkleEffectManager obstacleSaberSparkleEffectManager, ScoreController scoreController, BeatmapObjectManager beatmapObjectManager, BeatmapCallbacksController beatmapCallbacksController, ComboController comboController) { _levelEndActions = levelEndActions; _beatmapData = beatmapData; _obstacleSaberSparkleEffectManager = obstacleSaberSparkleEffectManager; _scoreController = scoreController; _beatmapObjectManager = beatmapObjectManager; _beatmapCallbacksController = beatmapCallbacksController; _comboController = comboController; _bombSubtypeIdentifier = NoteData.SubtypeIdentifier(ColorType.None); }
// printing char each cycle -> going into serial monitor (Arduino IDE) -> enabling timestamps => Subtract earlier time from newer time. void Awake() { _spawnController = FindObjectOfType <BeatmapObjectManager>(); Plugin.log.Notice("Initializing.."); Plugin.log.Notice(Settings.instance.EventChoice); BSEvents.gameSceneActive += OnGameSceneActive; BSEvents.songPaused += OnSongPaused; BSEvents.songUnpaused += OnSongUnpaused; Ec = Resources.FindObjectsOfTypeAll <BeatmapObjectCallbackController>().FirstOrDefault(); Cm = Resources.FindObjectsOfTypeAll <ColorManager>().LastOrDefault(); BMD = Resources.FindObjectsOfTypeAll <BeatmapLevelSO>().FirstOrDefault(); if (Settings.instance.EventChoice == "noteCuts") { Plugin.log.Info("Adding event listner to noteCuts"); _spawnController.noteWasCutEvent += OnNoteCut; //Flash on note cuts } if (Settings.instance.EventChoice == "lightEvents") { Plugin.log.Info("Adding event listner to lightEvents"); Ec.beatmapEventDidTriggerEvent += EventHappened; //Flash on map's light events } BSEvents.menuSceneActive += menuSceneActive; C1 = Cm.ColorForNoteType(NoteType.NoteB); redLeft = Mathf.RoundToInt(C1.r * 255); greenLeft = Mathf.RoundToInt(C1.g * 255); blueLeft = Mathf.RoundToInt(C1.b * 255); C2 = Cm.ColorForNoteType(NoteType.NoteA); redRight = Mathf.RoundToInt(C2.r * 255); greenRight = Mathf.RoundToInt(C2.g * 255); blueRight = Mathf.RoundToInt(C2.b * 255); BPM = (int)BMD.beatsPerMinute; //Not used, may come useful in future Plugin.log.Info(" BPM = " + BPM.ToString()); if (Settings.arduinoPort.IsOpen) { if (Settings.instance.RainbowMode) { StartRainbowMode(Settings.arduinoPort); } else { Plugin.log.Info("Sending Color to arduino..."); SendColorToArduino(Settings.arduinoPort); } } }
public CountersData() { BOM = Resources.FindObjectsOfTypeAll <BeatmapObjectManager>().First(); ScoreController = Resources.FindObjectsOfTypeAll <ScoreController>().First(); PlayerController = Resources.FindObjectsOfTypeAll <PlayerController>().First(); AudioTimeSyncController = Resources.FindObjectsOfTypeAll <AudioTimeSyncController>().First(); PlayerData = Resources.FindObjectsOfTypeAll <PlayerDataModel>().First(); ModifiersData = Resources.FindObjectsOfTypeAll <GameplayModifiersModelSO>().First(); GCSSD = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData; //By the time all of these load, so should GCSSD. Is360Or90Level = Resources.FindObjectsOfTypeAll <FlyingGameHUDRotation>().Any(x => x.isActiveAndEnabled); }
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter private static bool Prefix(BeatmapObjectManager __instance, NoteController noteController, NoteCutInfo noteCutInfo) #pragma warning restore SA1313 // Parameter names should begin with lower-case letter { if (!FakeNoteHelper.GetFakeNote(noteController)) { NoteCutCoreEffectsSpawnerStart.NoteCutCoreEffectsSpawner.HandleNoteWasCut(noteController, noteCutInfo); _despawnMethod.Invoke(__instance, new object[] { noteController }); return(false); } return(true); }
private void GameSceneLoaded() { PlayerDataModel dataModel = UnityEngine.Resources.FindObjectsOfTypeAll <PlayerDataModel>().FirstOrDefault(); if (!ConfigHelper.Config.Enabled || (dataModel?.playerData.playerSpecificSettings.noTextsAndHuds ?? false)) { return; } _colorManager = GameObject.FindObjectOfType <ColorManager>(); _spawnController = GameObject.FindObjectOfType <BeatmapObjectManager>(); _spawnController.noteWasCutEvent += OnNoteCut; _parentCanvas = GameObject.Instantiate(AssetBundleHelper.Canvas).transform; if (TwoNoteMode) { _sliceControllers = new SliceController[2]; float minX = -Separation * 0.5f; for (int x = 0; x < 2; ++x) { int index = x; float posX = minX + (Separation * x); float posY = 0f; SliceController controller = CreateSliceController(posX, posY); Color color = UseCustomNoteColors ? _colorManager.ColorForNoteType((NoteType)index) : _defaultColors[index]; controller.UpdateBlockColor(color); _sliceControllers[index] = controller; } } else { _sliceControllers = new SliceController[12]; float minX = -Separation * 1.5f; for (int x = 0; x < 4; ++x) { for (int y = 0; y < 3; ++y) { int index = 3 * x + y; float posX = minX + (Separation * x); float posY = (Separation * y); _sliceControllers[index] = CreateSliceController(posX, posY); } } } _parentCanvas.localPosition = Position; _parentCanvas.eulerAngles = Rotation; _parentCanvas.localScale *= Scale; }
public void Init(OnlinePlayerController newOwner, OnlineAudioTimeController syncController) { BeatmapObjectManager original = FindObjectsOfType <BeatmapObjectManager>().First(x => !(x is OnlineBeatmapObjectManager)); transform.position = original.transform.position; foreach (FieldInfo info in original.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic).Where(x => !x.Name.ToLower().Contains("event"))) { info.SetValue(this, info.GetValue(original)); } owner = newOwner; onlineSyncController = syncController; _localPlayer = FindObjectsOfType <PlayerController>().First(x => !(x is OnlinePlayerController)); _localSyncController = FindObjectsOfType <AudioTimeSyncController>().First(x => !(x is OnlineAudioTimeController)); }
internal override void Init(CountersData data, Vector3 position) { string iniValue = FormatLabel(0, 0, settings.AveragePrecision); Vector3 leftOffset; // Added this so you don't have to change position after creating the text TextAlignmentOptions leftAlign; _RankObject = new GameObject("Counters+ | Cut Label"); _RankObject.transform.parent = transform; beatmapObjectManager = data.BOM; TextHelper.CreateText(out cutLabel, position); cutLabel.text = "Average Cut"; cutLabel.fontSize = 3; cutLabel.color = Color.white; cutLabel.alignment = TextAlignmentOptions.Center; if (settings.SeparateSaberCounts) { TextHelper.CreateText(out cutCounterRight, position - new Vector3(-0.2f, 0.2f, 0)); cutCounterRight.fontSize = 4; cutCounterRight.color = Color.white; cutCounterRight.lineSpacing = -26; cutCounterRight.text = settings.SeparateCutValues ? $"{iniValue}\n{iniValue}\n{iniValue}" : $"{iniValue}"; cutCounterRight.alignment = TextAlignmentOptions.TopLeft; leftOffset = new Vector3(0.2f, 0.2f, 0); leftAlign = TextAlignmentOptions.TopRight; } else { leftOffset = new Vector3(0, 0.2f, 0); leftAlign = TextAlignmentOptions.Top; } TextHelper.CreateText(out cutCounterLeft, position - leftOffset); cutCounterLeft.fontSize = 4; cutCounterLeft.color = Color.white; cutCounterLeft.lineSpacing = -26; cutCounterLeft.text = settings.SeparateCutValues ? $"{iniValue}\n{iniValue}\n{iniValue}" : $"{iniValue}"; cutCounterLeft.alignment = leftAlign; if (beatmapObjectManager != null) { beatmapObjectManager.noteWasCutEvent += UpdateScore; } }
public BSEvents(BeatmapObjectManager beatmapObjectManager, GameEnergyCounter gameEnergyCounter, GameplayCoreSceneSetupData gameplayCoreSceneSetupData, ObstacleSaberSparkleEffectManager obstacleSaberSparkleEffectManager, ScoreController scoreController, PlayerDataModel playerDataModel, PrepareLevelCompletionResults prepareLevelCompletionResults, IBeatmapObjectCallbackController beatmapObjectCallbackController, IDifficultyBeatmap difficultyBeatmap) { _beatmapObjectManager = beatmapObjectManager; _gameEnergyCounter = gameEnergyCounter; _gameplayCoreSceneSetupData = gameplayCoreSceneSetupData; _obstacleSaberSparkleEffectManager = obstacleSaberSparkleEffectManager; _scoreController = scoreController; _playerDataModel = playerDataModel; _prepareLevelCompletionResults = prepareLevelCompletionResults; _beatmapObjectCallbackController = beatmapObjectCallbackController; _difficultyBeatmap = difficultyBeatmap; }
void DismissGraph(ResultsViewController vc) { if (panel != null) { panel.SetActive(false); Destroy(panel, 1); panel = null; scoreController = null; objectManager = null; comboController = null; energyCounter = null; rankCounter = null; audioController = null; endActions = null; } if (vc != null) { vc.continueButtonPressedEvent -= DismissGraph; vc.restartButtonPressedEvent -= DismissGraph; } }
static bool Prefix(BeatmapObjectManager __instance, NoteController noteController) { try { if (Config.Instance.SpectatorMode && SpectatingController.Instance != null && SpectatingController.active && Client.Instance != null && Client.Instance.connected && SpectatingController.Instance.spectatedPlayer != null && SpectatingController.Instance.spectatedPlayer.playerInfo != null) { ulong playerId = SpectatingController.Instance.spectatedPlayer.playerInfo.playerId; if (SpectatingController.Instance.playerUpdates.ContainsKey(playerId) && SpectatingController.Instance.playerUpdates[playerId].hits.Count > 0) { if (SpectatingController.Instance.playerUpdates[playerId].hits.TryGetValue(noteController.noteData.id, out HitData hit)) { if (hit.noteWasCut) { #if DEBUG Plugin.log.Warn("We missed the note, but the player cut it"); #endif __instance.Despawn(noteController); return(false); } else { return(true); } } } return(true); } else { return(true); } } catch (Exception e) { Plugin.log.Error("Exception in Harmony patch BeatmapObjectSpawnController.NoteWasMissed: " + e); return(true); } }
internal static IEnumerator DelayedStart(BeatmapObjectSpawnController beatmapObjectSpawnController) { yield return(new WaitForEndOfFrame()); BeatmapObjectSpawnController = beatmapObjectSpawnController; // prone to breaking if anything else implements these interfaces BeatmapObjectManager beatmapObjectManager = (BeatmapObjectManager)_beatmapObjectSpawnAccessor(ref beatmapObjectSpawnController); BeatmapObjectCallbackController coreSetup = (BeatmapObjectCallbackController)_callbackControllerAccessor(ref beatmapObjectSpawnController); IAudioTimeSource = _audioTimeSourceAccessor(ref coreSetup); IReadonlyBeatmapData beatmapData = _beatmapDataAccessor(ref coreSetup); beatmapObjectManager.noteWasCutEvent -= NoteColorizer.ColorizeSaber; beatmapObjectManager.noteWasCutEvent += NoteColorizer.ColorizeSaber; if (ChromaIsActive) { if (beatmapData is CustomBeatmapData customBeatmap) { if (ChromaConfig.Instance !.EnvironmentEnhancementsEnabled) { EnvironmentEnhancementManager.Init(customBeatmap, beatmapObjectSpawnController.noteLinesDistance); } } try { // please let me kill legacy LegacyLightHelper.Activate(beatmapData.beatmapEventsData); } catch (System.Exception e) { Plugin.Logger.Log("Could not run Legacy Chroma Lights"); Plugin.Logger.Log(e); } } }
public EventPlayerInterface( PluginConfig pluginConfig, [Inject(Id = "LastNoteId")] float lastNoteTime, ObstacleSaberSparkleEffectManager obstacleSaberSparkleEffectManager, GameEnergyCounter energyCounter, ScoreController scoreController, BeatmapObjectManager beatmapObjectManager) { _pluginConfig = pluginConfig; _lastNoteTime = lastNoteTime; _obstacleSaberSparkleEffectManager = obstacleSaberSparkleEffectManager; _energyCounter = energyCounter; _scoreController = scoreController; _beatmapObjectManager = beatmapObjectManager; _partEventsList = new List <PartEvents>(); if (!_pluginConfig.EnableEvents) { return; } // OnSlice LevelEnded Combobreak _beatmapObjectManager.noteWasCutEvent += OnNoteCut; _beatmapObjectManager.noteWasMissedEvent += OnNoteMiss; // Sabers clashing _obstacleSaberSparkleEffectManager.sparkleEffectDidStartEvent += SaberStartCollide; _obstacleSaberSparkleEffectManager.sparkleEffectDidEndEvent += SaberEndCollide; // OnLevelFail _energyCounter.gameEnergyDidReach0Event += InvokeOnLevelFail; // MultiplierUp _scoreController.multiplierDidChangeEvent += MultiplayerDidChange; // Combo changed _scoreController.comboDidChangeEvent += InvokeComboChanged; }
IEnumerator WaitForLoad() { while (!loaded) { var playerHeadAndObstacleInteraction = Resources.FindObjectsOfTypeAll <ScoreController>().FirstOrDefault()?.GetField <PlayerHeadAndObstacleInteraction, ScoreController>("_playerHeadAndObstacleInteraction"); beatmapObjectManager = playerHeadAndObstacleInteraction?.GetField <BeatmapObjectManager, PlayerHeadAndObstacleInteraction>("_beatmapObjectManager"); saberManager = Resources.FindObjectsOfTypeAll <SaberManager>().FirstOrDefault(); if (beatmapObjectManager == null || saberManager == null) { yield return(new WaitForSeconds(0.1f)); } else { loaded = true; } } yield return(new WaitForSeconds(0.1f)); sabers = new Saber[2]; sabers[0] = saberManager.leftSaber; sabers[1] = saberManager.rightSaber; }
internal override void Init(CountersData data, Vector3 position) { beatmapObjectManager = data.BOM; TextHelper.CreateText(out counterText, position - new Vector3(0, 0.4f, 0)); counterText.text = settings.ShowPercentage ? "0 / 0 - (100%)" : "0 / 0"; counterText.fontSize = 4; counterText.color = Color.white; counterText.alignment = TextAlignmentOptions.Center; GameObject labelGO = new GameObject("Counters+ | Notes Label"); labelGO.transform.parent = transform; TextHelper.CreateText(out TMP_Text label, position); label.text = "Notes"; label.fontSize = 3; label.color = Color.white; label.alignment = TextAlignmentOptions.Center; if (beatmapObjectManager != null) { beatmapObjectManager.noteWasCutEvent += OnNoteCut; beatmapObjectManager.noteWasMissedEvent += OnNoteMiss; } }
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; }
static bool Prefix(BeatmapObjectManager __instance, NoteController noteController, NoteCutInfo noteCutInfo) { try { if (Config.Instance.SpectatorMode && SpectatingController.Instance != null && SpectatingController.active && Client.Instance != null && Client.Instance.connected && SpectatingController.Instance.spectatedPlayer != null && SpectatingController.Instance.spectatedPlayer.playerInfo != null) { ulong playerId = SpectatingController.Instance.spectatedPlayer.playerInfo.playerId; if (SpectatingController.Instance.playerUpdates.ContainsKey(playerId) && SpectatingController.Instance.playerUpdates[playerId].hits.Count > 0) { if (SpectatingController.Instance.playerUpdates[playerId].hits.TryGetValue(noteController.noteData.id, out HitData hit)) { bool allIsOKExpected = hit.noteWasCut && hit.speedOK && hit.saberTypeOK && hit.directionOK && !hit.wasCutTooSoon; if (hit.noteWasCut) { if (noteCutInfo.allIsOK == allIsOKExpected) { return(true); } else if (!noteCutInfo.allIsOK && allIsOKExpected) { #if DEBUG Plugin.log.Warn("Oopsie, we missed it, let's forget about that"); #endif __instance.Despawn(noteController); return(false); } else if (noteCutInfo.allIsOK && !allIsOKExpected) { #if DEBUG Plugin.log.Warn("We cut the note, but the player cut it wrong"); #endif noteCutInfo.SetProperty("wasCutTooSoon", hit.wasCutTooSoon); noteCutInfo.SetProperty("directionOK", hit.directionOK); noteCutInfo.SetProperty("saberTypeOK", hit.saberTypeOK); noteCutInfo.SetProperty("speedOK", hit.speedOK); return(true); } } else { #if DEBUG Plugin.log.Warn("We cut the note, but the player missed it"); #endif __instance.HandleNoteWasMissed(noteController); return(false); } } } return(true); } else { return(true); } }catch (Exception e) { Plugin.log.Error("Exception in Harmony patch BeatmapObjectSpawnController.NoteWasCut: " + e); return(true); } }
public async void HandleSongStart() { // Check if level data is actually available in BS_Utils before proceeding further. It isn't available in the tutorial if (!BS_Utils.Plugin.LevelData.IsSet) { Plugin.log.Debug("BS_Utils level data is not present. Probably due to the tutorial being active."); return; } GameStatus gameStatus = statusManager.gameStatus; // Check for multiplayer early to abort if needed: gameplay controllers don't exist in multiplayer until later multiplayerSessionManager = FindFirstOrDefaultOptional <MultiplayerSessionManager>(); multiplayerController = FindFirstOrDefaultOptional <MultiplayerController>(); if (multiplayerSessionManager && multiplayerController) { Plugin.log.Debug("Multiplayer Level loaded"); // public event Action<DisconnectedReason> MultiplayerSessionManager#disconnectedEvent; multiplayerSessionManager.disconnectedEvent += OnMultiplayerDisconnected; // public event Action<State> MultiplayerController#stateChangedEvent; multiplayerController.stateChangedEvent += OnMultiplayerStateChanged; // Do nothing until the next state change to Gameplay. if (multiplayerController.state != MultiplayerController.State.Gameplay) { return; } multiplayerLocalActivePlayerFacade = FindFirstOrDefaultOptional <MultiplayerLocalActivePlayerFacade>(); if (multiplayerLocalActivePlayerFacade != null) { multiplayerLocalActivePlayerFacade.playerDidFinishEvent += OnMultiplayerLevelFinished; } } else if (!doDelayedSongStart) { doDelayedSongStart = true; return; } // `wants_to_play_next_level` is set for players who don't want to play the song aka want to spectate aka are not "active". `isSpectating` is apparently not spectating. gameStatus.scene = multiplayerSessionManager.isSpectating || !multiplayerSessionManager.LocalPlayerHasState(NetworkConstants.wantsToPlayNextLevel) ? "Spectator" : "Song"; gameStatus.multiplayer = multiplayerSessionManager.isConnectingOrConnected; pauseController = FindFirstOrDefaultOptional <PauseController>(); scoreController = FindWithMultiplayerFix <ScoreController>(); beatmapObjectManager = (BeatmapObjectManager)scoreControllerBeatmapObjectManagerField.GetValue(scoreController); gameplayManager = FindFirstOrDefaultOptional <StandardLevelGameplayManager>() as MonoBehaviour ?? FindFirstOrDefaultOptional <MissionLevelGameplayManager>(); beatmapObjectCallbackController = FindWithMultiplayerFix <BeatmapObjectCallbackController>(); gameplayModifiersSO = FindFirstOrDefault <GameplayModifiersModelSO>(); audioTimeSyncController = FindWithMultiplayerFix <AudioTimeSyncController>(); playerHeadAndObstacleInteraction = (PlayerHeadAndObstacleInteraction)scoreControllerHeadAndObstacleInteractionField.GetValue(scoreController); gameSongController = FindWithMultiplayerFix <GameSongController>(); gameEnergyCounter = FindWithMultiplayerFix <GameEnergyCounter>(); if (multiplayerController) { // NOOP } else if (gameplayManager is StandardLevelGameplayManager) { Plugin.log.Debug("Standard Level loaded"); } else if (gameplayManager is MissionLevelGameplayManager) { Plugin.log.Debug("Mission Level loaded"); } gameplayCoreSceneSetupData = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData; // Register event listeners // PauseController doesn't exist in multiplayer if (pauseController != null) { // public event Action PauseController#didPauseEvent; pauseController.didPauseEvent += OnGamePause; // public event Action PauseController#didResumeEvent; pauseController.didResumeEvent += OnGameResume; } // public ScoreController#noteWasCutEvent<NoteData, NoteCutInfo, int multiplier> // called after CutScoreBuffer is created scoreController.noteWasCutEvent += OnNoteWasCut; // public ScoreController#noteWasMissedEvent<NoteData, int multiplier> scoreController.noteWasMissedEvent += OnNoteWasMissed; // public ScoreController#scoreDidChangeEvent<int, int> // score scoreController.scoreDidChangeEvent += OnScoreDidChange; // public ScoreController#comboDidChangeEvent<int> // combo scoreController.comboDidChangeEvent += OnComboDidChange; // public ScoreController#multiplierDidChangeEvent<int, float> // multiplier, progress [0..1] scoreController.multiplierDidChangeEvent += OnMultiplierDidChange; beatmapObjectManager.noteWasSpawnedEvent += OnNoteWasSpawned; // public event Action<BeatmapEventData> BeatmapObjectCallbackController#beatmapEventDidTriggerEvent beatmapObjectCallbackController.beatmapEventDidTriggerEvent += OnBeatmapEventDidTrigger; // public event Action GameSongController#songDidFinishEvent; gameSongController.songDidFinishEvent += OnLevelFinished; // public event Action GameEnergyCounter#gameEnergyDidReach0Event; gameEnergyCounter.gameEnergyDidReach0Event += OnEnergyDidReach0Event; if (gameplayManager is ILevelEndActions levelEndActions) { // event Action levelFailedEvent; levelEndActions.levelFailedEvent += OnLevelFailed; } IDifficultyBeatmap diff = gameplayCoreSceneSetupData.difficultyBeatmap; IBeatmapLevel level = diff.level; gameStatus.partyMode = Gamemode.IsPartyActive; gameplayModifiers = gameplayCoreSceneSetupData.gameplayModifiers; gameplayModiferParamsList = gameplayModifiersSO.CreateModifierParamsList(gameplayModifiers); PlayerSpecificSettings playerSettings = gameplayCoreSceneSetupData.playerSpecificSettings; PracticeSettings practiceSettings = gameplayCoreSceneSetupData.practiceSettings; float songSpeedMul = gameplayModifiers.songSpeedMul; if (practiceSettings != null) { songSpeedMul = practiceSettings.songSpeedMul; } int beatmapObjectId = 0; var beatmapObjectsData = diff.beatmapData.beatmapObjectsData; // Generate NoteData to id mappings for backwards compatiblity with <1.12.1 noteToIdMapping = new NoteData[beatmapObjectsData.Count(obj => obj is NoteData)]; lastNoteId = 0; foreach (BeatmapObjectData beatmapObjectData in beatmapObjectsData) { if (beatmapObjectData is NoteData noteData) { noteToIdMapping[beatmapObjectId++] = noteData; } } gameStatus.songName = level.songName; gameStatus.songSubName = level.songSubName; gameStatus.songAuthorName = level.songAuthorName; gameStatus.levelAuthorName = level.levelAuthorName; gameStatus.songBPM = level.beatsPerMinute; gameStatus.noteJumpSpeed = diff.noteJumpMovementSpeed; gameStatus.noteJumpStartBeatOffset = diff.noteJumpStartBeatOffset; // 13 is "custom_level_" and 40 is the magic number for the length of the SHA-1 hash gameStatus.songHash = Regex.IsMatch(level.levelID, "^custom_level_[0-9A-F]{40}", RegexOptions.IgnoreCase) && !level.levelID.EndsWith(" WIP") ? level.levelID.Substring(13, 40) : null; gameStatus.levelId = level.levelID; gameStatus.songTimeOffset = (long)(level.songTimeOffset * 1000f / songSpeedMul); gameStatus.length = (long)(level.beatmapLevelData.audioClip.length * 1000f / songSpeedMul); gameStatus.start = GetCurrentTime() - (long)(audioTimeSyncController.songTime * 1000f / songSpeedMul); if (practiceSettings != null) { gameStatus.start -= (long)(practiceSettings.startSongTime * 1000f / songSpeedMul); } gameStatus.paused = 0; gameStatus.difficulty = diff.difficulty.Name(); gameStatus.difficultyEnum = Enum.GetName(typeof(BeatmapDifficulty), diff.difficulty); gameStatus.characteristic = diff.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName; gameStatus.notesCount = diff.beatmapData.cuttableNotesCount; gameStatus.bombsCount = diff.beatmapData.bombsCount; gameStatus.obstaclesCount = diff.beatmapData.obstaclesCount; gameStatus.environmentName = level.environmentInfo.sceneInfo.sceneName; ColorScheme colorScheme = gameplayCoreSceneSetupData.colorScheme ?? new ColorScheme(gameplayCoreSceneSetupData.environmentInfo.colorScheme); gameStatus.colorSaberA = colorScheme.saberAColor; gameStatus.colorSaberB = colorScheme.saberBColor; gameStatus.colorEnvironment0 = colorScheme.environmentColor0; gameStatus.colorEnvironment1 = colorScheme.environmentColor1; if (colorScheme.supportsEnvironmentColorBoost) { gameStatus.colorEnvironmentBoost0 = colorScheme.environmentColor0Boost; gameStatus.colorEnvironmentBoost1 = colorScheme.environmentColor1Boost; } gameStatus.colorObstacle = colorScheme.obstaclesColor; try { // From https://support.unity3d.com/hc/en-us/articles/206486626-How-can-I-get-pixels-from-unreadable-textures- // Modified to correctly handle texture atlases. Fixes #82. var active = RenderTexture.active; var sprite = await level.GetCoverImageAsync(CancellationToken.None); var texture = sprite.texture; var temporary = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear); Graphics.Blit(texture, temporary); RenderTexture.active = temporary; var spriteRect = sprite.rect; var uv = sprite.uv[0]; var cover = new Texture2D((int)spriteRect.width, (int)spriteRect.height); // Unity sucks. The coordinates of the sprite on its texture atlas are only accessible through the Sprite.uv property since rect always returns `x=0,y=0`, so we need to convert them back into texture space. cover.ReadPixels(new Rect( uv.x * texture.width, texture.height - uv.y * texture.height, spriteRect.width, spriteRect.height ), 0, 0); cover.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); gameStatus.songCover = System.Convert.ToBase64String(ImageConversion.EncodeToPNG(cover)); } catch { gameStatus.songCover = null; } gameStatus.ResetPerformance(); UpdateModMultiplier(); gameStatus.songSpeedMultiplier = songSpeedMul; gameStatus.batteryLives = gameEnergyCounter.batteryLives; gameStatus.modObstacles = gameplayModifiers.enabledObstacleType.ToString(); gameStatus.modInstaFail = gameplayModifiers.instaFail; gameStatus.modNoFail = gameplayModifiers.noFailOn0Energy; gameStatus.modBatteryEnergy = gameplayModifiers.energyType == GameplayModifiers.EnergyType.Battery; gameStatus.modDisappearingArrows = gameplayModifiers.disappearingArrows; gameStatus.modNoBombs = gameplayModifiers.noBombs; gameStatus.modSongSpeed = gameplayModifiers.songSpeed.ToString(); gameStatus.modNoArrows = gameplayModifiers.noArrows; gameStatus.modGhostNotes = gameplayModifiers.ghostNotes; gameStatus.modFailOnSaberClash = gameplayModifiers.failOnSaberClash; gameStatus.modStrictAngles = gameplayModifiers.strictAngles; gameStatus.modFastNotes = gameplayModifiers.fastNotes; gameStatus.modSmallNotes = gameplayModifiers.smallCubes; gameStatus.modProMode = gameplayModifiers.proMode; gameStatus.modZenMode = gameplayModifiers.zenMode; var environmentEffectsFilterPreset = diff.difficulty == BeatmapDifficulty.ExpertPlus ? playerSettings.environmentEffectsFilterExpertPlusPreset : playerSettings.environmentEffectsFilterDefaultPreset; // Backwards compatibility for <1.13.4 gameStatus.staticLights = environmentEffectsFilterPreset != EnvironmentEffectsFilterPreset.AllEffects; gameStatus.leftHanded = playerSettings.leftHanded; gameStatus.playerHeight = playerSettings.playerHeight; gameStatus.sfxVolume = playerSettings.sfxVolume; gameStatus.reduceDebris = playerSettings.reduceDebris; gameStatus.noHUD = playerSettings.noTextsAndHuds; gameStatus.advancedHUD = playerSettings.advancedHud; gameStatus.autoRestart = playerSettings.autoRestart; gameStatus.saberTrailIntensity = playerSettings.saberTrailIntensity; gameStatus.environmentEffects = environmentEffectsFilterPreset.ToString(); gameStatus.hideNoteSpawningEffect = playerSettings.hideNoteSpawnEffect; statusManager.EmitStatusUpdate(ChangedProperties.AllButNoteCut, "songStart"); }
private void CleanUpSong() { statusManager.gameStatus.ResetMapInfo(); statusManager.gameStatus.ResetPerformance(); noteControllerMapping.Clear(); // Release references for AfterCutScoreBuffers that don't resolve due to player leaving the map before finishing. foreach (var noteCutItem in noteCutMapping) { // CutScoreBuffers are pooled. Remove the event listener just in case it never fires the event. noteCutItem.Key.didFinishEvent.Remove(this); } noteCutMapping.Clear(); // Clear note id mappings. noteToIdMapping = null; if (pauseController != null) { pauseController.didPauseEvent -= OnGamePause; pauseController.didResumeEvent -= OnGameResume; pauseController = null; } if (scoreController != null) { scoreController.noteWasCutEvent -= OnNoteWasCut; scoreController.noteWasMissedEvent -= OnNoteWasMissed; scoreController.scoreDidChangeEvent -= OnScoreDidChange; scoreController.comboDidChangeEvent -= OnComboDidChange; scoreController.multiplierDidChangeEvent -= OnMultiplierDidChange; scoreController = null; } if (beatmapObjectManager != null) { beatmapObjectManager.noteWasSpawnedEvent -= OnNoteWasSpawned; beatmapObjectManager = null; } if (gameplayManager != null) { if (gameplayManager is ILevelEndActions levelEndActions) { // event Action levelFailedEvent; levelEndActions.levelFailedEvent -= OnLevelFailed; } gameplayManager = null; } if (beatmapObjectCallbackController != null) { beatmapObjectCallbackController.beatmapEventDidTriggerEvent -= OnBeatmapEventDidTrigger; beatmapObjectCallbackController = null; } if (gameplayModifiersSO != null) { gameplayModifiersSO = null; } if (audioTimeSyncController != null) { audioTimeSyncController = null; } if (playerHeadAndObstacleInteraction != null) { playerHeadAndObstacleInteraction = null; } if (gameSongController != null) { gameSongController.songDidFinishEvent -= OnLevelFinished; gameSongController = null; } if (gameEnergyCounter != null) { gameEnergyCounter.gameEnergyDidReach0Event -= OnEnergyDidReach0Event; gameEnergyCounter = null; } if (gameplayCoreSceneSetupData != null) { gameplayCoreSceneSetupData = null; } if (gameplayModifiers != null) { gameplayModifiers = null; } if (gameplayModiferParamsList != null) { gameplayModiferParamsList = null; } }
// Ask for the BeatmapObjectManager polietly. The BeatmapObjectManager is a MonoBehaviour that's already injected by the base game. As long as you know it's injected, you can ask for it! public GameManager(BeatmapObjectManager beatmapObjectManager) { _objectManager = beatmapObjectManager; }
public BreaktimeManager(BreaktimeSettings settings, [InjectOptional] IReadonlyBeatmapData readonlyBeatmapData, [InjectOptional] BeatmapObjectManager beatmapObjectManager) { _settings = settings; _readonlyBeatmapData = readonlyBeatmapData; _beatmapObjectManager = beatmapObjectManager; }
internal static IEnumerator DelayedStart() { yield return(new WaitForEndOfFrame()); AudioTimeSyncController = Resources.FindObjectsOfTypeAll <AudioTimeSyncController>().First(); BeatmapObjectSpawnController beatmapObjectSpawnController = Resources.FindObjectsOfTypeAll <BeatmapObjectSpawnController>().First(); BeatmapObjectManager beatmapObjectManager = _beatmapObjectSpawnAccessor(ref beatmapObjectSpawnController) as BeatmapObjectManager; SongBPM = beatmapObjectSpawnController.currentBpm; BeatmapObjectCallbackController coreSetup = Resources.FindObjectsOfTypeAll <BeatmapObjectCallbackController>().First(); IReadonlyBeatmapData beatmapData = coreSetup.GetField <IReadonlyBeatmapData, BeatmapObjectCallbackController>("_beatmapData"); beatmapObjectManager.noteWasCutEvent -= NoteColorizer.ColorizeSaber; beatmapObjectManager.noteWasCutEvent += NoteColorizer.ColorizeSaber; if (ChromaConfig.Instance.LightshowModifier) { foreach (BeatmapLineData b in beatmapData.beatmapLinesData) { BeatmapLineData refBeatmapLineData = b; _beatmapObjectsDataAccessor(ref refBeatmapLineData) = b.beatmapObjectsData.Where((source, index) => b.beatmapObjectsData[index].beatmapObjectType != BeatmapObjectType.Note).ToList(); } foreach (Saber saber in Resources.FindObjectsOfTypeAll <Saber>()) { saber.gameObject.SetActive(false); } BS_Utils.Gameplay.ScoreSubmission.DisableSubmission("Chroma"); if (ChromaConfig.Instance.PlayersPlace) { GameObject.Find("PlayersPlace")?.SetActive(false); } if (ChromaConfig.Instance.Spectrograms) { GameObject.Find("Spectrograms")?.SetActive(false); } if (ChromaConfig.Instance.BackColumns) { GameObject.Find("BackColumns")?.SetActive(false); } if (ChromaConfig.Instance.Buildings) { GameObject.Find("Buildings")?.SetActive(false); } } if (Harmony.HasAnyPatches(HARMONYID)) { if (beatmapData is CustomBeatmapData customBeatmap) { if (ChromaConfig.Instance.EnvironmentEnhancementsEnabled) { // Spaghetti code below until I can figure out a better way of doing this dynamic dynData = customBeatmap.beatmapCustomData; List <object> objectsToKill = Trees.at(dynData, "_environmentRemoval"); if (objectsToKill != null) { IEnumerable <GameObject> gameObjects = Resources.FindObjectsOfTypeAll <GameObject>(); foreach (string s in objectsToKill.Cast <string>()) { if (s == "TrackLaneRing" || s == "BigTrackLaneRing") { foreach (GameObject n in gameObjects.Where(obj => obj.name.Contains(s))) { if (s == "TrackLaneRing" && n.name.Contains("Big")) { continue; } n.SetActive(false); } } else { foreach (GameObject n in gameObjects .Where(obj => obj.name.Contains(s) && (obj.scene.name?.Contains("Environment") ?? false) && (!obj.scene.name?.Contains("Menu") ?? false))) { n.SetActive(false); } } } } } } // please let me kill legacy LegacyLightHelper.Activate(beatmapData.beatmapEventsData); } }