cf_pusher
<!-- zero:scaffolded-readme --> <!-- Replace the line below with what this module provides and who consumes it, then delete both comment lines. -->
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/v2A 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.
variant(key: string) → void
| arg | type | description |
|---|---|---|
| key | string |
quatY(theta: number) → void
| arg | type | description |
|---|---|---|
| theta | number |
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.
| arg | type | description |
|---|---|---|
| ctx | Ctx | |
| name | string | |
| 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.
| arg | type | description |
|---|---|---|
| ctx | Ctx | |
| name | string | |
| parent | ? | |
| mesh | string | |
| mat | string | |
| pos | ? | |
| scale | ? | |
| rotY | number? |
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.
| arg | type | description |
|---|---|---|
| ctx | Ctx | |
| name | string | |
| parent | ? | |
| mat | string | |
| a | ? | |
| b | ? | |
| dia | number |
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.
| arg | type | description |
|---|---|---|
| ctx | Ctx | |
| name | string | |
| parent | ? | |
| pos | ? | |
| size | ? | |
| friction | number? |
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.
| arg | type | description |
|---|---|---|
| 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.
| arg | type | description |
|---|---|---|
| key | string |
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.
| arg | type | description |
|---|---|---|
| name | string | |
| wx | number | |
| wy | number | |
| wz | number | |
| spin | number? |
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.
| arg | type | description |
|---|---|---|
| built | ? | |
| count | number | |
| seedName | string? |
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.
| arg | type | description |
|---|---|---|
| lz | number | |
| layer | number |
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.
| arg | type | description |
|---|---|---|
| built | ? | |
| count | number | |
| seedName | string? |
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).
| arg | type | description |
|---|---|---|
| built | ? | |
| t | number |
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.
| arg | type | description |
|---|---|---|
| built | ? | |
| dir | number | |
| speed | number? |
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.
| arg | type | description |
|---|---|---|
| built | ? |
haltStroke(built: ?) → void
Stop the pusher where it stands.
| arg | type | description |
|---|---|---|
| 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.
Problems
Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.
agent_score is exposed.+ 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".
Scoped to this part · feeds back into the world's score.