# Instant Route, Landing & Takeoff To skip long Landing, Takeoff and Route animations, animator speed can be set to a higher value, and audio sources temporarily muted. ### Animator However, animator is responsible for other animations as well, such as `HangarShipShake` which should play at a normal speed, so the increased speed has to be reset after skipping. `StartOfRound.shipAnimatorObject` is a NetworkObject, but only ever used to get the `Animator` component of its gameObject. Seems to be equivalent to using `StartOfRound.shipAnimator` directly. ```cs shipAnimatorObject.gameObject.GetComponent().SetTrigger("OpenShip"); ``` ### Audio Animation events are used to play audio via `PlayAudioAnimationEvent`. `PlayAudioAnimationEvent` does not use `AudioSource.mute` property, so it is safe to manipulate it. ## `StartOfRound` ### `StartOfRound.StartGame` A regular method, should not be patched. Calls `OpenShipDoors` -> `RoundManager.LoadNewLevel`. ### `StartOfRound.openingDoorsSequence` A coroutine. Has lots of WaitForSeconds. ```cs shipAnimator.SetTrigger("OpenShip"); shipHasLanded = true; ``` TODO if InstantLanding is enabled: - [ ] wrap in SkipWaitingForSeconds - [ ] speed up & restore animator speed ### `StartOfRound.gameOverAnimation` A coroutine. Has lots of WaitForSeconds. Called from `ShipLeaveAutomatically`, which is called at midnight, on player death or DC. - Waits until `shipHasLanded`. - Calls `ShipLeave()`. TODO if InstantTakeoff is enabled: - [ ] wrap in SkipWaitingForSeconds ### `StartOfRound.ShipLeave` A regular method. ```cs shipHasLanded = false; shipIsLeaving = true; shipAnimator.ResetTrigger("ShipLeave"); shipAnimator.SetTrigger("ShipLeave"); ``` Called from `EndGameClientRpc` (a player started the ship), and from `StartOfRound.gameOverAnimation` coroutine. TODO if InstantTakeoff is enabled: - [ ] speed up & restore animator speed ### `StartOfRound.EndOfGame` A coroutine. Has lots of WaitForSeconds, but only triggers `HUDManager` animators. ```cs shipIsLeaving = false; ``` TODO if InstantTakeoff is enabled: - [ ] wrap in SkipWaitingForSeconds ### `StartOfRound.TravelToLevelEffects` A coroutine. Has lots of WaitForSeconds, has loop of yield return null for audio fade out. ```cs shipAmbianceAudio.Play(); shipAnimator.SetBool("FlyingToNewPlanet", value: true); shipAnimator.SetBool("FlyingToNewPlanet", value: false); shipAmbianceAudio.volume -= 0.05; // loop shipAmbianceAudio.Stop() ``` Note: `shipAmbianceAudio` is not related to animator's `PlayAudioAnimationEvent`, but the loop of 20 `yield return null;` provides some natural delay during which the sped up animation might complete. TODO if InstantRoute is enabled: - [ ] wrap in SkipWaitingForSeconds - [ ] speed up & restore animator speed ## `RoundManager` ### `RoundManager.DetectElevatorRunning` **Only runs on server!** A coroutine. Has one WaitForSeconds. Called from `shipAnimator`'s "ShipLeave" animation event. Dewpawns props and enemies. Simple linear algorithm. Despite not altering the `shipAnimator`, might still be useful to skip in order to despawn faster. TODO if InstantTakeoff is enabled: - [ ] wrap in `SkipWaitingForSeconds` if Instant Takeoff ## Current patches Currently existing patches overlap (patching the same method twice) and one of them is in the wrong file. ```cs [HarmonyPatch(typeof(StartOfRound))] public class StartOfRoundPatch { [HarmonyPrefix] [HarmonyPatch("StartGame")] private static void StartGamePrefixPatch(StartOfRound __instance); [HarmonyPrefix] [HarmonyPatch("ShipLeave")] private static void ShipLeavePrefixPatch(StartOfRound __instance); [HarmonyPostfix] [HarmonyPatch("openingDoorsSequence")] private static void openingDoorsSequencePostfixPatch(StartOfRound __instance); // ... [HarmonyPostfix] [HarmonyPatch("openingDoorsSequence")] private static IEnumerator openingDoorsSequencePatch(IEnumerator __result); [HarmonyPostfix] [HarmonyPatch("EndOfGame")] private static IEnumerator EndOfGamePatch(IEnumerator __result); [HarmonyPostfix] [HarmonyPatch(typeof(RoundManager), "DetectElevatorRunning")] private static IEnumerator DetectElevatorRunningPatch(IEnumerator __result); } [HarmonyPatch(typeof(RoundManager))] internal static class RoundManagerPatch { [HarmonyPatch("DetectElevatorRunning")] private static void DetectElevatorRunningPostfixPatch(RoundManager __instance); } ```