Skip to content

Lua Scripting Overview

TalesMUD uses Lua (via gopher-lua) as the primary scripting language for dynamic game content. Scripts let you add custom mechanics, react to game events, and extend any system without modifying the Go source.

Room Events

Fire when players enter rooms (onEnterScript). Add atmosphere, reveal exits, grant quests.

Room Actions

Attach to interactive objects. Handle puzzles, switches, mechanisms.

Item Use

Execute when players use consumables or special items (onUseScriptId).

Quest Completion

Fire on quest completion (onCompleteScriptId). Award custom rewards, reveal content.

Scripts are stored in the database with this structure:

type Script struct {
ID string // Unique identifier (e.g., "SCR0007")
Name string // Human-readable name
Description string // What the script does
Code string // Lua source code
Type ScriptType // item | room | npc | quest | event | custom
Language ScriptLanguage // "lua" (or "javascript" — deprecated)
}

In the Creator UI, navigate to Scripts → New:

-- Example: Dungeon atmosphere script
-- Trigger: Room enter (attach to a room's "On Enter Script" field)
local charID = ctx.character.id
if tales.utils.chance(30) then
tales.game.msgToCharacter(charID,
"A bat swoops past your head in the darkness.")
end
if tales.utils.chance(10) then
tales.game.msgToRoom(ctx.room.id,
"The cave groans ominously around you.")
end

Or via the REST API:

Terminal window
curl -X POST http://localhost:8010/api/scripts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Dungeon Atmosphere",
"type": "room",
"language": "lua",
"code": "-- your script here"
}'

Scripts must be attached to trigger them. Attachment points:

AttachmentLocationTrigger
room.onEnterScriptIDRoom entityPlayer enters the room
room.actions[n].scriptIdRoom actionPlayer uses the action
item.onUseScriptIdItem entityPlayer uses the item
quest.onCompleteScriptIdQuest entityQuest is completed

Every script receives a ctx global with data relevant to the triggering event:

-- Room enter context
ctx.eventType -- "player.enter_room"
ctx.room -- The room entity
ctx.toRoom -- Destination room (when available)
ctx.character -- The character entering
ctx.user -- The user account
-- Item use context
ctx.item -- The item being used
ctx.character -- The character using it
ctx.room -- The room it's happening in
-- Quest completion context
ctx.character -- The character completing the quest
ctx.room -- Current room

All scripting functionality is in the tales global object:

tales.items.* -- Item management
tales.rooms.* -- Room queries and manipulation
tales.characters.* -- Character queries and actions
tales.npcs.* -- NPC management
tales.dialogs.* -- Dialog and conversation management
tales.quests.* -- Quest progress management
tales.game.* -- Messaging and game flags
tales.utils.* -- Random numbers, dice, time utilities

See the API Reference for full documentation of every function.

Scripts run in a sandboxed environment:

  • 5-second timeout — Scripts that exceed 5 seconds are terminated
  • Disabled modulesos, io, debug, loadfile, dofile are removed from the Lua sandbox
  • VM pool — 10 reusable Lua VMs for performance; each script gets its own state
  • Isolated execution — Scripts cannot access filesystem or network

TalesMUD previously used JavaScript (ES5 via the Otto engine). JavaScript scripts still run but show deprecation warnings in the server logs. All new scripts should use Lua.

See Migrating from JavaScript for the conversion guide.

If you have existing JavaScript scripts:

JavaScriptLua
var x = ...local x = ...
function() { }function() end
T_functionName()tales.module.functionName()
array[0]array[1] (1-indexed)
"a" + "b""a" .. "b"
Math.random()tales.utils.randomFloat()

JavaScript:

var item = ctx;
item.minDamage = Math.floor(Math.random() * 5) + 1;
item.maxDamage = item.minDamage + Math.floor(Math.random() * 10) + 5;
ctx = JSON.stringify(item);

Lua:

local item = ctx.item
item.minDamage = tales.utils.random(1, 5)
item.maxDamage = item.minDamage + tales.utils.random(5, 15)
return item