AoE Zone Configuration

Configure timed area-of-effect attack zones for mobs, with a telegraph warning phase followed by a damaging active phase.

AoE (area-of-effect) zones are timed attack areas that mobs can create — a warning outline followed by an active area, useful for boss telegraphs, ground slams, shockwaves, and similar attacks. Each zone has a telegraph phase (warning, no effect) followed by an active phase. During the active phase a zone can deal damage, apply a continuous force (updraft / wind / suction), or both.


File Location

Register the file in your mod’s manifest (mods/<YourMod>/<YourMod>.yaml):

aoe-zone-config: aoe-zone-config.yaml

Then create the file it points to, relative to your mod’s folder:

# mods/<YourMod>/aoe-zone-config.yaml
aoe-zones:
  - name: my_boss_slam
    # ... zone fields, see below

Zone names are automatically prefixed with your mod name unless you write one already containing a colon, so my_boss_slam becomes YourMod:my_boss_slam — this full name is what you use to trigger the zone from Lua.

Zones are registered per mod, not per mob: a zone belongs to no particular entity, and any entity can trigger any zone by name (see Triggering from Lua). Naming a zone after the boss that uses it is a helpful convention, nothing more.


Minimal Example

aoe-zones:
  - name: my_boss_slam
    shape:
      type: circle
      start-radius: 0.5
      end-radius: 5.0
    damage-mode:
      type: one_shot
      damage: 1.0

This declares a zone that telegraphs for 500ms (the default), then instantly deals 1.0 damage to anything within a 5-block radius. The top-level aoe-zones: wrapper is required — the file is a mapping with an aoe-zones list, not a bare list, and a file that omits the wrapper fails to load.


Fields

Timing

FieldTypeDefaultDescription
telegraph-duration-msinteger500How long the warning outline is shown before the zone becomes active
active-duration-msinteger300How long the zone deals damage after the telegraph ends

A non-zero telegraph-duration-ms below the instance’s telegraph floor (250 ms by default) is raised to the floor at load time, with a warning in the log — a tell too short to read is not a tell. telegraph-duration-ms: 0 is left alone: that declares a zone with no warning phase, which is a deliberate choice (a persistent traversal current, an instant hazard) rather than an unreadable one. See combat-config.md to change the floor.

Persistent zones

FieldTypeDefaultDescription
persistentbooleanfalseMake the zone a permanent terrain volume that never expires

A persistent zone is the primitive for a zone that exists as terrain rather than a timed strike — an updraft column, a traversal current, a warm rest pocket. When persistent: true:

  • it never expirestelegraph-duration-ms and active-duration-ms are ignored;
  • it skips the telegraph — it is active the instant it exists;
  • it holds a fixed shape at its start parameters — the start→end shape animation and the offset drift are meaningless for a permanent volume, so only the start size / start offset are used.

A persistent zone can be spawned like any other (from Lua, a projectile impact), but the intended use is to place it with world generation — see Placing zones with world generation. Everything else (shape, force, damage) behaves the same; a persistent zone simply never goes away.

Shape

All shapes animate from their start size to their end size over the active phase. The telegraph always displays the end size so players can see the full danger zone before it activates.

Circle

shape:
  type: circle
  start-radius: 0.5   # radius in blocks at the start of the active phase
  end-radius: 5.0      # optional, defaults to start-radius

Rectangle

shape:
  type: rectangle
  start-width: 1.0     # required
  start-height: 1.0    # required
  end-width: 8.0       # optional, defaults to start-width
  end-height: 6.0      # optional, defaults to start-height

Rectangles are centered horizontally on the spawn point and extend upward from it.

Ring

An annulus (donut) defined by an inner and outer radius. Entities between the two radii are inside the zone.

shape:
  type: ring
  start-outer-radius: 2.0   # required
  end-outer-radius: 9.0     # optional, defaults to start-outer-radius
  start-inner-radius: 0.0   # optional, defaults to 0
  end-inner-radius: 7.0     # optional, defaults to start-inner-radius

The telegraph outline shows the full sweep range — from start-inner-radius to end-outer-radius — so players can see the entire area the ring will travel through. An inner radius of 0 makes the ring a solid circle at that point in time.

Line

An oriented beam rooted at the spawn point, extending length blocks along an angle with a fixed width of thickness centered on that axis — for sweeping arena beams, lances, and diagonal walls of danger that the axis-aligned rectangle cannot express.

shape:
  type: line
  start-length: 2.0    # length in blocks at the start of the active phase
  end-length: 18.0     # optional, defaults to start-length (a "growing" lance)
  width: 1.5           # required; thickness in blocks, centered on the beam axis
  start-angle: 0.0     # optional, defaults to 0; degrees, 0 = +x, counter-clockwise
  end-angle: 90.0      # optional, defaults to start-angle (a "sweeping" beam)

The beam extends from the spawn point outward — the spawn point is the base of the line, not its center. angle is in degrees, measured counter-clockwise from the +x axis (0 points right, 90 points up, 180 left, 270 down). Both length and angle animate over the active phase, so a beam can grow, sweep, or both at once; width is constant. The telegraph shows the beam at its end length and end angle.


Damage Mode

One-Shot

Deals damage once to all entities in the full end-size area, the moment the active phase begins.

damage-mode:
  type: one_shot
  damage: 1.0    # flat damage dealt

Continuous

Deals damage repeatedly to entities in the animated area (which grows over the active phase) on a fixed cooldown.

damage-mode:
  type: continuous
  damage-per-second: 5.0    # damage rate
  hit-cooldown-ms: 200      # optional, defaults to 500. Minimum time between hits per entity.

Damage per hit = damage-per-second × (hit-cooldown-ms / 1000). With the values above: 5.0 × 0.2 = 1.0 damage per hit, at most once every 200 ms per entity.

Sweep

Deals damage once to each entity the moving zone passes over, the first time it touches them — good for a shockwave or an expanding wave that should only tag each target once.

damage-mode:
  type: sweep
  damage: 1.0    # flat damage dealt per entity

Combine with an expanding shape (e.g. a ring growing outward) or a shape that translates using offset-start/offset-end to create a wave that sweeps across the battlefield.


Damage Type

An optional top-level damage-type sets which mitigation channel the zone’s damage uses. It is case-insensitive and defaults to physical.

- name: shockwave
  damage-type: blast     # optional, default physical
  damage-mode:
    type: one_shot
    damage: 12.0
ValueMeaning
physicalDefault channel; reduced by general armor.
fireFire/burning damage.
blastExplosions and concussive AoE — the usual choice for a boss shockwave.
decayCorrupted unmaking — the Wither combat verb’s channel.
radiantSacred creation-light — the Kindling combat verb’s channel.

Each type has its own armor-resistance slot on top of general armor. The type is applied to every hit the zone deals, regardless of damage-mode. An unrecognized name logs a warning and falls back to physical.


Hazard-Field Ward (ward-capability)

An optional ward-capability turns a zone into a hazard field — a region-wide lethal hazard that a single capability negates. This is the mechanism behind gated regions like a storm zone or a deep-hazard floor: the region is deadly to enter, and holding the region’s ward capability is what makes it survivable.

- name: scourwind_storm
  ward-capability: storm-ward        # a player holding "storm-ward" is unharmed
  persistent: true
  damage-mode:
    type: continuous
    damage-per-second: 40.0
    hit-cooldown-ms: 500

When ward-capability is set:

  • A player holding that capability takes no damage from the zone.
  • A player without it takes the damage bypassing armor — a ward, not gear, is the only defense (armor and blocking never reduce a hazard field).
  • Mobs and mounts (which hold no capabilities) always take the damage.

The capability is granted the same way every other capability is — an armor set’s grants-capabilities, or a script/boss reward. Omitting ward-capability (the default) leaves an ordinary AoE zone whose damage is mitigated by armor as usual. force is unaffected by the ward — only the damage branches are gated.

Pair this with a persistent zone placed by worldgen to build a standing warded region; a transient telegraphed zone can be warded too, but the persistent case is the intended one.


Zone Offset (Movement)

Zones can translate in world space over the active phase using offset-start and offset-end. Both are {x, y} maps in blocks, relative to the zone’s spawn position — the same vector shape used everywhere else in the configs (particle velocity, entity max-velocity).

offset-start: {x: 0.0, y: 0.0}     # center offset at t=0 of active phase
offset-end: {x: 15.0, y: 0.0}      # center offset at t=1 of active phase (sweeps 15 blocks right)

Both fields are optional, and either axis within them may be omitted (defaulting to 0.0 independently). offset-start defaults to {x: 0.0, y: 0.0}; offset-end defaults to whatever offset-start resolved to (no movement). During the telegraph, the zone is displayed at its offset-end position (the full destination).


Force Field (Updraft / Wind / Suction)

A zone can apply a continuous force to everything inside it during its active phase — the primitive for updrafts, wind gusts, and directional push hazards. Add an optional force field, an {x, y} vector in the same shape as offset:

force: {x: 0.0, y: 45.0}     # a steady upward push — an updraft

The vector is an acceleration in blocks/s², the same units as the world’s gravity, and is applied every active tick as velocity += force × delta_time. Because it composes with gravity:

  • y greater than the world’s gravity → the entity is lifted (an updraft that carries you upward).
  • y equal to gravity → the entity hovers (weightless).
  • x non-zero → a horizontal wind push.

The push accelerates hard but is capped at each entity’s own maximum velocity, so it never flings anything faster than it could normally move — hold an entity in a strong updraft and it rises at (up to) its top speed, then falls back to gravity the instant it leaves the zone. force is optional; omitting it (the default) means the zone applies no force, so existing zones are unaffected.

Force is independent of the damage mode — a zone can push and damage, or push with no damage. damage-mode is still required, so for a pure updraft/wind zone use a zero-damage one-shot:

aoe-zones:
  - name: my_updraft
    persistent: true                # a permanent terrain volume — never expires, no telegraph
    shape:
      type: rectangle
      start-width: 4.0
      start-height: 20.0            # a tall column of rising air
    damage-mode:
      type: one_shot
      damage: 0.0                   # no damage — force only
    force: {x: 0.0, y: 45.0}

Force respects zone geometry and phase exactly like damage: it acts only within the current (animated) shape, only during the active phase (never the telegraph), and never on the entity that created the zone. It applies to players, mobs, and mounts alike.


Colors

Outline colors are optional. Each is an { r, g, b, a } map of RGBA components in the range [0.0, 1.0] — the same color format used by the light: block’s color everywhere else.

FieldDescription
outline-colorOutline color during the telegraph phase
outline-color-activeOutline color during the active phase

If either is omitted, the zone falls back to the standard danger color for that phase — amber while warning, red while active — so an unstyled zone is still visible and every boss speaks the same color. Those two defaults are themselves configurable instance-wide; see combat-config.md. Prefer leaving these out unless a zone genuinely needs to read differently from ordinary danger.

outline-color:            # orange, 80% opacity
  r: 1.0
  g: 0.5
  b: 0.0
  a: 0.8
outline-color-active:     # red, fully opaque
  r: 1.0
  g: 0.0
  b: 0.0
  a: 1.0

Triggering from Lua

Call create_aoe_zone on an entity, typically from that mob’s server update script:

entity:create_aoe_zone("YourMod:my_boss_slam", x, y)
  • First argument — the zone’s full name, including mod prefix
  • x, y — spawn position of the zone center in world coordinates

Example — a boss slams the ground at its own position every 10 seconds:

-- /mobs/my_boss/scripts/server_update.lua
return function(entity, delta_time_ns)
    if entity.lua_data.slam_cooldown_ns == nil then
        entity.lua_data.slam_cooldown_ns = 0
    end
    entity.lua_data.slam_cooldown_ns = entity.lua_data.slam_cooldown_ns + delta_time_ns
    if entity.lua_data.slam_cooldown_ns >= 10e9 then
        entity.lua_data.slam_cooldown_ns = 0
        local loc = entity:get_location()
        entity:create_aoe_zone("YourMod:my_boss_slam", loc.x, loc.y)
    end
end

Following a target

create_aoe_zone_following(zone_name, target_entity_id) spawns a zone that tracks an entity: its whole area — telegraph outline, geometry, damage, and force — follows that entity every tick instead of staying at a fixed point. Use it for a mark that chases the player before it resolves, or a beam anchored to a moving target.

-- a cold sigil appears under the player and tracks them for the telegraph, then reaps their spot
entity:create_aoe_zone_following("YourMod:the_marked", target_player_id)

The zone spawns at the target’s current position. If the target leaves the world (dies/despawns) the zone stays at its last-known position and resolves there, so a fast target can still outrun a short-telegraph mark. Pair a following zone with a long telegraph-duration-ms (the tracking window) and a short active-duration-ms (the strike) for a classic “it chases, then it hits where you were” attack.


Behavior Summary

PhaseDurationVisualDamage
Telegraphtelegraph-duration-msoutline-color, shown at full end sizeNone
Activeactive-duration-msoutline-color-active, animates start → endYes
  • The zone is removed automatically once the active phase ends.
  • One-shot zones deal damage exactly once, regardless of how long an entity stays in the area.
  • Continuous zones can hit the same entity multiple times, subject to hit-cooldown-ms.
  • Sweep zones deal damage once per entity, the first time the zone touches them.
  • Damage hits players, mobs, and mounts, but never the entity that created the zone.
  • A force field pushes players, mobs, and mounts inside the active zone every tick (updraft / wind / suction), independent of the damage mode; it too never affects the zone’s creator.

Complete Example

A boss that ground-slams with an expanding ring shockwave:

# mods/<YourMod>/aoe-zone-config.yaml
aoe-zones:
  - name: my_boss_ground_slam
    telegraph-duration-ms: 1000
    active-duration-ms: 800
    shape:
      type: ring
      start-inner-radius: 0.0
      end-inner-radius: 7.0
      start-outer-radius: 2.0
      end-outer-radius: 9.0
    damage-mode:
      type: sweep
      damage: 1.0
    outline-color:
      r: 1.0
      g: 0.5
      b: 0.0
      a: 0.8
    outline-color-active:
      r: 1.0
      g: 0.0
      b: 0.0
      a: 1.0

The boss then triggers it from its scripts.server-update hook (see mob-config.md#scripts):

-- /mobs/my_boss/scripts/server_update.lua
return function(entity, delta_time_ns)
    entity.lua_data.slam_cooldown_ns = (entity.lua_data.slam_cooldown_ns or 0) + delta_time_ns
    if entity.lua_data.slam_cooldown_ns >= 10e9 then
        entity.lua_data.slam_cooldown_ns = 0
        local loc = entity:get_location()
        entity:create_aoe_zone("YourMod:my_boss_ground_slam", loc.x, loc.y)
    end
end

Last updated