// Zaubertrank-Brauküche (Felix Felicis Potion Brewing Engine) (function() { let currentStep = 1; // 1: Ingredients, 2: Stirring, 3: Heat, 4: Done const ingredients = { dragon: 0, mandrake: 0, star: 0 }; const targetIngredients = { dragon: 2, mandrake: 1, star: 1 }; // DOM Elements const stepBadge = document.getElementById('stepBadge'); const stepInstruction = document.getElementById('stepInstruction'); const stepSubtext = document.getElementById('stepSubtext'); const ingredientsShelf = document.getElementById('ingredientsShelf'); const potionSurface = document.getElementById('potionSurface'); const stirCircle = document.getElementById('stirCircle'); const stirTracker = document.getElementById('stirTracker'); const stirCounterText = document.getElementById('stirCounterText'); const stirCountSpan = document.getElementById('stirCount'); const heatPanel = document.getElementById('heatPanel'); const tempIndicator = document.getElementById('tempIndicator'); const heatTimerSpan = document.getElementById('heatTimer'); const successPanel = document.getElementById('successPanel'); const cauldronZone = document.getElementById('cauldronZone'); // Step 1: Add Ingredient window.addIngredient = function(type) { if (currentStep !== 1) return; if (ingredients[type] >= targetIngredients[type]) return; ingredients[type]++; if (window.soundFX) window.soundFX.playBottleClink(); // Update UI Badge if (type === 'dragon') { document.getElementById('countDragon').innerText = `${ingredients.dragon} / ${targetIngredients.dragon}`; if (ingredients.dragon >= targetIngredients.dragon) document.getElementById('ingDragon').classList.add('done'); } else if (type === 'mandrake') { document.getElementById('countMandrake').innerText = `${ingredients.mandrake} / ${targetIngredients.mandrake}`; if (ingredients.mandrake >= targetIngredients.mandrake) document.getElementById('ingMandrake').classList.add('done'); } else if (type === 'star') { document.getElementById('countStar').innerText = `${ingredients.star} / ${targetIngredients.star}`; if (ingredients.star >= targetIngredients.star) document.getElementById('ingStar').classList.add('done'); } // Ripple effect on surface potionSurface.style.transform = 'scale(1.08)'; setTimeout(() => potionSurface.style.transform = 'scale(1)', 200); // Check if all ingredients added const total = ingredients.dragon + ingredients.mandrake + ingredients.star; if (total === 4) { setTimeout(startStep2, 600); } }; // Step 2: Stirring let completedStirs = 0; let lastAngle = null; let accumulatedAngle = 0; function startStep2() { currentStep = 2; stepBadge.innerText = "Schritt 2: Gleichmäßig rühren"; stepInstruction.innerText = "Rühre den Sud 3 Runden im Uhrzeigersinn!"; stepSubtext.innerText = "Führe deinen Finger oder die Maus im Kreis über dem Kessel oder tippe ihn an."; ingredientsShelf.style.display = 'none'; stirCounterText.style.display = 'block'; stirCircle.classList.add('active'); potionSurface.className = 'potion-surface state-stir'; if (window.soundFX) window.soundFX.playStoneSlide(); } // Touch / Pointer stirring logic let isStirring = false; function getAngle(e) { const rect = cauldronZone.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const clientX = e.touches ? e.touches[0].clientX : e.clientX; const clientY = e.touches ? e.touches[0].clientY : e.clientY; return Math.atan2(clientY - centerY, clientX - centerX) * (180 / Math.PI); } function onStirStart(e) { if (currentStep !== 2) return; isStirring = true; lastAngle = getAngle(e); } function onStirMove(e) { if (currentStep !== 2 || !isStirring) return; e.preventDefault(); const angle = getAngle(e); if (lastAngle !== null) { let diff = angle - lastAngle; // Handle wrap-around if (diff < -180) diff += 360; if (diff > 180) diff -= 360; // Only count clockwise if (diff > 0) { accumulatedAngle += diff; if (accumulatedAngle >= 360) { accumulatedAngle -= 360; incrementStir(); } } } lastAngle = angle; } function onStirEnd() { isStirring = false; lastAngle = null; } function incrementStir() { completedStirs++; stirCountSpan.innerText = completedStirs; if (window.soundFX) window.soundFX.playBottleClink(); if (completedStirs >= 3) { stirCircle.classList.remove('active'); stirCounterText.style.display = 'none'; setTimeout(startStep3, 600); } } // Direct tap fallback for mobile cauldronZone.addEventListener('click', () => { if (currentStep === 2 && !isStirring) { incrementStir(); } }); cauldronZone.addEventListener('mousedown', onStirStart); window.addEventListener('mousemove', onStirMove); window.addEventListener('mouseup', onStirEnd); cauldronZone.addEventListener('touchstart', onStirStart, { passive: false }); window.addEventListener('touchmove', onStirMove, { passive: false }); window.addEventListener('touchend', onStirEnd); // Step 3: Heat Control let currentTemp = 35; // percent (0-100) let heatTimer = 0.0; let heatInterval = null; function startStep3() { currentStep = 3; stepBadge.innerText = "Schritt 3: Hitze balancieren"; stepInstruction.innerText = "Pumpe mit dem Blasebalg, um die Hitze im grünen Bereich zu halten!"; stepSubtext.innerText = "Halte die Nadel für 4 Sekunden im grünen Bereich (60% - 85%)."; potionSurface.className = 'potion-surface state-heat'; heatPanel.classList.add('active'); if (window.soundFX) window.soundFX.playWhoosh(); heatInterval = setInterval(updateHeatLoop, 50); } window.pumpHeat = function() { if (currentStep !== 3) return; currentTemp = Math.min(100, currentTemp + 15); if (window.soundFX) window.soundFX.playWhoosh(); }; function updateHeatLoop() { if (currentStep !== 3) return; // Slow cooling down currentTemp = Math.max(0, currentTemp - 0.55); tempIndicator.style.width = currentTemp + '%'; // Check ideal zone (60% to 85%) if (currentTemp >= 60 && currentTemp <= 85) { heatTimer += 0.05; heatTimerSpan.innerText = heatTimer.toFixed(1); tempIndicator.style.background = '#2ecc71'; } else { tempIndicator.style.background = 'linear-gradient(90deg, #3498db, #f39c12, #e74c3c)'; } if (heatTimer >= 4.0) { clearInterval(heatInterval); 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 perfekt gelungen."; heatPanel.classList.remove('active'); potionSurface.className = 'potion-surface state-gold'; if (window.soundFX) window.soundFX.playMagicSuccess(); // API Completion Call try { const res = await fetch('/api/brew/complete', { method: 'POST' }); const data = await res.json(); if (data.new_item && window.notifyNewItem) { window.notifyNewItem(data.new_item); } } catch (e) { console.error("Brew complete error:", e); } successPanel.style.display = 'block'; } })();