Log inGet started
World

Blockbuster 767

Branchmain
Branchesmain
Commit8e9b87fcce

README.md

Plane767

The toy 767 the player IS. It sits on the Pilot prototype's airframe body, so every joining player gets one, and it owns the whole arc of a round: the launcher, the flight, the damage, and the moment the airframe stops.

The three phases

StateThe bodyWhat the controls do
windkinematic, posed on the launcherSteer x trims the heading (±Rules.LAUNCH.headingRange), steer y trims the launch elevation. launch is held to wind the key and released to throw. boost / brake step the called shot.
flightdynamicThe nose follows the stick, the velocity follows the nose, the wings carry most of gravity, boost adds speed and brake spoils the lift.
wreckdynamic, model stood downNothing is driven; the loose parts are still governed and culled.

Stick forward pushes the nose down and pull-back climbs, on the launcher and in the air, on every device at once.

Winding the key

Launch is held. Each Rules.LAUNCH.windSeconds of hold is one wind of the key, up to LAUNCH.winds; the last wind gets a window of its own, so a full throw is a release the player can aim for rather than an instant. Past that window the red zone runs for LAUNCH.overwindSeconds, and past THAT the spring lets go and the throw is a dud. With the numbers the rules carry today:

HoldWindsThrowBoost fuelDamage
0 – 0.55 s06 m/s0 s×1
0.55 – 1.10 s19 m/s1 s×1
1.10 – 1.65 s212 m/s2 s×1
1.65 – 2.20 s315 m/s3 s×1
2.20 – 2.90 s3, overwound16 m/s5 s×LAUNCH.overwindDamage
past 2.90 s0, the spring slipped6 m/s0 s×1

The modelled key on the toy's back turns a full turn per wind and trembles in the red zone; the spring's slip spins it back to rest. wind { winds, overwound } lands on the bus at each notch and once as the red zone opens, and launch { heading, winds, overwound, speed } when the key is let go.

Boost is what the wind BOUGHT: Game.telemetry.boostFuel is seconds of it, it drains only while Boost is actually thrusting, and an empty tank is a dead throttle for the rest of the round.

The called shot

On the launcher, boost steps forward and brake steps back through the landmarks City:landmarks() reports still standing, with "no call" as one of the stops, via Game.callShot. The city pays a called landmark's topple Rules.SCORE.calledShot times its landmark value. Missing costs nothing. The two buttons keep their flight meanings in the air, so the call needs no control of its own on any device.

The flight model

The airframe is driven with force, never with a velocity write, and the solver's own reading (Physics.bodyState().linearVelocity) is what the model reads back — so a block that hits the toy actually moves it, and the model sees that it did.

  • targetSpeed is script state, clamped to Rules.PHYS.planeMaxSpeed (planeBoostSpeed while Boost is held) before any force is spent, so the controller can never aim past the envelope. Anything above the cap — a collision, a fall — is taken straight back off the same frame.
  • The controller pulls the velocity onto the nose over followTime and hands back the share of gravity the wings carry, inside a budget of maxControlAccel. A harder hit than that budget still throws the toy.
  • Once the airframe has been scraping the table for groundedSeconds, the model stands down entirely and lets friction finish the round.
  • The round ends when the airframe has been below settleSpeed for Rules.SESSION.restSeconds and City:atRest() agrees, or when it has waited a further SESSION.restCityGrace for a city that will not settle. A toy that stops under a tower still coming down does not cut the tally off.
  • CCD is never enabled, here or on anything this component spawns.

Damage

Every frame in flight the airframe's contacts are read. A contact past impactThreshold raises impact { force, position, other } on the bus and adds to a damage pool; each whole point of damage sheds the part the hit landed nearest — the child the art slice built is hidden and a bounded loose copy is dropped in its place, with partLost { part, position } on the bus.

Losing a wing costs lift, control authority and rolls the toy toward the hole it left; losing an engine costs half the thrust and the boost cap; losing the tail costs pitch authority and most of the turn coupling. Game.telemetry.parts and .health carry the state for the HUD.

Loose parts are clamped every frame to Rules.PHYS.debrisMaxSpeed / debrisMaxSpin, culled below Rules.TABLE.floorY, and cleared when the next plane is armed.

Pause

menu toggles Game.setPaused. The airframe is frozen where it hangs — the body goes kinematic, its pose is held, and the model spends nothing — and resuming hands the same speed back along the nose. Scoped to this airframe on purpose: stopping the whole clock also stalls every task.wait in the world.

Reading it

  • Game.telemetry — written here every frame: speed, altitude, heading, pitch, bank, stick, boost, brake, health, parts, launched, elevation, winds, windCharge, winding, overwound, boostFuel, launchSpeed.
  • ref:status() — the same telemetry table.
  • ref:airframe() — { lost, partsLeft, damage, hardestHit, loosePieces, heading, elevation, winding, windHold, winds, windCharge, overwound, sprung, keyAngle, boostFuel, launchSpeed, damageScale, called, landmarks }, for a screen or a test that wants more than telemetry.

Controls

game/input/flight.inputMap — group flight, suppresses player, so the engine's walking scheme stands down while the toy is live. Every control carries keyboard, gamepad and touch; the on-screen controls are a stick in the left zone and one right-edge column, Launch (large, thumb-nearest), then Boost, Dive, Menu. The map's own README records what the overlay does with the margin it is given.

The builtin walking map is also held live here, inside the suppression this map already declares. It never reaches anything — flight outranks it — and it is what stops the engine arming the editor's map as the keyboard floor, which would put a "Frame" button and a look-drag zone on a touch player's screen.