Skip to content

GMCP Integration

MorquinDevlar edited this page Aug 20, 2026 · 4 revisions

GMCP Integration

Communication Channels

Route GMCP communication messages to appropriate tabs in a tabbed widget.

Step 1: Create the widget (registered via mdw.onReady, safe at any script position - see Getting Started)

-- Script: CommWidgetSetup
mdw = mdw or {}
mdw.onReady = mdw.onReady or {}

mdw.onReady["CommWidget"] = function()
  mdw.TabbedWidget:new({
    name = "Comm",
    title = "Communications",
    tabs = {"All", "Room", "Chat", "Tells"},
    allTab = "All",
    dock = "right",
    height = 300,
  })
end

if mdw.isSetUp and mdw.runReadyCallbacks then mdw.runReadyCallbacks("CommWidget") end

Step 2: Handle GMCP messages (in a separate Script with gmcp.Comm.Channel event handler)

-- Script: CommHandler
-- Event: gmcp.Comm.Channel

--[[
  gmcp.Comm.Channel structure:
  {
    channel = "chat",
    sender = "Bob",
    source = "player",
    text = "this is a test"
  }
]]

function onCommChannel()
  local comm = mdw.TabbedWidget.get("Comm")
  if not comm then return end

  local data = gmcp.Comm.Channel
  local channel = data.channel
  local sender = data.sender
  local text = data.text

  -- Map GMCP channel names to tab names
  local tabMap = {
    say = "Room",
    yell = "Room",
    chat = "Chat",
    newbie = "Chat",
    tell = "Tells",
    reply = "Tells",
  }

  local tabName = tabMap[channel] or "All"

  -- Format and display the message
  local color = (channel == "tell" or channel == "reply") and "yellow" or "white"
  comm:cechoTo(tabName, string.format(
    "<gray>[<" .. color .. ">%s<gray>] <<cyan>%s<gray>> %s\n",
    channel, sender, text
  ))
end

Character Vitals

Display character stats in a widget, updating whenever GMCP vitals are received.

Step 1: Create the widget (registered via mdw.onReady, safe at any script position)

-- Script: VitalsWidgetSetup
mdw = mdw or {}
mdw.onReady = mdw.onReady or {}

mdw.onReady["VitalsWidget"] = function()
  mdw.Widget:new({
    name = "Vitals",
    title = "Character Stats",
    dock = "left",
    height = 150,
  })
end

if mdw.isSetUp and mdw.runReadyCallbacks then mdw.runReadyCallbacks("VitalsWidget") end

Step 2: Handle GMCP vitals (in a separate Script with gmcp.Char.Vitals event handler)

-- Script: VitalsHandler
-- Event: gmcp.Char.Vitals

--[[
  gmcp.Char.Vitals structure:
  {
    health = 9,
    health_max = 9,
    mana = 7,
    mana_max = 7,
    stamina = 52,
    stamina_max = 52
  }
]]

function onCharVitals()
  local vitals = mdw.Widget.get("Vitals")
  if not vitals then return end

  local v = gmcp.Char.Vitals

  -- Calculate percentages
  local healthPct = (v.health / v.health_max) * 100
  local manaPct = (v.mana / v.mana_max) * 100
  local staminaPct = (v.stamina / v.stamina_max) * 100

  -- Choose colors based on percentage
  local function getColor(pct)
    if pct > 66 then return "green"
    elseif pct > 33 then return "yellow"
    else return "red"
    end
  end

  -- Clear and redraw
  vitals:clear()
  vitals:cecho(string.format(
    "  <white>Health:  <%s>%d<white>/<green>%d <gray>(%d%%)\n",
    getColor(healthPct), v.health, v.health_max, healthPct
  ))
  vitals:cecho(string.format(
    "  <white>Mana:    <%s>%d<white>/<green>%d <gray>(%d%%)\n",
    getColor(manaPct), v.mana, v.mana_max, manaPct
  ))
  vitals:cecho(string.format(
    "  <white>Stamina: <%s>%d<white>/<green>%d <gray>(%d%%)\n",
    getColor(staminaPct), v.stamina, v.stamina_max, staminaPct
  ))
end

Tips for GMCP Integration

  1. Always check if the widget exists before using it, in case MDW hasn't loaded yet or the widget was destroyed
  2. Use separate scripts for widget creation and GMCP handlers to keep code organized
  3. Create widgets through the mdw.onReady registry so they are recreated on every reload and package update, regardless of script order (see Getting Started)
  4. Use widget:clear() before redrawing for vitals/stats that replace their entire content
  5. Use echoTo()/cechoTo()/dechoTo()/hechoTo() for communication to take advantage of the "all tab" feature
  6. Prefer real gauges for vitals: declare a gauge row in the prompt bar (mdw.setPromptGauges, see Prompt Bar) or gauge and text rows at the top of a widget (mdw.setWidgetRows, see Widget Rows) instead of drawing bars from text

Clone this wiki locally