initial commit: llamamod 0.2.0 – reverse-engineered level formats (wad, map, trak, text, stpc), python tools and notes, java mod manager (iso install, mod pipeline with exe patching, save editor, wine/windows launcher) with mods (test world, debug wireframe, mirror, randomizer, fog, cheats, intro skip, practice, free camera, boot to level, level projects) and the 3d level editor (geometry, objects, cross-world import, environment, textures, play-test, manual)

This commit is contained in:
MineTec committed 2026-11-07 08:15:40 +01:00
commit b36a366240
826 files changed
+105304

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
# Randomizer mod (`randomizer`, GAMEPLAY)
Code: `src/main/java/com/eliasmueller/llamamod/mods/randomizer/` (`RandomizerMod`, `Shuffler`),
test `src/test/.../mods/randomizer/RandomizerModTest` (needs `-Dllamamod.cd=<cd dir>`).
## Options
| Key | Type | Default | Effect |
|---|---|---|---|
| `seed` | SEED | random on first use | same seed = same layout |
| `coins` | BOOL | on | `Coin`, `Coin5` |
| `food` | BOOL | on | `Health`, `HealthFull`, `Grapes`, `HealthBanana` |
| `mix` | BOOL | on | coins and food share one pool (otherwise each kind only among its own places) |
| `pots` | BOOL | off | `SmashPot(spawn)`, `Jar` among their own places |
| `enemies` | BOOL | off | enemies without patrol path, only among places of the same type |
## How it works
Per level WAD `t1l[1-8]mNNN.wad`: parse MAP (`MapChunk`, TRAK vertex counts), name every strat from
STPC (`Strats.nameOr`), sort eligible strats into pools, and permute the *places* inside each pool:
only fields 0–5 of the 58-byte strat record (rotation x/y/z, position x/y/z) are exchanged. Type
code, parameters, nVars/slots/flags/extra and the waypoint index stay with the strat, so the
multiset of objects in a level and the set of occupied places are unchanged – every pickup ends
on a spot where the original game had a pickup (reachable by construction). MAP is rebuilt with
`MapChunk.build()`; all other chunks are untouched.
PRNG: `java.util.Random(seed * 0x9E3779B97F4A7C15 + levelFileName.hashCode())`, pools in MAP order,
`Collections.shuffle` – both are specified by the JDK, so a seed gives the same result everywhere.
Never moved:
* every type not in the lists above (Llama/start, LevelDoor, CheckPoint*, Camera*, CutScene*,
triggers, Force*, switches/doors, RubyIdol (doors depend on it), ChargeBooster, CoinLine/Circle/
RollerCoaster, Secret, platforms …),
* strats with a waypoint (index ≠ −1: patrol paths, secret areas – their coordinates are absolute)
and strats with flag bit 1 (spawned later by an event),
* pots within 3 tiles of a `Secret` (the village secret is "smash the pot cluster").
Pool sizes (all options on, seed 1): 10–65 pickups per level, up to 14 pots; enemies only in
t1l4m002/3 (`VenusFlyTrap`, `AxeGuard`) because almost all enemies have patrol waypoints. Roller
coaster levels (t1l7m001/3/5) and t1l8m006 are unchanged.
Save game: coins per chapter are counted at pickup; the number of coins in a level is unchanged,
so the per-chapter totals and the "all coins" flag behave as in the original.
## Verified in game (apptest, 2026-11-06)
* Village t1l1m001, seed 1: level loads and plays, no crash (most swaps there are coin↔coin, so the
start view looks the same).
* Jungle t1l2m001, seed 2 (chosen because 3 food items land near the start): three of the four coins on
the path ahead of the start are replaced by Health/HealthFull pickups, the coins moved elsewhere
(`img/mods/randomizer-jungle-seed2.jpg`); level runs normally.
* Unit test (`RandomizerModTest`, all 33 WADs): deterministic per seed, different seeds differ,
pickup places are an exact permutation, type/params/waypoint fields unchanged, every other strat
(Llama, LevelDoor, CheckPoint*, cameras, triggers …) byte-identical, strats with waypoints never
move.
## Known limits
* Not played to the level exit in game; correctness of the exit/checkpoints rests on them being
untouched (unit test).
* A coin that sat in the air in an arc may now be a food item there (still reachable, it was a
pickup spot before); first coin parameter (0x1000 vs 0) stays with the strat.
* Enemy shuffle has little effect: almost all enemies have patrol waypoints and are excluded.