Creating Powers
Two ways to write a power
Every power lives in ~/plugins/EliteMobs/powers (subfolders are scanned too), and there are two formats:
| Format | File | Use it for |
|---|---|---|
| Lua | *.lua | Anything new. Full scripting language, all the boss hooks, loops and state. This is what the shipped powers use. |
| EliteScript | *.yml | The declarative event/action format documented on the rest of this page. Still fully supported. |
Almost all of the 71 powers that ship with EliteMobs are now Lua — 68 of them. Only bonus_coins.yml, custom_summon.yml and elite_script.yml remain as YAML-backed Java powers. If you are writing a new power from scratch, Lua is the path with the most capability behind it — start at Lua Getting Started and Boss Hooks & Lifecycle.
Either format is referenced from a boss the same way, via the powers list.
.lua power supersedes a same-named .yml powerWhen a boss asks for attack_fire.yml, EliteMobs first looks for attack_fire.lua and uses that if it exists. This is why old boss configs written against the pre-Lua power names still work unchanged — you do not have to rewrite your powers: lists. New configs should name the .lua file directly.
.lua files are written once, never overwrittenEach shipped Lua power is written into the powers folder only if that file does not already exist. Once you edit one, EliteMobs will not overwrite your version on update — but you also stop receiving upstream fixes to it. If you want a modified copy, prefer giving it a new filename.
on_zone_enter / on_zone_leave are not fired by Lua zonesBoth hook names are accepted by the boss script provider and will not raise a load error, but nothing in a Lua power can make them fire. They are dispatched only from EliteScript's zone listener, which is started when a YAML eliteScript: on the same boss lists ZoneEnterEvent or ZoneLeaveEvent in its Events:. A boss with only Lua powers will load a file containing these hooks and then never call them.
Do not build a Lua power around these two hooks unless you are deliberately pairing it with such a YAML zone script. Use context.zones:watch_zone(...) (whose own on_enter / on_leave callbacks are invoked directly), an EliteScript Zone block, or polling from on_game_tick instead. See Hooks & Lifecycle and Script Events.
EliteMobs Scripting system
The rest of this page covers how to Create Elite Scripts!
This is an advanced feature and requires some in-depth knowledge of EliteMobs.
Note: Elite Scripts can be added as power files or to custom boss files! If used as power files, you can add them as normal powers to bosses using the powers configuration setting of Custom Bosses, as per usual.
Adding an EliteScript
To start adding an EliteScript to a boss, add the following entry to the boss file:
eliteScript:
Note: The following is extremely case and space sensitive! Make sure your spaces, line breaks and overall formatting matches the examples!
Now that you have your script start declared, you can add your specific script. For this example, we're going to create a script called Example:
eliteScript:
Example:
EliteScripts have 5 different sections: Events, Conditions, Zones, Actions and Cooldowns. Only Actions are mandatory.
Let's take a look at a simple example:
eliteScript:
Example:
Events:
- EliteMobDamagedByPlayerEvent
Actions:
- action: PUSH
Target:
targetType: SELF
vValue: 0,0.5,0
Cooldowns:
local: 60
global: 20
This script makes an elite get pushed up when hit by a player, and will not do so again for 3 seconds (and will stop other powers from triggering for 1 second due to the settings we have set in the Cooldowns section).
Now that you know the general format of how scripts are structured, it's time to learn what you can do with each section!
Events
Click on the link above to learn how to use events!
Targets
Click on the link above to learn how to use targets!
Actions
Click on the link above to learn how to use actions!
Zones
Click on the link above to learn how to use zones!
Conditions
Click on the link above to learn how to use conditions!
Cooldowns
Click on the link above to learn how to use cooldowns!
Adding multiple EliteScripts
You can have multiple actions on an event, but what if you want multiple scripts on the same boss? This is as simple as creating a new script entry! Let us expand on the previous example and add another script to it:
eliteScript:
Example:
Events:
- EliteMobDamagedByPlayerEvent
Actions:
- action: PUSH
Target:
targetType: SELF
vValue: 0,0.5,0
Cooldowns:
local: 60
global: 20
Example2:
Events:
- PlayerDamagedByEliteMobEvent
Actions:
- action: SET_ON_FIRE
Target:
targetType: DIRECT_TARGET
Cooldowns:
local: 200
global: 60
In this example we have added a second script called Example2. Example2 will set-on-fire the player that gets damaged by the boss, this is due to the targetType being set to DIRECT_TARGET.
The cooldown for this script is set to 200 ticks meaning that the boss will only be able to set-on-fire players every 10 seconds.
Making standalone powers
Standalone powers are almost entirely composed by the Elite Script. There are only two fields that are optional. Do not forget that for the standalone powers to work they must be placed in the ~plugins/EliteMobs/powers folder.
Standalone power example:
isEnabled: true
powerType: UNIQUE
eliteScript:
Example:
Events:
- EliteMobDamagedByPlayerEvent
Actions:
- action: PUSH
Target:
targetType: SELF
vValue: 0,.3,0
Cooldowns:
local: 60
global: 20
isEnabled
Same with everywhere else in the plugin, sets if the power is enabled.
powerType
Power type sets how the power gets assigned. The values are:
UNIQUE: The power will only be applied to custom bosses that have the power set in the powers section.DEFENSIVE/MISCELLANEOUS/OFFENSIVE: ANY elite will be able to get these powers, and they will count to a specific subset of powers.MAJOR_ZOMBIE,MAJOR_SKELETON,MAJOR_BLAZE,MAJOR_ENDERMAN,MAJOR_GHAST: Only elites of the adequate entity type will be able to spawn naturally with these powers, and they will count towards major powers. These five are the only types that count as major powers; everything else counts as a minor power.
How powerType reaches natural elites: EliteMobPowers.yml
powerType does not on its own put a power in front of a natural elite. What natural elites actually roll from is ~/plugins/EliteMobs/EliteMobPowers.yml, which has these lists:
| Key | Meaning |
|---|---|
defensivePowers | Defensive powers natural elites can randomly roll |
offensivePowers | Offensive powers natural elites can randomly roll |
miscellaneousPowers | Miscellaneous powers natural elites can randomly roll |
majorPowers.<ENTITY_TYPE> | Major powers that entity type can randomly roll |
disabledPowers.<ENTITY_TYPE> | Powers removed from that entity type after the shared lists are applied |
When the file is first generated, each list is seeded with every loaded power of the matching powerType. After that the file is authoritative and is never re-seeded, so a power you add later — including any .lua file you drop into the powers folder — will not start appearing on natural elites until you add it to the relevant list yourself.
Both .lua filenames and legacy .yml names are accepted in these lists; the generated defaults are written using the .yml alias. A name that resolves to no power is skipped with a console warning naming the file and the key.
effect
Sets the material shown in the power stance ring — the items that orbit an elite to advertise which powers it has. Each power contributes one item to a ring, and effect is the material of that item. Which of the two rings it joins is decided by powerType: MAJOR_* powers go into the major ring, everything else into the minor ring.
A power with no effect (or an empty one) simply contributes no item to the ring. That is the normal state for custom Lua powers, which have no YAML header to read an effect from.
| Key | Values | Default |
|---|---|---|
effect | Material | none |
powerCooldown
Sets the cooldown, in ticks, for the individual power. This controls how often this specific power can trigger.
| Key | Values | Default |
|---|---|---|
powerCooldown | Integer | 0 |
globalCooldown
Sets the global cooldown, in ticks, shared across all powers. After this power triggers, no other power can trigger until the global cooldown expires.
| Key | Values | Default |
|---|---|---|
globalCooldown | Integer | 0 |
Making standalone Lua powers
A standalone Lua power is just a .lua file in ~/plugins/EliteMobs/powers (subfolders included — the folder is crawled recursively). There is no YAML wrapper and there are no config keys: the file is the power.
return {
api_version = 1,
on_player_damaged_by_boss = function(context)
if context.player == nil then
return
end
context.player:apply_potion_effect("BLINDNESS", 60, 0)
end
}
Because there is no YAML header to read them from, a Lua power discovered this way gets fixed metadata:
powerTypeisMISCELLANEOUS. You cannot set it toUNIQUEfrom the file. (The Lua powers that ship with EliteMobs carry their type in Java, which is why they can beUNIQUE,OFFENSIVE,MAJOR_*and so on.)effectis unset.
In practice this does not leak your power onto random elites, because the natural-elite roll pools come from EliteMobPowers.yml and that file is not re-seeded once it exists — see above. Add the power to a boss's powers: list to use it.
Hooks available to boss Lua powers
| Hook | Fires when |
|---|---|
on_spawn | The boss spawns |
on_game_tick | Every server tick |
on_boss_damaged | The boss takes damage from any source |
on_boss_damaged_by_player | The boss takes damage from a player |
on_boss_damaged_by_elite | The boss takes damage from another elite |
on_player_damaged_by_boss | The boss damages a player |
on_enter_combat | The boss enters combat |
on_exit_combat | The boss leaves combat |
on_heal | The boss heals |
on_boss_target_changed | The boss switches target |
on_death | The boss dies |
on_phase_switch | The boss switches phase |
on_zone_enter and on_zone_leave are also accepted by the parser, but nothing in a Lua power can make them fire — they are dispatched only from an EliteScript zone listener on the same boss. See the warning at the top of this page.
For what you can actually call inside these hooks, see Lua Getting Started, Boss Hooks & Lifecycle and Boss Entities.
