private static void Postfix(IBeatmapObjectSpawner ____beatmapObjectSpawner, BeatmapObjectSpawnMovementData ____beatmapObjectSpawnMovementData) { if (____beatmapObjectSpawner is BasicBeatmapObjectManager basicBeatmapObjectManager) { SpawnDataHelper.InitBeatmapObjectSpawnController(____beatmapObjectSpawnMovementData); } }
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter private static void Postfix(BeatmapObjectSpawnMovementData __instance, Vector3 ____centerPos, float ____jumpDuration, NoteData noteData, ref BeatmapObjectSpawnMovementData.NoteSpawnData __result) #pragma warning restore SA1313 // Parameter names should begin with lower-case letter { if (noteData is CustomNoteData customData) { dynamic dynData = customData.customData; IEnumerable <float?> position = ((List <object>)Trees.at(dynData, POSITION))?.Select(n => n.ToNullableFloat()); float?flipLineIndex = (float?)Trees.at(dynData, "flipLineIndex"); float?njs = (float?)Trees.at(dynData, NOTEJUMPSPEED); float?spawnoffset = (float?)Trees.at(dynData, NOTESPAWNOFFSET); float?startlinelayer = (float?)Trees.at(dynData, "startNoteLineLayer"); bool gravityOverride = (bool?)Trees.at(dynData, NOTEGRAVITYDISABLE) ?? false; float?startRow = position?.ElementAtOrDefault(0); float?startHeight = position?.ElementAtOrDefault(1); float jumpDuration = ____jumpDuration; Vector3 moveStartPos = __result.moveStartPos; Vector3 moveEndPos = __result.moveEndPos; Vector3 jumpEndPos = __result.jumpEndPos; float jumpGravity = __result.jumpGravity; Vector3 noteOffset = GetNoteOffset(noteData, startRow, startlinelayer ?? (float)noteData.startNoteLineLayer); if (position != null || flipLineIndex != null || njs.HasValue || spawnoffset.HasValue || startlinelayer.HasValue || gravityOverride) { GetNoteJumpValues(njs, spawnoffset, out float localJumpDuration, out float localJumpDistance, out Vector3 localMoveStartPos, out Vector3 localMoveEndPos, out Vector3 localJumpEndPos); jumpDuration = localJumpDuration; float localNoteJumpMovementSpeed = njs ?? NoteJumpMovementSpeed; float startLayerLineYPos = LineYPosForLineLayer(noteData, startlinelayer ?? (float)noteData.startNoteLineLayer); float lineYPos = LineYPosForLineLayer(noteData, startHeight); // Magic numbers below found with linear regression y=mx+b using existing HighestJumpPosYForLineLayer values float highestJump = startHeight.HasValue ? (0.875f * lineYPos) + 0.639583f + JumpOffsetY : __instance.HighestJumpPosYForLineLayer(noteData.noteLineLayer); jumpGravity = 2f * (highestJump - (gravityOverride ? lineYPos : startLayerLineYPos)) / Mathf.Pow(localJumpDistance / localNoteJumpMovementSpeed * 0.5f, 2f); jumpEndPos = localJumpEndPos + noteOffset; // IsBasicNote() check is skipped so bombs can flip too Vector3 noteOffset2 = GetNoteOffset(noteData, flipLineIndex ?? startRow, gravityOverride ? startHeight : startlinelayer ?? (float)noteData.startNoteLineLayer); moveStartPos = localMoveStartPos + noteOffset2; moveEndPos = localMoveEndPos + noteOffset2; __result = new BeatmapObjectSpawnMovementData.NoteSpawnData(moveStartPos, moveEndPos, jumpEndPos, jumpGravity, __result.moveDuration, jumpDuration); } // DEFINITE POSITION IS WEIRD, OK? // ty reaxt float startVerticalVelocity = jumpGravity * jumpDuration * 0.5f; float num = jumpDuration * 0.5f; float yOffset = (startVerticalVelocity * num) - (jumpGravity * num * num * 0.5f); dynData.noteOffset = ____centerPos + noteOffset + new Vector3(0, yOffset, 0); } }
private void LoadGameObjects() { levelFailController = Resources.FindObjectsOfTypeAll <StandardLevelFailedController>().LastOrDefault(); spawnController = Resources.FindObjectsOfTypeAll <BeatmapObjectSpawnController>().LastOrDefault(); spawnMovementData = spawnController.GetField <BeatmapObjectSpawnMovementData, BeatmapObjectSpawnController>("_beatmapObjectSpawnMovementData"); callbackController = spawnController.GetField <BeatmapCallbacksController, BeatmapObjectSpawnController>("_beatmapCallbacksController"); soundEffectManager = Resources.FindObjectsOfTypeAll <NoteCutSoundEffectManager>().LastOrDefault(); audioTimeSync = Resources.FindObjectsOfTypeAll <AudioTimeSyncController>().LastOrDefault(); songAudio = audioTimeSync.GetField <AudioSource, AudioTimeSyncController>("_audioSource"); }
public static void SetNJS(BeatmapObjectSpawnController spawnController) { BeatmapObjectSpawnMovementData spawnMovementData = spawnController.GetField <BeatmapObjectSpawnMovementData, BeatmapObjectSpawnController>("_beatmapObjectSpawnMovementData"); var bpm = spawnController.GetField <VariableBpmProcessor, BeatmapObjectSpawnController>("_variableBPMProcessor").currentBpm; spawnMovementData.SetField("_startNoteJumpMovementSpeed", BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap.noteJumpMovementSpeed); spawnMovementData.SetField("_noteJumpStartBeatOffset", BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap.noteJumpStartBeatOffset); spawnMovementData.Update(bpm, spawnController.GetField <float, BeatmapObjectSpawnController>("_jumpOffsetY")); }
private IEnumerator Setup() { yield return(new WaitForSeconds(0.1f)); callbackController = Resources.FindObjectsOfTypeAll <BeatmapObjectCallbackController>().LastOrDefault(); originalSpawnMovementData = GameObjects.spawnController.GetField <BeatmapObjectSpawnMovementData, BeatmapObjectSpawnController>("_beatmapObjectSpawnMovementData"); seManager = Resources.FindObjectsOfTypeAll <NoteCutSoundEffectManager>().LastOrDefault(); progessController = Resources.FindObjectsOfTypeAll <SongProgressUIController>().LastOrDefault(); pauseManager = Resources.FindObjectsOfTypeAll <PauseMenuManager>().LastOrDefault(); // switchTime = 20f; switchTime = GameObjects.songAudio.clip.length - 1f; Task.Run(PrepareNextSong); }
internal static float LineYPosForLineLayer(BeatmapObjectData beatmapObjectData, float?height) { float ypos = BaseLinesYPos; if (height.HasValue) { ypos = (height.Value * NoteLinesDistance) + BaseLinesYPos; // offset by 0.25 } else if (beatmapObjectData is NoteData noteData) { ypos = BeatmapObjectSpawnMovementData.LineYPosForLineLayer(noteData.noteLineLayer); } return(ypos); }
static void Postfix(BeatmapObjectSpawnMovementData __instance, int noteLineIndex, NoteLineLayer noteLineLayer, ref Vector3 __result, ref float ____noteLinesCount, ref float ____noteLinesDistance, Vector3 ____rightVec) { if (!Plugin.active) { return; } if (noteLineIndex >= 1000 || noteLineIndex <= -1000) { if (noteLineIndex <= -1000) { noteLineIndex += 2000; } float num = -(____noteLinesCount - 1f) * 0.5f; num = (num + (((float)noteLineIndex) * (____noteLinesDistance / 1000))); __result = ____rightVec * num + new Vector3(0f, __instance.LineYPosForLineLayer(noteLineLayer), 0f); } // Plugin.log.Info($"NoteOffset Index {noteLineIndex} Layer {(int)noteLineLayer} Final Result {__result}"); }
public static void UpdateSpawnMovementData(float njs, float noteJumpStartBeatOffset) { BeatmapObjectSpawnMovementData spawnMovementData = _spawnController.GetPrivateField <BeatmapObjectSpawnMovementData>("_beatmapObjectSpawnMovementData"); float bpm = _spawnController.GetPrivateField <VariableBpmProcessor>("_variableBpmProcessor").currentBpm; if (adjustNJSWithSpeed) { float newNJS = njs * (1 / TimeScale); njs = newNJS; } spawnMovementData.SetPrivateField("_startNoteJumpMovementSpeed", njs); spawnMovementData.SetPrivateField("_noteJumpStartBeatOffset", noteJumpStartBeatOffset); spawnMovementData.Update(bpm, _spawnController.GetPrivateField <float>("_jumpOffsetY")); }
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 static void Postfix(BeatmapObjectSpawnMovementData __instance) { InitBeatmapObjectSpawnController(__instance); }
internal static void InitBeatmapObjectSpawnController(BeatmapObjectSpawnMovementData beatmapObjectSpawnMovementData) { BeatmapObjectSpawnMovementDataVariables.beatmapObjectSpawnMovementData = beatmapObjectSpawnMovementData; }
static void Postfix(int noteLineIndex, NoteLineLayer noteLineLayer, ref Vector2 __result, ref BeatmapObjectSpawnMovementData __instance, float ____noteLinesCount, float ____noteLinesDistance) { if (!Plugin.active) { return; } float x, y = 0; if (noteLineIndex >= 1000 || noteLineIndex <= -1000) { if (noteLineIndex <= -1000) { noteLineIndex += 2000; } float num = -(____noteLinesCount - 1f) * 0.5f; x = (num + (((float)noteLineIndex) * (____noteLinesDistance / 1000))); y = __instance.LineYPosForLineLayer(noteLineLayer); __result = new Vector2(x, y); } }
public static void Prefix(ref float startNoteJumpMovementSpeed, float startBpm, ref float noteJumpStartBeatOffset, ref BeatmapObjectSpawnMovementData __instance, ref bool __state) { bool WillOverride = BS_Utils.Plugin.LevelData.IsSet && !BS_Utils.Gameplay.Gamemode.IsIsolatedLevel && Config.UserConfig.enabled && (BS_Utils.Plugin.LevelData.Mode == BS_Utils.Gameplay.Mode.Standard || BS_Utils.Plugin.LevelData.Mode == BS_Utils.Gameplay.Mode.Multiplayer) && (Config.UserConfig.enabledInPractice || BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.practiceSettings == null); __state = WillOverride; if (!WillOverride) { return; } // BS_Utils.Gameplay.ScoreSubmission.DisableSubmission("NjsFixer"); float mapNJS = startNoteJumpMovementSpeed; float njs = Config.UserConfig.dontForceNJS ? mapNJS : Config.UserConfig.njs; // float bpm = 124f; // float njs = 18; if (njs == 0) { njs = startNoteJumpMovementSpeed; } float simOffset = 0; //Change NJS and Offset if (!Config.UserConfig.dontForceNJS && BS_Utils.Plugin.LevelData.Mode == BS_Utils.Gameplay.Mode.Standard) { BS_Utils.Gameplay.ScoreSubmission.DisableSubmission("NjsFixer"); float numCurr = 60f / startBpm; float num2Curr = 4f; while (njs * numCurr * num2Curr > 18f) { num2Curr /= 2f; } // num2Curr += spawnMovementData.GetPrivateField<float>("_noteJumpStartBeatOffset"); if (num2Curr < 1f) { num2Curr = 1f; } float jumpDurCurr = num2Curr * numCurr * 2f; float jumpDisCurr = njs * jumpDurCurr; //SimBPM Calc float simBPM = Config.UserConfig.bpm > 0 ? Config.UserConfig.bpm : startBpm; float numSim = 60f / simBPM; float num2Sim = 4f; while (njs * numSim * num2Sim > 18f) { num2Sim /= 2f; } var num2SimOffset = num2Sim + Config.UserConfig.spawnOffset; if (num2Sim < 1f) { num2Sim = 1f; } if (num2SimOffset < 1f) { num2SimOffset = 1f; } float jumpDurSim = num2SimOffset * numSim * 2f; float jumpDisSim = njs * jumpDurSim; float jumpDurMul = jumpDurSim / jumpDurCurr; simOffset = (num2Curr * jumpDurMul) - num2Curr; Logger.log.Debug($"BPM/NJS/Offset {startBpm}/{startNoteJumpMovementSpeed}/{noteJumpStartBeatOffset}"); Logger.log.Debug($"Sim BPM/NJS/Offset {Config.UserConfig.bpm}/{njs}/{Config.UserConfig.spawnOffset}"); Logger.log.Debug($"HalfJumpCurrent: {num2Curr} | HalfJumpSimulated {num2SimOffset} | SimJumpDis {jumpDisSim} | CurrJumpDis {jumpDisCurr} | JumpDurMul {jumpDurMul} | Simulated Offset {simOffset}"); startNoteJumpMovementSpeed = njs; } else //Change Only Offset { float numCurr = 60f / startBpm; float num2Curr = 4f; while (njs * numCurr * num2Curr > 18f) { num2Curr /= 2f; } // num2Curr += spawnMovementData.GetPrivateField<float>("_noteJumpStartBeatOffset"); if (num2Curr < 1f) { num2Curr = 1f; } float jumpDurCurr = num2Curr * numCurr * 2f; float jumpDisCurr = njs * jumpDurCurr; float desiredJumpDis = Config.UserConfig.jumpDistance; if (Config.UserConfig.usePreferredJumpDistanceValues) { var pref = Config.UserConfig.preferredValues.FirstOrDefault(x => x.njs == mapNJS); if (pref != null) { desiredJumpDis = pref.jumpDistance; } } float desiredJumpDur = desiredJumpDis / njs; float desiredHalfJumpDur = desiredJumpDur / 2f / num2Curr; float jumpDurMul = desiredJumpDur / jumpDurCurr; simOffset = (num2Curr * jumpDurMul) - num2Curr; Logger.log.Debug($"BPM/NJS/Offset {startBpm}/{startNoteJumpMovementSpeed}/{noteJumpStartBeatOffset}"); Logger.log.Debug($"HalfJumpCurrent: {num2Curr} | DesiredHalfJump {desiredHalfJumpDur} | DesiredJumpDis {desiredJumpDis} | CurrJumpDis {jumpDisCurr} | Simulated Offset {simOffset}"); } noteJumpStartBeatOffset = simOffset; }
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter private static void Postfix(BeatmapObjectSpawnMovementData __instance) #pragma warning restore SA1313 // Parameter names should begin with lower-case letter { InitBeatmapObjectSpawnController(__instance); }
private IEnumerator OnGameCoreCoroutine() { if (_audioTimeSyncController == null) { _audioTimeSyncController = Resources.FindObjectsOfTypeAll <AudioTimeSyncController>().FirstOrDefault(); _audioSource = _audioTimeSyncController.GetPrivateField <AudioSource>("_audioSource"); } _originalTimeScale = _audioTimeSyncController.timeScale; if (_gamePause == null) { _gamePause = Resources.FindObjectsOfTypeAll <GamePause>().FirstOrDefault(); } _gamePause.didResumeEvent += OnPauseResume; // wait for CustomSaber mod yield return(new WaitUntil(() => Resources.FindObjectsOfTypeAll <Saber>().Any())); yield return(new WaitForSecondsRealtime(0.1f)); if (_playerController == null) { _playerController = Resources.FindObjectsOfTypeAll <PlayerController>().FirstOrDefault(); } if (_rightSaberTransform == null) { _rightSaberTransform = _playerController.rightSaber.transform; } if (_leftSaberTransform == null) { _leftSaberTransform = _playerController.leftSaber.transform; } if (_saberClashChecker == null) { _saberClashChecker = Resources.FindObjectsOfTypeAll <SaberClashChecker>().FirstOrDefault(); } if (_saberBurnMarkArea == null) { _saberBurnMarkArea = Resources.FindObjectsOfTypeAll <SaberBurnMarkArea>().FirstOrDefault(); } if (_saberBurnMarkSparkles == null) { _saberBurnMarkSparkles = Resources.FindObjectsOfTypeAll <SaberBurnMarkSparkles>().FirstOrDefault(); } // need some wait to GetNoteOffset if (Config.centering) { if (_beatmapObjectSpawnController == null) { _beatmapObjectSpawnController = Resources.FindObjectsOfTypeAll <BeatmapObjectSpawnController>().FirstOrDefault(); } BeatmapObjectSpawnMovementData beatmapObjectSpawnMovementData = _beatmapObjectSpawnController.GetPrivateField <BeatmapObjectSpawnMovementData>("_beatmapObjectSpawnMovementData"); Vector3 leftBase = beatmapObjectSpawnMovementData.GetNoteOffset(0, NoteLineLayer.Base); Vector3 rightTop = beatmapObjectSpawnMovementData.GetNoteOffset(3, NoteLineLayer.Top); NoteJumpManualUpdate.center = (leftBase + rightTop) / 2; //Logger.log.Debug($"leftBase={leftBase.x}, {leftBase.y}, {leftBase.z}"); //Logger.log.Debug($"rightTop={rightTop.x}, {rightTop.y}, {rightTop.z}"); } if (Config.hideSabers) { SetSaberVisible(_playerController.rightSaber, false); SetSaberVisible(_playerController.leftSaber, false); SetTrailWidth(0f); _saberClashChecker.enabled = false; _saberBurnMarkArea.enabled = false; _saberBurnMarkSparkles.enabled = false; } if (Config.hideSaberEffects) { SetTrailWidth(0f); _saberClashChecker.enabled = false; _saberBurnMarkArea.enabled = false; _saberBurnMarkSparkles.enabled = false; } if (Config.boxing) { SetTrailWidth(0.05f); } if (Config.headbang) { SetTrailWidth(0f); } if (Config.vacuum) { if (_gameEnergyCounter == null) { _gameEnergyCounter = Resources.FindObjectsOfTypeAll <GameEnergyCounter>().FirstOrDefault(); } _gameEnergyCounter.SetPrivateField("_hitBombEnergyDrain", 0f); } if (GameObject.Find("vacuum_saber_right")) { SetTrailWidth(0f); } if (Config.feetAvatar) { StartCoroutine(FindAvatarCoroutine()); } UpdateSaberActive(); _init = true; }
private static void Postfix(BeatmapObjectSpawnController __instance, IBeatmapObjectSpawner ____beatmapObjectSpawner, BeatmapObjectSpawnMovementData ____beatmapObjectSpawnMovementData) { BeatmapObjectSpawnController = __instance; if (____beatmapObjectSpawner is BasicBeatmapObjectManager basicBeatmapObjectManager) { BeatmapObjectManager = basicBeatmapObjectManager; SpawnDataHelper.InitBeatmapObjectSpawnController(____beatmapObjectSpawnMovementData); } }
private static void Postfix(BeatmapObjectSpawnMovementData __instance, Vector3 ____centerPos, float ____jumpDuration, NoteData noteData, ref BeatmapObjectSpawnMovementData.NoteSpawnData __result) { if (!NoodleObjectDatas.TryGetValue(noteData, out NoodleObjectData noodleObjectData)) { return; } NoodleNoteData noodleData = (NoodleNoteData)noodleObjectData; float?flipLineIndex = noodleData.FlipLineIndexInternal; float?njs = noodleData.NJS; float?spawnoffset = noodleData.SpawnOffset; float?startlinelayer = noodleData.StartNoteLineLayerInternal; bool gravityOverride = noodleData.DisableGravity; float?startRow = noodleData.StartX; float?startHeight = noodleData.StartY; float jumpDuration = ____jumpDuration; ////Vector3 moveStartPos = __result.moveStartPos; ////Vector3 moveEndPos = __result.moveEndPos; ////Vector3 jumpEndPos = __result.jumpEndPos; float jumpGravity = __result.jumpGravity; Vector3 noteOffset = GetNoteOffset(noteData, startRow, startlinelayer ?? (float)noteData.startNoteLineLayer); if (startRow.HasValue || startHeight.HasValue || flipLineIndex.HasValue || njs.HasValue || spawnoffset.HasValue || startlinelayer.HasValue || gravityOverride) { GetNoteJumpValues(njs, spawnoffset, out float localJumpDuration, out float localJumpDistance, out Vector3 localMoveStartPos, out Vector3 localMoveEndPos, out Vector3 localJumpEndPos); jumpDuration = localJumpDuration; float localNoteJumpMovementSpeed = njs ?? NoteJumpMovementSpeed; float startLayerLineYPos = LineYPosForLineLayer(noteData, startlinelayer ?? (float)noteData.startNoteLineLayer); float lineYPos = LineYPosForLineLayer(noteData, startHeight); // Magic numbers below found with linear regression y=mx+b using existing HighestJumpPosYForLineLayer values float highestJump = startHeight.HasValue ? (0.875f * lineYPos) + 0.639583f + JumpOffsetY : __instance.HighestJumpPosYForLineLayer(noteData.noteLineLayer); jumpGravity = 2f * (highestJump - (gravityOverride ? lineYPos : startLayerLineYPos)) / Mathf.Pow(localJumpDistance / localNoteJumpMovementSpeed * 0.5f, 2f); Vector3 jumpEndPos = localJumpEndPos + noteOffset; // IsBasicNote() check is skipped so bombs can flip too Vector3 noteOffset2 = GetNoteOffset(noteData, flipLineIndex ?? startRow, gravityOverride ? startHeight : startlinelayer ?? (float)noteData.startNoteLineLayer); Vector3 moveStartPos = localMoveStartPos + noteOffset2; Vector3 moveEndPos = localMoveEndPos + noteOffset2; __result = new BeatmapObjectSpawnMovementData.NoteSpawnData(moveStartPos, moveEndPos, jumpEndPos, jumpGravity, __result.moveDuration, jumpDuration); } // DEFINITE POSITION IS WEIRD, OK? // ty reaxt float startVerticalVelocity = jumpGravity * jumpDuration * 0.5f; float num = jumpDuration * 0.5f; float yOffset = (startVerticalVelocity * num) - (jumpGravity * num * num * 0.5f); noodleData.NoteOffset = ____centerPos + noteOffset + new Vector3(0, yOffset, 0); }
public static void Postfix(BeatmapObjectCallbackController __instance, BeatmapObjectSpawnMovementData ____beatmapObjectSpawnMovementData) { CustomEventCallbackController.spawnAheadTime = ____beatmapObjectSpawnMovementData.spawnAheadTime; }