The host names the stakes: classic tennis, or the death match
Three chips under VS A FRIEND — the host's pick rides the room and the start message rebuilds both courts on pairing. In the death match your opponent IS the zombie: their lost points tear its wound stages, their won points draw your blood, and bleeding out crosses the wire as the other phone's win. The same receiver-is-judge verdicts drive the match machinery through resolveInterlude, so the fall, the mop beat and the burst come along unmodified. New: gushProne — the game-winning body bleeds out on the ground, from prone-height anchors, until it bursts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5e80c4e69d
commit
c0b59eee90
10 files changed
+241
-26
No files matched your search
+7
-2
@@ -1017,6 +1017,9 @@ function onBounce() {
|
||||
// below read 'X' as HIS ball — bounce out and you were handed the duel, bounce twice in-court
|
||||
// and you LOST it for hitting him. Same rule as the dead-roller path in update().
|
||||
if (ball.lastHit === 'X') { spentBall(); return; }
|
||||
// NETPLAY (death match): same rule as the tennis block below — the receiving phone is the only
|
||||
// judge of a flight; our outbound ball is picture and its verdict arrives as a message.
|
||||
if (G.net && ball.lastHit === 'P') return;
|
||||
if (ball.bounces === 1) {
|
||||
const okSide = ball.lastHit === 'P' ? ball.z < COURT.netZ : ball.z > COURT.netZ;
|
||||
if (!inCourt(ball.x, ball.z) || !okSide) { ball.active = false; resolveInterlude(other(ball.lastHit)); voice('out'); }
|
||||
@@ -1035,7 +1038,9 @@ function onBounce() {
|
||||
// from before"). No more ordering proofs: the latch goes up BEFORE, the resolution in
|
||||
// progress is exempted via G.matchEarly in resolveInterlude's swallow, and any path that
|
||||
// re-arms play clears it in matchReady. Stale by construction impossible.
|
||||
else if (G.match && !G.match.ending && !G.match.decided && ball.lastHit === 'P'
|
||||
else if (G.match && !G.net && !G.match.ending && !G.match.decided && ball.lastHit === 'P'
|
||||
// !G.net: the early decide predicts the CPU's legs — a human on another phone is
|
||||
// not predictable, and the receiver is the only judge of this flight anyway
|
||||
&& matchFallWillPlay() && matchOutOfReach()) {
|
||||
G.match.decided = true; // scope: the REMAINING ball events of this rally
|
||||
G.matchEarly = true; // startFall leaves the ball rolling; the swallow exempts us
|
||||
@@ -1804,7 +1809,7 @@ export function update(dt) {
|
||||
if (G.mode === 'splatter' && !G.horde)
|
||||
// ...and not while the body is on the ground: the fall owns the sprite AND the pose for its
|
||||
// whole run, and racketAI would put a collapsing corpse back on its feet to chase a stray ball.
|
||||
if (!G.bench && !G.matchFall) for (const rz of zombies) if (rz.variant === "r") racketAI(rz, dt); // the bench drives its own body
|
||||
if (!G.bench && !G.matchFall && !G.net) for (const rz of zombies) if (rz.variant === "r") racketAI(rz, dt); // the bench drives its own body; netplay's body is the other phone (netTick)
|
||||
|
||||
// --- ball physics
|
||||
if (ball.active) {
|
||||
|
||||
Reference in new issue
Block a user