Files
llamamod/docs/strats/script-language.md

88 lines
4.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# The script language
LlamaMod's **script language** (version 2) is a small structured language in the style of the
Script view. [`StratCompiler`](../../src/main/java/com/eliasmueller/llamamod/format/strat/StratCompiler.java)
compiles it to strat assembly, and
[`StratAssembler`](../../src/main/java/com/eliasmueller/llamamod/format/strat/StratAssembler.java)
turns that into bytecode with the same checks as hand-written assembly. It is used by the editor's
type editor (*Language: Script*) and by mods such as the [arena](arena.md). Complete reference:
[notes/strat-language.md](../../notes/strat-language.md#script-language-stratcompiler--writing-new-behaviour);
tests: `StratCompilerTest`.
## A first strat
```
// bobs one cell up and down and turns
strat Bobber {
alias base = v0
alias phase = v1
setModel(model:5) // any opcode: name<inline operands>(stack arguments)
base = self.y + 1 // 1 = one cell
phase = 0
on touched { // event handler (type 4), runs as a subroutine
soundPlay(sound:6)
}
loop {
phase = phase + 4deg
self.y = base + sin(phase)
turnLeft(4deg)
yield // end of this frame
}
}
sub wobble { // called with "call wobble", ends with return
self.rotZ = sin(self.rotY) * 0.1
}
```
## Building blocks
| Construct | Notes |
|---|---|
| `strat Name { … }` | a type; its label `Name` is the entry point |
| `sub name { … }`, `call name`, `return` | subroutines |
| `alias name = v3` | a name for a variable; parameter names from the object schema are predefined |
| `x = e`, `x += e`, `-=`, `*=`, `/=` | assignment; `x += 1` compiles to `inc` |
| places | `vN`, alias, `gN`, `self.prop`, `player.prop`, `parent.prop`, `parent.vN`, `camera.` / `target.` / `boss.` / `dialog.prop` |
| `if (c) { } else if (c) { } else { }` | |
| `while (c) { }`, `loop { }`, `do { } while (c)` | a `yield` as the last statement of a loop becomes the loop's frame-ending back jump |
| `switch (e) { case 1: … break default: … }` | C rules (fall through without `break`); case values are constants |
| `break`, `continue`, `yield`, `end`, `remove` | |
| `on touched { … }`, `on event(type[, param]) [slot n] { … }` | event handlers; touched needs `collisionOn<…>()` and `collRadius(…)` |
| `op<a, b>(e1, e2)` | **any opcode** by name: inline operands in `<>` (raw words), stack arguments in `()`; the count must match the opcode |
### Numbers
* `10` and `10.0` are ten cells (fixed point); `1.5`, `90deg` as in assembly.
* **Raw** integers: `215r` (= 215/4096) or hex `0x10`. Values inside `<…>` are always raw.
* Operators over constants are folded at compile time with the VM's own fixed-point rules:
`2 * 3 + 0.5` → `6.5`.
* `use rawNumbers` switches to the version-1 rule (plain integers raw) – old scripts get it
automatically.
### Operators (low → high precedence)
`||` · `&&` · `|` · `&` · `==` `!=` · `<` `>` `<=` `>=` · `<<` `>>` · `+` `-` · `*` `/` · unary
`-` `!`. In conditions `&&` / `||` short-circuit; in a value both sides are evaluated.
### References
`model:N`, `anim:N`, `unit:N[+off]` or `unit:Name` (another custom type), `sound:N`, `tex:N` –
indices into the level the code is compiled against.
## What the compiler does not do (yet)
* no `for` loop, no typed variables (everything is a 32-bit word, fixed point by convention);
* `spawn` takes raw type fields (`spawn<0, 16, 5, 0xC400, 3>(unit:…)`) – you must know the
values the spawned type needs;
* the Script view does not show event handlers as `on … { }` blocks.
## Tips
* Look at an original type that does something similar first (Script panel) and copy its numbers
– speeds, animation indices, sounds and type fields are level-specific.
* Keep each frame's work small and always reach a `yield` in loops; a loop without a yield freezes
the game.
* Test in the game early: the compiler checks the code's form and references, not whether the
object behaves well.