/* state.js — Zustand ST + localStorage + Reset */ /* ══════════════════════════════════════════════ STATE ══════════════════════════════════════════════ */ const ST={ devName:'',name:'',desc:'',figure:'',figure2:'',background:'', playerCount:1, fieldCount:10,fields:Array(10).fill(null), storyItems:[],quizData:[], rules:{movement:'dice',fail:'lives',lives:'3',pts:'10'}, consequences:{win:'nothing',winVal:2,lose:'nothing',loseVal:1,winPts:10,losePts:5}, mgSettings:{}, worldSeed:0, worldLocked:false, shareCode:'', highestStep:0, }; try{ const sv=JSON.parse(localStorage.getItem('gameConfig')||'{}'); if(sv.devName)ST.devName=sv.devName; if(sv.name)ST.name=sv.name;if(sv.desc)ST.desc=sv.desc; if(sv.figure)ST.figure=sv.figure;if(sv.figure2)ST.figure2=sv.figure2;if(sv.background)ST.background=sv.background; if(sv.playerCount===1||sv.playerCount===2)ST.playerCount=sv.playerCount; if(sv.fieldCount)ST.fieldCount=sv.fieldCount; if(sv.fields){ST.fields=sv.fields;while(ST.fields.length>>0; if(sv.worldLocked)ST.worldLocked=!!sv.worldLocked; if(sv.shareCode)ST.shareCode=String(sv.shareCode); if(sv.highestStep)ST.highestStep=sv.highestStep; }catch(e){} let cur=0; function save(){ try { localStorage.setItem('gameConfig',JSON.stringify({ devName:ST.devName,name:ST.name,desc:ST.desc,figure:ST.figure,figure2:ST.figure2,playerCount:ST.playerCount,background:ST.background, fieldCount:ST.fieldCount,fields:ST.fields,storyItems:ST.storyItems, quizData:ST.quizData,rules:ST.rules,consequences:ST.consequences,mgSettings:ST.mgSettings,worldSeed:ST.worldSeed,worldLocked:ST.worldLocked,shareCode:ST.shareCode,highestStep:ST.highestStep, })); } catch(e) { if(e.name==='QuotaExceededError'){ appAlert('Speicher voll. Bitte altes Spiel löschen.'); } } showSaveIndicator(); // Note: code update is triggered by input/change listeners, not here } function showSaveIndicator(){ const el=document.getElementById('saveIndicator'); if(!el)return; el.style.opacity='1'; clearTimeout(el._hideTimer); el._hideTimer=setTimeout(()=>{el.style.opacity='0';},2000); } /* ── App-Dialog (ersetzt natives confirm/alert) ── */ let _appOk=null; function appConfirm(message, onOk, opts){ opts=opts||{}; const dlg=document.getElementById('appDialog'); if(!dlg){ if(confirm(message)&&onOk)onOk(); return; } document.getElementById('appDialogIcon').textContent = opts.icon || (opts.danger?'⚠️':'❓'); document.getElementById('appDialogMsg').textContent = message; const yes=document.getElementById('appDialogYes'); const no=document.getElementById('appDialogNo'); yes.textContent = opts.okText || 'Ja'; no.textContent = opts.cancelText || 'Abbrechen'; yes.classList.toggle('danger', !!opts.danger); no.style.display = opts.noCancel ? 'none' : ''; _appOk = onOk || null; dlg.classList.add('open'); } function appAlert(message, onOk, opts){ appConfirm(message, onOk, Object.assign({noCancel:true, okText:'OK', icon:'ℹ️'}, opts||{})); } function appDialogOk(){ document.getElementById('appDialog').classList.remove('open'); const fn=_appOk; _appOk=null; if(fn){ try{ fn(); }catch(e){ console.error(e); } } } function appDialogCancel(){ document.getElementById('appDialog').classList.remove('open'); _appOk=null; } function resetAll(){ appConfirm('Wirklich alles zurücksetzen?\n\nAlle Eingaben gehen verloren!', ()=>{ localStorage.removeItem('gameConfig'); localStorage.removeItem('testFeedback'); location.reload(); }, {danger:true, okText:'Zurücksetzen', icon:'🗑️'}); }