Files
llamamod/notes/mod-arena.md
T

7.2 KiB
Raw Blame History

Alligator Arena (arena, LEVELS)

Package mods/arena: ArenaMod (writes wads/T1L9M0nn.wad + loading picture T19n.COR), Arena (level script, village base like the test world), ArenaScripts (the strat scripts, script language 2), ArenaImport (compile against a source level + StpcMerge import). Registered in ModRegistry (one line). Test-only: ArenaTestMod (src/test, script options).

Option Default Meaning
lives 5 (1–10) hits per alligator
waves 3 (1–5) wave n has min(n, 2) alligators (3 waves = 5 alligators)
energy 4 (1–5) llama energy cap (5 = game normal)
coins 1 (0–5) EnemyCoins per hit (+5 on defeat, +5 bonus at the exit)
chapter 49 (32–49) TestLevel chapter; a chapter already written by another mod → apply error; a stored 2–8 falls back to 49

Only chapters 32–49: the coin counter 0x584F1C[world·6 + chapter] and the flag byte 0x584EC8[…] of world-9 chapters 2–31 overwrite other globals (chapter 8 = last played map, chapter 9 = furthest progress – verified, see testlevel-chapters.md). The tally total (LNFO) is 2 placed coins + alligators · ((lives − 1) · coins + 5) + 5 bonus.

Script options (Arena, tests/ArenaTestMod): probe=true (event probe 1.6 ahead of the llama), master=false (no alligators), start=x,z,rot, debug=true (HUD coin counter shows kills·100 + wave·10 + alive).

Layout

Island 10..30 in sea (death plane). Pit x/z 16..24 (sand), walls 1.1 high, corner towers. Llama (20.5, 18) facing +z, start camera node 1.6 behind (inside the pit). CheckPointPost (16.8, 16.8). Exit pad 1×1 cell at (20.5, 23.5), material 16, gate on the north wall; ArenaMaster stands on it. Alligator spawn spots (20.5, 22.2), (18, 21.8), (23, 21.8). Two Coins at the side walls.

How it works

ArenaImport.append compiles the units with StratCompiler and appends them to the STPC of t1l4m002 (Jungle by day 2, has the Alligator), so model:47, anim:98–104, sound:58–62 and unit:56+0xf0 (EnemyCoin) / unit:36+0x28 (Sparkles) are that level's. A unit may refer to an earlier one as unit:@Name (→ unit:N+off; the compiler has no @label references). merge imports the units into the village base like the editor's cross import (models, animations, textures, 3 sound samples, EnemyCoin/Sparkles shared), adds one prototype MAP record per type (nVars/slots/typeFlags/extra), then LevelBuilder builds the level.

  • ArenaMaster (12 vars, no model): g104/g105 = −1, 2 s, then per wave: move to a spawn spot, yield, spawn<0, 16, 5, 0xC400, 3>(ArenaGator), alive += 1; waits until alive == 0 (gators do parent.v3 −= 1), 1.5 s pause. Win: g101..g103 = door target (1, 9, chapter), g104/g105 = its cell (the llama's own material-16 check then ends the level too), 5 EnemyCoins, Sparkles every 8 frames, endLevel when the llama stands on the pad (as LevelDoor). Each frame player.health2 is capped at energy (also after a respawn).
  • ArenaGator (spawned, 16 vars): the Alligator's model, collision (0x4000, 3 bones), particles and animations. hitDamage = 1793 (1 | 256 | 512 | 1024). on touched: if damageTaken & 1792 (kick 256, dive 512, charge 1024) → hit flag, else → "bit" flag. Main loop (switch state): 0 watch (turn to the player, after a timer snap if within 5 units and on the same floor ±0.4), 1 snap anim, 2 chase (speed up to 0.03 + 0.006·wave), 4/5 lunge and slow down (original numbers), 3 back off. Hit: lives −1, sound, green puff, coins EnemyCoins, blink 45 frames (alpha 0.25 + red ambient every 4 frames, no further hits), back off. Bite: back off and rest 90 frames. Clamped to the pit, y = floor. Last life: the original death (shrink, puffs, 5 EnemyCoins), parent.v3 −= 1, remove. The aim sub (ported L_03d0) writes g17..g20 so the llama's dive homes in on it. Fade-in on spawn (setAmbient 0→63).

Engine facts found

  • Compiled on touched handlers fire (event type 4): probe in game – the llama walks into it, it removes itself and three EnemyCoins pop out and are collected (coin counter 3).
  • Contact: each side's hitDamage is copied into the other's damageTaken, both get event 4. Llama: kick = 256 (Action on the ground, anim 28, hind-leg collision bones), dive = 512 (Action while jumping: homes in on the target in g17..g19 that enemies' scripts publish, best distance g20), charge = 1024. The llama counts a contact as its hit if damageTaken & hitDamage ≠ 0, else damageTaken & 127 == 1 → loseHeart + knock-back (the original Alligator has 513 = only the dive hurts it, a kick gets you bitten).
  • spawn<params, vars, slots, typeFlags, extra>: same fields as a MAP record (FUN_0054bfc0); extra = words for collision bones. A MAP-placed type that uses collisionOn needs collision type flags (0x28000 like Coin) – with 0 the game crashed (page fault in the heap allocator FUN_0041ae20).
  • spawn copies the strat's matrix/translation block, not x/y/z: after self.x = … the child appears at the old place unless the spawner yields first.
  • Energy 0: the game's "Weiter / Beenden" screen; Weiter restarts the level (all strats fresh).
  • The level tally after the exit showed "Münzen gesammelt 0 / 55" on chapter 8: 0 = the coin slot after endLevel wrote the last played map into it, 55 = LNFO of the Village base. Fixed: chapter 32–49 and recounted LNFO ("2 / 12" for 1 alligator with 1 life).

Verified in game (apptest :24, Wine 6, load 3–9, 2026-11-07)

  • Probe (probe=true;master=false): handler fires, coins collected (counter 3).
  • Default options (energy 5 and 4 runs): alligator fades in, watches, snaps, chases, bites (HUD energy drops), backs off. Kicks (Z) hit: puff, blink, coins pop out, counter rises (1 → 13 over two waves); defeat with puff and coins; wave 2 brings two alligators (debug counter 122 = 1 kill, wave 2, 2 alive). Blind kicking dies in wave 2 → Weiter restarts the arena with energy capped again.
  • Win (lives=1, waves=1, start=20.5,21,0): one kick defeats it, bonus coins + sparkles on the pad, walking onto it → tally screen with the arena loading picture.
  • Not verified separately: the dive (jump + Action) as the hit (sequences mixed kicks and dives), the charge, waves 4–5, coins option values other than 1.

fight defeat win: bonus coins on the exit pad, tally

Tests

ArenaTest: scripts compile for all option corners (EnemyCoin spawns = coins + 5, gator spawns = alligators, energy cap code only below 5); wave sizes; settings validation; registered; built level (CD): Llama, master on the exit cell with its vars, checkpoint, 2 coins, no LevelDoor, merged code decodes, master spawns the gator unit, gator spawns EnemyCoin, lives in the code; another mod's chapter → IOException; probe option.

Issues / limits

  • Loading picture and tally use the TestLevel texts ("TestLevel Kapitel 49").
  • The exit target is the arena itself (1, 9, chapter): it restarts after the tally.
  • Exiting chapter 49 unlocks "chapter 50" (progress 9/50); the map caps the cursor at 49 (checked).