voidutil — the small shared maths the hazard modules all need.
Slice E only. Deterministic RNG (so every peer builds the SAME void),
vector helpers, axis-angle tumbling, and a guarded spawn/despawn pair
that never leaves an orphan behind.
seedOf(s: string) → number
Deterministic RNG — a 32-bit LCG, seeded by a string.
The world is multiplayer and the hazards are built independently on
every peer. Seeding from a string (never from os.clock or math.random)
is what makes two peers agree on where the debris is.
| arg | type | description |
|---|
| s | string | |
rng(seed: string | number) → void
| arg | type | description |
|---|
| seed | string | number | |
range(lo: number, hi: number) → number
| arg | type | description |
|---|
| lo | number | |
| hi | number | |
int(lo: number, hi: number) → number
| arg | type | description |
|---|
| lo | number | |
| hi | number | |
dir( ) → void
A random unit vector, evenly spread over the sphere.
add(a: ?, b: ?) → void
Vectors
scale(a: ?, k: number) → void
| arg | type | description |
|---|
| a | ? | |
| k | number | |
lerp(a: ?, b: ?, t: number) → void
| arg | type | description |
|---|
| a | ? | |
| b | ? | |
| t | number | |
dist(a: ?, b: ?) → number
dist2(a: ?, b: ?) → number
Squared distance — for the range gates that run over every object every
frame and never need the root.
quatAxisAngle(axis: ?, angle: number) → void
Rotation
Quaternion { x, y, z, w } for a rotation of `angle` radians about `axis`.
| arg | type | description |
|---|
| axis | ? | |
| angle | number | |
lookRotation(d: ?) → void
The rotation that points a mesh's +Z down `d`. Anything long and
travelling — an ember on a flare front, a lantern's trailing bell —
needs this, or it is a stretched sphere pointing the wrong way.
spawn(bag: ?) → void
Entity bookkeeping
Everything a hazard module spawns is temporary (never saved into the
scene) and tracked, so onDestroy can prove it left nothing behind.
despawnAll(list: { any }) → void
| arg | type | description |
|---|
| list | { any } | |
despawnByPrefix(mount: ?, prefix: string) → number
Sweep a mount point for anything a PREVIOUS instance of this module
spawned.
A module-local list is not enough on its own. Editing a `.module` file
hot-reloads it into a FRESH table with fresh locals, so the tracking
list that held the last build's entities is gone while the entities
themselves are still parented to the mount. Names are the only handle
that survives the reload, so every hazard module prefixes what it
spawns and sweeps that prefix when it starts.
| arg | type | description |
|---|
| mount | ? | |
| prefix | string | |
queue( ) → void
A spawn queue, because a hazard field is a hundred entities and spawning
a hundred entities inside one update() is a watchdog halt:
"script halted by the watchdog: it ran for more than 1000 ms".
Build enqueues; update drains a few per frame; the field fades in over
about a second instead of stalling the whole engine for one.
push(bag: ?, assign: ?) → void
| arg | type | description |
|---|
| bag | ? | |
| assign | ? | |
drain(budget: number) → number
| arg | type | description |
|---|
| budget | number | |
routes(sites: ?, origin: ?) → void
Routes — the crossings the voyage is actually made of
Every hazard in this slice is placed against THIS list rather than
against hardcoded coordinates, so if Slice C moves a site the danger
moves with it. A route is the straight line between two waypoints
(the spawn origin counts as one); the list comes back longest first,
because the long crossings are the ones worth making expensive.
| arg | type | description |
|---|
| sites | ? | |
| origin | ? | |
along(route: ?, t: number) → void
A point `t` of the way along a route.
| arg | type | description |
|---|
| route | ? | |
| t | number | |