mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-11 03:09:57 +00:00
feat(career): badge ceremony — the crowd erupts, the stamp drops (#941)
Earning a genre badge now stages the full moment (career v2, WS1):
- venue-crowd.js gains a public celebrate(): machine.force('ecstatic')
commits instantly (bypassing STABLE_MS/DWELL_MS; the stamped
lastSwitchAt makes the dwell window HOLD the forced state before the
real perf machine reasserts) + a cheer stinger via the same
_lastStingerAt=-Infinity bypass the end-of-song reaction uses. If a
stinger/intro owns the idle layer, the ecstatic loop is queued via
_pendingLoop exactly like onPerformanceState. No-op without a
manifest/active venue.
- career detectNewBadges() calls badgeCeremony(): crowd first, then a
body-appended full-screen overlay 300ms later (it cannot live in
#pp-overlay — #plugin-career is display:none during playback): dimmed
backdrop, the bronze stamp slamming in with a shine sweep, a 42-piece
canvas confetti burst, click-or-4s dismiss.
- prefers-reduced-motion: chime + fbNotify only, no overlay.
Tests: machine.force commit/dwell-hold/bogus-state, celebrate export +
no-manifest no-op, celebrate-called-once-per-badge, crowd-absent and
crowd-throwing degradation.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
45caa86ab8
commit
d26347981c
@@ -59,6 +59,15 @@
|
||||
candidate = null;
|
||||
lastSwitchAt = -Infinity;
|
||||
},
|
||||
// Commit a state NOW, bypassing stability/dwell (badge ceremony).
|
||||
// Stamping lastSwitchAt makes the dwell window hold the forced
|
||||
// state before the real perf machine can reassert.
|
||||
force(state, nowMs) {
|
||||
if (!CROWD_STATES.includes(state)) return;
|
||||
current = state;
|
||||
candidate = null;
|
||||
lastSwitchAt = nowMs;
|
||||
},
|
||||
// Feed the latest perf state; returns the new crowd state when a
|
||||
// transition commits, else null.
|
||||
update(perfState, nowMs) {
|
||||
@@ -596,6 +605,26 @@
|
||||
if (dev && !_manifest) setManifest(dev);
|
||||
}
|
||||
|
||||
// Badge-ceremony hook (career passports): the crowd erupts NOW — ecstatic
|
||||
// loop bypassing stability/dwell (the dwell window then holds it while
|
||||
// the real perf state waits its turn) plus a cheer. Degrades to a no-op
|
||||
// without a pack / outside the player, like every other entry point.
|
||||
function celebrate() {
|
||||
if (!_venueActive || !_manifest || !_videos[0]) return false;
|
||||
machine.force('ecstatic', now());
|
||||
if (_stingerUntilEnded || _introActive) {
|
||||
// A stinger/intro owns the idle layer (likely the end-of-song
|
||||
// accuracy cheer — the crowd is already reacting); queue the
|
||||
// ecstatic loop for when it ends, same as onPerformanceState.
|
||||
_pendingLoop = 'ecstatic';
|
||||
} else {
|
||||
showLoop('ecstatic', FADE_MS);
|
||||
_lastStingerAt = -Infinity; // a badge earn always gets its cheer
|
||||
playStinger('cheer');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getState() {
|
||||
return {
|
||||
venueActive: _venueActive,
|
||||
@@ -621,6 +650,7 @@
|
||||
setVenueActive,
|
||||
bindRuntime,
|
||||
getState,
|
||||
celebrate,
|
||||
};
|
||||
|
||||
if (root) root.v3VenueCrowd = api;
|
||||
|
||||
Reference in New Issue
Block a user