Building triggers
A DG trigger is a small script that fires on a specific in-game event. Mob triggers handle NPC behavior; object triggers handle item interactions; world triggers handle room-level events. You write them with trigedit and attach them to entities via the S menu in medit/oedit/redit.
This guide is the builder-facing overview. For the full reference (every trigger type, every variable, every script command) see DG Scripts (staff doc, readable as a builder).
Open the editor
trigedit 8500 Create or edit trigger vnum 8500
Triggers are vnum-addressed just like mobs/objs/rooms. Pick a vnum in your zone’s range.
Main menu
Trigger Editor [8500]
1) Name : baker greet
2) Intended for : Mobiles
3) Trigger types: GREET
4) Numeric Arg : 100
5) Arguments : (none)
6) Commands:
* Triggered when someone enters the room
wait 2 sec
say If you're going adventuring, I recommend the waybread.
wait 10 sec
%echo% The Baker takes a rack of fresh bread from the oven.
W) Copy Trigger
Q) Quit
Pick the attach type FIRST
2) Intended for determines the available trigger types. You can’t change it after saving — triggers are bound to mob/obj/world. To switch, delete and recreate.
| Attach type | Used for | Commands available |
|---|---|---|
| Mobiles | NPCs that react/speak/move | m* script commands (mecho, mload, mteleport, …) |
| Objects | Items that react to use/wear/get | o* script commands |
| Rooms | Rooms that react to enter/leave/cast | w* script commands |
The trigger type bitvector
Each attach type has its own list. Pick one or more (multiple types = trigger fires on any matching event).
Common mob trigger types
| Type | Fires when | Useful for |
|---|---|---|
GREET | Someone enters the room the mob can see | Welcoming, gating, scripted reactions to PCs |
GREET_ALL | Anything enters (even invisible) | Trap-style mobs, hidden detection |
COMMAND | A character types a command | Override commands (“buy” handled by shopkeeper script) |
SPEECH | A character says a phrase | NPC dialogue, password-recognition |
ACT | An act() message in the room contains a keyword | Reacting to “smiles at you” etc. |
DEATH | The mob dies | Loot drop, summon servants, last words |
RANDOM | Random pulse (numeric arg = % per tick) | Ambient flavor lines |
FIGHT | Each combat round while fighting | Combat tactics, special attacks |
HITPRCNT | HP drops below N% (numeric arg = threshold) | Boss “second phase” behavior |
LOWHP | Edge-fires once when HP crosses below 20% | Distress call, flee trigger |
RECEIVE | Given an object | Quest turn-in |
BRIBE | Given coins (numeric arg = min amount) | Bribery scripts |
LOAD | The mob is loaded (zone reset) | Initialization, special setup |
MEMORY | Mob sees someone in its memory list | Vengeance scripts |
CAST | Mob is targeted by a spell | Anti-magic responses |
TIME | Game-hour matches numeric arg | Scheduled behaviors |
WEATHEREVENT | Weather event starts in the mob’s zone | In-fiction weather reactions |
TELL | A PC tells the mob something | Conversational NPCs |
Common object trigger types
| Type | Fires when |
|---|---|
GET | Picked up |
DROP | Dropped |
GIVE | Given to someone |
WEAR | Worn |
REMOVE | Removed |
USE | use <obj> |
CONSUME | Eaten/drunk |
CAST | Targeted by a spell |
LOAD | Loaded (zone reset) |
TIMER | Object’s timer expires |
RANDOM | Random pulse |
COMMAND | Owner types a command |
Common room trigger types
| Type | Fires when |
|---|---|
ENTER | A character enters |
LEAVE | A character leaves |
COMMAND | Command typed in the room |
SPEECH | Someone speaks |
CAST | Spell cast in the room |
DOOR | Door manipulated |
RANDOM | Random pulse |
RESET | Zone reset |
LOGIN | A character logs in to this room |
Numeric arg and arglist
These two fields are interpreted differently per trigger type:
| Trigger type | Numeric arg | Arglist |
|---|---|---|
| RANDOM | %-chance per pulse (1-100) | — |
| COMMAND | — | Command keyword(s) |
| SPEECH | 1=any-of, 2=all-of | Keyword(s) to match in spoken text |
| HITPRCNT | HP threshold % | — |
| BRIBE | Minimum coin amount | — |
| TIME | Game-hour to fire | — |
| GREET | %-chance per greet (1-100) | — |
| WEATHEREVENT | — | Event name filter |
| PUBSUB | — | Topic patterns: weather.*, combat.kill, * |
When in doubt, the editor labels them.
Variables
Inside command lines, %var% is substituted with the variable’s current value.
Built-in variables (most common)
%self%— the trigger’s owner (mob/obj/room)%actor%— whoever triggered this event%random.N%— random integer 1..N%time.hour%,%time.day%,%time.month%%argument%— for COMMAND triggers, the rest of the command line%speech%— for SPEECH triggers, what was said%topic%,%payload%— for PUBSUB triggers%direction%— for GREET/LEAVE triggers, the direction they entered/left
Field access
%actor.name%, %actor.level%, %actor.class%, %actor.hp%, %actor.is_pc%, %actor.vnum% (for mobs).
Chain for nested fields: %actor.room.vnum%.
Sub-fields with arguments: %actor.eq(wield).name% (the weapon’s short desc), %actor.skill(magic missile)% (skill level).
Control flow
Inside the command body:
* This is a comment
if <condition>
<commands>
elseif <condition>
<commands>
else
<commands>
end
while <condition>
<commands>
done
switch <value>
case <val1>
<commands>
break
default
<commands>
break
done
set <varname> <value>
eval <varname> <expression>
wait <N> * wait N seconds
wait <N> tick
wait until <hour>
halt * abort execution
return <0|1> * 1 = command consumed (for COMMAND triggers)
Worked examples
Greeter
Name: Baker greeter
Intended for: Mobiles
Trigger types: GREET
Numeric arg: 100
Arguments: (none)
Commands:
wait 1 sec
msend %actor% The Baker waves at you.
mecho The Baker waves at %actor.name%.
Attach to the Baker via medit … S.
Conditional door guard
Name: Guard north
Intended for: Mobiles
Trigger types: COMMAND
Numeric arg:
Arguments: north
Commands:
if %actor.level% < 10
msend %actor% The guard blocks your way! "You are not yet ready."
return 1
end
msend %actor% The guard nods and lets you pass.
Attach to the guard. return 1 consumes the command so the player doesn’t actually walk north.
Quest item turn-in
Name: Collect dragon scales
Intended for: Mobiles
Trigger types: RECEIVE
Numeric arg:
Arguments:
Commands:
if %object.vnum% != 3000
msend %actor% %self% looks confused. "I have no use for that."
mforce %actor% take %object% from %self%
halt
end
msend %actor% %self% bows deeply. "Thank you, brave one!"
mload obj 3001
give scroll %actor%
if %actor.questvar(scales_quest)% != complete
set scales_quest complete
msend %actor% Quest "Dragon Scales" complete!
end
Ambient random mob action
Name: Tavern crowd noise
Intended for: Rooms
Trigger types: RANDOM
Numeric arg: 3
Arguments:
Commands:
switch %random.4%
case 1
wecho A merchant slams his mug on the table, laughing.
break
case 2
wecho A dwarf at the bar mutters something about deep tunnels.
break
case 3
wecho A traveler at a corner table glances around nervously.
break
default
wecho The fire crackles in the hearth.
break
done
Attach to the tavern room. With numeric_arg=3, fires roughly 3% of pulses — about every 30 seconds on average.
Boss second phase
Name: Dragon enrage
Intended for: Mobiles
Trigger types: HITPRCNT
Numeric arg: 50
Arguments:
Commands:
mecho %self% roars in fury, eyes blazing with rage!
set rage_active 1
mforce %self% breathe fire
Once per fight when HP drops below 50%, the dragon enrages and uses a special attack.
Periodic shopkeeper restock
Name: Restock bakery
Intended for: Mobiles
Trigger types: TIME
Numeric arg: 6
Arguments:
Commands:
* 6am every game-day
mecho %self% takes a fresh batch of bread from the oven.
mload obj 3010
mload obj 3011
mload obj 3012
Attaching triggers to entities
After saving the trigger:
- Mob:
medit <vnum>→S→ add trigger vnum. - Object:
oedit <vnum>→S→ add trigger vnum. - Room:
redit <vnum>→S→ add trigger vnum.
A trigger can be attached to multiple entities. Each instance gets its own running state.
You can also use the T zone reset command to attach a trigger only when the entity is loaded in a specific room.
Debugging
mlog/olog/wlog— write to the script log. Use freely. - Add comment lines (
* …) liberally. - For variable issues, use
mecho debug: var=%myvar%to confirm interpolation. tstat <vnum>andvstat trig <vnum>show the trigger’s loaded state in-game.- DG runtime errors log to
script.logAND toshow script-errors(GOD). show script-errors recentshows the latest failures.
Common pitfalls
| Symptom | Cause |
|---|---|
| Trigger doesn’t fire at all | Not attached, or the trigger type bitvector doesn’t include the event |
if runs unconditionally | Forgot == (used = which is assignment — set is the right keyword) |
%var% prints literally | Variable not set; check spelling and case |
| Trigger fires once then never again | Hit a halt somewhere, or a COMMAND trigger consumed with return 1 |
| Loop runs forever | while without an exit; engine caps with GET_TRIG_LOOPS after N iterations |
See also
- DG Scripts — full reference (every trigger type, every command, every variable).
- Building mobiles — attach mob triggers.
- Building objects — attach object triggers.
- Building rooms — attach room triggers.
- Building quests — quest triggers are a common use case.