EXO Script Timing

This page explains exactly when a script or Smart Action presses something, and how hard it pushes a stick. It also covers the five timing and magnitude randomness controls, with each one's range, default and the exact change it makes to the output.

The engine clock

The EXO's engine works in ticks of 1 ms. When a config carries any script, the engine runs at 1000 Hz, whatever output rate the config is set to. A script never changes the engine rate.

How often a script's main runs

A GPC script does not run every engine tick. It runs once per iteration, and the gap between iterations depends on the kind of script:

Script type Gap between runs of main vm_tctrl(n)
Cronus Zen 10 ms Sets the next gap to 10 + n ms, within 1–40 ms
GPC1 10 ms Sets the next gap to 10 + n ms, within 1–20 ms
Titan Two 1 ms Ignored

What happens in one iteration

  1. Read your controller.
  2. Run init (first iteration only).
  3. Run main.
  4. Run each running combo, in the order they are declared.
  5. Apply remaps.
  6. Build the output.

The output is held between iterations. On a 10 ms Zen script, a button you press at 103 ms reaches the console at 110 ms.

Waits and combos

A combo's wait() moves on once per iteration, so on a 10 ms script every wait rounds up to the next 10 ms:

You write At a 10 ms period it lasts At a 1 ms period it lasts
wait(1) 10 ms 1 ms
wait(40) 40 ms 40 ms
wait(45) 50 ms 45 ms

A combo that main restarts loses one period before it starts again.

Worked example: rapid fire

A rapid fire written as 40 ms on and 40 ms off, restarted from main, runs on a Zen-timed script as 40 ms on and 50 ms off: the extra 10 ms is the restart gap. That is 90 ms per shot, or 11.1 presses per second.

combo Rapid {
    set_val(PS4_R2, 100);
    wait(40);          // 40 ms pressed
    set_val(PS4_R2, 0);
    wait(40);          // 40 ms released, plus one 10 ms period on restart
}

Timing models

  • Zen timing (default): combos step once per iteration, as above.
  • Live timing: combos step every 1 ms, which lowers latency.

Smart Actions always play on the 1 ms engine clock.

Magnitude: how hard a stick or trigger is pushed

In GPC scripts

Control Range
Buttons 0 or 100
Triggers 0 to 100
Sticks -100 to 100
Hi-res sticks -32768 to 32767
Accelerometer 25 = 1 g
Gyro 100 = about 500°/s
Tip In GPC, stick X is positive to the right and stick Y is positive down. So set_val(PS4_RY, 20) pulls the right stick 20% downward. Output values are clamped: 0–100 for buttons and triggers, -100 to 100 for sticks.

In Smart Actions

A stick (aim) step uses a magnitude and an angle instead of X and Y:

  • How far: 0 to 1 of full deflection, shown in the app as 1–100%.
  • Direction: degrees, where 0 = right, 90 = up and 270 = down.
  • Which stick: Aim (right) by default, or Move (left).

So "How far 20%, Direction 270" is a 20% pull straight down. You can also measure a stick step in Turn speed (1–4000 deg/s) instead of stick %.

Sensitivity scale

A Speed step scales a stick for a set time instead of pushing it. It multiplies what you do with that stick.

Field Range Default Meaning
Which stick Aim (right), Move (left) Aim The stick to scale
Speed 0–300%, step 5 100% 100% is unchanged; 50% halves your stick; 200% doubles it
Which way Both, Left / right only, Up / down only Both Which axes are scaled
How long 0–10000 ms, step 100 — How long the scale lasts

Smart Action timing fields

Field Default Range
Press length 80 ms 0–10000 ms
Counts as held after 350 ms 100–2000 ms in the app
Taps must land within (double tap) 300 ms 150–1000 ms in the app
Counts as quick under (tap) 250 ms 80–600 ms in the app
Give up after 10 s up to 30 s
Wait before it can fire again (cooldown) 500 ms 0–60000 ms
How many times 1 1–10
Analog trigger counts as pressed / released 0.6 / 0.4 —

Timing and magnitude randomness

Smart Actions have five controls that vary their output from run to run. Each one changes a specific number in a specific way. Every control set to 0 draws nothing, so a Smart Action with all five at 0 plays exactly the same every time.

Control Range Default Exactly what it changes
1. Per-action variance (Human / Exact timing, "Wobble by up to") 0–500 ms, step 5 15 ms when Human is chosen; 0 for Exact Each timed step's length moves by a random amount within ±V ms, picked once when the step starts. A length never goes below 0. Holds are never varied.
2. Natural timing 0–1, shown as 0–15 ms 0 After control 1, each timed step is lengthened only, by a random 0 to extra ms, where extra = the smaller of (amount × 15) and a quarter of the step's length.
3. Wait variation % 0–50% 0 When set, replaces control 2. Each timed step is lengthened only, by a random 0 to (length × % ÷ 100) ms.
4. Stick variance 0–10 percentage points ±1 Each non-zero stick push moves by a random amount within ±V points of full deflection, picked once per step. It never changes sign. Zero stays zero and a full push stays full. Triggers and mouse MOVE steps are never varied.
5. Aim angle variation 0–15° 0 Each stick push is rotated by a random amount within ±A degrees, picked once per step. A full push is not rotated, and neither is an action set to Exact.
Timing and safety sheet: (A) Human/Exact timing choice, (B) Wobble by up to, (C) Stick variance slider.
Timing and safety sheet: (A) Human/Exact timing choice, (B) Wobble by up to, (C) Stick variance slider.

Worked examples

  • Natural timing at full (15 ms): a 40 ms tap becomes 40–50 ms (the extra is capped at a quarter of 40, which is 10). A 3 ms step stays exactly 3 ms.
  • Wait variation 15%: a 40 ms tap becomes 40–46 ms. A 1 s wait becomes 1000–1150 ms.
  • Per-action variance 15 ms: an 80 ms press lasts anywhere from 65 to 95 ms.
  • Stick variance 2: a 20% pull down lasts its step at somewhere between 18% and 22%.
  • Aim angle variation 5°: a pull at 270° points somewhere between 265° and 275° for that step.

Randomness in GPC scripts

The script engine adds no timing randomness of its own: a script runs exactly as written. A script that wants variation uses rand() itself, for example:

int hold;
combo Tap {
    hold = 40 + (rand() % 10);   // 40 to 49 ms
    set_val(PS4_R2, 100);
    wait(hold);
    set_val(PS4_R2, 0);
    wait(40);
}
Note Check each game's and platform's rules before you use scripts online.

Related: GPC scripts · Smart Actions · Settings reference