tbamud/lib/scripts/README.md

162 lines
5.2 KiB
Markdown

Scripts In lib/scripts
======================
This directory contains Python and DSL-style scripts used by the game. Scripts
are attached to rooms, npc's, and objects via builder commands (e.g. `rset add script`,
`mset add script`, `oset add script`). The script file itself is the data format.
Two Script Styles
-----------------
1) DSL (no function definitions)
- If the file does NOT contain `def on_trigger`, it is treated as the DSL.
- The DSL supports Python-style `if/elif/else`, `for`, and `while` blocks.
- Actions are written as simple verbs or function-style calls:
- `move("n")` or `move("north")`
- `move(1200)` (room vnum path step, no closed doors)
- `emote("looks around warily")`
- `sleep(3)`
- `log("text with {npc.vnum}")`
- `do("say hello")`
- Command-style is also supported:
- `move "n"`
- `sleep 3`
- `log "hello {npc.vnum}"`
- NOTE: The DSL does not support custom variable assignments yet. Use the
full Python style if you need variables.
2) Full Python (with `def on_trigger(event):`)
- If the file contains `def on_trigger`, it runs as normal Python.
- Use `mud.sleep(seconds)` to pause and resume later.
- You can use local variables, helpers, and full Python expressions.
Event Context (Full Python)
---------------------------
`on_trigger(event)` receives a dict with:
- `event["self"]`: the entity this trigger is attached to (mob/object/room)
- `event["trigger"]`: info about the trigger (vnum, name, type, narg, etc.)
- `event["vars"]`: trigger variables (if any)
Entity Data Model (DSL and Python)
----------------------------------
Every entity has these common properties:
- `entity.kind` -> kind id (mob/obj/room)
- `entity.uid` -> unique runtime id
- `entity.vnum` -> vnum (mob/obj/room)
- `entity.name` -> name/short for display
Mob (NPC or PC) properties:
- `npc.health` / `npc.max_health`
- `npc.mana` / `npc.max_mana`
- `npc.stamina` / `npc.max_stamina`
- `npc.move` / `npc.max_move` (alias for stamina)
- `npc.class` / `npc.class_id`
- `npc.species` / `npc.species_id`
- `npc.is_pc` / `npc.is_npc`
- `npc.keyword` (NPC keywords; for PCs, name)
- `npc.room` -> room entity where the mob is located
- `npc.room.vnum` -> room vnum
- `npc.room.name` -> room name/short
Object properties:
- `object.keyword` -> object keywords
- `object.oval` -> list of object values (oval[0] .. oval[NUM_OBJ_VAL_POSITIONS-1])
- `object.room` -> room entity where the object is located
- `object.room.vnum` -> room vnum
- `object.room.name` -> room name/short
Room properties:
- `room.contents` -> list of objects in the room
- `room.people` -> list of characters in the room
- `room.vnum` -> room vnum
- `room.name` -> room name/short
Entity comparisons:
- `entity == "rat"` checks keyword match for mobs/objects.
- `entity == 123456` checks entity uid.
- `entity_a == entity_b` matches if kind+uid are equal.
Available Methods
-----------------
These are available in both DSL and Python (via the `mud` module).
Core methods:
- `mud.do(command, actor=None)`
Execute a game command. If `actor` is a mob, it runs as that mob. If `actor`
is a room, it runs in that room context.
- `mud.emote(message, actor=None)`
Emote as a mob (actor is optional if the trigger is on a mob).
- `mud.move(direction, actor=None)`
Move a mob in a direction (e.g. "n", "south", "ne").
You can also pass a room vnum to step toward a destination, but if it is blocked (eg. with a door), this will not work.
- `mud.sleep(seconds)`
Pause the script and resume later.
- `mud.roll("1d6")`
Roll dice. Supported: d4/d6/d8/d10/d12/d20/d100.
- `mud.log(message)`
Write to `log/script.log`.
- `mud.echo_room(room, message)`
Echo a message to a specific room.
- `mud.send_char(character, message)`
Send a message to a character.
- `mud.call_later(seconds, func, *args, **kwargs)`
Call a function later (Python scripts only).
Convenience names in full Python scripts:
- `log("...")` is available as a shortcut for `mud.log(...)`.
- Direction strings are available as `mud.n`, `mud.s`, `mud.e`, `mud.w`, etc.
Formatting / Expressions
------------------------
DSL supports Python-style blocks:
```
while True:
if npc.stamina < 20:
rest
else:
stand
```
DSL logging supports f-string style with braces:
```
log "rat {npc.vnum} in room {npc.room.vnum}"
```
In full Python scripts, use normal f-strings:
```
log(f"rat {event['self'].vnum} in room {event['self'].room.vnum}")
```
Variables (Full Python)
-----------------------
Use normal Python variables:
```
def on_trigger(event):
room = event["self"]
count = 0
while True:
count += 1
mud.echo_room(room, f"tick {count}")
mud.sleep(30)
```
The DSL currently does not support custom variable assignment. If you need
variables, use full Python with `def on_trigger(event):`.
Best Practices
--------------
- Keep scripts small and focused.
- Use `log(...)` during development and remove or reduce noise later.
- Avoid infinite tight loops without `sleep`.
- Use comments generously (`# ...`).
- Prefer readable direction strings: `"north"`, `"west"`, etc.
Sample: Room Echo Script
------------------------
See `sample_echo.py` in this directory for a ready-to-attach room script.