The toss travels: the receiver watches the serve coming

One event on the toss, replayed as a real toss over O — update() already
poses the server off the phase and drops an uncaught ball back to pretoss
by plain physics, so the wind-up, the cancel and the re-toss all carry for
free. The strike's shot event overwrites whatever drifted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Fable 5 committed 2026-08-14 17:44:00 +02:00
1 parent f302354bb2
commit 8face714a6
4 files changed
+36 -4

No files matched your search

+5 -2
View File
@@ -9,7 +9,7 @@ import { updateDrill } from './drill.js';
import { endRun, beginRun, MODE_CLASSIC } from './stats.js';
import { updateZombies, updateParts, spawnZombie, spawnRacketZombie, spawnMachine, spawnChapterBoss, zombies, gore, explode, meleeSwipe, extras, parts, pellets, shots, playerGore, eatenBleed, resetZombies , firePellet , spawnBarrel , fireBeam , pops, popText } from './zombies.js';
import { proceedAfterClear, startDuel, startHorde, warnHorde, resolveInterlude, watchdog, updateBench, benchKey, tickMatchFall } from './beats.js'; // runtime-only cycle: beats calls back into cheer/aside/endBurst/deliverTin/showModal/logSwing
import { netSendShot, netTick, netJudging, netSendPoint, netSendFault, netClose } from './net.js'; // runtime-only cycle: net calls back into pointTo/fault/showModal
import { netSendShot, netSendToss, netTick, netJudging, netSendPoint, netSendFault, netClose } from './net.js'; // runtime-only cycle: net calls back into pointTo/fault/tossBall/showModal
// ------------------------------------------------------------- ballistics ----
// Launch ball from (x0,y0,z0) so it arrives at (tx, tz) with horizontal speed s under gravity g.
@@ -232,7 +232,7 @@ function doHit(ch, quality, aim) {
}
// ----------------------------------------------------------------- serve ----
function tossBall(sv) {
export function tossBall(sv) { // exported for net.js: a remote toss replays as a real toss over O
ball.active = true; ball.bounces = 0; ball.collected = false;
// The ball rises over the tossing HAND, not the head — TOSS.dx/oDx are measured off the toss
// frames' raised fingertips (see config). `* facing` because drawChar mirrors the whole sprite
@@ -250,6 +250,9 @@ function tossBall(sv) {
// same latent bug for anyone tossing from deep behind the line.
ball.lastHit = sv.side;
G.phase = 'toss';
// netplay: the toss travels too, so the receiver watches the serve COMING instead of a ball
// appearing from nothing — return timing is half the sport and it needs the wind-up
if (G.net && sv.side === 'P') netSendToss();
}
export function serveApexY() { return TOSS.y0 + TOSS.vy * TOSS.vy / (2 * TUNE.gravity); } // ~2.95