// [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 + '
' + '
1 / 2 or ← → to choose · Enter to play · your choice is remembered' + '
'; 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 }; })();