Effect Action Catalog

Effects are the data-driven extension surface for the engine. Every effect (artifact proc, passive bonus, status reaction, weapon-trigger reward) is a list of actions evaluated by the effect engine when its trigger fires and its conditions pass. An action is a small structured object — { type, params } — and its type selects one of the twenty built-in executors documented here. Numbers, strings, and booleans in params may be raw literals or expressions; they are resolved against the effect instance’s value bag at dispatch time.

All actions assume conditions have already been checked. They do not gate themselves. They mutate game state through existing systems — stat modifiers, damage pipeline, projectile lists, VFX queues — rather than reimplementing those systems. When the built-in vocabulary is not enough, an effect can call out to a named custom handler via the custom action.

The actions are grouped here by intent. Within each group, every action is described by its type string, what it does, and the params it reads.

Damage

These actions deal HP loss to enemies, directly or through ricochet effects.

  • damage_aoe — applies damage to every enemy inside a circle. damage is the value; radius is the circle’s size in world units; damageMode is flat for raw HP or hpPct to multiply each enemy’s max HP; center is ship (default) or signal to use the triggering signal’s (num1, num2) coordinates. Optional falloff: set falloff: 'linear' plus falloffFar to scale damage from the inputted value at the center down to falloffFar at the radius edge.

Healing

Two healing executors — one for HP, one for shields.

  • heal — restores HP. amount is the base value; mode is flat (default), percentMax (amount times hpMax), or percentMissing (amount times the missing-HP gap). Clamps to hpMax. Fires the player_healed signal with the actual amount restored.
  • heal_shield — restores shield. amount and mode (flat or percentMax) behave like heal but read shieldMax and write to ship.shield. Does not fire a signal.

Buffs (self)

Short-lived defensive grants and direct ship-state writes.

  • grant_invuln — sets the ship’s invulnerable flag and extends invulnTimer to at least duration seconds (won’t shorten an existing longer timer).
  • set_heat — overwrites the ship’s heat value directly. value is the new heat level. Used by weapons or artifacts that vent or set heat to a fixed state.

Stat modifiers

These create entries in the modifier pipeline — the same one statlines flow through every frame.

  • modify_stat — adds a single modifier to the ship. stat names the stat; value is the magnitude; mode is flat, percent, or set; duration (0 = permanent until removed); source (tag used to identify and later remove the modifier — defaults to the effect owner); stacking is independent (each application adds a new modifier) or refresh (re-trigger refreshes the existing one); maxStacks caps how many can coexist.
  • modify_stat_scaled — like modify_stat, but the value is interpolated from a ship variable each tick. scaleVar is heat, speed, hp_pct, or shield_pct; scaleMin/scaleMax define the input range; valueAtMin/valueAtMax define the output. The executor strips any prior modifier from the same source on the same stat before adding the new one, so this is the right action for live-tracking auras.
  • modify_upgrade_count — adjusts a global upgrade counter. upgradeId names the bucket in game.upgradeCounts; delta is the integer change. Used by passives that count their own stacks.
  • remove_modifiers — strips every modifier on the ship whose source matches the param. Used to clean up independent-stacked or permanent modifiers when the granting effect ends or is rebuilt.

Debuffs (enemies)

Statuses are applied through applyStatus and live on the enemy entity directly — burning, slowed, stunned, marked, etc. See the enemy-status reference for valid status strings.

  • apply_enemy_status — applies a status to a single enemy identified from the triggering signal’s uid1. status names the type; duration in seconds; value is the status’s payload (damage per tick, slow percent, etc.); maxStacks caps re-application.
  • apply_status_aoe — applies a status to every enemy inside radius. Same status/duration/value/maxStacks semantics as the single-target version. center is ship or signal. Skips dead enemies.

Movement (enemies)

The one built-in physics action — knock targets outward.

  • apply_knockback — pushes every non-pack-leader enemy inside radius directly away from the center point. force is added to each enemy’s velocity along the outward angle. center is ship or signal. Pack leaders are exempt by design so they don’t desync from their formation.

Spawning

Creating new world entities from an effect.

  • spawn_projectile — pushes one or more bullets into the player-bullet list. count is how many; damage, speed, lifetime, color, weaponId, archetype, pierceCount, homingStrength, blastRadius configure each bullet. spread of 360 fans evenly around a circle (with a small jitter); spread > 0 is a degrees-wide cone around the ship’s heading; spread = 0 is a tight fan. originX of signal uses the triggering signal’s coordinates; otherwise origin is the ship.

Weapon empowerment

A short-lived per-weapon damage boost without going through the stat-modifier system.

  • empower_weapon — sets _empowerMult and _empowerShots on one or all of the ship’s weapons. target is random (default — random slot), slot_0 (fixed first slot), or all (every weapon). damageMult is the multiplier; shotsRemaining is how many shots the buff covers.

Signal emission

Effects can re-broadcast on the signal bus, letting one effect chain into another.

  • emit_signal — fires a signal. signal is the event name; str1, num1, num2 ride along. If num1/num2 are omitted and the action was triggered by a signal, that signal’s coordinates pass through.

State

System-level state mutations that don’t fit the other groups.

  • modify_upgrade_count — listed above under stat modifiers; also serves as a state action for counters consumed elsewhere in the engine.

VFX and feedback

Pure visual/audio actions — no gameplay effect. These exist so data-driven effects can emit polish without touching code.

  • flash_artifact — the standard artifact-proc feedback bundle. Pops the artifact’s HUD icon, spawns a bright-then-primary double sonar ring, bursts spark particles in both colors, flashes the ship hull glow in the artifact’s bright color, and (if the artifact defines procAudioCue) plays its audio cue through Juice. Reads the artifact id from the effect owner (artifact:<id> prefix is stripped).
  • vfx — generic VFX dispatcher. type selects the recipe and the rest of params configures it:
    • sonar_ring — single ring with scale, lifetime, color.
    • particles — spark burst with count, speed, color.
    • starburst — radial star particles with count, lifetime.
    • dual_ring — two stacked rings with scale1/scale2 and color/color2.
    • player_glow — flashes the ship hull glow in color.
    • burst_and_ring — spark burst plus a sonar ring in one beat, with count, scale, lifetime, color.

Custom and engine-managed

Two escape hatches for cases the built-in vocabulary can’t reach.

  • custom — invokes a named function from the custom-handler registry. handler selects the function by name; all other params are resolved to numbers (booleans coerce to 0/1) and passed as a record. Used for one-off logic (battering-ram speed restore, multi-step combos) that doesn’t justify a new action type.
  • custom_tick — registered but a no-op when dispatched. custom_tick effects are driven by the engine’s tick loop directly, not by the action dispatcher; this entry exists so the registry has a slot for the type name without errors.

How params are resolved

Every parameter listed above passes through resolveNumber or resolveString before use. That means values can be literals (50, "#ffaa00"), references to the effect instance’s value bag (the engine’s expression system), or computed from previous actions in the same trigger. Defaults shown above apply only when the param is omitted entirely. The dispatcher throws if an action’s type is not in the registry, so a typo in data is caught at the first proc rather than silently no-oping.