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.

Owner Use it when Commands Typical events
Mobile An NPC acts, fights, speaks, remembers, receives, or reacts as a character. m* plus normal character commands Greet, Speech, Fight, Bribe, Damage
Object The behavior belongs to a carried, worn, room, timed, or consumed object. o* Get, Give, Wear, Timer, Consume
Room The 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

Symptom Likely cause Correction
Never fires Wrong 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 much Command 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 vanishes set created only a local variable. Use global for owner state or remote for target state.
Wrong command family An m*, o*, or w* command was used on another owner. Use the matching family or an owner-neutral pseudo-command.
Old behavior remains A 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.