Skip to content

Redo Instant Takeoff & Landing, add Instant Route - #162

Draft
ratijas wants to merge 9 commits into
giosuel:developmentfrom
ratijas:work/ratijas/instant-ship-animator
Draft

Redo Instant Takeoff & Landing, add Instant Route#162
ratijas wants to merge 9 commits into
giosuel:developmentfrom
ratijas:work/ratijas/instant-ship-animator

Conversation

@ratijas

@ratijas ratijas commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Draft because needs an actual UI from @giosuel


Using the same technique of internally managed coroutine and animation
state info tracking as in Speedy Shovel, re-implement the whole Instant
Takeoff & Landing, and add Instant Route to the mix.

Old (existing) patches were overlapping (patching the same method twice)
and one of them was in the wrong file entirely.

The following is an overview of the animations and coroutines involved.


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.

shipAnimatorObject.gameObject.GetComponent<Animator>().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.

TODO:

  • remove existing patch.

StartOfRound.openingDoorsSequence

A coroutine. Has lots of WaitForSeconds.

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.

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.

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.

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

Fixes #159
Closes #66

ratijas added 6 commits April 14, 2026 05:03
Is it ImpAnimator or AnimatorHash? ¿Por qué no los dos?

Amends be724cf
Restricting T to MonoBehaviour does not work with Transform, for example.
Let ShipManager and UI of ShipControlWindow be the sources of truth.
This doesn't do anything on its own, just provides a config storage.
Without a custom UI it can be toggled via LethalConfig for now.
@giosuel

giosuel commented Apr 17, 2026

Copy link
Copy Markdown
Owner

Small comment; I think it might be better to move the ShipAnimatorManager to its own file in src/Core/Scripts and rename it to something like ImpShipAnimatorManager instead, in order to be more consistent with the rest of the project structure.

@ratijas
ratijas force-pushed the work/ratijas/instant-ship-animator branch 2 times, most recently from db48b3e to 5772b6e Compare April 17, 2026 12:25
@ratijas

ratijas commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

Small comment; I think it might be better to move the ShipAnimatorManager to its own file in src/Core/Scripts and rename it to something like ImpShipAnimatorManager instead, in order to be more consistent with the rest of the project structure.

Done

Using the same technique of internally managed coroutine and animation
state info tracking as in Speedy Shovel, re-implement the whole Instant
Takeoff & Landing, and add Instant Route to the mix.

Old (existing) patches were overlapping (patching the same method twice)
and one of them was in the wrong file entirely.

The following is an overview of the animations and coroutines involved.

---

# 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<Animator>().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`.

TODO:
- [x] remove existing patch.

### `StartOfRound.openingDoorsSequence`

A coroutine. Has lots of WaitForSeconds.

```cs
shipAnimator.SetTrigger("OpenShip");
shipHasLanded = true;
```

TODO if InstantLanding is enabled:
- [x] wrap in SkipWaitingForSeconds
- [x] 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:
- [x] 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:
- [x] 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:
- [x] 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:
- [x] wrap in SkipWaitingForSeconds
- [x] 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:
- [x] wrap in `SkipWaitingForSeconds`

---

Fixes giosuel#159
Closes giosuel#66
@ratijas
ratijas force-pushed the work/ratijas/instant-ship-animator branch from 5772b6e to ce7fc87 Compare April 17, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants