// [e29 coach] Start screen: choose Look A / Look B before playing. Remembers the choice (via MuseLooks,
// localStorage 'muse-engine-29.look'). Skip with ?start=0 (used by tests).
(function () {
var E = window.MuseEngine29, M = window.MuseLooks;
var stage = document.getElementById('stage') || document.body;
if (!E || !M) return;
if (/[?&](start=0|skipstart=1)/.test(location.search)) return;
function rgb(c) { return c ? 'rgb(' + c.map(function (v) { return Math.round(Math.max(0, Math.min(1, v)) * 255); }).join(',') + ')' : 'transparent'; }
function swatches(p) {
var env = p.env || {}, n = p.nodes || {}, ch = p.characters || {};
function partCol(c) { return c && c.parts && c.parts[0] ? c.parts[0].color : (c && c.color); }
return [env.dayClear, n.ground && n.ground.color, n.crate0 && n.crate0.color, n.pier && n.pier.color,
partCol(ch.hostile) || [0.9, 0.2, 0.2], partCol(ch.patrol) || [0.95, 0.65, 0.15]]
.map(function (c) { return ''; }).join('');
}
var ov = document.createElement('div');
ov.className = 'e29-overlay show'; ov.id = 'e29-start';
function esc(t) { return String(t == null ? '' : t).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); }
function render() {
var act = M.active();
var cards = M.list().map(function (l) {
var p = M.get(l.id) || {};
return '
Look ' + esc(l.id) + ' · ' + esc(l.name) +
'
' + esc(l.blurb || '') + '
' + swatches(p) + '
';
}).join('');
ov.innerHTML = 'Muse Engine 31 · Animated Characters
' +
'
Phase 31: load your own animated character (skinned FBX / GLB) as the enemies, and your own scene (FBX / GLB) as the level, from the config panel (Tab). Clips are mapped by name (idle / walk / run / shoot / death), headshots count triple. Pick a look — gameplay, colliders and hitboxes are identical in both. ' +
'Change it any time with L or in the config panel (Tab).
' +
'
Choose a look
' + cards + '
' +
'
';
ov.querySelectorAll('.e29-look').forEach(function (el) {
el.onclick = function () { M.setActive(el.getAttribute('data-id')); render(); };
});
ov.querySelector('#e29-play').onclick = play;
}
function play() {
ov.classList.remove('show');
window.removeEventListener('keydown', onKey, true);
E.setBlocked(false);
E.flashHint('LOOK ' + M.active() + ' · click to aim · Tab = config · L = look');
var c = document.getElementById('muse-canvas'); if (c) c.focus();
}
function onKey(e) {
if (!ov.classList.contains('show')) return;
var ids = M.list().map(function (l) { return l.id; });
var i = ids.indexOf(M.active());
if (e.code === 'Enter' || e.code === 'NumpadEnter') { e.preventDefault(); play(); }
else if (e.code === 'ArrowRight' || e.code === 'ArrowLeft') { e.preventDefault(); M.setActive(ids[(i + (e.code === 'ArrowRight' ? 1 : ids.length - 1)) % ids.length]); render(); }
else if (/^Digit[1-9]$/.test(e.code) && ids[+e.code.slice(5) - 1]) { M.setActive(ids[+e.code.slice(5) - 1]); render(); }
else if (e.code === 'KeyL') { e.preventDefault(); M.next(); render(); }
e.stopPropagation();
}
window.addEventListener('keydown', onKey, true);
stage.appendChild(ov);
render();
E.setBlocked(true);
window.E29Start = { show: function () { ov.classList.add('show'); window.addEventListener('keydown', onKey, true); render(); E.setBlocked(true); }, play: play };
})();