---
title: Building triggers
summary: DG triggers are scripted reactions attached to mobs, objects, or rooms. This guide covers trigedit, the three attach types, common trigger types (GREET, COMMAND, RANDOM, DEATH, etc.), variable interpolation, control flow, and worked examples.
order: 50
updated: 2026-05-18
---

# 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/docs/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` <text>** — write to the script log. Use freely.
- Add comment lines (`* …`) liberally.
- For variable issues, use `mecho debug: var=%myvar%` to confirm interpolation.
- `tstat <vnum>` and `vstat trig <vnum>` show the trigger's loaded state in-game.
- DG runtime errors log to `script.log` AND to `show script-errors` (GOD).
- `show script-errors recent` shows 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](/staff/docs/dg-scripts) — full reference (every trigger type, every command, every variable).
- [Building mobiles](/builders/mobiles) — attach mob triggers.
- [Building objects](/builders/objects) — attach object triggers.
- [Building rooms](/builders/rooms) — attach room triggers.
- [Building quests](/builders/quests) — quest triggers are a common use case.
