Skip to content
Dragon's Exodus

Client Guide

Menu

Widgets

The web and desktop clients share one widget system. Everything on screen is a widget: vitals, group frames, effects, the target bar, chat, your prompt, cooldowns, score. Dock them, float them, resize them, collapse them. Make the screen yours.

  • Layout mode lives behind the arrange button in the client menu. Drag a widget onto a side rail to dock it or drop it anywhere to float it. Hold Alt for free placement. Chat can also dock to any edge of the terminal. Just drag it there.
  • opens a widget's settings. collapses it down to its title bar. ⇤ / ⇥ hop a docked widget to the other rail.
  • Floating widgets have an Overlay / Solid toggle. Overlay lets terminal text flow underneath. Solid makes the text stop at the widget's edge.
  • Session profiles remember your layout and settings per character. Hit + to manage them on either client.
  • History opens with Ctrl+F and lets you search back through everything you have seen. The desktop client keeps full logs on disk while the web client keeps the last couple megabytes of your current session.

Widget style guide

The default widgets share one look and anything a script creates inherits it automatically. Here's the language so your custom stuff fits right in.

Bars

Every bar in the client is the same element: a bordered track with a colored fill and a shadowed label in the middle. Vitals, group frames, the target bar, prompt bars and script bars all use it. Heights vary a little by context but everything else matches.

Buttons

One button style everywhere. Dark panel background with a thin border and a green tint on hover. Buttons your scripts make look exactly like ours.

Colors

Anywhere you can change a color you get the same choices. Default is the client palette. MUD shows up where an in-game color exists, so score fields can match the in-game score sheet. Custom hands you a color picker. Every widget's settings has a restore-defaults escape hatch.

Effect icons

Effects and debuffs are a text list by default with an icon grid option. Tiles are all the same size and long names just shrink and wrap to fit. Pick your tile shape in the Effects settings: hexagon, square or circle. Buffs get a hue from their name so a spell always looks the same. Debuffs are always red. Your own effects on a target get a gold halo.

Design tokens

The shared look comes from a handful of CSS variables. Scripts pick these up for free. They're listed here in case you want to build with them on purpose.

TokenWhat it is
--w-bar-heightDefault bar height (20px)
--w-radiusCorner radius on bars and buttons (3px)
--w-fontUI font for buttons and controls
--w-monoMonospace font for readouts
--bg, --bg-2, --bg-3Background steps from darkest to lightest
--line, --line-strongBorder colors, resting and hover
--fg, --fg-dimText colors, primary and secondary
--de-green, --de-green-ltAccent greens

Scripting

The client has a built-in Lua engine. Triggers and aliases, timers, GMCP access, line gagging and your own widgets with text, bars and buttons. Open Scripts in the client menu and check the Reference tab. It lists every GMCP package with a live peek at its current data plus the full de.* API and one-click starter templates.

Ground rules: scripts run sandboxed with no network access. The item database and area atlas are there through de.items and de.atlas. The client loads both for you. Scripts can hide built-in widgets but never remove them.

Starter templates

Same templates you'll find in the client's Reference tab.

Vitals bar widget

local w = de.widget('myvitals', 'My Vitals')
de.on_gmcp('Char.Vitals', function(v)
  w:bar('hp', { value = v.hp, max = v.maxhp, color = '#c0392b', label = 'HP ' .. v.hp .. '/' .. v.maxhp })
  w:bar('mana', { value = v.mana, max = v.maxmana, color = '#2a6fb0', label = 'Mana ' .. v.mana .. '/' .. v.maxmana })
end)

Custom buttons

local w = de.widget('mybuttons', 'Buttons')
w:button('heal', 'Heal', 'cast heal')
w:button('flee', 'Flee!', 'flee')
w:button('camp', 'Camp', function()
  de.send('sit')
  de.send('rest')
end)

Gag spam lines

de.on_line('The rain continues to fall', function()
  de.gag()
end)

Tell alert with captures

de.on_line('^(%a+) tells you', function(line, who)
  de.echo('*** ' .. who .. ' sent you a tell! ***')
end, 'pattern')

Low target announcer

local called = false
de.on_gmcp('Char.Target', function(t)
  if t.id == 0 then called = false return end
  if not called and t.hp and t.hp <= 15 then
    called = true
    de.send('say ' .. (t.name or 'Target') .. ' is nearly dead!')
  end
end)

Item lookup command

de.on_command('^lookup (.+)', function(cmd, what)
  local found = de.items.find(what)
  if found == nil then
    de.echo('Item database is still loading, try again in a moment.')
    return false
  end
  if #found == 0 then
    de.echo('No items match "' .. what .. '".')
    return false
  end
  for i = 1, #found do
    local it = found[i]
    de.echo(string.format('%-40s level %-3d %s', it.short, it.level, it.type))
  end
  return false
end, 'pattern')

Atlas lookup command

de.on_command('^atlas (.+)', function(cmd, name)
  local area = de.atlas.area(name)
  if area == nil then
    de.echo('Requesting that map...')
    return false
  end
  de.echo(area.name .. ': ' .. #area.rooms .. ' rooms mapped (' .. area.explored .. '/' .. area.total .. ' explored)')
  return false
end, 'pattern')
de.on_atlas(function(area)
  de.echo('Map ready: ' .. area.name)
end)