Let the horde gun keep up with the horde
The run ended on the second wave every time: the gun fired 6 flat rounds a second, hit one body each, and every shambler soaked one — while hordeGrow made each wave longer and denser. Doubled the rate and scaled it with the wave (14/s at one set banked, 21/s at four), gave a round 0.5m of extra reach, a wider cone, and enough damage to drop a shambler outright. Raised the spawn rate to match, so surviving a wave still leaves a standing crowd on your half — that pressure is the point of it. Also: he no longer carries a second racket at his hip while holding one forward (the run frames are the racket-less art), the umpire stopped talking over himself and saying "remain seated" twice, and a timed freeze now shows what it is counting down to instead of reading as dead controls. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
571cd4c399
commit
e904dfefa6
5 files changed
+47
-13
No files matched your search
+6
-5
@@ -304,10 +304,11 @@ function splatter(i, fanfare = true) { // the MAIN ball hit a zombie
|
||||
function spawnHordeZombie() { // all from the far baseline, across the court — never off-screen at the sides
|
||||
spawnZombie((Math.random() * 2 - 1) * 5, -1.5 - Math.random(), Math.random() < 0.5 ? 'a' : 'b');
|
||||
}
|
||||
let mgTick = 0;
|
||||
function firePellet() {
|
||||
const a = (Math.random() * 2 - 1) * 4 * Math.PI / 180, s = 26; // ±4° spread, straight up-court (-z)
|
||||
const a = (Math.random() * 2 - 1) * TUNE.mgSpread * Math.PI / 180, s = 26; // spread cone, straight up-court (-z)
|
||||
pellets.push({ x: P.x, y: 0.9, z: P.z, vx: Math.sin(a) * s, vz: -Math.cos(a) * s, t: 1.2 });
|
||||
pock(0.25, 1400); // rapid fire tick; if it clips on device, gate to every 2nd pellet
|
||||
if (++mgTick % 2 === 0) pock(0.25, 1400); // rapid fire tick, every 2nd round — at 12+/s every round buzzes
|
||||
}
|
||||
export function spawnRacketZombie() { // one takes up residence on the far court — an opponent, of sorts
|
||||
// He stiffens as the run goes on. hpMax is stored because the wound skins and bleed() anchors read
|
||||
@@ -338,7 +339,7 @@ function tickHorde(dt) {
|
||||
if (zombies.length < TUNE.zHordeCap) spawnHordeZombie(); // ...but bounded, see TUNE.zHordeCap
|
||||
h.spawnT = 1 / (h.rate || TUNE.hordeRate);
|
||||
}
|
||||
if ((h.mgT -= dt) <= 0) { firePellet(); h.mgT = 1 / TUNE.mgRate; }
|
||||
if ((h.mgT -= dt) <= 0) { firePellet(); h.mgT = 1 / (h.mgRate || TUNE.mgRate); }
|
||||
if (h.t <= 0) endHorde();
|
||||
}
|
||||
|
||||
@@ -578,12 +579,12 @@ export function updateZombies(dt) {
|
||||
for (let j = zombies.length - 1; j >= 0; j--) {
|
||||
const zb = zombies[j];
|
||||
if (!zb) continue;
|
||||
if (Math.hypot(zb.x - pe.x, zb.z - pe.z) < hitR(zb)) {
|
||||
if (Math.hypot(zb.x - pe.x, zb.z - pe.z) < hitR(zb) + TUNE.mgPelletR) {
|
||||
// Pellets used to skip the boss entirely, so a GUN burst (and every horde) did literally
|
||||
// nothing to him with no feedback at all. They CHIP him now: dmgPellet is fractional, so
|
||||
// three rounds take a point off and the gun is a slow, committed answer rather than a no-op.
|
||||
if (isBoss(zb)) { if (wound(zb, TUNE.dmgPellet, false)) killZombie(j, true); else pock(0.45, 240); }
|
||||
else if (zb.hp > 1) { zb.hp--; pock(0.5, 260); } // brutes AND shamblers soak pellets — wound, don't kill
|
||||
else if ((zb.hp -= TUNE.dmgPelletHp) > 0) pock(0.5, 260); // only brutes soak now; a shambler drops to one round
|
||||
else killZombie(j, true);
|
||||
hit = true; break;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user