Skip to content

Dashboard

A Lua-only HUD mod: a run panel with the time, wrecks and best streak, a marker on the nearest enemy, and settings to place, fade or hide them.

Mod id Kind Files
dashboard Lua code 2

Copy the whole folder into mods/ in the save folder to try it. Browse it on GitHub.

mod.json

{"id": "dashboard", "title": "Dashboard", "version": "1.0", "api": 1, "author": "Taxation Evasion",
 "description": "A Lua-only HUD mod: a run panel with the time, wrecks and best streak, a marker on the nearest enemy, and settings to place, fade or hide them.",
 "scripts": ["main.lua"],
 "settings": [
  {"id": "panel", "label": "RUN PANEL", "type": "toggle", "default": true,
   "help": "The time, wrecks and best streak at the side of the screen."},
  {"id": "side", "label": "PANEL SIDE", "type": "choice", "values": ["LEFT", "RIGHT"], "default": "LEFT"},
  {"id": "opacity", "label": "PANEL OPACITY", "type": "slider", "min": 0.2, "max": 1, "step": 0.1, "default": 0.8},
  {"id": "marker", "label": "TARGET MARKER", "type": "toggle", "default": true,
   "help": "A ring on the nearest enemy."}
 ]}

main.lua

-- A HUD panel and a world marker, drawn with the drawing kit `d`
-- (docs/modding/API.md#drawing). The player changes them on this mod's page
-- in Settings > CREDITS (mod.json `settings`).

-- Work numbers out in the simulation, where they are the same on every
-- machine; draw handlers only read them.
game.on('run_start', function(s) s.dashboard = {streak = 0, best = 0, last = 0} end)
game.on('kills', function(s, count)
  local t = s.dashboard
  t.streak = s.time - t.last < 3 and t.streak + count or count
  t.last = s.time
  if t.streak > t.best then t.best = t.streak end
end)

local function clock(seconds)
  return string.format('%d:%02d', math.floor(seconds / 60), math.floor(seconds % 60))
end

game.on('draw_hud', function(s, d)
  local t = s.dashboard
  if not t or not game.setting('panel') then return end
  local alpha = game.setting('opacity')
  local w, h = 92, 44
  local x = 8
  if game.setting('side') == 'RIGHT' then
    d.anchor('right')
    x = d.width - 8 - w
  else
    d.anchor('left')
  end
  local y = 180 - h / 2
  d.rect(x, y, w, h, 'black', 0.7 * alpha)
  d.box(x, y, w, h, 'gray', alpha)
  d.text('TIME', x + 6, y + 6, 'gray', 'left', alpha)
  d.text(clock(s.time or 0), x + w - 6, y + 6, 'white', 'right', alpha)
  d.text('WRECKS', x + 6, y + 18, 'gray', 'left', alpha)
  d.text(s.kills or 0, x + w - 6, y + 18, 'white', 'right', alpha)
  d.text('STREAK', x + 6, y + 30, 'gray', 'left', alpha)
  d.text(t.best, x + w - 6, y + 30, 'gold', 'right', alpha)
end)

game.on('draw_world', function(s, d)
  if not game.setting('marker') then return end
  local e = game.enemies(s, s.player.x, s.player.y, 220)[1]
  if not e or not d.visible(e.x, e.y, 20) then return end
  -- A slow pulse, held still for players who turned motion down.
  local pulse = d.reduced_motion and 0 or math.sin(d.time * 6) * 2
  d.ring(e.x, e.y, 14 + pulse, 'red', 0.8)
end)