# tecs.sequence Snapshot-safe programs, waits, ownership, actions, and tween timelines. Sequences store control flow as data. Snapshots, rewind, and hot reload can therefore preserve a playback's program, instruction pointer, waits, bindings, and parameters. ## Programs and actions Register an action on the world, name it from a program, and bind each playback to the entities it acts on: ```teal local sequence = tecs.sequence sequence.registerAction( world, "game.lockControls", function(_world, _ctx) controlsLocked = true end ) local intro = sequence.define( "game.bossIntro", { sequence.call("game.lockControls"), sequence.wait(1.5), sequence.emit("boss.ready"), } ) local playback = sequence.play( world, intro, { owner = encounter, bindings = {boss = bossEntity}, } ) ``` Program names form a snapshot compatibility surface. Use stable, qualified names for game and plugin programs. Redefining a name creates a new version. Running playbacks keep their original instructions, while later calls to `play` use the new program. Action bodies resolve by name when they run, so a reload can replace action code without moving a live program counter. Actions run synchronously and cannot yield. An action that raises faults its playback after preserving mutations it already completed. Keep wall-clock, file, and network access outside deterministic actions. ## Clocks and waits `"fixed"` advances once per fixed step and serves deterministic gameplay. `"frame"` advances once per gameplay frame. `"presentation"` advances with display time and serves values simulation never reads. Durations use seconds. Step and tick values count whole advances of the program's clock. Every positive duration waits at least one tick. `waitSteps(0)` yields until the next tick and gives a loop a fresh instruction budget. ## Ownership `owner` ties a playback to an entity. Despawning that entity cancels the playback. A named `channel` gives one owner a replaceable slot, so starting a second playback on the same channel cancels the first. Pause uses named holders. The playback resumes only after every holder releases it. Branches inherit owner, bindings, parameters, budget, and pause state. A branch cannot outlive its parent. Each playback receives a bounded instruction budget per tick. Exceeding it faults with `budgetExceeded` instead of hanging the frame. ## Timelines Timelines compile tweens into the same runtime and retain the same ownership, clock, channel, pause, and snapshot rules. Targets interpolate component fields. Parallel blocks share a start time, while sequential blocks start after the previous block ends. ## Module contents ### Types | Type | Kind | Description | | --- | --- | --- | | [`Action`](/modules/sequence/#tecs.sequence.Action) | type | Defines a registered effect that runs synchronously and cannot yield. | | [`ActionContext`](/modules/sequence/#tecs.sequence.ActionContext) | record | Provides the context received by a registered action. | | [`Argument`](/modules/sequence/#tecs.sequence.Argument) | type | Represents constants passed from call to its action. | | [`Awaitable`](/modules/sequence/#tecs.sequence.Awaitable) | record | Defines the response required from an awaitable provider. | | [`ClockId`](/modules/sequence/#tecs.sequence.ClockId) | enum | Selects the clock against which a program runs. | | [`DefineOptions`](/modules/sequence/#tecs.sequence.DefineOptions) | record | Configures define. | | [`EasingFunction`](/modules/sequence/#tecs.sequence.EasingFunction) | type | Maps normalized input progress to eased output progress. | | [`EasingName`](/modules/sequence/#tecs.sequence.EasingName) | enum | Names a built-in easing curve and describes the shape of any curve. | | [`EntityRef`](/modules/sequence/#tecs.sequence.EntityRef) | record | References an entity supplied at play time and resolves it when the instruction that uses it runs. | | [`Evaluator`](/modules/sequence/#tecs.sequence.Evaluator) | record | Defines the evaluator run by an eval step every tick. | | [`FaultReason`](/modules/sequence/#tecs.sequence.FaultReason) | enum | Explains why a cursor stopped running. | | [`Handle`](/modules/sequence/#tecs.sequence.Handle) | type | Identifies one playback through a generation-checked reference that remains meaningful across a snapshot load. | | [`Node`](/modules/sequence/#tecs.sequence.Node) | interface | Represents one authored step produced by the node constructors below. | | [`PlaybackMode`](/modules/sequence/#tecs.sequence.PlaybackMode) | enum | Selects how a timeline repeats. | | [`PlaybackState`](/modules/sequence/#tecs.sequence.PlaybackState) | enum | Describes the lifecycle state of one playback. | | [`PlayOptions`](/modules/sequence/#tecs.sequence.PlayOptions) | record | Configures play. | | [`Program`](/modules/sequence/#tecs.sequence.Program) | interface | Represents a compiled, immutable program produced by define and shared by every playback of it. | | [`QueryCondition`](/modules/sequence/#tecs.sequence.QueryCondition) | enum | Describes the condition awaited by a waitQuery step. | | [`RunOptions`](/modules/sequence/#tecs.sequence.RunOptions) | record | Configures how tweenRun plays its nested timeline. | | [`Status`](/modules/sequence/#tecs.sequence.Status) | record | Reports a playback's current state. | | [`Step`](/modules/sequence/#tecs.sequence.Step) | record | Describes one step a playback will reach without branching. | | [`Target`](/modules/sequence/#tecs.sequence.Target) | interface | Describes the component and one to four numeric fields written by a timeline operation. | | [`TargetName`](/modules/sequence/#tecs.sequence.TargetName) | enum | Names a built-in component-field target. | | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | type | Represents one authored timeline operation. | | [`TimelineOptions`](/modules/sequence/#tecs.sequence.TimelineOptions) | record | Configures timeline. | | [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec) | type | Lists timeline operations in execution order. | | [`TrackSource`](/modules/sequence/#tecs.sequence.TrackSource) | interface | Provides a live component-field tracking source. | | [`TweenOutcome`](/modules/sequence/#tecs.sequence.TweenOutcome) | enum | Reports how the tween awaited by waitTween ended. | ### Functions | Function | Kind | Description | | --- | --- | --- | | [`activeCount`](/modules/sequence/#tecs.sequence.activeCount) | Static | Returns the number of live playbacks for tests and diagnostics. | | [`await`](/modules/sequence/#tecs.sequence.await) | Static | Waits for work outside the sequencer to finish. | | [`bind`](/modules/sequence/#tecs.sequence.bind) | Static | References an entity supplied through PlayOptions.bindings. | | [`call`](/modules/sequence/#tecs.sequence.call) | Static | Runs a registered action. | | [`cancel`](/modules/sequence/#tecs.sequence.cancel) | Static | Stops a playback and releases its cursor. | | [`cancelOwnedBy`](/modules/sequence/#tecs.sequence.cancelOwnedBy) | Static | Cancels every playback owned by an entity. | | [`currentStep`](/modules/sequence/#tecs.sequence.currentStep) | Static | Returns a clock's current tick as counted by the sequencer. | | [`dataOps`](/modules/sequence/#tecs.sequence.dataOps) | Static | Returns the step names accepted by defineData, sorted. | | [`define`](/modules/sequence/#tecs.sequence.define) | Static | Compiles a program under a stable symbolic name. | | [`defineData`](/modules/sequence/#tecs.sequence.defineData) | Static | Compiles a program written as plain data instead of node calls. | | [`disassemble`](/modules/sequence/#tecs.sequence.disassemble) | Static | Renders a program as readable instructions. | | [`emit`](/modules/sequence/#tecs.sequence.emit) | Static | Emits an ECS event at address zero. | | [`eval`](/modules/sequence/#tecs.sequence.eval) | Static | Evaluates a registered evaluator every tick until it finishes. | | [`fork`](/modules/sequence/#tecs.sequence.fork) | Static | Starts a branch that runs alongside the rest of the program. | | [`hasAction`](/modules/sequence/#tecs.sequence.hasAction) | Static | Returns whether this world has registered an action name. | | [`hasQuery`](/modules/sequence/#tecs.sequence.hasQuery) | Static | Returns whether this world has registered a query name. | | [`join`](/modules/sequence/#tecs.sequence.join) | Static | Waits for every branch that has not yet joined. | | [`loop`](/modules/sequence/#tecs.sequence.loop) | Static | Repeats a block. | | [`parallel`](/modules/sequence/#tecs.sequence.parallel) | Static | Forks several blocks and waits for all of them. | | [`pause`](/modules/sequence/#tecs.sequence.pause) | Static | Suspends a playback, its branches, and anything it started. | | [`play`](/modules/sequence/#tecs.sequence.play) | Static | Starts a program. | | [`playbacks`](/modules/sequence/#tecs.sequence.playbacks) | Static | Returns handles for every live playback, branches included, in a stable order. | | [`playTween`](/modules/sequence/#tecs.sequence.playTween) | Static | Plays a registered tween preset on a bound entity. | | [`plugin`](/modules/sequence/#tecs.sequence.plugin) | Static | Installs the sequencer. | | [`program`](/modules/sequence/#tecs.sequence.program) | Static | Returns the newest version of a defined program or a requested version. | | [`programNames`](/modules/sequence/#tecs.sequence.programNames) | Static | Returns the names of every defined program, sorted. | | [`registerAction`](/modules/sequence/#tecs.sequence.registerAction) | Static | Registers an action that a call node can name. | | [`registerAwaitable`](/modules/sequence/#tecs.sequence.registerAwaitable) | Static | Registers a provider that an await step can name. | | [`registerEvaluator`](/modules/sequence/#tecs.sequence.registerEvaluator) | Static | Registers an evaluator that an eval step can name. | | [`registerQuery`](/modules/sequence/#tecs.sequence.registerQuery) | Static | Registers a query that a waitQuery step can name. | | [`resume`](/modules/sequence/#tecs.sequence.resume) | Static | Releases one holder's claim. | | [`setInstructionBudget`](/modules/sequence/#tecs.sequence.setInstructionBudget) | Static | Sets the per-step instruction budget for playbacks without their own. | | [`signal`](/modules/sequence/#tecs.sequence.signal) | Static | Raises a named signal and wakes every playback blocked on it. | | [`signalOnEvent`](/modules/sequence/#tecs.sequence.signalOnEvent) | Static | Raises a signal whenever an event emits at address zero. | | [`status`](/modules/sequence/#tecs.sequence.status) | Static | Returns playback status, or nil for a handle this world never issued. | | [`timeline`](/modules/sequence/#tecs.sequence.timeline) | Static | Compiles a tween timeline into a program under a stable name. | | [`tweenAdjust`](/modules/sequence/#tecs.sequence.tweenAdjust) | Static | Interpolates by a relative delta from the starting value. | | [`tweenEmit`](/modules/sequence/#tecs.sequence.tweenEmit) | Static | Emits a named sequence.Event when the cursor reaches this point. | | [`tweenParallel`](/modules/sequence/#tecs.sequence.tweenParallel) | Static | Runs timeline nodes concurrently and ends with the longest. | | [`tweenRun`](/modules/sequence/#tecs.sequence.tweenRun) | Static | Runs a nested timeline from its own spec. | | [`tweenTo`](/modules/sequence/#tecs.sequence.tweenTo) | Static | Interpolates to an absolute destination. | | [`tweenTrack`](/modules/sequence/#tecs.sequence.tweenTrack) | Static | Interpolates toward a destination that keeps moving. | | [`tweenWait`](/modules/sequence/#tecs.sequence.tweenWait) | Static | Advances the timeline cursor without changing anything. | | [`upcoming`](/modules/sequence/#tecs.sequence.upcoming) | Static | Returns the actions a playback will certainly perform next and their timing. | | [`wait`](/modules/sequence/#tecs.sequence.wait) | Static | Waits for a duration in seconds. | | [`waitingOn`](/modules/sequence/#tecs.sequence.waitingOn) | Static | Returns how many playbacks currently wait on a signal name. | | [`waitQuery`](/modules/sequence/#tecs.sequence.waitQuery) | Static | Blocks until a registered query matches or stops matching. | | [`waitSignal`](/modules/sequence/#tecs.sequence.waitSignal) | Static | Blocks until signal raises the named signal. | | [`waitSteps`](/modules/sequence/#tecs.sequence.waitSteps) | Static | Waits for a whole number of ticks of the program's clock. | | [`waitTween`](/modules/sequence/#tecs.sequence.waitTween) | Static | Waits for the tween started by the most recent playTween. | ### Values | Value | Type | Description | | --- | --- | --- | | [`easing`](/modules/sequence/#tecs.sequence.easing) | `Easings` | Read-only. Exposes built-in easing curves such as sequence.easing.quadOut. | | [`Event`](/modules/sequence/#tecs.sequence.Event) | [`Event`](/modules/sequence/#tecs.sequence.Event) | Read-only. Exposes the event emitted by an emit step at address zero. | | [`source`](/modules/sequence/#tecs.sequence.source) | `Sources` | Read-only. Exposes sources from which tweenTrack reads changing values: sequence.source.own(Transform2D, "x"). | | [`target`](/modules/sequence/#tecs.sequence.target) | `Targets` | Read-only. Exposes built-in targets and constructors for new ones: sequence.target.translateX,... | | [`TrackingTarget`](/modules/sequence/#tecs.sequence.TrackingTarget) | [`TrackingTarget`](/modules/sequence/#tecs.sequence.TrackingTarget) | Read-only. Exposes the component that selects a dynamic tracking-source entity. | ## Types ### tecs.sequence.Action type Defines a registered effect that runs synchronously and cannot yield. ```teal type tecs.sequence.Action = function(World, ActionContext) ``` ### tecs.sequence.ActionContext record Provides the context received by a registered action. The context and its `args` belong to the sequencer, which reuses them for the next call. ```teal record tecs.sequence.ActionContext world: World handle: Handle owner: integer args: {any} params: {string: any} bind: function(self, string, integer) entity: function(self, string): integer end ``` #### tecs.sequence.ActionContext.world field Read-only. The world this playback belongs to. ```teal tecs.sequence.ActionContext.world: World ``` #### tecs.sequence.ActionContext.handle field Read-only. The playback, for `status` or `cancel` from inside an action. ```teal tecs.sequence.ActionContext.handle: Handle ``` #### tecs.sequence.ActionContext.owner field Read-only. The `owner` supplied at `play`, or 0 for a world-scoped sequence. ```teal tecs.sequence.ActionContext.owner: integer ``` #### tecs.sequence.ActionContext.args field Read-only. Constants supplied by the `call` node, with any `bind` references already resolved to entity ids. ```teal tecs.sequence.ActionContext.args: {any} ``` #### tecs.sequence.ActionContext.params field Read-only. The `params` supplied at `play`, or nil. Unlike `args`, this is the playback's own table rather than borrowed scratch, and it is the same one every step of the playback sees. ```teal tecs.sequence.ActionContext.params: {string: any} ``` #### tecs.sequence.ActionContext:bind Instance Name an entity for the steps that follow, so an action that creates one can hand it on. Bindings travel with the playback and survive a snapshot; passing nil forgets the name. ```teal function tecs.sequence.ActionContext.bind(self, string, integer) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `ActionContext` | | | `#2` | `string` | | | `#3` | `integer` | | ##### Returns None. #### tecs.sequence.ActionContext:entity Instance Resolve a named binding. Returns nil when the binding was not supplied or its entity is no longer alive. ```teal function tecs.sequence.ActionContext.entity(self, string): integer ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `ActionContext` | | | `#2` | `string` | | ##### Returns | Type | Description | | --- | --- | | `integer` | | ### tecs.sequence.Argument type Represents constants passed from `call` to its action. ```teal type tecs.sequence.Argument = any ``` ### tecs.sequence.Awaitable record Defines the response required from an awaitable provider. ```teal record tecs.sequence.Awaitable isPending: function(World, integer, string): boolean setPaused: function(World, integer, string, boolean) end ``` #### tecs.sequence.Awaitable.isPending Static Whether the work named by `entity` and `key` is still going. Called at a step boundary for every cursor parked on this name, so it must be cheap and must not mutate the world. Returning false for something that never started is correct: a program waiting for an animation that is already over should carry on, not hang. ```teal function tecs.sequence.Awaitable.isPending( World, integer, string ): boolean ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | [`World`](/modules/ecs/#tecs.World) | | | `#2` | `integer` | | | `#3` | `string` | | ##### Returns | Type | Description | | --- | --- | | `boolean` | | #### tecs.sequence.Awaitable.setPaused Static Stop and start the work, when the provider knows how. Called when the playback parked on it is paused or resumed, so a cutscene that is waiting for an animation stops it rather than leaving it running underneath. Optional: a provider that cannot pause its work simply does not offer this. ```teal function tecs.sequence.Awaitable.setPaused( World, integer, string, boolean ) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | [`World`](/modules/ecs/#tecs.World) | | | `#2` | `integer` | | | `#3` | `string` | | | `#4` | `boolean` | | ##### Returns None. ### tecs.sequence.ClockId enum Selects the clock against which a program runs. ```teal enum tecs.sequence.ClockId "fixed" "frame" "presentation" end ``` ### tecs.sequence.DefineOptions record Configures `define`. ```teal record tecs.sequence.DefineOptions clock: ClockId end ``` #### tecs.sequence.DefineOptions.clock field Caller-writable. Selects the clock counted by program waits and defaults to `"fixed"`. ```teal tecs.sequence.DefineOptions.clock: ClockId ``` ### tecs.sequence.EasingFunction type Maps normalized input progress to eased output progress. Easing shapes the value, not the schedule: the argument is how far through its own window the interpolation is, clamped to [0, 1], and the result is the fraction of the way from start to destination to place the target at. A curve that leaves [0, 1] overshoots the destination rather than the duration, which is what `backOut` and `elasticOut` are for. Compilation fixes the window, so no curve can make a timeline longer or shorter or move what follows it. ```teal type tecs.sequence.EasingFunction = function(number): number ``` ### tecs.sequence.EasingName enum Names a built-in easing curve and describes the shape of any curve. ```teal enum tecs.sequence.EasingName "backIn" "backInOut" "backOut" "backOutIn" "bounceIn" "bounceInOut" "bounceOut" "bounceOutIn" "cubicIn" "cubicInOut" "cubicOut" "cubicOutIn" "elasticIn" "elasticInOut" "elasticOut" "elasticOutIn" "expoIn" "expoInOut" "expoOut" "expoOutIn" "linear" "quadIn" "quadInOut" "quadOut" "quadOutIn" "quartIn" "quartInOut" "quartOut" "quartOutIn" "quintIn" "quintInOut" "quintOut" "quintOutIn" "sineIn" "sineInOut" "sineOut" "sineOutIn" end ``` ### tecs.sequence.EntityRef record References an entity supplied at `play` time and resolves it when the instruction that uses it runs. ```teal record tecs.sequence.EntityRef bindName: string isBinding: boolean end ``` #### tecs.sequence.EntityRef.bindName field Read-only. Name of the binding this reference resolves. ```teal tecs.sequence.EntityRef.bindName: string ``` #### tecs.sequence.EntityRef.isBinding field Read-only. Marker distinguishing a reference from an ordinary table argument. ```teal tecs.sequence.EntityRef.isBinding: boolean ``` ### tecs.sequence.Evaluator record Defines the evaluator run by an `eval` step every tick. ```teal record tecs.sequence.Evaluator load: function(ProgramImpl, any, any): any newState: function(ProgramImpl, any, Cursor): any resolve: function(any): any save: function(any): any step: function(World, Cursor, number): boolean end ``` #### tecs.sequence.Evaluator.load Static ```teal function tecs.sequence.Evaluator.load(ProgramImpl, any, any): any ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `ProgramImpl` | | | `#2` | `any` | | | `#3` | `any` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### tecs.sequence.Evaluator.newState Static Per-cursor working state, or nil when it needs none. `data` is what the `eval` step carried, resolved; the cursor is there for what belongs to the playback rather than the program, chiefly its `owner` and its `params`. ```teal function tecs.sequence.Evaluator.newState(ProgramImpl, any, Cursor): any ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `ProgramImpl` | | | `#2` | `any` | | | `#3` | `Cursor` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### tecs.sequence.Evaluator.resolve Static Turn the constants an `eval` step carries into whatever form is cheapest to read every tick: functions bound, names resolved. Called once per program constant and the result shared by every playback of it, so this is where work that does not depend on the playback belongs. Omit it to hand the constants over as authored. ```teal function tecs.sequence.Evaluator.resolve(any): any ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `any` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### tecs.sequence.Evaluator.save Static Turn working state into something a snapshot can carry, and back. Without both, an evaluating playback comes back at the start of its state rather than where it was. ```teal function tecs.sequence.Evaluator.save(any): any ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | `any` | | ##### Returns | Type | Description | | --- | --- | | `any` | | #### tecs.sequence.Evaluator.step Static Advance one cursor by `dt`. Returns true when it is finished and the cursor should move on to the next instruction. ```teal function tecs.sequence.Evaluator.step(World, Cursor, number): boolean ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `#1` | [`World`](/modules/ecs/#tecs.World) | | | `#2` | `Cursor` | | | `#3` | `number` | | ##### Returns | Type | Description | | --- | --- | | `boolean` | | ### tecs.sequence.FaultReason enum Explains why a cursor stopped running. ```teal enum tecs.sequence.FaultReason "actionError" "branchFaulted" "budgetExceeded" "unregisteredAction" "unregisteredAwaitable" "unregisteredEvaluator" "unregisteredQuery" "unregisteredTween" end ``` ### tecs.sequence.Handle type Identifies one playback through a generation-checked reference that remains meaningful across a snapshot load. ```teal type tecs.sequence.Handle = seqtypes.Handle ``` ### tecs.sequence.Node interface Represents one authored step produced by the node constructors below. Treat the returned value as opaque and do not reuse a node across programs. ```teal interface tecs.sequence.Node end ``` ### tecs.sequence.PlaybackMode enum Selects how a timeline repeats. ```teal enum tecs.sequence.PlaybackMode "loop" "once" "pingPong" end ``` ### tecs.sequence.PlaybackState enum Describes the lifecycle state of one playback. ```teal enum tecs.sequence.PlaybackState "canceled" "completed" "faulted" "paused" "running" end ``` ### tecs.sequence.PlayOptions record Configures `play`. ```teal record tecs.sequence.PlayOptions owner: integer bindings: {string: integer} params: {string: any} budget: integer channel: string end ``` #### tecs.sequence.PlayOptions.owner field Caller-writable. Entity whose lifetime governs the playback. When it despawns, the playback is canceled. Omit for a world-scoped sequence. ```teal tecs.sequence.PlayOptions.owner: integer ``` #### tecs.sequence.PlayOptions.bindings field Caller-writable. Entities the program acts on, addressed by `sequence.bind(name)`. ```teal tecs.sequence.PlayOptions.bindings: {string: integer} ``` #### tecs.sequence.PlayOptions.params field Caller-writable. Constants this playback runs with, readable by its actions and its evaluators. A program is shared by every playback of it, so anything that differs between two of them belongs here rather than in the program. Plain data, for the same reason a `call` argument is: it travels with a snapshot. ```teal tecs.sequence.PlayOptions.params: {string: any} ``` #### tecs.sequence.PlayOptions.budget field Caller-writable. Per-step instruction budget for this playback. Defaults to the world's configured budget. See `setInstructionBudget`. ```teal tecs.sequence.PlayOptions.budget: integer ``` #### tecs.sequence.PlayOptions.channel field Caller-writable. Names a slot this playback occupies on its owner. Starting another playback on the same owner and channel cancels this one, which is how a second fade replaces the first rather than fighting it. ```teal tecs.sequence.PlayOptions.channel: string ``` ### tecs.sequence.Program interface Represents a compiled, immutable program produced by `define` and shared by every playback of it. See `internal/types` for the full contract. ```teal interface tecs.sequence.Program name: string version: integer end ``` #### tecs.sequence.Program.name field Read-only. The name passed to `define`. ```teal tecs.sequence.Program.name: string ``` #### tecs.sequence.Program.version field Read-only. Monotonic version, starting at 1. Incremented per redefinition. ```teal tecs.sequence.Program.version: integer ``` ### tecs.sequence.QueryCondition enum Describes the condition awaited by a `waitQuery` step. ```teal enum tecs.sequence.QueryCondition "any" "empty" end ``` ### tecs.sequence.RunOptions record Configures how `tweenRun` plays its nested timeline. Omitting it runs the nested timeline once. A nested `"loop"` or `"pingPong"` must set `count`, because a parent has to know how long its own window is; only the root timeline of a `sequence.timeline`, through `params`, may repeat without one. ```teal record tecs.sequence.RunOptions mode: PlaybackMode count: integer end ``` #### tecs.sequence.RunOptions.mode field Caller-writable. Nested timeline playback mode. Defaults to "once". ```teal tecs.sequence.RunOptions.mode: PlaybackMode ``` #### tecs.sequence.RunOptions.count field Caller-writable. Pass count for the nested timeline. ```teal tecs.sequence.RunOptions.count: integer ``` ### tecs.sequence.Status record Reports a playback's current state. ```teal record tecs.sequence.Status state: PlaybackState program: string version: integer pc: integer wakeAt: integer waitingFor: string waitingQuery: string waitingCondition: QueryCondition waitingAwaitable: string waitingAwaitableEntity: integer waitingTween: integer tweenOutcome: TweenOutcome branches: integer joining: boolean fault: FaultReason faultMessage: string end ``` #### tecs.sequence.Status.state field Read-only. ```teal tecs.sequence.Status.state: PlaybackState ``` #### tecs.sequence.Status.program field Read-only. Program name this playback is running. ```teal tecs.sequence.Status.program: string ``` #### tecs.sequence.Status.version field Read-only. Program version this playback is running. ```teal tecs.sequence.Status.version: integer ``` #### tecs.sequence.Status.pc field Read-only. Instruction index, for disassembly and debugging. ```teal tecs.sequence.Status.pc: integer ``` #### tecs.sequence.Status.wakeAt field Read-only. Fixed step this playback next runs on. Nil when it is blocked on a signal rather than a time. ```teal tecs.sequence.Status.wakeAt: integer ``` #### tecs.sequence.Status.waitingFor field Read-only. Signal name this playback is blocked on, when it is. ```teal tecs.sequence.Status.waitingFor: string ``` #### tecs.sequence.Status.waitingQuery field Read-only. Query name this playback is blocked on, when it is, and the condition it is waiting for. ```teal tecs.sequence.Status.waitingQuery: string ``` #### tecs.sequence.Status.waitingCondition field Read-only. Query condition this playback is waiting for. ```teal tecs.sequence.Status.waitingCondition: QueryCondition ``` #### tecs.sequence.Status.waitingAwaitable field Read-only. Awaitable provider this playback is blocked on, when it is, and the entity it is waiting on. ```teal tecs.sequence.Status.waitingAwaitable: string ``` #### tecs.sequence.Status.waitingAwaitableEntity field Read-only. Entity this playback's awaitable is waiting on. ```teal tecs.sequence.Status.waitingAwaitableEntity: integer ``` #### tecs.sequence.Status.waitingTween field Read-only. Tween playback token this playback is blocked on, when it is. ```teal tecs.sequence.Status.waitingTween: integer ``` #### tecs.sequence.Status.tweenOutcome field Read-only. How the last tween it waited on ended. ```teal tecs.sequence.Status.tweenOutcome: TweenOutcome ``` #### tecs.sequence.Status.branches field Read-only. Live branches this playback forked and has not joined. ```teal tecs.sequence.Status.branches: integer ``` #### tecs.sequence.Status.joining field Read-only. Whether it is parked at a `join` waiting for those branches. ```teal tecs.sequence.Status.joining: boolean ``` #### tecs.sequence.Status.fault field Read-only. Set when `state` is `"faulted"`. ```teal tecs.sequence.Status.fault: FaultReason ``` #### tecs.sequence.Status.faultMessage field Read-only. Error message set when `state` is `"faulted"`. ```teal tecs.sequence.Status.faultMessage: string ``` ### tecs.sequence.Step record Describes one step a playback will reach without branching. ```teal record tecs.sequence.Step ticks: integer kind: string name: string args: {any} end ``` #### tecs.sequence.Step.ticks field Read-only. Ticks of the program's clock from the reference point until it runs. ```teal tecs.sequence.Step.ticks: integer ``` #### tecs.sequence.Step.kind field Read-only. `"call"` or `"emit"`. ```teal tecs.sequence.Step.kind: string ``` #### tecs.sequence.Step.name field Read-only. Action name for a call, event name for an emit. ```teal tecs.sequence.Step.name: string ``` #### tecs.sequence.Step.args field Read-only. Constants the step carries, unresolved. ```teal tecs.sequence.Step.args: {any} ``` ### tecs.sequence.Target interface Describes the component and one to four numeric fields written by a timeline operation. numeric fields of it to interpolate. Opaque, and built only through `sequence.target`: a built-in such as `sequence.target.translateXY`, or `sequence.target.field(C, "hp")` for a component of your own. Every operation that takes one also accepts a [`TargetName`](/modules/sequence/#tecs.sequence.TargetName) naming the same built-in, which is the form that survives `defineData`. Safe to share between timelines: a target holds no per-playback state. ```teal interface tecs.sequence.Target end ``` ### tecs.sequence.TargetName enum Names a built-in component-field target. ```teal enum tecs.sequence.TargetName "color.a" "color.rgba" "transform.rotation" "transform.rotationShortest" "transform.scaleX" "transform.scaleXY" "transform.scaleY" "transform.x" "transform.xy" "transform.y" end ``` ### tecs.sequence.TimelineNode type Represents one authored timeline operation. ```teal type tecs.sequence.TimelineNode = {any} ``` ### tecs.sequence.TimelineOptions record Configures `timeline`. ```teal record tecs.sequence.TimelineOptions clock: ClockId end ``` #### tecs.sequence.TimelineOptions.clock field Caller-writable. Selects the clock used to evaluate the timeline. It defaults to `"presentation"`, which moves at the display's rate. `"fixed"` makes it deterministic from a snapshot alone, at the cost of stepping at the simulation's rate: the renderer interpolates only [`Transform2D`](/modules/ecs/#tecs.ecs.Transform2D) between fixed steps, so a fixed-clock tween of anything else visibly steps. If the simulation can observe the value, put it on `"fixed"`. ```teal tecs.sequence.TimelineOptions.clock: ClockId ``` ### tecs.sequence.TimelineSpec type Lists timeline operations in execution order. Entries run one after the next, each starting where the one before it ended, except that a `tweenParallel` runs its arguments from a shared start. A nested list is read as a block and behaves the same as one. `timeline` and `tweenRun` compile the resolved form into the same table, consuming the spec. Pass a fresh spec to each timeline. ```teal type tecs.sequence.TimelineSpec = {TimelineNode} ``` ### tecs.sequence.TrackSource interface Provides a live component-field tracking source. ```teal interface tecs.sequence.TrackSource end ``` ### tecs.sequence.TweenOutcome enum Reports how the tween awaited by `waitTween` ended. ```teal enum tecs.sequence.TweenOutcome "canceled" "completed" "replaced" "targetLost" end ``` ## Functions ### tecs.sequence.activeCount Static Returns the number of live playbacks for tests and diagnostics. ```teal function tecs.sequence.activeCount(world: World): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the playbacks. | #### Returns | Type | Description | | --- | --- | | `integer` | Branches counted individually, since a branch is a playback of its own, and so are the playbacks a `playTween` started. | ### tecs.sequence.await Static Waits for work outside the sequencer to finish. A subsystem registers a provider under a name and answers whether the work is still going; this parks the playback until it is not. The sequencer never learns what the work is, which is how a program waits on a sprite animation without the sequencer requiring the renderer. A binding that is missing or dead is not a fault: there is nothing to wait for and the program carries on. So is a provider reporting a thing that never started. sequence.call("game.playTag", sequence.bind("hero"), "hurt"), sequence.await("game.spriteAnimation", sequence.bind("hero")), ```teal function tecs.sequence.await( provider: string, target: EntityRef, key: string ): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `provider` | `string` | Resolved globally when the instruction runs, and checked before the binding: a name no build registered faults the playback with `unregisteredAwaitable`. The runtime asks the provider again at each fixed step boundary while the playback waits. An error faults the playback with `actionError`. | | `target` | [`EntityRef`](/modules/sequence/#tecs.sequence.EntityRef) | A `bind` reference and nothing else, as `playTween`'s is. An entity that dies while the playback waits releases it rather than stranding it for the life of the world. | | `key` | `string` | Handed to the provider unread, for a provider that answers about more than one thing per entity. Nil when omitted, which is what a provider with one answer per entity sees. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.bind Static References an entity supplied through `PlayOptions.bindings`. Resolved when the instruction using it runs, not at `play`, so a binding may name an entity that does not exist yet. ```teal function tecs.sequence.bind(name: string): EntityRef ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | Must be non-empty, and an empty one raises here rather than at `define`. The runtime matches it against `PlayOptions.bindings`. A missing binding resolves to nothing instead of faulting. | #### Returns | Type | Description | | --- | --- | | [`EntityRef`](/modules/sequence/#tecs.sequence.EntityRef) | A reference to put in a `call` or `emit` argument list, or to hand to `playTween` or `await`. The program interns it in the const pool, and each playback resolves it against its own bindings. | ### tecs.sequence.call Static Runs a registered action. ```teal function tecs.sequence.call(action: string, ...: Argument): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `action` | `string` | Resolved per world when the instruction runs, not at `define`, so a program may name an action registered later. A name still unregistered when the step runs faults the playback. | | `...` | [`Argument`](/modules/sequence/#tecs.sequence.Argument) | Compiled into the program's const pool, so they are the same values for every playback of it. Put anything that differs between two playbacks in `PlayOptions.params` instead. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.cancel Static Stops a playback and releases its cursor. This remains safe on a finished handle. It takes the branches it forked with it, and a playback parked in a `waitTween` on the one canceled is told `canceled` and resumes. What a `playTween` started is a playback in its own right and is not canceled with the one that started it, unlike a pause, which cascades to it: stop it through its owner with `cancelOwnedBy`. ```teal function tecs.sequence.cancel(world: World, handle: Handle): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the playback. | | `handle` | [`Handle`](/modules/sequence/#tecs.sequence.Handle) | Read against this world's cursor arena, so one issued by another world is meaningless here rather than reliably ignored. | #### Returns | Type | Description | | --- | --- | | `boolean` | false when the handle names nothing running, whether it already finished or was already canceled. | ### tecs.sequence.cancelOwnedBy Static Cancels every playback owned by an entity. `reason` is what anything waiting on one of them is told. The owner despawning reports `targetLost`, which lets a waiter distinguish cancellation from target loss. ```teal function tecs.sequence.cancelOwnedBy( world: World, owner: integer, reason: TweenOutcome ): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the playbacks. | | `owner` | `integer` | An entity id. A playback started without an owner is nothing owns a playback started without an owner, rather than entity 0, so no argument reaches one and only `cancel` on its handle stops it. | | `reason` | [`TweenOutcome`](/modules/sequence/#tecs.sequence.TweenOutcome) | What a playback parked in a `waitTween` on one of these is told, and what its `status` reports afterwards as `tweenOutcome`. Omitted, a waiter is told `canceled`. | #### Returns | Type | Description | | --- | --- | | `integer` | Returns the number of canceled playbacks, or zero when the entity owns none. The call reaches branches through their inherited owner and counts each cursor once. | ### tecs.sequence.currentStep Static Returns a clock's current tick as counted by the sequencer. It defaults to the fixed clock. ```teal function tecs.sequence.currentStep( world: World, clock: ClockId ): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the clock counters. | | `clock` | [`ClockId`](/modules/sequence/#tecs.sequence.ClockId) | Which of the three counters to read. Omitted, `"fixed"`. | #### Returns | Type | Description | | --- | --- | | `integer` | Ticks of that one clock, rising by one each time the sequencer advances it and by nothing else. It counts from when this world's the world created its sequencer state, not when the process started. A snapshot load puts back the count the snapshot carried. Comparable only against another reading of the same clock. | ### tecs.sequence.dataOps Static Returns the step names accepted by `defineData`, sorted. ```teal function tecs.sequence.dataOps(): {string} ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `{string}` | A fresh table each call, which the caller owns. It is narrower than the node constructors: `await` and `eval` have no data form and are not among them. | ### tecs.sequence.define Static Compiles a program under a stable symbolic name. `options.clock` picks what the program's waits count. `"fixed"`, the default, counts fixed steps and is what gameplay logic wants. `"frame"` counts gameplay frames, one tick per frame however many fixed steps that frame runs, which is what scripted input needs. `"presentation"` also ticks once per gameplay frame carrying the frame's real elapsed time. ```teal function tecs.sequence.define( name: string, nodes: {Node}, options: DefineOptions ): Program ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | Defining over a name already in use publishes a new version rather than replacing the old one: playbacks already running keep the version they started on, and only later `play` calls see the new one. | | `nodes` | `{`[`Node`](/modules/sequence/#tecs.sequence.Node)`}` | Accepts an empty list, which compiles to a program that completes on its first tick. | | `options` | [`DefineOptions`](/modules/sequence/#tecs.sequence.DefineOptions) | Omitted, the program counts fixed steps. A `clock` that is none of the three names raises here. | #### Returns | Type | Description | | --- | --- | | [`Program`](/modules/sequence/#tecs.sequence.Program) | The compiled program, immutable and shared by every playback of it, so the same value plays on any number of worlds. | ### tecs.sequence.defineData Static Compiles a program written as plain data instead of node calls. The same authoring surface as a list of steps, for callers that cannot invoke Lua: a tool over MCP, a file on disk, a hand-written table. Returns nil plus the path to the first bad entry. sequence.defineData("game.intro", { {op = "call", action = "game.lockControls"}, {op = "wait", seconds = 1.5}, }) ```teal function tecs.sequence.defineData( name: string, rows: {any}, options: DefineOptions ): Program, string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | As `define`'s, and sharing its namespace and its versioning. | | `rows` | `{any}` | One table per step, keyed by `op` and the fields that step takes. `dataOps` lists the step names. This function rejects an empty list, unlike `define`, because it has nothing to run. | | `options` | [`DefineOptions`](/modules/sequence/#tecs.sequence.DefineOptions) | As `define`'s. | #### Returns | Type | Description | | --- | --- | | [`Program`](/modules/sequence/#tecs.sequence.Program) | The compiled program, or nil when a row is bad. | | `string` | nil on success; on failure the path to the first bad entry, as `program[2].loop[1]`, and what it was missing. That is why the two are never both set. A row whose shape is right and whose value is not, a negative wait among them, raises instead: the path covers what this decoder checks, not what the node constructors do. | ### tecs.sequence.disassemble Static Renders a program as readable instructions. ```teal function tecs.sequence.disassemble( program: Program, pc: integer ): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `program` | [`Program`](/modules/sequence/#tecs.sequence.Program) | A value from `define` or `timeline`; anything else raises. | | `pc` | `integer` | Mark this instruction, as a playback's `status` reports it. Omit for an unmarked listing. One past the end, or any other address the program does not hold, marks nothing. | #### Returns | Type | Description | | --- | --- | | `string` | A header naming the program and its version, then one line per instruction, newline separated. For reading and not for parsing: the format is free to change. | ### tecs.sequence.emit Static Emits an ECS event at address zero. Occupies no tick: the step after it runs in the same one. ```teal function tecs.sequence.emit(event: string, ...: Argument): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `event` | `string` | Carried as the `sequence.Event`'s name. Observers watch `sequence.Event` itself and filter on this, rather than each name being an event type of its own. | | `...` | [`Argument`](/modules/sequence/#tecs.sequence.Argument) | Const-pool values, as `call`'s are, delivered on the event's `args` with any `bind` reference already resolved to an entity id. Each emit copies the list and sends it with the event, so an observer may keep it, unlike the one an action receives. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.eval Static Evaluates a registered evaluator every tick until it finishes. Unlike every other step, this one does not hand the tick back: the playback joins its clock's active set, and the runtime steps it each tick. Values that move every frame need this behavior. Compilation stores `data` beside the evaluator's name in the program, so it travels with a snapshot and must remain plain data for the same reason a `call` argument does. What the evaluator makes of it is its own business. ```teal function tecs.sequence.eval(evaluator: string, data: any): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `evaluator` | `string` | Resolved globally when the instruction runs, so a program may name an evaluator registered later. A name still unregistered when the step runs faults the playback with `unregisteredEvaluator`, and an evaluator that raises while resolving the data or building its state faults it with `actionError`. | | `data` | `any` | Passed through the evaluator's `resolve` once per program constant and the answer shared by every playback of it, so an evaluator must not write per-playback state into what it gets back. Omit it for an evaluator that needs none. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.fork Static Starts a branch that runs alongside the rest of the program. The branch is a playback of its own running the same program at a different instruction, and it inherits the owner, bindings, params and instruction budget of the playback that forked it. It starts once that playback next waits, joins, or ends, within the same tick. A branch never outlives the playback that forked it: finishing or canceling that playback cancels the branches it has not joined. A branch that faults takes its parent with it, faulted `branchFaulted`, rather than leaving a `join` one branch short forever. ```teal function tecs.sequence.fork(nodes: {Node}): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `nodes` | `{`[`Node`](/modules/sequence/#tecs.sequence.Node)`}` | The branch body, run in order. Must be non-empty. It reads and writes the forking playback's own bindings table rather than a copy, so both see any name an action binds. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.hasAction Static Returns whether this world has registered an action name. ```teal function tecs.sequence.hasAction(world: World, name: string): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the action registry. | | `name` | `string` | The caller supplies the action name to find. | #### Returns | Type | Description | | --- | --- | | `boolean` | false for a name this world never registered, including one another world has: actions are per world. | ### tecs.sequence.hasQuery Static Returns whether this world has registered a query name. ```teal function tecs.sequence.hasQuery(world: World, name: string): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the query registry. | | `name` | `string` | The caller supplies the query name to find. | #### Returns | Type | Description | | --- | --- | | `boolean` | false for a name this world never registered, including one another world has: queries are per world. | ### tecs.sequence.join Static Waits for every branch that has not yet joined. Falls straight through when there are none. When the last branch finishes, the waiting playback resumes within that same tick. ```teal function tecs.sequence.join(): Node ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.loop Static Repeats a block. ```teal function tecs.sequence.loop(count: integer, nodes: {Node}): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `count` | `integer` | Iterations, or nil to repeat until canceled. A positive whole number. This function rejects zero and fractions. | | `nodes` | `{`[`Node`](/modules/sequence/#tecs.sequence.Node)`}` | The block, run in order and started again from its first node. Must be non-empty. A block with no wait in it spends the playback's per-step instruction budget within one tick and faults it with `budgetExceeded`, which is what that budget is for. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.parallel Static Forks several blocks and waits for all of them. Sugar for a `fork` per block followed by one `join`. Blocks start in argument order. ```teal function tecs.sequence.parallel(...: {Node}): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `...` | `{`[`Node`](/modules/sequence/#tecs.sequence.Node)`}` | Supplies at least one non-empty node list, one per branch. Each shares the playback's bindings table, as a `fork` does. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.pause Static Suspends a playback, its branches, and anything it started. Pause is holder counted: two systems can hold the same playback for unrelated reasons, and it runs again only when the last one lets go, so whichever resumes first cannot undo the other. `holder` names who is holding it and defaults to `"user"`. Its wait, if any, resumes from where it paused. What it is waiting on stops with it when the awaitable provider knows how. ```teal function tecs.sequence.pause( world: World, handle: Handle, holder: string ): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the playback. | | `handle` | [`Handle`](/modules/sequence/#tecs.sequence.Handle) | The caller supplies the playback to pause. | | `holder` | `string` | Any string, and a set rather than a count: two pauses under the same holder are one hold, and one `resume` under it releases both. Two callers that both leave it at the default therefore share a single hold. | #### Returns | Type | Description | | --- | --- | | `boolean` | Whether the playback stopped. A second holder taking a hold on one that is already paused registers the hold and returns false, because nothing observable changed. So does a handle that names nothing running. | ### tecs.sequence.play Static Starts a program. The first instruction runs on the next tick of the program's own clock, never inside this call. ```teal function tecs.sequence.play( world: World, program: Program, options: PlayOptions ): Handle ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the new playback. | | `program` | [`Program`](/modules/sequence/#tecs.sequence.Program) | A value from `define` or `timeline`, not a name. The playback runs this version for its whole life, even if another `define` replaces the name. Anything other than a compiled program raises. | | `options` | [`PlayOptions`](/modules/sequence/#tecs.sequence.PlayOptions) | Omitted, the playback has no owner, no bindings, no params, no channel, and the world's instruction budget. Taking a channel another playback on the same owner holds cancels that one first, reporting `replaced` to anything waiting on it. | #### Returns | Type | Description | | --- | --- | | [`Handle`](/modules/sequence/#tecs.sequence.Handle) | A handle to the new playback, valid until it ends. A handle carries a generation, so one whose playback has ended never names a later playback that took the same slot. | ### tecs.sequence.playbacks Static Returns handles for every live playback, branches included, in a stable order. For diagnostics and the debugger, not for hot paths. ```teal function tecs.sequence.playbacks(world: World): {Handle} ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the playbacks. | #### Returns | Type | Description | | --- | --- | | `{`[`Handle`](/modules/sequence/#tecs.sequence.Handle)`}` | Returns a fresh table ordered by cursor slot. Slot order remains stable within a run but differs from creation order because new playbacks reuse free slots. The table also includes playbacks started by `playTween`. | ### tecs.sequence.playTween Static Plays a registered tween preset on a bound entity. Needs the sequencer, which `tecs.newApplication` installs. A binding that is missing or dead is not a fault: nothing plays, and a following `waitTween` resumes at once reporting `targetLost`. The step itself costs no tick. It starts a separate playback owned by the bound entity, running on the named program's clock and using this playback's instruction budget. ```teal function tecs.sequence.playTween( timeline: string, target: EntityRef, params: {string: any} ): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `timeline` | `string` | Resolved when the instruction runs, and always to the newest version of the name; any program defined under it will do, though `timeline` is what normally publishes one. A name that is not defined faults the playback with `unregisteredTween`. | | `target` | [`EntityRef`](/modules/sequence/#tecs.sequence.EntityRef) | A `bind` reference and nothing else: an entity id raises here, for the same reason `define` rejects one as a constant. | | `params` | `{string : any}` | The started playback's `params`, so `mode`, `count`, `speed` and `delay` shape it as they do for `play`. A `channel` in it names the slot the playback takes on that entity, canceling whatever held the slot and reporting `replaced` to anything waiting on it. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.plugin Static Installs the sequencer. `tecs.newApplication` installs it automatically, and it remains safe to call again: a second install on the same world does nothing. ```teal function tecs.sequence.plugin(world: World) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world receives sequencer state and systems. | #### Returns None. ### tecs.sequence.program Static Returns the newest version of a defined program or a requested version. Every version a playback still runs stays reachable. ```teal function tecs.sequence.program( name: string, version: integer ): Program ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | The caller supplies a name previously passed to `define` or `timeline`. | | `version` | `integer` | Versions start at 1 and rise by one per `define` of the same name. Omit it for the newest. | #### Returns | Type | Description | | --- | --- | | [`Program`](/modules/sequence/#tecs.sequence.Program) | nil when the name was never defined, or when that version was after a newer definition replaces it and its last playback ends. The newest version of a name is never dropped. | ### tecs.sequence.programNames Static Returns the names of every defined program, sorted. ```teal function tecs.sequence.programNames(): {string} ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `{string}` | A fresh table each call, which the caller owns. Registration is global, so this spans every world in the process. | ### tecs.sequence.registerAction Static Registers an action that a `call` node can name. Actions must obey the deterministic-action contract to keep replay and rewind meaningful: no wall-clock reads, no file or network access, and randomness only from a generator whose state travels with the snapshot. ```teal function tecs.sequence.registerAction( world: World, name: string, action: Action ) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the action registry. | | `name` | `string` | Per world, unlike an evaluator or an awaitable. Registering it twice replaces the action, and a playback resolves the name at each `call`, so one already running picks the new one up. An empty name raises. | | `action` | [`Action`](/modules/sequence/#tecs.sequence.Action) | Must be a function, or this raises. Raising when it runs faults the playback with `actionError`, and whatever it already wrote to the world stays written: the sequencer rolls nothing back. | #### Returns None. ### tecs.sequence.registerAwaitable Static Registers a provider that an `await` step can name. Registration remains global, like an evaluator, because a provider is code. ```teal function tecs.sequence.registerAwaitable( name: string, provider: Awaitable ) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | Registering a name twice replaces the provider, which is what a hot reload wants: a playback already parked on the name asks the new one at the next step. An empty name raises. | | `provider` | [`Awaitable`](/modules/sequence/#tecs.sequence.Awaitable) | Must carry `isPending`, or this raises. `setPaused` is optional. Without it, the provider leaves its work running when a pause stops the waiting playback. | #### Returns None. ### tecs.sequence.registerEvaluator Static Registers an evaluator that an `eval` step can name. Registration is global, like a program: an evaluator is code, and two worlds evaluating the same name run the same thing. ```teal function tecs.sequence.registerEvaluator( name: string, evaluator: Evaluator ) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | Registering a name twice replaces it. An empty name raises. | | `evaluator` | `Evaluator` | Must carry `step`, or this raises. The rest are optional, and without `save` and `load` a playback evaluating this name comes back from a snapshot at the start of its state rather than where it was. | #### Returns None. ### tecs.sequence.registerQuery Static Registers a query that a `waitQuery` step can name. The query subscribes to archetype transitions, so a wait on it stays event driven rather than polling. Registration is startup work: a name registered twice keeps the newer query, and the replaced one holds its subscriptions for the life of the world. ```teal function tecs.sequence.registerQuery( world: World, name: string, descriptor: types.Query.Descriptor ) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the query registry. | | `name` | `string` | Empty raises. Registering it again re-tests every playback already parked on the name, against the new query, at the next fixed step. | | `descriptor` | [`types.Query.Descriptor`](/modules/ecs/#tecs.Query.Descriptor) | The function copies this descriptor and wraps its `onEntitiesAdded` and `onEntitiesRemoved` callbacks. It marks the name before calling the supplied callbacks. A non-table raises. | #### Returns None. ### tecs.sequence.resume Static Releases one holder's claim. ```teal function tecs.sequence.resume( world: World, handle: Handle, holder: string ): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the playback. | | `handle` | [`Handle`](/modules/sequence/#tecs.sequence.Handle) | The caller supplies the paused playback. | | `holder` | `string` | Must be the string that took the hold; releasing one that never held it changes nothing. Defaults to `"user"`, as `pause`'s does. | #### Returns | Type | Description | | --- | --- | | `boolean` | Whether the playback started running again, which is only true for the last holder to let go. A wake time that passed while it was held runs it on the next tick rather than immediately. | ### tecs.sequence.setInstructionBudget Static Sets the per-step instruction budget for playbacks without their own. ```teal function tecs.sequence.setInstructionBudget( world: World, instructions: integer ) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world applies the budget to new playbacks. | | `instructions` | `integer` | Must be at least 1. It caps how many instructions one playback runs per tick, and exceeding it faults the playback with `budgetExceeded` rather than deferring the rest, so it is a guard against a `loop` with no wait in it, not a scheduler. Applies to playbacks started after this call; a running one keeps the budget it started with. | #### Returns None. ### tecs.sequence.signal Static Raises a named signal and wakes every playback blocked on it. Delivery happens on the next fixed step. Raising a signal nothing is waiting on is not an error and is not remembered: a playback that reaches `waitSignal` afterwards keeps waiting. ```teal function tecs.sequence.signal(world: World, name: string): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the signal state. | | `name` | `string` | Any string, registered nowhere. An empty one raises. | #### Returns | Type | Description | | --- | --- | | `integer` | Returns the number of playbacks waiting on the name now. The next fixed step wakes the set waiting then, which may differ. | ### tecs.sequence.signalOnEvent Static Raises a signal whenever an event emits at address zero. An ECS event is an edge, like a signal, so this wires one to the other rather than adding a separate kind of wait. Delivery follows the ordinary signal rule: waiters wake on the next fixed step. ```teal function tecs.sequence.signalOnEvent( world: World, name: string, event: T ) ``` #### Type Parameters | Name | Constraint | Description | | --- | --- | --- | | `T` | [`events.Event`](/modules/events/#tecs.events.Event) | | #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the event observer and signal state. | | `name` | `string` | The signal to raise, once per emission. An empty one raises. | | `event` | `T` | Observed at address 0, and only there. The observer lasts for the life of the world; wiring the same pair twice observes it twice, and there is nothing that unwires one. | #### Returns None. ### tecs.sequence.status Static Returns playback status, or nil for a handle this world never issued. ```teal function tecs.sequence.status(world: World, handle: Handle): Status ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the playback. | | `handle` | [`Handle`](/modules/sequence/#tecs.sequence.Handle) | Read against this world's cursor arena, as `cancel`'s is. | #### Returns | Type | Description | | --- | --- | | [`Status`](/modules/sequence/#tecs.sequence.Status) | A fresh table each call, which the caller owns. A finished playback still answers, with `state` saying how it ended, until its a later `play` takes its slot. The runtime fills waiting fields only while the playback lives, so a finished playback reports its program, the `pc` it stopped at, how it ended and its last tween outcome, with the rest nil. | ### tecs.sequence.timeline Static Compiles a tween timeline into a program under a stable name. The compiled slots travel in the program's const pool, so a timeline is snapshot-safe for the same reason every other program is. Play it with `play`, giving the entity it animates as the `owner`. It reads four `params`, all optional: mode "once" (default), "loop", or "pingPong" count passes for a finite loop or ping-pong; endless without it speed playback multiplier, defaulting to 1 delay seconds to wait before the first frame local fade = sequence.timeline("game.fade", { sequence.tweenTo(0.4, "quadOut", "color.a", 0), }) sequence.play(world, fade, {owner = e, params = {delay = 0.2}}) ```teal function tecs.sequence.timeline( name: string, spec: TimelineSpec, options: TimelineOptions ): Program ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | Shared with `define`'s namespace, and versioned the same way: compiling over a live name publishes a new version and leaves playbacks of the old one running it. | | `spec` | [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec) | The compiler consumes this table in place. Do not compile it again. | | `options` | [`TimelineOptions`](/modules/sequence/#tecs.sequence.TimelineOptions) | Omitted, the timeline runs on the presentation clock. `"fixed"` and `"presentation"` are the only two accepted; `"frame"` raises, though `define` takes it. | #### Returns | Type | Description | | --- | --- | | [`Program`](/modules/sequence/#tecs.sequence.Program) | The compiled program, also reachable by name through `program`. Play it on an entity: a playback with no `owner` has nothing to write to and completes on its first tick without animating anything. The `params` above are read when that playback builds its state, so a `speed` of zero or less, a negative `delay`, or a repeat of a zero-length timeline faults the playback with `actionError` rather than raising from `play`. | ### tecs.sequence.tweenAdjust Static Interpolates by a relative delta from the starting value. Identical to `tweenTo` except that `t1` through `t4` are the amount to move by rather than where to end up, so the destination depends on the entity's value when the operation evaluates its first tick. ```teal function tecs.sequence.tweenAdjust( duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, t1: number, t2: number, t3: number, t4: number ): TimelineNode ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `duration` | `number` | Seconds, and strictly positive. | | `curve` | [`EasingName`](/modules/sequence/#tecs.sequence.EasingName) | [`EasingFunction`](/modules/sequence/#tecs.sequence.EasingFunction) | As `tweenTo`'s, and built in for the same reason. | | `target` | [`TargetName`](/modules/sequence/#tecs.sequence.TargetName) | [`Target`](/modules/sequence/#tecs.sequence.Target) | Which component fields move, and in which order `t1` through `t4` line up with them. | | `t1` | `number` | Change applied to the target's first field, in that field's own units, and signed: negative moves the other way. | | `t2` | `number` | Change applied to the second field. | | `t3` | `number` | Change applied to the third field. | | `t4` | `number` | Change applied to the fourth field. An argument past the The compiler ignores arguments past the target's field count and treats an omitted argument as zero. | #### Returns | Type | Description | | --- | --- | | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | Returns a node for a [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec). Its compiling timeline consumes it. | ### tecs.sequence.tweenEmit Static Emits a named `sequence.Event` when the cursor reaches this point. Occupies no time, so what follows it starts at the same instant. The event carries the entity the timeline is animating as its one argument, and the timeline's own playback as its handle. It fires as the cursor passes the point going forward, so a `pingPong`'s return leg does not fire it a second time. ```teal function tecs.sequence.tweenEmit(name: string): TimelineNode ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | Carried on the event as its name; the sequencer attaches no meaning to it. | #### Returns | Type | Description | | --- | --- | | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | Returns a node for a [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec). | ### tecs.sequence.tweenParallel Static Runs timeline nodes concurrently and ends with the longest. Every argument starts at the point the `tweenParallel` sits at, and what follows starts after the last of them ends. Two arguments writing the same component field is not an error and the later one in argument order wins each tick. ```teal function tecs.sequence.tweenParallel(...: TimelineNode): TimelineNode ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `...` | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | One node per concurrent operation. A list of nodes counts as one argument and runs in sequence within it, which describes a branch longer than one operation. | #### Returns | Type | Description | | --- | --- | | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | Returns a node for a [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec). | ### tecs.sequence.tweenRun Static Runs a nested timeline from its own spec. The nested timeline occupies a window of the parent equal to its own length times its pass count, so a repeating nested run needs a finite `count`. Its own operations keep their per-playback state separately from the parent's. ```teal function tecs.sequence.tweenRun( spec: TimelineSpec, options: RunOptions ): TimelineNode ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `spec` | [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec) | Compiled in place if it has not been already, so the table given here belongs to this node afterwards. | | `options` | [`RunOptions`](/modules/sequence/#tecs.sequence.RunOptions) | Omit to run the nested timeline once. `"loop"` and `"pingPong"` need a `count` here, and compiling raises without one. | #### Returns | Type | Description | | --- | --- | | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | Returns a node for a [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec). | ### tecs.sequence.tweenTo Static Interpolates to an absolute destination. The operation reads starting values from the entity on its first tick, not during compilation, so the same timeline played on two entities starts from wherever each of them is. ```teal function tecs.sequence.tweenTo( duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, t1: number, t2: number, t3: number, t4: number ): TimelineNode ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `duration` | `number` | Supplies a strictly positive number of seconds. The compiler rejects zero. Use `tweenWait` for a gap that moves nothing. | | `curve` | [`EasingName`](/modules/sequence/#tecs.sequence.EasingName) | [`EasingFunction`](/modules/sequence/#tecs.sequence.EasingFunction) | A name from `sequence.easing`, or one of those functions itself. The compiler rejects a custom curve: a compiled slot carries the curve's name so it can travel in a const pool, and a function it cannot name has none. | | `target` | [`TargetName`](/modules/sequence/#tecs.sequence.TargetName) | [`Target`](/modules/sequence/#tecs.sequence.Target) | Which component fields move, and in which order `t1` through `t4` line up with them. | | `t1` | `number` | Destination for the target's first field, in that field's own units: pixels for a translate, radians for a rotation, 0 to 1 for a color channel. A shortest-path rotation target still takes an absolute angle and picks the short way round to it. | | `t2` | `number` | Destination for the second field, for a target that has one. | | `t3` | `number` | Destination for the third field, for a four-field target. | | `t4` | `number` | Destination for the fourth field, for a four-field target. The compiler ignores arguments past the target's field count and treats each omitted target field as zero. | #### Returns | Type | Description | | --- | --- | | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | Returns a node for a [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec). Its compiling timeline consumes it. | ### tecs.sequence.tweenTrack Static Interpolates toward a destination that keeps moving. The first tick fixes the start, as with `tweenTo`, but each later tick reads the destination again from `from` while the operation remains inside its window, so the entity chases a value that is still changing. Once the window ends, the operation holds its last destination. ```teal function tecs.sequence.tweenTrack( duration: number, curve: EasingName | EasingFunction, target: TargetName | Target, from: TrackSource ): TimelineNode ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `duration` | `number` | Seconds, and strictly positive. | | `curve` | [`EasingName`](/modules/sequence/#tecs.sequence.EasingName) | [`EasingFunction`](/modules/sequence/#tecs.sequence.EasingFunction) | As `tweenTo`'s. It shapes how far toward the current destination the value sits, and that destination keeps moving underneath it. | | `target` | [`TargetName`](/modules/sequence/#tecs.sequence.TargetName) | [`Target`](/modules/sequence/#tecs.sequence.Target) | Which component fields move, and which fields of `from` line up with them: the source is read into the same one to four numbers the target writes. | | `from` | [`TrackSource`](/modules/sequence/#tecs.sequence.TrackSource) | Where the destination is read each tick. A source whose entity or component is missing reads as zero rather than faulting, so an entity chasing something that despawned drifts to the origin. A source named by world key is the exception and requires the key to be set. | #### Returns | Type | Description | | --- | --- | | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | Returns a node for a [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec). Its compiling timeline consumes it. | ### tecs.sequence.tweenWait Static Advances the timeline cursor without changing anything. ```teal function tecs.sequence.tweenWait(duration: number): TimelineNode ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `duration` | `number` | Supplies seconds. Zero performs no work. | #### Returns | Type | Description | | --- | --- | | [`TimelineNode`](/modules/sequence/#tecs.sequence.TimelineNode) | Returns a node for a [`TimelineSpec`](/modules/sequence/#tecs.sequence.TimelineSpec). | ### tecs.sequence.upcoming Static Returns the actions a playback will certainly perform next and their timing. Walks the straight-line run ahead of where it sits, accumulating waits, and stops at the first instruction whose successor requires execution. It counts ticks in the playback's own clock, from now. ```teal function tecs.sequence.upcoming( world: World, handle: Handle, withinTicks: integer ): {Step} ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the playback. | | `handle` | [`Handle`](/modules/sequence/#tecs.sequence.Handle) | The caller supplies the playback to inspect. | | `withinTicks` | `integer` | Report only what is due within this many ticks. Counted in the playback's own clock, from now. Omit for everything the walk can reach. | #### Returns | Type | Description | | --- | --- | | `{Step}` | A fresh table each call, holding the calls and emits ahead in order. Empty for a handle that names nothing running, and also for one parked on a signal, a query, a join, a tween or an evaluator, since none of those has a predictable start. A wait written in seconds also ends the walk, because converting it needs a clock the program does not carry. Each step's `args` is the program's own constant list rather than a copy of it, so read it and do not write to it. A paused playback still answers, counted as though it were running. | ### tecs.sequence.wait Static Waits for a duration in seconds. Converted to whole ticks when the instruction runs, rounded to nearest, with any non-zero duration waiting at least one tick. A program on the fixed clock divides the duration by the world's fixed timestep; the frame and presentation clocks both tick once per frame, so both divide by the loop's nominal frame dt. Programs therefore stay independent of any one world's timing, and the same duration is the same wall-clock wait on all three. Use `waitSteps` when the exact tick count matters more than the wall-clock duration. ```teal function tecs.sequence.wait(seconds: number): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `seconds` | `number` | Supplies a non-negative duration. This function rejects a negative value. Zero still costs a tick: the cursor resumes on the program's next tick rather than carrying on within this one, so no duration makes `wait` free. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.waitingOn Static Returns how many playbacks currently wait on a signal name. ```teal function tecs.sequence.waitingOn(world: World, name: string): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `world` | [`World`](/modules/ecs/#tecs.World) | The world owns the waiting playbacks. | | `name` | `string` | The caller supplies the signal name to count. | #### Returns | Type | Description | | --- | --- | | `integer` | 0 for a name nothing waits on, including one never signaled. Counts current waiters. A signal raised during this step remains in the count until the next step delivers it. | ### tecs.sequence.waitQuery Static Blocks until a registered query matches or stops matching. Unlike a signal, which is an edge, this is a condition on the world: a wait whose condition already holds resumes rather than waiting for a transition that has already happened. The runtime evaluates the condition at the start of the next fixed step, never at the instruction itself, so it never reads a world that a spawn or the world has not committed a current-step despawn yet. A query wait therefore costs at least one step. ```teal function tecs.sequence.waitQuery( name: string, condition: QueryCondition ): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | Resolved per world when the instruction runs, not at `define`, so a program may name a query registered later. A name still unregistered when the step runs faults the playback with `unregisteredQuery`. | | `condition` | [`QueryCondition`](/modules/sequence/#tecs.sequence.QueryCondition) | Rejected here, not at compile time, when it is neither `"any"` nor `"empty"`. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.waitSignal Static Blocks until `signal` raises the named signal. The next fixed step delivers signals after `signal` runs, so a signal raised by one sequence never runs another within the same step. That bounds a chain of signals to one link per step and keeps delivery order independent of which cursor happened to run first. Delivery runs on the fixed clock whatever clock the program is on, so a frame or presentation program wakes at its own clock's next tick after the fixed step that delivered it. ```teal function tecs.sequence.waitSignal(name: string): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | Matched by value against `signal`'s, and registered nowhere: any string names a channel. A name nothing raises parks the playback until something cancels it, because a signal raised before the wait is not remembered. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.waitSteps Static Waits for a whole number of ticks of the program's clock. `waitSteps(0)` yields: the cursor resumes on its program's next tick rather than continuing within the current one. ```teal function tecs.sequence.waitSteps(steps: integer): Node ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `steps` | `integer` | Ticks of the program's own clock, so a program defined against `"frame"` or `"presentation"` counts those and not fixed steps. This function requires a non-negative whole number. | #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ### tecs.sequence.waitTween Static Waits for the tween started by the most recent `playTween`. Resumes when that specific playback completes, gets canceled, loses its channel, or loses its entity, so it never waits forever. `status` reports the outcome as `tweenOutcome`. A `waitTween` that no `playTween` in this playback preceded falls straight through without costing a tick. ```teal function tecs.sequence.waitTween(): Node ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | [`Node`](/modules/sequence/#tecs.sequence.Node) | A node for `define`, and not to be put in a second program. | ## Values ### tecs.sequence.easing variable Read-only. Exposes built-in easing curves such as `sequence.easing.quadOut`. ```teal tecs.sequence.easing: tweeneval.Easings ``` ### tecs.sequence.Event variable Read-only. Exposes the event emitted by an `emit` step at address zero. ```teal tecs.sequence.Event: seqtypes.Event ``` ### tecs.sequence.source variable Read-only. Exposes sources from which `tweenTrack` reads changing values: `sequence.source.own(Transform2D, "x")`. ```teal tecs.sequence.source: tweeneval.Sources ``` ### tecs.sequence.target variable Read-only. Exposes built-in targets and constructors for new ones: `sequence.target.translateX`, `sequence.target.field(C, "hp")`. ```teal tecs.sequence.target: tweeneval.Targets ``` ### tecs.sequence.TrackingTarget variable Read-only. Exposes the component that selects a dynamic tracking-source entity. ```teal tecs.sequence.TrackingTarget: tweeneval.TrackingTarget ```