4.9 KiB
Reading scripts
LlamaMod shows every strat in two forms: the Script view, a readable reconstruction, and the Assembly listing, the exact instructions. Both are in the level editor's Script panel (View → Panels → Script, Ctrl+Shift+K); the user-level walkthrough is manual chapter 22.
Code: StratListing
(assembly), StratPseudo
(script view), OpTable
(names and help texts).
Example: the Coin
Script view of the village coin:
strat Coin:
setModel(model:5)
collRadius(409r)
onEvent ev_0000, 0 // event type 4 → L_0084
if (v1) { collisionOn<32768>() ... }
if (v0) {
if (self.floorMaterial == -1.0) { skipArgs … } else {
self.y = self.floorHeight + 204r
self.rotY = rnd(4096.0)
}
}
loop { turnLeft(5.625deg); yield }
Line by line:
| Line | Meaning |
|---|---|
setModel(model:5) |
show model 5 of this level's STPC (the coin) |
collRadius(409r) |
collision radius 409/4096 ≈ 0.1 cell |
onEvent ev_0000, 0 |
install the handler table entry ev_0000 in slot 0: event type 4 (touched) jumps to L_0084, the pick-up code |
if (v1) … |
parameter 1 switches collision on |
if (v0) … |
parameter 0 (snapToFloor in the editor) puts the coin 204/4096 ≈ 0.05 above the floor under it and turns it randomly – unless there is no floor (floorMaterial == -1) |
loop { turnLeft(5.625deg); yield } |
spin 5.625° per frame, forever |
Changing 204r to 1.5 makes every snapping coin float 1.5 cells high – that is a constant edit
(Customising strats).
Script view conventions
| You see | It means |
|---|---|
self.x, player.y, parent.v3 |
property or variable of this strat, the player, the spawner |
v0, snapToFloor |
variable 0; named when the editor knows the type's parameter |
g12 |
global variable 12 |
1.0, 5.625deg, 204r |
fixed point (1.0 = one cell), an angle, a raw integer (204/4096) |
op<a, b>(x, y) |
instruction op with inline operands a, b and stack arguments x, y |
loop { … yield } |
runs once per frame |
while, do … while, switch, break, continue, break name |
rebuilt from the jumps |
a && b, a || b |
short-circuit conditions (chains of conditional jumps) |
goto L_xxxx |
jumps that do not form nested blocks – 31 places in the whole game, all one pattern in the llama's script |
The script view is a reading aid and is not compiled back. Edits happen on the assembly (or in the script language for new types).
The assembly listing
One instruction per line, exactly as stored:
Coin:
debugName "Coin"
address model:5 ; model
setModel
onEvent ev_0000, 0 ; event type 4 → L_0084
pushVar snapToFloor ; v0 (alias from the object schema)
jz L_018c
...
L_0218:
push 5.625deg ; = 64.0
turnLeft
jmpYield L_0218
end
- Short opcodes (below 0x45) carry a signed 16-bit operand:
pushVar v3,pushShort 1.5,jz label. Long opcodes take inline words:spawn 3, 6, 0, 0, 0. - Directives:
.unit,.alias,.word,.string,.event,.switch/.case,.at. - Disassemble → assemble is byte-identical for all 1461 units of the game; no instruction is emitted as raw words.
Full syntax: notes/strat-language.md. Every opcode with its stack effect and meaning: notes/strat-opcodes.md.
Finding things
- Which script runs this object? Select it with Follow selection on.
- Who spawns this type? The side panel lists the units that reference it.
- What does this instruction do? Select the line; the side panel shows the opcode's semantics, stack effect, Argonaut name and confidence.
- Where is this variable used? Uses lists every line with the selected operand.
- Outside the editor:
tools/strats.pylevel.wad --alllists every named strat of a level with code offsets and type fields; notes/strat_types_table.md shows which level has which type.
Typical patterns
| Pattern | Meaning |
|---|---|
v1 * 30 |
seconds → frames |
self.distToPlayerSqXZ < 25 |
player within 5 cells (squared distance) |
turnTowardAngleY(self.angleToPlayer, 2deg) |
turn towards the player, 2° per frame |
if (!self.animPlaying) animPlay(anim:N) |
loop an animation |
wpFirst(), wpNext(), self.wpParam |
walk the waypoint chain; per-node parameter |
g95 = g95 | (1 << (v - 1)) |
set an event bit that guards wait for |
