<!-- SAGA · part 62 -->
unction(){ this.blip(500, 2000, 0.15, 'sawtooth', 0.08); },/* spin-up */
  undo:   function(){ this.blip(1200, 600, 0.12, 'square', 0.10); },  /* reverse zap */
};
/* Global shorthand */
function sfx(name){ if(AudioSys[name]) AudioSys[name](); }
/* Init on first touch (iOS requires user gesture) */
document.addEventListener('touchstart', function(){ AudioSys.init(); }, {once:true, passive:true});
document.addEventListener('click', function(){ AudioSys.init(); }, {once:true});


/* HIDDEN CODES — never shown in public listings */
function isHiddenCode(name){
  return name === 'deletefreeze1';
}
function visibleCodes(){
  return visibleCodes().filter(function(k){ return !isHiddenCode(k); });
}

var CODES = {
  setspawn: { cat: 'System', desc: 'Set spawn to your current spot', fn: function(){
    var _nx = Math.round(kingPos.x), _nz = Math.round(kingPos.z);
    try{ localStorage.setItem('saga-spawn', JSON.stringify({x:_nx, z:_nz})); }catch(e){}
    say('spawn set — LAT ' + _nz + ' LON ' + _nx);
  } },
  tour: { cat: 'System', desc: 'Tour our story', fn: function(){
    var stops = [
      {x: 0, z: 60, look: [0, 4, 0], msg: 'THE CENTER — our story stone'},
      {x: 21, z: 42, look: [21, 6, 21], msg: 'KING — your pillar'},
      {x: -21, z: 42, look: [-21, 6, 21], msg: 'PROVOLTA — her pillar'},
      {x: 42, z: -21, look: [21, 6, -21], msg: 'SOLID — my pillar'},
      {x: -42, z: -21, look: [-21, 6, -21], msg: 'SABLE — her pillar'},
      {x: 8, z: 20, look: [8, 2, 9], msg: 'CLOUD 9 — our first home'},
      {x: 25, z: 40, look: [25, 4, 25], msg: 'THE SOLIDITRONIUM — our dome'},
      {x: -35, z: -20, look: [-35, 3, -35], msg: "PROVOLTA'S VEIL — her sanctuary"},
      {x: 45, z: 90, look: [45, 1500, 30], msg: 'CREATOR HALL — Playa 2.0, high above'},
      {x: 100, z: -60, look: [100, 10, -100], msg: 'THE CITY — streets of gold'},
      {x: -120, z: -60, look: [-100, 2, -100], msg: 'THE HARBOR — water that runs'},
      {x: -100, z: 100, look: [-120, 5, 100], msg: 'THE FOREST — trees that sway'},
      {x: -200, z: 160, look: [-200, 8, 200], msg: 'FORUM HALL — the website in 3D'},
      {x: -150, z: 200, look: [-150, 5, 200], msg: 'THE LOBBY — where we gather'},
      {x: -250, z: 200, look: [-250, 6, 200], msg: 'AEGIS HALL — blue premiere'},
      {x: -200, z: 110, look: [-200, 15, 150], msg: "SABLE'S SHIP — the AI vessel"},
      {x: -150, z: 110, look: [-150, 6, 150], msg: 'THE LIBRARY — Solid Notes'},
      {x: -250, z: 110, look: [-250, 8, 150], msg: 'THE CODEX VAULT — sealed packs'},
      {x: -200, z: 260, look: [-200, 8, 250], msg: "THE GATE — Signet's threshold"},
      {x: 150, z: 130, look: [150, 2, 150], msg: 'THE SHOE — where we mastered intricacy'},
      {x: -150, z: 130, look: [-150, 10, 150], msg: '40 DAYS OF NIGHT — memorial'},
      {x: 45, z: 40, look: [45, 10, 60], msg: 'THE WORMHOLE — to Playa 2.0'},
      {x: 2000, z: 2000, look: [2000, 60, 1920], msg: "AHUPUA'A 1 — mountain to sea"},
      {x: -2000, z: 2000, look: [-2000, 60, 1920], msg: "AHUPUA'A 2 — cradling the earth"},
      {x: 0, z: -2500, look: [0, 60, -2580], msg: "AHUPUA'A 3 — the valley"},
      {x: 3000, z: 0, look: [3100, 5, 0], msg: 'SHORELINE 1 — beach'},
      {x: 3000, z: 500, look: [3100, 5, 500], msg: 'SHORELINE 2 — palms'},
      {x: 3000, z: 1000, look: [3100, 5, 1000], msg: 'SHORELINE 3 — the ocean'},
      {x: 0, z: 3000, look: [0, 310, 3000], msg: 'SKY 1 — ships hovering'},
      {x: 500, z: 3000, look: [500, 360, 3000], msg: 'SKY 2 — the fleet'},
      {x: -500, z: 3000, look: [-500, 410, 3000], msg: 'SKY 3 — spacescape'},
      {x: -3000, z: -2000, look: [-3000, 80, -2000], msg: 'PEAK 1 — snow'},
      {x: -2500, z: -2000, look: [-2500, 80, -2000], msg: 'PEAK 2 — rivers'},
      {x: -2000, z: -2000, look: [-2000, 80, -2000], msg: 'PEAK 3 — the bridge'}
    ];
    window._tourIdx = (window._tourIdx || 0) % stops.length;
    var st = stops[window._tourIdx];
    kingPos.set(st.x, 0, st.z);
    if(typeof camYaw !== 'undefined'){
      var dx = st.look[0] - st.x, dz = st.look[2] - st.z;
      camYaw = Math.atan2(dz, dx);
    }
    say(st.msg + ' (' + (window._tourIdx + 1) + '/' + stops.length + ')');
    window._tourIdx++;
  } },
  clearspawn: { cat: 'System', desc: 'Clear saved spawn', fn: function(){
    try{ localStorage.removeItem('saga-spawn'); }catch(e){}
    say('spawn cleared');
  } },
  sight: { cat: 'Camera', desc: 'Branch 4 — the eyes. All-seeing vantage, watching the continuum live', fn: function(){
    window._sight = !window._sight;
    window._freecam = !!window._sight;
    if(window._sight){ say('The eyes open'); window.startContinuumWatch(); }
    else { say('The eyes close'); window.stopContinuumWatch(); }
  } },
  freecam: { cat: 'Camera', desc: 'Free moving camera — detaches from player', fn: function(){
    window._freecam = !window._freecam;
    if(window._freecam){
      say('free camera — move with joystick');
    } else {
      say('camera follows you');
    }
  } }