Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Spells

The spellbook resource describes learned spells, their targeting behavior, and their visible cooldown state. daRPC can cast a spell through native client methods and report each stage of delayed casting.

UseRoute or events
Read learned spellsGET /clients/{client}/spells
Cast a spellPOST /clients/{client}/spells/cast
Swap spellsPOST /clients/{client}/spells/swap
Watch casting, feedback, and spellbook changesSpell events

Reading the spellbook

curl "http://127.0.0.1:2626/clients/ZiLo/spells"

Each occupied slot includes:

  • One-based slot
  • icon and available name
  • Current level and max_level
  • The number of chant lines
  • target_type: none, target, or text_input
  • An optional cleaned ASCII prompt for text-input spells
  • Cooldown activity plus optional total and exact remaining durations

The prompt is only present for text-input spells. A cooldown can be known to be active without exact cooldown_ms or remaining_ms values. daRPC retains exact timing from live server action-delay packets. A spell already cooling when the DLL attaches exposes only its active flag because the spellbook retains no start or end timestamp.

Spellbook {
    observation: ObservationMetadata,
    spells: Spell[]?,
}

Spell {
    slot: u8,
    icon: u16,
    name: string?,
    level: u8,
    max_level: u8,
    lines: u8,
    target_type: SpellTargetType,
    prompt: string?,
    cooldown: Cooldown,
}

Cooldown {
    active: bool,
    cooldown_ms: u32?,
    remaining_ms: u32?,
}

Casting a spell

Select the spell by one-based slot or case-insensitive name:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"name":"Mist"}' \
  "http://127.0.0.1:2626/clients/ZiLo/spells/cast"

Targeted spells accept a character or Mundane name, a current object ID, or a map tile:

curl --request POST --header "Content-Type: application/json" \
  --data '{"name":"Taunt","target":"OtherPlayer"}' \
  "http://127.0.0.1:2626/clients/ZiLo/spells/cast"
curl --request POST --header "Content-Type: application/json" \
  --data '{"slot":12,"target":1843}' \
  "http://127.0.0.1:2626/clients/ZiLo/spells/cast"
curl --request POST --header "Content-Type: application/json" \
  --data '{"name":"Ground Spell","target":{"x":20,"y":14}}' \
  "http://127.0.0.1:2626/clients/ZiLo/spells/cast"

A targeted spell with no target defaults to the casting character. A name search is case-insensitive and checks players within 14 tiles before visible Mundanes. Players remain valid targets while invisible when their latest observation, including object ID and position, is still retained. Object IDs must identify a current retained target within the same range. Tile coordinates are zero-based and must fit the current map. For example, a named Mundane target could use "target": "Beggar".

Text-input spells use input:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"name":"Learning Spell","input":"Elemental Bless 6"}' \
  "http://127.0.0.1:2626/clients/ZiLo/spells/cast"

Text input must contain 1 through 100 ASCII bytes. Extra, conflicting, or incorrect argument types return 400 Bad Request. An unknown spell or named target returns 404 Not Found.

The DLL checks the live spell slot and arguments again before calling the matching native client routine. It does not switch the visible spell panel or synthesize user input.

After the native routine accepts a cast, the command remains pending for 500 milliseconds so immediate server feedback can determine its result. These exact system messages complete the command with distinct failures:

System messageFailure
Your Will is too weak.insufficient_mana
The magic has been deflected.resist
No target.invalid_target
That doesn't work here.not_allowed

not_allowed includes attempts to cast on no-cast maps. Silence during the bounded response window completes the command successfully.

Spell casts have 10 percent tolerance on the normal one-second start deadline. This bounded window accommodates small native dispatcher overruns during an earlier cast; the one-second action deadline remains in effect for other commands.

Swapping spells

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"source":{"name":"Mist"},"destination":{"slot":12}}' \
  "http://127.0.0.1:2626/clients/ZiLo/spells/swap"

Both selectors accept exactly one of slot or case-insensitive name, using the same payload as inventory and skill swaps. A destination slot may be empty. The source must be occupied, and the resolved slots must be different.

Casting events

The complete payload structures and stream names are in Spell events.

daRPC observes the same outbound spell path for casts started through the game interface and casts requested through REST.

EventMeaning
spell.beginA delayed spell began. Includes slot, optional name, and total_lines.
spell.chantOne visible chant line was submitted. Includes line and total_lines.
spell.castThe final spell use was submitted. Includes any retained arguments.
spell.cancelledA delayed spell ended without a final cast.
spell.succeededThe game confirmed a submitted spell by name.
spell.failedThe game reported that a submitted spell failed or was rejected.
spell.receivedAnother player, Mundane, or monster cast or attacked with a spell on this character.

An instant spell normally produces only spell.cast. A delayed spell normally produces spell.begin, one or more spell.chant events, and then spell.cast.

Cancellation source is client, server, or replaced. Starting another spell while chanting is allowed. daRPC reports the old spell as replaced before it reports the new spell’s begin or cast event, so the two casts do not appear to overlap.

The final cast can retain one of these argument forms:

target: object ID, available name, and coordinates
input:  submitted text
values: bounded numeric values used by less common spell types
unknown: the argument could not be classified

Spells with no arguments omit this field. Target names are best-effort daemon enrichment. The object ID and coordinates come from the observed submission.

is_casting in character status follows the same ordered begin, cast, and cancellation events.

Cast results

spell.cast means the client submitted the spell. It does not by itself mean the server accepted the result. The daemon keeps up to 256 recent submissions for each connected DLL instance and compares later system feedback with that queue. A submission expires after five seconds.

A named success such as You cast Mist matches the oldest queued cast with that spell name. Generic failures match a cast only when exactly one submission is pending. When several submissions are pending, the feedback does not contain enough information to prove which cast failed, so the daemon discards the ambiguous candidates and emits only the original message.system event. The queue is held only in memory and is cleared when the DLL disconnects or the daemon restarts.

The system message You failed to concentrate. matches a queued Fas Spiorad cast by name and produces spell.failed with reason failed.

spell.succeeded and spell.failed retain the submitted slot, available spell name, and cast arguments. They also include:

feedback:          original system feedback
submitted_tick_ms: client tick when spell.cast was observed
elapsed_ms:        wrapping millisecond difference to the feedback

Failure reason is one of:

failed, error, resisted, already_active, conflicting_effect

For a conflicting curse, active_spell contains the spell named by the game when available. The attempted spell remains in name.

spell.received does not need a matching local submission. It contains the reported caster, spell name, and a kind of cast or attack. If that caster is still visible, caster_object supplies the current world object as best-effort context. Friendly feedback uses the game’s “cast … spell on you” form, while harmful feedback uses its “attacks you with … spell” form.

The original message.system is still retained and broadcast. Semantic spell events add useful structure without hiding the text that appeared in the game.

Spellbook events

EventMeaning
spell.addedA learned spell appeared in a slot.
spell.removedA spell left a slot.
spell.changedA spell moved or its retained details changed.
spell.cooldownA retained spell entered or restarted cooldown.
spell.readyA retained spell left cooldown and is ready to cast.

Spellbook changes use batch_index, batch_count, slot, before, and after. Moving or swapping spells can create several frames in one batch. The daemon applies the full batch before it broadcasts the first frame.

spell.changed is not emitted for a cooldown-only transition. A live action-delay packet supplies cooldown_ms and remaining_ms on spell.cooldown. On late attach those fields remain absent, but daRPC polls the active slot until it can emit spell.ready. Both cooldown events include observation, the one-based slot, and the spell name when known.

Availability

spells: null means the spellbook was unavailable. An empty array means it was read successfully and no occupied spell slots were found.