[lane E] The biome meter: the reputation you're building, made visible
A teal BIOME STANDING bar joins coat/hull in the HUD (matches the thin-cyan line-work; scale- only per the 60fps law). Hidden until the first `standing` event, so a flora-less level never shows a bar you can't fill. Brightens near full to telegraph an incoming phage ally. combat/index.js: rescaled standing to a clean 0..100 (tend +5, harm -35) — a FULL bar buds an ally and drops to a 50 recharge floor, so the meter reads as "charge it to summon help." First- pass numbers; tune to taste. Verified in-engine: tending flora reveals the bar and fills it proportionally (0.20 -> 0.45), teal, below coat/hull. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
71b0663b77
commit
4bcb942312
@ -76,15 +76,18 @@ export function createCombat({ scene, world, bus, rng, flags = {}, assets = null
|
||||
// (flora:harmed) to lose a chunk. At the symbiotic threshold the biome BUDS phage allies near
|
||||
// you that hunt your foes — the payoff. A `standing` event feeds a future HUD meter (Lane E).
|
||||
// ponytail: one run-scoped float, not a system. Persistence/tiers/L5-gate come when C needs them.
|
||||
// Scaled 0..100 so E can meter it honestly: tending fills the bar, a full bar buds an ally
|
||||
// and drops it to 50 (the recharge floor), harming flora empties a big chunk. Numbers are a
|
||||
// first pass — C/playtest tunes the feel.
|
||||
let standing = 0, phageBudCd = 0;
|
||||
const setStanding = (v) => { standing = Math.max(0, Math.min(100, v)); bus.emit('standing', { value: standing }); };
|
||||
const offTended = bus.on('flora:tended', () => { setStanding(standing + 2); budPhage(); });
|
||||
const offHarmed = bus.on('flora:harmed', () => setStanding(standing - 25));
|
||||
const offTended = bus.on('flora:tended', () => { setStanding(standing + 5); budPhage(); });
|
||||
const offHarmed = bus.on('flora:harmed', () => setStanding(standing - 35));
|
||||
function budPhage() {
|
||||
if (standing < 40 || phageBudCd > 0) return;
|
||||
if (standing < 100 || phageBudCd > 0) return; // a FULL bar buds an ally
|
||||
if (enemies.live.filter((e) => e.type === 'phage' && e.alive).length >= 3) return; // ally cap
|
||||
if (enemies.spawn('phage', { s: player.state.s + 8 })) {
|
||||
setStanding(standing - 20); // spend standing to bud
|
||||
setStanding(50); // recharge floor — the next ally is halfway earned
|
||||
phageBudCd = 3; // seconds between buds (decremented below)
|
||||
bus.emit('audio:cue', { name: 'pickup' }); // a friendly chirp when an ally is born
|
||||
}
|
||||
|
||||
@ -14,6 +14,8 @@ const C = {
|
||||
warn: '#ffb13a',
|
||||
bad: '#ff5a2a',
|
||||
surf: '#b06aff',
|
||||
ally: '#33ffbe', // teal — matches EMISSIVE.ally; the flora/phage reputation
|
||||
allyHot: '#c9fff0', // near-full: an ally is imminent
|
||||
};
|
||||
|
||||
const RAIL_W = 190; // px; shared by the CSS and the blip transform below
|
||||
@ -129,6 +131,15 @@ export function createHUD({ bus, flags = {}, level = null, mount = null } = {})
|
||||
// --- bottom-left: what's keeping you alive --------------------------------------------
|
||||
const coat = makeBar(bl, 'coat');
|
||||
const hull = makeBar(bl, 'hull');
|
||||
// biome standing — the flora reputation. Fills as you tend flora; a full bar buds a phage
|
||||
// ally (it drops to the recharge floor). Starts hidden and reveals on the first `standing`
|
||||
// event, so a level with no flora never shows an empty bar the player can't act on.
|
||||
const biomeRow = el('div', 'row', bl);
|
||||
biomeRow.style.display = 'none';
|
||||
const biomeLbl = el('span', 'lbl', biomeRow);
|
||||
biomeLbl.textContent = 'biome';
|
||||
const biomeRail = el('div', 'rail thin', biomeRow);
|
||||
const biomeFill = el('div', 'fill', biomeRail);
|
||||
|
||||
// --- bottom-right: what you're shooting with ------------------------------------------
|
||||
const heat = makeBar(br, 'heat', true);
|
||||
@ -195,6 +206,17 @@ export function createHUD({ bus, flags = {}, level = null, mount = null } = {})
|
||||
|
||||
offs.push(bus.on('combo', (e) => chain.set(e.n > 1 ? `×${e.n} chain` : '')));
|
||||
|
||||
// biome standing — reveal on first event, then scale-only (60fps law). Brightens near full
|
||||
// to telegraph an incoming ally.
|
||||
let biomeShown = false, lastStand = -1, lastStandC = '';
|
||||
offs.push(bus.on('standing', (e) => {
|
||||
if (!biomeShown) { biomeRow.style.display = ''; biomeShown = true; }
|
||||
const f = Math.max(0, Math.min(1, (e.value || 0) / 100));
|
||||
if (f !== lastStand) { biomeFill.style.transform = `scaleX(${f})`; lastStand = f; }
|
||||
const col = f >= 0.9 ? C.allyHot : C.ally;
|
||||
if (col !== lastStandC) { biomeRail.style.color = col; lastStandC = col; }
|
||||
}));
|
||||
|
||||
offs.push(bus.on('level:event', (ev) => {
|
||||
if (ev.type === 'checkpoint' && ev.name) where.set(ev.name);
|
||||
}));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user