142 lines
7.8 KiB
Markdown
142 lines
7.8 KiB
Markdown
# 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)) |
|