115 lines
4.9 KiB
Markdown
115 lines
4.9 KiB
Markdown
# 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](../manual/22-strats.md).
|
||
|
||

|
||
|
||
Code: [`StratListing`](../../src/main/java/com/eliasmueller/llamamod/format/strat/StratListing.java)
|
||
(assembly), [`StratPseudo`](../../src/main/java/com/eliasmueller/llamamod/format/strat/StratPseudo.java)
|
||
(script view), [`OpTable`](../../src/main/java/com/eliasmueller/llamamod/format/strat/OpTable.java)
|
||
(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](custom-types.md)).
|
||
|
||
## 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](../../notes/strat-language.md). Every opcode with its stack
|
||
effect and meaning: [notes/strat-opcodes.md](../../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.py`](../../tools/strats.py) `level.wad --all` lists every
|
||
named strat of a level with code offsets and type fields;
|
||
[notes/strat_types_table.md](../../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 |
|