🐳 04/03 - 15:53 - bei games wo too expensive steht sollte auch der preis stehen, aber dann der kauf button nicht blau sein sondern ausgegraut, damit der spieler direkt weiß dass man dies noch nicht k
5e582f9 verified | // Computer Evolution Idle Game | |
| class ComputerEvolution { | |
| constructor() { | |
| this.money = 50; | |
| this.totalEarned = 0; | |
| this.investors = 0; | |
| this.soundEnabled = true; | |
| this.lastSave = Date.now(); | |
| // Prestige system | |
| this.prestigeMultiplier = 1; | |
| this.totalPrestiges = 0; | |
| this.prestigeThreshold = 10; // Minimum 10% investors to prestige | |
| // Hardware | |
| this.hardware = { | |
| hdd: { | |
| quantity: 1, | |
| capacity: 12, // MB | |
| used: 0, | |
| baseCost: { quantity: 2.5, capacity: 1.9 }, | |
| costMultiplier: 1.5 | |
| }, | |
| cpu: { | |
| cores: 1, | |
| speed: 38.7, // MHz | |
| used: 0, | |
| baseCost: { cores: 50, speed: 23 }, | |
| costMultiplier: 1.6 | |
| }, | |
| ram: { | |
| quantity: 1, | |
| capacity: 31.3, // MB | |
| used: 0, | |
| baseCost: { quantity: 50, capacity: 23 }, | |
| costMultiplier: 1.5 | |
| }, | |
| motherboard: { | |
| level: 1, | |
| maxOS: 2, | |
| baseCost: 11.5, | |
| costMultiplier: 2.5 | |
| } | |
| }; | |
| // OS Levels | |
| this.osLevels = [ | |
| { name: "Sixtem 1.0", multiplier: 1, reqMotherboard: 1 }, | |
| { name: "Sixtem 2.0", multiplier: 1.5, reqMotherboard: 1 }, | |
| { name: "Sixtem 3.0", multiplier: 2.5, reqMotherboard: 2 }, | |
| { name: "Sixtem Pro", multiplier: 4, reqMotherboard: 3 }, | |
| { name: "Sixtem Ultra", multiplier: 7, reqMotherboard: 4 }, | |
| { name: "Quantum OS", multiplier: 12, reqMotherboard: 5 } | |
| ]; | |
| this.currentOS = 1; // Index | |
| // Apps | |
| this.availableApps = [ | |
| { id: 'terminal', name: 'Terminal', icon: 'terminal', cost: 0, income: 0.5, storage: 2, ram: 1, color: 'bg-gray-800', installed: true }, | |
| { id: 'loserar', name: 'Loserar', icon: 'file-archive', cost: 100, income: 2, storage: 4, ram: 2, color: 'bg-pink-500', installed: false }, | |
| { id: 'landbrush', name: 'Landbrush', icon: 'paintbrush', cost: 500, income: 5, storage: 8, ram: 4, color: 'bg-purple-500', installed: false }, | |
| { id: 'webnav', name: 'WebNav', icon: 'globe', cost: 2000, income: 12, storage: 16, ram: 8, color: 'bg-blue-500', installed: false }, | |
| { id: 'mailer', name: 'Mailer', icon: 'mail', cost: 8000, income: 30, storage: 32, ram: 16, color: 'bg-yellow-500', installed: false }, | |
| { id: 'musicbox', name: 'MusicBox', icon: 'music', cost: 25000, income: 80, storage: 64, ram: 32, color: 'bg-red-500', installed: false }, | |
| { id: 'videocut', name: 'VideoCut', icon: 'video', cost: 100000, income: 200, storage: 128, ram: 64, color: 'bg-indigo-500', installed: false }, | |
| { id: 'gamedev', name: 'GameDev', icon: 'gamepad-2', cost: 500000, income: 600, storage: 256, ram: 128, color: 'bg-green-500', installed: false } | |
| ]; | |
| this.installedApps = ['terminal']; | |
| this.init(); | |
| } | |
| init() { | |
| this.loadGame(); | |
| this.updateUI(); | |
| this.renderApps(); | |
| // Game loop | |
| setInterval(() => this.gameLoop(), 100); | |
| setInterval(() => this.saveGame(), 30000); // Auto-save every 30s | |
| // Update UI every 100ms for smooth progress bars | |
| setInterval(() => this.updateProgressBars(), 100); | |
| } | |
| gameLoop() { | |
| const income = this.calculateIncome(); | |
| this.money += income / 10; // Divide by 10 because we run 10 times per second | |
| this.totalEarned += income / 10; | |
| // Update investors based on total earned | |
| this.investors = Math.min(100, (this.totalEarned / 1000000) * 100); | |
| this.updateUI(); | |
| } | |
| calculateIncome() { | |
| let baseIncome = 1.6; // Base OS income | |
| // Add app incomes | |
| this.installedApps.forEach(appId => { | |
| const app = this.availableApps.find(a => a.id === appId); | |
| if (app) baseIncome += app.income; | |
| }); | |
| // Apply CPU speed multiplier | |
| const cpuMultiplier = 1 + (this.hardware.cpu.speed / 100); | |
| // Apply OS multiplier | |
| const osMultiplier = this.osLevels[this.currentOS].multiplier; | |
| // Apply Prestige multiplier | |
| // Formula: 1 + (investors% / 100) * 0.5 at 10%, up to 1 + (100/100) * 2 = 3x at 100% | |
| // But we use the stored prestigeMultiplier which is calculated at prestige time | |
| return baseIncome * cpuMultiplier * osMultiplier * this.prestigeMultiplier; | |
| } | |
| calculatePrestigeBoost() { | |
| // Calculate potential boost based on current investors | |
| // At 10%: 1.1x boost (10% increase) | |
| // At 50%: 1.5x boost (50% increase) | |
| // At 100%: 2.5x boost (150% increase) | |
| if (this.investors < this.prestigeThreshold) return 0; | |
| // Formula: 1 + (investors / 100) * 1.5 | |
| // 10% = 1.15x, 100% = 2.5x | |
| const boost = 1 + (this.investors / 100) * 1.5; | |
| return boost; | |
| } | |
| canPrestige() { | |
| return this.investors >= this.prestigeThreshold; | |
| } | |
| prestige() { | |
| if (!this.canPrestige()) { | |
| this.showToast('Cannot Prestige', `You need at least ${this.prestigeThreshold}% investors!`); | |
| return; | |
| } | |
| const boost = this.calculatePrestigeBoost(); | |
| const oldMultiplier = this.prestigeMultiplier; | |
| this.prestigeMultiplier *= boost; | |
| this.totalPrestiges++; | |
| // Reset game progress | |
| this.money = 50; | |
| this.totalEarned = 0; | |
| this.investors = 0; | |
| // Reset hardware | |
| this.hardware = { | |
| hdd: { | |
| quantity: 1, | |
| capacity: 12, | |
| used: 0, | |
| baseCost: { quantity: 2.5, capacity: 1.9 }, | |
| costMultiplier: 1.5 | |
| }, | |
| cpu: { | |
| cores: 1, | |
| speed: 38.7, | |
| used: 0, | |
| baseCost: { cores: 50, speed: 23 }, | |
| costMultiplier: 1.6 | |
| }, | |
| ram: { | |
| quantity: 1, | |
| capacity: 31.3, | |
| used: 0, | |
| baseCost: { quantity: 50, capacity: 23 }, | |
| costMultiplier: 1.5 | |
| }, | |
| motherboard: { | |
| level: 1, | |
| maxOS: 2, | |
| baseCost: 11.5, | |
| costMultiplier: 2.5 | |
| } | |
| }; | |
| // Reset OS | |
| this.currentOS = 1; | |
| // Reset apps | |
| this.installedApps = ['terminal']; | |
| this.availableApps.forEach(app => { | |
| app.installed = app.id === 'terminal'; | |
| }); | |
| // Close modal if open | |
| this.toggleSettings(); | |
| this.showToast('Prestige Complete!', | |
| `Boost: ${boost.toFixed(2)}x\nTotal Multiplier: ${oldMultiplier.toFixed(2)}x → ${this.prestigeMultiplier.toFixed(2)}x`, | |
| 5000); | |
| this.updateUI(); | |
| this.renderApps(); | |
| this.saveGame(); | |
| } | |
| calculateUsage() { | |
| let storageUsed = 0; | |
| let ramUsed = 0; | |
| let cpuUsed = 0; | |
| this.installedApps.forEach(appId => { | |
| const app = this.availableApps.find(a => a.id === appId); | |
| if (app) { | |
| storageUsed += app.storage; | |
| ramUsed += app.ram; | |
| cpuUsed += app.income; // Higher income apps use more CPU | |
| } | |
| }); | |
| return { storage: storageUsed, ram: ramUsed, cpu: cpuUsed }; | |
| } | |
| formatMoney(amount) { | |
| if (amount >= 1e12) return '$' + (amount / 1e12).toFixed(2) + 'T'; | |
| if (amount >= 1e9) return '$' + (amount / 1e9).toFixed(2) + 'B'; | |
| if (amount >= 1e6) return '$' + (amount / 1e6).toFixed(2) + 'M'; | |
| if (amount >= 1e3) return '$' + (amount / 1e3).toFixed(2) + 'K'; | |
| return '$' + amount.toFixed(2); | |
| } | |
| formatBytes(mb) { | |
| if (mb >= 1024) return (mb / 1024).toFixed(2) + 'GB'; | |
| if (mb >= 1) return mb.toFixed(2) + 'MB'; | |
| return (mb * 1024).toFixed(0) + 'kB'; | |
| } | |
| formatFreq(mhz) { | |
| if (mhz >= 1000) return (mhz / 1000).toFixed(2) + 'GHz'; | |
| return mhz.toFixed(2) + 'MHz'; | |
| } | |
| getUpgradeCost(component, type) { | |
| const hw = this.hardware[component]; | |
| const currentLevel = hw[type]; | |
| return hw.baseCost[type] * Math.pow(hw.costMultiplier, currentLevel - 1); | |
| } | |
| getMotherboardCost() { | |
| const mb = this.hardware.motherboard; | |
| return mb.baseCost * Math.pow(mb.costMultiplier, mb.level - 1); | |
| } | |
| upgrade(component, type) { | |
| const cost = this.getUpgradeCost(component, type); | |
| if (this.money >= cost) { | |
| this.money -= cost; | |
| this.hardware[component][type]++; | |
| this.updateUI(); | |
| this.showToast('Upgrade Complete', `${component.toUpperCase()} ${type} upgraded!`); | |
| } | |
| } | |
| upgradeMotherboard() { | |
| const cost = this.getMotherboardCost(); | |
| if (this.money >= cost) { | |
| this.money -= cost; | |
| this.hardware.motherboard.level++; | |
| this.hardware.motherboard.maxOS = this.hardware.motherboard.level + 1; | |
| this.checkOSUpgrade(); | |
| this.updateUI(); | |
| this.showToast('Motherboard Upgraded', 'You can now install better OS versions!'); | |
| } | |
| } | |
| checkOSUpgrade() { | |
| // Auto-upgrade OS if possible | |
| for (let i = this.osLevels.length - 1; i >= 0; i--) { | |
| if (this.hardware.motherboard.level >= this.osLevels[i].reqMotherboard && i > this.currentOS) { | |
| this.currentOS = i; | |
| this.showToast('OS Upgraded', `Welcome to ${this.osLevels[i].name}!`); | |
| break; | |
| } | |
| } | |
| } | |
| installApp(appId) { | |
| const app = this.availableApps.find(a => a.id === appId); | |
| if (!app || app.installed) return; | |
| const usage = this.calculateUsage(); | |
| const maxStorage = this.hardware.hdd.capacity * this.hardware.hdd.quantity; | |
| const maxRam = this.hardware.ram.capacity * this.hardware.ram.quantity; | |
| if (usage.storage + app.storage > maxStorage) { | |
| this.showToast('Error', 'Not enough storage space!'); | |
| return; | |
| } | |
| if (usage.ram + app.ram > maxRam) { | |
| this.showToast('Error', 'Not enough RAM!'); | |
| return; | |
| } | |
| if (this.money < app.cost) { | |
| this.showToast('Error', 'Not enough money!'); | |
| return; | |
| } | |
| this.money -= app.cost; | |
| app.installed = true; | |
| this.installedApps.push(appId); | |
| this.renderApps(); | |
| this.updateUI(); | |
| this.closeAppStore(); | |
| this.showToast('App Installed', `${app.name} has been installed!`); | |
| } | |
| manualClick(event) { | |
| const amount = 1 + (this.hardware.cpu.cores * 0.5); | |
| this.money += amount; | |
| this.totalEarned += amount; | |
| // Visual feedback | |
| const floatEl = document.createElement('div'); | |
| floatEl.className = 'fixed pointer-events-none text-green-600 font-bold text-xl money-animation z-50'; | |
| floatEl.textContent = '+' + this.formatMoney(amount); | |
| floatEl.style.left = event.clientX + 'px'; | |
| floatEl.style.top = event.clientY + 'px'; | |
| document.body.appendChild(floatEl); | |
| setTimeout(() => floatEl.remove(), 1000); | |
| this.updateUI(); | |
| } | |
| updateUI() { | |
| // Header | |
| document.getElementById('balance-display').textContent = this.formatMoney(this.money); | |
| document.getElementById('income-display').textContent = this.formatMoney(this.calculateIncome()); | |
| document.getElementById('investors-display').textContent = this.investors.toFixed(1) + '%'; | |
| // Update prestige display | |
| const prestigeDisplay = document.getElementById('prestige-display'); | |
| const prestigeBtn = document.getElementById('prestige-btn'); | |
| const currentMultiplierEl = document.getElementById('current-prestige-multiplier'); | |
| const totalPrestigesEl = document.getElementById('total-prestiges'); | |
| if (prestigeDisplay) { | |
| prestigeDisplay.textContent = this.prestigeMultiplier.toFixed(2) + 'x'; | |
| } | |
| if (currentMultiplierEl) { | |
| currentMultiplierEl.textContent = this.prestigeMultiplier.toFixed(2) + 'x'; | |
| } | |
| if (totalPrestigesEl) { | |
| totalPrestigesEl.textContent = this.totalPrestiges; | |
| } | |
| // Update prestige button state | |
| if (prestigeBtn) { | |
| if (this.canPrestige()) { | |
| const potentialBoost = this.calculatePrestigeBoost(); | |
| const potentialMultiplier = this.prestigeMultiplier * potentialBoost; | |
| prestigeBtn.innerHTML = ` | |
| <div class="flex flex-col items-center"> | |
| <span class="font-bold">PRESTIGE NOW</span> | |
| <span class="text-xs opacity-90">+${potentialBoost.toFixed(2)}x boost (${this.investors.toFixed(1)}% investors)</span> | |
| <span class="text-xs opacity-75">New total: ${potentialMultiplier.toFixed(2)}x</span> | |
| </div> | |
| `; | |
| prestigeBtn.classList.remove('opacity-50', 'cursor-not-allowed'); | |
| prestigeBtn.classList.add('animate-pulse'); | |
| } else { | |
| prestigeBtn.innerHTML = ` | |
| <div class="flex flex-col items-center"> | |
| <span class="font-bold">PRESTIGE LOCKED</span> | |
| <span class="text-xs opacity-75">Need ${this.prestigeThreshold}% investors (${(this.prestigeThreshold - this.investors).toFixed(1)}% more)</span> | |
| </div> | |
| `; | |
| prestigeBtn.classList.add('opacity-50', 'cursor-not-allowed'); | |
| prestigeBtn.classList.remove('animate-pulse'); | |
| } | |
| } | |
| // HDD | |
| const maxStorage = this.hardware.hdd.capacity * this.hardware.hdd.quantity; | |
| const usage = this.calculateUsage(); | |
| const storagePercent = (usage.storage / maxStorage) * 100; | |
| document.getElementById('hdd-quantity').textContent = this.hardware.hdd.quantity; | |
| document.getElementById('hdd-capacity').textContent = this.formatBytes(this.hardware.hdd.capacity); | |
| document.getElementById('hdd-usage-text').textContent = `${this.formatBytes(maxStorage - usage.storage)} free of ${this.formatBytes(maxStorage)}`; | |
| document.getElementById('hdd-percent').textContent = storagePercent.toFixed(0) + '%'; | |
| document.getElementById('hdd-bar').style.width = storagePercent + '%'; | |
| document.getElementById('hdd-quantity-cost').textContent = this.formatMoney(this.getUpgradeCost('hdd', 'quantity')); | |
| document.getElementById('hdd-capacity-cost').textContent = this.formatMoney(this.getUpgradeCost('hdd', 'capacity')); | |
| // CPU | |
| const maxCpu = this.hardware.cpu.speed * this.hardware.cpu.cores; | |
| const cpuPercent = Math.min(100, (usage.cpu / maxCpu) * 100); | |
| document.getElementById('cpu-cores').textContent = this.hardware.cpu.cores; | |
| document.getElementById('cpu-speed').textContent = this.formatFreq(this.hardware.cpu.speed); | |
| document.getElementById('cpu-usage-text').textContent = `${this.formatFreq(maxCpu - usage.cpu)} free of ${this.formatFreq(maxCpu)}`; | |
| document.getElementById('cpu-percent').textContent = cpuPercent.toFixed(0) + '%'; | |
| document.getElementById('cpu-bar').style.width = cpuPercent + '%'; | |
| document.getElementById('cpu-cores-cost').textContent = this.formatMoney(this.getUpgradeCost('cpu', 'cores')); | |
| document.getElementById('cpu-speed-cost').textContent = this.formatMoney(this.getUpgradeCost('cpu', 'speed')); | |
| // RAM | |
| const maxRam = this.hardware.ram.capacity * this.hardware.ram.quantity; | |
| const ramPercent = (usage.ram / maxRam) * 100; | |
| document.getElementById('ram-quantity').textContent = this.hardware.ram.quantity; | |
| document.getElementById('ram-capacity').textContent = this.formatBytes(this.hardware.ram.capacity); | |
| document.getElementById('ram-usage-text').textContent = `${this.formatBytes(maxRam - usage.ram)} free of ${this.formatBytes(maxRam)}`; | |
| document.getElementById('ram-percent').textContent = ramPercent.toFixed(0) + '%'; | |
| document.getElementById('ram-bar').style.width = ramPercent + '%'; | |
| document.getElementById('ram-quantity-cost').textContent = this.formatMoney(this.getUpgradeCost('ram', 'quantity')); | |
| document.getElementById('ram-capacity-cost').textContent = this.formatMoney(this.getUpgradeCost('ram', 'capacity')); | |
| // Motherboard | |
| document.getElementById('supported-os').textContent = this.osLevels[Math.min(this.osLevels.length - 1, this.hardware.motherboard.maxOS - 1)].name; | |
| document.getElementById('motherboard-cost').textContent = this.formatMoney(this.getMotherboardCost()); | |
| // OS Panel | |
| const os = this.osLevels[this.currentOS]; | |
| document.getElementById('os-name').textContent = os.name; | |
| document.getElementById('os-income').textContent = this.formatMoney(this.calculateIncome()) + '/s'; | |
| document.getElementById('os-storage').textContent = this.formatBytes(usage.storage); | |
| document.getElementById('os-cpu').textContent = this.formatFreq(usage.cpu); | |
| document.getElementById('os-ram').textContent = this.formatBytes(usage.ram); | |
| // Click value | |
| document.getElementById('click-value').textContent = this.formatMoney(1 + (this.hardware.cpu.cores * 0.5)); | |
| // Update button states | |
| this.updateButtonStates(); | |
| } | |
| updateButtonStates() { | |
| // Disable buttons if not enough money | |
| const components = ['hdd', 'cpu', 'ram']; | |
| const types = { hdd: ['quantity', 'capacity'], cpu: ['cores', 'speed'], ram: ['quantity', 'capacity'] }; | |
| components.forEach(comp => { | |
| types[comp].forEach(type => { | |
| const btn = document.getElementById(`btn-${comp}-${type}`); | |
| if (btn) { | |
| btn.disabled = this.money < this.getUpgradeCost(comp, type); | |
| } | |
| }); | |
| }); | |
| const mbBtn = document.getElementById('btn-motherboard'); | |
| if (mbBtn) mbBtn.disabled = this.money < this.getMotherboardCost(); | |
| } | |
| updateProgressBars() { | |
| // Smooth updates for progress bars are handled in updateUI | |
| } | |
| renderApps() { | |
| const grid = document.getElementById('apps-grid'); | |
| grid.innerHTML = ''; | |
| this.installedApps.forEach(appId => { | |
| const app = this.availableApps.find(a => a.id === appId); | |
| if (app) { | |
| const div = document.createElement('div'); | |
| div.className = `app-card ${app.color} rounded-lg p-3 text-white shadow-md cursor-pointer aspect-square flex flex-col items-center justify-center gap-2`; | |
| div.innerHTML = ` | |
| <i data-lucide="${app.icon}" class="w-8 h-8"></i> | |
| <span class="text-xs font-semibold text-center">${app.name}</span> | |
| <span class="text-xs opacity-75">+${this.formatMoney(app.income)}/s</span> | |
| `; | |
| grid.appendChild(div); | |
| } | |
| }); | |
| lucide.createIcons(); | |
| } | |
| openAppStore() { | |
| const modal = document.getElementById('app-store-modal'); | |
| const content = document.getElementById('app-store-content'); | |
| content.innerHTML = ''; | |
| this.availableApps.filter(app => !app.installed).forEach(app => { | |
| const div = document.createElement('div'); | |
| div.className = 'flex items-center justify-between p-4 border border-gray-200 rounded-lg mb-3 hover:bg-gray-50 transition'; | |
| const canAfford = this.money >= app.cost; | |
| const usage = this.calculateUsage(); | |
| const maxStorage = this.hardware.hdd.capacity * this.hardware.hdd.quantity; | |
| const maxRam = this.hardware.ram.capacity * this.hardware.ram.quantity; | |
| const hasSpace = usage.storage + app.storage <= maxStorage && usage.ram + app.ram <= maxRam; | |
| div.innerHTML = ` | |
| <div class="flex items-center gap-4"> | |
| <div class="${app.color} w-12 h-12 rounded-lg flex items-center justify-center text-white"> | |
| <i data-lucide="${app.icon}" class="w-6 h-6"></i> | |
| </div> | |
| <div> | |
| <h4 class="font-bold text-gray-800">${app.name}</h4> | |
| <p class="text-sm text-gray-600">Income: +${this.formatMoney(app.income)}/s</p> | |
| <p class="text-xs text-gray-500">Uses: ${this.formatBytes(app.storage)} storage, ${this.formatBytes(app.ram)} RAM</p> | |
| </div> | |
| </div> | |
| <button onclick="game.installApp('${app.id}')" | |
| class="px-4 py-2 rounded font-semibold text-sm transition ${canAfford && hasSpace ? 'bg-blue-500 hover:bg-blue-600 text-white' : 'bg-gray-300 text-gray-500 cursor-not-allowed'}" | |
| ${!canAfford || !hasSpace ? 'disabled' : ''}> | |
| ${this.formatMoney(app.cost)} | |
| </button> | |
| `; | |
| content.appendChild(div); | |
| }); | |
| if (content.innerHTML === '') { | |
| content.innerHTML = '<p class="text-center text-gray-500 py-8">All apps installed! Check back later for updates.</p>'; | |
| } | |
| modal.classList.remove('hidden'); | |
| lucide.createIcons(); | |
| } | |
| closeAppStore() { | |
| document.getElementById('app-store-modal').classList.add('hidden'); | |
| } | |
| toggleSettings() { | |
| const modal = document.getElementById('settings-modal'); | |
| modal.classList.toggle('hidden'); | |
| } | |
| toggleSound() { | |
| this.soundEnabled = !this.soundEnabled; | |
| document.getElementById('sound-text').textContent = this.soundEnabled ? 'Sound' : 'Muted'; | |
| document.getElementById('sound-btn').classList.toggle('bg-emerald-600'); | |
| document.getElementById('sound-btn').classList.toggle('bg-gray-600'); | |
| } | |
| showInfo(component) { | |
| const info = { | |
| hdd: { title: 'Hard Drive', text: 'Stores your applications. Upgrade capacity to install more apps, or quantity for redundancy.' }, | |
| cpu: { title: 'Processor', text: 'Processes data. More cores and speed increases your income multiplier.' }, | |
| ram: { title: 'Memory', text: 'Required to run applications. Each app needs RAM to function.' }, | |
| motherboard: { title: 'Motherboard', text: 'Determines which OS versions you can support. Required for major upgrades.' } | |
| }; | |
| if (info[component]) { | |
| this.showToast(info[component].title, info[component].text, 5000); | |
| } | |
| } | |
| showToast(title, text, duration = 3000) { | |
| const toast = document.getElementById('info-toast'); | |
| document.getElementById('info-title').textContent = title; | |
| document.getElementById('info-text').textContent = text; | |
| toast.classList.remove('translate-y-20', 'opacity-0'); | |
| setTimeout(() => { | |
| toast.classList.add('translate-y-20', 'opacity-0'); | |
| }, duration); | |
| } | |
| saveGame() { | |
| const data = { | |
| money: this.money, | |
| totalEarned: this.totalEarned, | |
| investors: this.investors, | |
| hardware: this.hardware, | |
| currentOS: this.currentOS, | |
| installedApps: this.installedApps, | |
| availableApps: this.availableApps.map(app => ({ id: app.id, installed: app.installed })), | |
| prestigeMultiplier: this.prestigeMultiplier, | |
| totalPrestiges: this.totalPrestiges | |
| }; | |
| localStorage.setItem('computerEvolutionSave', JSON.stringify(data)); | |
| this.showToast('Game Saved', 'Your progress has been saved!'); | |
| } | |
| loadGame() { | |
| const saved = localStorage.getItem('computerEvolutionSave'); | |
| if (saved) { | |
| try { | |
| const data = JSON.parse(saved); | |
| this.money = data.money || 50; | |
| this.totalEarned = data.totalEarned || 0; | |
| this.investors = data.investors || 0; | |
| if (data.hardware) this.hardware = data.hardware; | |
| if (data.currentOS) this.currentOS = data.currentOS; | |
| if (data.installedApps) this.installedApps = data.installedApps; | |
| if (data.availableApps) { | |
| data.availableApps.forEach(savedApp => { | |
| const app = this.availableApps.find(a => a.id === savedApp.id); | |
| if (app) app.installed = savedApp.installed; | |
| }); | |
| } | |
| if (data.prestigeMultiplier) this.prestigeMultiplier = data.prestigeMultiplier; | |
| if (data.totalPrestiges) this.totalPrestiges = data.totalPrestiges; | |
| this.showToast('Game Loaded', 'Welcome back!'); | |
| } catch (e) { | |
| console.error('Failed to load save:', e); | |
| } | |
| } | |
| } | |
| resetGame() { | |
| if (confirm('Are you sure you want to reset all progress?')) { | |
| localStorage.removeItem('computerEvolutionSave'); | |
| location.reload(); | |
| } | |
| } | |
| } | |
| // Initialize game | |
| const game = new ComputerEvolution(); | |
| // Prevent context menu on right click for game feel | |
| document.addEventListener('contextmenu', e => e.preventDefault()); |