MadROM Mudlet MSDP Setup Guide

This walkthrough is for players who already use Mudlet/Lua but want a reliable, repeatable setup for MSDP values on MadROM. If MSDP has ever felt weird compared to zMUD/cMUD triggers, this is the "just make it work" path.

Want the fast path instead? Import the MadROM package directly: madrom.mpackage.

1) Connection profile settings

  1. Open your MadROM profile in Mudlet.
  2. Go to Settings -> Special Options and keep telnet option negotiation enabled (default).
  3. Connect once so Mudlet and MadROM negotiate MSDP.

2) Create one script to track MSDP updates

In Mudlet, create a new script named madrom_msdp_core and paste this:

-- MadROM MSDP cache for Mudlet
madrom = madrom or {}
madrom.msdp = madrom.msdp or {}

-- Mudlet stores MSDP values in the global msdp table and raises msdp.* events.
function madrom_on_msdp(event)
  local key = type(event) == "string" and event:match("^msdp%.(.+)$") or nil
  if not key or not msdp then
    return
  end

  madrom.msdp[key] = msdp[key]
end

registerAnonymousEventHandler("msdp", function()
  for key, value in pairs(msdp or {}) do
    madrom.msdp[key] = value
  end
end)

registerAnonymousEventHandler("msdp.HEALTH", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.HEALTH_MAX", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.MANA", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.MANA_MAX", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.MOVEMENT", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.MOVEMENT_MAX", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.ROOM_NAME", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.OPPONENT_NAME", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.OPPONENT_HEALTH", "madrom_on_msdp")
registerAnonymousEventHandler("msdp.OPPONENT_HEALTH_MAX", "madrom_on_msdp")

-- Convenience helpers
function msdpNumber(name, fallback)
  local v = madrom.msdp[name]
  v = tonumber(v)
  if v == nil then
    return fallback or 0
  end
  return v
end

function msdpText(name, fallback)
  local v = madrom.msdp[name]
  if v == nil or v == "" then
    return fallback or ""
  end
  return tostring(v)
end

3) Verify values are actually arriving

Create a second script named madrom_msdp_test:

function showMadromVitals()
  cecho(string.format(
    "<cyan>HP %d/%d  Mana %d/%d  Move %d/%d\n",
    msdpNumber("HEALTH"),
    msdpNumber("HEALTH_MAX"),
    msdpNumber("MANA"),
    msdpNumber("MANA_MAX"),
    msdpNumber("MOVEMENT"),
    msdpNumber("MOVEMENT_MAX")
  ))
end

showMadromVitals()

If that prints sane numbers, your MSDP link is good.

The current package also renders the server's MSDP button hints as clickable buttons and keeps separate chat tabs for all/gossip/tell/group traffic inside the side pane.

4) Useful MadROM MSDP fields

Common values you can read immediately:

  • HEALTH, HEALTH_MAX
  • MANA, MANA_MAX
  • MOVEMENT, MOVEMENT_MAX
  • EXPERIENCE, EXPERIENCE_TNL
  • ROOM_NAME, ROOM_VNUM, AREA_NAME
  • OPPONENT_NAME, OPPONENT_HEALTH, OPPONENT_HEALTH_MAX

5) Troubleshooting when it feels cursed

  • If your values stay nil, reconnect after saving scripts.
  • If you imported an older package build, re-import the latest madrom.mpackage manually.
  • Client helpers should send MSDP REPORT/SEND as an operation plus separate variable names (repeated MSDP_VAR/MSDP_VAL pairs on the wire), not as one packed table/list argument.
  • If one key is empty, test another key first (for example HEALTH) to confirm the event path works.
  • Avoid duplicate handlers: if you copy scripts around, you can accidentally register the same event multiple times.
  • In Mudlet, MSDP values land in the global msdp table and the client raises msdp.HEALTH-style events; they do not arrive through sysDataReceive the way this guide once implied.
  • When in doubt, print the whole MSDP table once:
    registerAnonymousEventHandler("msdp", function() display(msdp) end)

Once this is stable, you can build gauges, condition warnings, auto-map notes, and combat widgets on top of madrom.msdp without rewriting your core parser.