Skip to content

Triggers (TriggerType and active_triggers)

Previous: Full Skill Definition Reference · Next: Passive Skills


This page makes clear "what kind of trigger this player input actually counts as":

  • TriggerType — the "kind" of trigger (right-click / left-click / sneak right-click / hold / passive…), 15 in total (server admins mainly use the first 10 click types; the rest are for internal use).
  • active_triggers — the "source" of the trigger (item key press / skill slot hotkey / command / API), 4 in total, defaulting to QI_ACTION.
  • trigger.primary — the skill's primary trigger; it must appear in the graph entry node's triggers, otherwise the skill won't cast.
  • atom mapping — how QinhItems item key presses (atoms) map onto TriggerTypes.

💡 Remember this in one sentence: the "source" decides where this input enters QS (active_triggers); the "kind" decides which skill it routes to (TriggerType). Each handles one end and neither replaces the other.

🖼️ [Image placeholder] A flow diagram of "item key press → QI emits atom → QS normalizes to TriggerType → hits a graph node" · suggested assets/trigger-pipeline.png


1. Full TriggerType set (15 types)

TriggerType is QS's unified enum for "what action this input is." It appears in three places:

  1. The skill definition's trigger.primary (primary trigger);
  2. A graph node's triggers: (which actions this node accepts);
  3. Inside passive skills (passives are uniformly recorded as PASSIVE).
TriggerTypeMeaningTypical use
RIGHT_CLICKright-clickthe most common active skill trigger
LEFT_CLICKleft-clickmelee / basic-attack skills
SHIFT_RIGHT_CLICKsneak + right-clicka "second set" of skills on the same item
SHIFT_LEFT_CLICKsneak + left-clicksame, another set
SHIFT_TOGGLEsneak toggle (press/release sneak)toggle-type skills
DOUBLE_SHIFT_TOGGLEdouble sneak toggle (reserved)not yet implemented, reserved enum
DOUBLE_RIGHT_CLICKdouble right-clickdash, dodge, and other "two quick presses"
DOUBLE_LEFT_CLICKdouble left-clicksame, left-click version
HOLD_RIGHT_CLICKhold right-clickcharge-up / channel opener
HOLD_LEFT_CLICKhold left-clicksustained opener
CI_TESTinternal testing🔧 for internal regression testing, admins don't need it
COMMANDcommand🔧 internal/non-item key: triggered by /qs cast
APIinterface🔧 internal/non-item key: triggered by plugin code calls
PASSIVEpassive🔧 internal/non-item key: passives use it internally (don't write it in primary)
UNKNOWNunknown / internal fallback value🔧 internal: do not use in config, only the fallback when recognition fails

🔧 The 5 marked "internal/non-item key" (CI_TEST / COMMAND / API / PASSIVE / UNKNOWN) aren't meant for item key presses; admins mainly use the first 10 click-type triggers. UNKNOWN is the internal fallback when recognition fails—never write it in config.

⚠️ Case-sensitive, must be all uppercase, copied verbatim. Writing right_click will be treated as an unknown trigger (normalized to UNKNOWN).

How to pick a TriggerType?

  • Single-skill item: RIGHT_CLICK is enough.
  • Want to pack two skills on one weapon: right-click casts A, sneak right-click casts B → RIGHT_CLICK + SHIFT_RIGHT_CLICK.
  • Want an aura/buff that's "press once on, press again off": use SHIFT_TOGGLE with the skill's cast_mode: toggle.
  • Charge-up channeled skill: open with HOLD_RIGHT_CLICK and the skill's cast_mode: channel.

2. active_triggers — active trigger sources (4 types)

TriggerType answers "what action is this"; active_triggers answers "where does this come from." It's a list in the skill yml, defaulting to [QI_ACTION] (i.e. "only accept QinhItems item key presses").

Source typeMeaningHow it triggersNotes
QI_ACTIONQinhItems item key pressplayer presses a key holding a QI item with a skilldefault, most common, this is the default
KEY_SLOTskill slot hotkeyplayer uses a skill slot hotkey to cast the slotted skillrequires slots.active_count (config.yml, default 5)
COMMANDcommand cast/qs cast <skill>testing / command bridges (NI, MI, etc.) go through here
APIinterface callplugin code calls QinhSkillsAPIdeveloper integration
yaml
# default form: equivalent to active_triggers: [QI_ACTION], can be omitted entirely
active_triggers:
  - type: QI_ACTION             # item key press trigger (default)

# example: allow both "item key press" and "skill slot hotkey" sources
active_triggers:
  - type: QI_ACTION
  - type: KEY_SLOT

💡 Most item skills can omit active_triggers entirely—the default QI_ACTION is exactly what you want. Only list it explicitly when connecting to skill slots / command bridges / API.


3. atom mapping — how item key presses become TriggerTypes

QinhItems items are configured with atoms (key atoms). When the item is pressed, QI sends the atom to QS, and QS normalizes it into a TriggerType to match against skills and graphs.

QI item atomnormalized TriggerType
left_clickLEFT_CLICK
right_clickRIGHT_CLICK
shift_left_clickSHIFT_LEFT_CLICK
shift_right_clickSHIFT_RIGHT_CLICK
shift_toggleSHIFT_TOGGLE

Rule of thumb: the item's atom should ideally match the skill's trigger.primary.

  • Atom matches primary: it hits the entry node directly, everything works.
  • Atom doesn't match primary: QS still falls back to the entry node and casts the skill (no misfire), but you lose the fine-grained branching of "right-click and left-click cast different skills."

🔌 For how to configure atoms on the item side, see Connecting QinhItems. Here you just need to remember the mapping.


4. The relationship between trigger.primary and the graph entry node (key section)

This is the pitfall newcomers hit most often. Two iron rules:

  1. trigger.primary must appear in the graph entry node's triggers: list.
  2. If they don't match, the skill won't cast (or the fallback behavior won't be what you expect).

Here are a positive and a negative example.

✅ Correct: primary is inside the entry node's triggers

skills/combat/blade_slash.yml (excerpt from the bundled example):

yaml
trigger:
  primary: LEFT_CLICK           # primary trigger: left-click
graph:
  entry: blade_slash            # corresponds to the graph's entry node name

The matching graphs/combat/blade_slash.graph.yml:

yaml
graph_id: blade_slash
entry: blade_slash
nodes:
  blade_slash:                  # ← entry node
    skill_id: blade_slash
    mythic_skill: blade_slash
    require_state: IDLE
    triggers:
      - LEFT_CLICK              # ✅ primary(LEFT_CLICK) is here, it matches → can cast

❌ Wrong: primary doesn't appear in the entry node

yaml
# in the skill:
trigger:
  primary: RIGHT_CLICK         # primary trigger is right-click
# but the graph entry node:
  fire_wave:
    triggers:
      - LEFT_CLICK             # ❌ only accepts left-click, right-click isn't listed → primary falls through

⚠️ After changing triggers, remember to /qs reload and double-check with /qs info <skill>.


5. A complete small example: one weapon, two skills

Goal: right-click casts fire wave, sneak right-click casts blade slash.

yaml
# skill fire_wave: right-click
trigger:
  primary: RIGHT_CLICK
graph:
  entry: fire_wave

The matching graph entry node lists both triggers and routes them via skills (see the skills: section in config.yml):

yaml
# config.yml — branch to different skills by TriggerType
skills:
  fire_wave:
    RIGHT_CLICK: fire_wave       # right-click → fire wave
    LEFT_CLICK: blade_slash      # left-click → blade slash
    default: fire_wave           # fallback

On the item side, give the same weapon two atoms, right_click and shift_right_click, each matching the primary of one of the two skills.


✅ Self-check list

  • [ ] trigger.primary uses a valid all-uppercase TriggerType.
  • [ ] That primary appears in the graph entry node's triggers:.
  • [ ] The item atom matches the primary (right_clickRIGHT_CLICK).
  • [ ] If connecting to skill slots / command bridges, active_triggers is written explicitly.
  • [ ] After changes, you ran /qs reload and double-checked with /qs info.

Further reading