class: SpecterInputSequence

A builder class used to generate mathematically accurate timelines of input data. Instead of firing simple one-off keys, SpecterInputSequence allows you to define complex patterns (like joystick circles or fighting game combos) and stream them frame-by-frame to Unreal Engine using Specter's high-resolution execution loop.

How it Works

Once you build an input sequence, you can play it on the entire world or localized to a specific actor using world.playSequence(seq) or actor.playSequence(seq). The framework yields to the Node.js event loop using performance.now() to guarantee hyper-accurate delivery of input frames to the engine.

sequence.addAxisCircle

Generates a perfect analog circle using Math.sin and Math.cos on two axes.

Usage

import { SpecterInputSequence } from '@specter-automation/test';

// Does two full circles on the left thumbstick over 1.5 seconds
const spinAttack = new SpecterInputSequence()
    .addAxisCircle('Gamepad_LeftX', 'Gamepad_LeftY', 0, 1500, 2);

await world.playSequence(spinAttack);

Arguments

  • xAxisstring
    The X axis name (e.g. 'Gamepad_LeftX').
  • yAxisstring
    The Y axis name (e.g. 'Gamepad_LeftY').
  • startTimeMsnumber
    When the circle should begin in the timeline.
  • durationMsnumber
    How long the circle should take to complete.
  • rotationsnumber
    Number of 360-degree rotations to perform.

Returns

  • SpecterInputSequence (this)

sequence.addAxisSweep

Smoothly interpolates an analog axis from a start value to an end value over time. Perfect for triggers or racing games.

Usage

const accelerate = new SpecterInputSequence()
    // Squeeze the right trigger from 0% to 100% over 2 seconds
    .addAxisSweep('Gamepad_RightTrigger', 0.0, 1.0, 0, 2000);

await playerCar.playSequence(accelerate);

Arguments

  • axisstring
    The axis name (e.g. 'Gamepad_RightTrigger').
  • startValuenumber
    The initial value (e.g. 0.0).
  • endValuenumber
    The final value (e.g. 1.0).
  • startTimeMsnumber
    When the sweep begins.
  • durationMsnumber
    How long the interpolation lasts.

Returns

  • SpecterInputSequence (this)

sequence.addCombo

Strings together an array of button states with precise delays between them. Perfect for fighting game inputs.

Usage

const hadouken = new SpecterInputSequence()
    .addCombo(0, 100, [
        { 'Gamepad_DPad_Down': 'Pressed' },
        { 'Gamepad_DPad_Down': 'Released', 'Gamepad_DPad_Right': 'Pressed' },
        { 'Gamepad_FaceButton_Bottom': 'Pressed' }, // Punch!
        { 'Gamepad_FaceButton_Bottom': 'Released', 'Gamepad_DPad_Right': 'Released' }
    ]);

// Play the combo and loop it 3 times!
await world.playSequence(hadouken, { loops: 3 });

Arguments

  • startTimeMsnumber
    When the combo should start.
  • frameDelayMsnumber
    The time delay in milliseconds between each step of the combo.
  • keyframesArray<Record<string, string>>
    An array of key states (e.g. { 'Gamepad_DPad_Down': 'Pressed' }).

Returns

  • SpecterInputSequence (this)

sequence.addKeyframe

The low-level base method for defining procedural patterns. Adds a single explicit state of inputs at a specific timestamp.

Usage

// Example of creating a custom procedural easing curve
const customAim = new SpecterInputSequence();

for (let t = 0; t <= 1000; t += 16) {
    const easeInQuad = (t / 1000) * (t / 1000);
    customAim.addKeyframe(t, { axes: { 'Gamepad_RightX': easeInQuad } });
}

Arguments

  • timeMsnumber
    The exact timestamp for this frame.
  • stateObject
    The state of the inputs, e.g. { axes: { ... }, buttons: { ... } }.

Returns

  • SpecterInputSequence (this)