scmJS docs

Unit graphics

npm run extract:units mirrors the part of the MPQ tree that leads from a unit type to its picture:

Files For
arr/{units,flingy,sprites,images}.dat, arr/images.tbl the lookup chain
arr/{weapons,upgrades,techdata}.dat defaults the settings dialogs show
game/tunit.pcx team colour rows
scripts/iscript.bin animation bytecode
unit/**/*.grp, unit/**/*.lo? sprite sheets and overlay positions
units.dat[id].flingy ─▶ flingy.dat.sprite ─▶ sprites.dat.image ─▶ images.dat.grp
   ─▶ images.tbl ─▶ unit\…\*.grp
GRP palette indices 8–15 ─▶ tunit.pcx row for the player's colour ─▶ tileset WPE palette
images.dat.iscript ─▶ iscript.bin header ─▶ Init / Built / StarEditInit ─▶ frames, overlays, turns

The GRP walk is seeded from the 228 unit types and all 517 sprites.dat entries, so pure sprites and doodad overlays have graphics too. That is about 750 GRPs and 12 MB in the current manifest. GRPs and overlay files are fetched lazily the first time they are needed, so a melee map only pulls minerals, geysers and start locations.

Team colour comes from the tunit.pcx row for the player's colour, remapping palette indices 8–15, painted through the tileset palette. Sprites therefore need the tileset loaded as well. Pink and the custom Remastered colours have no row to remap to, so teamColor.ts synthesises a ramp for them.

Animation#

Placed units run their in-game idle animations (View ▸ Animate Units). The viewport steps every unit's iscript once per game frame (42 ms, "Fastest"), the same rAF loop that drives water cycling. Preferences ▸ Display scales either rate on its own (0.25× to 4×), so a slow machine — or a preference for a calmer map — can turn one down without turning it off.

Each unit is a stack of images (shadow, main graphic, overlays), each with its own script. Buildings play their Built animation; tanks and Goliaths play StarEditInit, StarEdit's own hook, which adds the turret overlay. That gives turning turrets, pulsing Hatcheries, marines looking around, the Nexus glow, Starport lights and refinery smoke.

Damage overlays are re-evaluated from hit points: a building below two thirds burns (Terran), sparks (Protoss) or bleeds (Zerg) at the positions its .lo file gives, more of them the lower the HP, with the large effect below one third. Fire draws through the tileset's ofire/gfire/bfire/bexpl remap tables, extracted alongside the tileset files, blended additively as a stand-in for the game's palette-index lookup. Cloaked units draw half transparent.

Anything that needs the running game (attacks, sounds, projectiles, condition jumps) is a no-op. src/formats/dat/iscript.ts is dependency-free so the extraction script can import it under Node's type stripping and walk the scripts for reachable images.