exit logic corrected from in-game debugging: the leveldoor only sets g101-g105, the llama's script ends the level (material 16, exit cell, near the floor); stale floor record after a position jump explains the hover exit skip in jungle day 2
This commit is contained in:
1 parent
64259ea15b
commit
0568ae7f24
3 files changed
+82
-15
No files matched your search
+37
-15
@@ -81,27 +81,49 @@ nothing solid right behind the llama (the camera moves aside).
|
||||
| cameras | `CameraSide`, `CutSceneCameraDirectional`, `CutSceneTrigger` | camera zones and cut scenes |
|
||||
| always present | `CheatTeleport`, `Wompy`, `CutSceneTrigger` | |
|
||||
|
||||
### The exit (LevelDoor) – *certain*
|
||||
### The exit (LevelDoor)
|
||||
|
||||
The LevelDoor has no model. Every frame it checks:
|
||||
An exit is **two parts working together** (decompiled strat code; the details below were checked
|
||||
in game in Jungle Day 2 with a debugger, the basic rule also in Village 1):
|
||||
|
||||
* The **LevelDoor** object (no model) writes its three parameters – the next level (tribe, world,
|
||||
chapter) – to globals g101–g103 and its grid cell to g104/g105. It does **not** end the level
|
||||
itself in the cases we tested (see the details below).
|
||||
* **Kuzco's own script** ends the level when **all** of these hold:
|
||||
|
||||
```
|
||||
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
|
||||
floor material under Kuzco == 16 ; the remembered floor (see "floor test" below)
|
||||
and floor(x), floor(z) == the cell in g104/g105 ; the exit's grid cell, any height
|
||||
and Kuzco is at most ~0.6 above that floor's height
|
||||
-> level change to g101..g103 (tally screen)
|
||||
```
|
||||
|
||||
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.
|
||||
On a material-16 floor **outside** the exit cell the same check is a house door: fade-out and
|
||||
the teleport of the environment zone of that cell.
|
||||
|
||||
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)).
|
||||
So a normal exit needs **a floor with collision material 16 in the exit's grid cell**. In several
|
||||
original levels that floor only exists after a tile swap opens the door (Village 1 and Jungle Day 2:
|
||||
the RubyIdolDoor swaps the tile to a model that has the material-16 pad; checked in game in Village
|
||||
1). The parameters of the originals are (1, world, chapter + 1); **(7, 7, 7)** in the last chapter of
|
||||
a world means "world finished" – in TestLevel that crashes, so custom levels use (1, 9, chapter).
|
||||
The tally shows coins x / LNFO total and secrets and unlocks the next chapter. The arena sets
|
||||
g101–g105 itself to make its own exit ([Arena](../strats/arena.md)).
|
||||
|
||||
**Details checked in game (Jungle Day 2, t1l4m002, 2026-11-07):**
|
||||
|
||||
* The LevelDoor stores its parameters and cell in g101–g105, then checks global 0x21 **once**
|
||||
(after 5 ticks); if it is not 3 the door removes itself. In Jungle Day 2 it was gone after the
|
||||
start, so the Llama's check is what ends the level. That check needs floor material 16, the
|
||||
door's cell, and the llama no more than 0.6 above the recorded floor height. Off the exit cell
|
||||
the same material-16 check is the house door (fade-out and zone teleport).
|
||||
* The floor test only looks at tiles in the player's cell and takes the **nearest upward floor
|
||||
below the player, at any distance**. Material 17 is ignored for the llama. A llama hovering 3.7
|
||||
units above a house-door pad records material 16.
|
||||
* Each tick runs all strat scripts first and then the floor tests. A position change made after
|
||||
the floor tests is seen by the next tick's scripts with the **old** floor record. So hovering
|
||||
above any house-door pad and then moving the llama straight to floor height in the exit cell
|
||||
ends the level, even though the exit cell has no material 16 yet (it appears only in the swap
|
||||
model when the RubyIdolDoor opens). Moving there from normal ground does nothing.
|
||||
|
||||
## Environment zones (90 bytes, *certain* for the fields below)
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 157 KiB |
@@ -173,6 +173,11 @@ stairs, platforms register as shadow casters (`solids`). 1.0 = texture colour
|
||||
|
||||
## Exit (LevelDoor) – how it works
|
||||
|
||||
> **Corrected 2026-11-07 (in game, Jungle Day 2):** the listing below was the first reading. The
|
||||
> LevelDoor only sets g101–g105 and checks global 0x21 *once*; the level is ended by the **Llama's
|
||||
> script** (material 16 + exit cell + at most ~0.6 above the floor). See "Exit via stale floor
|
||||
> material" further down and docs/reference/objects.md.
|
||||
|
||||
Strat bytecode (village, STPC 0x430332, 3 parameters, invisible, no model), decoded via the
|
||||
VM `FUN_0054d180` (opcode < 0x45: table 0x5796bc with 16-bit operand, otherwise 0x578ff4+op·4):
|
||||
```
|
||||
@@ -199,6 +204,46 @@ loop: if g21 == 3 ; game state "running"
|
||||
(zone teleport). t1l3m003: 2 of the 4 doors (cells 71,48/71,49) have no pad at all.
|
||||
* Second path (strat code at 0x4252aa, player logic [likely]): floor material 16 and cell =
|
||||
g104/g105 (set by the LevelDoor at start, Llama sets them to −1) → level change(g101..g103).
|
||||
|
||||
### Exit via stale floor material (hover + position jump, t1l4m002) – checked 2026-11-07
|
||||
|
||||
Speedrun video (position/hover hack): Kuzco hovers above a house-door stump, is moved to the exit and
|
||||
the level ends. Reproduced in game (apptest, gdb through `winedbg --gdb`, position written by gdb):
|
||||
* **Jungle Day chapter 2 = t1l4m002** (LNFO 95 coins / 2 secrets; tally "Dschungeltag Kapitel 2,
|
||||
0/95, 0/2"). LevelDoor at 44.5/25.5 (cell 44,25), params (1,4,3); RubyIdolDoor in the same
|
||||
cell. Cell 44,25 (tile 255) has material 16 **only in swap model 95** (pad x 44.67–45.0,
|
||||
z 25.25–25.75, y 2.25); main model 94 has none → with the door closed the exit cannot fire.
|
||||
House-door pads (material 16, main models) in cells 38,20 / 51,0 / 52,5 / 41,24 / 44,27 /
|
||||
50,27 / 41,29 / 57,55 / 41,38 / 41,44 plus swap pads in 22,21 / 26,21 / 23,23 / 50,1 / 43,21 /
|
||||
46,30 / 58,49 / 31,50; the zones pair them (e.g. 44,27 → 50.5/27.5, 50,27 → 44.5/27.5).
|
||||
* **Floor test (FUN_004036d0):** only tiles of the player's own cell; per upward polygon the plane
|
||||
height at (x,z) is compared with a probe point (y + 0.25, or y + (floor record +0x18)/2 with
|
||||
+0xe8 flag 0x200000 as for the llama);
|
||||
the **nearest floor below the probe wins, with no distance limit**. Material 17 is skipped for
|
||||
the llama (+0xe8 = 0x24882a, no 0x8000000). If nothing is below: for the llama (+0xe8 & 0x40000)
|
||||
material/height are **not** updated (stale) and x/z go back to the previous position.
|
||||
In game: llama held at 44.9/**6.0**/27.5 (3.7 above the pad of the stump at 44,27) → floor
|
||||
record h 2.30, **material 16**, tile 282 poly 15, every frame.
|
||||
* **Order per tick (FUN_0054c4a0):** all strat scripts (VM FUN_0054d180) first, then the
|
||||
collision pass (FUN_00403020 for every strat with +0xe8 & 0x8000). A position written after the
|
||||
collision pass is seen by the scripts of the next tick with the **old floor record**.
|
||||
In game: after hovering above the 44,27 pad, llama set to 44.5/2.3/25.5 right after its floor
|
||||
test → next event endLevel `FUN_0054d620` (called from the VM, floor record still 16), before
|
||||
any new floor test → tally (twice with screenshot, once traced). Control: same jump from normal
|
||||
ground (material 0) → no exit; jump written just *before* the floor test → record becomes 0, no exit.
|
||||
* **Who ends the level here: the Llama, not the LevelDoor.** LevelDoor bytecode: wait 5 ticks,
|
||||
g101..g105 = params + cell, then **once** `if global 0x21 != 3 → end` (so "g21 == 3" above is a
|
||||
one-time check, and global 0x21 is not the game state 0x5846e4), then the per-tick loop. In
|
||||
t1l4m002 the LevelDoor was gone from the strat list (scan of 0x6d9e38) while g101..g105 =
|
||||
1,4,3,44,25 and global 0x21 = 0. The Llama block at STPC 0x39ff4c–0x3a0064: if floorMaterial
|
||||
== 16 and health > 0 and (y < floorHeight + 0.6 and global 0x21 != 2, or y < floorHeight + 0.025
|
||||
and (g1 == 0 or global 0x23)): cell == (g104, g105) → level change(g101..g103), else fade-out +
|
||||
`getDoorPos` (op 0x100, zone teleport = house door) + `forceCollision`. The 0.6 limit is why
|
||||
hovering high above a house pad does not trigger the house teleport (bytecode; not separately
|
||||
tested), while landing at floor height in the exit cell with the stale record does.
|
||||
* Not explained: in two sessions with a moved player start (boot-to-level `start` 43.3/25.5) the
|
||||
same jump did not end the level (Llama script ran with record 16 in cell 44,25, no endLevel).
|
||||
* Images: `img/debug/exit-hover-trick.jpg` (top: video; bottom: our pool/door platform, tally).
|
||||
* Parameters in the originals: (1, world, chapter+1) = next chapter; in the last chapter of a
|
||||
world **(7,7,7)** = "world completed" → back to the selection map, unlock the next world.
|
||||
* `FUN_0054d620`: remembers the current level (0x585008..14), sets the next (0x584eb4/b8/bc), shows the
|
||||
|
||||
Reference in new issue
Block a user