Files
llamamod/docs/reference/objects.md
T

142 lines
7.8 KiB
Markdown
Raw 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.
# Objects, waypoints, zones and lights
Everything that is not static geometry lives in the second half of the MAP chunk: object
instances ("strats"), their parameters, waypoint chains and environment zones. Lights are in their
own chunk, LGHT. Full byte layouts: [notes/objects.md](../../notes/objects.md).
## Strats: objects are programs
An object – coin, enemy, door, camera, the player – is an instance of a **strat**: a script in the
level's STPC code. A MAP record says *where* and *which code*; the code does the rest. There is no
type id: **the type is the code's byte offset in STPC**. Type names come from the code itself
(a `debugName "Coin"` instruction at the entry point). How the code works: [Strats](../strats/README.md).
About 300 types are placed in the original levels, about 200 more are only spawned by other
strats (splinters, effects, heads). The full list of which type appears in which level, with
instance counts, is [notes/strat_types_table.md](../../notes/strat_types_table.md)
(`tools/strat_table.py`).
## The MAP object blocks
After the geometry blocks ([Geometry](geometry.md#map-the-tile-grid-certain)):
| Block | Format |
|---|---|
| parameter pool | `u32 n, n × u32` – all object parameters of the level, referenced by index |
| environment zones | `u32 n, n × 90 bytes` (below) |
| waypoints | `u32 n, n × 34 bytes {u32 next, u32, u16 rx, ry, rz, s32 x, y, z, u32, u32}`; `next ≠ 0` = the following entry belongs to the same chain |
| strats | `u32 nStrats, u32 poolExtra`, nStrats × 58-byte records |
| optional tail | paths (WFPC 0x200000, unused by the CD levels), a buffer size (WFPC 0x10), a u16 |
### Strat record (58 bytes, *certain* unless noted)
| Offset | Field |
|---|---|
| 0 | rotation x, y, z (u16 each, 4096 = 360°; x/z almost always 0) |
| 6 | position x, y, z (s32, 20.12 fixed point, game space) |
| 18 | **code offset in STPC = the type** |
| 22 / 26 | parameter count / index into the parameter pool (−1 if none) |
| 30 | number of strat variables (fixed per type) |
| 34 | 16-byte slots for event handlers (fixed per type, *likely*) |
| 38 | type flags: collision and physics setup (fixed per type) |
| 42 | extra memory words (collision bones; fixed per type) |
| 46 | first waypoint index or −1 |
| 54 | flags; bit 1 = not created at level start |
`poolExtra` is the number of strat slots beyond 30: the engine allocates `poolExtra + 30` slots,
which must cover all placed objects **plus everything spawned at run time**.
The type fields (variables, slots, flags, extra) come from the compiler and must be copied from an
original instance of the same type; a type that uses collision but has type flags 0 crashes the
game. Builders and the editor do this automatically.
### Parameters
The *n* parameters of an instance are pushed onto the new strat's stack and become its
**variables v0 … v(n−1)**. Values are 20.12 fixed point by convention (0x1000 = 1.0), booleans
0 / 0x1000, counts and world/chapter numbers `n << 12`. The editor knows the meaning of the
parameters of many types (schemas in
[`editor/tools/objects/Schemas.java`](../../src/main/java/com/eliasmueller/llamamod/editor/tools/objects/Schemas.java),
findings in [notes/editor-object-schemas.md](../../notes/editor-object-schemas.md)); the others are
shown raw with the values used in the original levels.
### Waypoints
A waypoint chain is a list of positions used for patrol paths, moving platforms, camera paths –
and for some types (guards, box walkers) as a **pair of boxes** the object must stand in, or the
game removes it ("removing strat"). Guards also wait for an **event bit** (global variable 95) that
another object sets ([notes/editor-object-schemas.md](../../notes/editor-object-schemas.md#event-bits-global-95)).
The **player's waypoint chain is the start camera**: the camera takes the first node within 2.5
cells of the llama. A good start has one node about 2 cells behind the llama and 0.5 above it, and
nothing solid right behind the llama (the camera moves aside).
## Special objects
| Role | Type | Notes |
|---|---|---|
| player start | `Llama` | exactly one per level (`RollerCoaster`, `KuscoAndPachaTogetherOnATree`, `LlamaChase` in special levels) |
| checkpoint | `CheckPointPost` (spawns `CheckPointHead`), `CheckPointBox` | the respawn point after a fall |
| exit | `LevelDoor` | invisible trigger, see below; variants `VillageEndDoor`, `EndGameDoor` |
| cameras | `CameraSide`, `CutSceneCameraDirectional`, `CutSceneTrigger` | camera zones and cut scenes |
| always present | `CheatTeleport`, `Wompy`, `CutSceneTrigger` | |
### The exit (LevelDoor) – *certain*
The LevelDoor has no model. Every frame it checks:
```
game state is "running"
and the floor polygon under the llama has collision material 16
and floor(llama.x) == floor(door.x) and floor(llama.z) == floor(door.z) ; same grid cell
-> endLevel(tribe, world, chapter) ; its three parameters
```
So an exit needs **a floor with collision material 16 in the door's grid cell** – height does not
matter. In several original levels the pad only appears when a tile swap opens the door (Village 1:
the RubyIdolDoor swaps the tile to a model that has the material-16 pad). The parameters are the
next level; the originals use (1, world, chapter + 1), and **(7, 7, 7)** in the last chapter of a
world means "world finished" – in TestLevel that crashes, so custom levels use (1, 9, chapter).
`endLevel` shows the tally (coins x / LNFO total, secrets) and unlocks the next chapter.
A second path in the Llama's own code ends the level when it stands on material 16 in the cell
stored in globals g104/g105 with the target in g101–g103 – the arena uses this
([Arena](../strats/arena.md)).
## Environment zones (90 bytes, *certain* for the fields below)
A zone sets fog, colours, music and sky, and optionally teleports the player.
| Field | Meaning |
|---|---|
| cell x, y, z | the trigger cell |
| target x, y, z, angle | teleport target and facing |
| flags (+0x20) | flag 8 = **start zone** (exactly one per level: the level begins with its settings); flag 4 = do not move the player |
| sky model | STPC offset of a sky model (0 = none) |
| fog mode | 0 none, 1 darkness with a light around the player, 2 table fog, 3 vertex fog |
| fog start / end | two pairs (detail Minimum and Maximum); **fog end = far clip = draw distance** |
| colours | ambient colour for object lighting, fog/backdrop colour |
| music id | 1–39 (see [Music](audio.md#music)), 0 stops the music |
Teleports are triggered from strat code (opcode 0x100 looks up the zone of the calling object's
cell). In the original levels the trigger cells hold exit floors (material 16) or door objects –
this is how the village house doors work. The editor edits zones in the
*Environment* panel ([manual chapter 12](../manual/12-environment.md)).
## Lights
LGHT: `u32 n`, then per light a type, a colour (×2/255) and direction or position (game space).
Lights only light **object models** (ambient + all directional lights + the nearest point lights,
at most 6). Tiles use baked vertex colours, so changing a light does not change the ground – bake
the vertex colours again. Point lights are full up to radius *a* and fade to 0 at *b*; one byte
makes them flicker.
## Tools
| Task | Tool |
|---|---|
| list types, instances, parameters of a level | [`tools/strats.py`](../../tools/strats.py) `level.wad [--all]`, [`tools/map_dump.py`](../../tools/map_dump.py) `--strats --tiles --lights` |
| type × level table | [`tools/strat_table.py`](../../tools/strat_table.py) |
| place objects from a script | [`tools/levelbuild.py`](../../tools/levelbuild.py) `L.strat(...)`, Java [`LevelBuilder`](../../src/main/java/com/eliasmueller/llamamod/levelbuild/LevelBuilder.java) |
| place, edit, check objects visually | the level editor ([manual chapter 9](../manual/09-objects.md), [10](../manual/10-waypoints.md), [11](../manual/11-cameras-triggers.md)) |