Mudlet HP/SP/XP Bars Script
Live gauge bars showing your health, spell points, and XP progress
This script uses GMCP (Generic MUD Communication Protocol) to receive your character's vital stats in real time and display them as color-coded gauge bars in Mudlet. The HP bar shifts from green to yellow to red as your health drops. The XP bar shows your progress toward your next level.
Requirements
- Mudlet 4.x or newer
- Connect via telnet:
mysticmud.comport3000 - Connect via telnet with TLS:
mysticmud.comport3100
Installation
- Copy the script below (use the Copy button).
- In Mudlet, open the Script Editor (the
<>button in the toolbar). - Click Add Item and choose Script (not Trigger or Alias).
- Give it a name like Mystic Bars, paste the script, then click Save Item and Save Profile.
- Disconnect and reconnect to Mystic. The bars will appear in the bottom-right corner of the main window.
Usage
- Bars update automatically whenever your HP, SP, or XP changes.
- The HP bar turns red below 25%, yellow below 50%, and green at 50%+.
- The XP bar shows how much XP you have earned toward the next level, with the TNL (to next level) count as its label.
To reposition or resize the bars:
Edit the
Edit the
mystic.gaugeConfig table at the top of the script.
rightMargin and bottomMargin control the anchor point;
width, height, and spacing control the bar dimensions.
After editing, re-save the script and run: lua mystic.createGauges()
Script
-- ============================================================
-- Mystic MUD: GMCP Bootstrap + HP/SP/XP Gauge Bars
-- ============================================================
-- Install: Toolbox > Scripts > Add Item > paste this > Save
-- Reconnect to Mystic (or type: lua mystic.gmcpBootstrap())
-- ============================================================
mystic = mystic or {}
-- ---------------------------------------------------------
-- Configuration: tweak these to taste
-- ---------------------------------------------------------
mystic.gaugeConfig = {
-- Position: gauges anchor to bottom-right of main window
width = 250,
height = 22,
spacing = 4,
rightMargin = 50,
bottomMargin = 590,
fontSize = 10,
}
-- ---------------------------------------------------------
-- Create or recreate the gauge bars
-- ---------------------------------------------------------
function mystic.createGauges()
local cfg = mystic.gaugeConfig
local x = -(cfg.width + cfg.rightMargin)
local yBase = -(cfg.bottomMargin)
-- XP bar (bottom)
if mystic.xpBar then mystic.xpBar:hide() end
mystic.xpBar = Geyser.Gauge:new({
name = "mysticXPBar",
x = x, y = yBase - cfg.height,
width = cfg.width, height = cfg.height,
})
mystic.xpBar.front:setStyleSheet([[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #665514, stop:1 #ccaa20);
border: 1px solid #332a0a;
]])
mystic.xpBar.back:setStyleSheet([[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #1a1509, stop:1 #332a0a);
border: 1px solid #332a0a;
]])
mystic.xpBar:setValue(0, 100, "<b>XP</b>")
mystic.xpBar.text:setStyleSheet(string.format(
"font-size: %dpx; color: white; font-family: monospace;",
cfg.fontSize
))
-- SP bar (above XP)
if mystic.spBar then mystic.spBar:hide() end
mystic.spBar = Geyser.Gauge:new({
name = "mysticSPBar",
x = x, y = yBase - (cfg.height * 2) - cfg.spacing,
width = cfg.width, height = cfg.height,
})
mystic.spBar.front:setStyleSheet([[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #141466, stop:1 #2a20cc);
border: 1px solid #0a0a33;
]])
mystic.spBar.back:setStyleSheet([[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #09091a, stop:1 #0a0a33);
border: 1px solid #0a0a33;
]])
mystic.spBar:setValue(0, 100, "<b>SP</b>")
mystic.spBar.text:setStyleSheet(string.format(
"font-size: %dpx; color: white; font-family: monospace;",
cfg.fontSize
))
-- HP bar (above SP)
if mystic.hpBar then mystic.hpBar:hide() end
mystic.hpBar = Geyser.Gauge:new({
name = "mysticHPBar",
x = x, y = yBase - (cfg.height * 3) - (cfg.spacing * 2),
width = cfg.width, height = cfg.height,
})
mystic.hpBar.front:setStyleSheet([[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #661414, stop:1 #cc2020);
border: 1px solid #330a0a;
]])
mystic.hpBar.back:setStyleSheet([[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #1a0909, stop:1 #330a0a);
border: 1px solid #330a0a;
]])
mystic.hpBar:setValue(0, 100, "<b>HP</b>")
mystic.hpBar.text:setStyleSheet(string.format(
"font-size: %dpx; color: white; font-family: monospace;",
cfg.fontSize
))
end
-- ---------------------------------------------------------
-- Update gauges from GMCP Char.Vitals
-- ---------------------------------------------------------
function mystic.onVitals()
local v = gmcp.Char.Vitals
if not v then return end
local hp = v.hp or 0
local maxhp = v.maxhp or 1
local sp = v.sp or 0
local maxsp = v.maxsp or 1
local xp_tnl = v.xp_tnl or 0
local xp_earned = v.xp_earned or 0
local xp_level = v.xp_level or 1
-- HP bar with color shift
local hp_pct = (hp / maxhp) * 100
local hp_css
if hp_pct < 25 then
hp_css = [[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #661414, stop:1 #cc2020);
border: 1px solid #330a0a;
]]
elseif hp_pct < 50 then
hp_css = [[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #665514, stop:1 #ccaa20);
border: 1px solid #332a0a;
]]
else
hp_css = [[
background-color: QLinearGradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #146614, stop:1 #20cc20);
border: 1px solid #0a330a;
]]
end
mystic.hpBar.front:setStyleSheet(hp_css)
mystic.hpBar:setValue(hp, maxhp,
string.format("<b>HP: %d / %d</b>", hp, maxhp))
-- SP bar
mystic.spBar:setValue(sp, maxsp,
string.format("<b>SP: %d / %d</b>", sp, maxsp))
-- XP bar (shows progress within current level)
if xp_level > 0 then
mystic.xpBar:setValue(xp_earned, xp_level,
string.format("<b>XP: %s TNL</b>",
mystic.formatNumber(xp_tnl)))
else
mystic.xpBar:setValue(100, 100, "<b>XP: Max Level</b>")
end
end
-- ---------------------------------------------------------
-- Number formatting helper (1234567 -> "1,234,567")
-- ---------------------------------------------------------
function mystic.formatNumber(n)
local s = tostring(n)
local result = ""
local count = 0
for i = #s, 1, -1 do
count = count + 1
result = s:sub(i, i) .. result
if count % 3 == 0 and i > 1 then
result = "," .. result
end
end
return result
end
-- ---------------------------------------------------------
-- GMCP Bootstrap
-- ---------------------------------------------------------
function mystic.gmcpBootstrap()
sendGMCP('Core.Supports.Set ["Char 1", "Room 1", "Comm 1", "Group 1"]')
end
-- ---------------------------------------------------------
-- Register everything
-- ---------------------------------------------------------
if mystic._bootstrapHandler then
killAnonymousEventHandler(mystic._bootstrapHandler)
end
if mystic._vitalsHandler then
killAnonymousEventHandler(mystic._vitalsHandler)
end
mystic._bootstrapHandler = registerAnonymousEventHandler(
"gmcp.Core.Hello", "mystic.gmcpBootstrap"
)
mystic._vitalsHandler = registerAnonymousEventHandler(
"gmcp.Char.Vitals", "mystic.onVitals"
)
-- Create the gauges now
mystic.createGauges()
cecho("\n<green>[Mystic] <white>HP/SP/XP gauges loaded. Reconnect or run: lua mystic.gmcpBootstrap()\n")
Questions? Ask in-game or on Discord.