// Player Menu & Inventory (Zauberer-Beutel & Profil) (function() { const drawer = document.getElementById('playerDrawer'); const drawerBackdrop = document.getElementById('drawerBackdrop'); const bagBtn = document.getElementById('openBagBtn'); const closeBtn = document.getElementById('closeDrawerBtn'); const bagBadge = document.getElementById('bagBadge'); const bagHouseIcon = document.getElementById('bagHouseIcon'); // Tabs const tabBtns = document.querySelectorAll('.drawer-tab-btn'); const tabPanes = document.querySelectorAll('.drawer-tab-pane'); // Item Detail Card const itemDetailBox = document.getElementById('itemDetailBox'); const itemDetailIcon = document.getElementById('itemDetailIcon'); const itemDetailName = document.getElementById('itemDetailName'); const itemDetailDesc = document.getElementById('itemDetailDesc'); const itemDetailActionBtn = document.getElementById('itemDetailActionBtn'); // House selection buttons const houseBtns = document.querySelectorAll('.house-select-btn'); let currentItem = null; let lumosActive = false; window.togglePlayerDrawer = function() { if (!drawer) return; const isOpen = drawer.classList.contains('open'); if (isOpen) { closePlayerDrawer(); } else { openPlayerDrawer(); } }; window.openPlayerDrawer = function(tabName) { if (!drawer) return; drawer.classList.add('open'); if (drawerBackdrop) drawerBackdrop.classList.add('open'); document.body.style.overflow = 'hidden'; if (window.soundFX) window.soundFX.playStoneSlide(); if (tabName) switchTab(tabName); }; window.closePlayerDrawer = function() { if (!drawer) return; drawer.classList.remove('open'); if (drawerBackdrop) drawerBackdrop.classList.remove('open'); document.body.style.overflow = ''; if (window.soundFX) window.soundFX.playStoneSlide(); }; if (bagBtn) bagBtn.addEventListener('click', window.togglePlayerDrawer); if (closeBtn) closeBtn.addEventListener('click', window.closePlayerDrawer); if (drawerBackdrop) drawerBackdrop.addEventListener('click', window.closePlayerDrawer); window.addEventListener('keydown', (e) => { if (e.key === 'Escape' && drawer && drawer.classList.contains('open')) { window.closePlayerDrawer(); } }); // Tab Switching tabBtns.forEach(btn => { btn.addEventListener('click', () => { const target = btn.dataset.tab; switchTab(target); }); }); function switchTab(tabId) { tabBtns.forEach(b => b.classList.toggle('active', b.dataset.tab === tabId)); tabPanes.forEach(p => p.classList.toggle('active', p.id === tabId)); if (window.soundFX) window.soundFX.playBottleClink(); } // Item Selection in Bag const itemSlots = document.querySelectorAll('.inv-item-slot'); itemSlots.forEach(slot => { slot.addEventListener('click', () => { selectItem(slot); }); }); function selectItem(slot) { itemSlots.forEach(s => s.classList.remove('selected')); slot.classList.add('selected'); const itemId = slot.dataset.itemId; const itemName = slot.dataset.itemName; const itemIcon = slot.dataset.itemIcon; const itemDesc = slot.dataset.itemDesc; const actionLabel = slot.dataset.actionLabel; const action = slot.dataset.action; currentItem = { id: itemId, name: itemName, icon: itemIcon, action: action }; if (itemDetailBox) { itemDetailBox.style.display = 'block'; itemDetailIcon.innerText = itemIcon; itemDetailName.innerText = itemName; itemDetailDesc.innerText = itemDesc; itemDetailActionBtn.innerText = actionLabel || "Benutzen ✨"; itemDetailActionBtn.onclick = () => performItemAction(action); } if (window.soundFX) window.soundFX.playBottleClink(); } function performItemAction(action) { if (action === 'lumos') { lumosActive = !lumosActive; let glow = document.getElementById('lumosLightOverlay'); if (!glow) { glow = document.createElement('div'); glow.id = 'lumosLightOverlay'; glow.className = 'lumos-light'; document.body.appendChild(glow); } glow.classList.toggle('active', lumosActive); itemDetailActionBtn.innerText = lumosActive ? "Nox / Erlöschen 🌑" : "Lumos wirken 💡"; if (window.soundFX) window.soundFX.playKeyChime(); showFloatingToast(lumosActive ? "💡 Lumos! Dein Zauberstab erleuchtet die Kammer." : "🌑 Nox! Das Zauberlicht erlischt."); } else if (action === 'read_scroll') { // Open scroll modal window.closePlayerDrawer(); const modalBackdrop = document.getElementById('modalBackdrop'); const modalTitle = document.getElementById('modalTitle'); const modalText = document.getElementById('modalText'); const modalBtn = document.getElementById('modalBtn'); const modalIcon = document.getElementById('modalIcon'); if (modalBackdrop) { modalIcon.innerText = "📜"; modalTitle.innerText = "Snapes Logik-Rätsel"; modalText.innerHTML = `
"Gefahr liegt vor euch, die Rettung zurück,
Zwei von uns helfen euch, habt ihr das Glück,
Eine von sieben führt euch hindurch,
Eine bringt den, der sie trinkt, sicher zurück,
Zwei von ihnen enthalten nur Brennnesselwein,
Drei sind tödlich, schenkt ihr sie ein.
Wählt oder bleibt auf ewig hier stehen,
Vier Hinweise helfen euch, alles zu sehen..."


1. Links neben jedem Wein steht immer Gift.
2. Die Enden sind verschieden, keines führt nach vorn.
3. Weder Zwerg noch Riese birgt Gift.
4. Zweite von links & zweite von rechts schmecken gleich!
`; modalBtn.innerText = "Verstanden ➔"; modalBtn.onclick = () => modalBackdrop.classList.remove('show'); modalBackdrop.classList.add('show'); } } else if (action === 'broom_polish') { if (window.soundFX) window.soundFX.playWhoosh(); showFloatingToast("🧹 Der Nimbus 2000 glänzt wie neu. Die Zweige sind perfekt gestutzt!"); } else if (action === 'spark_wand') { if (window.soundFX) window.soundFX.playWhoosh(); showFloatingToast("⚡ Magische Funken sprühen aus deiner Zauberstabspitze!"); } else if (action === 'read_recipe') { window.closePlayerDrawer(); const modalBackdrop = document.getElementById('modalBackdrop'); const modalTitle = document.getElementById('modalTitle'); const modalText = document.getElementById('modalText'); const modalBtn = document.getElementById('modalBtn'); const modalIcon = document.getElementById('modalIcon'); if (modalBackdrop) { if (modalIcon) modalIcon.innerText = "📜"; if (modalTitle) modalTitle.innerText = "Snapes Felix-Felicis-Rezeptur"; if (modalText) { modalText.innerHTML = `
»Felix Felicis ist kein Trank für Scharlatane. Wer die Maße missachtet, verdirbt den Kessel augenblicklich:«

🐉 Drachenblut: "So viele Tropfen wie Köpfe des schlafenden Fluffy (3 Tropfen)"
🌿 Alraunenblatt: "Harrys treue Gefährten am Gryffindor-Tisch (Ron & Hermine = 2 Blätter)"
✨ Sternenstaub: "Der eine Siegelring des Alchemisten (1 Prise)"

🥄 Rühr-Anweisung: "Zuerst 3 Sekunden gleichmäßig linksherum rühren (↺), danach 3 Sekunden rechtsherum (↻)! Ein Hektiker schlägt Schaum, ein Zauderer lässt den Sud erstarren!"
`; } if (modalBtn) { modalBtn.innerText = "Rezeptur einprägen ➔"; modalBtn.onclick = () => modalBackdrop.classList.remove('show'); } modalBackdrop.classList.add('show'); } } else if (action === 'lucky_aura') { if (window.soundFX) window.soundFX.playMagicSuccess(); showFloatingToast("🍀 Ein Tropfen Felix Felicis! Eine Welle goldenen Glücks erfüllt deine Adern!"); } else if (action === 'inspect_key') { if (window.soundFX) window.soundFX.playKeyChime(); showFloatingToast("🗝️ Die Gravur der vier Gründer leuchtet warm auf: 'Hogwarts, Hogwarts, warzenschweinig alt...'"); } else if (action === 'poke_jar') { if (window.soundFX) window.soundFX.playWhoosh(); showFloatingToast("🧚 *Klopf-Klopf!* Der blaue Wichtel im Glas verzieht frech das Gesicht!"); } else if (action === 'examine_key') { if (window.soundFX) window.soundFX.playKeyChime(); showFloatingToast("🗝️ Der alte Silberschlüssel ist schwer und trägt Spuren vergangener Kämpfe."); } else if (action === 'feel_power') { if (window.soundFX) window.soundFX.playMagicSuccess(); showFloatingToast("💎 Eine unendliche Wärme durchströmt deine Finger. Der Stein schützt die Welt!"); } } // House selection houseBtns.forEach(btn => { btn.addEventListener('click', async () => { const house = btn.dataset.house; try { const res = await fetch('/api/player/house', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ house: house }) }); const data = await res.json(); if (data.success) { houseBtns.forEach(b => b.classList.toggle('active', b.dataset.house === house)); if (bagHouseIcon) bagHouseIcon.innerText = data.house.icon; document.documentElement.style.setProperty('--house-accent', data.house.accent); if (window.soundFX) window.soundFX.playMagicSuccess(); showFloatingToast(`Du gehörst nun stolz zum Haus ${data.house.name} ${data.house.icon}!`); } } catch (e) { console.error(e); } }); }); // Toast Notification window.showFloatingToast = function(msg) { let toast = document.getElementById('floatingEscapeToast'); if (!toast) { toast = document.createElement('div'); toast.id = 'floatingEscapeToast'; toast.className = 'escape-toast'; document.body.appendChild(toast); } toast.innerHTML = msg; toast.classList.add('show'); clearTimeout(toast._timeout); toast._timeout = setTimeout(() => { toast.classList.remove('show'); }, 3500); }; window.notifyNewItem = function(item) { if (!item) return; if (bagBadge) { let count = parseInt(bagBadge.innerText, 10) || 0; bagBadge.innerText = count + 1; bagBadge.classList.add('pulse'); setTimeout(() => bagBadge.classList.remove('pulse'), 2000); } if (window.soundFX) window.soundFX.playMagicSuccess(); window.showFloatingToast(`🎒 Neuer Gegenstand im Beutel: ${item.icon} ${item.name}!`); }; // Confetti Animation Controller let confettiAnimId = null; function runVictoryConfetti() { const canvas = document.getElementById('victoryConfettiCanvas'); if (!canvas) return; const ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const colors = ['#ffd700', '#f39c12', '#e74c3c', '#3498db', '#2ecc71', '#9b59b6', '#ffffff']; const particles = []; for (let i = 0; i < 90; i++) { particles.push({ x: Math.random() * canvas.width, y: Math.random() * -canvas.height * 0.5, w: Math.random() * 9 + 5, h: Math.random() * 5 + 3, vx: (Math.random() - 0.5) * 4, vy: Math.random() * 3 + 2.5, color: colors[Math.floor(Math.random() * colors.length)], angle: Math.random() * Math.PI * 2, vAngle: (Math.random() - 0.5) * 0.15, shape: Math.random() > 0.4 ? 'rect' : 'star' }); } let start = Date.now(); if (confettiAnimId) cancelAnimationFrame(confettiAnimId); function drawConfetti() { ctx.clearRect(0, 0, canvas.width, canvas.height); const elapsed = (Date.now() - start) / 1000; particles.forEach(p => { p.x += p.vx; p.y += p.vy; p.angle += p.vAngle; ctx.save(); ctx.translate(p.x, p.y); ctx.rotate(p.angle); ctx.fillStyle = p.color; if (p.shape === 'star') { ctx.beginPath(); ctx.arc(0, 0, p.w * 0.45, 0, Math.PI * 2); ctx.fill(); } else { ctx.fillRect(-p.w / 2, -p.h / 2, p.w, p.h); } ctx.restore(); if (p.y > canvas.height + 20) { p.y = -20; p.x = Math.random() * canvas.width; } }); if (elapsed < 8) { confettiAnimId = requestAnimationFrame(drawConfetti); } else { ctx.clearRect(0, 0, canvas.width, canvas.height); } } confettiAnimId = requestAnimationFrame(drawConfetti); } // Unified Spectacular Victory Celebration Overlay window.showChamberVictory = function(config) { const modal = document.getElementById('victoryCelebrationModal'); if (!modal) { // Fallback to standard modal if celebration overlay missing if (window.modalTitle) window.modalTitle.innerText = config.title; if (window.modalText) window.modalText.innerHTML = config.storyText; if (window.modalBackdrop) window.modalBackdrop.classList.add('show'); return; } const badge = document.getElementById('vicChamberBadge'); const title = document.getElementById('vicTitle'); const statsBox = document.getElementById('vicStatsBox'); const itemBox = document.getElementById('vicItemRewardBox'); const rewardIcon = document.getElementById('vicRewardIcon'); const rewardName = document.getElementById('vicRewardName'); const rewardDesc = document.getElementById('vicRewardDesc'); const storyBox = document.getElementById('vicStoryBox'); const nextBtn = document.getElementById('vicNextBtn'); if (badge) badge.innerText = config.chamberBadge || 'Kammer Gemeistert'; if (title) title.innerText = config.title || 'Hervorragend!'; if (statsBox) { statsBox.innerHTML = config.statsHtml || ''; statsBox.style.display = config.statsHtml ? 'flex' : 'none'; } if (storyBox) storyBox.innerHTML = config.storyText || ''; if (config.item && itemBox) { itemBox.style.display = 'flex'; if (rewardIcon) rewardIcon.innerText = config.item.icon || '✨'; if (rewardName) rewardName.innerText = config.item.name || ''; if (rewardDesc) rewardDesc.innerText = config.item.desc || ''; window.notifyNewItem(config.item); } else if (itemBox) { itemBox.style.display = 'none'; } if (nextBtn) { nextBtn.href = config.nextUrl || '/'; nextBtn.innerHTML = config.nextBtnText || '➔ Weiter zur nächsten Kammer ✨'; } // Trigger Audio, Haptic & Particle Celebration if (window.soundFX) window.soundFX.playMagicSuccess(); if (window.navigator && window.navigator.vibrate) { window.navigator.vibrate([60, 50, 80, 50, 180]); } modal.classList.add('show'); runVictoryConfetti(); }; // Auto-select first item if available if (itemSlots.length > 0) { selectItem(itemSlots[0]); } })();