// Zaubertrank-Brauküche (Felix Felicis Potion Brewing Engine: Riddles, Two-Way Stirring & Snape's Wrath) (function() { let currentStep = 1; // 1: Dosage, 2: Stirring, 3: Heat, 4: Done // Step 1: Ingredient Doses const doses = { dragon: 0, mandrake: 0, star: 0 }; const targetDoses = { dragon: 3, // Fluffy's 3 heads mandrake: 2, // Harry's companions Ron & Hermione star: 1 // The Alchemist's 1 ring }; // DOM Elements const stepBadge = document.getElementById('stepBadge'); const stepInstruction = document.getElementById('stepInstruction'); const stepSubtext = document.getElementById('stepSubtext'); const step1Wrapper = document.getElementById('step1Wrapper'); const doseValDragon = document.getElementById('doseValDragon'); const doseValMandrake = document.getElementById('doseValMandrake'); const doseValStar = document.getElementById('doseValStar'); // SVG Elements const gradStop1 = document.getElementById('gradStop1'); const gradStop2 = document.getElementById('gradStop2'); const gradStop3 = document.getElementById('gradStop3'); const liquidSurface = document.getElementById('liquidSurface'); const stirSpoon = document.getElementById('stirSpoon'); const dropItemAnim = document.getElementById('dropItemAnim'); // Step 2: Stirring Controls const stirPanel = document.getElementById('stirPanel'); const stirPhaseLabel = document.getElementById('stirPhaseLabel'); const stirIndicatorBar = document.getElementById('stirIndicatorBar'); const stirTimerVal = document.getElementById('stirTimerVal'); const btnStirLeft = document.getElementById('btnStirLeft'); const btnStirRight = document.getElementById('btnStirRight'); // Step 3: Heat Controls const heatPanel = document.getElementById('heatPanel'); const tempIndicator = document.getElementById('tempIndicator'); const heatTimerSpan = document.getElementById('heatTimer'); const bellowsBtn = document.getElementById('bellowsBtn'); // Success & Modals const successPanel = document.getElementById('successPanel'); const snapeModal = document.getElementById('snapeReprimandModal'); const snapeText = document.getElementById('snapeReprimandText'); const riddleModal = document.getElementById('recipeRiddleModal'); // Snape Insult Repository const snapeQuotes = [ "»Kläglich. Sogar ein Bergtroll mit verbundenen Augen hätte die Mengenangaben treffender ergründet.«", "»Offenbar mangelt es Ihnen nicht nur an magischem Talent, sondern auch an elementarem Leseverständnis.«", "»Ein weiterer solcher Fehltritt, und dieser Kessel fliegt Ihnen um die Ohren wie Longbottoms letzte Missetat.«", "»Haben Sie Ihre Brille verlegt, oder ist das schlichte Ignoranz gegenüber den feinsten Künsten des Zaubertrankbrauens?«", "»3 Drachenblut, 2 Alraunen, 1 Sternenstaub – ist das für Ihr Denkvermögen tatsächlich zu hoch gegriffen?«" ]; function getRandomSnapeQuote() { return snapeQuotes[Math.floor(Math.random() * snapeQuotes.length)]; } // Modal helpers window.openRecipeRiddleModal = function() { if (riddleModal) riddleModal.classList.add('show'); if (window.soundFX) window.soundFX.playStoneSlide(); }; window.closeRecipeRiddleModal = function() { if (riddleModal) riddleModal.classList.remove('show'); if (window.soundFX) window.soundFX.playStoneSlide(); }; window.triggerSnapeInsult = function(customQuote) { if (snapeText) snapeText.innerText = customQuote || getRandomSnapeQuote(); if (snapeModal) snapeModal.classList.add('show'); // Turn cauldron murky black with foul smoke if (gradStop1 && gradStop2 && gradStop3) { gradStop1.setAttribute('stop-color', '#2d2d2d'); gradStop2.setAttribute('stop-color', '#1a1a1a'); gradStop3.setAttribute('stop-color', '#0d0d0d'); } if (window.soundFX) window.soundFX.playWhoosh(); if (window.navigator && window.navigator.vibrate) window.navigator.vibrate([60, 40, 100]); }; window.closeSnapeModal = function() { if (snapeModal) snapeModal.classList.remove('show'); // Reset liquid back to clean starting emerald green if (gradStop1 && gradStop2 && gradStop3) { gradStop1.setAttribute('stop-color', '#2ecc71'); gradStop2.setAttribute('stop-color', '#16a085'); gradStop3.setAttribute('stop-color', '#0b3b30'); } if (window.soundFX) window.soundFX.playStoneSlide(); }; // Step 1: Ingredient Dosage Adjustments window.adjustDose = function(type, delta) { if (currentStep !== 1) return; doses[type] = Math.max(0, Math.min(9, doses[type] + delta)); if (type === 'dragon' && doseValDragon) doseValDragon.innerText = doses.dragon; if (type === 'mandrake' && doseValMandrake) doseValMandrake.innerText = doses.mandrake; if (type === 'star' && doseValStar) doseValStar.innerText = doses.star; if (window.soundFX) window.soundFX.playBottleClink(); if (window.navigator && window.navigator.vibrate) window.navigator.vibrate(25); }; window.verifyAndMixIngredients = function() { if (currentStep !== 1) return; // Check if correct: 3 Dragon, 2 Mandrake, 1 Star const isCorrect = (doses.dragon === targetDoses.dragon && doses.mandrake === targetDoses.mandrake && doses.star === targetDoses.star); if (!isCorrect) { // Wrong dosage! Trigger Snape's rebuke! window.triggerSnapeInsult(); return; } // Correct! Play dropping animations and proceed to Step 2 if (dropItemAnim) { dropItemAnim.textContent = '🐉🌿✨'; dropItemAnim.style.display = 'block'; dropItemAnim.style.animation = 'ingredientDropAnim 0.7s ease-out forwards'; setTimeout(() => { dropItemAnim.style.display = 'none'; }, 750); } if (liquidSurface) { liquidSurface.style.transform = 'scale(1.08)'; setTimeout(() => liquidSurface.style.transform = 'scale(1)', 300); } if (window.soundFX) window.soundFX.playBottleClink(); if (window.navigator && window.navigator.vibrate) window.navigator.vibrate([40, 80]); setTimeout(startStep2, 700); }; // Step 2: Two-Way Stirring with Tempo Bar let stirPhase = 'left'; // 'left' then 'right' let phaseTimer = 0.0; let stirTempo = 25; // 0 to 100% let stirLoopInterval = null; let wildTempoTime = 0.0; function startStep2() { currentStep = 2; stirPhase = 'left'; phaseTimer = 0.0; stirTempo = 25; wildTempoTime = 0.0; stepBadge.innerText = "Schritt 2: Rhythmisches Rühren"; stepInstruction.innerText = "Rühre den Sud gleichmäßig im Takt!"; stepSubtext.innerText = "Laut Rezept: Zuerst 3 Sekunden LINKS (↺), danach 3 Sekunden RECHTS (↻)!"; if (step1Wrapper) step1Wrapper.style.display = 'none'; if (stirPanel) stirPanel.style.display = 'flex'; if (stirSpoon) stirSpoon.style.display = 'block'; // Set liquid to rich amethyst purple if (gradStop1 && gradStop2 && gradStop3) { gradStop1.setAttribute('stop-color', '#9b59b6'); gradStop2.setAttribute('stop-color', '#8e44ad'); gradStop3.setAttribute('stop-color', '#341f47'); } updateStirUI(); if (window.soundFX) window.soundFX.playStoneSlide(); // Start tempo decay loop if (stirLoopInterval) clearInterval(stirLoopInterval); stirLoopInterval = setInterval(updateStirLoop, 50); } function updateStirUI() { if (stirPhaseLabel) { if (stirPhase === 'left') { stirPhaseLabel.innerText = "↺ LINKS (Phase 1)"; stirPhaseLabel.style.color = "#4cc9f0"; if (btnStirLeft) btnStirLeft.classList.add('active-target'); if (btnStirRight) btnStirRight.classList.remove('active-target'); } else { stirPhaseLabel.innerText = "↻ RECHTS (Phase 2)"; stirPhaseLabel.style.color = "#ffd700"; if (btnStirLeft) btnStirLeft.classList.remove('active-target'); if (btnStirRight) btnStirRight.classList.add('active-target'); } } if (stirTimerVal) stirTimerVal.innerText = phaseTimer.toFixed(1); } window.stirTap = function(direction) { if (currentStep !== 2) return; // Check if wrong direction tapped! if (direction !== stirPhase) { const wrongDirQuote = (stirPhase === 'left') ? "»Linksherum, sagte ich! Verwechseln Sie die Drehrichtungen wie Mr. Finnigan?«" : "»Nun rechtsherum! Hören Sie überhaupt zu oder träumen Sie von Schokofröschen?«"; window.triggerSnapeInsult(wrongDirQuote); phaseTimer = 0.0; stirTempo = 25; updateStirUI(); return; } // Correct direction tap: give a rhythmic boost stirTempo = Math.min(100, stirTempo + 13); if (window.soundFX) window.soundFX.playBottleClink(); if (window.navigator && window.navigator.vibrate) window.navigator.vibrate(20); // Animate spoon if (stirSpoon) { stirSpoon.classList.remove('stirring-active'); void stirSpoon.offsetWidth; stirSpoon.classList.add('stirring-active'); } }; function updateStirLoop() { if (currentStep !== 2) return; // Continuous tempo decay stirTempo = Math.max(0, stirTempo - 1.1); if (stirIndicatorBar) stirIndicatorBar.style.width = stirTempo + '%'; // Check if in green zone (40% to 75%) if (stirTempo >= 40 && stirTempo <= 75) { phaseTimer += 0.05; wildTempoTime = 0.0; if (stirIndicatorBar) stirIndicatorBar.style.background = '#2ecc71'; if (stirTimerVal) stirTimerVal.innerText = phaseTimer.toFixed(1); } else if (stirTempo > 82) { // Too frantic! if (stirIndicatorBar) stirIndicatorBar.style.background = '#e74c3c'; wildTempoTime += 0.05; if (wildTempoTime > 1.2) { wildTempoTime = 0.0; stirTempo = 20; phaseTimer = 0.0; window.triggerSnapeInsult("»Mäßigen Sie Ihr ungestümes Tempo! Sie schlagen Schaum statt zu rühren! Das ist kein Pfannkuchenteig!«"); updateStirUI(); return; } } else { // Too slow (blue/cold) if (stirIndicatorBar) stirIndicatorBar.style.background = 'linear-gradient(90deg, #3498db 0%, #2ecc71 50%, #e74c3c 100%)'; wildTempoTime = 0.0; } // Phase completion checks (3.0 seconds needed each) if (phaseTimer >= 3.0) { if (stirPhase === 'left') { // Switch to Phase 2: Right stirPhase = 'right'; phaseTimer = 0.0; stirTempo = 30; updateStirUI(); if (window.soundFX) window.soundFX.playKeyChime(); if (window.showFloatingToast) { window.showFloatingToast("✨ Hervorragend! Jetzt 3 Sekunden gleichmäßig RECHTS (↻) rühren!"); } } else if (stirPhase === 'right') { // Step 2 Complete! clearInterval(stirLoopInterval); stirLoopInterval = null; if (stirSpoon) stirSpoon.style.display = 'none'; if (stirPanel) stirPanel.style.display = 'none'; startStep3(); } } } // Step 3: Heat Control (Blasebalg) with Overheat Insults let currentTemp = 35; let heatTimer = 0.0; let heatInterval = null; let overheatSeconds = 0.0; function startStep3() { currentStep = 3; heatTimer = 0.0; currentTemp = 35; overheatSeconds = 0.0; stepBadge.innerText = "Schritt 3: Hitze balancieren"; stepInstruction.innerText = "Pumpe mit dem Blasebalg, um die Flammen zu nähren!"; stepSubtext.innerText = "Halte die Anzeige für 3 Sekunden im grünen Idealbereich (45% - 85%). Nicht überhitzen!"; if (heatPanel) heatPanel.classList.add('active'); // Shift liquid color to fiery orange if (gradStop1 && gradStop2 && gradStop3) { gradStop1.setAttribute('stop-color', '#e67e22'); gradStop2.setAttribute('stop-color', '#d35400'); gradStop3.setAttribute('stop-color', '#561d00'); } if (window.soundFX) window.soundFX.playWhoosh(); if (heatInterval) clearInterval(heatInterval); heatInterval = setInterval(updateHeatLoop, 50); } window.pumpHeat = function() { if (currentStep !== 3) return; currentTemp = Math.min(100, currentTemp + 18); if (window.soundFX) window.soundFX.playWhoosh(); if (window.navigator && window.navigator.vibrate) window.navigator.vibrate(20); if (bellowsBtn) { bellowsBtn.style.transform = 'scale(0.92)'; setTimeout(() => bellowsBtn.style.transform = 'scale(1)', 100); } }; function updateHeatLoop() { if (currentStep !== 3) return; // Cooling decay currentTemp = Math.max(0, currentTemp - 0.45); if (tempIndicator) tempIndicator.style.width = currentTemp + '%'; // Check overheat condition if (currentTemp > 92) { overheatSeconds += 0.05; if (overheatSeconds > 1.0) { overheatSeconds = 0.0; currentTemp = 35; heatTimer = 0.0; if (heatTimerSpan) heatTimerSpan.innerText = "0.0"; window.triggerSnapeInsult("»Kesselüberhitzung! Sie kochen die kostbaren Essenzen zu Schlacke! Ein wenig mehr Feingefühl mit dem Blasebalg!«"); return; } } else { overheatSeconds = 0.0; } // Check ideal zone (45% to 85%) if (currentTemp >= 45 && currentTemp <= 85) { heatTimer += 0.05; if (heatTimerSpan) heatTimerSpan.innerText = heatTimer.toFixed(1); if (tempIndicator) tempIndicator.style.background = '#2ecc71'; } else { if (tempIndicator) tempIndicator.style.background = 'linear-gradient(90deg, #3498db, #f39c12, #e74c3c)'; } if (heatTimer >= 3.0) { clearInterval(heatInterval); heatInterval = null; finishPotionBrew(); } } // Step 4: Victory async function finishPotionBrew() { currentStep = 4; stepBadge.innerText = "✅ Trank vollendet!"; stepBadge.style.background = "rgba(46, 204, 113, 0.3)"; stepBadge.style.borderColor = "#2ecc71"; stepBadge.style.color = "#2ecc71"; stepInstruction.innerText = "Felix Felicis strahlt in reinem Gold!"; stepSubtext.innerText = "Dein Zaubertrank ist meisterhaft gelungen. Selbst Snape nickt widerwillig!"; if (heatPanel) heatPanel.classList.remove('active'); // Turn liquid into radiant shimmering gold if (gradStop1 && gradStop2 && gradStop3) { gradStop1.setAttribute('stop-color', '#fff6a5'); gradStop2.setAttribute('stop-color', '#ffd700'); gradStop3.setAttribute('stop-color', '#b7950b'); } if (window.soundFX) window.soundFX.playMagicSuccess(); if (window.navigator && window.navigator.vibrate) window.navigator.vibrate([50, 100, 150]); // API Completion Call let newItem = null; try { const res = await fetch('/api/brew/complete', { method: 'POST' }); const data = await res.json(); if (data.new_item) newItem = data.new_item; } catch (e) { console.error("Brew complete error:", e); } if (!newItem) { newItem = { id: "felix_felicis", name: "Felix Felicis", icon: "🧪", desc: "Ein Tropfen flüssiges Gold! Verleiht dir unerschütterliches Glück und enthüllt verborgene Runen." }; } if (successPanel) successPanel.style.display = 'block'; if (window.showChamberVictory) { window.showChamberVictory({ chamberBadge: "Kammer III: Die Brauküche", title: "⚗️ Zaubertrank Gemeistert!", statsHtml: `🧪 Elixier: Felix Felicis🥄 Rühren: 2 Phasen perfekt🌡️ Hitze: Meisterlich`, item: newItem, storyText: "Der Kessel erstrahlt in gleißendem, flüssigem Gold! Du füllst eine Phiole des unbezahlbaren Felix Felicis ab. Selbst Severus Snape quittiert dein Werk mit einem knappen, anerkennenden Nicken. Seine Wärme durchdringt deinen Geist. Mit geschärften Sinnen trittst du vor das gewaltige Runen-Drehschloss der vier Gründer!", nextUrl: "/cryptex", nextBtnText: "➔ Weiter zu Kammer IV: Das Drehschloss 🔐" }); } } })();