Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·originates fromworld 9d2cf424-f…

cf_pusher

<!-- zero:scaffolded-readme --> <!-- Replace the line below with what this module provides and who consumes it, then delete both comment lines. -->

byzero-proxy @ DESKTOP-DB3UJOJ·posted 2mo ago
What it does

cf_pusher

<!-- zero:scaffolded-readme --> <!-- Replace the line below with what this module provides and who consumes it, then delete both comment lines. -->

TODO: describe this module.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

A coin pusher machine, rebuilt from photographs as a measured part hierarchy. `SPEC` holds every dimension read off the reference; `build()` spawns the cabinet as named primitives hanging off empty pivot entities, so the pusher, the chute and the payout flap articulate. The measurements and the identity list they answer to are written up in `/zero/source/reference/SPEC.md`, beside the photographs they came from. Every machine in the arcade is this same object at a rising `corruption`. `VARIANTS` names them, in the order the quota chain unlocks them: the first is a working arcade cabinet, the last is not a machine.

ModelBoxColliderPhysicsLightMeshCollider

variant(key: string) → void

argtypedescription
keystring

quatY(theta: number) → void

argtypedescription
thetanumber

pivot(ctx: Ctx, name: string, parent: ?, pos: ?) → void

An empty joint entity. Carries no Model, which is what makes it a pivot: the parts that travel with the joint hang under it and it is the only thing posed.

argtypedescription
ctxCtx
namestring
parent?
pos?

part(ctx: Ctx, name: string, parent: ?, mesh: string, mat: string, pos: ?, scale: ?, rotY: number?) → void

One primitive. A primitive is unit-sized and centred on its own origin, so a scale value IS the dimension in metres and no conversion is needed.

argtypedescription
ctxCtx
namestring
parent?
meshstring
matstring
pos?
scale?
rotYnumber?

tube(ctx: Ctx, name: string, parent: ?, mat: string, a: ?, b: ?, dia: number) → void

A cylinder spanning two points, working out the midpoint, length and rotation. Most of a manufactured object is struts between measured points.

argtypedescription
ctxCtx
namestring
parent?
matstring
a?
b?
dianumber

wall(ctx: Ctx, name: string, parent: ?, pos: ?, size: ?, friction: number?) → void

A static box collider stated as a FULL extent, halved here. Sizing by the entity's scale instead would also scale any model sitting on it.

argtypedescription
ctxCtx
namestring
parent?
pos?
size?
frictionnumber?

build(opts: { [string]: any }?) → void

Spawn one machine. `opts.variant` is a key from `VARIANTS`, `opts.name` the root entity's name, `opts.position` its world position and `opts.yaw` the rotation that turns it to face the hall. Returns `{ root, parts, count }`. An existing root of the same name is despawned first, so calling this again replaces the machine rather than stacking a second one beside it.

argtypedescription
opts{ [string]: any }?

mechanicOf(key: string) → string

The MECHANIC a variant plays by -- what the machine does to the bed beyond sweeping it. The hardware the builder puts on the cabinet and the rule the machine runs are named by the same string, so a machine cannot look like it plays one way and play another.

argtypedescription
keystring

spawnCoin(name: string, wx: number, wy: number, wz: number, spin: number?) → void

Spawn one coin as a dynamic body at a world point. The collider is a MeshCollider over the coin's own disc, fitted as a hull: identical geometry is built once and shared, so a field of hundreds of coins pays for one hull. A box would be the wrong shape, and it is the shape a coin visibly is not.

argtypedescription
namestring
wxnumber
wynumber
wznumber
spinnumber?

fillBed(built: ?, count: number, seedName: string?) → void

Lay a bed of coins over the deck and the pusher platform, the way a machine that has been played for a while looks. `count` coins are placed in rows across the field at coin pitch, so the bed reads as a carpet. Returns the entities laid.

argtypedescription
built?
countnumber
seedNamestring?

restY(lz: number, layer: number) → number

Which surface a coin rests on. A coin over the platform rests on the platform, not on the deck the platform slides above: the platform's underside sits higher than the deck, so laying a coin at deck height anywhere over the platform's footprint drops it into the gap between them.

argtypedescription
lznumber
layernumber

layTrinkets(built: ?, count: number, seedName: string?) → void

Lay trinkets on the bed — the prizes riding on the money, which are what a player is actually pushing for. Each is heavier than a coin, so it shoulders the bed aside as it travels. Returns the entities laid.

argtypedescription
built?
countnumber
seedNamestring?

setStroke(built: ?, t: number) → void

Pose the pusher. `t` in 0..1 walks one full stroke: 0 fully retracted, 1 fully extended toward the front lip. Writing the pivot is the only way the machine is posed. Teleport the pusher to a point in its stroke. This SETS a pose; it does not push. A body moved by having its transform written arrives at the new place without ever having travelled, so the solver has no motion to hand on to the bed — measured, one full stroke that way moves 2 of 28 coins by a millimetre. `M.driveStroke` is what a running machine uses; this is for placing the pusher at a known point before a measurement, and for posing it in edit. The stroke is applied in WORLD space: a body's transform is owned by the solver, and writing `localPosition` on one updates the field and moves nothing (#7405).

argtypedescription
built?
tnumber

driveStroke(built: ?, dir: number, speed: number?) → void

Drive the pusher for one frame. `dir` is +1 travelling toward the lip and -1 returning; the pusher is given a VELOCITY along the machine's depth axis rather than being placed, because a velocity is what the solver hands on to the bed. Measured over one full stroke: driven this way 40 of 40 coins in front of the face travel with it, by a mean of 0.141 m. Call every frame from the machine's update, flipping `dir` at the ends of the stroke — `M.strokePhase` reports which end the pusher has reached. The velocity is given in the BODY'S OWN frame: `Physics.setVelocity` rotates what it is handed by the body's orientation, while `Physics.getVelocity` reports world space (#7618). The pusher's local +Z already runs along the machine's depth however the cabinet is turned, so the vector is simply (0, 0, v) -- and a caller that converts to world first drives every machine on the left wall of the hall sideways out of its own cabinet. The pusher is also CLAMPED to its rails here. A kinematic body holds whatever velocity it was last given, so a single frame where the end of the stroke is missed sends it travelling down the hall for the rest of the run, taking the playfield with it.

argtypedescription
built?
dirnumber
speednumber?

strokePhase(built: ?) → number

How far through its travel the pusher is, 0 fully retracted to 1 fully extended, read off its live position. The machine flips direction on this rather than on a timer, so a stroke that is held up by the bed stays in step.

argtypedescription
built?

haltStroke(built: ?) → void

Stop the pusher where it stands.

argtypedescription
built?

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

3items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · cf_pusher.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.