Skip to content
DG Scripts

Getting started

Build one small, observable behavior first. The goal is to understand which event starts a script, who owns it, and which state survives after it stops.

Implementation trailEvent hooks: src/dgscript/dg_triggers.c. Execution: src/dgscript/dg_scripts.c. Editing: src/dgscript/dg_olc.c.

The runtime in one pass

Game evententer, say, get...
Trigger hooktype + chance
Event variablesactor, direction...
Script driversubstitute + run
World effectsend, load, state...

A trigger prototype has a VNUM, name, intended owner type, event flags, Numeric Arg, Arguments string, and command list. Attaching that prototype gives an entity a runnable trigger instance. When a matching hook fires, the driver substitutes %variables% and sends non-control commands to the interpreter for the owner type.

A trigger is not a polling script

Most triggers run only because a specific game hook calls them. Random and Time triggers are the periodic exceptions, and their Global flag changes whether empty-zone checks are allowed.

1. Choose the owner that receives the event

Ownership is structural, not cosmetic. It selects the available trigger types, the meaning of %self%, and the command interpreter used after control commands are handled.

OwnerUse it whenCommandsTypical events
MobileAn NPC acts, fights, speaks, remembers, receives, or reacts as a character.m* plus normal character commandsGreet, Speech, Fight, Bribe, Damage
ObjectThe behavior belongs to a carried, worn, room, timed, or consumed object.o*Get, Give, Wear, Timer, Consume
RoomThe location observes entrants, speech, doors, drops, login, or zone reset.w*Enter, Command, Zone Reset, Login

Do not choose a room owner merely because an effect happens in a room. Choose it when the room receives the relevant hook. The trigger matrix shows every owner/event combination.

2. Rebuild a small live trigger

The Dollhouse room trigger below reacts only when someone enters from the west. It is useful as a first exercise because the trigger has one event variable, short waits, and visible output.

VNUM
Use a free VNUM in your assigned zone
Name
Hiding girl beckons
Intended for
Rooms
Trigger type
Enter
Numeric Arg
100 (100 percent chance)
Arguments
Empty
Live pattern: lib/world/trg/118.trg, trigger 11868
if %direction% == west
  wait 1 s
  %send% %actor% You hear a shuffling sound from under the bed.
  wait 1 s
  %send% %actor% A child's voice whispers: Quick, crawl in here!
end
  1. Enter trigedit <vnum> and fill the fields above.
  2. Open the Commands editor, enter the body, save, and quit.
  3. Open REDIT for a test room, choose S, then attach the trigger by VNUM.
  4. Save the room, leave it, and enter from west and from a different direction.

%send% is an owner-neutral pseudo-command. On a room owner it resolves to the room implementation of send; the command guide explains the mapping.

3. Know where values come from

The Enter hook creates actor and direction for this run. %actor% substitutes the actor's internal UID where a command needs an entity target; %actor.name% reads a field. Trigger-local variables created with set disappear when the run finishes.

  • set clue redLocal to this trigger run.
  • global clueMoves that local value into the owner's script-global state, under the current context.
  • remote clue %actor.id%Copies the local value to the actor's script-global state.
  • rdelete clue %actor.id%Deletes that remote global value.

UID rule

Pass event-supplied UIDs directly to entity commands. Use an entity's .id only where a command explicitly asks for a numeric script ID, such as remote or rdelete. Use makeuid when a marked UID must be built from an ID or nearby name; never construct or guess its prefix.

4. Attach, reload, and test both paths

Permanent attachments are edited from the S scripts menu in MEDIT, OEDIT, or REDIT and written as T <trigger-vnum> records in world files. The staff attach command affects a runtime instance and is best used for controlled inspection.

  • Save both the trigger and its owning prototype or room.
  • Load a fresh mobile or object instance after changing attachments.
  • Exercise the matching case and at least one non-matching case.
  • Check visible output, owner state, player state, and logs.
  • Run python3 scripts/world/wtool.py validate --zone <zone>.

See Testing and debugging for a repeatable verification sequence and runtime limits.

Common first-script mistakes

SymptomLikely causeCorrection
Never firesWrong owner/event pairing, no attachment, failed chance roll, or zone is empty for a periodic trigger.Use tstat, inspect the owner, and temporarily make the condition observable.
Intercepts too muchCommand prefix or wildcard is broad, and the body does not reject unrelated commands.Compare %cmd.mudcommand% and %arg%; use return 0 on the non-match path.
State vanishesset created only a local variable.Use global for owner state or remote for target state.
Wrong command familyAn m*, o*, or w* command was used on another owner.Use the matching family or an owner-neutral pseudo-command.
Old behavior remainsA live owner still has an older attachment set, aggregate event flags, or owner-global state.Save both editors, reload the owner, and retest from a clean state.

Return values are hook-specific

return N sets an integer result, but only event hooks that read that result give it gameplay meaning. Receive can veto a transfer, and Damage uses the returned value as replacement damage. Do not assume every trigger type consumes it.