diff --git a/app.js b/app.js index 5c72f4b..aa40f7f 100644 --- a/app.js +++ b/app.js @@ -46,6 +46,7 @@ let discoveredMolecules = new Set(JSON.parse(localStorage.getItem('chem_lab_disc let currentLevelIndex = parseInt(localStorage.getItem('chem_lab_story_level') || '0'); let completedLevels = JSON.parse(localStorage.getItem('chem_lab_story_completed') || '[]'); let currentAllowedAtoms = []; +let playerEnergy = parseInt(localStorage.getItem('chem_lab_energy') || '0'); // Elemente Datenbank für Spawnen (Symbole, Farben, Namen) const elementDetails = { @@ -430,6 +431,36 @@ clearDeskBtn.addEventListener('click', () => { document.getElementById('reactor-synth-btn').addEventListener('click', synthesizeReactor); document.getElementById('reactor-decompose-btn').addEventListener('click', decomposeReactor); +// Machine Toggles in Reaktor Box +const heatToggle = document.getElementById('reactor-heat-toggle'); +const elecToggle = document.getElementById('reactor-elec-toggle'); + +if (heatToggle) { + heatToggle.addEventListener('change', () => { + if (heatToggle.checked) { + setAssistantText("Brenner gezündet! 🔥 Hitze liefert die nötige Aktivierungsenergie, um reaktionsträge Dreifachbindungen anzuregen."); + } else { + setAssistantText("Brenner aus. Der Reaktor kühlt langsam ab."); + } + }); +} + +if (elecToggle) { + elecToggle.addEventListener('change', () => { + if (elecToggle.checked) { + setAssistantText("Strom ein! ⚡ Die Elektrolyse zwingt Elektronen auf Bahnen und spaltet selbst extrem stabile Moleküle."); + } else { + setAssistantText("Strom aus. Die Ionenbewegung normalisiert sich."); + } + }); +} + +// Particle Accelerator fire event +const accFireBtn = document.getElementById('acc-fire-btn'); +if (accFireBtn) { + accFireBtn.addEventListener('click', fireAccelerator); +} + // ========================================= // MODALS LOGIC // ========================================= @@ -700,12 +731,39 @@ function ejectMoleculeFromReactor(idx) { } } +function analyzeFailedSynthesis() { + const counts = {}; + reactorAtoms.forEach(sym => { + counts[sym] = (counts[sym] || 0) + 1; + }); + + if (counts['N'] && counts['H'] && counts['H'] && counts['H'] !== 3) { + setAssistantText("Achtung! Stickstoff (N) benötigt genau 3 Wasserstoff-Atome (H) für Ammoniak (NH₃). Deine Mischung lässt freie Valenzen ungesättigt. Füge noch ein H hinzu!", true); + } else if (counts['H'] === 1 && counts['O'] === 1) { + setAssistantText("Wasserstoff (H) und Sauerstoff (O) können nicht im Verhältnis 1:1 binden. Sie brauchen entweder 2x H und 1x O für Wasser (H₂O) oder 2x H und 2x O für Wasserstoffperoxid (H₂O₂).", true); + } else if (counts['C'] && counts['O'] && counts['C'] === 1 && counts['O'] !== 1 && counts['O'] !== 2) { + setAssistantText("Kohlenstoff (C) bindet sich mit Sauerstoff (O) entweder zu Kohlenmonoxid (CO, 1:1) oder Kohlendioxid (CO₂, 1:2). Passe dein Verhältnis an!", true); + } else { + setAssistantText("Diese Atome können sich nicht zu einem stabilen Molekül verbinden. Achte auf die Oktettregel und die Wertigkeiten (H=1, O=2, N=3, C=4, Na=1, Cl=1)!", true); + } +} + function synthesizeReactor() { if (reactorAtoms.length === 0) { alert("Der Reaktor enthält keine freien Atome für die Synthese!"); return; } + const hasNitrogen = reactorAtoms.includes('N'); + const heatOn = document.getElementById('reactor-heat-toggle').checked; + const elecOn = document.getElementById('reactor-elec-toggle').checked; + + if (hasNitrogen && !heatOn && !elecOn) { + setAssistantText("Halt! Stickstoff (N) ist extrem reaktionsträge aufgrund seiner starken Dreifachbindung! Um ihn zur Reaktion zu bringen, benötigst du zusätzliche Aktivierungsenergie. Schalte die Brenner-Station (Hitze) oder die Elektrolyse-Kammer (Strom) hinzu!", true); + alert("Synthese blockiert: Aktivierungsenergie fehlt für Stickstoff!"); + return; + } + // Sort recipes by ingredient length descending so we build larger molecules first const sortedRecipes = [...recipes].sort((a, b) => b.ingredients.length - a.ingredients.length); @@ -749,6 +807,11 @@ function synthesizeReactor() { const ry = parseFloat(reactorBox.style.top || (workspace.clientHeight - 190)) + Math.random() * 40; createMolecule(recipe, Math.max(10, rx), Math.max(10, ry)); + // Award energy + const energyAwarded = recipe.ingredients.length * 15; + playerEnergy += energyAwarded; + localStorage.setItem('chem_lab_energy', playerEnergy); + // Explosion at the reactor center const rect = reactorBox.getBoundingClientRect(); const workspaceRect = workspace.getBoundingClientRect(); @@ -774,6 +837,9 @@ function synthesizeReactor() { showModal(recipe, isNew); + const cleanName = recipe.result.substring(recipe.result.indexOf('(') + 1, recipe.result.indexOf(')')); + setAssistantText(`Sensationell! Wir haben ${cleanName} synthetisiert und dabei ${energyAwarded} J Energie freigesetzt!`); + synthesizedAny = true; keepMatching = true; break; @@ -784,10 +850,19 @@ function synthesizeReactor() { if (synthesizedAny) { updateReactorUI(); } else { - alert("Aus den vorhandenen Atomen konnte kein bekanntes Molekül synthetisiert werden!"); + analyzeFailedSynthesis(); } } +function setAssistantText(text, isWarning = false) { + const avatar = document.querySelector('.assistant-avatar'); + const textEl = document.getElementById('assistant-text'); + if (!avatar || !textEl) return; + + avatar.innerText = isWarning ? "⚠️" : "🔬"; + textEl.innerText = text; +} + function decomposeReactor() { if (reactorMolecules.length === 0) { alert("Es befinden sich keine Moleküle in der Reaktor-Box, die zerlegt werden können!"); @@ -970,11 +1045,33 @@ function renderDiscoveryBook() { discoveryProgress.innerText = `${count}/${recipes.length}`; } +function checkPhysicsUnlock() { + const physicsBtn = document.getElementById('tab-physics-btn'); + if (!physicsBtn) return; + if (playerEnergy >= 150) { + physicsBtn.classList.remove('locked'); + physicsBtn.disabled = false; + physicsBtn.title = "Klicke, um den Teilchenbeschleuniger zu öffnen!"; + physicsBtn.innerHTML = "⚛️ Physik"; + } else { + physicsBtn.classList.add('locked'); + physicsBtn.disabled = true; + physicsBtn.innerHTML = `⚛️ Physik 🔒 (${playerEnergy}/150J)`; + } +} + function updateStats() { const atoms = elementsOnDesk.filter(el => el.classList.contains('atom')).length; const molecules = elementsOnDesk.filter(el => el.classList.contains('molecule')).length; atomCountEl.innerText = atoms; moleculeCountEl.innerText = molecules; + + const energyCountEl = document.getElementById('energy-count'); + if (energyCountEl) { + energyCountEl.innerText = playerEnergy; + } + localStorage.setItem('chem_lab_energy', playerEnergy); + checkPhysicsUnlock(); } // ========================================= @@ -1113,8 +1210,10 @@ function renderBohrModel(electronsArray) { // Dom Tabs switching const tabSandboxBtn = document.getElementById('tab-sandbox-btn'); const tabStoryBtn = document.getElementById('tab-story-btn'); +const tabPhysicsBtn = document.getElementById('tab-physics-btn'); const sandboxContentEl = document.getElementById('sandbox-content'); const storyContentEl = document.getElementById('story-content'); +const physicsContentEl = document.getElementById('physics-content'); tabSandboxBtn.addEventListener('click', () => { switchMode('sandbox'); @@ -1124,6 +1223,14 @@ tabStoryBtn.addEventListener('click', () => { switchMode('story'); }); +if (tabPhysicsBtn) { + tabPhysicsBtn.addEventListener('click', () => { + if (!tabPhysicsBtn.classList.contains('locked')) { + switchMode('physics'); + } + }); +} + function switchMode(mode) { gameMode = mode; const elementsToRemove = workspace.querySelectorAll('.atom, .molecule'); @@ -1139,19 +1246,38 @@ function switchMode(mode) { if (mode === 'sandbox') { tabSandboxBtn.classList.add('active'); tabStoryBtn.classList.remove('active'); + if (tabPhysicsBtn) tabPhysicsBtn.classList.remove('active'); + sandboxContentEl.classList.remove('hidden'); storyContentEl.classList.add('hidden'); + if (physicsContentEl) physicsContentEl.classList.add('hidden'); deskTitle.innerText = "Labor-Tisch (Sandbox)"; - deskSubtitle.innerText = "Ziehe Atome übereinander, um Reaktionen frei auszulösen!"; + deskSubtitle.innerText = "Ziehe Atome in die Reaktor-Box, um Reaktionen auszulösen!"; currentAllowedAtoms = Object.keys(elementDetails); - } else { + } else if (mode === 'story') { tabSandboxBtn.classList.remove('active'); tabStoryBtn.classList.add('active'); + if (tabPhysicsBtn) tabPhysicsBtn.classList.remove('active'); + sandboxContentEl.classList.add('hidden'); storyContentEl.classList.remove('hidden'); + if (physicsContentEl) physicsContentEl.classList.add('hidden'); loadStoryLevel(currentLevelIndex); + } else if (mode === 'physics') { + tabSandboxBtn.classList.remove('active'); + tabStoryBtn.classList.remove('active'); + if (tabPhysicsBtn) tabPhysicsBtn.classList.add('active'); + + sandboxContentEl.classList.add('hidden'); + storyContentEl.classList.add('hidden'); + if (physicsContentEl) physicsContentEl.classList.remove('hidden'); + + deskTitle.innerText = "Labor-Tisch (Kernphysik)"; + deskSubtitle.innerText = "Teilchenbeschleuniger geladen. Kollidiere Atome, um neue Elemente zu erschaffen!"; + currentAllowedAtoms = Object.keys(elementDetails); + populateAcceleratorDropdowns(); } } @@ -1321,3 +1447,109 @@ storyNextLevelBtn.addEventListener('click', () => { // Zusätzliche Modal Close-Events if (storySuccessCloseIcon) storySuccessCloseIcon.addEventListener('click', closeStorySuccessModal); if (storySuccessOverlay) storySuccessOverlay.addEventListener('click', closeStorySuccessModal); + +function populateAcceleratorDropdowns() { + const s1 = document.getElementById('acc-source-1'); + const s2 = document.getElementById('acc-source-2'); + if (!s1 || !s2) return; + + s1.innerHTML = ''; + s2.innerHTML = ''; + + const playable = pseElements.filter(el => el.playable); + playable.forEach(el => { + const opt1 = document.createElement('option'); + opt1.value = el.symbol; + opt1.innerText = `${el.symbol} (${el.name}, Z=${el.number})`; + s1.appendChild(opt1); + + const opt2 = document.createElement('option'); + opt2.value = el.symbol; + opt2.innerText = `${el.symbol} (${el.name}, Z=${el.number})`; + s2.appendChild(opt2); + }); +} + +function fireAccelerator() { + if (playerEnergy < 20) { + alert("Nicht genug Energie! Du benötigst mindestens 20 J, um den Teilchenbeschleuniger zu laden."); + return; + } + + const s1 = document.getElementById('acc-source-1'); + const s2 = document.getElementById('acc-source-2'); + if (!s1 || !s2) return; + + const sym1 = s1.value; + const sym2 = s2.value; + + const el1 = pseElements.find(e => e.symbol === sym1); + const el2 = pseElements.find(e => e.symbol === sym2); + if (!el1 || !el2) return; + + // Cost + playerEnergy -= 20; + updateStats(); + + // Animate + const animZone = document.getElementById('acc-animation-zone'); + const fireBtn = document.getElementById('acc-fire-btn'); + const resultBox = document.getElementById('acc-result-box'); + + if (animZone) animZone.classList.add('firing'); + if (resultBox) resultBox.classList.add('hidden'); + if (fireBtn) fireBtn.disabled = true; + + // Set labels + const p1 = document.getElementById('acc-particle-1'); + const p2 = document.getElementById('acc-particle-2'); + if (p1) p1.innerText = el1.symbol; + if (p2) p2.innerText = el2.symbol; + + setTimeout(() => { + if (animZone) animZone.classList.remove('firing'); + if (fireBtn) fireBtn.disabled = false; + + const totalZ = el1.number + el2.number; + const resultEl = pseElements.find(e => e.number === totalZ); + + if (resultBox) resultBox.classList.remove('hidden'); + + const resSymbolEl = document.getElementById('acc-result-element'); + const resDescEl = document.getElementById('acc-result-desc'); + + if (resultEl) { + // SUCCESS! + resultBox.classList.remove('decayed'); + if (resSymbolEl) { + resSymbolEl.innerText = resultEl.symbol; + resSymbolEl.className = 'acc-result-circle'; + resSymbolEl.style.backgroundColor = getElementColor(resultEl.symbol); + } + if (resDescEl) { + resDescEl.innerText = `Kernfusion erfolgreich! Du hast ${resultEl.name} (Ordnungszahl ${totalZ}) erschaffen.`; + } + + // Spawn on desk! + spawnAtom(resultEl.symbol, getElementColor(resultEl.symbol)); + } else { + // DECAY! + resultBox.classList.add('decayed'); + if (resSymbolEl) { + resSymbolEl.innerText = "💥"; + resSymbolEl.style.backgroundColor = "#e74c3c"; + } + if (resDescEl) { + resDescEl.innerText = `Instabiler Kern! Das Element mit Ordnungszahl ${totalZ} ist sofort in leichtere Trümmer-Isotope zerfallen.`; + } + + // Spawn random lighter elements as debris + const count = 2 + Math.floor(Math.random() * 2); + for (let i = 0; i < count; i++) { + const randomLight = pseElements.filter(e => e.playable && e.number < 20); + const randomEl = randomLight[Math.floor(Math.random() * randomLight.length)]; + spawnAtom(randomEl.symbol, getElementColor(randomEl.symbol)); + } + } + }, 800); +} diff --git a/index.html b/index.html index 18c993a..cb76b4e 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,7 @@
@@ -86,6 +87,43 @@ + + +Hallo! Ich bin dein Labor-Assistent. Ziehe Atome in die Box, schalte bei Bedarf Brenner oder Elektrolyse ein und klicke auf Synthetisieren!
+