Initial Push
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
client:
|
||||
image: nginx
|
||||
ports:
|
||||
- 82:80
|
||||
volumes:
|
||||
- ./:/usr/share/nginx/html
|
||||
@@ -0,0 +1,732 @@
|
||||
// ============================================
|
||||
// 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);
|
||||
});
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Celestial Hierarchy - Human Engine</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Hamburger Button -->
|
||||
<button class="hamburger-btn" onclick="toggleSidePanel()">
|
||||
<span></span><span></span><span></span>
|
||||
</button>
|
||||
|
||||
<!-- Overlay -->
|
||||
<div class="overlay" id="overlay" onclick="closeSidePanel()"></div>
|
||||
|
||||
<!-- Side Panel (Hamburger Menu) -->
|
||||
<div class="side-panel" id="sidePanel">
|
||||
<div class="panel-header">
|
||||
<h2>👼 Angelic Summoning</h2>
|
||||
<button class="close-panel-btn" onclick="closeSidePanel()">×</button>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center; color: #888; margin-bottom: 20px;">View currencies in the Left Sidebar</div>
|
||||
|
||||
<!-- Panel Angel Cards -->
|
||||
<div id="panel-angels-container">
|
||||
<!-- Tier 1: Common Angels -->
|
||||
<div class="angel-card unlocked" id="common-angel-panel-card">
|
||||
<div class="tier-badge tier-common">Tier 1</div>
|
||||
<div class="angel-name">Common Angel</div>
|
||||
<div class="angel-count" id="panel-common-count">0</div>
|
||||
<div class="angel-cost" id="panel-common-cost">Cost: 50 Prayers</div>
|
||||
<div class="angel-buff">+1 Grace/sec each</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="common" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="common" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="common" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="common" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 2: Principalities -->
|
||||
<div class="angel-card locked" id="principality-angel-panel-card">
|
||||
<div class="tier-badge tier-principalities">Tier 2</div>
|
||||
<div class="angel-name">Principalities Angel</div>
|
||||
<div class="angel-count" id="panel-principality-count">0</div>
|
||||
<div class="angel-cost" id="panel-principality-cost">Cost: 150 Grace</div>
|
||||
<!-- CORRECTED: Unlocks based on Grace now -->
|
||||
<div class="unlock-req">Requires 150 Grace to unlock Tier 2</div>
|
||||
<div class="angel-buff">+10% nearby bonus</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="principality" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="principality" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="principality" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="principality" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 3: Powers -->
|
||||
<div class="angel-card locked" id="power-angel-panel-card">
|
||||
<div class="tier-badge tier-powers">Tier 3</div>
|
||||
<div class="angel-name">Power Angel</div>
|
||||
<div class="angel-count" id="panel-power-count">0</div>
|
||||
<div class="angel-cost" id="panel-power-cost">Cost: 250 Sacred Vessels</div>
|
||||
<div class="unlock-req">Requires 100 Sacred Vessels to unlock Tier 3</div>
|
||||
<div class="angel-buff">+15% resource collection</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="power" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="power" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="power" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="power" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 4: Virtues -->
|
||||
<div class="angel-card locked" id="virtue-angel-panel-card">
|
||||
<div class="tier-badge tier-virtues">Tier 4</div>
|
||||
<div class="angel-name">Virtue Angel</div>
|
||||
<div class="angel-count" id="panel-virtue-count">0</div>
|
||||
<div class="angel-cost" id="panel-virtue-cost">Cost: 400 Blessings</div>
|
||||
<div class="unlock-req">Requires 150 Manna to unlock Tier 4</div>
|
||||
<div class="angel-buff">+25% miracle chance</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="virtue" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="virtue" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="virtue" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="virtue" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 5: Dominions -->
|
||||
<div class="angel-card locked" id="dominion-angel-panel-card">
|
||||
<div class="tier-badge tier-dominions">Tier 5</div>
|
||||
<div class="angel-name">Dominion Angel</div>
|
||||
<div class="angel-count" id="panel-dominion-count">0</div>
|
||||
<div class="angel-cost" id="panel-dominion-cost">Cost: 600 Souls</div>
|
||||
<div class="unlock-req">Requires 200 Wisdom to unlock Tier 5</div>
|
||||
<div class="angel-buff">+20% all output</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="dominion" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="dominion" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="dominion" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="dominion" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 6: Thrones -->
|
||||
<div class="angel-card locked" id="throne-angel-panel-card">
|
||||
<div class="tier-badge tier-thrones">Tier 6</div>
|
||||
<div class="angel-name">Throne Angel</div>
|
||||
<div class="angel-count" id="panel-throne-count">0</div>
|
||||
<div class="angel-cost" id="panel-throne-cost">Cost: 800 Wisdom</div>
|
||||
<div class="unlock-req">Requires 250 Miracles to unlock Tier 6</div>
|
||||
<div class="angel-buff">+15% efficiency</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="throne" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="throne" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="throne" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="throne" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 7: Cherubim -->
|
||||
<div class="angel-card locked premium-angel" id="cherub-angel-panel-card">
|
||||
<div class="tier-badge tier-cherubim">Tier 7</div>
|
||||
<div class="angel-name">Cherubim Guardian</div>
|
||||
<div class="angel-count" id="panel-cherub-count">0</div>
|
||||
<div class="angel-cost" id="panel-cherub-cost">Cost: 1000 Manna</div>
|
||||
<div class="unlock-req">Requires 300 Auras to unlock Tier 7</div>
|
||||
<div class="angel-buff">-25% spawn costs</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="cherub" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="cherub" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="cherub" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="cherub" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 8: Seraphim -->
|
||||
<div class="angel-card locked premium-angel" id="seraph-angel-panel-card">
|
||||
<div class="tier-badge tier-seraphim">Tier 8</div>
|
||||
<div class="angel-name">Seraphim Fire Angel</div>
|
||||
<div class="angel-count" id="panel-seraph-count">0</div>
|
||||
<div class="angel-cost" id="panel-seraph-cost">Cost: 1500 Miracles</div>
|
||||
<div class="unlock-req">Requires 350 Sacred Icons to unlock Tier 8</div>
|
||||
<div class="angel-buff">+5x Prayer generation</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="seraph" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="seraph" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="seraph" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="seraph" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tier 9: Arch-Angels -->
|
||||
<div class="angel-card locked premium-angel" id="archangel-angel-panel-card">
|
||||
<div class="tier-badge tier-archangels">Tier 9</div>
|
||||
<div class="angel-name">Arch-Angel (Michael/Gabriel)</div>
|
||||
<div class="angel-count" id="panel-archangel-count">0</div>
|
||||
<div class="angel-cost" id="panel-archangel-cost">Cost: 500 Sacred Icons</div>
|
||||
<div class="unlock-req">Requires Tier 8 to unlock Tier 9</div>
|
||||
<div class="angel-buff">10x+ Multiplier! Ultimate!</div>
|
||||
<div class="quick-buys">
|
||||
<button class="buy-option-btn" data-tier="archangel" data-qty="1">x1</button>
|
||||
<button class="buy-option-btn" data-tier="archangel" data-qty="5">x5</button>
|
||||
<button class="buy-option-btn" data-tier="archangel" data-qty="10">x10</button>
|
||||
<button class="buy-option-btn" data-tier="archangel" data-qty="100">x100</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Game Content Wrapper -->
|
||||
<div class="main-layout">
|
||||
|
||||
<!-- LEFT SIDEBAR: All Currencies -->
|
||||
<aside class="sidebar">
|
||||
<div class="currency-frame">
|
||||
<h3>💎 Divine Currencies</h3>
|
||||
|
||||
<div class="currency-row humans-currency">
|
||||
<span class="currency-name">Humans</span>
|
||||
<span class="currency-amount" id="sidebar-humans-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row prayers-currency">
|
||||
<span class="currency-name">Prayers</span>
|
||||
<span class="currency-amount" id="sidebar-prayers-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row grace-currency">
|
||||
<span class="currency-name">Grace</span>
|
||||
<span class="currency-amount" id="sidebar-grace-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row vessel-currency">
|
||||
<span class="currency-name">Vessels</span>
|
||||
<span class="currency-amount" id="sidebar-vessel-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row scripture-currency">
|
||||
<span class="currency-name">Scripture</span>
|
||||
<span class="currency-amount" id="sidebar-scripture-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row blessing-currency">
|
||||
<span class="currency-name">Blessings</span>
|
||||
<span class="currency-amount" id="sidebar-blessing-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row manna-currency">
|
||||
<span class="currency-name">Manna</span>
|
||||
<span class="currency-amount" id="sidebar-manna-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row souls-currency">
|
||||
<span class="currency-name">Souls</span>
|
||||
<span class="currency-amount" id="sidebar-souls-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row wisdom-currency">
|
||||
<span class="currency-name">Wisdom</span>
|
||||
<span class="currency-amount" id="sidebar-wisdom-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row miracle-currency">
|
||||
<span class="currency-name">Miracles</span>
|
||||
<span class="currency-amount" id="sidebar-miracle-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row aura-currency">
|
||||
<span class="currency-name">Auras</span>
|
||||
<span class="currency-amount" id="sidebar-aura-display">0</span>
|
||||
</div>
|
||||
|
||||
<div class="currency-row icon-currency">
|
||||
<span class="currency-name">Icons</span>
|
||||
<span class="currency-amount" id="sidebar-icon-display">0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="production-info" style="margin-top: 20px;">
|
||||
<h4>⚡ Metrics (per sec)</h4>
|
||||
<div class="production-item">
|
||||
<span>Prayers:</span>
|
||||
<span id="prayer-click-rate">10.0</span>
|
||||
</div>
|
||||
<div class="production-item">
|
||||
<span>Holy Power:</span>
|
||||
<span id="holy-power">1000</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sound Toggle -->
|
||||
<div class="sound-toggle">
|
||||
<button id="sound-toggle-btn" class="sound-btn">🔊 Sound: <span id="sound-status">ON</span></button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- RIGHT GAME CONTENT -->
|
||||
<main class="game-content">
|
||||
<h1 style="color: #ffd700; text-align: center; margin-bottom: 10px;">🕊️ CELESTIAL HIERARCHY 🕊️</h1>
|
||||
<p class="subtitle" style="text-align: center; color: #aaa; margin-bottom: 20px;">Ascend through the 9 Tiers of Heaven with 11 Currencies</p>
|
||||
|
||||
<!-- Tier Display Section -->
|
||||
<div class="tier-display-section">
|
||||
<h3>🌟 Angelic Tiers Unlocked</h3>
|
||||
|
||||
<div class="tiers-grid">
|
||||
<div class="tier-card unlocked" id="tier-1-card">
|
||||
<div class="tier-badge tier-common">Tier 1</div>
|
||||
<div class="tier-name">Common Angels</div>
|
||||
<div class="tier-count" id="common-count">0</div>
|
||||
<div class="tier-desc">+1 Grace/sec | Cost: Prayers</div>
|
||||
</div>
|
||||
|
||||
<div class="tier-card locked" id="tier-2-card">
|
||||
<div class="tier-badge tier-principalities">Tier 2</div>
|
||||
<div class="tier-name">Principalities</div>
|
||||
<div class="tier-count" id="principality-count">0</div>
|
||||
<div class="tier-desc">+10% bonus | Cost: Grace (150 Grace unlock)</div>
|
||||
</div>
|
||||
|
||||
<div class="tier-card locked" id="tier-3-card">
|
||||
<div class="tier-badge tier-powers">Tier 3</div>
|
||||
<div class="tier-name">Powers</div>
|
||||
<div class="tier-count" id="power-count">0</div>
|
||||
<div class="tier-desc">+15% resource | Cost: Vessels (100 Vessels unlock)</div>
|
||||
</div>
|
||||
|
||||
<div class="tier-card locked" id="tier-4-card">
|
||||
<div class="tier-badge tier-virtues">Tier 4</div>
|
||||
<div class="tier-name">Virtues</div>
|
||||
<div class="tier-count" id="virtue-count">0</div>
|
||||
<div class="tier-desc">+25% miracle | Cost: Blessings (150 Manna unlock)</div>
|
||||
</div>
|
||||
|
||||
<div class="tier-card locked" id="tier-5-card">
|
||||
<div class="tier-badge tier-dominions">Tier 5</div>
|
||||
<div class="tier-name">Dominions</div>
|
||||
<div class="tier-count" id="dominion-count">0</div>
|
||||
<div class="tier-desc">+20% output | Cost: Souls (200 Wisdom unlock)</div>
|
||||
</div>
|
||||
|
||||
<div class="tier-card locked" id="tier-6-card">
|
||||
<div class="tier-badge tier-thrones">Tier 6</div>
|
||||
<div class="tier-name">Thrones</div>
|
||||
<div class="tier-count" id="throness-count">0</div>
|
||||
<div class="tier-desc">+15% efficiency | Cost: Wisdom (250 Miracles unlock)</div>
|
||||
</div>
|
||||
|
||||
<div class="tier-card locked" id="tier-7-card">
|
||||
<div class="tier-badge tier-cherubim">Tier 7</div>
|
||||
<div class="tier-name">Cherubim</div>
|
||||
<div class="tier-count" id="cherub-count">0</div>
|
||||
<div class="tier-desc">Cost Reduction | Cost: Manna (300 Auras unlock)</div>
|
||||
</div>
|
||||
|
||||
<div class="tier-card locked" id="tier-8-card">
|
||||
<div class="tier-badge tier-seraphim">Tier 8</div>
|
||||
<div class="tier-name">Seraphim</div>
|
||||
<div class="tier-count" id="seraph-count">0</div>
|
||||
<div class="tier-desc">+5x Prayer | Cost: Miracles (350 Icons unlock)</div>
|
||||
</div>
|
||||
|
||||
<div class="tier-card locked" id="tier-9-card">
|
||||
<div class="tier-badge tier-archangels">Tier 9</div>
|
||||
<div class="tier-name">Arch-Angels</div>
|
||||
<div class="tier-count" id="archangel-count">0</div>
|
||||
<div class="tier-desc">10x+ Multiplier | Cost: Sacred Icons (Tier 8 unlock)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Prayer Section -->
|
||||
<div class="prayer-section">
|
||||
<h3>🙏 Human Summoning</h3>
|
||||
<button id="prayer-btn" class="click-btn glow-btn">🔮 Pray for Humans (+10 Humans)</button>
|
||||
</div>
|
||||
|
||||
<!-- Prestige Section -->
|
||||
<div class="prestige-section">
|
||||
<h3>🔯 Ascension (Prestige)</h3>
|
||||
<p style="text-align: center; margin-bottom: 10px;">Reset progress for permanent bonuses!</p>
|
||||
|
||||
<button id="ascend-btn" class="buy-option-btn">Ascend to Heaven (Cost: 1 Virtue Point)</button>
|
||||
|
||||
<div class="multiplier-display">
|
||||
✨ Global Bonus: <span id="global-multiplier">1.0</span>x
|
||||
</div>
|
||||
|
||||
<div class="prestige-counter">
|
||||
Ascensions: <span id="ascension-count">0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="action-buttons">
|
||||
<button id="save-btn" class="action-btn glow-btn save-btn">💾 Save</button>
|
||||
<button id="load-btn" class="action-btn glow-btn load-btn">📂 Load</button>
|
||||
<button id="new-btn" class="action-btn glow-btn new-btn">🆕 New Game</button>
|
||||
</div>
|
||||
|
||||
<!-- Status -->
|
||||
<div class="status-bar" id="status-display">Welcome to Celestial Hierarchy!</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="game.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,413 @@
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||||
color: #fff;
|
||||
min-height: 100vh;
|
||||
padding: 15px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Main Layout Grid */
|
||||
.main-layout {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 300px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.game-content {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Hamburger Button */
|
||||
.hamburger-btn {
|
||||
position: fixed;
|
||||
top: 15px;
|
||||
right: 280px;
|
||||
background: linear-gradient(145deg, #7b1fa2, #4a148c);
|
||||
border: none;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
z-index: 1001;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.hamburger-btn:hover { transform: scale(1.1); background: linear-gradient(145deg, #9c27b0, #6a1b9a); }
|
||||
|
||||
.hamburger-btn span {
|
||||
display: block;
|
||||
width: 24px;
|
||||
height: 3px;
|
||||
background: #fff;
|
||||
margin: 5px auto;
|
||||
border-radius: 3px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.hamburger-btn.active span:nth-child(1) { transform: rotate(45deg) translate(8px, 8px); }
|
||||
.hamburger-btn.active span:nth-child(2) { opacity: 0; }
|
||||
.hamburger-btn.active span:nth-child(3) { transform: rotate(-45deg) translate(7px, -6px); }
|
||||
|
||||
/* Side Panel */
|
||||
.side-panel {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: -400px;
|
||||
width: 380px;
|
||||
height: 100vh;
|
||||
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
|
||||
box-shadow: -5px 0 15px rgba(0, 0, 0, 0.5);
|
||||
z-index: 1000;
|
||||
transition: right 0.4s ease-in-out;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.side-panel.open { right: 0; }
|
||||
|
||||
.panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 2px solid #ffd700;
|
||||
}
|
||||
|
||||
.panel-header h2 { color: #ffd700; font-size: 1.4rem; }
|
||||
|
||||
.close-panel-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.close-panel-btn:hover { color: #ffd700; transform: rotate(90deg); }
|
||||
|
||||
/* Currency Sidebar */
|
||||
.currency-frame {
|
||||
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.currency-frame h3 {
|
||||
margin-bottom: 10px;
|
||||
color: #ffd700;
|
||||
font-size: 1.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.currency-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 12px;
|
||||
margin: 3px 0;
|
||||
border-radius: 5px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.currency-name {
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 140px;
|
||||
}
|
||||
|
||||
.currency-amount { font-weight: bold; font-size: 1.1rem; min-width: 60px; text-align: right; }
|
||||
|
||||
/* Currency Colors */
|
||||
.humans-currency { background-color: #FCE4EC; color: #E91E63; }
|
||||
.prayers-currency { background-color: #E8F5E9; color: #2E7D32; }
|
||||
.grace-currency { background-color: #FFF3E0; color: #E65100; }
|
||||
.vessel-currency { background-color: #E3F2FD; color: #1565C0; }
|
||||
.scripture-currency { background-color: #F3E5F5; color: #7B1FA2; }
|
||||
.blessing-currency { background-color: #FFECB3; color: #FF8F00; }
|
||||
.manna-currency { background-color: #C8E6C9; color: #388E3C; }
|
||||
.souls-currency { background-color: #FFCCBC; color: #D84315; }
|
||||
.wisdom-currency { background-color: #BBDEFB; color: #0277BD; }
|
||||
.miracle-currency { background-color: #FFE0B2; color: #E65100; }
|
||||
.aura-currency { background-color: #E1BEE7; color: #8E24AA; }
|
||||
.icon-currency { background-color: #FFF9C4; color: #FBC02D; box-shadow: 0 0 5px #FFD700; }
|
||||
|
||||
/* Tier Display */
|
||||
.tier-badge {
|
||||
display: inline-block;
|
||||
padding: 3px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 0.65rem;
|
||||
font-weight: bold;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.tier-common { background-color: #9E9E9E; color: white; }
|
||||
.tier-principalities { background-color: #4CAF50; color: white; }
|
||||
.tier-powers { background-color: #FF5722; color: white; }
|
||||
.tier-virtues { background-color: #FFD700; color: black; }
|
||||
.tier-dominions { background-color: #9C27B0; color: white; }
|
||||
.tier-thrones { background-color: #03A9F4; color: white; }
|
||||
.tier-cherubim { background-color: #8BC34A; color: black; }
|
||||
.tier-seraphim { background-color: #E91E63; color: white; }
|
||||
.tier-archangels { background-color: #FFD700; color: black; box-shadow: 0 0 15px #FFD700; }
|
||||
|
||||
/* Tier Display Section */
|
||||
.tier-display-section {
|
||||
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.tier-display-section h3 {
|
||||
color: #ffd700;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tiers-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.tier-card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
padding: 8px;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tier-card.locked { opacity: 0.3; pointer-events: none; }
|
||||
.tier-card.unlocked { opacity: 1; }
|
||||
|
||||
.tier-name { font-size: 0.85rem; color: #ffd700; margin-bottom: 4px; }
|
||||
.tier-count { font-size: 1rem; color: #fff; margin-bottom: 3px; }
|
||||
.tier-desc { font-size: 0.65rem; color: #aaa; line-height: 1.2; }
|
||||
|
||||
/* Prayer Section */
|
||||
.prayer-section {
|
||||
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.prayer-section h3 { margin-bottom: 15px; color: #ffd700; text-align: center; font-size: 1.2rem; }
|
||||
|
||||
/* Click Button */
|
||||
.click-btn {
|
||||
display: block;
|
||||
width: 90%;
|
||||
margin: 20px auto;
|
||||
padding: 15px 30px;
|
||||
font-size: 1.1rem;
|
||||
background: linear-gradient(145deg, #7b1fa2, #4a148c);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.click-btn:hover { background: linear-gradient(145deg, #9c27b0, #6a1b9a); transform: scale(1.02); }
|
||||
.click-btn:active { transform: scale(0.98); }
|
||||
|
||||
/* Panel Angel Cards */
|
||||
.angel-card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 15px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.angel-card.locked { opacity: 0.4; pointer-events: none; }
|
||||
.angel-card.unlocked { opacity: 1; }
|
||||
|
||||
.premium-angel { border: 2px solid #ffd700; }
|
||||
|
||||
.angel-name { font-size: 1rem; color: #ffd700; margin-bottom: 5px; }
|
||||
.angel-count { font-size: 1.2rem; color: #fff; margin-bottom: 5px; }
|
||||
.angel-cost { font-size: 0.85rem; color: #aaa; margin-bottom: 3px; }
|
||||
.angel-buff { font-size: 0.7rem; color: #4CAF50; line-height: 1.2; margin-top: 3px; }
|
||||
|
||||
/* Panel Angel Buttons */
|
||||
.buy-option-btn {
|
||||
background: linear-gradient(145deg, #7b1fa2, #4a148c);
|
||||
border: none;
|
||||
padding: 6px 10px;
|
||||
color: white;
|
||||
font-size: 0.8rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.buy-option-btn:hover:not(:disabled) { background: linear-gradient(145deg, #9c27b0, #6a1b9a); }
|
||||
.buy-option-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
|
||||
.quick-buys { display: flex; gap: 5px; margin-top: 8px; justify-content: center; }
|
||||
|
||||
/* Panel Unlock Requirements */
|
||||
.unlock-req { font-size: 0.7rem; color: #FFB300; margin-top: 4px; text-align: center; }
|
||||
|
||||
/* Prestige Section */
|
||||
.prestige-section {
|
||||
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
||||
border: 2px solid #ffd700;
|
||||
}
|
||||
|
||||
.prestige-section h3 {
|
||||
color: #ffd700;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
/* Prestige Counter */
|
||||
.prestige-counter {
|
||||
text-align: center;
|
||||
font-size: 2rem;
|
||||
color: #ffd700;
|
||||
margin-top: 15px;
|
||||
text-shadow: 0 0 20px rgba(255, 215, 0, 0.8);
|
||||
}
|
||||
|
||||
.multiplier-display {
|
||||
text-align: center;
|
||||
font-size: 1.2rem;
|
||||
color: #ffd700;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* Production Info */
|
||||
.production-info {
|
||||
background: linear-gradient(145deg, #2a2a4a, #1e1e3a);
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.production-info h4 { color: #ffd700; margin-bottom: 10px; }
|
||||
|
||||
.production-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
/* Action Buttons */
|
||||
.action-buttons { display: flex; justify-content: center; gap: 15px; margin: 15px 0; }
|
||||
|
||||
.action-btn {
|
||||
padding: 12px 25px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.save-btn { background: linear-gradient(145deg, #2e7d32, #1b5e20); color: white; }
|
||||
.load-btn { background: linear-gradient(145deg, #1976d2, #0d47a1); color: white; }
|
||||
.new-btn { background: linear-gradient(145deg, #c62828, #b71c1c); color: white; }
|
||||
|
||||
.action-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); }
|
||||
|
||||
/* Status */
|
||||
.status-bar { text-align: center; padding: 10px; font-size: 1rem; color: #aaa; min-height: 24px; margin-bottom: 15px;}
|
||||
|
||||
/* Floating Numbers Animation */
|
||||
.floating-number {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
font-weight: bold;
|
||||
animation: floatUp 1.5s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes floatUp {
|
||||
0% { opacity: 1; transform: translateY(0) scale(1); }
|
||||
100% { opacity: 0; transform: translateY(-100px) scale(1.5); }
|
||||
}
|
||||
|
||||
/* Particle Effects */
|
||||
.particle {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
z-index: 999;
|
||||
border-radius: 50%;
|
||||
animation: particleAnim 1s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes particleAnim {
|
||||
0% { opacity: 1; transform: translate(0, 0) scale(1); }
|
||||
100% { opacity: 0; transform: translate(var(--tx), var(--ty)) scale(0.2); }
|
||||
}
|
||||
|
||||
/* Sparkle Effect */
|
||||
.sparkle {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
z-index: 998;
|
||||
animation: sparkleAnim 0.6s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes sparkleAnim {
|
||||
0% { opacity: 1; transform: scale(0); }
|
||||
50% { opacity: 1; transform: scale(1.2); }
|
||||
100% { opacity: 0; transform: scale(0); }
|
||||
}
|
||||
|
||||
/* Sound Toggle */
|
||||
.sound-toggle { text-align: center; margin-top: 10px; }
|
||||
.sound-btn { background: #333; color: #fff; padding: 8px 20px; border-radius: 5px; cursor: pointer; font-size: 0.9rem; border: none;}
|
||||
|
||||
/* Backdrop overlay */
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.overlay.active { display: block; }
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.main-layout { flex-direction: column; }
|
||||
.sidebar { width: 100%; }
|
||||
.hamburger-btn { right: 15px; }
|
||||
}
|
||||
Reference in New Issue
Block a user