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

hotbars.toml

Named bars of buttons for the hotbars widget.

Prefer the built-in editor over hand-editing: .hotbars opens the hotbar editor in both TUI and GUI.

Location: ~/.vellum-fe/global/hotbars.toml, plus an optional per-character ~/.vellum-fe/profiles/<name>/hotbars.toml. A character bar with the same name replaces the global one entirely.

Bars and Buttons

[[bars]]
name = "default"      # referenced by hotkeybar windows in layout.toml
title = "Actions"
icon_size = 48        # optional: icon face edge in px (GUI; default 24)

[[bars.buttons]]
id = "hide"           # stable id, unique within the bar
label = "Hide"        # text shown on the button
command = "hide"      # game command sent on click or hotkey
hotkey = "alt+h"      # optional (keybinds.toml syntax); keybinds.toml wins on conflict
tooltip = "Attempt to hide"   # hover text (GUI)
category = "Stealth"  # editor grouping only

Countdowns

An optional [bars.buttons.countdown] overlays remaining seconds on the button:

[bars.buttons.countdown]
source = "roundtime"          # "roundtime" | "casttime" | "effect"

For source = "effect", name the effect to track:

[bars.buttons.countdown]
source = "effect"
category = "Buffs"            # Buffs | Debuffs | Cooldowns | ActiveSpells
name = "Celerity"
name_match = "exact"          # "exact" or "contains"

Conditional States

[[bars.buttons.states]] entries restyle a button while a condition holds. The first matching state wins. Each state has a when condition and a style:

# Show the Hide button green and relabeled while hidden
[[bars.buttons.states]]
[bars.buttons.states.when]
type = "indicator"
id = "hidden"
active = true
[bars.buttons.states.style]
label = "Hidden"
fg = "#80ff80"

# Dim it during roundtime
[[bars.buttons.states]]
[bars.buttons.states.when]
type = "rt_active"
[bars.buttons.states.style]
dim = true

Condition Types

typeFieldsMatches when
effect_activecategory, name, name_matchThe effect is up
effect_inactivecategory, name, name_matchThe effect is not up
effect_timecategory, name, name_match, cmp, secondsRemaining time compares true (e.g. cmp = "<", seconds = 30)
rt_activeRoundtime is running
ct_activeCasttime is running
indicatorid, activeA status indicator matches: standing, kneeling, sitting, prone, stunned, bleeding, hidden, invisible, webbed, joined, dead
vitalvital, cmp, value, unitA vital compares true: health/mana/stamina/spirit, cmp one of < <= > >=, unit "percent" or "absolute"
spell_affordablenumberThe bundled spell table lists static costs for that spell number and your current absolute vitals cover them. Works without Lich. Fails closed on unknown numbers, variable (formula) costs, or before vitals data arrives; unlike Lich’s affordable? it does not model feats or debuffs.
all / anyconditions = [ ... ]All / any of the nested conditions match

Style Fields

FieldEffect
labelReplace the button text
fg / bgText / background color (#rrggbb)
dimRender the button dimmed
iconIcon override for this state (see Icons below)

A state may also carry its own [bars.buttons.states.countdown] (same schema as the button-level countdown); while the state is active it replaces the button-level source — e.g. show the cooldown timer only in the “on cooldown” state. Likewise command = "..." on a state replaces the button’s command while active (literal text — ;eq ... commands are evaluated by Lich, so dynamic behavior belongs in the command itself).

Icons (GUI)

Buttons can show an image face from a registered sprite sheet. Sheets are tiled into fixed-size cells with no padding, numbered 1-based left→right then top→bottom — the barbar convention. The TUI always renders the text label; icons are ignored there, and the GUI falls back to text when no registered sheet matches.

Sheets live in one of two places:

  • Shared store (~/.vellum-fe/global/images/icons/ with an icons.toml manifest) — available to every skin, and with no skin active at all. This is the default and the right choice for personal icon sets.
  • Active skin (the skin’s [sheets] table in skin.toml, see the skin docs) — travels with the skin; a skin sheet overrides a shared sheet with the same name.

The .hotbars editor does all of this without TOML: the button form has a Face selector (Text / Icon / Icon + label), a sheet dropdown, a clickable “Pick cell from sheet” grid, grayscale/border controls, and the same icon controls on every state card. The editor’s “Icon sheets” section registers a new sheet — give it a name and an image path and it copies the image into the shared store (or, with “All skins” unticked, into the active skin) and records it in the matching manifest for you. Each state card also carries its own countdown source (“Countdown while active”) that replaces the button-level one while the state matches.

[[bars.buttons]]
id = "hide"
label = "Hide"
command = "hide"
icon_mode = "icon"            # "text" (default) | "icon" | "icon_and_label"

[bars.buttons.icon]
sheet = "rogue"               # sheet name from the skin's [sheets] table
cell = 5                      # 1-based cell index
grayscale = false             # desaturate (e.g. for a "not ready" look)
border = "#00ff00"            # optional solid border over the icon
border_width = 3              # pixels, 1-10 (default 2)
border_end = "#004400"        # optional: gradient border toward this color
border_dir = "radial"         # horizontal (default) | vertical |
                              # diagonal_down | diagonal_up | radial | square

With icon_mode = "icon" the label moves into the hover tooltip. States can swap the icon (a different cell, or the same cell grayscaled) via [bars.buttons.states.style.icon] — dimmed states automatically use the grayscale variant. The sheet entry itself — in the shared store’s icons.toml (paths relative to global/images/icons/) or a skin’s skin.toml (paths relative to the skin directory) — looks the same either way:

[sheets.rogue]
path = "icons/rogue.png"      # image path; absolute paths allowed
cell = 64                     # cell edge in pixels (default 64)

Reloading

.reload hotbars re-reads the file; the editor saves and applies immediately.