Fill the rack yourself, and roll barrels out that fill it
The rack had five hardcoded slots where the index WAS the weapon, spelled out in
five places: SLOTS, slotStock, WDESC, drawRack's three parallel arrays,
deliverTin's w+1, and bare wsel === 1|2|3 / G.weapon === 4 tests across five
files. config.WEAPONS is the one table now, G.rack holds up to four {id, n} in
the order you GATHERED them, and slot 0 stays BALL. Everything reads through
slotId/slotStock/slotEntry, so nothing else knows how the rack is stored.
A fifth weapon is always allowed, per Oliver: it rides slot 0 as G.temp until
spent, then slot 0 goes back to the infinite ball. A barrel arms on the spot and
is spent quickly, so refusing it would mean a barrel you shot did nothing. And a
spent weapon LEAVES its slot -- with gathered slots, an exhausted weapon holding
one is a quarter of the rack you can never pick up into. (The old rack kept its
empties dimmed, which was right when a slot meant "BOMB goes here".)
Four new weapons, and they are all the ONE existing pellet loop. firePellet(w)
stamps the WEAPONS row onto the round -- r, dmg, hp, pierce, boom, ignite, col,
speed, life -- so the beacon cannon, flamethrower, laser and rocket needed no new
array and no new update; the break after the first body was the only thing making
a pellet single-target. All four go through the same isBoss branch, which is why
none can silently no-op on a boss the way three of five once did. Measured:
gun/beacon/laser/rocket reach past 16 m, the flamer is a ~6 m cone that ignites.
G.mgT stays the mode timer for all of them, so the eighteen !(G.mgT > 0) guards
across five files did not have to change. kind:'burst' auto-fires at its own rate
for len seconds; kind:'shot' holds the same braced stance and fires one per tap.
The barrels reuse the ball machine's shape: a rolling, shootable non-body. All
three of the registrations that fail silently are done -- blocksClear (loot must
not gate the hand-clear), the contact guard (furniture cannot eat you), and
hitR/GORE_MUL/zombieH. It scores nothing.
The pink had to become procedural. The chroma key deletes every pixel where red
and blue both beat green by 40, so a magenta drum and a magenta laser pistol both
came back as hollow outlines -- 19% and 15% solid against 50-56% for the icons in
other colours. The drum is grey steel with hazard chevrons and every bit of its
pink is the halo drawBarrel paints; the laser went electric blue. Both are solid
now (92% and 58%), and the rule is written down in HANDOFF.
tinTriples 3 -> 10 as asked, and the four dead TUNE ammo constants are gone --
nothing read them once the table landed, which is a panel value you can tune all
day for no effect.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4cda6bde76
commit
25f915f236
16 files changed
+385
-97
No files matched your search
@@ -211,10 +211,9 @@ export const TUNE = {
|
||||
// on its own so there is always a chance at one. Fires off the next hand-cleared wave.
|
||||
duelFirst: 2, // game after which the first scheduled sudden-death duel is called
|
||||
duelEvery: 3, // games between scheduled duels after the first
|
||||
bombMax: 3, // bomb balls in a fresh tin
|
||||
tinTriples: 3, // triple-serves in a fresh tin
|
||||
tinFlames: 3, // flame balls in a fresh tin
|
||||
tinGuns: 1, // machine-gun charges in a fresh tin
|
||||
// How many a fresh tin holds now lives on its WEAPONS row (`tin`), because the rack is no longer
|
||||
// four fixed types — bombMax/tinTriples/tinFlames/tinGuns lived here and nothing read them after
|
||||
// the table landed, which is a value you can tune in the panel all day for no effect.
|
||||
wCap: 9, // per-type cap on the courtside rack — tins accumulate, but only so many
|
||||
rackH: 30, // px height of the bottom weapon rack (feel knob: how much court it covers).
|
||||
// 22 logical px is ~30 CSS px on a phone — under half Apple's 44px target, which
|
||||
@@ -231,6 +230,14 @@ export const TUNE = {
|
||||
mgPelletR: 0.5, // m of extra hit radius on a pellet: a fat round. "Bigger ball = more damage."
|
||||
dmgPelletHp: 2, // hp a pellet takes off a body — shamblerHp is 2, so the horde gun one-shots them
|
||||
mgPickupLen: 8, // s the machine-gun tin (4th delivery) auto-fires outside hordes
|
||||
shotHoldLen: 14, // s you stay braced with a TAP-fired weapon (laser, rocket) before the window
|
||||
// closes on its own. Running the magazine out ends it earlier, which is the
|
||||
// normal way; this only stops a forgotten rocket freezing the serve loop.
|
||||
// ---- the weapon barrel: the only way to get the four weapons that are not on the duel ladder
|
||||
barrelEvery: 3, // games between barrels being rolled on (like the ball machine's machEvery)
|
||||
barrelRoll: 2.6, // m/s it trundles across the far court — fast enough to have to be led
|
||||
barrelHp: 1, // anything pops it: ball, pellet, bomb, flame, swish. It is a target, not a body
|
||||
barrelH: 1.15, // drawn height (a body is 1.8)
|
||||
fps: 60, // frame cap — 30 halves battery/heat but Oliver felt it; smoothness wins (0 = uncapped)
|
||||
runnerSpeed: 3.2, // runner ('f') speed multiplier over the shamble
|
||||
runnerVMax: 4.2, // hard runner speed cap — the late-game ramp must stay humanly reactable
|
||||
@@ -293,7 +300,10 @@ export const EATEN_FEED_R = 1.15; // m — how tight the feeding ring packs arou
|
||||
// desaturated from the original arcade primaries: they were shouting over the artwork.
|
||||
// (NOT the gore — blood and piles keep their loud reds; only text and interactive UI.)
|
||||
export const UI = { hot: '#d9705f', warm: '#e0cc72', pick: '#cbd06a', cream: '#e8e8dc',
|
||||
dim: '#8fa0b8', bad: '#a34a42', ball: '#dbe063' };
|
||||
dim: '#8fa0b8', bad: '#a34a42', ball: '#dbe063',
|
||||
// the weapon barrel's glow, and the only pink on the court: nothing else in the
|
||||
// palette is near it, so "pink means a weapon is in there" needs no explaining
|
||||
pink: '#ff5cf0' };
|
||||
|
||||
// ------------------------------------------------------------------ courts ----
|
||||
// A court type is pure DATA: adding one is a row here plus its four PNGs, never a change to render().
|
||||
@@ -408,13 +418,54 @@ export const ZWOUND = {
|
||||
k: ['z_kw', 'z_kw2', 'z_kw3', 'z_kw4'],
|
||||
};
|
||||
|
||||
// ---- THE ARSENAL. One table, keyed by id, replacing the five places the roster used to be spelled
|
||||
// out (SLOTS, slotStock, WDESC, drawRack's three parallel arrays, and deliverTin's index mapping).
|
||||
// The rack no longer has a fixed weapon per slot: G.rack holds up to four of these in the order you
|
||||
// GATHERED them, and slot 0 stays BALL. A weapon is defined entirely by its row.
|
||||
// kind 'serve' — arms the next serve (the four original tins)
|
||||
// kind 'burst' — commits to a braced auto-fire window: `len` seconds at `rate` rounds/s
|
||||
// kind 'shot' — same braced stance, but each TAP fires one and `tin` is the magazine
|
||||
// The pellet fields (r, dmg, pierce, boom, ignite, col, speed) are stamped onto the round by
|
||||
// firePellet, so all four new weapons are the ONE existing pellet loop with different numbers.
|
||||
export const WEAPONS = {
|
||||
bomb: { label: 'BOMB', icon: 'w_bomb', tin: 3, kind: 'serve',
|
||||
desc: ['DETONATES ON CONTACT', 'CLEARS A WHOLE CROWD AT ONCE'] },
|
||||
triple: { label: 'TRIPLE', icon: 'w_triple', tin: 10, kind: 'serve', // was 3 — Oliver asked for ten
|
||||
desc: ['ONE SERVE, THREE BALLS', 'FANNED WIDE ACROSS THE LANE'] },
|
||||
fire: { label: 'FIRE', icon: 'w_fire', tin: 3, kind: 'serve',
|
||||
desc: ['KILLS ON ANY TOUCH', 'AND SETS THE OTHERS ALIGHT'] },
|
||||
gun: { label: 'GUN', icon: 'w_gun', tin: 1, kind: 'burst', len: 8, rate: 12,
|
||||
r: 0.5, dmg: 0.34, hp: 2, speed: 26,
|
||||
desc: ['HOLD THE LINE AND SPRAY', 'A BURST, NOT A SERVE'] },
|
||||
// ---- the four that come out of a barrel. Won by shooting one, never delivered.
|
||||
beacon: { label: 'BEACON', icon: 'w_beacon', tin: 1, kind: 'burst', len: 10, rate: 3,
|
||||
r: 1.1, dmg: 3, hp: 9, speed: 17, col: '#7fefff', glow: 1,
|
||||
desc: ['A SLOW BEAT OF BIG', 'GLOWING SHELLS'] },
|
||||
flamer: { label: 'FLAMER', icon: 'w_flamer', tin: 1, kind: 'burst', len: 5, rate: 16,
|
||||
r: 0.8, dmg: 2, hp: 9, speed: 11, life: 0.55, ignite: true, col: '#ffa040', glow: 1, // life 0.55s x 11 m/s = a ~6 m cone
|
||||
desc: ['A CONE OF FIRE', 'AND THE FIRE SPREADS'] },
|
||||
laser: { label: 'LASER', icon: 'w_laser', tin: 10, kind: 'shot',
|
||||
// NOT magenta: the icon art is chroma-keyed and the key eats every pink/purple
|
||||
// (min(r,b) > g+40), so a magenta laser came back as a hollow outline. Pink stays
|
||||
// the BARREL's identity, where it is a procedural glow and never goes near the key.
|
||||
r: 0.55, dmg: 3, hp: 9, speed: 70, pierce: true, col: '#8ab6ff', glow: 1,
|
||||
desc: ['TEN SHOTS, AND EACH ONE', 'GOES THROUGH THE WHOLE LANE'] },
|
||||
rocket: { label: 'ROCKET', icon: 'w_rocket', tin: 3, kind: 'shot',
|
||||
r: 0.6, dmg: 3, hp: 9, speed: 22, boom: true, col: '#ffd050', glow: 1,
|
||||
desc: ['THREE ROCKETS', 'EACH ONE TAKES THE CROWD'] },
|
||||
};
|
||||
// what a pink barrel can be carrying — the four above that you cannot win any other way
|
||||
export const BARREL_WEAPONS = ['beacon', 'laser', 'rocket', 'flamer'];
|
||||
export const RACK_MAX = 4; // gathered weapons the rack holds; a 5th rides slot 0 until it is spent
|
||||
|
||||
export const MACH_H = 1.55; // was 1.15 — waist high read as a prop you could ignore. Still furniture
|
||||
// (a body is PLAYER_H 1.88), but big enough to be a thing on the court.
|
||||
|
||||
// Drawn height of a body on the far side, by variant. render draws to it AND the serve aims at a
|
||||
// fraction of it, so the two cannot drift — a shot at a brute has to arrive at the brute's chest,
|
||||
// not at the height a shambler's chest happens to be.
|
||||
export const zombieH = zb => zb.variant === 'g' ? 2.7 : zb.variant === 'd' ? 2.15
|
||||
export const zombieH = zb => zb.variant === 'o' ? TUNE.barrelH
|
||||
: zb.variant === 'g' ? 2.7 : zb.variant === 'd' ? 2.15
|
||||
: zb.variant === 'k' ? 3.2 : zb.variant === 'h' ? 2.4
|
||||
: zb.variant === 'r' ? 1.85 : zb.variant === 'm' ? MACH_H
|
||||
: zb.variant === 'B' ? 1.8 * (zb.scale || 1.5) : 1.8;
|
||||
|
||||
Reference in new issue
Block a user