67 lines
4.6 KiB
Markdown
67 lines
4.6 KiB
Markdown
# Level projects as mods (`mods.levels`, category LEVELS)
|
||
|
||
Every `.llamalevel` file (format: `notes/editor-format.md`) in `<data>/levels/` is a mod.
|
||
Code: `mods/levels/LevelProjectSource` (a `ModSource`), `LevelProjectMod`, `LevelProjects`
|
||
(folder, `importFile` for an "Import level…" button), `LoadingPicture`, `EditorCli`.
|
||
|
||
| | |
|
||
|---|---|
|
||
| id | `level-<file name>` (lower case, non-alphanumerics → `-`); names that collide (`My-level` / `my-level`) get `-2`, `-3`… (first in name order keeps the plain id, a suffix never takes an id another file has) |
|
||
| name / description | level name, description and author from the project |
|
||
| version | first 16 hex digits of the file's SHA-256 (any change of the file rebuilds) |
|
||
| order | 60: after Test World (50, chapter 1), before Mirror (75) and the debug view (100), so those also apply to the level |
|
||
| option `chapter` (new levels only) | TestLevel (world 9) chapter 1..49; default = the project's `targetChapter`, or the next free one (from 2) if another project already uses it |
|
||
|
||
Apply: the project is loaded against the **pristine** CD (`ctx.originalCd()`), built with
|
||
`editor.io.WadBuilder` and written to `wads/T1L9M0nn.wad` (new levels) or `wads/<base>.wad`
|
||
(edited originals). New levels also get a loading picture `T19<n>.COR` (thumbnail if present,
|
||
level name, "TestLevel – chapter n"). If the target was already changed by an earlier mod (Test
|
||
World on chapter 1, another level on the same chapter, two edits of one original level), the apply
|
||
stops with a clear message naming the file and what to do.
|
||
|
||
World 9: `ModManager.world9Fixup` now also works when only a chapter other than 1 is provided:
|
||
the lowest provided chapter fills all missing chapters 1..49 (the map crashes on a missing
|
||
chapter WAD), loading pictures as before. To play chapter n: unlock it in the save editor (or
|
||
`--unlock <slot> 9 <n> --cursor`), then select it on the world-9 map.
|
||
|
||
**Temporary play-test copies**: `levels/.playtest/*.llamalevel` are listed too, as
|
||
`playtest-<stem>` (`LevelProjectMod.playtest()`, name "… (play-test)", chapter = the project's
|
||
own, not counted for other levels' defaults). The editor deletes them after the play-test
|
||
(`LevelProjects.clearPlaytest`), see editor-playtest.md. Files from older play-tests in `levels/`
|
||
cannot be told apart from saved levels and are left alone (users remove them).
|
||
|
||
**Removing** (`LevelProjects.remove`, launcher card "Remove…", CLI `--remove-level <id|file>`):
|
||
moves the file to `<data>/backups/levels/<yyyyMMdd-HHmmss>/`, takes the id out of `enabledMods`
|
||
(`activeMods` stays → the launcher shows "Apply" pending), refused while the game runs and for
|
||
play-test copies. The Levels header has "Open levels folder". Screenshots:
|
||
`img/mods/levels_remove_dialog.jpg`, `levels_removed.jpg`.
|
||
|
||
CLI (`EditorCli`): `--editor-import`, `--editor-new`, `--editor-build`, `--import-level`, see
|
||
editor-format.md. The registry reads the folder when it is created (restart the app / create a
|
||
new `ModRegistry` after importing).
|
||
|
||
## Verified in game (apptest, display :7, Wine 6, 2026-11-06)
|
||
|
||
* **Original imported → project → built** (`--editor-import t1l1m001`, mod `level-village`): the
|
||
WAD in cd-active is byte-identical to the CD file; Village 1 loads and plays (intro, Pacha).
|
||
* **Edited original** (`level-village-edited`: three coins moved, coins, charge boosters and three
|
||
CheckPointPosts added): loads and plays; the added post stands where placed (3 cells ahead of
|
||
the start, `img/mods/levels_01_village_edit.jpg`), the moved coins appear at their new places,
|
||
added coins are collected (coin HUD). Note: in Village 1 the coins and other objects within ~3
|
||
cells of the start are not visible at the start (also in the original), so edits there are
|
||
hard to see.
|
||
* **New level from brushes** (`examples/testwelt.llamalevel` → `level-testwelt`, chapter 2):
|
||
loads from the world-9 map (slot shows "TestLevel Kapitel 2"), generated loading picture, plaza,
|
||
gallery objects, walking (`img/mods/levels_02_testwelt_chapter2.jpg`). Its geometry, objects,
|
||
waypoints and textures equal the Test World mod's WAD (unit test; only the generated death plane
|
||
model differs).
|
||
* **Mesh and texture import** (testwelt + an OBJ box with a PNG texture via MTL, a block with an
|
||
imported PNG texture, chapter 3): both render with their textures, the mesh has collision
|
||
(`img/mods/levels_03_mesh_import.jpg`).
|
||
|
||
## Known limits
|
||
|
||
* Exit doors (LevelDoor) keep their parameters; the test world's door leads to (1,9,1) = chapter 1
|
||
(which then is a copy of the lowest provided chapter if no other mod provides it).
|
||
* New ModRegistry instances are needed to see newly imported projects.
|