Room Events
Fire when players enter rooms (onEnterScript). Add atmosphere, reveal exits, grant quests.
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.")endOr via the REST API:
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:
| Attachment | Location | Trigger |
|---|---|---|
room.onEnterScriptID | Room entity | Player enters the room |
room.actions[n].scriptId | Room action | Player uses the action |
item.onUseScriptId | Item entity | Player uses the item |
quest.onCompleteScriptId | Quest entity | Quest is completed |
ctx Context VariableEvery script receives a ctx global with data relevant to the triggering event:
-- Room enter contextctx.eventType -- "player.enter_room"ctx.room -- The room entityctx.toRoom -- Destination room (when available)ctx.character -- The character enteringctx.user -- The user account
-- Item use contextctx.item -- The item being usedctx.character -- The character using itctx.room -- The room it's happening in
-- Quest completion contextctx.character -- The character completing the questctx.room -- Current roomtales Global APIAll scripting functionality is in the tales global object:
tales.items.* -- Item managementtales.rooms.* -- Room queries and manipulationtales.characters.* -- Character queries and actionstales.npcs.* -- NPC managementtales.dialogs.* -- Dialog and conversation managementtales.quests.* -- Quest progress managementtales.game.* -- Messaging and game flagstales.utils.* -- Random numbers, dice, time utilitiesSee the API Reference for full documentation of every function.
Scripts run in a sandboxed environment:
os, io, debug, loadfile, dofile are removed from the Lua sandboxTalesMUD 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:
| JavaScript | Lua |
|---|---|
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.itemitem.minDamage = tales.utils.random(1, 5)item.maxDamage = item.minDamage + tales.utils.random(5, 15)return itemtales.* function documented