Skip to content
Dragon's Exodus

Client Guide

Menu

Use the same interface in the browser or the desktop client. This guide covers everyday controls and the Lua scripting tools.

Sessions and settings

Use + to create or open a saved session. Each profile keeps its own layout, preferences, scripts, aliases, triggers and saved Lua variables. Browser profiles stay on this device. Desktop profiles can use the secure relay or a direct server connection, with optional automatic connection and login.

Press Enter to send a command and Shift+Enter to add a line. The up and down arrows recall commands. Open Settings for interface themes, keyboard shortcuts and saved-settings exports. The client menu's Font controls terminal size, input size and UI scale separately.

Settings and scripts are stored locally. Export a backup before clearing browser data or moving to another device. Browser automation runs while the page is open and connected; background tabs and device sleep can delay timers.

Widgets

The web and desktop clients share one widget system. Vitals, group frames, effects, the target bar, chat, your prompt, cooldowns and score are widgets. Dock them, float them, resize them, collapse them. Make the screen yours.

  • Layout mode opens from Layout 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. The collapse control folds 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.
  • Add a widget… restores hidden widgets. Resize a widget from its corner or drag a rail divider to change the rail width. Auto / Fixed switches between content sizing and a fixed height with scrolling.
  • On desktop, Window ↗ moves a widget into a separate Widgets window. Return brings it back. Closing that window returns its widgets to the main window.
  • Session logs opens with Ctrl+F (Cmd+F on Mac) by default. Desktop logging saves sessions to disk when enabled in Settings. The browser keeps about 2 MB of recent output from the current session.

Maps, inventory and tools

The toolbar opens the world map, mail, item database, inventory, equipment, shop, bank, auction house, crafting, quest journal and notepad. Hover over a button to see its name and shortcut. Shortcuts can be changed in Settings.

In the world map, search for an area or mapped room, drag to pan and scroll to zoom. Use the floor selector or Shift+scroll to change floors. Select a room for connections and details. Room notes are private to your character on this device.

Select an inventory item to inspect it and see available actions. Drag pane dividers to resize the inventory view; double-click a divider to reset it. Shop and bank actions depend on your location.

On desktop, Open tools in separate windows in Settings controls tool windows. Use a window's Move to… menu to move it to a session tab, a new window or another tool window.

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

Script buttons inherit the client theme, font and UI scale. Buttons can show a selected option or current value; toggles display an On/Off switch. Choose Exodus or Original green in Settings to change the interface palette.

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.

Effects and debuffs

Effects appear as a text list with optional duration bars. The Effects settings let you split debuffs into their own widget, choose timer formatting and control expiry flashing. Debuffs use red accents, and your own effects on a target are marked in gold.

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 colors for the selected theme

Scripting

Open Scripts in the client menu. The workspace has All, Scripts, Aliases, Triggers, Variables and Reference tabs. Reference lists the client Lua API, GMCP packages with a Peek button for current data, and starter templates you can add to your scripts.

Create and apply a script

  1. Choose + Guided Script for a form-based editor or + Lua script for Lua 5.4 source.
  2. For a guided script, choose when it runs: game text, a command, GMCP data, connection, disconnection or a timer. Add any conditions and actions. All conditions must pass, and actions run in order.
  3. Edits are saved as a draft. Click Apply saved draft (or Save) to reload the active scripts. Discard draft restores the applied version. Ctrl+S or Cmd+S applies changes from the scripting window.

A script and its parent folders must be enabled to run. Applying scripts recreates their timers, handlers and custom widgets; Lua locals start fresh, while values saved with de.set persist. Errors appear in the terminal with the script name.

Matching and timing

Guided scripts and Lua handlers offer Contains, Exact and Lua pattern matching. Contains and Exact ignore case. Lua patterns use captures such as (%a+) and are case sensitive. The separate Triggers tab accepts plain text or JavaScript regular expressions written as /pattern/flags.

Guided Wait actions use seconds. While a sequence waits, repeated starts are skipped; disconnecting cancels its pending steps. A delay does not confirm a game command succeeded. In Lua, use de.await to wait for a GMCP update, then check its contents before sending the next command. Register the wait before sending the command; a timeout calls your callback with nil.

Imports and backups

Import accepts DE JSON packages and Lua files. Choose Mudlet to import XML, ZIP or mpackage files. Mudlet imports install disabled and provide a conversion report; review that report, the folders and individual entries before enabling them. Export Lua saves script source, while Export package includes scripts, aliases, triggers, groups and saved variables.

Lua scripts run in a sandbox without direct file or network access. Use de.send for game commands, de.items for item lookups and de.atlas for character map data. Lookups can return nil while loading. Item searches return at most 25 matches. Scripts can show or hide built-in widgets and create their own widgets with text, bars, buttons, toggles and section headings.

de.on_gmcp handles incoming updates; de.gmcp reads cached data. Fields can be absent until the server sends them. de.on_connect and de.on_disconnect handle connection changes. de.publish and de.on_message share data with other sessions in this client; they do not send game chat. Use a script-specific prefix for persistent variable keys.

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
local target_id = 0
de.on_gmcp('Char.Target', function(t)
  if t.id ~= target_id then called = false target_id = t.id end
  if not t.id or t.id == 0 then 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('Map unavailable or loading; try the lookup again in a moment.')
    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)