From 3d472c3c8f0d16f6b50714dab7f63885dbcae1ff Mon Sep 17 00:00:00 2001 From: netim Date: Wed, 17 Jun 2026 18:20:21 +0200 Subject: [PATCH] Quests & Tracker spoilerfrei im Spielmodus + Live-Sync der Schlucke - Quests- und Tracker-Tab auch im Spieler-Modus sichtbar; Spoiler (NPC/Komplize, Belohnungen, Beschreibungen, Details, Notizen) per .gm-only nur im Spielleiter-Modus - pollState() gleicht alle 3s Schlucke/Wuerfel/Quests ueber offene Instanzen ab; Notizen werden beim Tippen nicht ueberschrieben - Start: Quests erst nach Server-State bauen (Erledigt-Status korrekt) Co-Authored-By: Claude Opus 4.8 --- index.html | 79 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/index.html b/index.html index 531408a..e25fb8f 100644 --- a/index.html +++ b/index.html @@ -895,6 +895,9 @@ body:not(.gm-mode) .nav-tab.gm-tab { display: none; } body.gm-mode .nav-tab.player-tab { display: none; } + /* Spoiler-Inhalte nur im Spielleiter-Modus zeigen */ + body:not(.gm-mode) .gm-only { display: none !important; } + /* Dezenter GM-Hinweis-Streifen */ .gm-banner { display: none; @@ -945,10 +948,10 @@ - + - + @@ -1112,9 +1115,11 @@
Die Quests
-
Aufgaben der NPCs — Klicken zum Aufklappen
+
Die Prüfungen für Wendl
-
+

Im Spielleiter-Modus mit allen Details — Spieler sehen nur die Quest-Namen & den Fortschritt.

+ +
Farbcode
  • AKT 1 Leichte Prüfungen
  • @@ -1365,7 +1370,7 @@
    0/6
    Würfel 🎲
    - Ab 6 → Kampf frei · im Intro-Tab verwalten + Ab 6 → Kampf frei · im Intro-Tab verwalten
@@ -1375,14 +1380,14 @@
-
+
Notizen
-
-
+
@@ -1561,7 +1566,39 @@ async function syncState() { if (s.questDone) s.questDone.forEach((v, i) => { if (i < questDone.length) questDone[i] = v; }); document.getElementById('drinkCount').textContent = drinks; const ta = document.getElementById('notes'); - if (ta && typeof s.notesText === 'string') ta.value = s.notesText; + // Notizen nicht überschreiben, während jemand tippt + if (ta && document.activeElement !== ta && typeof s.notesText === 'string') ta.value = s.notesText; +} + +// Live-Sync: zieht regelmäßig den Server-State und gleicht offene Instanzen ab +// (Schlucke, Würfel, Quests synchron über mehrere Geräte hinweg). +let pollTimer = null; +async function pollState() { + const data = await apiGet('/game'); + if (!data || !data.state) return; + const s = data.state; + let itemsChanged = false, questsChanged = false; + if (s.drinks !== undefined && s.drinks !== drinks) { + drinks = s.drinks; + const dc = document.getElementById('drinkCount'); + if (dc) dc.textContent = drinks; + } + if (s.itemCollected) s.itemCollected.forEach((v, i) => { + if (i < itemCollected.length && itemCollected[i] !== v) { itemCollected[i] = v; itemsChanged = true; } + }); + if (s.questDone) s.questDone.forEach((v, i) => { + if (i < questDone.length && questDone[i] !== v) { questDone[i] = v; questsChanged = true; } + }); + if (itemsChanged) { + for (let i = 0; i < itemCollected.length; i++) { + const slot = document.getElementById('inv-' + i); + if (slot) slot.classList.toggle('collected', itemCollected[i]); + } + } + if (questsChanged) buildQuests(); + if (itemsChanged || questsChanged) updateQuestStatus(); + const ta = document.getElementById('notes'); + if (ta && document.activeElement !== ta && typeof s.notesText === 'string' && ta.value !== s.notesText) ta.value = s.notesText; } // State zum Server speichern @@ -1704,14 +1741,16 @@ function toggleMode() { } } -function startApp() { +async function startApp() { document.getElementById('cover').style.display = 'none'; document.getElementById('app').style.display = 'block'; - buildQuests(); buildDice(); - syncState(); - syncSpieler(); - updateQuestStatus(); + await syncState(); // erst Server-State holen … + await syncSpieler(); + buildQuests(); // … dann Quests mit korrektem Erledigt-Status bauen + refreshUI(); + // Live-Sync starten (nur einmal, auch wenn startApp doppelt läuft) + if (!pollTimer) pollTimer = setInterval(pollState, 3000); } // ═══════════════════════════════════════════ @@ -1728,20 +1767,20 @@ function buildQuests() { card.innerHTML = ` ${q.badgeLabel}
${q.name}
-
NPC: ${q.holder}
-
${q.desc}
-
+
NPC: ${q.holder}
+
${q.desc}
+
${q.success} ${q.fail}
-
${q.details}

+
${q.details}

-
▼ Aufklappen für Details
`; +
▼ Aufklappen für Details
`; card.addEventListener('click', () => toggleExpand(i)); grid.appendChild(card); }); @@ -1798,7 +1837,7 @@ function updateQuestStatus() { color:${questDone[i]?'#2a5a1a':'#5a3a10'};"> ${questDone[i] ? '✓' : '○'} ${q.name} - ${q.item} + ${q.item}
`).join(''); } // ═══════════════════════════════════════════