// ============================================ // GAME STATE & INITIALIZATION // ============================================ let state = { humans: 0, prayers: 0, grace: 0, sacredVessels: 0, holyScripture: 0, blessings: 0, manna: 0, souls: 0, wisdom: 0, miracles: 0, auras: 0, sacredIcons: 0, commonCount: 0, principalityCount: 0, powerCount: 0, virtueCount: 0, dominionCount: 0, thronesCount: 0, cherubCount: 0, seraphCount: 0, archangelCount: 0, commonBaseCost: 50, principalityBaseCost: 150, powerBaseCost: 250, virtueBaseCost: 400, dominionBaseCost: 600, thronesBaseCost: 800, cherubBaseCost: 1000, seraphBaseCost: 1500, archangelCost: 500, unlockRequirements: { tier2: 50, tier3: 100, tier4: 150, tier5: 200, tier6: 250, tier7: 300, tier8: 350, tier9: 0 }, costScalingFactor: 1.15, globalMultiplier: 1.0, ascensionCount: 0, lastTick: Date.now() }; let soundEnabled = true; let audioCtx = null; // ============================================ // SOUND FUNCTIONS // ============================================ function initAudio() { if (!audioCtx) { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } } function playClickSound() { if (!soundEnabled || !audioCtx) return; const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.connect(gain); gain.connect(audioCtx.destination); osc.frequency.value = 440; gain.gain.setValueAtTime(0.3, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.1); osc.start(); osc.stop(audioCtx.currentTime + 0.1); } function playBuySound() { if (!soundEnabled || !audioCtx) return; const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.connect(gain); gain.connect(audioCtx.destination); osc.frequency.value = 523.25; gain.gain.setValueAtTime(0.3, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.2); osc.start(); osc.stop(audioCtx.currentTime + 0.2); } function playPrestigeSound() { if (!soundEnabled || !audioCtx) return; const notes = [523.25, 659.25, 783.99, 1046.50]; let time = audioCtx.currentTime; notes.forEach((freq, i) => { setTimeout(() => { const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.connect(gain); gain.connect(audioCtx.destination); osc.frequency.value = freq; gain.gain.setValueAtTime(0.3, time + i * 100 / 1000); gain.gain.exponentialRampToValueAtTime(0.01, time + i * 100 / 1000 + 0.4); osc.start(time + i * 100 / 1000); osc.stop(time + i * 100 / 1000 + 0.4); }, i * 100); }); } // ============================================ // SIDE PANEL FUNCTIONS // ============================================ function toggleSidePanel() { const panel = document.getElementById('sidePanel'); const overlay = document.getElementById('overlay'); const btn = document.querySelector('.hamburger-btn'); if (panel.classList.contains('open')) { closeSidePanel(); } else { panel.classList.add('open'); overlay.classList.add('active'); btn.classList.add('active'); } } function closeSidePanel() { const panel = document.getElementById('sidePanel'); const overlay = document.getElementById('overlay'); const btn = document.querySelector('.hamburger-btn'); panel.classList.remove('open'); overlay.classList.remove('active'); btn.classList.remove('active'); } // ============================================ // VISUAL EFFECTS // ============================================ function createFloatingNumber(x, y, amount, color = '#ffd700') { const floatNum = document.createElement('div'); floatNum.className = 'floating-number'; let textToDisplay = '+0'; if (amount && !isNaN(amount)) { textToDisplay = '+' + Math.round(Math.abs(amount)); } floatNum.textContent = textToDisplay; const roundedAmount = amount ? Math.round(Math.abs(amount)) : 0; floatNum.style.color = color; floatNum.style.fontSize = (roundedAmount > 100 ? '2rem' : '1.5rem'); floatNum.style.left = (x - 30) + 'px'; floatNum.style.top = (y - 50) + 'px'; const offsetX = (Math.random() - 0.5) * 40; floatNum.style.setProperty('--tx', offsetX + 'px'); document.body.appendChild(floatNum); setTimeout(() => { floatNum.remove(); }, 1500); } function createParticleBurst(x, y, color = '#ffd700') { const particleCount = 12; for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.className = 'particle'; const size = Math.random() * 8 + 4; particle.style.width = size + 'px'; particle.style.height = size + 'px'; const colors = ['#ffd700', '#ffecb3', '#ffe082', '#fff59d', '#ffffff']; particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; particle.style.left = x + 'px'; particle.style.top = y + 'px'; const angle = Math.random() * 2 * Math.PI; const distance = Math.random() * 80 + 40; const tx = Math.cos(angle) * distance + 'px'; const ty = Math.sin(angle) * distance + 'px'; particle.style.setProperty('--tx', tx); particle.style.setProperty('--ty', ty); document.body.appendChild(particle); setTimeout(() => { particle.remove(); }, 1000); } } function createSparkle(x, y, color = '#ffd700') { const sparkleCount = 8; for (let i = 0; i < sparkleCount; i++) { setTimeout(() => { const sparkle = document.createElement('div'); sparkle.className = 'sparkle'; sparkle.style.width = '20px'; sparkle.style.height = '20px'; sparkle.style.background = color; sparkle.style.left = x + 'px'; sparkle.style.top = y + 'px'; document.body.appendChild(sparkle); setTimeout(() => { sparkle.remove(); }, 600); }, i * 50); } } // ============================================ // CALCULATION HELPERS // ============================================ function calculatePrayerMultiplier() { let multiplier = state.globalMultiplier; if (state.commonCount > 0) multiplier *= (1 + (state.commonCount * 0.01)); if (state.principalityCount > 0) multiplier *= (1 + (state.principalityCount * 0.1)); if (state.powerCount > 0) multiplier *= (1 + (state.powerCount * 0.15)); if (state.virtueCount > 0) multiplier *= (1 + (state.virtueCount * 0.25)); if (state.dominionCount > 0) multiplier *= (1 + (state.dominionCount * 0.2)); if (state.thronesCount > 0) multiplier *= (1 + (state.thronesCount * 0.15)); if (state.cherubCount > 0) multiplier *= (1 + (state.cherubCount * 0.25)); if (state.seraphCount > 0) multiplier *= (1 + (state.seraphCount * 5)); if (state.archangelCount > 0) multiplier *= (10 + (state.archangelCount * 2)); return multiplier; } function calculateSoulsMultiplier() { let multiplier = state.globalMultiplier; if (state.commonCount > 0) multiplier *= (1 + (state.commonCount * 0.5)); if (state.principalityCount > 0) multiplier *= (1 + (state.principalityCount * 0.1)); if (state.powerCount > 0) multiplier *= (1 + (state.powerCount * 0.15)); return multiplier; } function getCostMultiplier() { let costReduction = state.globalMultiplier; if (state.cherubCount > 0) costReduction *= Math.pow(0.75, state.cherubCount); return costReduction; } function getCurrentCost(baseCost, count) { const currentCost = baseCost * Math.pow(state.costScalingFactor, count); const finalCost = currentCost * getCostMultiplier(); return Math.round(finalCost); } // ============================================ // UI UPDATE FUNCTIONS // ============================================ function showStatus(message) { document.getElementById('status-display').textContent = message; } function updateUI() { const currencies = [ { name: 'humans', displayId: 'sidebar-humans-display' }, { name: 'prayers', displayId: 'sidebar-prayers-display' }, { name: 'grace', displayId: 'sidebar-grace-display' }, { name: 'sacredVessels', displayId: 'sidebar-vessel-display' }, { name: 'holyScripture', displayId: 'sidebar-scripture-display' }, { name: 'blessings', displayId: 'sidebar-blessing-display' }, { name: 'manna', displayId: 'sidebar-manna-display' }, { name: 'souls', displayId: 'sidebar-souls-display' }, { name: 'wisdom', displayId: 'sidebar-wisdom-display' }, { name: 'miracles', displayId: 'sidebar-miracle-display' }, { name: 'auras', displayId: 'sidebar-aura-display' }, { name: 'sacredIcons', displayId: 'sidebar-icon-display' } ]; currencies.forEach(curr => { const el = document.getElementById(curr.displayId); if (el) el.textContent = Math.round(state[curr.name]); }); const prayerMultiplier = calculatePrayerMultiplier(); const totalPrayerGenPerSec = state.humans * 0.5; // Base Human Prayer Rate document.getElementById('prayer-click-rate').textContent = Math.round(totalPrayerGenPerSec * prayerMultiplier) + '/click'; document.getElementById('holy-power').textContent = Math.round(totalPrayerGenPerSec * prayerMultiplier); const tierCounts = ['commonCount', 'principalityCount', 'powerCount', 'virtueCount', 'dominionCount', 'thronesCount', 'cherubCount', 'seraphCount', 'archangelCount']; const countIds = ['common-count', 'principality-count', 'power-count', 'virtue-count', 'dominion-count', 'throness-count', 'cherub-count', 'seraph-count', 'archangel-count']; tierCounts.forEach((countVar, i) => { document.getElementById(countIds[i]).textContent = state[countVar]; const panelCountId = 'panel-' + countIds[i]; const panelEl = document.getElementById(panelCountId); if (panelEl) panelEl.textContent = state[countVar]; }); document.getElementById('global-multiplier').textContent = state.globalMultiplier.toFixed(1); document.getElementById('ascension-count').textContent = state.ascensionCount; const costMult = getCostMultiplier(); const commonCost = getCurrentCost(state.commonBaseCost, state.commonCount); const principalityCost = getCurrentCost(state.principalityBaseCost, state.principalityCount); const powerCost = getCurrentCost(state.powerBaseCost, state.powerCount); const virtueCost = getCurrentCost(state.virtueBaseCost, state.virtueCount); const dominionCost = getCurrentCost(state.dominionBaseCost, state.dominionCount); const thronesCost = getCurrentCost(state.thronesBaseCost, state.thronesCount); const cherubCost = getCurrentCost(state.cherubBaseCost, state.cherubCount); const seraphCost = getCurrentCost(state.seraphBaseCost, state.seraphCount); updatePanelAngelButtonsWithBatch(commonCost, principalityCost, powerCost, virtueCost, dominionCost, thronesCost, cherubCost, seraphCost, costMult); const ascendCost = 1 * state.ascensionCount; document.getElementById('ascend-btn').textContent = `Ascend to Heaven (Cost: ${ascendCost} Virtue Point${ascendCost > 1 ? 's' : ''})`; updateTierUnlocks(costMult); } function getCurrencyNameForTier(tier) { const mappings = { 'common': 'Prayers', 'principality': 'Grace', 'power': 'Sacred Vessels', 'virtue': 'Blessings', 'dominion': 'Souls', 'throne': 'Wisdom', 'cherub': 'Manna', 'seraph': 'Miracles', 'archangel': 'Sacred Icons' }; return mappings[tier] || 'Resource'; } function updatePanelAngelButtonsWithBatch(commonCost, principalityCost, powerCost, virtueCost, dominionCost, thronesCost, cherubCost, seraphCost, costMult) { const updateQuickBuyButtons = (tierCardId, currencyKey, costPerUnit, baseAmounts = [1, 5, 10, 100]) => { const card = document.getElementById(tierCardId); if (!card) return; const currentCurrency = state[currencyKey]; const quickBuyBtns = card.querySelectorAll('.quick-buys .buy-option-btn'); for (let i = 0; i < baseAmounts.length && quickBuyBtns[i]; i++) { const amountToBuy = baseAmounts[i] * costPerUnit; quickBuyBtns[i].disabled = currentCurrency < amountToBuy; } }; updateQuickBuyButtons('common-angel-panel-card', 'prayers', commonCost); // CORRECTED TIER 2: Checks Grace instead of Souls if (state.grace >= state.unlockRequirements.tier2) { const card = document.getElementById('principality-angel-panel-card'); if (card) card.classList.remove('locked'); updateQuickBuyButtons('principality-angel-panel-card', 'grace', principalityCost); } else { const card = document.getElementById('principality-angel-panel-card'); if (card) card.classList.add('locked'); } if (state.sacredVessels >= state.unlockRequirements.tier3) { const card = document.getElementById('power-angel-panel-card'); if (card) card.classList.remove('locked'); updateQuickBuyButtons('power-angel-panel-card', 'sacredVessels', powerCost); } else { const card = document.getElementById('power-angel-panel-card'); if (card) card.classList.add('locked'); } if (state.manna >= state.unlockRequirements.tier4) { const card = document.getElementById('virtue-angel-panel-card'); if (card) card.classList.remove('locked'); updateQuickBuyButtons('virtue-angel-panel-card', 'blessings', virtueCost); } else { const card = document.getElementById('virtue-angel-panel-card'); if (card) card.classList.add('locked'); } if (state.wisdom >= state.unlockRequirements.tier5) { const card = document.getElementById('dominion-angel-panel-card'); if (card) card.classList.remove('locked'); updateQuickBuyButtons('dominion-angel-panel-card', 'souls', dominionCost); } else { const card = document.getElementById('dominion-angel-panel-card'); if (card) card.classList.add('locked'); } if (state.miracles >= state.unlockRequirements.tier6) { const card = document.getElementById('throne-angel-panel-card'); if (card) card.classList.remove('locked'); updateQuickBuyButtons('throne-angel-panel-card', 'wisdom', thronesCost); } else { const card = document.getElementById('throne-angel-panel-card'); if (card) card.classList.add('locked'); } if (state.auras >= state.unlockRequirements.tier7) { const card = document.getElementById('cherub-angel-panel-card'); if (card) card.classList.remove('locked'); updateQuickBuyButtons('cherub-angel-panel-card', 'manna', cherubCost); } else { const card = document.getElementById('cherub-angel-panel-card'); if (card) card.classList.add('locked'); } if (state.sacredIcons >= state.unlockRequirements.tier8) { const card = document.getElementById('seraph-angel-panel-card'); if (card) card.classList.remove('locked'); updateQuickBuyButtons('seraph-angel-panel-card', 'miracles', seraphCost); } else { const card = document.getElementById('seraph-angel-panel-card'); if (card) card.classList.add('locked'); } if (state.seraphCount > 0) { const card = document.getElementById('archangel-angel-panel-card'); if (card) card.classList.remove('locked'); updateQuickBuyButtons('archangel-angel-panel-card', 'sacredIcons', state.archangelCost); } else { const card = document.getElementById('archangel-angel-panel-card'); if (card) card.classList.add('locked'); } } function updateTierUnlocks(costMult) { const tierCards = [ { id: 'tier-1-card', unlocked: true }, { id: 'tier-2-card', unlocked: state.souls >= state.unlockRequirements.tier2 }, { id: 'tier-3-card', unlocked: state.sacredVessels >= state.unlockRequirements.tier3 }, { id: 'tier-4-card', unlocked: state.manna >= state.unlockRequirements.tier4 }, { id: 'tier-5-card', unlocked: state.wisdom >= state.unlockRequirements.tier5 }, { id: 'tier-6-card', unlocked: state.miracles >= state.unlockRequirements.tier6 }, { id: 'tier-7-card', unlocked: state.auras >= state.unlockRequirements.tier7 }, { id: 'tier-8-card', unlocked: state.sacredIcons >= state.unlockRequirements.tier8 }, { id: 'tier-9-card', unlocked: state.seraphCount > 0 } ]; tierCards.forEach(tier => { const card = document.getElementById(tier.id); if (card) { if (tier.unlocked) { card.classList.remove('locked'); card.classList.add('unlocked'); } else { card.classList.add('locked'); card.classList.remove('unlocked'); } } }); const tierIds = ['tier-2-card', 'tier-3-card', 'tier-4-card', 'tier-5-card', 'tier-6-card', 'tier-7-card', 'tier-8-card']; const panelCardIds = ['principality-angel-panel-card', 'power-angel-panel-card', 'virtue-angel-panel-card', 'dominion-angel-panel-card', 'throne-angel-panel-card', 'cherub-angel-panel-card', 'seraph-angel-panel-card']; tierIds.forEach((tierId, i) => { const card = document.getElementById(panelCardIds[i]); if (card) { if (tierCards[i+1].unlocked) { card.classList.remove('locked'); card.classList.add('unlocked'); } else { card.classList.add('locked'); card.classList.remove('unlocked'); } } }); const archCard = document.getElementById('archangel-angel-panel-card'); if (archCard && tierCards[8].unlocked) { archCard.classList.remove('locked'); archCard.classList.add('unlocked'); } else if (archCard) { archCard.classList.add('locked'); archCard.classList.remove('unlocked'); } } // ============================================ // GAME LOGIC FUNCTIONS // ============================================ function prayForAnswers(event) { state.humans += 10; updateUI(); const rect = event.target.getBoundingClientRect(); const x = rect.left + rect.width / 2; const y = rect.top + rect.height / 2; playClickSound(); createFloatingNumber(x, y, 10, '#E91E63'); createParticleBurst(x, y, '#E91E63'); createSparkle(x, y, '#E91E63'); } function buyAngel(tier, quantity) { let baseCost, currentCurrency, currencyName, countVar; switch (tier) { case 'common': baseCost = state.commonBaseCost; currentCurrency = 'prayers'; currencyName = 'Prayers'; countVar = 'commonCount'; break; case 'principality': baseCost = state.principalityBaseCost; currentCurrency = 'grace'; currencyName = 'Grace'; countVar = 'principalityCount'; break; case 'power': baseCost = state.powerBaseCost; currentCurrency = 'sacredVessels'; currencyName = 'Sacred Vessels'; countVar = 'powerCount'; break; case 'virtue': baseCost = state.virtueBaseCost; currentCurrency = 'blessings'; currencyName = 'Blessings'; countVar = 'virtueCount'; break; case 'dominion': baseCost = state.dominionBaseCost; currentCurrency = 'souls'; currencyName = 'Souls'; countVar = 'dominionCount'; break; case 'throne': baseCost = state.thronesBaseCost; currentCurrency = 'wisdom'; currencyName = 'Wisdom'; countVar = 'thronesCount'; break; case 'cherub': baseCost = state.cherubBaseCost; currentCurrency = 'manna'; currencyName = 'Manna'; countVar = 'cherubCount'; break; case 'seraph': baseCost = state.seraphBaseCost; currentCurrency = 'miracles'; currencyName = 'Miracles'; countVar = 'seraphCount'; break; case 'archangel': baseCost = state.archangelCost; currentCurrency = 'sacredIcons'; currencyName = 'Sacred Icons'; countVar = 'archangelCount'; break; default: return; } const scaledBaseCost = getCurrentCost(baseCost, state[countVar]); const costToPay = scaledBaseCost * quantity; if (state[currentCurrency] >= costToPay) { const eventTarget = document.activeElement; playBuySound(); createFloatingNumber(eventTarget.getBoundingClientRect().left + 50, eventTarget.getBoundingClientRect().top, costToPay, '#4CAF50'); createParticleBurst(eventTarget.getBoundingClientRect().left + 100, eventTarget.getBoundingClientRect().top, '#4CAF50'); state[currentCurrency] -= costToPay; state[countVar] += quantity; showStatus(`Purchased ${quantity} x ${tier.toUpperCase()}!`); updateUI(); } else { const eventTarget = document.activeElement; showStatus(`Not enough ${currencyName}! Need ${costToPay}`); createParticleBurst(eventTarget.getBoundingClientRect().left, eventTarget.getBoundingClientRect().top, '#FF5722'); setTimeout(updateUI, 100); } } function prestigeAscend(event) { const ascendCost = 1 * state.ascensionCount; if (state.virtuePoints >= ascendCost) { state.virtuePoints -= ascendCost; state.virtuePoints += 1; state.ascensionCount++; state.globalMultiplier *= 1.5; state.humans = 0; state.prayers = 0; state.souls = 0; state.commonCount = 0; state.principalityCount = 0; state.powerCount = 0; state.virtueCount = 0; state.dominionCount = 0; state.thronesCount = 0; state.cherubCount = 0; state.seraphCount = 0; const rect = event.target.getBoundingClientRect(); playPrestigeSound(); createParticleBurst(rect.left + rect.width / 2, rect.top + rect.height / 2, '#ffd700'); createSparkle(rect.left + rect.width / 2, rect.top + rect.height / 2, '#ffd700'); showStatus(`🌟 ASCENDED! Tiers Ascended: ${state.ascensionCount} | Multiplier: ${state.globalMultiplier.toFixed(1)}x`); updateUI(); } else { const rect = event.target.getBoundingClientRect(); showStatus(`Not enough Virtue Points! Need ${ascendCost}`); event.target.style.background = '#c62828'; setTimeout(() => event.target.style.background = '', 300); } } function saveGame() { localStorage.setItem('celestialHierarchySave', JSON.stringify(state)); showStatus('Game saved successfully!'); if (soundEnabled) playClickSound(); const rect = document.getElementById('save-btn').getBoundingClientRect(); createFloatingNumber(rect.left + 50, rect.top - 20, '💾', '#2E7D32'); } function loadGame() { const saved = localStorage.getItem('celestialHierarchySave'); if (saved) { try { const loadedState = JSON.parse(saved); state = {...state, ...loadedState}; showStatus('Game loaded successfully!'); } catch (e) { showStatus('Load failed: corrupted save data'); console.error(e); } } else { showStatus('No save found. Starting new game!'); } updateUI(); if (soundEnabled) playClickSound(); const rect = document.getElementById('load-btn').getBoundingClientRect(); createFloatingNumber(rect.left + 30, rect.top - 20, '📂', '#1976d2'); } function newGame() { if (confirm('Are you sure? All progress will be lost.')) { localStorage.removeItem('celestialHierarchySave'); state = { humans: 0, prayers: 0, grace: 0, sacredVessels: 0, holyScripture: 0, blessings: 0, manna: 0, souls: 0, wisdom: 0, miracles: 0, auras: 0, sacredIcons: 0, commonCount: 0, principalityCount: 0, powerCount: 0, virtueCount: 0, dominionCount: 0, thronesCount: 0, cherubCount: 0, seraphCount: 0, archangelCount: 0, commonBaseCost: 50, principalityBaseCost: 150, powerBaseCost: 250, virtueBaseCost: 400, dominionBaseCost: 600, thronesBaseCost: 800, cherubBaseCost: 1000, seraphBaseCost: 1500, archangelCost: 500, unlockRequirements: { tier2: 50, tier3: 100, tier4: 150, tier5: 200, tier6: 250, tier7: 300, tier8: 350, tier9: 0 }, costScalingFactor: 1.15, globalMultiplier: 1.0, ascensionCount: 0, lastTick: Date.now() }; showStatus('Starting new game!'); if (soundEnabled) playClickSound(); const rect = document.getElementById('new-btn').getBoundingClientRect(); createFloatingNumber(rect.left + 30, rect.top - 20, '🆕', '#c62828'); updateUI(); } } function toggleSound() { soundEnabled = !soundEnabled; document.getElementById('sound-status').textContent = soundEnabled ? 'ON' : 'OFF'; if (soundEnabled) playClickSound(); } // ============================================ // GAME LOOP // ============================================ function gameLoop() { const now = Date.now(); const elapsed = Math.max((now - state.lastTick) / 1000, 0.01); let virtueGain = 0; if (state.virtueCount > 0) virtueGain += state.virtueCount * 0.1 * elapsed; if (state.dominionCount > 0) virtueGain += state.dominionCount * 0.2 * elapsed; if (state.archangelCount > 0) virtueGain += state.archangelCount * 1.0 * elapsed; state.virtuePoints += virtueGain; if (state.humans > 0) { const prayerMultiplier = calculatePrayerMultiplier(); const prayerRateFromHumans = state.humans * 0.5; state.prayers += (prayerRateFromHumans * elapsed * prayerMultiplier); } if (state.commonCount > 0) { state.grace += (state.commonCount * 1 * elapsed); } if (state.principalityCount > 0) { state.sacredVessels += (state.souls * 0.1 * elapsed); } if (state.powerCount > 0) { state.holyScripture += (state.grace * 0.2 * elapsed); } if (state.virtueCount > 0) { state.manna += (state.sacredVessels * 0.15 * elapsed); if (state.commonCount > 0) { const soulsMultiplier = calculateSoulsMultiplier(); state.souls += (state.prayers * 0.5 * elapsed * soulsMultiplier); } } if (state.dominionCount > 0) { state.wisdom += (state.manna * 0.2 * elapsed); } if (state.thronesCount > 0) { state.miracles += (state.souls * 0.4 * elapsed); } if (state.cherubCount > 0) { state.auras += (state.wisdom * 0.15 * elapsed); } if (state.seraphCount > 0) { state.sacredIcons += (state.miracles * 0.25 * elapsed); } state.lastTick = now; updateUI(); } // ============================================ // INITIALIZATION // ============================================ document.addEventListener('DOMContentLoaded', function() { initAudio(); document.getElementById('prayer-btn').addEventListener('click', prayForAnswers); const quickBuyButtons = document.querySelectorAll('.buy-option-btn'); quickBuyButtons.forEach(btn => { const tier = btn.getAttribute('data-tier'); const qty = parseInt(btn.getAttribute('data-qty')); if (tier && qty) { btn.addEventListener('click', (e) => { e.preventDefault(); buyAngel(tier, qty); }); } }); document.getElementById('ascend-btn').addEventListener('click', prestigeAscend); document.getElementById('save-btn').addEventListener('click', saveGame); document.getElementById('load-btn').addEventListener('click', loadGame); document.getElementById('new-btn').addEventListener('click', newGame); document.getElementById('sound-toggle-btn').addEventListener('click', toggleSound); loadGame(); updateUI(); setInterval(gameLoop, 100); });