objects: snap to floor follows the engine's cell rule (cell tiles, swap models, then neighbours), alligator, alligator spawner and cow guard spawner schemas with box checks, every way of adding a box walker gives it a box, guard info names the objects that set its event bit, new and moved player starts carry their start camera node (no camera in the llama's head), edit and delete type in the object palettes' context menu
No files matched your search
@@ -63,7 +63,7 @@ values only.
|
||||
| RubyIdol | p0 falls, p1 snap | – |
|
||||
| Secret (high) | p0 box mode (player inside the box of the 2 nodes, op 0x178) | box (2 nodes) |
|
||||
| CoinLine / CoinCircle (low) | count (counted down), spacing / radius | – |
|
||||
| Llama | p0 spawns a helper, p1 unused, p2 camera mode (global 107) | first node = camera start |
|
||||
| Llama | p0 spawns a helper, p1 unused, p2 camera mode (global 107) | camera starts: first node within 2.5 cells of the llama (see "Start camera") |
|
||||
| CheckPointPost (high) | p0 collision radius (+0xD2, 0.2) | 1 node = respawn position + yaw (98 of 102) |
|
||||
| LevelDoor (high) | tribe, world, chapter of the next level (7,7,7 = world finished); fires on material-16 floor of a tile in its cell (any height; often only in the swap model a RubyIdolDoor/other door object switches to when it opens) | – |
|
||||
| CameraSide | p0 height (g48), p1 distance (g47), p2 yaw mode (1 node yaw, 2 node yaw or ±180°), p3 only below node y, p4 flag 0x10000, p10 several boxes, p11 height offset, p12/p13 alt. height/distance | box pairs, node 0 yaw = camera yaw |
|
||||
@@ -100,7 +100,53 @@ info for p2 > 0; the Inspector shows the state plus a **Box around it** button (
|
||||
`Setups.guardBox`). Verified in game: CityGuard with its box on a new level (base village 2)
|
||||
appears and attacks the llama; a second one with a 4-node "square path" next to it never appears.
|
||||
|
||||
The rest (~150 placed types) shows raw values with the original statistics. Next candidates:
|
||||
Alligator (also box pairs: "Forcing alligator inside first WP box"), PressurePadDoor (bit field), TargetRopePlatform, CataSwingingBlade (speeds/angles), RiverLog.
|
||||
### Other box walkers (2026-11-07, objs2)
|
||||
|
||||
Same pair scan, kind-specific rules (`Guards`, model list `editor.model.WaypointBoxes`):
|
||||
* **CowGuardSpawned** (spawned by CowGuardSpawner, same guard code): p0 view, p1 chase, p2 event
|
||||
bit (spawner passes 0), p3 not read (overwritten by the box scan). Box rule as guards (unk2 = 0).
|
||||
* **CowGuardSpawner** (6 params, t1l8m005 ×8): `spawn<4,…>(v0, v1, 0, v5, CowGuardSpawned)` at its
|
||||
own position with its chain, then `wait(v3·30)` until the player is > 1.5 cells away and fewer
|
||||
than v2 of its guards live (the guard does `parent.v6 −= 1` when it dies). So p0 = view range,
|
||||
p1 = chase range, p2 = max guards, p3 = interval (s), p4 not read, p5 = guard p3 (unused). The
|
||||
spawner must stand in a box with unk2 = 0 or each guard is removed at once – 1 of 8 originals
|
||||
(t1l8m005 strat 82) stands 0.12 outside (warning, not verified in game).
|
||||
* **Alligator** (no params; v0–v6 are locals), **SpawnedAlligator**: odd node count → "Odd number
|
||||
of WPs!" + remove; outside every box → "Forcing alligator inside first WP box", clamped into the
|
||||
first box. No unk2 rule. Bites only when `|player.floorHeight − y| < 0.2` and inside its boxes.
|
||||
* **AlligatorSpawner** (t1l6m003 ×2): p0 max alive (`v3 < v0`, `parent.v3 −= 1` on death), p1
|
||||
interval s, p2 → spawned `collisionOn 0x8400` when set. The spawned alligator (spawner's chain)
|
||||
walks straight ahead (`moveForwardQ`, spawner yaw) with a fade-in until it is inside the
|
||||
*first* box – both originals stand outside it, facing it. Check: warning if the ray misses.
|
||||
Placement (every path through `Edits.placeStrat`): one 4×4 box around the object, unk2 = 0, guards
|
||||
event bit 0. In game (TestLevel 6 on t1l4m002): an Alligator added this way appears and snaps at
|
||||
the llama (`img/editor/obj_game_alligator.jpg`).
|
||||
|
||||
### Event bits (global 95)
|
||||
|
||||
Setters found by a sweep over the strat code of all 31 levels (`g95 = g95 | (1 << (v − 1))`),
|
||||
v = parameter: TipoVillage p6, ChacaVillage p6, SmashStatueSmall/Big/Door p0, RiverCrocGame p1,
|
||||
RiverTriggerBox p0, KidOnCanoe p4, YzmaRiver p2 and p6, Condor p2 (also clears it), GoldIdol p1,
|
||||
CityWall p4, NakedPeacock p0, LabSlidingDoor p5, LabSlidingDoorJamie p5, LabBigCutscene p1, LabWall
|
||||
p4, EndGameTriggerBox p0 (`EventBits`). No native code touches global 95. Check: lab level
|
||||
t1l8m001 – LizardGuardNoCoin bit 8 ← LabBigCutscene p1 = 8, GorillaGuard bit 30 ← LabWall p4 = 30;
|
||||
CowGuard bit 20 and CowGuardNoCoin bit 1 have no setter in the level (they never appear in the
|
||||
original either). `ObjectChecks` adds this to the guard info, naming the setter types of the base.
|
||||
|
||||
### Start camera (Llama waypoints)
|
||||
|
||||
Camera strat (spawned by the Llama with `self.hasWaypoints`), case g0 = 4 at level start, L_1330:
|
||||
walks the Llama's chain; the first node with `playerDistToWp < 2.5` becomes the camera position,
|
||||
yaw = angle to the player; if the node's wpParam (unk2) ≠ 0, also g47 = x/z distance and g48 =
|
||||
height difference, and g43 = 3 blocks the approach to the normal distance until the llama moves.
|
||||
The defaults are g47 = 1.0, g48 = 0.5 (Camera params from the Llama spawn). Originals: one node per
|
||||
entry door (unk2 4096 on some), none within 2.5 of the village starts. The old editor setup (and
|
||||
levelbuild) copied the prototype chain onto the llama: village 2's node 2 has unk2 = 4096 → camera
|
||||
in the llama's head until it moves (seen in game). Fix: `PlayerStart` (one node 2 behind, unk2 0;
|
||||
moving keeps door nodes). Village fly-by: CutSceneTrigger on the start, radius² 0.5; p6 bit 1 makes
|
||||
it (L_0148) rewrite its last path node to a point behind the player – set when the start moves.
|
||||
|
||||
The rest (~145 placed types) shows raw values with the original statistics. Next candidates:
|
||||
PressurePadDoor (bit field), TargetRopePlatform, CataSwingingBlade (speeds/angles), RiverLog.
|
||||
Tooling used (not in the repo): Ghidra script decompiling the handler table, a Python sweep
|
||||
disassembler with an op-name table, "parameter use" context dumps per type.
|
||||
@@ -12,7 +12,7 @@ screenshot tour `ObjectsTour` (test classes).
|
||||
|---|---|
|
||||
| **Objects panel** (left dock) | every placeable type of the base with rendered thumbnail, category filter, search (name + schema summary), favourites (right-click, ★ filter), "parameters decoded" marker; drag into the viewport or click → Place tool. Quick setups: Player start, Checkpoint, Exit, Secret, Coin line, Coin arc |
|
||||
| **Place tool** (P) | click = place on the collision floor under the cursor (snap to floor, grid snap), yaw = camera direction / facing the camera / 0° / type default; click + drag an object = move along the ground (its waypoints move along); drag the yellow knob = rotate (angle snap; a checkpoint's respawn node turns with it). Modes for the setups |
|
||||
| Setups | **Player start** moves the existing player (exactly one) or places a Llama with its chain (camera node 8 cells behind). **Checkpoint** = CheckPointPost + respawn node 0.4 ahead (floor height). **Exit** = LevelDoor in the cell centre + 1×1 FLOOR brush with collision material 16; target picked in the options bar (world/chapter names, "world finished 7,7,7"). **Secret** = Secret with a 3×3 box (2 nodes). Guards (any placement) get one 4×4 box and event bit 0 |
|
||||
| Setups | **Player start** moves the existing player (exactly one) or places a Llama with one start camera node 2 cells behind (moving keeps door nodes, carries the near nodes and the village fly-by trigger). **Checkpoint** = CheckPointPost + respawn node 0.4 ahead (floor height). **Exit** = LevelDoor in the cell centre + 1×1 FLOOR brush with collision material 16; target picked in the options bar (world/chapter names, "world finished 7,7,7"). **Secret** = Secret with a 3×3 box (2 nodes). Guards, alligators and spawners get one 4×4 box (and guards event bit 0) on every way of adding an object (`Edits.placeStrat`: Place tool, drag from Objects panel / Assets, double-click) |
|
||||
| **Coin tool** (O) | Line: two clicks, coins every *spacing*; Arc: centre + point on the circle, *count* coins over *arc°*; Coin/Coin5, height above floor, follow floor; live preview |
|
||||
| **Waypoint tool** (N) | select an object (or node): click = add node after the selected node / at the chain end (creates the chain if missing), Ctrl+click = insert before, drag = move (keeps height above floor), Backspace/Del = remove and relink; Reverse; orient new nodes along the path |
|
||||
| **Zones & triggers** (J) | handles: 4 corners of box zones (node pairs: Secret, CameraSide/Lift, ObjectDontDropInBox, FallOffNoHurt …), radius knob for RADIUS parameters (CutSceneTrigger, guards, CameraFocusPoint) |
|
||||
@@ -20,7 +20,7 @@ screenshot tour `ObjectsTour` (test classes).
|
||||
| Inspector "Waypoint chain" | node i of n, owner and role, ◀ ▶, select object, delete node, look through |
|
||||
| Viewport layers | *Path directions* (arrows, dashed wrap segment for patrol paths, node yaw ticks), *Zone areas & trigger radii* (boxes for all zone objects, fills for the selection), *Camera frusta* (CameraSide/Lift: computed game camera from height/distance/node yaw; cut-scene cameras: a frustum per node from node yaw/pitch) |
|
||||
| Look through camera (Ctrl+Shift+L, View → Camera) | viewport takes the camera of the selected node / cut-scene camera / camera zone; while active, flying writes back node position + yaw/pitch, or for CameraSide the height/distance params and node yaw (one undo step per pilot session) |
|
||||
| Problems (Level → Check, Build) | guards the game would remove (no start box / odd node count) and guards waiting for an event bit, chains not stored contiguously (error, Tools → Repair waypoint chains), param count, out-of-range values, missing required waypoints / odd box pairs, types whose originals always have a chain, LevelDoor without material-16 floor in its cell, impossible exit targets and (7,7,7) in TestLevel, far respawn nodes, several player starts |
|
||||
| Problems (Level → Check, Build) | guards/alligators/spawners the game would remove (no start box / odd node count), alligators outside their boxes, spawners facing away from their first box, guards waiting for an event bit (and whether any object in the level sets it), a start camera inside the llama, chains not stored contiguously (error, Tools → Repair waypoint chains), param count, out-of-range values, missing required waypoints / odd box pairs, types whose originals always have a chain, LevelDoor without material-16 floor in its cell, impossible exit targets and (7,7,7) in TestLevel, far respawn nodes, several player starts |
|
||||
| Copy / paste between levels | Edit → Copy objects (Ctrl+Shift+C) puts JSON (objects + chains + brushes, relative to their centre) on the system clipboard; Paste objects (Ctrl+Shift+V) at the view centre in any level – types are matched by name/variant in the target base (unknown types skipped with a message) |
|
||||
| Prefabs | Tools → Save selection as prefab… / asset browser tab "Prefabs": `<data>/editor/prefabs/<name>.json` + thumbnail; double-click = place at view centre, drag = place under the cursor |
|
||||
| Delete | `edit.delete` is re-registered: a selection of waypoints is removed with the chain relinked |
|
||||
@@ -32,14 +32,17 @@ repair action guard it).
|
||||
## Files
|
||||
|
||||
`ObjectsEditorPlugin` (registration, actions, waypoint inspector), `Schemas`/`ParamSchema`/
|
||||
`TypeStats` (+ `type-stats.tsv`), `ParamsSection`, `ObjectChecks`, `PlaceTool`, `Setups`,
|
||||
`TypeStats` (+ `type-stats.tsv`), `ParamsSection`, `ObjectChecks`, `Guards`, `EventBits`, `PlaceTool`, `Setups`,
|
||||
`ExitTarget`, `CoinTool`, `PathTool`, `ChainOps`, `ZoneTool`, `ObjectOverlays`, `CameraView`
|
||||
(zone camera + pilot), `ObjectPalette`, `ObjectClipboard`, `Prefabs`, `LinkDialog`, `Ground`
|
||||
(floor finder on the collision polygons of tiles + brush preview tiles), `Session`, `Roles`, `Draw`
|
||||
(all game↔render conversions in one place).
|
||||
|
||||
Shared change: `editor.ui.view.SceneRenderer.brushOutput()` getter (brush preview tiles for the
|
||||
floor finder). Nothing else outside the package.
|
||||
Shared changes: `editor.ui.view.SceneRenderer.brushOutput()` getter (brush preview tiles for the
|
||||
floor finder); `editor.model.WaypointBoxes` + box setup in `Edits.placeStrat`;
|
||||
`editor.model.cmd.PlayerStart` (also used by the shell's new-level templates); `editor.ui.TypeMenus`
|
||||
(object type context menu, used by Assets → Objects and the Objects panel; the objects plugin adds
|
||||
Edit type… / Delete type… for custom types through `editor.tools.strats.CustomTypes`).
|
||||
|
||||
## Verified
|
||||
|
||||
@@ -65,6 +68,15 @@ JumpingBeetleBlue with a 4-node patrol path, CityGuard with two boxes):
|
||||
→ tally "Dorf Kapitel 1" at once (`obj_game_village_door.jpg`); at the door's own position
|
||||
42.5/3.5/49.8 or in the original (door closed) → nothing.
|
||||
|
||||
* (2026-11-07, objs2, display :25, TestLevel on village 2 / village 1 / t1l4m002): old player
|
||||
setup on village 2 = camera in the llama's head until it moves, new setup = camera behind it
|
||||
from the start (`obj_game_startcam_v2.jpg`); a CityGuard added through the Add-object path
|
||||
walks in its box; an Alligator added the same way appears and snaps (`obj_game_alligator.jpg`);
|
||||
original village 1 with the start moved and turned (240°): the fly-by plays at the new start and
|
||||
ends behind the llama (`obj_game_village1_moved_start.jpg`). Editor: type menu in Assets →
|
||||
Objects / Objects panel (`obj_type_menu.jpg`, `obj_palette_type_menu.jpg`), event-bit info
|
||||
(`obj_event_bit_info.jpg`, `obj_guard_event_inspector.jpg`).
|
||||
|
||||
## Known limits
|
||||
|
||||
* Parameters are decoded for ~35 common types (confidence per type in the schema doc); the rest
|
||||
@@ -77,8 +89,10 @@ JumpingBeetleBlue with a 4-node patrol path, CityGuard with two boxes):
|
||||
loader exactly (`Tile.cellX/cellZ` = ftol(x − 0.5), −ftol(z + 0.5)); `ObjectChecks` tests the
|
||||
door cell like the engine (tiles listed in the cell, any height, swap models), same as
|
||||
`GeometryChecks`. Tests: `GuardsTest`, `OriginalExitsTest`, `OriginalStartsTest`.
|
||||
* Snap-to-floor (`Ground`) is geometric: it finds polygons that reach into a cell from a
|
||||
neighbouring tile, which the engine ignores (`FloorFinder` follows the engine for the player).
|
||||
* Snap-to-floor (`Ground`) follows the engine's floor test (FUN_004036d0, used for strats too):
|
||||
only tiles listed in the point's cell; then their swap models; a neighbour tile's polygon only
|
||||
where the cell has no floor at all (`Hit.source`). `GroundTest` compares it with `FloorFinder`
|
||||
on three originals. The Place tool drag moves only a player start's nodes within 2.5 cells.
|
||||
* Zone heights are estimated (+1.2 above the lower node); the engine tests x/z only.
|
||||
* Camera preview of CameraSide assumes the player in the box centre and default distance 2 /
|
||||
height 1 when the parameters are 0; the game's FOV is approximated by 60°.
|
||||
|
||||
@@ -158,7 +158,7 @@ public; invisible tile instances are no longer baked into chunks; `History.undoL
|
||||
|
||||
* **New level**: dialog (name, author, base level by name with its loading picture, TestLevel
|
||||
chapter = next free one, template Empty / Flat floor / Island). Templates add brushes, a Llama
|
||||
(camera node 8 cells behind, as levelbuild) and a LevelDoor on a material-16 floor.
|
||||
(one start camera node 2 cells behind, `PlayerStart`) and a LevelDoor on a material-16 floor.
|
||||
* **Open original level**: list "Village – Chapter 1" … "Lab – Chapter 5" (+ unused/front-end WADs)
|
||||
with the CD loading pictures (`OriginalLevels`, `Cor`).
|
||||
* **Save** (`.llamalevel`, default folder `<data>/levels` = listed as mods in LlamaMod), Save as, Open
|
||||
|
||||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 34 KiB |