3.8 KiB
3.8 KiB
Draw distance mod (fog, VISUAL)
Code: src/main/java/com/eliasmueller/llamamod/mods/fog/FogMod.java, test
src/test/.../mods/fog/FogModTest (needs -Dllamamod.cd=<cd dir>). Data-only (MAP chunks), no
exe patch.
Options
| Key | Type | Default | Effect |
|---|---|---|---|
distance |
INT % 100–600 | 250 | fog start/end (= far clip) × distance/100 |
fog |
CHOICE scaled / off |
scaled | off: fog band shrunk to 1/16 tile, i.e. no fade, hard edge at the draw distance |
Engine facts (groove.exe)
- Environment zone (MAP block 4, 90 bytes on disk, 0x5c in memory; loader FUN_0042ac50). Fog
values are 20.12 fixed point, 4096 = 1 tile:
memory file offset meaning +0x34 0x34 fog mode (3 = vertex fog/darkening; 2 = other mode; read by FUN_00438180) +0x3c / +0x40 0x3a / 0x3e fog start / end for detail "Minimum" +0x44 / +0x48 0x42 / 0x46 fog start / end for detail "Maximum" (loader: if +0x44 ≤ +0x3c, both are set to 1.5 × the low pair) +0x4c, +0x50 0x4a, 0x4e colours (ambient → FUN_0041bcf0, backdrop/fog → FUN_00439110) +0x58 0x56 music id The u16 at +0x38 takes 2 bytes on disk, so all later file offsets are memory − 2. - Per frame (FUN_0041a480; zone switch FUN_0041e1c0):
t= detail setting (0x5848cc: 1.0 Maximum, 0.5 Medium, 0.0 Minimum). Fixedend = lo_end + (hi_end − lo_end)·t→ 0x58658c / 0x586590; floatfar = end·(t + (1−t)·0.5)/4096→ 0x57f90c = 0x57f8fc; fog start likewise → 0x57f8f8; 0x57f904 = 1/(far − start) (fog factor), 0x57f914 = 0.9999999/(far − near) (depth).FUN_00424bb0(near, far)sets the clip range for the rasteriser. - Everything that limits view distance derives from these zone values:
- fog: vertex colours are scaled by
(far − d)·0x57f904whend > start(0x421a14 …, 0x557b20 …), - far clip plane 0x57f90c,
- tile renderer FUN_0042bf40 walks the grid cells within camera ± (far + const),
- strat visibility/activity radius
0x586590 + 0x800(FUN_00428700, FUN_004361xx; strat opcode 0xf2 also returns it). So objects (and enemies) wake up from further away as well.
- fog: vertex colours are scaled by
- Not changed: the region mask
0x58642c(32 region bits from MAP block 6/7, set by triggers; hides other rooms/areas) – it is a level-design visibility mechanism, not a distance limit. - Original fog end at Maximum detail, per level: 7–16 tiles (village t1l1m001 8.2–12.8, jungle t1l2m001 8.6–10.5, jungle night chase t1l2m003 6.9, city t1l6m001 14, roller coaster up to 23). At Minimum the float far is only half of the low pair (2.5–4 tiles). Zones with mode 0 carry placeholder values (2.0/3.5/3.0/5.25) and are scaled as well.
Verified in game (apptest, Wine 6, llvmpipe, 2026-11-06)
- Jungle t1l2m001 at 50 % / original / 400 %: at 50 % the spider-web gate at the end of the first
path disappears in the dark fog, at 400 % it is a bit clearer than in the original
(
img/mods/fog-jungle-50-100-400.jpg). This proves the four zone values drive fog + clip. - Village t1l1m001 (400 %, 300 %, 50 %) and city t1l6m001 (400 %,
img/mods/fog-city-400.jpg): levels load and run, no crash, no slowdown noticeable in the harness; the start views are enclosed (village backdrop mountains are a sky texture, the city streets are short), so the difference there is small. - Not tested: 600 % in large open levels (roller coaster, 23 tiles × 6) – expect more tiles and
strats per frame; and the
offmode in game (unit test only).
Known limits
- Many areas are enclosed or use region masks, so the gain is mostly visible on long paths and open views (jungle, river, roller coaster). The village backdrop is a texture, not geometry.
- Objects/enemies activate from further away (strat radius = fog end); with large values enemies may start moving before they are in view.