Skip to content

Create an event automation

An event automation is a module that runs automatically every time a matching game event occurs — no button required. heliana watches the Squad server log in real time and starts the module when the event arrives from a server in its scope.

See all available event types in the Event types reference.

  1. In Automations, click New automation. The editor opens on its own screen with an empty module; there is no type to pick — the header trigger sets it. To start from a working module, paste one from the examples.
  2. Set the header name to something descriptive; it is what the list and the run history show.
  3. In the header trigger, write kind: 'event' and set event to a key — select the event that should fire this automation:
    • chat — any player chat message
    • join — a player connecting
    • leave — a player disconnecting
    • teamkill — a player killed a teammate
    • death — a death that is not a teamkill
    • broadcast — an admin broadcast
    • marker — a player placed a map marker
    • capture — a capture zone was captured or neutralized
    • deployed — a deployable spawned
    • map — the map changed
    • round — a round ended
  4. Write run(ctx): read the event through ctx.event, decide with an ordinary if, and act with ctx.rcon, ctx.ban, ctx.note or ctx.fetch. See Write conditions and the Run context reference.
  5. To space runs out, add pause to the header — see Pause an automation. To wait for the N-th matching event, declare a counter — see Declare a counter below.
  6. Press Test run and read Would call and Output. A test run calls nothing on the server. With more than one server, pick the Test server; Test player takes a player ID. A test run carries no event: ctx.event is empty in it, so a module that reads the event has nothing to read there.
  7. A new automation is Enabled, so it runs as soon as it is saved; switch it to Disabled to save it off. Then click Save.
  8. Under the editor, Servers says where the automation runs. A new automation starts on All servers; picking named servers narrows it, and clearing the field returns it to All servers. To stop an automation everywhere, switch it to Disabled.

A complete event module, adapted from the teamkill-escalation example:

import { defineAutomation } from '@heliana/automation'
export default defineAutomation({
game: 'squad',
name: 'Teamkill escalation',
pause: { for: '10m', per: 'player' },
async run(ctx) {
const bans = Number(await ctx.player.bansCount())
if (bans >= 3) {
await ctx.ban({ for: 'permanent', reason: 'Repeat teamkiller', servers: 'all' })
return
}
await ctx.note('Teamkill recorded')
await ctx.rcon('AdminBroadcast Teamkilling is a bannable offence.')
},
trigger: { event: 'teamkill', kind: 'event' },
})

A new organization has no event automations: write your own or paste one from the examples. Download, Copy and Import move a module in and out of the editor as a file.

A counter answers “how many times has this player done this, lately”. A pause spaces runs out; it cannot make an automation hold off until the N-th offence. A counter can, and it keeps no state of its own — it is recomputed from the event history before each run, so a restart doesn’t reset it.

  1. Add counters to the header. Each entry is a key — what you refer to it by, kept short: tk, deaths, spam — with three literal fields under it:
    • event — which event gets counted. It does not have to be the event of the trigger: a chat automation can read a counter over teamkills.
    • window — a duration such as 1h or 300s, counted back from now.
    • per: 'actor' — the counter always counts the acting player, so ctx.counter.tk on a teamkill event means “teamkills by this attacker”, not against them.
  2. Read it in run as ctx.counter.<name> and compare it like any number.
import { defineAutomation } from '@heliana/automation'
export default defineAutomation({
counters: { tk: { event: 'teamkill', per: 'actor', window: '1h' } },
game: 'squad',
name: 'Teamkill warn and ban',
async run(ctx) {
if (ctx.counter.tk >= 7) {
await ctx.ban({ for: '1h', reason: 'Teamkilling', servers: 'all' })
return
}
await ctx.rcon(`AdminWarn "${ctx.player.name}" Stop teamkilling (${ctx.counter.tk}).`)
},
trigger: { event: 'teamkill', kind: 'event' },
})

The header is read without running the code, so counters, like every header field, are literals only. See Module header for the exact shape.

To edit an automation, find it in the Automations table and click Edit; the editor reopens with the current module. The row menu holds History, which lists its runs, and Delete, which deletes the automation after you confirm.