Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught ReferenceError: createAchievementsMenu is not defined' in or related to this line: 'createAchievementsMenu();' Line Number: 1650
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'elapsed')' in or related to this line: 'var currentTime = LK.time.elapsed;' Line Number: 407
User prompt
Please fix the bug: 'TypeError: game.sortChildren is not a function' in or related to this line: 'game.sortChildren();' Line Number: 541
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'elapsed')' in or related to this line: 'var currentTime = LK.time.elapsed;' Line Number: 383
Code edit (4 edits merged)
Please save this source code
User prompt
Move the cancel button on upgrade menu 50 pixels right and 50 pixels up
User prompt
set the opacity of the "rectangle" asset to 90%
User prompt
make rectangle asset opacity 75%
Code edit (1 edits merged)
Please save this source code
User prompt
add these sounds /**** * SOUND INITIALIZATION ****/ LK.init.sound('mine_coal', { volume:0.5 }); LK.init.sound('mine_iron', { volume:0.5 }); LK.init.sound('mine_gold', { volume:0.5 }); LK.init.sound('mine_diamond', { volume:0.5 }); LK.init.sound('mine_sapphire', { volume:0.5 }); LK.init.sound('mine_emerald', { volume:0.5 }); LK.init.sound('mine_ruby', { volume:0.5 }); LK.init.sound('mine_chronostone', { volume:0.5 }); LK.init.sound('mine_soulember', { volume:0.5 }); LK.init.sound('mine_quantumshard', { volume:0.5 }); LK.init.sound('drone_shot', { volume:0.5 }); LK.init.sound('ore_destroy_coal', { volume:0.7 }); LK.init.sound('ore_destroy_iron', { volume:0.7 }); LK.init.sound('ore_destroy_gold', { volume:0.7 }); LK.init.sound('ore_destroy_diamond', { volume:0.7 }); LK.init.sound('ore_destroy_sapphire', { volume:0.7 }); LK.init.sound('ore_destroy_emerald', { volume:0.7 }); LK.init.sound('ore_destroy_ruby', { volume:0.7 }); LK.init.sound('ore_destroy_chronostone', { volume:0.7 }); LK.init.sound('ore_destroy_soulember', { volume:0.7 }); LK.init.sound('ore_destroy_quantumshard', { volume:0.7 });
Code edit (3 edits merged)
Please save this source code
User prompt
add these sounds /**** * SOUND INITIALIZATION ****/ LK.init.sound('mine_coal', { volume:0.5 }); LK.init.sound('mine_iron', { volume:0.5 }); LK.init.sound('mine_gold', { volume:0.5 }); LK.init.sound('mine_diamond', { volume:0.5 }); LK.init.sound('mine_sapphire', { volume:0.5 }); LK.init.sound('mine_emerald', { volume:0.5 }); LK.init.sound('mine_ruby', { volume:0.5 }); LK.init.sound('mine_chronostone', { volume:0.5 }); LK.init.sound('mine_soulember', { volume:0.5 }); LK.init.sound('mine_quantumshard', { volume:0.5 }); LK.init.sound('drone_shot', { volume:0.5 }); LK.init.sound('ore_destroy_coal', { volume:0.7 }); LK.init.sound('ore_destroy_iron', { volume:0.7 }); LK.init.sound('ore_destroy_gold', { volume:0.7 }); LK.init.sound('ore_destroy_diamond', { volume:0.7 }); LK.init.sound('ore_destroy_sapphire', { volume:0.7 }); LK.init.sound('ore_destroy_emerald', { volume:0.7 }); LK.init.sound('ore_destroy_ruby', { volume:0.7 }); LK.init.sound('ore_destroy_chronostone', { volume:0.7 }); LK.init.sound('ore_destroy_soulember', { volume:0.7 }); LK.init.sound('ore_destroy_quantumshard', { volume:0.7 });
User prompt
Add these sound assets: /**** * SOUND INITIALIZATION ****/ LK.init.sound('mine_coal', { volume:0.5 }); LK.init.sound('mine_iron', { volume:0.5 }); LK.init.sound('mine_gold', { volume:0.5 }); LK.init.sound('mine_diamond', { volume:0.5 }); LK.init.sound('mine_sapphire', { volume:0.5 }); LK.init.sound('mine_emerald', { volume:0.5 }); LK.init.sound('mine_ruby', { volume:0.5 }); LK.init.sound('mine_chronostone', { volume:0.5 }); LK.init.sound('mine_soulember', { volume:0.5 }); LK.init.sound('mine_quantumshard', { volume:0.5 }); LK.init.sound('drone_shot', { volume:0.5 }); LK.init.sound('ore_destroy_coal', { volume:0.7 }); LK.init.sound('ore_destroy_iron', { volume:0.7 }); LK.init.sound('ore_destroy_gold', { volume:0.7 }); LK.init.sound('ore_destroy_diamond', { volume:0.7 }); LK.init.sound('ore_destroy_sapphire', { volume:0.7 }); LK.init.sound('ore_destroy_emerald', { volume:0.7 }); LK.init.sound('ore_destroy_ruby', { volume:0.7 }); LK.init.sound('ore_destroy_chronostone', { volume:0.7 }); LK.init.sound('ore_destroy_soulember', { volume:0.7 }); LK.init.sound('ore_destroy_quantumshard', { volume:0.7 });
User prompt
Please fix the bug: 'Uncaught ReferenceError: hideUpgradeDesc is not defined' in or related to this line: 'hideUpgradeDesc();' Line Number: 1492
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught ReferenceError: canPrestige is not defined' in or related to this line: 'if (canPrestige()) {' Line Number: 1212
User prompt
Please fix the bug: 'Uncaught ReferenceError: canPrestige is not defined' in or related to this line: 'if (canPrestige()) {' Line Number: 1230
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'initialSpawn is not defined' in or related to this line: 'initialSpawn();' Line Number: 778
User prompt
Please fix the bug: 'ReferenceError: quantumSelectionActive is not defined' in or related to this line: 'if (quantumSelectionActive) {' Line Number: 746
User prompt
Please fix the bug: 'ReferenceError: upgradeMenu is not defined' in or related to this line: 'if (upgradeMenu.parent) {' Line Number: 733
User prompt
Please fix the bug: 'ReferenceError: droneObjects is not defined' in or related to this line: 'for (var i = 0; i < droneObjects.length; i++) {' Line Number: 715
User prompt
Please fix the bug: 'ReferenceError: clusters is not defined' in or related to this line: 'clusters.forEach(function (c) {' Line Number: 167
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ /**** * CLASSES ****/ /** Cluster – spawns multiple ore objects. ****/ var Cluster = Container.expand(function (type) { var self = Container.call(this); self.type = type; self.oreList = []; self.zIndex = 0; var centerX = 100 + Math.random() * (2048 - 200); var centerY = 100 + Math.random() * (2732 - 200); self.x = centerX; self.y = centerY; var cc = gameState.clusterConfig; var count = randomInt(cc.min, cc.max); for (var i = 0; i < count; i++) { var ore = new Ore(type, self); ore.x = (Math.random() - 0.5) * 120; ore.y = (Math.random() - 0.5) * 120; self.oreList.push(ore); self.addChild(ore); } self.notifyOreDestroyed = function (ore) { var idx = self.oreList.indexOf(ore); if (idx >= 0) { self.oreList.splice(idx, 1); } ore.destroy(); if (self.oreList.length === 0) { if (self.parent) { self.parent.removeChild(self); } var cidx = clusters.indexOf(self); if (cidx >= 0) { clusters.splice(cidx, 1); } gameState.clusterCount[type]--; // Increment ore–mined stat: gameState.oreMined[type] = (gameState.oreMined[type] || 0) + 1; var finalDelay = gameState.respawnTime; if (type === 'coal') { finalDelay *= 2; } LK.setTimeout(function () { maybeSpawnCluster(type); }, finalDelay); } }; return self; }); /** Drone – moves and zaps ores. * With increased AOE range, spinning effect, and plasma–ring effect on hit. ****/ var Drone = Container.expand(function () { var self = Container.call(this); self.droneSprite = LK.getAsset('drone_asset', { anchorX: 0.5, anchorY: 0.5 }); self.addChild(self.droneSprite); self.AOE_RANGE = 150; self.droneDamage = 2; self.COOLDOWN_MAX = 60; self.cooldown = 0; var SPEED = 8, MIN_X = 50, MAX_X = 2000, MIN_Y = 50, MAX_Y = 2682; self.vx = Math.random() < 0.5 ? SPEED : -SPEED; self.vy = Math.random() < 0.5 ? SPEED : -SPEED; self.updateDrone = function () { self.x += self.vx; self.y += self.vy; if (self.x < MIN_X || self.x > MAX_X) { self.vx = -self.vx; } if (self.y < MIN_Y || self.y > MAX_Y) { self.vy = -self.vy; } if (Math.random() < 0.01) { self.vx += (Math.random() - 0.5) * 2; self.vy += (Math.random() - 0.5) * 2; var speed = Math.sqrt(self.vx * self.vx + self.vy * self.vy); if (speed > SPEED) { self.vx = self.vx / speed * SPEED; self.vy = self.vy / speed * SPEED; } } self.droneSprite.rotation += 0.1; if (self.cooldown > 0) { self.cooldown--; } else { self.tryZap(); } }; self.tryZap = function () { var hitSomething = false; clusters.forEach(function (cluster) { cluster.oreList.forEach(function (ore) { if (ore.health > 0) { var oreGlobalX = cluster.x + ore.x, oreGlobalY = cluster.y + ore.y; var dx = self.x - oreGlobalX, dy = self.y - oreGlobalY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.AOE_RANGE) { var damage = self.droneDamage; var actualDamage = Math.min(damage, ore.health); var fraction = actualDamage / ore.maxHealth; var reward = Math.round(fraction * ore.getValue()); if (ore.awardedMoney + reward > ore.getValue()) { reward = ore.getValue() - ore.awardedMoney; } ore.awardedMoney += reward; gameState.money += reward; gameState.totalMoneyEarned += reward; updateUI(); ore.health -= actualDamage; hitSomething = true; spawnDroneAOE(ore); if (ore.health <= 0) { ore.cluster.notifyOreDestroyed(ore); spawnMiningParticles(ore, 5); } else { spawnMiningParticles(ore, 2); } } } }); }); if (hitSomething) { LK.getSound('drone_shot').play(); self.cooldown = self.COOLDOWN_MAX; } }; return self; }); /** Miner – moves toward and mines the nearest ore. * Uses partial reward logic on each hit. ****/ var Miner = Container.expand(function () { var self = Container.call(this); self.attachAsset('miner', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.currentTarget = null; self.miningRange = 25; self.miningCooldown = 0; self.miningRate = 60; self.miningDamage = 1; self.originalMiningRate = self.miningRate; self.originalMiningDamage = self.miningDamage; self.speedBoostMultiplier = 1; self.speedBoostTimer = 0; self.soulEmberStacks = 0; self.quantumPathActive = false; self.quantumPath = []; self.quantumShardValueBonus = false; self.hyperMiningActive = false; self.hyperMiningTimer = 0; self.activateHyperMining = function () { self.hyperMiningActive = true; self.hyperMiningTimer = 10 * 60; self.miningDamage *= 2; self.miningRate = Math.max(1, Math.floor(self.miningRate / 2)); }; self.findNewTarget = function () { if (self.quantumPathActive && self.quantumPath.length > 0) { self.currentTarget = self.quantumPath[0]; if (!self.currentTarget || self.currentTarget.health <= 0) { self.quantumPath.shift(); if (self.quantumPath.length === 0) { self.quantumShardValueBonus = false; self.quantumPathActive = false; self.currentTarget = null; } return; } return; } var validOre = []; clusters.forEach(function (c) { c.oreList.forEach(function (ore) { if (ore.health > 0 && ore.tier <= gameState.currentTier) { validOre.push(ore); } }); }); if (validOre.length === 0) { self.currentTarget = null; return; } self.currentTarget = validOre.sort(function (a, b) { var aX = a.parent.x + a.x, aY = a.parent.y + a.y; var bX = b.parent.x + b.x, bY = b.parent.y + b.y; return Math.hypot(aX - self.x, aY - self.y) - Math.hypot(bX - self.x, bY - self.y); })[0]; }; self.update = function () { if (self.hyperMiningActive) { self.hyperMiningTimer--; if (self.hyperMiningTimer <= 0) { self.miningDamage = self.originalMiningDamage; self.miningRate = self.originalMiningRate; self.hyperMiningActive = false; } } if (self.speedBoostTimer > 0) { self.speedBoostTimer--; if (self.speedBoostTimer <= 0) { self.speedBoostMultiplier = 1; } } self.findNewTarget(); if (self.currentTarget) { var tx = self.currentTarget.parent.x + self.currentTarget.x, ty = self.currentTarget.parent.y + self.currentTarget.y; var dx = tx - self.x, dy = ty - self.y, dist = Math.sqrt(dx * dx + dy * dy); var finalSpeed = self.speed * self.speedBoostMultiplier; if (dist > self.miningRange) { self.x += dx / dist * finalSpeed; self.y += dy / dist * finalSpeed; } else { self.mineOre(self.currentTarget); } } else { if (typeof LK.time !== 'undefined') { self.y += Math.sin(LK.time.elapsed / 250) * 0.5; } } }; self.mineOre = function (ore) { if (self.miningCooldown > 0) { self.miningCooldown--; return; } var damageDealt = self.miningDamage * gameState.pickaxeLevel * (gameState.pickaxeBaseMultiplier || 1); var actualDamage = Math.min(damageDealt, ore.health); var fraction = actualDamage / ore.maxHealth; var reward = Math.round(fraction * ore.getValue()); if (ore.awardedMoney + reward > ore.getValue()) { reward = ore.getValue() - ore.awardedMoney; } ore.awardedMoney += reward; gameState.money += reward; gameState.totalMoneyEarned += reward; gameState.minerHitCount++; updateUI(); ore.health -= actualDamage; self.miningCooldown = self.miningRate; var mineSound = LK.getSound('mine_' + ore.type); if (mineSound) { mineSound.play(); } if (ore.health <= 0) { spawnMiningParticles(ore, 5); var destroySound = LK.getSound('ore_destroy_' + ore.type); if (destroySound) { destroySound.play(); } if (ore.type === "explosive" && ore.explode) { ore.explode(); } ore.cluster.notifyOreDestroyed(ore); } else { spawnMiningParticles(ore, 2); } }; self.applyChronostoneBoost = function () { self.speedBoostMultiplier *= 3; self.speedBoostTimer = 30 * 60; }; self.applySoulEmberBoost = function () { if (gameState.money >= 1e6) { var drain = gameState.money * 0.10; gameState.money -= drain; self.soulEmberStacks = 10; updateUI(); } }; self.triggerQuantumShardMode = function () { self.quantumShardValueBonus = true; self.quantumPathActive = true; self.quantumPath = []; game.pauseForQuantumSelection(); }; return self; }); /** Ore – represents a single ore. * Now interactive and awards per–hit money (with rewards rounded to whole numbers). ****/ var Ore = Container.expand(function (type, cluster) { var self = Container.call(this); self.type = type; self.cluster = cluster; self.zIndex = 0; var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby']; if (typeList.indexOf(type) >= 0) { self.tier = typeList.indexOf(type) + 1; } else { self.tier = 999; } self.baseValue = oreData[type].baseValue; self.maxHealth = oreData[type].baseHealth; self.health = self.maxHealth; self.attachAsset(oreData[type].assetId, { anchorX: 0.5, anchorY: 0.5 }); self.healthBar = LK.getAsset('rectangle', { width: 120, height: 20, fill: 0x00FF00, anchorX: 0.5, anchorY: 0.5 }); self.healthBar.x = 0; self.healthBar.y = -70; self.addChild(self.healthBar); self.awardedMoney = 0; self.lastTapTime = 0; self.interactive = true; self.buttonMode = true; self.down = function () { var currentTime = typeof LK.time !== 'undefined' ? LK.time.elapsed : Date.now(); if (currentTime - self.lastTapTime < 1) { return; } self.lastTapTime = currentTime; var damage = gameState.tapDamage; var actualDamage = Math.min(damage, self.health); var fraction = actualDamage / self.maxHealth; var reward = Math.round(fraction * self.getValue()); if (self.awardedMoney + reward > self.getValue()) { reward = self.getValue() - self.awardedMoney; } self.awardedMoney += reward; gameState.money += reward; gameState.totalMoneyEarned += reward; gameState.tapCount++; updateUI(); self.health -= actualDamage; spawnMiningParticles(self, 2); if (self.health <= 0) { self.cluster.notifyOreDestroyed(self); } }; if (["chronostone", "soulember", "quantumshard"].indexOf(type) >= 0) { var _pulseGlow = function pulseGlow() { tween(glow, { alpha: 1 }, { duration: 1000, onFinish: function onFinish() { tween(glow, { alpha: 0.5 }, { duration: 1000, onFinish: _pulseGlow }); } }); }; var glow = LK.getAsset('glowing_line_asset', { anchorX: 0.5, anchorY: 0.5 }); glow.alpha = 0.5; self.addChildAt(glow, 0); _pulseGlow(); } if (type === "explosive") { self.explode = function () { var explosionRadius = 100; clusters.forEach(function (cluster) { cluster.oreList.forEach(function (otherOre) { if (otherOre !== self && otherOre.health > 0) { var oreGlobalX = cluster.x + otherOre.x; var oreGlobalY = cluster.y + otherOre.y; var dx = self.parent.x + self.x - oreGlobalX; var dy = self.parent.y + self.y - oreGlobalY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < explosionRadius) { otherOre.health -= 50; if (otherOre.health <= 0) { var baseValue = otherOre.getValue(); gameState.money += baseValue; updateUI(); otherOre.cluster.notifyOreDestroyed(otherOre); spawnMiningParticles(otherOre, 5); } else { spawnMiningParticles(otherOre, 2); } } } }); }); screenShake(500, 10); }; } self.getValue = function () { var val = self.baseValue * gameState.oreMultipliers[self.type]; return Math.round(val / 2) * 2; // Force even }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ /**** * GAME-STATE & STATS ****/ /**** * Helper Functions ****/ var gameState = { money: 0, pickaxeLevel: 1, pickaxeBaseMultiplier: 1, droneLevel: 0, currentTier: 1, oreMultipliers: { coal: 1, iron: 1, gold: 1, diamond: 1, sapphire: 1, emerald: 1, ruby: 1, chronostone: 1, soulember: 1, quantumshard: 1 }, respawnTime: 3000, maxClustersPerType: 3, clusterCount: { coal: 0, iron: 0, gold: 0, diamond: 0, sapphire: 0, emerald: 0, ruby: 0, chronostone: 0, soulember: 0, quantumshard: 0 }, clusterConfigLevels: [{ min: 2, max: 3 }, { min: 3, max: 4 }, { min: 4, max: 5 }, { min: 5, max: 6 }, { min: 6, max: 7 }, { min: 6, max: 8 }], clusterUpgradeTier: 0, get clusterConfig() { return this.clusterConfigLevels[this.clusterUpgradeTier] || { min: 2, max: 3 }; }, prestigeCount: 0, prestigeCurrency: 0, tapDamage: 1, totalMoneyEarned: 0, tapCount: 0, minerHitCount: 0, startTime: Date.now(), oreMined: { coal: 0, iron: 0, gold: 0, diamond: 0, sapphire: 0, emerald: 0, ruby: 0, chronostone: 0, soulember: 0, quantumshard: 0 } }; /**** * ACHIEVEMENTS ****/ var achievements = [{ id: 'first_mine', name: 'First Mine', description: 'Mine your first ore', achieved: false, condition: function condition() { return gameState.money > 0; } }, { id: 'rich_miner', name: 'Rich Miner', description: 'Earn 1 Billion money', achieved: false, condition: function condition() { return gameState.money >= 1e9; } }, // New achievement with progress bar { id: 'coal_miner', name: 'Coal Miner', description: 'Mine 50 coal ores', achieved: false, target: 50, condition: function condition() { return gameState.oreMined.coal >= 50; } }]; /**** * ORE DATA (All ore values will be forced even.) ****/ var oreData = { coal: { baseValue: 5, baseHealth: 10, assetId: 'coal_ore' }, iron: { baseValue: 500, baseHealth: 100, assetId: 'iron_ore' }, gold: { baseValue: 10000, baseHealth: 500, assetId: 'gold_ore' }, diamond: { baseValue: 25000, baseHealth: 1000, assetId: 'diamond_ore' }, sapphire: { baseValue: 100000, baseHealth: 2000, assetId: 'sapphire_ore' }, emerald: { baseValue: 500000, baseHealth: 5000, assetId: 'emerald_ore' }, ruby: { baseValue: 1000000, baseHealth: 10000, assetId: 'ruby_ore' }, chronostone: { baseValue: 2000000, baseHealth: 2000, assetId: 'chronostone_ore', color: 0xc997d8 }, soulember: { baseValue: 5000000, baseHealth: 5000, assetId: 'soulember_ore', color: 0xdef3e5 }, quantumshard: { baseValue: 10000000, baseHealth: 10000, assetId: 'quantumshard_ore', color: 0xa1bb12 } }; function hideUpgradeDesc() {/* Placeholder */} function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function spawnMiningParticles(ore, num) { for (var i = 0; i < num; i++) { var p = LK.getAsset('mining_particle', { anchorX: 0.5, anchorY: 0.5 }); if (ore.parent) { p.x = ore.parent.x + ore.x; p.y = ore.parent.y + ore.y; } else { p.x = ore.x; p.y = ore.y; } if (["chronostone", "soulember", "quantumshard"].indexOf(ore.type) >= 0) { p.tint = oreData[ore.type].color || 0xffffff; } p.vx = (Math.random() - 0.5) * 10; p.vy = (Math.random() - 0.5) * 10; p.alpha = 1; p.zIndex = -1; tween(p, { alpha: 0, y: p.y - 50 }, { duration: 1000, onFinish: function onFinish() { p.destroy(); } }); game.addChild(p); } } function interpolateColor(c1, c2, f) { var r1 = c1 >> 16 & 0xFF, g1 = c1 >> 8 & 0xFF, b1 = c1 & 0xFF; var r2 = c2 >> 16 & 0xFF, g2 = c2 >> 8 & 0xFF, b2 = c2 & 0xFF; var r = Math.round(r1 + f * (r2 - r1)); var g = Math.round(g1 + f * (g2 - g1)); var b = Math.round(b1 + f * (b2 - b1)); return r << 16 | g << 8 | b; } function screenShake(duration, magnitude) { var originalX = game.x, originalY = game.y, shakeInterval = 50, elapsed = 0; var shake = setInterval(function () { elapsed += shakeInterval; game.x = originalX + (Math.random() - 0.5) * magnitude; game.y = originalY + (Math.random() - 0.5) * magnitude; if (elapsed >= duration) { clearInterval(shake); game.x = originalX; game.y = originalY; } }, shakeInterval); } function spawnDroneAOE(ore) { var effect = LK.getAsset('drone_aoe_effect', { anchorX: 0.5, anchorY: 0.5 }); if (ore.parent) { effect.x = ore.parent.x + ore.x; effect.y = ore.parent.y + ore.y; } else { effect.x = ore.x; effect.y = ore.y; } effect.alpha = 1; effect.zIndex = 1; game.addChild(effect); tween(effect, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { effect.destroy(); game.sortChildren(); } }); } /**** * Achievements Menu & Stats Tab ****/ // Achievements Menu – shows a progress bar for achievements with a target. function createAchievementsMenu() { upgradeMenu.removeChildren(); var menuBg = LK.getAsset('rectangle', { width: 1800, height: 2200, color: 0x333333, anchorX: 0.5, anchorY: 0.5 }); menuBg.alpha = 0.9; menuBg.x = 2048 / 2; menuBg.y = 2732 / 2 + 50; upgradeMenu.addChild(menuBg); var titleText = new Text2("Achievements", { size: 60, fill: 0xFFFFFF, align: "center" }); titleText.anchor.set(0.5); titleText.x = menuBg.x; titleText.y = menuBg.y - 1000; upgradeMenu.addChild(titleText); var yStart = menuBg.y - 800, spacing = 150; achievements.forEach(function (ach, index) { var container = new Container(); container.x = menuBg.x; container.y = yStart + index * spacing; var title = new Text2(ach.name, { size: 40, fill: 0xFFFFFF }); title.anchor.set(0.5); container.addChild(title); if (ach.target !== undefined) { var currentProgress = 0; if (ach.id === 'coal_miner') { currentProgress = gameState.oreMined.coal; } var progressBarBg = LK.getAsset('rectangle', { width: 400, height: 30, color: 0x555555, anchorX: 0, anchorY: 0.5 }); progressBarBg.x = -200; progressBarBg.y = 50; container.addChild(progressBarBg); var progressWidth = Math.min(currentProgress / ach.target * 400, 400); var progressBarFg = LK.getAsset('rectangle', { width: progressWidth, height: 30, color: 0x00FF00, anchorX: 0, anchorY: 0.5 }); progressBarFg.x = -200; progressBarFg.y = 50; container.addChild(progressBarFg); var progressText = new Text2(currentProgress + "/" + ach.target, { size: 30, fill: 0xFFFFFF }); progressText.anchor.set(0.5); progressText.x = 0; progressText.y = 50; container.addChild(progressText); } if (ach.achieved) { var achievedText = new Text2("Achieved!", { size: 30, fill: 0xFFD700 }); achievedText.anchor.set(0.5); achievedText.x = 300; achievedText.y = 0; container.addChild(achievedText); } upgradeMenu.addChild(container); }); var backBtn = LK.getAsset('cancelButton', { anchorX: 0.5, anchorY: 0.5 }); backBtn.x = menuBg.x + 700; backBtn.y = menuBg.y - 1000; backBtn.down = function () { createMainUpgradeMenu(); }; upgradeMenu.addChild(backBtn); } // Game Stats Menu – shows various overall statistics. function createStatsMenu() { upgradeMenu.removeChildren(); var menuBg = LK.getAsset('rectangle', { width: 1800, height: 2200, color: 0x222222, anchorX: 0.5, anchorY: 0.5 }); menuBg.alpha = 0.9; menuBg.x = 2048 / 2; menuBg.y = 2732 / 2 + 50; upgradeMenu.addChild(menuBg); var titleText = new Text2("Game Stats", { size: 60, fill: 0xFFFFFF, align: "center" }); titleText.anchor.set(0.5); titleText.x = menuBg.x; titleText.y = menuBg.y - 1000; upgradeMenu.addChild(titleText); // For each ore type, show its asset and number mined. var oreTypes = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby', 'chronostone', 'soulember', 'quantumshard']; var yStart = menuBg.y - 800, spacing = 60; oreTypes.forEach(function (type, index) { var statContainer = new Container(); statContainer.x = menuBg.x - 600; statContainer.y = yStart + index * spacing; var oreAsset = LK.getAsset(type + '_ore', { anchorX: 0.5, anchorY: 0.5 }); oreAsset.scale = 0.5; oreAsset.x = 0; oreAsset.y = 0; statContainer.addChild(oreAsset); var countText = new Text2("Mined: " + (gameState.oreMined[type] || 0), { size: 40, fill: 0xFFFFFF }); countText.x = 100; countText.y = 0; statContainer.addChild(countText); upgradeMenu.addChild(statContainer); }); var statsText = ""; statsText += "Total Money Earned: $" + gameState.totalMoneyEarned.toLocaleString() + "\n"; var achievedCount = achievements.filter(function (a) { return a.achieved; }).length; statsText += "Achievements: " + achievedCount + "/" + achievements.length + "\n"; statsText += "Prestige Count: " + gameState.prestigeCount + "\n"; var timePlayed = Math.floor((Date.now() - gameState.startTime) / 1000); statsText += "Time Played: " + timePlayed + " sec\n"; statsText += "Ore Taps: " + gameState.tapCount + "\n"; statsText += "Miner Hits: " + gameState.minerHitCount + "\n"; var fullyUpgraded = 0; for (var key in oreUpgrades) { oreUpgrades[key].forEach(function (upg) { if (upg.level >= upg.maxLevel) { fullyUpgraded++; } }); } statsText += "Fully Upgraded Ore Upgrades: " + fullyUpgraded + "\n"; var otherStats = new Text2(statsText, { size: 40, fill: 0xFFFFFF }); otherStats.x = menuBg.x + 200; otherStats.y = menuBg.y - 800; upgradeMenu.addChild(otherStats); var backBtn = LK.getAsset('cancelButton', { anchorX: 0.5, anchorY: 0.5 }); backBtn.x = menuBg.x + 700; backBtn.y = menuBg.y - 1000; backBtn.down = function () { createMainUpgradeMenu(); }; upgradeMenu.addChild(backBtn); } /**** * PRESTIGE & BACKGROUND HELPERS ****/ function getPrestigeRequirement() { return 1e9 * Math.pow(2, gameState.prestigeCount); } function canPrestige() { return gameState.money >= getPrestigeRequirement(); } function calculatePrestigeShards() { return 1; } function doPrestige() { for (var i = clusters.length - 1; i >= 0; i--) { var c = clusters[i]; c.removeChildren(); if (c.parent) { c.parent.removeChild(c); } clusters.splice(i, 1); } droneObjects.forEach(function (d) { if (d.parent) { d.parent.removeChild(d); } }); droneObjects = []; droneSprites.forEach(function (ds) { if (ds.parent) { ds.parent.removeChild(ds); } }); droneSprites = []; var shards = calculatePrestigeShards(); gameState.prestigeCurrency += shards; gameState.prestigeCount++; gameState.money = 0; gameState.currentTier = 1; for (var key in gameState.clusterCount) { gameState.clusterCount[key] = 0; } resetUpgrades(); gameState.droneLevel = 0; handleBackgroundTransition(); initialSpawn(); updateUI(); } function resetUpgrades() { gameState.oreMultipliers = { coal: 1, iron: 1, gold: 1, diamond: 1, sapphire: 1, emerald: 1, ruby: 1, chronostone: 1, soulember: 1, quantumshard: 1 }; gameState.pickaxeLevel = 1; gameState.pickaxeBaseMultiplier = 1; gameState.tapDamage = 1; gameState.respawnTime = 3000; gameState.clusterUpgradeTier = 0; for (var key in oreUpgrades) { oreUpgrades[key].forEach(function (upg) { if (upg.initCost === undefined) { upg.initCost = upg.cost; } upg.cost = upg.initCost; upg.level = 0; upg.purchased = false; }); } generalUpgrades.forEach(function (upg) { if (upg.initCost === undefined) { upg.initCost = upg.cost; } upg.cost = upg.initCost; upg.level = 0; upg.purchased = false; }); droneUpgrades.forEach(function (upg) { if (upg.initCost === undefined) { upg.initCost = upg.cost; } upg.cost = upg.initCost; upg.level = 0; upg.purchased = false; }); } function handleBackgroundTransition() { if (nextBackground && nextBackground.parent) { nextBackground.parent.removeChild(nextBackground); } var newBg = null; if (gameState.prestigeCount >= 8) { newBg = LK.getAsset('background_tier8', { anchorX: 0.5, anchorY: 0.5 }); } else if (gameState.prestigeCount >= 5) { newBg = LK.getAsset('background_tier5', { anchorX: 0.5, anchorY: 0.5 }); } else if (gameState.prestigeCount >= 3) { newBg = LK.getAsset('background_tier3', { anchorX: 0.5, anchorY: 0.5 }); } else { newBg = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5 }); } newBg.x = 2048 / 2; newBg.y = 2732 + 2732 / 2; game.addChildAt(newBg, 0); nextBackground = newBg; var oldBg = currentBackground; if (!oldBg) { oldBg = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5 }); oldBg.x = 2048 / 2; oldBg.y = 2732 / 2; game.addChildAt(oldBg, 0); } if (oldBg === newBg) { currentBackground = newBg; return; } var dur = 3000; tween(oldBg, { y: oldBg.y - 2732 }, { duration: dur, onFinish: function onFinish() { if (oldBg && oldBg.parent) { oldBg.parent.removeChild(oldBg); } } }); tween(newBg, { y: 2732 / 2 }, { duration: dur, onFinish: function onFinish() { currentBackground = newBg; } }); } var clusters = []; var currentBackground = null; var nextBackground = null; var miner = null; var droneObjects = []; var droneSprites = []; var prestigeMainButton = null; /**** * Spawn Functions ****/ function initialSpawn() { var allTypes = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby']; allTypes.forEach(function (type, idx) { var t = idx + 1; if (t <= gameState.currentTier) { for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster(type); } } }); maybeSpawnSpecialOres(); } function updateDroneObjects() { while (droneObjects.length < gameState.droneLevel) { var d = new Drone(); d.x = 200 + Math.random() * (2048 - 400); d.y = 200 + Math.random() * (2732 - 400); droneObjects.push(d); game.addChild(d); } } function updateDroneSprites() { while (droneSprites.length < gameState.droneLevel) { var drone = LK.getAsset('drone_asset', { anchorX: 0.5, anchorY: 0.5 }); drone.x = 100 + droneSprites.length * 90; drone.y = 200; droneSprites.push(drone); game.addChild(drone); } } function maybeSpawnCluster(type) { var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby']; if (typeList.indexOf(type) >= 0) { var tIndex = typeList.indexOf(type) + 1; if (tIndex > gameState.currentTier) { return; } } if (gameState.clusterCount[type] >= gameState.maxClustersPerType) { return; } var cluster = new Cluster(type); game.addChild(cluster); clusters.push(cluster); gameState.clusterCount[type]++; } function maybeSpawnSpecialOres() { var spawnChances = []; if (gameState.prestigeCount >= 3) { spawnChances.push({ type: 'chronostone', min: 3, max: 5 }); } if (gameState.prestigeCount >= 5) { spawnChances.push({ type: 'soulember', min: 1.5, max: 2.5 }); } if (gameState.prestigeCount >= 8) { spawnChances.push({ type: 'quantumshard', min: 0.8, max: 1.2 }); } if (spawnChances.length === 0) { return; } var standardTypes = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby']; standardTypes.forEach(function (type) { if (gameState.clusterCount[type] < gameState.maxClustersPerType) { for (var i = 0; i < spawnChances.length; i++) { var chanceObj = spawnChances[i]; var chance = randomInt(chanceObj.min * 10, chanceObj.max * 10) / 10; var roll = Math.random() * 100; if (roll < chance) { if (gameState.clusterCount[chanceObj.type] < gameState.maxClustersPerType) { maybeSpawnCluster(chanceObj.type); } } } } }); } /**** * Drone DPS Functions ****/ function getDroneDPS() { return 10 * gameState.droneLevel; } function droneDamageTick() { var dps = getDroneDPS(); if (dps <= 0) { return; } var allValidOres = []; clusters.forEach(function (c) { c.oreList.forEach(function (ore) { if (ore.health > 0 && ore.tier <= gameState.currentTier) { allValidOres.push(ore); } }); }); if (allValidOres.length === 0) { return; } var damageRemaining = dps; while (damageRemaining > 0 && allValidOres.length > 0) { var randomIndex = Math.floor(Math.random() * allValidOres.length); var ore = allValidOres[randomIndex]; var chunk = Math.min(damageRemaining, 10); ore.health -= chunk; damageRemaining -= chunk; if (ore.health <= 0) { var baseValue = ore.getValue(); gameState.money += baseValue; updateUI(); ore.cluster.notifyOreDestroyed(ore); spawnMiningParticles(ore, 5); allValidOres.splice(randomIndex, 1); } } } /**** * UPGRADE DATA ****/ var oreUpgrades = { coal: [{ id: 'double_coal', name: 'Double Coal Value', cost: 100, multi: true, level: 0, maxLevel: 20, effect: 'Doubles Coal Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.coal *= 2; this.cost *= 2; } }], iron: [{ id: 'unlock_iron', name: 'Unlock Iron Mining', cost: 7000, effect: 'Allows iron ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 2) { gameState.currentTier = 2; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('iron'); } } }, { id: 'double_iron', name: 'Double Iron Value', cost: 1000, multi: true, level: 0, maxLevel: 20, effect: 'Doubles Iron Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.iron *= 2; this.cost *= 2; } }], gold: [{ id: 'unlock_gold', name: 'Unlock Gold Mining', cost: 70000, effect: 'Allows gold ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 3) { gameState.currentTier = 3; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('gold'); } } }, { id: 'double_gold', name: 'Double Gold Value', cost: 20000, multi: true, level: 0, maxLevel: 20, effect: 'Doubles Gold Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.gold *= 2; this.cost *= 2; } }], diamond: [{ id: 'unlock_diamond', name: 'Unlock Diamond Mining', cost: 280000, effect: 'Allows diamond ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 4) { gameState.currentTier = 4; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('diamond'); } } }, { id: 'double_diamond', name: 'Double Diamond Value', cost: 50000, multi: true, level: 0, maxLevel: 20, effect: 'Doubles Diamond Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.diamond *= 2; this.cost *= 2; } }], sapphire: [{ id: 'unlock_sapphire', name: 'Unlock Sapphire Mining', cost: 1400000, effect: 'Allows sapphire ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 5) { gameState.currentTier = 5; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('sapphire'); } } }, { id: 'double_sapphire', name: 'Double Sapphire Value', cost: 200000, multi: true, level: 0, maxLevel: 20, effect: 'Doubles Sapphire Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.sapphire *= 2; this.cost *= 2; } }], emerald: [{ id: 'unlock_emerald', name: 'Unlock Emerald Mining', cost: 7000000, effect: 'Allows emerald ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 6) { gameState.currentTier = 6; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('emerald'); } } }, { id: 'double_emerald', name: 'Double Emerald Value', cost: 1000000, multi: true, level: 0, maxLevel: 20, effect: 'Doubles Emerald Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.emerald *= 2; this.cost *= 2; } }], ruby: [{ id: 'unlock_ruby', name: 'Unlock Ruby Mining', cost: 14000000, effect: 'Allows ruby ore clusters to spawn', purchased: false, action: function action() { if (gameState.currentTier < 7) { gameState.currentTier = 7; } for (var i = 0; i < gameState.maxClustersPerType; i++) { maybeSpawnCluster('ruby'); } } }, { id: 'double_ruby', name: 'Double Ruby Value', cost: 2000000, multi: true, level: 0, maxLevel: 20, effect: 'Doubles Ruby Value each purchase', action: function action() { this.level++; gameState.oreMultipliers.ruby *= 2; this.cost *= 2; } }] }; var generalUpgrades = [{ id: 'faster_respawn', name: 'Quicker Respawn', cost: 8000, effect: 'Halves respawn time (min 500 ms)', multi: true, level: 0, maxLevel: 3, action: function action() { gameState.respawnTime = Math.max(500, gameState.respawnTime / 2); this.level++; this.cost = Math.floor(this.cost * 2); } }, { id: 'cluster_up', name: 'Cluster Growth', cost: 1000, effect: 'Increases cluster size range', multi: true, level: 0, maxLevel: 5, action: function action() { if (gameState.clusterUpgradeTier < gameState.clusterConfigLevels.length - 1) { gameState.clusterUpgradeTier++; } this.level++; this.cost += 2000; } }, { id: 'pickaxe_buff', name: 'Pickaxe DMG +20%', cost: 20000, effect: 'Increases your total pickaxe damage by 20%', multi: true, level: 0, maxLevel: 20, action: function action() { this.level++; gameState.pickaxeBaseMultiplier *= 1.2; this.cost = Math.floor(this.cost * 2); } }, // New: Tap Damage Upgrade { id: 'tap_damage', name: 'Tap Damage Upgrade', cost: 5000, effect: 'Increase tap damage by 50%', multi: true, level: 0, maxLevel: 20, action: function action() { this.level++; gameState.tapDamage = gameState.tapDamage * 1.5; this.cost = Math.floor(this.cost * 2); } }, // New: Miner Swing Speed Upgrade { id: 'miner_speed', name: 'Miner Swing Speed Upgrade', cost: 20000, effect: 'Increase miner swing speed (reduce cooldown by 10%)', multi: true, level: 0, maxLevel: 20, action: function action() { this.level++; miner.miningRate = Math.max(1, Math.floor(miner.miningRate * 0.9)); this.cost = Math.floor(this.cost * 2); } }]; var prestigeUpgrades = [{ id: 'pickaxe_plus_1', name: 'Pickaxe Level +1', cost: 3, effect: 'Increases pickaxe damage by 1', purchased: false, action: function action() { gameState.pickaxeLevel++; } }, { id: 'pickaxe_plus_2', name: 'Pickaxe Speed +10%', cost: 4, effect: 'Reduces mining cooldown by 10%', purchased: false, action: function action() { miner.miningRate = Math.floor(miner.miningRate * 0.90); if (miner.miningRate < 1) { miner.miningRate = 1; } } }, { id: 'pickaxe_plus_3', name: 'Pickaxe Bonus DMG +2', cost: 6, effect: 'Increases pickaxe damage by an additional 2', purchased: false, action: function action() { gameState.pickaxeLevel += 2; } }, { id: 'pickaxe_plus_4', name: 'Mega Pickaxe', cost: 15, effect: 'Increases pickaxe damage by an additional 5', purchased: false, action: function action() { gameState.pickaxeLevel += 5; } }]; var prestigeDrones = [{ id: 'drone_speedup', name: 'Drone Technology +1', cost: 8, effect: 'Increases Drone DPS by 50', purchased: false, action: function action() { if (!gameState.droneLevel) { gameState.droneLevel = 0; } gameState.droneLevel += 5; } }, { id: 'drone_overclock', name: 'Drone Overclock', cost: 12, effect: 'Increases Drone DPS by 100', purchased: false, action: function action() { gameState.droneLevel += 10; } }]; var droneUpgrades = [{ id: 'drone_level_1', name: 'Buy Drones (Lv +1)', cost: 5000, effect: 'Each level adds +10 DPS', purchased: false, multi: true, level: 0, maxLevel: 20, action: function action() { if (!gameState.droneLevel) { gameState.droneLevel = 0; } gameState.droneLevel++; this.level++; this.cost = Math.floor(this.cost * 1.5); updateDroneObjects(); } }]; /**** * UI ****/ var upgradeMenu = new Container(); upgradeMenu.zIndex = 10000; // Force on top. var tooltip = new Text2('', { size: 40, fill: 0xFFFFFF }); game.addChild(tooltip); var moneyDisplay = new Text2('$0', { size: 80, fill: 0xFFFFFF, fontWeight: 'bold', stroke: 0x000000, strokeThickness: 5 }); moneyDisplay.x = 2048 / 2 - moneyDisplay.width / 2; moneyDisplay.y = 50; game.addChild(moneyDisplay); var prestigeDisplay = new Text2('Prestige: 0', { size: 50, fill: 0xFFFFFF, fontWeight: 'bold', stroke: 0x000000, strokeThickness: 4 }); prestigeDisplay.x = 250; prestigeDisplay.y = 50; game.addChild(prestigeDisplay); var shopOpenButton = LK.getAsset('shop_icon', { anchorX: 0.5, anchorY: 0.5 }); shopOpenButton.x = 2048 - 150; shopOpenButton.y = 2732 - 150; shopOpenButton.down = function () { createMainUpgradeMenu(); game.addChild(upgradeMenu); upgradeMenu.parent.setChildIndex(upgradeMenu, upgradeMenu.parent.children.length - 1); }; game.addChild(shopOpenButton); var addMoneyButton = LK.getAsset('buy_button', { anchorX: 0.5, anchorY: 0.5 }); addMoneyButton.x = 200; addMoneyButton.y = 2732 - 300; addMoneyButton.down = function () { gameState.money += 5000000000; updateUI(); }; game.addChild(addMoneyButton); /**** * UPGRADE MODAL HELPER ****/ function showUpgradeModal(upg, btn, callback) { var modal = new Container(); var bg = LK.getAsset('upgrade_popup_bg', { anchorX: 0.5, anchorY: 0.5 }); modal.addChild(bg); var nextCost = upg.multi ? Math.floor(upg.cost * 2) : upg.cost; var textStr = upg.effect + "\nCost: $" + upg.cost; if (upg.multi) { textStr += " Next: $" + nextCost; } var desc = new Text2(textStr, { size: 35, fill: 0xFFFFFF, align: 'center' }); desc.anchor.set(0.5); modal.addChild(desc); var upgradeBtn = LK.getAsset('upgrade_confirm_button', { anchorX: 0.5, anchorY: 0.5 }); upgradeBtn.x = -100; upgradeBtn.y = 60; modal.addChild(upgradeBtn); var upgradeTxt = new Text2("Upgrade", { size: 35, fill: 0x000000, align: 'center' }); upgradeTxt.anchor.set(0.5); upgradeTxt.x = upgradeBtn.x; upgradeTxt.y = upgradeBtn.y; modal.addChild(upgradeTxt); var cancelBtn = LK.getAsset('cancelButton', { anchorX: 0.5, anchorY: 0.5 }); cancelBtn.x = 100; cancelBtn.y = 60; modal.addChild(cancelBtn); modal.x = btn.x; modal.y = btn.y - 150; upgradeMenu.addChild(modal); upgradeMenu.parent.setChildIndex(upgradeMenu, upgradeMenu.parent.children.length - 1); upgradeBtn.down = function () { callback(true); modal.destroy(); }; cancelBtn.down = function () { callback(false); modal.destroy(); }; upgradeMenu.down = function (event) { modal.destroy(); }; } /**** * PRESTIGE MODAL ****/ function showPrestigeModal() { var modal = new Container(); var popup = LK.getAsset('prestige_popup', { anchorX: 0.5, anchorY: 0.5 }); modal.addChild(popup); var req = getPrestigeRequirement(); var prompt = new Text2("Prestige?\nYou need: $" + req.toLocaleString() + "\nYou have: $" + Math.floor(gameState.money).toLocaleString(), { size: 40, fill: 0xFFFFFF, align: 'center' }); prompt.anchor.set(0.5); modal.addChild(prompt); popup.x = 0; popup.y = 0; prompt.x = 0; prompt.y = -30; var yesBtn = LK.getAsset('yes_button', { anchorX: 0.5, anchorY: 0.5 }); yesBtn.x = -100; yesBtn.y = 60; modal.addChild(yesBtn); var noBtn = LK.getAsset('cancelButton', { anchorX: 0.5, anchorY: 0.5 }); noBtn.x = 100; noBtn.y = 60; modal.addChild(noBtn); modal.x = 2048 / 2; modal.y = 2732 / 2; upgradeMenu.addChild(modal); yesBtn.down = function () { if (canPrestige()) { doPrestige(); modal.destroy(); upgradeMenu.removeChild(modal); } }; noBtn.down = function () { modal.destroy(); upgradeMenu.removeChild(modal); }; upgradeMenu.down = function (event) { modal.destroy(); }; } /**** * MAIN UPGRADE MENU – with new categories including "Game Stats" ****/ function createMainUpgradeMenu() { upgradeMenu.removeChildren(); subUpgradeItemRefs = []; var menuBg = LK.getAsset('rectangle', { width: 1800, height: 2200, color: 0x2a2a2a, anchorX: 0.5, anchorY: 0.5 }); menuBg.alpha = 0.9; menuBg.x = 2048 / 2; menuBg.y = 2732 / 2 + 50; upgradeMenu.addChild(menuBg); var categories = [{ name: 'Coal Upgrades', type: 'coal' }, { name: 'Iron Upgrades', type: 'iron' }, { name: 'Gold Upgrades', type: 'gold' }, { name: 'Diamond Upgrades', type: 'diamond' }, { name: 'Sapphire Upgrades', type: 'sapphire' }, { name: 'Emerald Upgrades', type: 'emerald' }, { name: 'Ruby Upgrades', type: 'ruby' }, { name: 'General Upgrades', type: 'general' }, { name: 'Drones', type: 'drones' }, { name: 'Achievements', type: 'achievements' }, { name: 'Prestige', type: 'prestige' }, { name: 'Game Stats', type: 'stats' }]; var colSpacing = 400, rowSpacing = 300; for (var i = 0; i < categories.length; i++) { var col = i % 2, row = Math.floor(i / 2); var x = menuBg.x + (col === 0 ? -colSpacing : colSpacing); var y = menuBg.y - 800 + row * rowSpacing; var btn = LK.getAsset('buy_button', { anchorX: 0.5, anchorY: 0.5 }); btn.x = x; btn.y = y; upgradeMenu.addChild(btn); var txt = new Text2(categories[i].name, { size: 50, fill: 0x000000, align: 'center' }); txt.anchor.set(0.5); txt.x = btn.x; txt.y = btn.y; upgradeMenu.addChild(txt); btn.down = function (cat) { return function (event) { event.stopPropagation && event.stopPropagation(); hideUpgradeDesc(); if (cat.type === 'general') { createSubUpgradeMenu('General Upgrades', generalUpgrades); } else if (cat.type === 'drones') { createSubUpgradeMenu('Drone Upgrades', droneUpgrades); } else if (cat.type === 'achievements') { createAchievementsMenu(); } else if (cat.type === 'prestige') { createPrestigeMenu(); } else if (cat.type === 'stats') { createStatsMenu(); } else { createSubUpgradeMenu(cat.name, oreUpgrades[cat.type]); } }; }(categories[i]); } var closeBtn = LK.getAsset('cancelButton', { anchorX: 0.5, anchorY: 0.5 }); closeBtn.x = menuBg.x + 750; closeBtn.y = menuBg.y - 950; closeBtn.down = function () { game.removeChild(upgradeMenu); }; upgradeMenu.addChild(closeBtn); upgradeMenu.down = function (event) { hideUpgradeDesc(); }; upgradeMenu.parent && upgradeMenu.parent.setChildIndex(upgradeMenu, upgradeMenu.parent.children.length - 1); } var subUpgradeItemRefs = []; function createSubUpgradeMenu(title, upgList) { upgradeMenu.removeChildren(); subUpgradeItemRefs = []; var menuBg = LK.getAsset('rectangle', { width: 1800, height: 2200, color: 0x2a2a2a, anchorX: 0.5, anchorY: 0.5 }); menuBg.alpha = 0.9; menuBg.x = 2048 / 2; menuBg.y = 2732 / 2 + 50; upgradeMenu.addChild(menuBg); var titleText = new Text2(title, { size: 60, fill: 0xFFFFFF, align: 'center' }); titleText.anchor.set(0.5); titleText.x = menuBg.x; titleText.y = menuBg.y - 1000; upgradeMenu.addChild(titleText); var startY = menuBg.y - 800, colSpacing = 400; for (var i = 0; i < upgList.length; i++) { var col = i % 2, row = Math.floor(i / 2); var btn = LK.getAsset('buy_button', { anchorX: 0.5, anchorY: 0.5 }); btn.x = menuBg.x + (col === 0 ? -colSpacing : colSpacing); btn.y = startY + row * 250; upgradeMenu.addChild(btn); var displayName = upgList[i].name; if (typeof upgList[i].level === 'number' && upgList[i].level > 0) { displayName += " (Lv " + upgList[i].level + ")"; } var txt = new Text2(displayName + "\nCost: $" + upgList[i].cost, { size: 45, fill: 0x000000, align: 'center' }); txt.anchor.set(0.5); txt.x = btn.x; txt.y = btn.y; upgradeMenu.addChild(txt); btn.down = function (upg, btn) { return function (event) { event.stopPropagation && event.stopPropagation(); showUpgradeModal(upg, btn, function (confirmed) { if (confirmed && canPurchaseUpgrade(upgList, upg)) { gameState.money -= upg.cost; upg.purchased = true; upg.action(); updateUI(); createSubUpgradeMenu(title, upgList); } }); }; }(upgList[i], btn); subUpgradeItemRefs.push({ upgList: upgList, upgrade: upgList[i], textObj: txt }); } var backBtn = LK.getAsset('cancelButton', { anchorX: 0.5, anchorY: 0.5 }); backBtn.x = menuBg.x + 700; backBtn.y = menuBg.y - 1000; backBtn.down = function () { createMainUpgradeMenu(); }; upgradeMenu.addChild(backBtn); upgradeMenu.down = function (event) { hideUpgradeDesc(); }; } function canPurchaseUpgrade(upgList, upg) { if (upg.requires) { var needed = upgList.find(function (u) { return u.id === upg.requires; }); if (!needed || !needed.purchased) { return false; } } if (upg.multi && upg.maxLevel !== undefined && upg.level >= upg.maxLevel) { return false; } if (!upg.multi && upg.purchased) { return false; } if (gameState.money < upg.cost) { return false; } return true; } /**** * GAME LOOP ****/ var quantumSelectTimer = 0, quantumSelectionActive = false; game.update = function () { if (miner) { miner.update(); } for (var i = 0; i < droneObjects.length; i++) { droneObjects[i].updateDrone(); } if (typeof LK.time !== 'undefined' && LK.time.elapsed % 60 === 0) { droneDamageTick(); } clusters.forEach(function (cluster) { cluster.oreList.forEach(function (ore) { if (ore.health > 0) { var fraction = ore.health / ore.maxHealth; ore.healthBar.width = 120 * fraction; ore.healthBar.fill = interpolateColor(0xFF0000, 0x00FF00, fraction); ore.alpha = fraction; } }); }); if (upgradeMenu.parent) { subUpgradeItemRefs.forEach(function (ref) { var upg = ref.upgrade; var canBuy = canPurchaseUpgrade(ref.upgList, upg); if (ref.textObj && ref.textObj.style) { ref.textObj.style.fill = canBuy ? 0xFFFFFF : 0x666666; } }); } if (quantumSelectionActive) { quantumSelectTimer++; if (quantumSelectTimer > 15 * 60) { quantumSelectionActive = false; miner.quantumPathActive = false; } } achievements.forEach(function (ach) { if (!ach.achieved && ach.condition()) { ach.achieved = true; var achText = new Text2("Achievement Unlocked: " + ach.name, { size: 40, fill: 0xFFFF00 }); achText.x = 2048 / 2; achText.y = 100; game.addChild(achText); tween(achText, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { achText.destroy(); } }); } }); if (canPrestige()) { if (!prestigeMainButton) { prestigeMainButton = LK.getAsset('prestige_main_button', { anchorX: 0.5, anchorY: 0.5 }); prestigeMainButton.x = 150; prestigeMainButton.y = 2732 - 150; prestigeMainButton.down = function () { doPrestige(); if (prestigeMainButton && prestigeMainButton.parent) { prestigeMainButton.parent.removeChild(prestigeMainButton); prestigeMainButton = null; } }; game.addChild(prestigeMainButton); } } else { if (prestigeMainButton) { if (prestigeMainButton.parent) { prestigeMainButton.parent.removeChild(prestigeMainButton); } prestigeMainButton = null; } } }; /**** * UI REFRESH & SAVE/LOAD ****/ function updateUI() { moneyDisplay.setText("$" + Math.floor(gameState.money).toLocaleString()); moneyDisplay.x = 2048 / 2 - moneyDisplay.width / 2; prestigeDisplay.setText("Prestige: " + gameState.prestigeCount); } LK.saveGame = function () { return gameState; }; LK.loadGame = function (data) { gameState = data; updateUI(); }; /**** * START GAME ****/ function startGame() { currentBackground = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5 }); currentBackground.x = 2048 / 2; currentBackground.y = 2732 / 2; game.addChildAt(currentBackground, 0); miner = new Miner(); miner.x = 2048 / 2; miner.y = 2732 / 2; game.addChild(miner); initialSpawn(); updateUI(); } startGame(); game.pauseForQuantumSelection = function () { quantumSelectionActive = true; quantumSelectTimer = 0; /* Optional: add visual cues */ };
===================================================================
--- original.js
+++ change.js
@@ -14,9 +14,8 @@
var Cluster = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.oreList = [];
- // Set low zIndex so clusters (and ores) remain behind UI menus
self.zIndex = 0;
var centerX = 100 + Math.random() * (2048 - 200);
var centerY = 100 + Math.random() * (2732 - 200);
self.x = centerX;
@@ -29,9 +28,8 @@
ore.y = (Math.random() - 0.5) * 120;
self.oreList.push(ore);
self.addChild(ore);
}
- // Only remove the cluster when all ores are destroyed
self.notifyOreDestroyed = function (ore) {
var idx = self.oreList.indexOf(ore);
if (idx >= 0) {
self.oreList.splice(idx, 1);
@@ -45,8 +43,10 @@
if (cidx >= 0) {
clusters.splice(cidx, 1);
}
gameState.clusterCount[type]--;
+ // Increment ore–mined stat:
+ gameState.oreMined[type] = (gameState.oreMined[type] || 0) + 1;
var finalDelay = gameState.respawnTime;
if (type === 'coal') {
finalDelay *= 2;
}
@@ -57,19 +57,17 @@
};
return self;
});
/** Drone – moves and zaps ores.
-* Now with an increased AOE range (150) and added spinning effect.
-* Also, when a drone damages an ore, it spawns a plasma–ring effect.
+* With increased AOE range, spinning effect, and plasma–ring effect on hit.
****/
var Drone = Container.expand(function () {
var self = Container.call(this);
self.droneSprite = LK.getAsset('drone_asset', {
anchorX: 0.5,
anchorY: 0.5
});
self.addChild(self.droneSprite);
- // Increase AOE range from 100 to 150
self.AOE_RANGE = 150;
self.droneDamage = 2;
self.COOLDOWN_MAX = 60;
self.cooldown = 0;
@@ -79,9 +77,8 @@
MIN_Y = 50,
MAX_Y = 2682;
self.vx = Math.random() < 0.5 ? SPEED : -SPEED;
self.vy = Math.random() < 0.5 ? SPEED : -SPEED;
- // Update drone movement and add spinning effect
self.updateDrone = function () {
self.x += self.vx;
self.y += self.vy;
if (self.x < MIN_X || self.x > MAX_X) {
@@ -89,9 +86,8 @@
}
if (self.y < MIN_Y || self.y > MAX_Y) {
self.vy = -self.vy;
}
- // Slight random deviation
if (Math.random() < 0.01) {
self.vx += (Math.random() - 0.5) * 2;
self.vy += (Math.random() - 0.5) * 2;
var speed = Math.sqrt(self.vx * self.vx + self.vy * self.vy);
@@ -99,17 +95,15 @@
self.vx = self.vx / speed * SPEED;
self.vy = self.vy / speed * SPEED;
}
}
- // Spinning effect:
self.droneSprite.rotation += 0.1;
if (self.cooldown > 0) {
self.cooldown--;
} else {
self.tryZap();
}
};
- // Drone zap: now for each ore in range, apply partial damage with reward and spawn an AOE effect.
self.tryZap = function () {
var hitSomething = false;
clusters.forEach(function (cluster) {
cluster.oreList.forEach(function (ore) {
@@ -122,14 +116,15 @@
if (dist < self.AOE_RANGE) {
var damage = self.droneDamage;
var actualDamage = Math.min(damage, ore.health);
var fraction = actualDamage / ore.maxHealth;
- var reward = fraction * ore.getValue();
+ var reward = Math.round(fraction * ore.getValue());
if (ore.awardedMoney + reward > ore.getValue()) {
reward = ore.getValue() - ore.awardedMoney;
}
ore.awardedMoney += reward;
gameState.money += reward;
+ gameState.totalMoneyEarned += reward;
updateUI();
ore.health -= actualDamage;
hitSomething = true;
spawnDroneAOE(ore);
@@ -150,10 +145,9 @@
};
return self;
});
/** Miner – moves toward and mines the nearest ore.
-* Now uses partial reward logic so that every hit awards money proportional to the percentage of the ore’s total value lost.
-* (Also note: the miner’s swing speed has been slowed by default – its miningRate is 60 instead of 30.)
+* Uses partial reward logic on each hit.
****/
var Miner = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('miner', {
@@ -163,14 +157,12 @@
self.speed = 5;
self.currentTarget = null;
self.miningRange = 25;
self.miningCooldown = 0;
- self.miningRate = 60; // Slower default swing speed
+ self.miningRate = 60;
self.miningDamage = 1;
- // Save originals for hyper mode
self.originalMiningRate = self.miningRate;
self.originalMiningDamage = self.miningDamage;
- // Boost and mode variables
self.speedBoostMultiplier = 1;
self.speedBoostTimer = 0;
self.soulEmberStacks = 0;
self.quantumPathActive = false;
@@ -252,23 +244,24 @@
self.y += Math.sin(LK.time.elapsed / 250) * 0.5;
}
}
};
- // Modified mineOre: now every hit (automated by the miner) awards partial money.
self.mineOre = function (ore) {
if (self.miningCooldown > 0) {
self.miningCooldown--;
return;
}
var damageDealt = self.miningDamage * gameState.pickaxeLevel * (gameState.pickaxeBaseMultiplier || 1);
var actualDamage = Math.min(damageDealt, ore.health);
var fraction = actualDamage / ore.maxHealth;
- var reward = fraction * ore.getValue();
+ var reward = Math.round(fraction * ore.getValue());
if (ore.awardedMoney + reward > ore.getValue()) {
reward = ore.getValue() - ore.awardedMoney;
}
ore.awardedMoney += reward;
gameState.money += reward;
+ gameState.totalMoneyEarned += reward;
+ gameState.minerHitCount++;
updateUI();
ore.health -= actualDamage;
self.miningCooldown = self.miningRate;
var mineSound = LK.getSound('mine_' + ore.type);
@@ -309,15 +302,14 @@
};
return self;
});
/** Ore – represents a single ore.
-* Now set to be interactive and to award partial money on every hit.
+* Now interactive and awards per–hit money (with rewards rounded to whole numbers).
****/
var Ore = Container.expand(function (type, cluster) {
var self = Container.call(this);
self.type = type;
self.cluster = cluster;
- // Set low zIndex so that ores remain behind the upgrade menu
self.zIndex = 0;
var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby'];
if (typeList.indexOf(type) >= 0) {
self.tier = typeList.indexOf(type) + 1;
@@ -326,14 +318,12 @@
}
self.baseValue = oreData[type].baseValue;
self.maxHealth = oreData[type].baseHealth;
self.health = self.maxHealth;
- // Attach the ore asset
self.attachAsset(oreData[type].assetId, {
anchorX: 0.5,
anchorY: 0.5
});
- // Health bar for ore
self.healthBar = LK.getAsset('rectangle', {
width: 120,
height: 20,
fill: 0x00FF00,
@@ -342,38 +332,36 @@
});
self.healthBar.x = 0;
self.healthBar.y = -70;
self.addChild(self.healthBar);
- // Track how much money has been awarded so far
self.awardedMoney = 0;
self.lastTapTime = 0;
- // Make ore interactive so that clicks/taps trigger the down handler.
self.interactive = true;
- // When the player taps/clicks the ore, apply damage and award partial money.
+ self.buttonMode = true;
self.down = function () {
- var currentTime = typeof LK.time !== 'undefined' ? LK.time.elapsed : 0;
- // Minimal cooldown (~1 ms)
+ var currentTime = typeof LK.time !== 'undefined' ? LK.time.elapsed : Date.now();
if (currentTime - self.lastTapTime < 1) {
return;
}
self.lastTapTime = currentTime;
var damage = gameState.tapDamage;
var actualDamage = Math.min(damage, self.health);
var fraction = actualDamage / self.maxHealth;
- var reward = fraction * self.getValue();
+ var reward = Math.round(fraction * self.getValue());
if (self.awardedMoney + reward > self.getValue()) {
reward = self.getValue() - self.awardedMoney;
}
self.awardedMoney += reward;
gameState.money += reward;
+ gameState.totalMoneyEarned += reward;
+ gameState.tapCount++;
updateUI();
self.health -= actualDamage;
spawnMiningParticles(self, 2);
if (self.health <= 0) {
self.cluster.notifyOreDestroyed(self);
}
};
- // Special pulsing glow for certain ores.
if (["chronostone", "soulember", "quantumshard"].indexOf(type) >= 0) {
var _pulseGlow = function pulseGlow() {
tween(glow, {
alpha: 1
@@ -426,41 +414,201 @@
screenShake(500, 10);
};
}
self.getValue = function () {
- return self.baseValue * gameState.oreMultipliers[self.type];
+ var val = self.baseValue * gameState.oreMultipliers[self.type];
+ return Math.round(val / 2) * 2; // Force even
};
return self;
});
/****
* Initialize Game
****/
-/****
-* GAME INITIALIZATION & HELPER FUNCTIONS
-****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
-function createAchievementsMenu() {
- // Placeholder for creating the achievements menu
- console.log("Achievements menu created");
-}
-// New assets for popups, prestige main button, drone AOE effect:
/****
+* GAME-STATE & STATS
+****/
+/****
* Helper Functions
****/
-function hideUpgradeDesc() {
- // Placeholder for hiding upgrade description UI elements if needed
-}
+var gameState = {
+ money: 0,
+ pickaxeLevel: 1,
+ pickaxeBaseMultiplier: 1,
+ droneLevel: 0,
+ currentTier: 1,
+ oreMultipliers: {
+ coal: 1,
+ iron: 1,
+ gold: 1,
+ diamond: 1,
+ sapphire: 1,
+ emerald: 1,
+ ruby: 1,
+ chronostone: 1,
+ soulember: 1,
+ quantumshard: 1
+ },
+ respawnTime: 3000,
+ maxClustersPerType: 3,
+ clusterCount: {
+ coal: 0,
+ iron: 0,
+ gold: 0,
+ diamond: 0,
+ sapphire: 0,
+ emerald: 0,
+ ruby: 0,
+ chronostone: 0,
+ soulember: 0,
+ quantumshard: 0
+ },
+ clusterConfigLevels: [{
+ min: 2,
+ max: 3
+ }, {
+ min: 3,
+ max: 4
+ }, {
+ min: 4,
+ max: 5
+ }, {
+ min: 5,
+ max: 6
+ }, {
+ min: 6,
+ max: 7
+ }, {
+ min: 6,
+ max: 8
+ }],
+ clusterUpgradeTier: 0,
+ get clusterConfig() {
+ return this.clusterConfigLevels[this.clusterUpgradeTier] || {
+ min: 2,
+ max: 3
+ };
+ },
+ prestigeCount: 0,
+ prestigeCurrency: 0,
+ tapDamage: 1,
+ totalMoneyEarned: 0,
+ tapCount: 0,
+ minerHitCount: 0,
+ startTime: Date.now(),
+ oreMined: {
+ coal: 0,
+ iron: 0,
+ gold: 0,
+ diamond: 0,
+ sapphire: 0,
+ emerald: 0,
+ ruby: 0,
+ chronostone: 0,
+ soulember: 0,
+ quantumshard: 0
+ }
+};
+/****
+* ACHIEVEMENTS
+****/
+var achievements = [{
+ id: 'first_mine',
+ name: 'First Mine',
+ description: 'Mine your first ore',
+ achieved: false,
+ condition: function condition() {
+ return gameState.money > 0;
+ }
+}, {
+ id: 'rich_miner',
+ name: 'Rich Miner',
+ description: 'Earn 1 Billion money',
+ achieved: false,
+ condition: function condition() {
+ return gameState.money >= 1e9;
+ }
+},
+// New achievement with progress bar
+{
+ id: 'coal_miner',
+ name: 'Coal Miner',
+ description: 'Mine 50 coal ores',
+ achieved: false,
+ target: 50,
+ condition: function condition() {
+ return gameState.oreMined.coal >= 50;
+ }
+}];
+/****
+* ORE DATA (All ore values will be forced even.)
+****/
+var oreData = {
+ coal: {
+ baseValue: 5,
+ baseHealth: 10,
+ assetId: 'coal_ore'
+ },
+ iron: {
+ baseValue: 500,
+ baseHealth: 100,
+ assetId: 'iron_ore'
+ },
+ gold: {
+ baseValue: 10000,
+ baseHealth: 500,
+ assetId: 'gold_ore'
+ },
+ diamond: {
+ baseValue: 25000,
+ baseHealth: 1000,
+ assetId: 'diamond_ore'
+ },
+ sapphire: {
+ baseValue: 100000,
+ baseHealth: 2000,
+ assetId: 'sapphire_ore'
+ },
+ emerald: {
+ baseValue: 500000,
+ baseHealth: 5000,
+ assetId: 'emerald_ore'
+ },
+ ruby: {
+ baseValue: 1000000,
+ baseHealth: 10000,
+ assetId: 'ruby_ore'
+ },
+ chronostone: {
+ baseValue: 2000000,
+ baseHealth: 2000,
+ assetId: 'chronostone_ore',
+ color: 0xc997d8
+ },
+ soulember: {
+ baseValue: 5000000,
+ baseHealth: 5000,
+ assetId: 'soulember_ore',
+ color: 0xdef3e5
+ },
+ quantumshard: {
+ baseValue: 10000000,
+ baseHealth: 10000,
+ assetId: 'quantumshard_ore',
+ color: 0xa1bb12
+ }
+};
+function hideUpgradeDesc() {/* Placeholder */}
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
-// Spawn mining particles – set low zIndex so they remain behind menus.
function spawnMiningParticles(ore, num) {
for (var i = 0; i < num; i++) {
var p = LK.getAsset('mining_particle', {
anchorX: 0.5,
@@ -478,9 +626,8 @@
}
p.vx = (Math.random() - 0.5) * 10;
p.vy = (Math.random() - 0.5) * 10;
p.alpha = 1;
- // Set particles behind UI
p.zIndex = -1;
tween(p, {
alpha: 0,
y: p.y - 50
@@ -492,9 +639,8 @@
});
game.addChild(p);
}
}
-// Interpolate between two colors (used for health bars)
function interpolateColor(c1, c2, f) {
var r1 = c1 >> 16 & 0xFF,
g1 = c1 >> 8 & 0xFF,
b1 = c1 & 0xFF;
@@ -505,14 +651,13 @@
var g = Math.round(g1 + f * (g2 - g1));
var b = Math.round(b1 + f * (b2 - b1));
return r << 16 | g << 8 | b;
}
-// Simple screen shake effect (for explosions)
function screenShake(duration, magnitude) {
var originalX = game.x,
- originalY = game.y;
- var shakeInterval = 50;
- var elapsed = 0;
+ originalY = game.y,
+ shakeInterval = 50,
+ elapsed = 0;
var shake = setInterval(function () {
elapsed += shakeInterval;
game.x = originalX + (Math.random() - 0.5) * magnitude;
game.y = originalY + (Math.random() - 0.5) * magnitude;
@@ -522,9 +667,8 @@
game.y = originalY;
}
}, shakeInterval);
}
-// Spawn a drone AOE effect (a plasma–ring that fades out)
function spawnDroneAOE(ore) {
var effect = LK.getAsset('drone_aoe_effect', {
anchorX: 0.5,
anchorY: 0.5
@@ -536,9 +680,8 @@
effect.x = ore.x;
effect.y = ore.y;
}
effect.alpha = 1;
- // Set its zIndex so it appears above ores but below the upgrade menu
effect.zIndex = 1;
game.addChild(effect);
tween(effect, {
alpha: 0
@@ -550,151 +693,190 @@
}
});
}
/****
-* ACHIEVEMENT SYSTEM
+* Achievements Menu & Stats Tab
****/
-var achievements = [{
- id: 'first_mine',
- name: 'First Mine',
- description: 'Mine your first ore',
- achieved: false,
- condition: function condition() {
- return gameState.money > 0;
+// Achievements Menu – shows a progress bar for achievements with a target.
+function createAchievementsMenu() {
+ upgradeMenu.removeChildren();
+ var menuBg = LK.getAsset('rectangle', {
+ width: 1800,
+ height: 2200,
+ color: 0x333333,
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ menuBg.alpha = 0.9;
+ menuBg.x = 2048 / 2;
+ menuBg.y = 2732 / 2 + 50;
+ upgradeMenu.addChild(menuBg);
+ var titleText = new Text2("Achievements", {
+ size: 60,
+ fill: 0xFFFFFF,
+ align: "center"
+ });
+ titleText.anchor.set(0.5);
+ titleText.x = menuBg.x;
+ titleText.y = menuBg.y - 1000;
+ upgradeMenu.addChild(titleText);
+ var yStart = menuBg.y - 800,
+ spacing = 150;
+ achievements.forEach(function (ach, index) {
+ var container = new Container();
+ container.x = menuBg.x;
+ container.y = yStart + index * spacing;
+ var title = new Text2(ach.name, {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ title.anchor.set(0.5);
+ container.addChild(title);
+ if (ach.target !== undefined) {
+ var currentProgress = 0;
+ if (ach.id === 'coal_miner') {
+ currentProgress = gameState.oreMined.coal;
+ }
+ var progressBarBg = LK.getAsset('rectangle', {
+ width: 400,
+ height: 30,
+ color: 0x555555,
+ anchorX: 0,
+ anchorY: 0.5
+ });
+ progressBarBg.x = -200;
+ progressBarBg.y = 50;
+ container.addChild(progressBarBg);
+ var progressWidth = Math.min(currentProgress / ach.target * 400, 400);
+ var progressBarFg = LK.getAsset('rectangle', {
+ width: progressWidth,
+ height: 30,
+ color: 0x00FF00,
+ anchorX: 0,
+ anchorY: 0.5
+ });
+ progressBarFg.x = -200;
+ progressBarFg.y = 50;
+ container.addChild(progressBarFg);
+ var progressText = new Text2(currentProgress + "/" + ach.target, {
+ size: 30,
+ fill: 0xFFFFFF
+ });
+ progressText.anchor.set(0.5);
+ progressText.x = 0;
+ progressText.y = 50;
+ container.addChild(progressText);
+ }
+ if (ach.achieved) {
+ var achievedText = new Text2("Achieved!", {
+ size: 30,
+ fill: 0xFFD700
+ });
+ achievedText.anchor.set(0.5);
+ achievedText.x = 300;
+ achievedText.y = 0;
+ container.addChild(achievedText);
+ }
+ upgradeMenu.addChild(container);
+ });
+ var backBtn = LK.getAsset('cancelButton', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ backBtn.x = menuBg.x + 700;
+ backBtn.y = menuBg.y - 1000;
+ backBtn.down = function () {
+ createMainUpgradeMenu();
+ };
+ upgradeMenu.addChild(backBtn);
+}
+// Game Stats Menu – shows various overall statistics.
+function createStatsMenu() {
+ upgradeMenu.removeChildren();
+ var menuBg = LK.getAsset('rectangle', {
+ width: 1800,
+ height: 2200,
+ color: 0x222222,
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ menuBg.alpha = 0.9;
+ menuBg.x = 2048 / 2;
+ menuBg.y = 2732 / 2 + 50;
+ upgradeMenu.addChild(menuBg);
+ var titleText = new Text2("Game Stats", {
+ size: 60,
+ fill: 0xFFFFFF,
+ align: "center"
+ });
+ titleText.anchor.set(0.5);
+ titleText.x = menuBg.x;
+ titleText.y = menuBg.y - 1000;
+ upgradeMenu.addChild(titleText);
+ // For each ore type, show its asset and number mined.
+ var oreTypes = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby', 'chronostone', 'soulember', 'quantumshard'];
+ var yStart = menuBg.y - 800,
+ spacing = 60;
+ oreTypes.forEach(function (type, index) {
+ var statContainer = new Container();
+ statContainer.x = menuBg.x - 600;
+ statContainer.y = yStart + index * spacing;
+ var oreAsset = LK.getAsset(type + '_ore', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ oreAsset.scale = 0.5;
+ oreAsset.x = 0;
+ oreAsset.y = 0;
+ statContainer.addChild(oreAsset);
+ var countText = new Text2("Mined: " + (gameState.oreMined[type] || 0), {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ countText.x = 100;
+ countText.y = 0;
+ statContainer.addChild(countText);
+ upgradeMenu.addChild(statContainer);
+ });
+ var statsText = "";
+ statsText += "Total Money Earned: $" + gameState.totalMoneyEarned.toLocaleString() + "\n";
+ var achievedCount = achievements.filter(function (a) {
+ return a.achieved;
+ }).length;
+ statsText += "Achievements: " + achievedCount + "/" + achievements.length + "\n";
+ statsText += "Prestige Count: " + gameState.prestigeCount + "\n";
+ var timePlayed = Math.floor((Date.now() - gameState.startTime) / 1000);
+ statsText += "Time Played: " + timePlayed + " sec\n";
+ statsText += "Ore Taps: " + gameState.tapCount + "\n";
+ statsText += "Miner Hits: " + gameState.minerHitCount + "\n";
+ var fullyUpgraded = 0;
+ for (var key in oreUpgrades) {
+ oreUpgrades[key].forEach(function (upg) {
+ if (upg.level >= upg.maxLevel) {
+ fullyUpgraded++;
+ }
+ });
}
-}, {
- id: 'rich_miner',
- name: 'Rich Miner',
- description: 'Earn 1 Billion money',
- achieved: false,
- condition: function condition() {
- return gameState.money >= 1e9;
- }
-}];
+ statsText += "Fully Upgraded Ore Upgrades: " + fullyUpgraded + "\n";
+ var otherStats = new Text2(statsText, {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ otherStats.x = menuBg.x + 200;
+ otherStats.y = menuBg.y - 800;
+ upgradeMenu.addChild(otherStats);
+ var backBtn = LK.getAsset('cancelButton', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ backBtn.x = menuBg.x + 700;
+ backBtn.y = menuBg.y - 1000;
+ backBtn.down = function () {
+ createMainUpgradeMenu();
+ };
+ upgradeMenu.addChild(backBtn);
+}
/****
-* ORE DATA
-****/
-var oreData = {
- coal: {
- baseValue: 5,
- baseHealth: 10,
- assetId: 'coal_ore'
- },
- iron: {
- baseValue: 500,
- baseHealth: 100,
- assetId: 'iron_ore'
- },
- gold: {
- baseValue: 10000,
- baseHealth: 500,
- assetId: 'gold_ore'
- },
- diamond: {
- baseValue: 25000,
- baseHealth: 1000,
- assetId: 'diamond_ore'
- },
- sapphire: {
- baseValue: 100000,
- baseHealth: 2000,
- assetId: 'sapphire_ore'
- },
- emerald: {
- baseValue: 500000,
- baseHealth: 5000,
- assetId: 'emerald_ore'
- },
- ruby: {
- baseValue: 1000000,
- baseHealth: 10000,
- assetId: 'ruby_ore'
- },
- chronostone: {
- baseValue: 2000000,
- baseHealth: 2000,
- assetId: 'chronostone_ore',
- color: 0xc997d8
- },
- soulember: {
- baseValue: 5000000,
- baseHealth: 5000,
- assetId: 'soulember_ore',
- color: 0xdef3e5
- },
- quantumshard: {
- baseValue: 10000000,
- baseHealth: 10000,
- assetId: 'quantumshard_ore',
- color: 0xa1bb12
- }
-};
-/****
-* GAME STATE
-****/
-var gameState = {
- money: 0,
- pickaxeLevel: 1,
- pickaxeBaseMultiplier: 1,
- droneLevel: 0,
- currentTier: 1,
- oreMultipliers: {
- coal: 1,
- iron: 1,
- gold: 1,
- diamond: 1,
- sapphire: 1,
- emerald: 1,
- ruby: 1,
- chronostone: 1,
- soulember: 1,
- quantumshard: 1
- },
- respawnTime: 3000,
- maxClustersPerType: 3,
- clusterCount: {
- coal: 0,
- iron: 0,
- gold: 0,
- diamond: 0,
- sapphire: 0,
- emerald: 0,
- ruby: 0,
- chronostone: 0,
- soulember: 0,
- quantumshard: 0
- },
- clusterConfigLevels: [{
- min: 2,
- max: 3
- }, {
- min: 3,
- max: 4
- }, {
- min: 4,
- max: 5
- }, {
- min: 5,
- max: 6
- }, {
- min: 6,
- max: 7
- }, {
- min: 6,
- max: 8
- }],
- clusterUpgradeTier: 0,
- get clusterConfig() {
- return this.clusterConfigLevels[this.clusterUpgradeTier] || {
- min: 2,
- max: 3
- };
- },
- prestigeCount: 0,
- prestigeCurrency: 0,
- tapDamage: 1
-};
-/****
* PRESTIGE & BACKGROUND HELPERS
****/
function getPrestigeRequirement() {
return 1e9 * Math.pow(2, gameState.prestigeCount);
@@ -705,18 +887,16 @@
function calculatePrestigeShards() {
return 1;
}
function doPrestige() {
- // Remove all clusters
for (var i = clusters.length - 1; i >= 0; i--) {
var c = clusters[i];
c.removeChildren();
if (c.parent) {
c.parent.removeChild(c);
}
clusters.splice(i, 1);
}
- // Reset drone objects & sprites
droneObjects.forEach(function (d) {
if (d.parent) {
d.parent.removeChild(d);
}
@@ -727,26 +907,22 @@
ds.parent.removeChild(ds);
}
});
droneSprites = [];
- // Increase prestige currency/count
var shards = calculatePrestigeShards();
gameState.prestigeCurrency += shards;
gameState.prestigeCount++;
gameState.money = 0;
gameState.currentTier = 1;
for (var key in gameState.clusterCount) {
gameState.clusterCount[key] = 0;
}
- // Reset upgrades (all except prestige upgrades persist)
resetUpgrades();
- // Reset drones to 0
gameState.droneLevel = 0;
handleBackgroundTransition();
initialSpawn();
updateUI();
}
-// Resets general, ore, and drone upgrades (and relevant gameState values) to default.
function resetUpgrades() {
gameState.oreMultipliers = {
coal: 1,
iron: 1,
@@ -763,9 +939,8 @@
gameState.pickaxeBaseMultiplier = 1;
gameState.tapDamage = 1;
gameState.respawnTime = 3000;
gameState.clusterUpgradeTier = 0;
- // Reset ore upgrades
for (var key in oreUpgrades) {
oreUpgrades[key].forEach(function (upg) {
if (upg.initCost === undefined) {
upg.initCost = upg.cost;
@@ -774,18 +949,16 @@
upg.level = 0;
upg.purchased = false;
});
}
- // Reset general upgrades
generalUpgrades.forEach(function (upg) {
if (upg.initCost === undefined) {
upg.initCost = upg.cost;
}
upg.cost = upg.initCost;
upg.level = 0;
upg.purchased = false;
});
- // Reset drone upgrades
droneUpgrades.forEach(function (upg) {
if (upg.initCost === undefined) {
upg.initCost = upg.cost;
}
@@ -793,11 +966,8 @@
upg.level = 0;
upg.purchased = false;
});
}
-/****
-* PRESTIGE & BACKGROUND HELPERS (continued)
-****/
function handleBackgroundTransition() {
if (nextBackground && nextBackground.parent) {
nextBackground.parent.removeChild(nextBackground);
}
@@ -866,11 +1036,12 @@
var nextBackground = null;
var miner = null;
var droneObjects = [];
var droneSprites = [];
-// Global prestige main button (appears on the lower left once eligible)
var prestigeMainButton = null;
-// Initial spawn of clusters
+/****
+* Spawn Functions
+****/
function initialSpawn() {
var allTypes = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby'];
allTypes.forEach(function (type, idx) {
var t = idx + 1;
@@ -881,9 +1052,8 @@
}
});
maybeSpawnSpecialOres();
}
-// Create drones up to droneLevel
function updateDroneObjects() {
while (droneObjects.length < gameState.droneLevel) {
var d = new Drone();
d.x = 200 + Math.random() * (2048 - 400);
@@ -903,9 +1073,8 @@
droneSprites.push(drone);
game.addChild(drone);
}
}
-// Spawn a cluster of a given ore type (if allowed by tier and max count)
function maybeSpawnCluster(type) {
var typeList = ['coal', 'iron', 'gold', 'diamond', 'sapphire', 'emerald', 'ruby'];
if (typeList.indexOf(type) >= 0) {
var tIndex = typeList.indexOf(type) + 1;
@@ -920,9 +1089,8 @@
game.addChild(cluster);
clusters.push(cluster);
gameState.clusterCount[type]++;
}
-// Attempt to spawn special ores based on prestige level.
function maybeSpawnSpecialOres() {
var spawnChances = [];
if (gameState.prestigeCount >= 3) {
spawnChances.push({
@@ -1231,9 +1399,9 @@
gameState.pickaxeBaseMultiplier *= 1.2;
this.cost = Math.floor(this.cost * 2);
}
},
-// New: Tap Damage Upgrade (increases tap/click damage)
+// New: Tap Damage Upgrade
{
id: 'tap_damage',
name: 'Tap Damage Upgrade',
cost: 5000,
@@ -1246,9 +1414,9 @@
gameState.tapDamage = gameState.tapDamage * 1.5;
this.cost = Math.floor(this.cost * 2);
}
},
-// New: Miner Swing Speed Upgrade (reduces miner cooldown)
+// New: Miner Swing Speed Upgrade
{
id: 'miner_speed',
name: 'Miner Swing Speed Upgrade',
cost: 20000,
@@ -1346,9 +1514,9 @@
/****
* UI
****/
var upgradeMenu = new Container();
-upgradeMenu.zIndex = 10000; // Force upgrade menu on top.
+upgradeMenu.zIndex = 10000; // Force on top.
var tooltip = new Text2('', {
size: 40,
fill: 0xFFFFFF
});
@@ -1384,9 +1552,8 @@
game.addChild(upgradeMenu);
upgradeMenu.parent.setChildIndex(upgradeMenu, upgradeMenu.parent.children.length - 1);
};
game.addChild(shopOpenButton);
-// Debug: Add money button
var addMoneyButton = LK.getAsset('buy_button', {
anchorX: 0.5,
anchorY: 0.5
});
@@ -1397,9 +1564,9 @@
updateUI();
};
game.addChild(addMoneyButton);
/****
-* UPGRADE MODAL HELPER – for confirming an upgrade.
+* UPGRADE MODAL HELPER
****/
function showUpgradeModal(upg, btn, callback) {
var modal = new Container();
var bg = LK.getAsset('upgrade_popup_bg', {
@@ -1458,9 +1625,9 @@
modal.destroy();
};
}
/****
-* PRESTIGE MODAL – uses custom assets for the popup and Yes button.
+* PRESTIGE MODAL
****/
function showPrestigeModal() {
var modal = new Container();
var popup = LK.getAsset('prestige_popup', {
@@ -1512,10 +1679,9 @@
modal.destroy();
};
}
/****
-* MAIN UPGRADE MENU – arranged in two columns with tabs moved upward.
-* Contains a "Prestige" category which now does not include a "Prestige Now" button (that is on the main screen).
+* MAIN UPGRADE MENU – with new categories including "Game Stats"
****/
function createMainUpgradeMenu() {
upgradeMenu.removeChildren();
subUpgradeItemRefs = [];
@@ -1562,16 +1728,18 @@
type: 'achievements'
}, {
name: 'Prestige',
type: 'prestige'
+ }, {
+ name: 'Game Stats',
+ type: 'stats'
}];
var colSpacing = 400,
rowSpacing = 300;
for (var i = 0; i < categories.length; i++) {
- var col = i % 2;
- var row = Math.floor(i / 2);
+ var col = i % 2,
+ row = Math.floor(i / 2);
var x = menuBg.x + (col === 0 ? -colSpacing : colSpacing);
- // Tabs moved upward:
var y = menuBg.y - 800 + row * rowSpacing;
var btn = LK.getAsset('buy_button', {
anchorX: 0.5,
anchorY: 0.5
@@ -1599,8 +1767,10 @@
} else if (cat.type === 'achievements') {
createAchievementsMenu();
} else if (cat.type === 'prestige') {
createPrestigeMenu();
+ } else if (cat.type === 'stats') {
+ createStatsMenu();
} else {
createSubUpgradeMenu(cat.name, oreUpgrades[cat.type]);
}
};
@@ -1644,13 +1814,13 @@
titleText.anchor.set(0.5);
titleText.x = menuBg.x;
titleText.y = menuBg.y - 1000;
upgradeMenu.addChild(titleText);
- var startY = menuBg.y - 800;
- var colSpacing = 400;
+ var startY = menuBg.y - 800,
+ colSpacing = 400;
for (var i = 0; i < upgList.length; i++) {
- var col = i % 2;
- var row = Math.floor(i / 2);
+ var col = i % 2,
+ row = Math.floor(i / 2);
var btn = LK.getAsset('buy_button', {
anchorX: 0.5,
anchorY: 0.5
});
@@ -1724,91 +1894,12 @@
}
return true;
}
/****
-* PRESTIGE SHOP MENU – now integrated as the "Prestige" tab.
-****/
-function createPrestigeMenu() {
- upgradeMenu.removeChildren();
- subUpgradeItemRefs = [];
- var menuBg = LK.getAsset('rectangle', {
- width: 1800,
- height: 2200,
- color: 0x2a2a2a,
- anchorX: 0.5,
- anchorY: 0.5
- });
- menuBg.alpha = 0.9;
- menuBg.x = 2048 / 2;
- menuBg.y = 2732 / 2 + 50;
- upgradeMenu.addChild(menuBg);
- var titleText = new Text2('Prestige Shop', {
- size: 60,
- fill: 0xFFFFFF,
- align: 'center'
- });
- titleText.anchor.set(0.5);
- titleText.x = menuBg.x;
- titleText.y = menuBg.y - 1000;
- upgradeMenu.addChild(titleText);
- // List prestige upgrades in two columns with increased spacing.
- var combinedUpgrades = prestigeUpgrades.concat(prestigeDrones);
- var colSpacing = 400,
- rowSpacing = 300;
- var startX = menuBg.x - colSpacing / 2;
- for (var i = 0; i < combinedUpgrades.length; i++) {
- var col = i % 2;
- var row = Math.floor(i / 2);
- var btn = LK.getAsset('buy_button', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- btn.x = startX + col * colSpacing;
- btn.y = menuBg.y - 500 + row * rowSpacing;
- upgradeMenu.addChild(btn);
- var txtStr = combinedUpgrades[i].name + "\nCost: " + combinedUpgrades[i].cost + " Shards";
- var txt = new Text2(txtStr, {
- size: 45,
- fill: 0x000000,
- align: 'center'
- });
- txt.anchor.set(0.5);
- txt.x = btn.x;
- txt.y = btn.y;
- upgradeMenu.addChild(txt);
- btn.down = function (upg, btn) {
- return function (event) {
- event.stopPropagation && event.stopPropagation();
- showUpgradeModal(upg, btn, function (confirmed) {
- if (confirmed && gameState.prestigeCurrency >= upg.cost) {
- gameState.prestigeCurrency -= upg.cost;
- upg.action();
- updateUI();
- createPrestigeMenu();
- }
- });
- };
- }(combinedUpgrades[i], btn);
- }
- var backBtn = LK.getAsset('cancelButton', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- backBtn.x = menuBg.x + 700;
- backBtn.y = menuBg.y - 1000;
- backBtn.down = function () {
- createMainUpgradeMenu();
- };
- upgradeMenu.addChild(backBtn);
- upgradeMenu.down = function (event) {
- hideUpgradeDesc();
- };
-}
-/****
* GAME LOOP
****/
-var quantumSelectTimer = 0;
-var quantumSelectionActive = false;
+var quantumSelectTimer = 0,
+ quantumSelectionActive = false;
game.update = function () {
if (miner) {
miner.update();
}
@@ -1843,9 +1934,8 @@
quantumSelectionActive = false;
miner.quantumPathActive = false;
}
}
- // Check achievements and show popup for newly unlocked ones.
achievements.forEach(function (ach) {
if (!ach.achieved && ach.condition()) {
ach.achieved = true;
var achText = new Text2("Achievement Unlocked: " + ach.name, {
@@ -1864,9 +1954,8 @@
}
});
}
});
- // Ensure the prestige main button appears on the lower left when eligible.
if (canPrestige()) {
if (!prestigeMainButton) {
prestigeMainButton = LK.getAsset('prestige_main_button', {
anchorX: 0.5,
@@ -1927,7 +2016,6 @@
}
startGame();
game.pauseForQuantumSelection = function () {
quantumSelectionActive = true;
- quantumSelectTimer = 0;
- // (Optional: darken screen, highlight ores, etc.)
+ quantumSelectTimer = 0; /* Optional: add visual cues */
};
\ No newline at end of file
drone_shot
Sound effect
mine_coal
Sound effect
mine_iron
Sound effect
mine_gold
Sound effect
mine_diamond
Sound effect
mine_sapphire
Sound effect
mine_emerald
Sound effect
mine_ruby
Sound effect
mine_chronostone
Sound effect
mine_quantumshard
Sound effect
ore_destroy_coal
Sound effect
ore_destroy_iron
Sound effect
ore_destroy_gold
Sound effect
ore_destroy_diamond
Sound effect
ore_destroy_sapphire
Sound effect
ore_destroy_emerald
Sound effect
ore_destroy_ruby
Sound effect
mine_coal_1
Sound effect
mine_coal_2
Sound effect
mine_coal_3
Sound effect
mine_diamond1
Sound effect
mine_diamond2
Sound effect
mine_diamond3
Sound effect
mine_emerald1
Sound effect
mine_emerald2
Sound effect
mine_emerald3
Sound effect
mine_gold1
Sound effect
mine_gold2
Sound effect
mine_gold3
Sound effect
mine_iron1
Sound effect
mine_iron2
Sound effect
mine_iron3
Sound effect
mine_ruby1
Sound effect
mine_ruby2
Sound effect
mine_ruby3
Sound effect
mine_sapphire1
Sound effect
mine_sapphire2
Sound effect
mine_sapphire3
Sound effect
song1
Music
song2
Music
song3
Music
song4
Music
song5
Music
song6
Music
song7
Music
song8
Music
song9
Music
song10
Music
song11
Music
song12
Music
song1a
Music
song1b
Music
song2a
Music
song2b
Music
song3a
Music
song3b
Music
song4a
Music
song4b
Music
song5a
Music
song5b
Music
song6a
Music
song6b
Music
song7a
Music
song7b
Music
song8a
Music
song8b
Music
song9a
Music
song9b
Music
song10a
Music
song10b
Music
song11a
Music
song11b
Music
song12a
Music
song12b
Music