English
Triggers
Trigger configuration covers when active skills may be cast, which game events fire passive skills, how conflicts between triggers are handled, and how to set up cast mode
A trigger is the rule for "when a skill fires". EmakiSkills splits them into active triggers and passive triggers
- Active triggers are global slot triggers. You bind a skill to a trigger slot in the GUI, then cast it while cast mode is enabled
- Passive triggers are declared in skill definitions through
trigger_type: passiveandpassive_triggers, and fire automatically when their event happens
text
Active: the player binds a skill to right_click → right click while in cast mode
Passive: the definition says passive_triggers: [attack] → fires on a successful hitThe registry is built from two parts: the plugin's built-in default definitions plus same-id overrides from config.yml under triggers / passive_triggers. Config therefore only supplies the display name, enabled flag, and conflict declarations; if you want a trigger id that is not in the built-in list (for example consume), you must register it in config explicitly, otherwise it is dropped at dispatch time without an error
Active triggers
| Trigger | Operation |
|---|---|
left_click | Left click |
right_click | Right click |
shift_left_click | Shift + left click |
shift_right_click | Shift + right click |
drop_q | Drop key |
hotbar_1 ~ hotbar_9 | Number keys 1-9 |
NOTE
Active triggers carry no cooldown of their own; the cooldown comes from the skill definition's cooldown_ticks and global_cooldown_ticks
triggers configuration
yaml
triggers:
left_click:
display_name: "[Left Click]"
enabled: true
incompatible_with:
- shift_left_click| Field | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
triggers.<id> | map | No | built-in default | — | The trigger id is the key. A scalar value skips that key |
triggers.<id>.display_name | string | No | the key; blank falls back to Unknown | MiniMessage | Trigger name shown in the GUI and action bar |
triggers.<id>.enabled | boolean | No | true | true / false | When off, the trigger is neither dispatched nor bindable in the GUI |
triggers.<id>.incompatible_with | list<\string> | No | [] | Trigger ids | Declares conflicting triggers; conflicts are mutual (see conflict resolution below) |
Active trigger settings
yaml
trigger_settings:
# When enabled, events already cancelled by Bukkit are still dispatched; leaving it off keeps protection plugins from being followed by energy use or casting
legacy_dispatch_cancelled_events: false| Field | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
trigger_settings.legacy_dispatch_cancelled_events | boolean | No | false | true / false | Whether interaction / drop / hotbar events already cancelled by Bukkit are still dispatched. Default false: a cancelled event is dropped, so protection plugins can no longer be followed by energy use or casting; true restores the legacy behavior and logs a one-time deprecation warning |
Passive triggers
yaml
id: lifesteal_passive
trigger_type: passive
passive_triggers:
- attack
cooldown_ticks: 60| Trigger | When it fires |
|---|---|
attack | The player hits an entity (including projectile hits) |
damaged | The player takes any damage |
damaged_by_entity | The player is damaged by an entity |
death | The player dies |
kill_entity | The player kills a non-player entity |
kill_player | The player kills another player |
shoot_bow | The player shoots a bow |
arrow_hit | An arrow hits an entity |
arrow_land | An arrow lands without hitting an entity |
shoot_trident | The player throws a trident |
trident_hit | A trident hits an entity |
trident_land | A trident lands |
break_block | The player breaks a block |
place_block | The player places a block |
drop_item | The player drops an item |
shift_drop_item | Shift + drop item |
swap_items | Swap main hand and off hand |
shift_swap_items | Shift + swap hands |
login | Player login |
sneak | The moment sneaking starts (not when it stops) |
teleport | Teleport |
timer | Periodic trigger, at the interval set by passive_trigger_settings.timer_interval_ticks |
combo_attack | Combo trigger. Attacks no further apart than passive_trigger_settings.combo_timeout_ticks accumulate the combo state, which is passed as %combo_count% at dispatch |
consume must be registered in config.yml yourself
The listener dispatches consume for PlayerItemConsumeEvent (eating or drinking), but consume is neither a built-in default trigger nor present in the bundled config.yml > passive_triggers. Unregistered triggers are dropped at dispatch time, so writing passive_triggers: [consume] alone has no effect and raises no error
To enable it, add this section under config.yml > passive_triggers first:
yaml
passive_triggers:
consume:
display_name: "[Consume]"
enabled: true
incompatible_with: []passive_triggers configuration
yaml
passive_triggers:
attack:
display_name: "[Attack]"
enabled: true| Field | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
passive_triggers.<id> | map | No | built-in default | — | The passive trigger id is the key. A scalar value skips that key |
passive_triggers.<id>.display_name | string | No | the key; blank falls back to Unknown | MiniMessage | Display name. Players cannot bind passive triggers in the GUI, so this is mainly for display |
passive_triggers.<id>.enabled | boolean | No | true | true / false | When off, the passive trigger is no longer dispatched |
passive_triggers.<id>.incompatible_with | list<\string> | No | [] | Trigger ids | Same meaning as for active triggers; usually left empty for passives |
Passive trigger settings
yaml
passive_trigger_settings:
# Interval of the timer check, in ticks; values below 1 are treated as 1
timer_interval_ticks: 20
# Combo timeout, in ticks; the combo counter resets when no attack arrives in time
combo_timeout_ticks: 60| Field | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
passive_trigger_settings.timer_interval_ticks | integer | No | 20 | ≥ 1, values below 1 become 1 | Check interval of the timer passive trigger, in ticks |
passive_trigger_settings.combo_timeout_ticks | integer | No | 60 | ≥ 1, values below 1 become 1 | Combo state timeout for combo_attack, in ticks; a longer gap without attacking resets the counter |
Cron passive trigger
When a skill definition sets cron_expression, a passive trigger with the ID cron_<skill id> is registered automatically and added to that skill's passive_triggers; you do not write it by hand. The expression uses the same format as spawn_rules' cron, see CoreLib expressions - Cron. cron_max_executions caps the total number of firings; 0 means unlimited. An invalid expression logs a warning and skips that skill
Trigger conflict resolution
Conflicts are declared with incompatible_with, and the relation is mutual:
- Every trigger conflicts with itself (one trigger cannot carry two skills)
- Conflicting triggers cannot both hold a skill (for example
left_clickandshift_left_click)
The conflict matrix is built while loading config, so the plugin checks conflicts automatically when a player binds in the GUI. The built-in defaults declare four pairs: left_click ↔ shift_left_click and right_click ↔ shift_right_click
Cast mode
To cast an active skill, enter cast mode first
yaml
cast_mode:
# The entry key is fixed to F; enabled only controls the F-key toggle, it is not a master switch
entry_key: "f"
# With false, F restores the vanilla hand swap while the command and GUI can still toggle cast mode
enabled: true
# Whether the previous cast mode state is restored when the player rejoins
restore_last_state_on_join: true| Field | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
cast_mode.entry_key | string | No | "f" | Always f | Entry key. The config record forces f while being constructed, so any other configured value has no effect |
cast_mode.enabled | boolean | No | true | true / false | Whether the F key toggles cast mode. With false, F restores the vanilla hand swap while the command and GUI still toggle cast mode |
cast_mode.restore_last_state_on_join | boolean | No | true | true / false | Whether the previous cast mode state is restored after rejoining |
- The F key toggles cast mode by default
- Active triggers only listen to server-visible actions (left/right click, Q, number keys) while cast mode is on; those actions dispatch nothing when cast mode is off
- While cast mode is on, the action bar shows slot state; templates and variables are in Action bar
Configuration examples
Active skill
yaml
id: fireball
trigger_type: active
display_name: '<red>Fireball'
cooldown_ticks: 100
global_cooldown_ticks: 20
resource_costs:
- type: ea-resource
target_id: mana
amount: 20
operation: consumeBind it to the right_click slot in the GUI, then right click while in cast mode to release it
Passive skill
yaml
id: thorns_aura
trigger_type: passive
passive_triggers:
- damaged_by_entity
display_name: '<yellow>Thorns Aura'
cooldown_ticks: 40It fires when you are damaged by an entity, limited by cooldown_ticks
Timed passive
yaml
id: regen_aura
trigger_type: passive
passive_triggers:
- timer
display_name: '<green>Regen Aura'
cooldown_ticks: 0
resource_costs:
- type: ea-resource
target_id: mana
amount: 5
operation: consumeIt fires automatically at the global timer_interval_ticks interval
Combo passive
combo_attack attaches combo_count (the current combo count) to the trigger invocation, so your skill can use it in conditions or variables. The bundled skills/example_combo_skill.yml reads it from a condition block:
yaml
id: combo_finisher
trigger_type: passive
passive_triggers:
- combo_attack
condition:
type: all_of
entries:
- "%combo_count% >= 5"
cooldown_ticks: 100The %...% inside a condition expression must be resolvable by PlaceholderAPI; see Definitions - The condition block. combo_attack uses the entity just hit as both target and area centre