/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 25; self.target = null; self.hasHit = false; self.update = function () { if (!self.target || self.hasHit) { return; } var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 20) { if (self.isPiercing && self.hitTargets.indexOf(self.target) === -1) { // Piercing bullet hits target but continues self.target.takeDamage(self.damage); self.hitTargets.push(self.target); // Find next target var nextTarget = null; var closestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase || self.hitTargets.indexOf(enemy) !== -1) { continue; } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < closestDistance && dist <= 200) { closestDistance = dist; nextTarget = enemy; } } if (nextTarget) { self.target = nextTarget; } else { self.hasHit = true; } } else if (self.isSplash) { // Splash damage to all enemies in radius for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var splashDx = enemy.x - self.x; var splashDy = enemy.y - self.y; var splashDistance = Math.sqrt(splashDx * splashDx + splashDy * splashDy); if (splashDistance <= self.splashRadius) { enemy.takeDamage(self.damage); } } self.hasHit = true; } else if (self.isMagic) { // Magic damage with slow effect self.target.takeDamage(self.damage); self.target.applySlow(self.slowEffect, self.slowDuration); self.hasHit = true; } else { // Regular damage self.target.takeDamage(self.damage); self.hasHit = true; } LK.getSound('enemyHit').play(); if (self.hasHit) { return; } } var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 100; self.health = self.maxHealth; self.speed = 2; self.reward = 10; self.pathIndex = 0; self.isDead = false; self.reachedBase = false; self.originalSpeed = self.speed; self.slowEndTime = 0; self.isSlowed = false; // Add health bar var healthBarBg = LK.getAsset('pathTile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.1 }); healthBarBg.y = -40; healthBarBg.tint = 0x333333; self.addChild(healthBarBg); var healthBar = LK.getAsset('grassTile', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.1 }); healthBar.y = -40; healthBar.tint = 0x00FF00; self.addChild(healthBar); self.updateHealthBar = function () { var healthPercent = self.health / self.maxHealth; healthBar.scaleX = 0.6 * healthPercent; if (healthPercent > 0.6) { healthBar.tint = 0x00FF00; // Green } else if (healthPercent > 0.3) { healthBar.tint = 0xFFFF00; // Yellow } else { healthBar.tint = 0xFF0000; // Red } }; self.applySlow = function (slowFactor, duration) { self.speed = self.originalSpeed * slowFactor; self.slowEndTime = LK.ticks + duration; self.isSlowed = true; enemyGraphics.tint = 0x3498db; // Blue tint for slowed enemies }; self.takeDamage = function (damage) { self.health -= damage; self.updateHealthBar(); if (self.health <= 0 && !self.isDead) { self.isDead = true; LK.getSound('enemyDeath').play(); currency += self.reward; // Track boss defeats for achievements if (self.isBoss || self.isUltraBoss) { gameStats.bossesDefeated++; } // Create floating currency text animation var currencyFloat = new Text2('+' + self.reward + 'g', { size: 25, fill: 0xFFD700 }); currencyFloat.anchor.set(0.5, 0.5); currencyFloat.x = self.x; currencyFloat.y = self.y; currencyFloat.alpha = 1; game.addChild(currencyFloat); tween(currencyFloat, { y: self.y - 100, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { currencyFloat.destroy(); } }); updateUI(); // Enhanced death animation with explosion effect tween(enemyGraphics, { scaleX: 1.5, scaleY: 1.5, tint: 0xFF6B6B }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(enemyGraphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 }, { duration: 400, easing: tween.easeIn }); } }); } }; self.update = function () { if (self.isDead || self.reachedBase) { return; } // Check if slow effect should end if (self.isSlowed && LK.ticks >= self.slowEndTime) { self.speed = self.originalSpeed; self.isSlowed = false; enemyGraphics.tint = 0xFFFFFF; // Reset tint } if (self.pathIndex < enemyPath.length) { var target = enemyPath[self.pathIndex]; var dx = target.x - self.x; var dy = target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 20) { self.pathIndex++; if (self.pathIndex >= enemyPath.length) { self.reachedBase = true; lives--; gameStats.livesLost++; updateUI(); return; } } var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; // Add subtle wobble animation while moving if (LK.ticks % 60 === 0) { tween(enemyGraphics, { rotation: Math.sin(LK.ticks * 0.1) * 0.2 }, { duration: 500, easing: tween.easeInOut }); } } }; return self; }); var UltraBoss = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with ultra boss enemy self.removeChildAt(0); var enemyGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5, scaleX: 3.5, scaleY: 3.5 }); enemyGraphics.tint = 0x4B0082; // Dark violet for ultra boss self.maxHealth = 8000; // Much more health for wave 21 self.health = self.maxHealth; self.speed = 1.2; // Faster movement self.originalSpeed = self.speed; self.reward = 500; // Higher reward self.enemyType = 'ultraboss'; self.isUltraBoss = true; self.lastSpecialAttack = 0; self.specialAttackCooldown = 120; // Faster special attacks self.healAmount = 300; // More healing self.shieldActive = false; self.shieldEndTime = 0; self.teleportCooldown = 0; self.pulseTimer = 0; // For continuous pulsing animation // Ultra boss shield ability - damage immunity self.activateShield = function () { self.shieldActive = true; self.shieldEndTime = LK.ticks + 180; // 3 seconds // Shield visual effect tween(enemyGraphics, { tint: 0x00FFFF, scaleX: 3, scaleY: 3 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { enemyGraphics.tint = 0x87CEEB; // Light blue while shielded } }); LK.effects.flashObject(self, 0x00FFFF, 500); }; // Ultra boss teleport ability self.teleportToPath = function () { var randomIndex = Math.min(self.pathIndex + 3, enemyPath.length - 1); var targetPos = enemyPath[randomIndex]; // Teleport effect tween(self, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 200, onFinish: function onFinish() { self.x = targetPos.x; self.y = targetPos.y; self.pathIndex = randomIndex; tween(self, { alpha: 1, scaleX: 2.5, scaleY: 2.5 }, { duration: 300, easing: tween.bounceOut }); } }); LK.effects.flashScreen(0x9932CC, 300); }; // Ultra boss healing ability self.healSelf = function () { self.health = Math.min(self.maxHealth, self.health + self.healAmount); self.updateHealthBar(); // Healing visual effect tween(enemyGraphics, { tint: 0x00FF00, scaleX: 3.5, scaleY: 3.5 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { tween(enemyGraphics, { tint: 0x4B0082, scaleX: 2.5, scaleY: 2.5 }, { duration: 400, easing: tween.easeIn }); } }); LK.effects.flashObject(self, 0x00FF00, 700); }; // Ultra boss area damage ability self.areaDamage = function () { // Damage all nearby towers for (var i = 0; i < towers.length; i++) { var tower = towers[i]; var dx = tower.x - self.x; var dy = tower.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 250) { // Disable tower temporarily and reduce level tower.stunned = true; tower.stunEndTime = LK.ticks + 300; // 5 seconds if (tower.level > 1) { tower.level--; tower.damage = Math.max(10, tower.damage - 15); } // Visual effect tween(tower, { tint: 0x8B0000, alpha: 0.3 }, { duration: 300 }); } } // Ultra boss area damage visual effect LK.effects.flashScreen(0x8B0000, 800); }; self.takeDamage = function (damage, damageType) { if (self.shieldActive) { // No damage while shield is active return; } var actualDamage = damage * 0.6; // Ultra boss takes 40% less damage self.health -= actualDamage; self.updateHealthBar(); if (self.health <= 0 && !self.isDead) { self.isDead = true; LK.getSound('enemyDeath').play(); currency += self.reward; diamonds += 10; // Ultra boss drops more diamonds updateUI(); // Epic ultra boss death animation tween(enemyGraphics, { scaleX: 4, scaleY: 4, tint: 0x9932CC, rotation: Math.PI * 6 }, { duration: 1200, easing: tween.easeOut, onFinish: function onFinish() { tween(enemyGraphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 800, easing: tween.easeIn }); } }); LK.effects.flashScreen(0x9932CC, 1500); } }; self.update = function () { if (self.isDead || self.reachedBase) { return; } // Continuous epic pulsing animation self.pulseTimer++; if (self.pulseTimer % 30 === 0) { var pulseScale = 3.5 + Math.sin(LK.ticks * 0.1) * 0.3; var pulseColor = [0x4B0082, 0x8B0082, 0xFF0082, 0x4B00FF][Math.floor(LK.ticks / 15) % 4]; tween(enemyGraphics, { scaleX: pulseScale, scaleY: pulseScale, tint: pulseColor }, { duration: 500, easing: tween.easeInOut }); } // Epic particle trail effect if (LK.ticks % 10 === 0) { var particle = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); particle.x = self.x + (Math.random() - 0.5) * 100; particle.y = self.y + (Math.random() - 0.5) * 100; particle.tint = 0x4B0082; game.addChild(particle); tween(particle, { alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 3 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Check if shield should end if (self.shieldActive && LK.ticks >= self.shieldEndTime) { self.shieldActive = false; enemyGraphics.tint = 0x4B0082; // Reset ultra boss tint } // Check if slow effect should end if (self.isSlowed && LK.ticks >= self.slowEndTime) { self.speed = self.originalSpeed; self.isSlowed = false; enemyGraphics.tint = self.shieldActive ? 0x87CEEB : 0x4B0082; } // Ultra boss special attacks (more frequent) if (LK.ticks - self.lastSpecialAttack >= self.specialAttackCooldown) { var specialType = Math.floor(Math.random() * 4); if (specialType === 0) { self.healSelf(); } else if (specialType === 1) { self.activateShield(); } else if (specialType === 2 && self.teleportCooldown <= 0) { self.teleportToPath(); self.teleportCooldown = 300; // Shorter cooldown for more teleporting } else { self.areaDamage(); } self.lastSpecialAttack = LK.ticks; } if (self.teleportCooldown > 0) { self.teleportCooldown--; } if (self.pathIndex < enemyPath.length) { var target = enemyPath[self.pathIndex]; var dx = target.x - self.x; var dy = target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 20) { self.pathIndex++; if (self.pathIndex >= enemyPath.length) { self.reachedBase = true; lives -= 15; // Even more damage to base updateUI(); return; } } var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; // Ground shake effect while moving if (LK.ticks % 60 === 0) { LK.effects.flashScreen(0x4B0082, 200); } } }; return self; }); var MagicWarrior = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with magic warrior self.removeChildAt(0); var enemyGraphics = self.attachAsset('magicWarrior', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 120; self.health = self.maxHealth; self.speed = 2.2; self.originalSpeed = self.speed; self.reward = 20; self.enemyType = 'magic'; self.magicResistance = 0.5; // Takes 50% less damage from magic towers self.takeDamage = function (damage, damageType) { var actualDamage = damage; if (damageType === 'magic') { actualDamage = damage * self.magicResistance; } self.health -= actualDamage; self.updateHealthBar(); if (self.health <= 0 && !self.isDead) { self.isDead = true; LK.getSound('enemyDeath').play(); currency += self.reward; updateUI(); tween(enemyGraphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 500 }); } }; return self; }); var HeavyWarrior = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with heavy warrior self.removeChildAt(0); var enemyGraphics = self.attachAsset('heavyWarrior', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 200; self.health = self.maxHealth; self.speed = 1.0; self.originalSpeed = self.speed; self.reward = 25; self.enemyType = 'heavy'; return self; }); var FastWarrior = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with fast warrior self.removeChildAt(0); var enemyGraphics = self.attachAsset('fastWarrior', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 60; self.health = self.maxHealth; self.speed = 3.5; self.originalSpeed = self.speed; self.reward = 15; self.enemyType = 'fast'; return self; }); var Boss = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with boss enemy self.removeChildAt(0); var enemyGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); self.maxHealth = 1000; self.health = self.maxHealth; self.speed = 1.0; self.originalSpeed = self.speed; self.reward = 100; self.enemyType = 'boss'; self.isBoss = true; self.lastSpecialAttack = 0; self.specialAttackCooldown = 300; // 5 seconds at 60fps self.healAmount = 50; self.stun = false; self.stunEndTime = 0; // Boss special ability - healing self.healSelf = function () { self.health = Math.min(self.maxHealth, self.health + self.healAmount); self.updateHealthBar(); // Healing visual effect tween(enemyGraphics, { tint: 0x00FF00, scaleX: 2.5, scaleY: 2.5 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(enemyGraphics, { tint: 0x8B0000, scaleX: 2, scaleY: 2 }, { duration: 300, easing: tween.easeIn }); } }); LK.effects.flashObject(self, 0x00FF00, 500); }; // Boss stun ability - temporarily disable nearby towers self.stunTowers = function () { for (var i = 0; i < towers.length; i++) { var tower = towers[i]; var dx = tower.x - self.x; var dy = tower.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 200) { // Disable tower temporarily tower.stunned = true; tower.stunEndTime = LK.ticks + 180; // 3 seconds // Visual effect tween(tower, { tint: 0x666666, alpha: 0.5 }, { duration: 200 }); } } // Boss stun visual effect LK.effects.flashScreen(0xFF0000, 500); }; self.takeDamage = function (damage, damageType) { var actualDamage = damage * 0.8; // Boss takes 20% less damage self.health -= actualDamage; self.updateHealthBar(); if (self.health <= 0 && !self.isDead) { self.isDead = true; LK.getSound('enemyDeath').play(); currency += self.reward; diamonds += 5; // Boss drops diamonds updateUI(); // Epic boss death animation tween(enemyGraphics, { scaleX: 3, scaleY: 3, tint: 0xFFD700, rotation: Math.PI * 4 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { tween(enemyGraphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 500, easing: tween.easeIn }); } }); LK.effects.flashScreen(0xFFD700, 1000); } }; self.update = function () { if (self.isDead || self.reachedBase) { return; } // Check if slow effect should end if (self.isSlowed && LK.ticks >= self.slowEndTime) { self.speed = self.originalSpeed; self.isSlowed = false; enemyGraphics.tint = 0x8B0000; // Reset boss tint } // Boss special attacks if (LK.ticks - self.lastSpecialAttack >= self.specialAttackCooldown) { var specialType = Math.floor(Math.random() * 2); if (specialType === 0) { self.healSelf(); } else { self.stunTowers(); } self.lastSpecialAttack = LK.ticks; } if (self.pathIndex < enemyPath.length) { var target = enemyPath[self.pathIndex]; var dx = target.x - self.x; var dy = target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 20) { self.pathIndex++; if (self.pathIndex >= enemyPath.length) { self.reachedBase = true; lives -= 5; // Boss deals more damage to base updateUI(); return; } } var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; } }; return self; }); var Tower = Container.expand(function () { var self = Container.call(this); var towerGraphics = self.attachAsset('tower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 150; self.damage = 25; self.fireRate = 60; self.lastFire = 0; self.cost = 50; self.level = 1; self.maxLevel = 3; self.showingRange = false; self.upgradeCost = 75; var rangeIndicator = self.attachAsset('towerRange', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.visible = false; self.showRange = function () { rangeIndicator.visible = true; self.showingRange = true; }; self.hideRange = function () { rangeIndicator.visible = false; self.showingRange = false; }; self.findTarget = function () { var closestEnemy = null; var closestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range && distance < closestDistance) { closestDistance = distance; closestEnemy = enemy; } } return closestEnemy; }; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = target; bullet.damage = self.damage; // Bullet spawn animation bullet.alpha = 0; bullet.scaleX = 0.5; bullet.scaleY = 0.5; bullets.push(bullet); game.addChild(bullet); // Enhanced bullet appearance with trail effect tween(bullet, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeOut }); // Add bullet trail animation tween(bullet, { rotation: Math.PI * 2 }, { duration: 800, easing: tween.linear }); // Tower fire animation var originalScale = towerGraphics.scaleX; tween(towerGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: originalScale, scaleY: originalScale }, { duration: 100, easing: tween.easeIn }); } }); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; self.damage += 15; self.range += 25; self.fireRate = Math.max(30, self.fireRate - 10); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); // Update range indicator rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; // Enhanced visual upgrade animation tween(towerGraphics, { scaleX: 1.4, scaleY: 1.4, tint: 0x00ff00 }, { duration: 300, easing: tween.bounceOut, onFinish: function onFinish() { var finalTint = self.level === 2 ? 0x3A7BD5 : 0x2E5BBA; tween(towerGraphics, { scaleX: 1, scaleY: 1, tint: finalTint }, { duration: 200, easing: tween.easeOut }); } }); // Upgrade sparkle effect LK.effects.flashObject(self, 0xffd700, 800); updateUI(); return true; }; self.down = function (x, y, obj) { // Always start dragging on click draggingTower = self; selectedTower = self; // Use x, y parameters directly instead of trying to convert coordinates dragOffset.x = x - self.x; dragOffset.y = y - self.y; originalTowerPosition.x = self.x; originalTowerPosition.y = self.y; // Find original grid position var gridPos = getGridPosition(self.x, self.y); if (gridPos) { originalGridPosition.x = gridPos.x; originalGridPosition.y = gridPos.y; grid[gridPos.x][gridPos.y].occupied = false; } // Add drag visual effect tween(self, { alpha: 0.7, scaleX: 1.1, scaleY: 1.1 }, { duration: 200 }); hideAllRanges(); self.showRange(); }; self.update = function () { // Check if tower is stunned by boss if (self.stunned && LK.ticks >= self.stunEndTime) { self.stunned = false; // Reset visual effects tween(self, { tint: 0xFFFFFF, alpha: 1 }, { duration: 300 }); } if (self.stunned) { return; } // Skip firing when stunned var target = self.findTarget(); if (target) { self.fire(target); } }; return self; }); var VoidTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with void tower self.removeChildAt(0); var towerGraphics = self.attachAsset('lightningTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0x000080; // Dark blue for void tower towerGraphics.scaleX = 1.6; towerGraphics.scaleY = 1.6; self.range = 400; // Void range self.damage = 75000; // Void damage self.fireRate = 150; // Void firing rate self.cost = 75000; // Void cost self.level = 1; self.maxLevel = 6; // Void upgrades self.upgradeCost = 30000; self.towerType = 'void'; self.voidRifts = true; // Creates void rifts self.timeStop = true; // Stops time for enemies self.realityTear = true; // Tears reality self.voidPull = true; // Pulls enemies into void // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x000080; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Void attack with reality distortion target.takeDamage(self.damage); // Create void rift at target location var riftX = target.x; var riftY = target.y; var rift = LK.getAsset('towerRange', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1, x: riftX, y: riftY }); rift.tint = 0x000080; rift.alpha = 0.8; game.addChild(rift); // Void rift expansion animation tween(rift, { scaleX: 3, scaleY: 3, rotation: Math.PI * 8 }, { duration: 1200, easing: tween.easeOut, onFinish: function onFinish() { // Void pull effect on all enemies for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - riftX; var dy = enemy.y - riftY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 200) { enemy.takeDamage(self.damage * 0.8); // Pull enemies toward void tween(enemy, { x: riftX, y: riftY, alpha: 0.3, scaleX: 0.5, scaleY: 0.5 }, { duration: 800, easing: tween.easeIn }); } } tween(rift, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 600, onFinish: function onFinish() { rift.destroy(); } }); } }); // Void tower firing animation tween(towerGraphics, { scaleX: 2.2, scaleY: 2.2, tint: 0x000000, rotation: Math.PI * 0.8 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1.6, scaleY: 1.6, tint: 0x000080, rotation: 0 }, { duration: 1000, easing: tween.easeIn }); } }); // Void screen distortion effect LK.effects.flashScreen(0x000080, 1200); self.lastFire = LK.ticks; LK.getSound('lightning').play(); }; return self; }); var TitanTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with titan tower self.removeChildAt(0); var towerGraphics = self.attachAsset('superTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0x800080; // Dark purple for titan tower towerGraphics.scaleX = 2.5; towerGraphics.scaleY = 2.5; self.range = 800; // Titan range covers most of the map self.damage = 100000; // Titan damage self.fireRate = 200; // Slow but devastating self.cost = 100000; // Titan cost self.level = 1; self.maxLevel = 10; // Titan upgrades self.upgradeCost = 50000; self.towerType = 'titan'; self.titanWrath = true; // Devastating area attacks self.earthShatter = true; // Shatters the ground self.titanRoar = true; // Stuns all enemies self.meteorStrike = true; // Calls down meteors // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x800080; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Titan wrath - massive area damage var wrathRadius = 400; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - target.x; var dy = enemy.y - target.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= wrathRadius) { var wrathDamage = self.damage * (1 - distance / wrathRadius * 0.5); enemy.takeDamage(wrathDamage); // Titan wrath visual effect tween(enemy, { tint: 0x800080, scaleX: 2, scaleY: 2, rotation: Math.PI }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1, rotation: 0 }, { duration: 800 }); } }); } } // Meteor strike effect for (var m = 0; m < 5; m++) { var meteorX = target.x + (Math.random() - 0.5) * 600; var meteorY = target.y + (Math.random() - 0.5) * 600; var meteor = LK.getAsset('enemy', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, x: meteorX, y: meteorY - 800 }); meteor.tint = 0xFF4500; game.addChild(meteor); // Meteor fall animation tween(meteor, { y: meteorY, scaleX: 2, scaleY: 2, rotation: Math.PI * 3 }, { duration: 1000, easing: tween.easeIn, onFinish: function onFinish() { // Meteor impact damage for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - meteorX; var dy = enemy.y - meteorY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 150) { enemy.takeDamage(self.damage * 0.3); } } tween(meteor, { alpha: 0, scaleX: 5, scaleY: 5 }, { duration: 500, onFinish: function onFinish() { meteor.destroy(); } }); } }); } // Titan tower firing animation tween(towerGraphics, { scaleX: 3.5, scaleY: 3.5, tint: 0xFFFFFF, rotation: Math.PI * 0.3 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 2.5, scaleY: 2.5, tint: 0x800080, rotation: 0 }, { duration: 1200, easing: tween.easeIn }); } }); // Massive screen effects for titan attack LK.effects.flashScreen(0x800080, 3000); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; // Titan roar ability - stuns all enemies self.titanRoar = function () { for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } enemy.applySlow(0.1, 600); // 10 second stun // Roar visual effect tween(enemy, { tint: 0x800080, scaleX: 0.5, scaleY: 0.5 }, { duration: 200, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 600 }); } }); } LK.effects.flashScreen(0x800080, 1500); }; self.update = function () { // Check if tower is stunned by boss if (self.stunned && LK.ticks >= self.stunEndTime) { self.stunned = false; // Reset visual effects tween(self, { tint: 0xFFFFFF, alpha: 1 }, { duration: 300 }); } if (self.stunned) { return; } // Skip firing when stunned // Titan roar every 5 seconds if (LK.ticks % 300 === 0) { self.titanRoar(); } // Titan breathing animation if (LK.ticks % 60 === 0) { var breatheScale = 2.5 + Math.sin(LK.ticks * 0.02) * 0.3; towerGraphics.scaleX = breatheScale; towerGraphics.scaleY = breatheScale; } var target = self.findTarget(); if (target) { self.fire(target); } }; return self; }); var SuperTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with super tower self.removeChildAt(0); var towerGraphics = self.attachAsset('superTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0xFFD700; // Gold color for super tower self.range = 500; // Increased range self.damage = Infinity; self.fireRate = 5; // Much faster firing self.cost = 4000; // Expensive but powerful tower self.level = 1; self.maxLevel = 10; // More upgrade levels self.upgradeCost = 1000; self.towerType = 'super'; self.multiShot = 8; // Fires 8 bullets at once self.piercing = true; // Bullets can hit multiple enemies self.criticalChance = 1.0; // 100% critical hits self.criticalMultiplier = 10; // Critical hits do 10x damage self.isBuffed = true; // Super tower is now buffed self.screenClearChance = 0.1; // 10% chance to clear entire screen self.holyAura = true; // Damages all enemies continuously self.timeWarp = true; // Slows down all enemies globally // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xFFD700; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Screen clear ability - 10% chance to obliterate all enemies if (Math.random() < self.screenClearChance) { for (var e = 0; e < enemies.length; e++) { var enemy = enemies[e]; if (!enemy.isDead && !enemy.reachedBase) { enemy.takeDamage(Infinity); // Epic obliteration animation tween(enemy, { alpha: 0, scaleX: 3, scaleY: 3, rotation: Math.PI * 4, tint: 0xFFFFFF }, { duration: 500, easing: tween.easeOut }); } } // Screen clear visual effect LK.effects.flashScreen(0xFFD700, 1500); } // Multi-shot bullets with buffed critical hit system for (var shot = 0; shot < self.multiShot; shot++) { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = target; // Buffed critical hit calculation (always critical now) bullet.damage = self.damage * self.criticalMultiplier; bullet.isPiercing = self.piercing; bullet.hitTargets = []; // Track hit targets for piercing bullet.isCritical = true; // Spread bullets in a wider fan pattern var angleOffset = (shot - Math.floor(self.multiShot / 2)) * 0.5; bullet.angleOffset = angleOffset; // Buffed super bullet visual - always epic bullet.children[0].tint = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF, 0xFFD700][shot % 8]; bullet.children[0].scaleX = 3; bullet.children[0].scaleY = 3; // Add divine glow effect to bullets tween(bullet.children[0], { alpha: 0.7 }, { duration: 100, onFinish: function onFinish() { tween(bullet.children[0], { alpha: 1 }, { duration: 100 }); } }); bullets.push(bullet); game.addChild(bullet); } // Enhanced super tower fire animation with divine energy pulse var currentScale = 1.5 + (self.level - 1) * 0.2; tween(towerGraphics, { scaleX: currentScale + 1.5, scaleY: currentScale + 1.5, tint: 0xFFFFFF }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: currentScale, scaleY: currentScale, tint: 0xFFD700 }, { duration: 150, easing: tween.easeIn }); } }); // Add massive energy pulse ring animation tween(rangeIndicator, { alpha: 1.0, scaleX: 2.0, scaleY: 2.0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(rangeIndicator, { alpha: 0.3, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeIn }); } }); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; // Add buffed update method for continuous abilities self.update = function () { // Check if tower is stunned by boss if (self.stunned && LK.ticks >= self.stunEndTime) { self.stunned = false; // Reset visual effects tween(self, { tint: 0xFFFFFF, alpha: 1 }, { duration: 300 }); } if (self.stunned) { return; } // Skip firing when stunned // Holy Aura - continuously damage all enemies in massive range if (self.holyAura && LK.ticks % 30 === 0) { for (var e = 0; e < enemies.length; e++) { var enemy = enemies[e]; if (!enemy.isDead && !enemy.reachedBase) { var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 800) { // Massive holy aura range enemy.takeDamage(self.damage * 0.1); // Continuous damage // Holy damage visual effect tween(enemy, { tint: 0xFFD700 }, { duration: 100, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF }, { duration: 200 }); } }); } } } } // Time Warp - globally slow all enemies if (self.timeWarp && LK.ticks % 60 === 0) { for (var e = 0; e < enemies.length; e++) { var enemy = enemies[e]; if (!enemy.isDead && !enemy.reachedBase) { enemy.applySlow(0.3, 180); // Slow all enemies significantly } } // Time warp visual effect LK.effects.flashScreen(0x0080FF, 200); } // Divine pulsing animation if (LK.ticks % 60 === 0) { var pulseColor = [0xFFD700, 0xFF8C00, 0xFFA500, 0xFFFF00][Math.floor(LK.ticks / 60) % 4]; var currentScale = 1.5 + (self.level - 1) * 0.2; tween(towerGraphics, { tint: pulseColor, scaleX: currentScale + 0.3, scaleY: currentScale + 0.3 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(towerGraphics, { tint: 0xFFD700, scaleX: currentScale, scaleY: currentScale }, { duration: 500, easing: tween.easeInOut }); } }); } var target = self.findTarget(); if (target) { self.fire(target); } }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; // Powerful level-based upgrades self.damage += 100; // Massive damage increase self.range += 75; // Significant range boost self.fireRate = Math.max(5, self.fireRate - 2); // Faster firing self.multiShot = Math.min(8, self.multiShot + 1); // More bullets self.criticalChance = Math.min(0.8, self.criticalChance + 0.15); // Higher crit chance self.criticalMultiplier += 0.5; // Higher crit damage self.upgradeCost = Math.floor(self.upgradeCost * 2.2); // Exponential cost increase // Special abilities per level if (self.level === 2) { // Level 2: Area damage self.areaDamage = true; self.areaRadius = 100; } else if (self.level === 3) { // Level 3: Improved area and slowing self.areaRadius = 150; self.slowingShots = true; } else if (self.level === 4) { // Level 4: Chain lightning effect self.chainLightning = true; self.chainCount = 3; } else if (self.level === 5) { // Level 5: Ultimate power - massive improvements self.damage += 200; self.multiShot = 10; self.ultimateMode = true; } // Update range indicator rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; // Define level tints array var levelTints = [0xFFD700, 0xFFA500, 0xFF8C00, 0xFF6347, 0xFF0000]; // Epic upgrade animation with increasing intensity var newScale = 1.2 + (self.level - 1) * 0.1; tween(towerGraphics, { scaleX: newScale + 1.5, scaleY: newScale + 1.5, tint: 0xFFFFFF }, { duration: 600 + self.level * 100, easing: tween.elasticOut, onFinish: function onFinish() { var levelTint = levelTints[self.level - 1]; tween(towerGraphics, { scaleX: newScale, scaleY: newScale, tint: levelTint }, { duration: 400, easing: tween.easeOut }); } }); // Upgrade visual effects based on level if (self.level === 5) { LK.effects.flashScreen(0xFF0000, 1500); // Red flash for ultimate level } else { LK.effects.flashObject(self, levelTints[self.level - 1], 1200); } updateUI(); return true; }; return self; }); var UltimateGodTower = SuperTower.expand(function () { var self = SuperTower.call(this); // Replace graphics with ultimate god tower self.removeChildAt(0); var towerGraphics = self.attachAsset('superTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0xFF0080; // Pink/purple god color self.range = 500; self.damage = Infinity; self.fireRate = 5; self.cost = 90000; // Ultimate tower costs 90000 gold self.level = 1; self.maxLevel = 10; // 10 upgrade levels self.upgradeCost = 10000; self.towerType = 'ultimategod'; self.multiShot = 10; // Fires 10 bullets at once self.piercing = true; self.criticalChance = 1.0; // 100% critical hits self.criticalMultiplier = 10; // Critical hits do 10x damage self.godPower = true; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xFF0080; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Ultimate god multi-shot with divine power for (var shot = 0; shot < self.multiShot; shot++) { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = target; bullet.damage = self.damage * self.criticalMultiplier; // Always critical bullet.isPiercing = self.piercing; bullet.hitTargets = []; bullet.isCritical = true; // God bullets are larger and rainbow colored bullet.children[0].tint = [0xFF0080, 0x80FF00, 0x0080FF, 0xFF8000][shot % 4]; bullet.children[0].scaleX = 3; bullet.children[0].scaleY = 3; bullets.push(bullet); game.addChild(bullet); } // Epic god tower fire animation with divine energy var currentScale = 2.0 + (self.level - 1) * 0.2; tween(towerGraphics, { scaleX: currentScale + 1.5, scaleY: currentScale + 1.5, tint: 0xFFFFFF }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: currentScale, scaleY: currentScale, tint: 0xFF0080 }, { duration: 150, easing: tween.easeIn }); } }); // Divine energy pulse animation tween(rangeIndicator, { alpha: 1.0, scaleX: 2.0, scaleY: 2.0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(rangeIndicator, { alpha: 0.3, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeIn }); } }); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; return self; }); var RocketTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with rocket tower self.removeChildAt(0); var towerGraphics = self.attachAsset('cannonTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0xFF4500; // Orange-red for rocket tower self.range = 300; // Long range rocket launcher self.damage = 500; // High damage rockets self.fireRate = 120; // Slower firing rate for balance self.cost = 0; // Free support tower self.level = 1; self.maxLevel = 5; // Can be upgraded self.upgradeCost = 200; self.towerType = 'rocket'; self.rocketSpeed = 4; // Slower rocket speed // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xFF4500; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Create rocket projectile var rocket = new Bullet(); rocket.x = self.x; rocket.y = self.y; rocket.target = target; rocket.damage = self.damage; rocket.speed = self.rocketSpeed; rocket.isRocket = true; // Make rocket look different rocket.children[0].tint = 0xFF4500; rocket.children[0].scaleX = 2; rocket.children[0].scaleY = 3; // Add rocket trail effect rocket.trailTimer = 0; var originalUpdate = rocket.update; rocket.update = function () { if (originalUpdate) { originalUpdate.call(this); } // Create rocket trail effects rocket.trailTimer++; if (rocket.trailTimer % 3 === 0) { var trail = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); trail.x = rocket.x + (Math.random() - 0.5) * 10; trail.y = rocket.y + (Math.random() - 0.5) * 10; trail.tint = 0xFF4500; game.addChild(trail); tween(trail, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { trail.destroy(); } }); } }; bullets.push(rocket); game.addChild(rocket); // Epic rocket launch animation tween(towerGraphics, { scaleX: 2.0, scaleY: 2.0, tint: 0xFFFFFF }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1.5, scaleY: 1.5, tint: 0xFF4500 }, { duration: 300, easing: tween.easeIn }); } }); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; self.damage += 200; // Significant damage increase self.range += 50; // Range increase self.fireRate = Math.max(80, self.fireRate - 10); // Faster firing self.upgradeCost = Math.floor(self.upgradeCost * 1.8); // Higher upgrade cost rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; // Upgrade visual effects var levelTints = [0xFF4500, 0xFF6500, 0xFF8500, 0xFFA500, 0xFFD700]; towerGraphics.tint = levelTints[self.level - 1]; tween(towerGraphics, { scaleX: 2.0, scaleY: 2.0, tint: 0xFFFFFF }, { duration: 400, easing: tween.bounceOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1.5, scaleY: 1.5, tint: levelTints[self.level - 1] }, { duration: 300, easing: tween.easeOut }); } }); LK.effects.flashObject(self, 0xFFD700, 800); updateUI(); return true; }; return self; }); var QuantumTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with quantum tower self.removeChildAt(0); var towerGraphics = self.attachAsset('lightningTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0x9900FF; // Purple for quantum tower towerGraphics.scaleX = 1.4; towerGraphics.scaleY = 1.4; self.range = 500; // Quantum range self.damage = 25000; // Quantum damage self.fireRate = 100; // Quantum firing rate self.cost = 35000; // Quantum technology cost self.level = 1; self.maxLevel = 7; // Quantum upgrades self.upgradeCost = 18000; self.towerType = 'quantum'; self.quantumField = true; // Creates quantum field self.timeDistortion = true; // Distorts time around enemies self.quantumTeleport = true; // Can teleport enemies self.dimensionalRift = true; // Creates dimensional rifts // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x9900FF; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Quantum attack with multiple effects target.takeDamage(self.damage); // Quantum teleportation - teleport enemy backwards if (self.quantumTeleport && target.pathIndex > 2) { target.pathIndex -= 3; var newPos = enemyPath[target.pathIndex]; target.x = newPos.x; target.y = newPos.y; // Teleport visual effect tween(target, { alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 3 }, { duration: 200, onFinish: function onFinish() { tween(target, { alpha: 1, scaleX: 1, scaleY: 1, rotation: 0 }, { duration: 400, easing: tween.bounceOut }); } }); } // Quantum field effect on nearby enemies for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range * 0.7) { // Time distortion - slow enemies significantly enemy.applySlow(0.2, 300); // Quantum field visual effect tween(enemy, { tint: 0x9900FF, alpha: 0.7 }, { duration: 300, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF, alpha: 1 }, { duration: 500 }); } }); } } // Quantum tower firing animation tween(towerGraphics, { scaleX: 1.8, scaleY: 1.8, tint: 0xFFFFFF, rotation: Math.PI * 0.5 }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1.4, scaleY: 1.4, tint: 0x9900FF, rotation: 0 }, { duration: 600, easing: tween.easeIn }); } }); // Quantum screen distortion effect LK.effects.flashScreen(0x9900FF, 800); self.lastFire = LK.ticks; LK.getSound('lightning').play(); }; // Quantum field continuous effects self.update = function () { // Check if tower is stunned by boss if (self.stunned && LK.ticks >= self.stunEndTime) { self.stunned = false; // Reset visual effects tween(self, { tint: 0xFFFFFF, alpha: 1 }, { duration: 300 }); } if (self.stunned) { return; } // Skip firing when stunned // Dimensional rift creation every 180 ticks if (LK.ticks % 180 === 0) { var riftX = self.x + (Math.random() - 0.5) * 400; var riftY = self.y + (Math.random() - 0.5) * 400; var rift = LK.getAsset('towerRange', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1, x: riftX, y: riftY }); rift.tint = 0x9900FF; rift.alpha = 0.6; game.addChild(rift); // Rift expansion animation tween(rift, { scaleX: 2, scaleY: 2, rotation: Math.PI * 4 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { // Damage enemies caught in rift for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - riftX; var dy = enemy.y - riftY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 100) { enemy.takeDamage(self.damage * 0.5); } } tween(rift, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 400, onFinish: function onFinish() { rift.destroy(); } }); } }); } // Quantum pulsing animation if (LK.ticks % 40 === 0) { var pulseColor = [0x9900FF, 0xBB00FF, 0xDD00FF, 0xFF00FF][Math.floor(LK.ticks / 40) % 4]; towerGraphics.tint = pulseColor; } var target = self.findTarget(); if (target) { self.fire(target); } }; return self; }); var NuclearTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with nuclear tower self.removeChildAt(0); var towerGraphics = self.attachAsset('superTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0xFF0000; // Red for nuclear tower towerGraphics.scaleX = 1.5; towerGraphics.scaleY = 1.5; self.range = 600; // Massive range for nuclear strikes self.damage = 50000; // Nuclear damage self.fireRate = 300; // Slow nuclear charges self.cost = 50000; // Expensive nuclear technology self.level = 1; self.maxLevel = 8; // Nuclear upgrades self.upgradeCost = 25000; self.towerType = 'nuclear'; self.nuclearCharge = 0; self.maxCharge = 180; // 3 seconds to charge self.radiationDamage = 1000; // Continuous radiation damage self.radiationRadius = 400; // Radiation area self.nuclearExplosionRadius = 300; // Explosion radius // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xFF0000; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Nuclear explosion at target location var explosionX = target.x; var explosionY = target.y; // Damage all enemies in massive explosion radius for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - explosionX; var dy = enemy.y - explosionY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.nuclearExplosionRadius) { var explosionDamage = self.damage * (1 - distance / self.nuclearExplosionRadius); enemy.takeDamage(explosionDamage); // Nuclear blast visual effect tween(enemy, { tint: 0xFF0000, scaleX: 1.5, scaleY: 1.5 }, { duration: 200, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 500 }); } }); } } // Nuclear explosion visual effect var explosion = LK.getAsset('superTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1, x: explosionX, y: explosionY }); explosion.tint = 0xFF0000; game.addChild(explosion); tween(explosion, { scaleX: 10, scaleY: 10, alpha: 0, rotation: Math.PI * 4 }, { duration: 1500, easing: tween.easeOut, onFinish: function onFinish() { explosion.destroy(); } }); // Nuclear tower recoil animation tween(towerGraphics, { scaleX: 2.5, scaleY: 2.5, tint: 0xFFFFFF }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1.5, scaleY: 1.5, tint: 0xFF0000 }, { duration: 800, easing: tween.easeIn }); } }); // Massive screen flash for nuclear explosion LK.effects.flashScreen(0xFF0000, 2000); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; // Nuclear radiation continuous damage self.update = function () { // Check if tower is stunned by boss if (self.stunned && LK.ticks >= self.stunEndTime) { self.stunned = false; // Reset visual effects tween(self, { tint: 0xFFFFFF, alpha: 1 }, { duration: 300 }); } if (self.stunned) { return; } // Skip firing when stunned // Continuous radiation damage every 30 ticks if (LK.ticks % 30 === 0) { for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.radiationRadius) { enemy.takeDamage(self.radiationDamage); // Radiation visual effect tween(enemy, { tint: 0x00FF00 }, { duration: 100, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF }, { duration: 300 }); } }); } } } // Nuclear charging animation if (LK.ticks % 10 === 0) { var chargeColor = [0xFF0000, 0xFF4000, 0xFF8000, 0xFFFF00][Math.floor(LK.ticks / 10) % 4]; towerGraphics.tint = chargeColor; } var target = self.findTarget(); if (target) { self.fire(target); } }; return self; }); var MagicTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with magic tower self.removeChildAt(0); var towerGraphics = self.attachAsset('magicTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 130; self.damage = 20; self.fireRate = 50; self.cost = 80; self.upgradeCost = 120; self.towerType = 'magic'; self.slowEffect = 0.5; self.slowDuration = 120; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xe67e22; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Create slowing bullet var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = target; bullet.damage = self.damage; bullet.slowEffect = self.slowEffect; bullet.slowDuration = self.slowDuration; bullet.isMagic = true; bullets.push(bullet); game.addChild(bullet); // Add magical sparkle trail to bullet bullet.sparkleTimer = 0; var originalUpdate = bullet.update; bullet.update = function () { if (originalUpdate) { originalUpdate.call(this); } // Create sparkle effects every few frames bullet.sparkleTimer++; if (bullet.sparkleTimer % 5 === 0) { var sparkle = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3 }); sparkle.x = bullet.x + (Math.random() - 0.5) * 20; sparkle.y = bullet.y + (Math.random() - 0.5) * 20; sparkle.tint = 0xe67e22; game.addChild(sparkle); tween(sparkle, { alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { sparkle.destroy(); } }); } }; self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; self.damage += 12; self.range += 25; self.slowEffect = Math.max(0.2, self.slowEffect - 0.1); self.slowDuration += 30; self.fireRate = Math.max(30, self.fireRate - 10); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0xD35400 : 0xA04000; updateUI(); return true; }; return self; }); var LightningTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with lightning tower self.removeChildAt(0); var towerGraphics = self.attachAsset('lightningTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 140; self.damage = 35; self.fireRate = 80; self.cost = 120; self.upgradeCost = 180; self.towerType = 'lightning'; self.chainCount = 3; self.chainRadius = 100; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xf1c40f; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Lightning chain effect var chainTargets = [target]; var currentTarget = target; // Find chain targets for (var c = 0; c < self.chainCount - 1; c++) { var nextTarget = null; var closestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } if (chainTargets.indexOf(enemy) !== -1) { continue; } var dx = enemy.x - currentTarget.x; var dy = enemy.y - currentTarget.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.chainRadius && distance < closestDistance) { closestDistance = distance; nextTarget = enemy; } } if (nextTarget) { chainTargets.push(nextTarget); currentTarget = nextTarget; } } // Apply damage to all chain targets for (var i = 0; i < chainTargets.length; i++) { var chainTarget = chainTargets[i]; var chainDamage = self.damage * (1 - i * 0.2); // Decreasing damage chainTarget.takeDamage(chainDamage); // Lightning effect animation tween(chainTarget, { tint: 0xf1c40f }, { duration: 100, onFinish: function onFinish() { tween(chainTarget, { tint: 0xFFFFFF }, { duration: 200 }); } }); } // Tower fire animation tween(towerGraphics, { tint: 0xf1c40f, scaleX: 1.3, scaleY: 1.3 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); self.lastFire = LK.ticks; LK.getSound('lightning').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; self.damage += 18; self.range += 20; self.chainCount++; self.chainRadius += 20; self.fireRate = Math.max(50, self.fireRate - 10); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0xd4ac0d : 0xb7950b; updateUI(); return true; }; return self; }); var LightningStormTower = LightningTower.expand(function () { var self = LightningTower.call(this); // Replace graphics with storm lightning tower self.removeChildAt(0); var towerGraphics = self.attachAsset('lightningTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0x9932CC; // Purple for storm tower towerGraphics.scaleX = 1.3; towerGraphics.scaleY = 1.3; self.range = 200; self.damage = 80; self.fireRate = 60; self.cost = 300; self.upgradeCost = 400; self.towerType = 'stormLightning'; self.stormChains = 5; // More chain targets self.stormRadius = 150; self.stormDamage = 1.5; // Damage multiplier // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x9932CC; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Storm lightning with massive chain effect var chainTargets = [target]; var currentTarget = target; // Find more chain targets for storm effect for (var c = 0; c < self.stormChains - 1; c++) { var nextTarget = null; var closestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } if (chainTargets.indexOf(enemy) !== -1) { continue; } var dx = enemy.x - currentTarget.x; var dy = enemy.y - currentTarget.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.stormRadius && distance < closestDistance) { closestDistance = distance; nextTarget = enemy; } } if (nextTarget) { chainTargets.push(nextTarget); currentTarget = nextTarget; } } // Apply storm damage to all chain targets for (var i = 0; i < chainTargets.length; i++) { var chainTarget = chainTargets[i]; var stormDamage = self.damage * self.stormDamage * (1 - i * 0.1); chainTarget.takeDamage(stormDamage); // Epic storm lightning effect tween(chainTarget, { tint: 0x9932CC, scaleX: 1.2, scaleY: 1.2 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(chainTarget, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 300 }); } }); } // Epic tower storm animation tween(towerGraphics, { tint: 0xFFFFFF, scaleX: 1.8, scaleY: 1.8, rotation: Math.PI * 0.5 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { tint: 0x9932CC, scaleX: 1.3, scaleY: 1.3, rotation: 0 }, { duration: 400, easing: tween.bounceOut }); } }); // Storm screen effect LK.effects.flashScreen(0x9932CC, 400); self.lastFire = LK.ticks; LK.getSound('lightning').play(); }; return self; }); var LaserTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with laser tower self.removeChildAt(0); var towerGraphics = self.attachAsset('laserTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 160; self.damage = 8; self.fireRate = 10; self.cost = 110; self.upgradeCost = 160; self.towerType = 'laser'; self.currentTarget = null; self.beamDuration = 0; self.maxBeamDuration = 300; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xe74c3c; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Continuous laser beam if (self.currentTarget === target) { self.beamDuration++; // Increasing damage over time var damageMultiplier = 1 + self.beamDuration / 100; target.takeDamage(self.damage * damageMultiplier); } else { self.currentTarget = target; self.beamDuration = 0; target.takeDamage(self.damage); } // Laser beam visual effect tween(target, { tint: 0xe74c3c }, { duration: 50, onFinish: function onFinish() { tween(target, { tint: 0xFFFFFF }, { duration: 100 }); } }); // Tower rotation towards target var angle = Math.atan2(target.y - self.y, target.x - self.x); tween(towerGraphics, { rotation: angle }, { duration: 100, easing: tween.easeOut }); self.lastFire = LK.ticks; if (self.beamDuration % 30 === 0) { LK.getSound('laser').play(); } }; self.findTarget = function () { // Prefer to keep current target if still in range if (self.currentTarget && !self.currentTarget.isDead && !self.currentTarget.reachedBase) { var dx = self.currentTarget.x - self.x; var dy = self.currentTarget.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range) { return self.currentTarget; } } // Find new target if current is lost self.currentTarget = null; self.beamDuration = 0; var closestEnemy = null; var closestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range && distance < closestDistance) { closestDistance = distance; closestEnemy = enemy; } } return closestEnemy; }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; self.damage += 5; self.range += 25; self.maxBeamDuration += 100; self.fireRate = Math.max(5, self.fireRate - 2); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0xc0392b : 0xa93226; updateUI(); return true; }; return self; }); var PlasmaTower = LaserTower.expand(function () { var self = LaserTower.call(this); // Replace graphics with plasma tower self.removeChildAt(0); var towerGraphics = self.attachAsset('laserTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0x00FF80; // Green plasma color towerGraphics.scaleX = 1.2; towerGraphics.scaleY = 1.2; self.range = 180; self.damage = 12; self.fireRate = 5; // Very fast continuous beam self.cost = 250; self.upgradeCost = 350; self.towerType = 'plasma'; self.energyLevel = 0; self.maxEnergy = 100; self.energyBuildup = 2; self.overchargeMode = false; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x00FF80; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Build up energy over time self.energyLevel = Math.min(self.maxEnergy, self.energyLevel + self.energyBuildup); // Damage increases with energy level var energyMultiplier = 1 + self.energyLevel / self.maxEnergy * 2; var finalDamage = self.damage * energyMultiplier; // Overcharge mode at max energy if (self.energyLevel >= self.maxEnergy && !self.overchargeMode) { self.overchargeMode = true; finalDamage *= 3; // Triple damage in overcharge // Overcharge visual effect tween(towerGraphics, { tint: 0xFFFFFF, scaleX: 1.8, scaleY: 1.8 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { tint: 0x00FF80, scaleX: 1.2, scaleY: 1.2 }, { duration: 800 }); } }); LK.effects.flashScreen(0x00FF80, 600); self.energyLevel = 0; // Reset energy after overcharge } target.takeDamage(finalDamage); // Plasma beam visual effect with energy color var energyColor = self.energyLevel < 50 ? 0x00FF80 : 0x00FFFF; tween(target, { tint: energyColor, scaleX: 1.1, scaleY: 1.1 }, { duration: 60, onFinish: function onFinish() { tween(target, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 120 }); } }); // Energy buildup animation on tower var energyScale = 1.2 + self.energyLevel / self.maxEnergy * 0.3; towerGraphics.scaleX = energyScale; towerGraphics.scaleY = energyScale; self.lastFire = LK.ticks; if (self.energyLevel % 20 === 0) { LK.getSound('laser').play(); } }; return self; }); var InfernalTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with infernal tower self.removeChildAt(0); var towerGraphics = self.attachAsset('cannonTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0x8B0000; // Dark red for infernal tower towerGraphics.scaleX = 1.7; towerGraphics.scaleY = 1.7; self.range = 350; // Infernal range self.damage = 100000; // Infernal damage self.fireRate = 120; // Infernal firing rate self.cost = 120000; // Infernal cost self.level = 1; self.maxLevel = 7; // Infernal upgrades self.upgradeCost = 45000; self.towerType = 'infernal'; self.hellfire = true; // Hellfire attacks self.demonSummon = true; // Summons demons self.infernalBlast = true; // Infernal explosions self.soulBurn = true; // Burns enemy souls // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x8B0000; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Hellfire attack target.takeDamage(self.damage); // Infernal blast at target location var blastX = target.x; var blastY = target.y; var blast = LK.getAsset('superTower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1, x: blastX, y: blastY }); blast.tint = 0x8B0000; game.addChild(blast); // Infernal blast expansion tween(blast, { scaleX: 8, scaleY: 8, alpha: 0.7, rotation: Math.PI * 6 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Damage enemies in blast radius for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - blastX; var dy = enemy.y - blastY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 250) { enemy.takeDamage(self.damage * 0.7); // Soul burn effect tween(enemy, { tint: 0x8B0000, scaleX: 0.8, scaleY: 0.8 }, { duration: 400, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 800 }); } }); } } tween(blast, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 500, onFinish: function onFinish() { blast.destroy(); } }); } }); // Infernal tower firing animation tween(towerGraphics, { scaleX: 2.3, scaleY: 2.3, tint: 0xFF0000, rotation: Math.PI * 0.6 }, { duration: 350, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1.7, scaleY: 1.7, tint: 0x8B0000, rotation: 0 }, { duration: 900, easing: tween.easeIn }); } }); // Infernal screen effect LK.effects.flashScreen(0x8B0000, 900); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; return self; }); var FreezeTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with freeze tower self.removeChildAt(0); var towerGraphics = self.attachAsset('freezeTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 120; self.damage = 10; self.fireRate = 120; self.cost = 90; self.upgradeCost = 140; self.towerType = 'freeze'; self.freezeRadius = 80; self.freezeDuration = 180; self.freezeEffect = 0.1; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x7fb3d3; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Area freeze effect for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.freezeRadius) { enemy.takeDamage(self.damage); enemy.applySlow(self.freezeEffect, self.freezeDuration); // Freeze effect animation tween(enemy, { tint: 0x7fb3d3 }, { duration: 200, onFinish: function onFinish() { tween(enemy, { tint: 0x3498db }, { duration: self.freezeDuration * 16 }); } }); } } // Tower fire animation with pulse effect tween(towerGraphics, { scaleX: 1.4, scaleY: 1.4, tint: 0x3498db }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 300, easing: tween.bounceOut }); } }); self.lastFire = LK.ticks; LK.getSound('freeze').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; self.damage += 8; self.range += 15; self.freezeRadius += 20; self.freezeDuration += 60; self.freezeEffect = Math.max(0.05, self.freezeEffect - 0.025); self.fireRate = Math.max(80, self.fireRate - 15); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0x5dade2 : 0x3498db; updateUI(); return true; }; return self; }); var ChronoTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with chrono tower self.removeChildAt(0); var towerGraphics = self.attachAsset('freezeTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0x4169E1; // Blue for chrono tower towerGraphics.scaleX = 1.5; towerGraphics.scaleY = 1.5; self.range = 300; // Chrono range self.damage = 80000; // Chrono damage self.fireRate = 90; // Chrono firing rate self.cost = 80000; // Chrono cost self.level = 1; self.maxLevel = 6; // Chrono upgrades self.upgradeCost = 35000; self.towerType = 'chrono'; self.timeFreeze = true; // Freezes time self.timeReverse = true; // Reverses enemy movement self.temporalShield = true; // Temporal protection self.chronoBlast = true; // Chrono explosions // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x4169E1; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Chrono attack target.takeDamage(self.damage); // Time freeze effect on all enemies in range for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range) { // Time freeze - slow enemies dramatically enemy.applySlow(0.05, 300); // Time reverse effect if (enemy.pathIndex > 0) { enemy.pathIndex--; var newPos = enemyPath[enemy.pathIndex]; tween(enemy, { x: newPos.x, y: newPos.y, tint: 0x4169E1, alpha: 0.6 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF, alpha: 1 }, { duration: 600 }); } }); } } } // Chrono tower firing animation tween(towerGraphics, { scaleX: 2.0, scaleY: 2.0, tint: 0x00BFFF, rotation: Math.PI * 0.4 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1.5, scaleY: 1.5, tint: 0x4169E1, rotation: 0 }, { duration: 700, easing: tween.easeIn }); } }); // Chrono screen effect LK.effects.flashScreen(0x4169E1, 700); self.lastFire = LK.ticks; LK.getSound('freeze').play(); }; return self; }); var CelestialTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with celestial tower self.removeChildAt(0); var towerGraphics = self.attachAsset('superTower', { anchorX: 0.5, anchorY: 0.5 }); towerGraphics.tint = 0xFFFFFF; // White for celestial tower towerGraphics.scaleX = 1.8; towerGraphics.scaleY = 1.8; self.range = 600; // Celestial range self.damage = 150000; // Celestial damage self.fireRate = 180; // Celestial firing rate self.cost = 150000; // Celestial cost self.level = 1; self.maxLevel = 8; // Celestial upgrades self.upgradeCost = 60000; self.towerType = 'celestial'; self.divineBeam = true; // Divine beam attacks self.healingAura = true; // Heals other towers self.angelicWings = true; // Angelic protection self.holyJudgment = true; // Divine judgment // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0xFFFFFF; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Divine beam attack target.takeDamage(self.damage); // Holy judgment on nearby enemies for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.isDead || enemy.reachedBase) { continue; } var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range * 0.8) { enemy.takeDamage(self.damage * 0.6); // Divine judgment visual effect tween(enemy, { tint: 0xFFFFFF, scaleX: 1.3, scaleY: 1.3, alpha: 0.7 }, { duration: 300, onFinish: function onFinish() { tween(enemy, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 800 }); } }); } } // Celestial tower firing animation tween(towerGraphics, { scaleX: 2.5, scaleY: 2.5, tint: 0xFFD700, rotation: Math.PI * 0.2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(towerGraphics, { scaleX: 1.8, scaleY: 1.8, tint: 0xFFFFFF, rotation: 0 }, { duration: 1200, easing: tween.easeIn }); } }); // Divine screen effect LK.effects.flashScreen(0xFFFFFF, 1000); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; return self; }); var CannonTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with cannon tower self.removeChildAt(0); var towerGraphics = self.attachAsset('cannonTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 120; self.damage = 40; self.fireRate = 90; self.cost = 100; self.upgradeCost = 150; self.towerType = 'cannon'; self.splashRadius = 80; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x34495e; self.fire = function (target) { if (LK.ticks - self.lastFire < self.fireRate) { return; } // Create splash damage bullet var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.target = target; bullet.damage = self.damage; bullet.splashRadius = self.splashRadius; bullet.isSplash = true; bullets.push(bullet); game.addChild(bullet); self.lastFire = LK.ticks; LK.getSound('shoot').play(); }; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; self.damage += 20; self.range += 20; self.splashRadius += 20; self.fireRate = Math.max(60, self.fireRate - 15); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0x2C3E50 : 0x1B2631; updateUI(); return true; }; return self; }); var ArcherTower = Tower.expand(function () { var self = Tower.call(this); // Replace graphics with archer tower self.removeChildAt(0); var towerGraphics = self.attachAsset('archerTower', { anchorX: 0.5, anchorY: 0.5 }); self.range = 200; self.damage = 15; self.fireRate = 40; self.cost = 75; self.upgradeCost = 100; self.towerType = 'archer'; // Update range indicator var rangeIndicator = self.children[self.children.length - 1]; rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; rangeIndicator.tint = 0x8e44ad; self.upgrade = function () { if (self.level >= self.maxLevel || currency < self.upgradeCost) { return false; } currency -= self.upgradeCost; self.level++; self.damage += 10; self.range += 30; self.fireRate = Math.max(25, self.fireRate - 5); self.upgradeCost = Math.floor(self.upgradeCost * 1.5); rangeIndicator.width = self.range * 2; rangeIndicator.height = self.range * 2; towerGraphics.tint = self.level === 2 ? 0x7D3C98 : 0x6C3483; updateUI(); return true; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var gridSize = 100; var mapWidth = 20; var mapHeight = 25; var currency = 390; var diamonds = 0; var lives = 20; var wave = 1; var enemiesInWave = 5; var enemiesSpawned = 0; var waveActive = false; var gameOver = false; var towers = []; var enemies = []; var bullets = []; var grid = []; var enemyPath = []; var selectedTower = null; var placingTower = false; var selectedTowerType = 'basic'; var draggingTower = null; var dragOffset = { x: 0, y: 0 }; var originalTowerPosition = { x: 0, y: 0 }; var originalGridPosition = { x: 0, y: 0 }; var rocketDelivered = false; var superTowerUnlocked = true; var gameMode = 'normal'; // Always normal mode // Achievements system var achievements = [{ id: 'first_victory', name: 'First Victory', description: 'Complete your first tower defense game', icon: 'š', unlocked: false }, { id: 'wave_master', name: 'Wave Master', description: 'Survive 20 waves in a single game', icon: 'š', unlocked: false }, { id: 'tower_commander', name: 'Tower Commander', description: 'Build 10 towers in a single game', icon: 'š°', unlocked: false }, { id: 'currency_collector', name: 'Currency Collector', description: 'Accumulate 5000 gold in a single game', icon: 'š°', unlocked: false }, { id: 'diamond_hunter', name: 'Diamond Hunter', description: 'Collect 50 diamonds in a single game', icon: 'š', unlocked: false }, { id: 'boss_slayer', name: 'Boss Slayer', description: 'Defeat 5 bosses in a single game', icon: 'āļø', unlocked: false }, { id: 'perfect_defense', name: 'Perfect Defense', description: 'Complete the game without losing a single life', icon: 'š”ļø', unlocked: false }, { id: 'ultimate_warrior', name: 'Ultimate Warrior', description: 'Defeat the final boss and complete all 31 waves', icon: 'š', unlocked: false }]; // Load saved achievements var savedAchievements = storage.achievements || {}; for (var i = 0; i < achievements.length; i++) { if (savedAchievements[achievements[i].id]) { achievements[i].unlocked = true; } } // Achievement tracking variables var gameStats = { towersBuilt: 0, bossesDefeated: 0, maxCurrency: 0, maxDiamonds: 0, livesLost: 0 }; function checkAchievements() { var newUnlocks = []; // Check each achievement for (var i = 0; i < achievements.length; i++) { var achievement = achievements[i]; if (!achievement.unlocked) { var shouldUnlock = false; switch (achievement.id) { case 'first_victory': shouldUnlock = wave > 31; break; case 'wave_master': shouldUnlock = wave >= 20; break; case 'tower_commander': shouldUnlock = gameStats.towersBuilt >= 10; break; case 'currency_collector': shouldUnlock = gameStats.maxCurrency >= 5000; break; case 'diamond_hunter': shouldUnlock = gameStats.maxDiamonds >= 50; break; case 'boss_slayer': shouldUnlock = gameStats.bossesDefeated >= 5; break; case 'perfect_defense': shouldUnlock = wave > 31 && gameStats.livesLost === 0; break; case 'ultimate_warrior': shouldUnlock = wave > 31; break; } if (shouldUnlock) { achievement.unlocked = true; newUnlocks.push(achievement); // Save achievement to storage if (!savedAchievements[achievement.id]) { savedAchievements[achievement.id] = true; storage.achievements = savedAchievements; } } } } return newUnlocks; } function showAchievementUnlock(achievement) { // Create achievement notification var achievementNotification = new Text2(achievement.icon + ' ' + achievement.name, { size: 60, fill: 0xFFD700 }); achievementNotification.anchor.set(0.5, 0.5); achievementNotification.x = 2048 / 2; achievementNotification.y = 200; achievementNotification.alpha = 0; achievementNotification.scaleX = 0.1; achievementNotification.scaleY = 0.1; game.addChild(achievementNotification); // Create description text var descriptionText = new Text2(achievement.description, { size: 35, fill: 0xFFFFFF }); descriptionText.anchor.set(0.5, 0.5); descriptionText.x = 2048 / 2; descriptionText.y = 270; descriptionText.alpha = 0; descriptionText.scaleX = 0.1; descriptionText.scaleY = 0.1; game.addChild(descriptionText); // Achievement unlock animation tween(achievementNotification, { alpha: 1, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.bounceOut, onFinish: function onFinish() { tween(achievementNotification, { scaleX: 1, scaleY: 1 }, { duration: 400, easing: tween.easeOut }); } }); tween(descriptionText, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { // Hold for 3 seconds then fade out LK.setTimeout(function () { tween(achievementNotification, { alpha: 0, y: 150 }, { duration: 800, onFinish: function onFinish() { achievementNotification.destroy(); } }); tween(descriptionText, { alpha: 0, y: 220 }, { duration: 800, onFinish: function onFinish() { descriptionText.destroy(); } }); }, 3000); } }); // Achievement unlock screen effect LK.effects.flashScreen(0xFFD700, 1000); } function showCompletionAchievements() { // Check for newly unlocked achievements var newUnlocks = checkAchievements(); if (newUnlocks.length > 0) { // Show each achievement with a delay for (var i = 0; i < newUnlocks.length; i++) { (function (achievement, delay) { LK.setTimeout(function () { showAchievementUnlock(achievement); }, delay * 1500); })(newUnlocks[i], i); } } // Show all unlocked achievements summary after individual notifications LK.setTimeout(function () { showAchievementsSummary(); }, newUnlocks.length * 1500 + 2000); } function showAchievementsSummary() { // Create achievements summary background var summaryBg = LK.getAsset('grassTile', { anchorX: 0.5, anchorY: 0.5, scaleX: 18, scaleY: 20, x: 2048 / 2, y: 2732 / 2 }); summaryBg.tint = 0x000000; summaryBg.alpha = 0; game.addChild(summaryBg); // Fade in background tween(summaryBg, { alpha: 0.8 }, { duration: 500 }); // Create title var titleText = new Text2('š ACHIEVEMENTS UNLOCKED! š', { size: 80, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 400; titleText.alpha = 0; game.addChild(titleText); tween(titleText, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 600, easing: tween.bounceOut }); // Show unlocked achievements list var unlockedCount = 0; var yOffset = 600; for (var i = 0; i < achievements.length; i++) { if (achievements[i].unlocked) { unlockedCount++; var achievementText = new Text2(achievements[i].icon + ' ' + achievements[i].name, { size: 45, fill: 0x00FF00 }); achievementText.anchor.set(0.5, 0.5); achievementText.x = 2048 / 2; achievementText.y = yOffset; achievementText.alpha = 0; game.addChild(achievementText); // Stagger the appearance of each achievement (function (text, delay) { LK.setTimeout(function () { tween(text, { alpha: 1, scaleX: 1.1, scaleY: 1.1 }, { duration: 400, easing: tween.easeOut }); }, delay * 200); })(achievementText, i); yOffset += 120; } } // Show completion percentage var completionText = new Text2('Completion: ' + unlockedCount + '/' + achievements.length + ' (' + Math.round(unlockedCount / achievements.length * 100) + '%)', { size: 50, fill: 0xFFFFFF }); completionText.anchor.set(0.5, 0.5); completionText.x = 2048 / 2; completionText.y = yOffset + 100; completionText.alpha = 0; game.addChild(completionText); LK.setTimeout(function () { tween(completionText, { alpha: 1, scaleX: 1.3, scaleY: 1.3 }, { duration: 600, easing: tween.bounceOut }); }, achievements.length * 200 + 500); } // Create UI elements (initially hidden) var currencyTxt = new Text2('Gold: 390', { size: 35, fill: 0xFFD700 }); currencyTxt.anchor.set(0, 0); currencyTxt.x = 120; currencyTxt.y = 20; currencyTxt.visible = true; LK.gui.topLeft.addChild(currencyTxt); var diamondsTxt = new Text2('Diamonds: 0', { size: 35, fill: 0x00FFFF }); diamondsTxt.anchor.set(0, 0); diamondsTxt.x = 120; diamondsTxt.y = 60; diamondsTxt.visible = true; LK.gui.topLeft.addChild(diamondsTxt); var livesTxt = new Text2('Lives: 20', { size: 35, fill: 0xFF0000 }); livesTxt.anchor.set(0.5, 0); livesTxt.visible = true; LK.gui.top.addChild(livesTxt); var waveTxt = new Text2('Wave: 1', { size: 35, fill: 0xFFFFFF }); waveTxt.anchor.set(1, 0); waveTxt.visible = true; LK.gui.topRight.addChild(waveTxt); var nextWaveTimer = 0; var waveBreakDuration = 180; // 3 seconds at 60fps var buyTowerBtn = new Text2('Basic Tower (20g)', { size: 28, fill: 0x4A90E2 }); buyTowerBtn.anchor.set(0, 1); buyTowerBtn.x = 20; buyTowerBtn.y = -20; buyTowerBtn.visible = true; LK.gui.bottomLeft.addChild(buyTowerBtn); var buyArcherBtn = new Text2('Archer Tower (30g)', { size: 28, fill: 0x8e44ad }); buyArcherBtn.anchor.set(0, 1); buyArcherBtn.x = 20; buyArcherBtn.y = -50; buyArcherBtn.visible = true; LK.gui.bottomLeft.addChild(buyArcherBtn); var buyCannonBtn = new Text2('Cannon Tower (40g)', { size: 28, fill: 0x34495e }); buyCannonBtn.anchor.set(0, 1); buyCannonBtn.x = 20; buyCannonBtn.y = -80; buyCannonBtn.visible = true; LK.gui.bottomLeft.addChild(buyCannonBtn); var buyMagicBtn = new Text2('Magic Tower (35g)', { size: 28, fill: 0xe67e22 }); buyMagicBtn.anchor.set(0, 1); buyMagicBtn.x = 20; buyMagicBtn.y = -110; buyMagicBtn.visible = true; LK.gui.bottomLeft.addChild(buyMagicBtn); var buyLightningBtn = new Text2('Lightning Tower (50g)', { size: 28, fill: 0xf1c40f }); buyLightningBtn.anchor.set(0, 1); buyLightningBtn.x = 20; buyLightningBtn.y = -140; buyLightningBtn.visible = true; LK.gui.bottomLeft.addChild(buyLightningBtn); var buyFreezeBtn = new Text2('Freeze Tower (40g)', { size: 28, fill: 0x7fb3d3 }); buyFreezeBtn.anchor.set(0, 1); buyFreezeBtn.x = 20; buyFreezeBtn.y = -170; buyFreezeBtn.visible = true; LK.gui.bottomLeft.addChild(buyFreezeBtn); var buyLaserBtn = new Text2('Laser Tower (45g)', { size: 28, fill: 0xe74c3c }); buyLaserBtn.anchor.set(0, 1); buyLaserBtn.x = 20; buyLaserBtn.y = -200; buyLaserBtn.visible = true; LK.gui.bottomLeft.addChild(buyLaserBtn); var buySuperBtn = new Text2('SUPER TOWER (4000g)', { size: 28, fill: 0xFFD700 }); buySuperBtn.anchor.set(0, 1); buySuperBtn.x = 20; buySuperBtn.y = -230; buySuperBtn.visible = true; LK.gui.bottomLeft.addChild(buySuperBtn); var buyUltimateBtn = new Text2('ULTIMATE GOD TOWER (90000g)', { size: 28, fill: 0xFF0080 }); buyUltimateBtn.anchor.set(0, 1); buyUltimateBtn.x = 20; buyUltimateBtn.y = -260; buyUltimateBtn.visible = true; LK.gui.bottomLeft.addChild(buyUltimateBtn); var buyStormBtn = new Text2('Lightning Storm Tower (80g)', { size: 28, fill: 0x9932CC }); buyStormBtn.anchor.set(0, 1); buyStormBtn.x = 20; buyStormBtn.y = -290; buyStormBtn.visible = true; LK.gui.bottomLeft.addChild(buyStormBtn); var buyPlasmaBtn = new Text2('Plasma Tower (70g)', { size: 28, fill: 0x00FF80 }); buyPlasmaBtn.anchor.set(0, 1); buyPlasmaBtn.x = 20; buyPlasmaBtn.y = -320; buyPlasmaBtn.visible = true; LK.gui.bottomLeft.addChild(buyPlasmaBtn); var buyNuclearBtn = new Text2('Nuclear Tower (1000g)', { size: 28, fill: 0xFF0000 }); buyNuclearBtn.anchor.set(0, 1); buyNuclearBtn.x = 20; buyNuclearBtn.y = -350; buyNuclearBtn.visible = true; LK.gui.bottomLeft.addChild(buyNuclearBtn); var buyQuantumBtn = new Text2('Quantum Tower (800g)', { size: 28, fill: 0x9900FF }); buyQuantumBtn.anchor.set(0, 1); buyQuantumBtn.x = 20; buyQuantumBtn.y = -380; buyQuantumBtn.visible = true; LK.gui.bottomLeft.addChild(buyQuantumBtn); var buyTitanBtn = new Text2('TITAN TOWER (2500g)', { size: 28, fill: 0x800080 }); buyTitanBtn.anchor.set(0, 1); buyTitanBtn.x = 20; buyTitanBtn.y = -410; buyTitanBtn.visible = true; LK.gui.bottomLeft.addChild(buyTitanBtn); var buyVoidBtn = new Text2('VOID TOWER (1500g)', { size: 28, fill: 0x000080 }); buyVoidBtn.anchor.set(0, 1); buyVoidBtn.x = 20; buyVoidBtn.y = -440; buyVoidBtn.visible = true; LK.gui.bottomLeft.addChild(buyVoidBtn); var buyCelestialBtn = new Text2('CELESTIAL TOWER (3000g)', { size: 28, fill: 0xFFFFFF }); buyCelestialBtn.anchor.set(0, 1); buyCelestialBtn.x = 20; buyCelestialBtn.y = -470; buyCelestialBtn.visible = true; LK.gui.bottomLeft.addChild(buyCelestialBtn); var buyInfernalBtn = new Text2('INFERNAL TOWER (2200g)', { size: 28, fill: 0x8B0000 }); buyInfernalBtn.anchor.set(0, 1); buyInfernalBtn.x = 20; buyInfernalBtn.y = -500; buyInfernalBtn.visible = true; LK.gui.bottomLeft.addChild(buyInfernalBtn); var buyChronoBtn = new Text2('CHRONO TOWER (1800g)', { size: 28, fill: 0x4169E1 }); buyChronoBtn.anchor.set(0, 1); buyChronoBtn.x = 20; buyChronoBtn.y = -530; buyChronoBtn.visible = true; LK.gui.bottomLeft.addChild(buyChronoBtn); var upgradeTowerBtn = new Text2('Upgrade Tower', { size: 32, fill: 0xFF6B35 }); upgradeTowerBtn.anchor.set(0, 1); upgradeTowerBtn.x = 20; upgradeTowerBtn.y = -560; upgradeTowerBtn.visible = false; LK.gui.bottomLeft.addChild(upgradeTowerBtn); var enhanceAllBtn = new Text2('Enhance All Towers (10ā¦)', { size: 28, fill: 0x00FFFF }); enhanceAllBtn.anchor.set(1, 1); enhanceAllBtn.x = -20; enhanceAllBtn.y = -20; enhanceAllBtn.visible = true; LK.gui.bottomRight.addChild(enhanceAllBtn); var superDamageBtn = new Text2('Super Damage (15ā¦)', { size: 28, fill: 0xFF6B35 }); superDamageBtn.anchor.set(1, 1); superDamageBtn.x = -20; superDamageBtn.y = -50; superDamageBtn.visible = true; LK.gui.bottomRight.addChild(superDamageBtn); var rapidFireBtn = new Text2('Rapid Fire (12ā¦)', { size: 28, fill: 0xFFFF00 }); rapidFireBtn.anchor.set(1, 1); rapidFireBtn.x = -20; rapidFireBtn.y = -80; rapidFireBtn.visible = true; LK.gui.bottomRight.addChild(rapidFireBtn); var skipWaveBtn = new Text2('Skip Wave (5ā¦)', { size: 28, fill: 0xFF00FF }); skipWaveBtn.anchor.set(1, 1); skipWaveBtn.x = -20; skipWaveBtn.y = -110; skipWaveBtn.visible = true; LK.gui.bottomRight.addChild(skipWaveBtn); // Initialize game directly in normal mode initializeGrid(); createPath(); drawMap(); drawBase(); // Give free support tower at start with 567 damage var supportTower = new Tower(); supportTower.x = 5 * gridSize + gridSize / 2; supportTower.y = 5 * gridSize + gridSize / 2; supportTower.damage = 567; supportTower.range = 200; supportTower.fireRate = 30; towers.push(supportTower); game.addChild(supportTower); grid[5][5].occupied = true; // Add entrance animation for support tower supportTower.alpha = 0; supportTower.scaleX = 0.1; supportTower.scaleY = 0.1; tween(supportTower, { alpha: 1, scaleX: 1.2, scaleY: 1.2, tint: 0x00FF00 }, { duration: 800, easing: tween.bounceOut, onFinish: function onFinish() { tween(supportTower, { scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 400 }); } }); updateUI(); function updateUI() { currencyTxt.setText('Gold: ' + currency); diamondsTxt.setText('Diamonds: ' + diamonds); livesTxt.setText('Lives: ' + lives); waveTxt.setText('Wave: ' + wave); // Track max currency and diamonds for achievements gameStats.maxCurrency = Math.max(gameStats.maxCurrency, currency); gameStats.maxDiamonds = Math.max(gameStats.maxDiamonds, diamonds); if (currency >= 20) { buyTowerBtn.tint = 0x4A90E2; } else { buyTowerBtn.tint = 0x666666; } if (currency >= 30) { buyArcherBtn.tint = 0x8e44ad; } else { buyArcherBtn.tint = 0x666666; } if (currency >= 40) { buyCannonBtn.tint = 0x34495e; } else { buyCannonBtn.tint = 0x666666; } if (currency >= 35) { buyMagicBtn.tint = 0xe67e22; } else { buyMagicBtn.tint = 0x666666; } if (currency >= 50) { buyLightningBtn.tint = 0xf1c40f; } else { buyLightningBtn.tint = 0x666666; } if (currency >= 40) { buyFreezeBtn.tint = 0x7fb3d3; } else { buyFreezeBtn.tint = 0x666666; } if (currency >= 45) { buyLaserBtn.tint = 0xe74c3c; } else { buyLaserBtn.tint = 0x666666; } // Update upgrade button visibility and state if (selectedTower && selectedTower.level < selectedTower.maxLevel) { upgradeTowerBtn.visible = true; upgradeTowerBtn.setText('Upgrade Lv' + selectedTower.level + ' (' + selectedTower.upgradeCost + 'g)'); if (currency >= selectedTower.upgradeCost) { upgradeTowerBtn.tint = 0xFF6B35; } else { upgradeTowerBtn.tint = 0x666666; } } else { upgradeTowerBtn.visible = false; } // Update diamond enhancement buttons if (diamonds >= 10) { enhanceAllBtn.tint = 0x00FFFF; } else { enhanceAllBtn.tint = 0x666666; } if (diamonds >= 15) { superDamageBtn.tint = 0xFF6B35; } else { superDamageBtn.tint = 0x666666; } if (diamonds >= 12) { rapidFireBtn.tint = 0xFFFF00; } else { rapidFireBtn.tint = 0x666666; } // Update skip wave button if (diamonds >= 5 && waveActive) { skipWaveBtn.tint = 0xFF00FF; } else { skipWaveBtn.tint = 0x666666; } // Update super tower button visibility buySuperBtn.visible = true; buySuperBtn.setText('SUPER TOWER (500g)'); if (currency >= 500) { buySuperBtn.tint = 0xFFD700; } else { buySuperBtn.tint = 0x666666; } // Update ultimate god tower button buyUltimateBtn.setText('ULTIMATE GOD TOWER (2000g)'); if (currency >= 2000) { buyUltimateBtn.tint = 0xFF0080; } else { buyUltimateBtn.tint = 0x666666; } // Update storm tower button if (currency >= 80) { buyStormBtn.tint = 0x9932CC; } else { buyStormBtn.tint = 0x666666; } // Update plasma tower button if (currency >= 70) { buyPlasmaBtn.tint = 0x00FF80; } else { buyPlasmaBtn.tint = 0x666666; } // Update nuclear tower button if (currency >= 1000) { buyNuclearBtn.tint = 0xFF0000; } else { buyNuclearBtn.tint = 0x666666; } // Update quantum tower button if (currency >= 800) { buyQuantumBtn.tint = 0x9900FF; } else { buyQuantumBtn.tint = 0x666666; } // Update titan tower button if (currency >= 2500) { buyTitanBtn.tint = 0x800080; } else { buyTitanBtn.tint = 0x666666; } // Update void tower button if (currency >= 1500) { buyVoidBtn.tint = 0x000080; } else { buyVoidBtn.tint = 0x666666; } // Update celestial tower button if (currency >= 3000) { buyCelestialBtn.tint = 0xFFFFFF; } else { buyCelestialBtn.tint = 0x666666; } // Update infernal tower button if (currency >= 2200) { buyInfernalBtn.tint = 0x8B0000; } else { buyInfernalBtn.tint = 0x666666; } // Update chrono tower button if (currency >= 1800) { buyChronoBtn.tint = 0x4169E1; } else { buyChronoBtn.tint = 0x666666; } } function hideAllRanges() { for (var i = 0; i < towers.length; i++) { towers[i].hideRange(); } } function initializeGrid() { for (var x = 0; x < mapWidth; x++) { grid[x] = []; for (var y = 0; y < mapHeight; y++) { grid[x][y] = { x: x * gridSize + gridSize / 2, y: y * gridSize + gridSize / 2, occupied: false, isPath: false }; } } } function createPath() { enemyPath = []; var pathCoords = [{ x: 0, y: 12 }, { x: 1, y: 12 }, { x: 2, y: 12 }, { x: 3, y: 12 }, { x: 4, y: 12 }, { x: 5, y: 12 }, { x: 6, y: 12 }, { x: 7, y: 12 }, { x: 8, y: 12 }, { x: 8, y: 11 }, { x: 8, y: 10 }, { x: 8, y: 9 }, { x: 8, y: 8 }, { x: 9, y: 8 }, { x: 10, y: 8 }, { x: 11, y: 8 }, { x: 12, y: 8 }, { x: 12, y: 9 }, { x: 12, y: 10 }, { x: 12, y: 11 }, { x: 12, y: 12 }, { x: 13, y: 12 }, { x: 14, y: 12 }, { x: 15, y: 12 }, { x: 16, y: 12 }, { x: 17, y: 12 }, { x: 18, y: 12 }, { x: 19, y: 12 }]; for (var i = 0; i < pathCoords.length; i++) { var coord = pathCoords[i]; if (coord.x < mapWidth && coord.y < mapHeight) { grid[coord.x][coord.y].isPath = true; // Also mark adjacent tiles as path to make path wider if (coord.y > 0) { grid[coord.x][coord.y - 1].isPath = true; } if (coord.y < mapHeight - 1) { grid[coord.x][coord.y + 1].isPath = true; } enemyPath.push({ x: coord.x * gridSize + gridSize / 2, y: coord.y * gridSize + gridSize / 2 }); } } } function drawMap() { for (var x = 0; x < mapWidth; x++) { for (var y = 0; y < mapHeight; y++) { var tile; if (grid[x][y].isPath) { tile = LK.getAsset('pathTile', { x: x * gridSize, y: y * gridSize }); } else { tile = LK.getAsset('grassTile', { x: x * gridSize, y: y * gridSize }); } game.addChild(tile); } } } function drawBase() { var base = LK.getAsset('base', { anchorX: 0.5, anchorY: 0.5, x: (mapWidth - 1) * gridSize + gridSize / 2, y: 12 * gridSize + gridSize / 2 }); game.addChild(base); } function spawnEnemy() { if (enemiesSpawned >= enemiesInWave) { return; } var enemy; // Spawn ultra boss on wave 21 and give 4000 gold at wave start if (wave === 21 && enemiesSpawned === 0) { // Give 4000 gold when wave 21 starts currency += 4000; updateUI(); } // Wave 10: Give ultra tower with 90999999999999 damage if (wave === 10 && enemiesSpawned === 0) { // Create ultra support tower with massive damage var ultraTower = new Tower(); ultraTower.x = 7 * gridSize + gridSize / 2; // Place at grid position (7,7) ultraTower.y = 7 * gridSize + gridSize / 2; ultraTower.damage = 90999999999999; // Set damage to 90999999999999 ultraTower.range = 400; // Massive range for maximum support ultraTower.fireRate = 5; // Ultra fast firing towers.push(ultraTower); game.addChild(ultraTower); grid[7][7].occupied = true; // Mark grid position as occupied // Add epic entrance animation for ultra tower ultraTower.alpha = 0; ultraTower.scaleX = 0.1; ultraTower.scaleY = 0.1; tween(ultraTower, { alpha: 1, scaleX: 2.0, scaleY: 2.0, tint: 0xFFD700 }, { duration: 1500, easing: tween.elasticOut, onFinish: function onFinish() { tween(ultraTower, { scaleX: 1.5, scaleY: 1.5, tint: 0xFF0080 }, { duration: 800 }); } }); // Show ultra support message var ultraMsg = new Text2('ULTRA SUPPORT TOWER DEPLOYED!', { size: 60, fill: 0xFFD700 }); ultraMsg.anchor.set(0.5, 0.5); ultraMsg.x = 2048 / 2; ultraMsg.y = 400; ultraMsg.alpha = 0; game.addChild(ultraMsg); tween(ultraMsg, { alpha: 1, scaleX: 2.5, scaleY: 2.5 }, { duration: 1800, easing: tween.bounceOut, onFinish: function onFinish() { tween(ultraMsg, { alpha: 0 }, { duration: 2500, onFinish: function onFinish() { ultraMsg.destroy(); } }); } }); // Epic screen flash for ultra support arrival LK.effects.flashScreen(0xFFD700, 2000); updateUI(); } // Wave 12: Gold rush bonus if (wave === 12 && enemiesSpawned === 0) { currency += 800; diamonds += 8; var goldMsg = new Text2('GOLD RUSH BONUS!', { size: 50, fill: 0xFFD700 }); goldMsg.anchor.set(0.5, 0.5); goldMsg.x = 2048 / 2; goldMsg.y = 350; goldMsg.alpha = 0; game.addChild(goldMsg); tween(goldMsg, { alpha: 1, scaleX: 2.0, scaleY: 2.0 }, { duration: 1200, easing: tween.bounceOut, onFinish: function onFinish() { tween(goldMsg, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { goldMsg.destroy(); } }); } }); LK.effects.flashScreen(0xFFD700, 1000); updateUI(); } // Wave 14: Lightning storm enhancement if (wave === 14 && enemiesSpawned === 0) { for (var i = 0; i < towers.length; i++) { var tower = towers[i]; if (tower.towerType === 'lightning' || tower.towerType === 'stormLightning') { tower.damage *= 3; tower.chainCount += 2; tower.chainRadius += 50; tween(tower, { tint: 0xFFFF00, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.bounceOut, onFinish: function onFinish() { tween(tower, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 600 }); } }); } } var stormMsg = new Text2('LIGHTNING TOWERS SUPERCHARGED!', { size: 100, fill: 0xFFFF00 }); stormMsg.anchor.set(0.5, 0.5); stormMsg.x = 2048 / 2; stormMsg.y = 400; stormMsg.alpha = 0; game.addChild(stormMsg); tween(stormMsg, { alpha: 1, scaleX: 1.8, scaleY: 1.8 }, { duration: 1000, easing: tween.bounceOut, onFinish: function onFinish() { tween(stormMsg, { alpha: 0 }, { duration: 1800, onFinish: function onFinish() { stormMsg.destroy(); } }); } }); LK.effects.flashScreen(0xFFFF00, 1200); updateUI(); } // Wave 16: Freeze enhancement if (wave === 16 && enemiesSpawned === 0) { for (var i = 0; i < towers.length; i++) { var tower = towers[i]; if (tower.towerType === 'freeze') { tower.damage *= 2.5; tower.freezeRadius += 60; tower.freezeDuration += 120; tower.freezeEffect = Math.max(0.01, tower.freezeEffect - 0.05); tween(tower, { tint: 0x00FFFF, scaleX: 1.4, scaleY: 1.4 }, { duration: 700, easing: tween.bounceOut, onFinish: function onFinish() { tween(tower, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 500 }); } }); } } var freezeMsg = new Text2('FREEZE TOWERS ENHANCED!', { size: 100, fill: 0x00FFFF }); freezeMsg.anchor.set(0.5, 0.5); freezeMsg.x = 2048 / 2; freezeMsg.y = 450; freezeMsg.alpha = 0; game.addChild(freezeMsg); tween(freezeMsg, { alpha: 1, scaleX: 1.7, scaleY: 1.7 }, { duration: 1000, easing: tween.bounceOut, onFinish: function onFinish() { tween(freezeMsg, { alpha: 0 }, { duration: 1600, onFinish: function onFinish() { freezeMsg.destroy(); } }); } }); LK.effects.flashScreen(0x00FFFF, 1000); updateUI(); } // Wave 18: Massive currency boost if (wave === 18 && enemiesSpawned === 0) { currency += 2000; diamonds += 12; var massiveMsg = new Text2('MASSIVE RESOURCE BOOST!', { size: 130, fill: 0x00FF00 }); massiveMsg.anchor.set(0.5, 0.5); massiveMsg.x = 2048 / 2; massiveMsg.y = 500; massiveMsg.alpha = 0; game.addChild(massiveMsg); tween(massiveMsg, { alpha: 1, scaleX: 2.2, scaleY: 2.2, rotation: Math.PI * 0.1 }, { duration: 1300, easing: tween.elasticOut, onFinish: function onFinish() { tween(massiveMsg, { alpha: 0 }, { duration: 2200, onFinish: function onFinish() { massiveMsg.destroy(); } }); } }); LK.effects.flashScreen(0x00FF00, 1500); updateUI(); } // Give free super rocket tower at wave 20 if (wave === 20 && enemiesSpawned === 0) { // Create super rocket tower with high damage var rocketTower = new RocketTower(); rocketTower.x = 3 * gridSize + gridSize / 2; // Place at grid position (3,3) rocketTower.y = 3 * gridSize + gridSize / 2; towers.push(rocketTower); game.addChild(rocketTower); grid[3][3].occupied = true; // Mark grid position as occupied // Add epic entrance animation for rocket tower rocketTower.alpha = 0; rocketTower.scaleX = 0.1; rocketTower.scaleY = 0.1; tween(rocketTower, { alpha: 1, scaleX: 1.8, scaleY: 1.8, tint: 0xFFFFFF }, { duration: 1200, easing: tween.bounceOut, onFinish: function onFinish() { tween(rocketTower, { scaleX: 1.5, scaleY: 1.5, tint: 0xFF4500 }, { duration: 600 }); } }); // Show rocket support message var rocketMsg = new Text2('SUPER ROCKET LAUNCHER DEPLOYED!', { size: 120, fill: 0xFF4500 }); rocketMsg.anchor.set(0.5, 0.5); rocketMsg.x = 2048 / 2; rocketMsg.y = 500; rocketMsg.alpha = 0; game.addChild(rocketMsg); tween(rocketMsg, { alpha: 1, scaleX: 2.0, scaleY: 2.0 }, { duration: 1500, easing: tween.bounceOut, onFinish: function onFinish() { tween(rocketMsg, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { rocketMsg.destroy(); } }); } }); // Epic screen flash for rocket support arrival LK.effects.flashScreen(0xFF4500, 1800); updateUI(); } // Wave 22: Archer enhancement if (wave === 22 && enemiesSpawned === 0) { for (var i = 0; i < towers.length; i++) { var tower = towers[i]; if (tower.towerType === 'archer') { tower.damage *= 4; tower.range += 100; tower.fireRate = Math.max(10, tower.fireRate - 20); tween(tower, { tint: 0xFF00FF, scaleX: 1.6, scaleY: 1.6 }, { duration: 900, easing: tween.bounceOut, onFinish: function onFinish() { tween(tower, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 700 }); } }); } } var archerMsg = new Text2('ARCHER TOWERS PERFECTED!', { size: 110, fill: 0xFF00FF }); archerMsg.anchor.set(0.5, 0.5); archerMsg.x = 2048 / 2; archerMsg.y = 420; archerMsg.alpha = 0; game.addChild(archerMsg); tween(archerMsg, { alpha: 1, scaleX: 1.9, scaleY: 1.9 }, { duration: 1100, easing: tween.bounceOut, onFinish: function onFinish() { tween(archerMsg, { alpha: 0 }, { duration: 1900, onFinish: function onFinish() { archerMsg.destroy(); } }); } }); LK.effects.flashScreen(0xFF00FF, 1100); updateUI(); } // Wave 24: Laser enhancement if (wave === 24 && enemiesSpawned === 0) { for (var i = 0; i < towers.length; i++) { var tower = towers[i]; if (tower.towerType === 'laser' || tower.towerType === 'plasma') { tower.damage *= 5; tower.range += 80; tower.fireRate = Math.max(3, tower.fireRate - 5); if (tower.towerType === 'plasma') { tower.maxEnergy += 50; tower.energyBuildup += 3; } tween(tower, { tint: 0xFF0000, scaleX: 1.7, scaleY: 1.7 }, { duration: 1000, easing: tween.bounceOut, onFinish: function onFinish() { tween(tower, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 800 }); } }); } } var laserMsg = new Text2('LASER SYSTEMS MAXIMIZED!', { size: 115, fill: 0xFF0000 }); laserMsg.anchor.set(0.5, 0.5); laserMsg.x = 2048 / 2; laserMsg.y = 470; laserMsg.alpha = 0; game.addChild(laserMsg); tween(laserMsg, { alpha: 1, scaleX: 2.0, scaleY: 2.0, rotation: Math.PI * 0.05 }, { duration: 1200, easing: tween.elasticOut, onFinish: function onFinish() { tween(laserMsg, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { laserMsg.destroy(); } }); } }); LK.effects.flashScreen(0xFF0000, 1300); updateUI(); } // Wave 26: Cannon enhancement if (wave === 26 && enemiesSpawned === 0) { for (var i = 0; i < towers.length; i++) { var tower = towers[i]; if (tower.towerType === 'cannon') { tower.damage *= 6; tower.splashRadius += 80; tower.fireRate = Math.max(30, tower.fireRate - 30); tween(tower, { tint: 0xFFFF00, scaleX: 1.8, scaleY: 1.8 }, { duration: 1100, easing: tween.bounceOut, onFinish: function onFinish() { tween(tower, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 900 }); } }); } } var cannonMsg = new Text2('CANNON TOWERS EXPLOSIVE!', { size: 115, fill: 0xFFFF00 }); cannonMsg.anchor.set(0.5, 0.5); cannonMsg.x = 2048 / 2; cannonMsg.y = 380; cannonMsg.alpha = 0; game.addChild(cannonMsg); tween(cannonMsg, { alpha: 1, scaleX: 2.1, scaleY: 2.1 }, { duration: 1150, easing: tween.bounceOut, onFinish: function onFinish() { tween(cannonMsg, { alpha: 0 }, { duration: 2100, onFinish: function onFinish() { cannonMsg.destroy(); } }); } }); LK.effects.flashScreen(0xFFFF00, 1400); updateUI(); } // Wave 28: Magic enhancement if (wave === 28 && enemiesSpawned === 0) { for (var i = 0; i < towers.length; i++) { var tower = towers[i]; if (tower.towerType === 'magic') { tower.damage *= 7; tower.range += 100; tower.slowEffect = Math.max(0.01, tower.slowEffect - 0.1); tower.slowDuration += 180; tween(tower, { tint: 0x9932CC, scaleX: 1.9, scaleY: 1.9 }, { duration: 1200, easing: tween.bounceOut, onFinish: function onFinish() { tween(tower, { tint: 0xFFFFFF, scaleX: 1, scaleY: 1 }, { duration: 1000 }); } }); } } var magicMsg = new Text2('MAGIC TOWERS ASCENDED!', { size: 120, fill: 0x9932CC }); magicMsg.anchor.set(0.5, 0.5); magicMsg.x = 2048 / 2; magicMsg.y = 430; magicMsg.alpha = 0; game.addChild(magicMsg); tween(magicMsg, { alpha: 1, scaleX: 2.3, scaleY: 2.3, rotation: Math.PI * 0.08 }, { duration: 1300, easing: tween.elasticOut, onFinish: function onFinish() { tween(magicMsg, { alpha: 0 }, { duration: 2300, onFinish: function onFinish() { magicMsg.destroy(); } }); } }); LK.effects.flashScreen(0x9932CC, 1500); updateUI(); } // Wave 30: Give 90000 gold when wave 30 starts if (wave === 30 && enemiesSpawned === 0) { // Give 90000 gold when wave 30 starts currency += 90000; diamonds += 20; // Add ultimate preparation message var ultimateMsg = new Text2('ULTIMATE PREPARATION COMPLETE!', { size: 140, fill: 0xFFD700 }); ultimateMsg.anchor.set(0.5, 0.5); ultimateMsg.x = 2048 / 2; ultimateMsg.y = 500; ultimateMsg.alpha = 0; game.addChild(ultimateMsg); tween(ultimateMsg, { alpha: 1, scaleX: 2.5, scaleY: 2.5, rotation: Math.PI * 0.1 }, { duration: 1500, easing: tween.elasticOut, onFinish: function onFinish() { tween(ultimateMsg, { alpha: 0 }, { duration: 2500, onFinish: function onFinish() { ultimateMsg.destroy(); } }); } }); LK.effects.flashScreen(0xFFD700, 2000); updateUI(); } // Epic power surge at wave 25 if (wave === 25 && enemiesSpawned === 0) { // Power surge all towers for (var i = 0; i < towers.length; i++) { var tower = towers[i]; tower.damage = Math.floor(tower.damage * 3); tower.range = Math.floor(tower.range * 1.5); tower.fireRate = Math.max(5, Math.floor(tower.fireRate * 0.3)); // Epic power surge animation tween(tower, { scaleX: 2.0, scaleY: 2.0, tint: 0xFFD700, rotation: Math.PI * 2 }, { duration: 1200, easing: tween.elasticOut, onFinish: function onFinish() { tween(tower, { scaleX: 1.5, scaleY: 1.5, tint: 0xFFFFFF, rotation: 0 }, { duration: 800 }); } }); } // Epic power surge notification var surgeMsg = new Text2('POWER SURGE ACTIVATED!', { size: 180, fill: 0xFFD700 }); surgeMsg.anchor.set(0.5, 0.5); surgeMsg.x = 2048 / 2; surgeMsg.y = 600; surgeMsg.alpha = 0; game.addChild(surgeMsg); tween(surgeMsg, { alpha: 1, scaleX: 3.0, scaleY: 3.0, rotation: Math.PI * 0.3 }, { duration: 2000, easing: tween.elasticOut, onFinish: function onFinish() { tween(surgeMsg, { alpha: 0 }, { duration: 1500, onFinish: function onFinish() { surgeMsg.destroy(); } }); } }); LK.effects.flashScreen(0xFFD700, 2500); } if (wave === 21 && enemiesSpawned === enemiesInWave - 1) { // Create ultra boss taunt animation first var tauntText = new Text2('YOU WILL BE DEFEATED!', { size: 180, fill: 0xFF0000 }); tauntText.anchor.set(0.5, 0.5); tauntText.x = 2048 / 2; tauntText.y = 2732 / 2; tauntText.alpha = 0; tauntText.scaleX = 0.1; tauntText.scaleY = 0.1; game.addChild(tauntText); // Dramatic taunt entrance animation tween(tauntText, { alpha: 1, scaleX: 2.5, scaleY: 2.5, rotation: Math.PI * 0.2 }, { duration: 1500, easing: tween.elasticOut, onFinish: function onFinish() { // Hold the taunt for dramatic effect LK.setTimeout(function () { tween(tauntText, { alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 }, { duration: 1000, easing: tween.easeIn, onFinish: function onFinish() { tauntText.destroy(); // Now spawn the ultra boss after taunt animation enemy = new UltraBoss(); // Epic ultra boss entrance with massive effects LK.effects.flashScreen(0x4B0082, 2000); // Create epic announcement var announcement = new Text2('ULTRA BOSS UNLEASHED!', { size: 150, fill: 0x4B0082 }); announcement.anchor.set(0.5, 0.5); announcement.x = 2048 / 2; announcement.y = 300; announcement.alpha = 0; game.addChild(announcement); tween(announcement, { alpha: 1, scaleX: 2, scaleY: 2, rotation: Math.PI * 0.1 }, { duration: 1000, easing: tween.elasticOut, onFinish: function onFinish() { tween(announcement, { alpha: 0, y: 100 }, { duration: 1500, onFinish: function onFinish() { announcement.destroy(); } }); } }); // Continue with enemy placement enemy.x = gridSize / 2; enemy.y = 12 * gridSize + gridSize / 2; // Scale stats with wave enemy.health = enemy.maxHealth + (wave - 1) * 20; enemy.maxHealth = enemy.health; enemy.speed = enemy.originalSpeed + (wave - 1) * 0.2; enemy.originalSpeed = enemy.speed; enemy.reward = enemy.reward + (wave - 1) * 2; // Spawn animation enemy.alpha = 0; enemy.scaleX = 0.1; enemy.scaleY = 0.1; enemies.push(enemy); game.addChild(enemy); // Enhanced enemy entrance animation with rotation var spawnAnimationType = Math.floor(Math.random() * 3); if (spawnAnimationType === 0) { // Bounce entrance tween(enemy, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.bounceOut }); } else if (spawnAnimationType === 1) { // Spiral entrance enemy.rotation = Math.PI * 4; tween(enemy, { alpha: 1, scaleX: 1, scaleY: 1, rotation: 0 }, { duration: 600, easing: tween.easeOut }); } else { // Elastic entrance tween(enemy, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 700, easing: tween.elasticOut }); } // Special boss spawn effects if (enemy.isBoss || enemy.isUltraBoss) { // Screen flash and shake for boss spawn LK.effects.flashScreen(0x8B0000, 800); // Create warning text var warningText = new Text2(enemy.isUltraBoss ? 'ULTRA BOSS INCOMING!' : 'BOSS INCOMING!', { size: 50, fill: 0xFF0000 }); warningText.anchor.set(0.5, 0.5); warningText.x = 2048 / 2; warningText.y = 300; warningText.alpha = 0; game.addChild(warningText); tween(warningText, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.bounceOut, onFinish: function onFinish() { tween(warningText, { alpha: 0, y: 200 }, { duration: 1000, onFinish: function onFinish() { warningText.destroy(); } }); } }); } enemiesSpawned++; return; } }); }, 2000); // Wait 2 seconds before removing taunt } }); return; // Exit function to prevent normal enemy spawning } else if (wave > 10 && wave % 5 === 0 && enemiesSpawned === enemiesInWave - 1) { enemy = new UltraBoss(); } else if (wave % 10 === 0 && enemiesSpawned === enemiesInWave - 1) { // Spawn regular boss on wave 10 and every 10 waves enemy = new Boss(); } else { var enemyType = Math.floor(Math.random() * 4); if (enemyType === 0) { enemy = new Enemy(); } else if (enemyType === 1) { enemy = new FastWarrior(); } else if (enemyType === 2) { enemy = new HeavyWarrior(); } else { enemy = new MagicWarrior(); } } enemy.x = gridSize / 2; enemy.y = 12 * gridSize + gridSize / 2; // Scale stats with wave enemy.health = enemy.maxHealth + (wave - 1) * 20; enemy.maxHealth = enemy.health; enemy.speed = enemy.originalSpeed + (wave - 1) * 0.2; enemy.originalSpeed = enemy.speed; enemy.reward = enemy.reward + (wave - 1) * 2; // Spawn animation enemy.alpha = 0; enemy.scaleX = 0.1; enemy.scaleY = 0.1; enemies.push(enemy); game.addChild(enemy); // Enhanced enemy entrance animation with rotation var spawnAnimationType = Math.floor(Math.random() * 3); if (spawnAnimationType === 0) { // Bounce entrance tween(enemy, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.bounceOut }); } else if (spawnAnimationType === 1) { // Spiral entrance enemy.rotation = Math.PI * 4; tween(enemy, { alpha: 1, scaleX: 1, scaleY: 1, rotation: 0 }, { duration: 600, easing: tween.easeOut }); } else { // Elastic entrance tween(enemy, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 700, easing: tween.elasticOut }); } // Special boss spawn effects if (enemy.isBoss || enemy.isUltraBoss) { // Screen flash and shake for boss spawn LK.effects.flashScreen(0x8B0000, 800); // Create warning text var warningText = new Text2(enemy.isUltraBoss ? 'ULTRA BOSS INCOMING!' : 'BOSS INCOMING!', { size: 100, fill: 0xFF0000 }); warningText.anchor.set(0.5, 0.5); warningText.x = 2048 / 2; warningText.y = 300; warningText.alpha = 0; game.addChild(warningText); tween(warningText, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.bounceOut, onFinish: function onFinish() { tween(warningText, { alpha: 0, y: 200 }, { duration: 1000, onFinish: function onFinish() { warningText.destroy(); } }); } }); } enemiesSpawned++; } function getGridPosition(x, y) { var gridX = Math.floor(x / gridSize); var gridY = Math.floor(y / gridSize); if (gridX >= 0 && gridX < mapWidth && gridY >= 0 && gridY < mapHeight) { return { x: gridX, y: gridY }; } return null; } function canPlaceTower(gridX, gridY) { return !grid[gridX][gridY].occupied && !grid[gridX][gridY].isPath; } function placeTower(gridX, gridY) { var tower; var cost; if (selectedTowerType === 'basic') { cost = 20; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new Tower(); } else if (selectedTowerType === 'archer') { cost = 30; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new ArcherTower(); } else if (selectedTowerType === 'cannon') { cost = 40; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new CannonTower(); } else if (selectedTowerType === 'magic') { cost = 35; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new MagicTower(); } else if (selectedTowerType === 'lightning') { cost = 50; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new LightningTower(); } else if (selectedTowerType === 'freeze') { cost = 40; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new FreezeTower(); } else if (selectedTowerType === 'laser') { cost = 45; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new LaserTower(); } else if (selectedTowerType === 'super') { cost = 500; // Super tower costs 500 gold if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new SuperTower(); } else if (selectedTowerType === 'ultimategod') { cost = 2000; // Ultimate god tower costs 2000 gold if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new UltimateGodTower(); } else if (selectedTowerType === 'stormLightning') { cost = 80; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new LightningStormTower(); } else if (selectedTowerType === 'plasma') { cost = 70; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new PlasmaTower(); } else if (selectedTowerType === 'nuclear') { cost = 1000; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new NuclearTower(); } else if (selectedTowerType === 'quantum') { cost = 800; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new QuantumTower(); } else if (selectedTowerType === 'titan') { cost = 2500; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new TitanTower(); } else if (selectedTowerType === 'void') { cost = 1500; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new VoidTower(); } else if (selectedTowerType === 'celestial') { cost = 3000; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new CelestialTower(); } else if (selectedTowerType === 'infernal') { cost = 2200; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new InfernalTower(); } else if (selectedTowerType === 'chrono') { cost = 1800; if (!canPlaceTower(gridX, gridY) || currency < cost) { return false; } tower = new ChronoTower(); } tower.x = gridX * gridSize + gridSize / 2; tower.y = gridY * gridSize + gridSize / 2; // Placement animation tower.alpha = 0; tower.scaleX = 0.1; tower.scaleY = 0.1; towers.push(tower); game.addChild(tower); // Animate tower placement tween(tower, { alpha: 1, scaleX: 1.2, scaleY: 1.2 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(tower, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeIn }); } }); grid[gridX][gridY].occupied = true; currency -= cost; placingTower = false; // Track tower building for achievements gameStats.towersBuilt++; updateUI(); return true; } function startWave() { if (waveActive) { return; } waveActive = true; enemiesSpawned = 0; enemiesInWave = 5 + wave * 2; // Special rocket animation for wave 20 if (wave === 20 && !rocketDelivered) { deliverSuperTowerRocket(); rocketDelivered = true; } // Enhanced wave start effects with screen shake LK.effects.flashScreen(0x00FF00, 300); // Screen shake animation var originalX = game.x; var originalY = game.y; var shakeIntensity = 10; var shakeDuration = 500; var shakeInterval = 50; for (var i = 0; i < shakeDuration / shakeInterval; i++) { LK.setTimeout(function () { var shakeX = (Math.random() - 0.5) * shakeIntensity; var shakeY = (Math.random() - 0.5) * shakeIntensity; tween(game, { x: originalX + shakeX, y: originalY + shakeY }, { duration: shakeInterval / 2, onFinish: function onFinish() { tween(game, { x: originalX, y: originalY }, { duration: shakeInterval / 2 }); } }); }, i * shakeInterval); } } function deliverSuperTowerRocket() { // Create rocket var rocket = LK.getAsset('tower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 2, x: 2048 / 2, y: -100 }); rocket.tint = 0xFF4500; rocket.rotation = Math.PI; game.addChild(rocket); // Rocket descent animation tween(rocket, { y: 2732 / 2, rotation: 0 }, { duration: 2000, easing: tween.easeIn, onFinish: function onFinish() { // Explosion effect LK.effects.flashScreen(0xFFD700, 1000); // Remove rocket and show super tower unlock message rocket.destroy(); superTowerUnlocked = true; // Create super tower unlock notification var unlockMsg = new Text2('SUPER TOWER UNLOCKED!', { size: 120, fill: 0xFFD700 }); unlockMsg.anchor.set(0.5, 0.5); unlockMsg.x = 2048 / 2; unlockMsg.y = 2732 / 2; unlockMsg.alpha = 0; game.addChild(unlockMsg); // Animate unlock message tween(unlockMsg, { alpha: 1, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.bounceOut, onFinish: function onFinish() { tween(unlockMsg, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { unlockMsg.destroy(); } }); } }); updateUI(); } }); } function checkWaveComplete() { if (!waveActive) { return; } var allEnemiesGone = true; for (var i = 0; i < enemies.length; i++) { if (!enemies[i].isDead && !enemies[i].reachedBase) { allEnemiesGone = false; break; } } if (enemiesSpawned >= enemiesInWave && allEnemiesGone) { waveActive = false; wave++; currency += 25; diamonds += 5; // Award 5 diamonds per wave nextWaveTimer = waveBreakDuration; // Start 3-second countdown updateUI(); // Clean up dead enemies for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].isDead || enemies[i].reachedBase) { enemies[i].destroy(); enemies.splice(i, 1); } } } } updateUI(); // Event handlers buyTowerBtn.down = function () { if (currency >= 20) { selectedTowerType = 'basic'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyArcherBtn.down = function () { if (currency >= 75) { selectedTowerType = 'archer'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyCannonBtn.down = function () { if (currency >= 100) { selectedTowerType = 'cannon'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyMagicBtn.down = function () { if (currency >= 80) { selectedTowerType = 'magic'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyLightningBtn.down = function () { if (currency >= 120) { selectedTowerType = 'lightning'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyFreezeBtn.down = function () { if (currency >= 90) { selectedTowerType = 'freeze'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyLaserBtn.down = function () { if (currency >= 110) { selectedTowerType = 'laser'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; upgradeTowerBtn.down = function () { if (selectedTower && selectedTower.upgrade()) { updateUI(); } }; enhanceAllBtn.down = function () { if (diamonds >= 10) { diamonds -= 10; for (var i = 0; i < towers.length; i++) { var tower = towers[i]; tower.damage = Math.floor(tower.damage * 1.5); tower.range = Math.floor(tower.range * 1.2); // Visual enhancement effect tween(tower, { scaleX: 1.3, scaleY: 1.3, tint: 0x00FFFF }, { duration: 400, easing: tween.bounceOut, onFinish: function onFinish() { tween(tower, { scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 300 }); } }); } LK.effects.flashScreen(0x00FFFF, 500); updateUI(); } }; superDamageBtn.down = function () { if (diamonds >= 15) { diamonds -= 15; for (var i = 0; i < towers.length; i++) { var tower = towers[i]; tower.damage = Math.floor(tower.damage * 2.5); // Super damage visual effect tween(tower, { scaleX: 1.5, scaleY: 1.5, tint: 0xFF6B35 }, { duration: 500, easing: tween.elasticOut, onFinish: function onFinish() { tween(tower, { scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 400 }); } }); } LK.effects.flashScreen(0xFF6B35, 800); updateUI(); } }; rapidFireBtn.down = function () { if (diamonds >= 12) { diamonds -= 12; for (var i = 0; i < towers.length; i++) { var tower = towers[i]; tower.fireRate = Math.max(10, Math.floor(tower.fireRate * 0.5)); // Rapid fire visual effect tween(tower, { tint: 0xFFFF00 }, { duration: 200, onFinish: function onFinish() { tween(tower, { tint: 0xFFFFFF }, { duration: 200 }); } }); } LK.effects.flashScreen(0xFFFF00, 600); updateUI(); } }; buySuperBtn.down = function () { if (currency >= 500) { selectedTowerType = 'super'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyUltimateBtn.down = function () { if (currency >= 2000) { selectedTowerType = 'ultimategod'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; skipWaveBtn.down = function () { if (diamonds >= 5 && waveActive) { diamonds -= 5; // Clear all enemies from the field for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; // Teleport animation for skip effect tween(enemy, { alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: Math.PI * 2 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { if (enemy.parent) { enemy.destroy(); } } }); enemies.splice(i, 1); } // Complete the wave immediately waveActive = false; wave++; currency += 25; diamonds += 5; // Award 5 diamonds per wave nextWaveTimer = waveBreakDuration; // Start 3-second countdown // Skip wave visual effect LK.effects.flashScreen(0xFF00FF, 500); updateUI(); } }; buyStormBtn.down = function () { if (currency >= 300) { selectedTowerType = 'stormLightning'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyPlasmaBtn.down = function () { if (currency >= 250) { selectedTowerType = 'plasma'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyNuclearBtn.down = function () { if (currency >= 50000) { selectedTowerType = 'nuclear'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyQuantumBtn.down = function () { if (currency >= 35000) { selectedTowerType = 'quantum'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyTitanBtn.down = function () { if (currency >= 100000) { selectedTowerType = 'titan'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyVoidBtn.down = function () { if (currency >= 75000) { selectedTowerType = 'void'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyCelestialBtn.down = function () { if (currency >= 150000) { selectedTowerType = 'celestial'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyInfernalBtn.down = function () { if (currency >= 120000) { selectedTowerType = 'infernal'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; buyChronoBtn.down = function () { if (currency >= 80000) { selectedTowerType = 'chrono'; placingTower = true; selectedTower = null; hideAllRanges(); updateUI(); } }; game.move = function (x, y, obj) { if (draggingTower) { draggingTower.x = x - dragOffset.x; draggingTower.y = y - dragOffset.y; // Visual feedback for valid/invalid placement var gridPos = getGridPosition(draggingTower.x, draggingTower.y); if (gridPos && gridPos.x >= 0 && gridPos.x < mapWidth && gridPos.y >= 0 && gridPos.y < mapHeight && grid[gridPos.x] && grid[gridPos.x][gridPos.y] && !grid[gridPos.x][gridPos.y].occupied && !grid[gridPos.x][gridPos.y].isPath) { draggingTower.tint = 0x00FF00; // Green for valid } else { draggingTower.tint = 0xFF0000; // Red for invalid } } }; game.down = function (x, y, obj) { if (placingTower) { var gridPos = getGridPosition(x, y); if (gridPos) { placeTower(gridPos.x, gridPos.y); } } else { // Clear tower selection if clicking on empty space var gridPos = getGridPosition(x, y); if (gridPos && !grid[gridPos.x][gridPos.y].occupied) { selectedTower = null; hideAllRanges(); updateUI(); } } }; game.up = function (x, y, obj) { if (draggingTower) { var gridPos = getGridPosition(draggingTower.x, draggingTower.y); var canPlace = gridPos && canPlaceTower(gridPos.x, gridPos.y); if (canPlace) { // Successfully place tower at new position draggingTower.x = gridPos.x * gridSize + gridSize / 2; draggingTower.y = gridPos.y * gridSize + gridSize / 2; grid[gridPos.x][gridPos.y].occupied = true; // Smooth placement animation tween(draggingTower, { alpha: 1, scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 300, easing: tween.bounceOut }); } else { // Return to original position tween(draggingTower, { x: originalTowerPosition.x, y: originalTowerPosition.y, alpha: 1, scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 400, easing: tween.elasticOut }); // Restore original grid position grid[originalGridPosition.x][originalGridPosition.y].occupied = true; } draggingTower = null; } }; // Main game loop game.update = function () { if (lives <= 0 && !gameOver) { gameOver = true; LK.showGameOver(); return; } if (wave > 31) { // Show achievements before win screen showCompletionAchievements(); // Delay showing win screen to allow achievements to display LK.setTimeout(function () { LK.showYouWin(); }, 8000); return; } // Handle automatic wave progression if (!waveActive && nextWaveTimer > 0) { nextWaveTimer--; if (nextWaveTimer <= 0) { startWave(); } } // Start first wave immediately if (wave === 1 && !waveActive && nextWaveTimer === 0) { startWave(); } // Spawn enemies during wave with decreasing interval var spawnInterval = Math.max(45, 90 - wave * 2); if (waveActive && LK.ticks % spawnInterval === 0) { spawnEnemy(); } // Clean up bullets that hit targets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.hasHit || !bullet.target || bullet.target.isDead) { bullet.destroy(); bullets.splice(i, 1); } } // Add breathing animation to towers when not firing for (var t = 0; t < towers.length; t++) { var tower = towers[t]; if (LK.ticks - tower.lastFire > 120) { // If haven't fired for 2 seconds if (!tower.isBreathing) { tower.isBreathing = true; var breatheScale = 1 + Math.sin(LK.ticks * 0.05) * 0.05; tween(tower, { scaleX: breatheScale, scaleY: breatheScale }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tower.isBreathing = false; } }); } } else { tower.isBreathing = false; } } checkWaveComplete(); // Check for achievement unlocks during gameplay var newUnlocks = checkAchievements(); if (newUnlocks.length > 0) { // Show achievement notifications during gameplay (except completion ones) for (var i = 0; i < newUnlocks.length; i++) { if (newUnlocks[i].id !== 'first_victory' && newUnlocks[i].id !== 'perfect_defense' && newUnlocks[i].id !== 'ultimate_warrior') { showAchievementUnlock(newUnlocks[i]); } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 25;
self.target = null;
self.hasHit = false;
self.update = function () {
if (!self.target || self.hasHit) {
return;
}
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 20) {
if (self.isPiercing && self.hitTargets.indexOf(self.target) === -1) {
// Piercing bullet hits target but continues
self.target.takeDamage(self.damage);
self.hitTargets.push(self.target);
// Find next target
var nextTarget = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase || self.hitTargets.indexOf(enemy) !== -1) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < closestDistance && dist <= 200) {
closestDistance = dist;
nextTarget = enemy;
}
}
if (nextTarget) {
self.target = nextTarget;
} else {
self.hasHit = true;
}
} else if (self.isSplash) {
// Splash damage to all enemies in radius
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var splashDx = enemy.x - self.x;
var splashDy = enemy.y - self.y;
var splashDistance = Math.sqrt(splashDx * splashDx + splashDy * splashDy);
if (splashDistance <= self.splashRadius) {
enemy.takeDamage(self.damage);
}
}
self.hasHit = true;
} else if (self.isMagic) {
// Magic damage with slow effect
self.target.takeDamage(self.damage);
self.target.applySlow(self.slowEffect, self.slowDuration);
self.hasHit = true;
} else {
// Regular damage
self.target.takeDamage(self.damage);
self.hasHit = true;
}
LK.getSound('enemyHit').play();
if (self.hasHit) {
return;
}
}
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 100;
self.health = self.maxHealth;
self.speed = 2;
self.reward = 10;
self.pathIndex = 0;
self.isDead = false;
self.reachedBase = false;
self.originalSpeed = self.speed;
self.slowEndTime = 0;
self.isSlowed = false;
// Add health bar
var healthBarBg = LK.getAsset('pathTile', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.1
});
healthBarBg.y = -40;
healthBarBg.tint = 0x333333;
self.addChild(healthBarBg);
var healthBar = LK.getAsset('grassTile', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.1
});
healthBar.y = -40;
healthBar.tint = 0x00FF00;
self.addChild(healthBar);
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBar.scaleX = 0.6 * healthPercent;
if (healthPercent > 0.6) {
healthBar.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
healthBar.tint = 0xFFFF00; // Yellow
} else {
healthBar.tint = 0xFF0000; // Red
}
};
self.applySlow = function (slowFactor, duration) {
self.speed = self.originalSpeed * slowFactor;
self.slowEndTime = LK.ticks + duration;
self.isSlowed = true;
enemyGraphics.tint = 0x3498db; // Blue tint for slowed enemies
};
self.takeDamage = function (damage) {
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0 && !self.isDead) {
self.isDead = true;
LK.getSound('enemyDeath').play();
currency += self.reward;
// Track boss defeats for achievements
if (self.isBoss || self.isUltraBoss) {
gameStats.bossesDefeated++;
}
// Create floating currency text animation
var currencyFloat = new Text2('+' + self.reward + 'g', {
size: 25,
fill: 0xFFD700
});
currencyFloat.anchor.set(0.5, 0.5);
currencyFloat.x = self.x;
currencyFloat.y = self.y;
currencyFloat.alpha = 1;
game.addChild(currencyFloat);
tween(currencyFloat, {
y: self.y - 100,
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
currencyFloat.destroy();
}
});
updateUI();
// Enhanced death animation with explosion effect
tween(enemyGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF6B6B
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2
}, {
duration: 400,
easing: tween.easeIn
});
}
});
}
};
self.update = function () {
if (self.isDead || self.reachedBase) {
return;
}
// Check if slow effect should end
if (self.isSlowed && LK.ticks >= self.slowEndTime) {
self.speed = self.originalSpeed;
self.isSlowed = false;
enemyGraphics.tint = 0xFFFFFF; // Reset tint
}
if (self.pathIndex < enemyPath.length) {
var target = enemyPath[self.pathIndex];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 20) {
self.pathIndex++;
if (self.pathIndex >= enemyPath.length) {
self.reachedBase = true;
lives--;
gameStats.livesLost++;
updateUI();
return;
}
}
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
// Add subtle wobble animation while moving
if (LK.ticks % 60 === 0) {
tween(enemyGraphics, {
rotation: Math.sin(LK.ticks * 0.1) * 0.2
}, {
duration: 500,
easing: tween.easeInOut
});
}
}
};
return self;
});
var UltraBoss = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace graphics with ultra boss enemy
self.removeChildAt(0);
var enemyGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3.5,
scaleY: 3.5
});
enemyGraphics.tint = 0x4B0082; // Dark violet for ultra boss
self.maxHealth = 8000; // Much more health for wave 21
self.health = self.maxHealth;
self.speed = 1.2; // Faster movement
self.originalSpeed = self.speed;
self.reward = 500; // Higher reward
self.enemyType = 'ultraboss';
self.isUltraBoss = true;
self.lastSpecialAttack = 0;
self.specialAttackCooldown = 120; // Faster special attacks
self.healAmount = 300; // More healing
self.shieldActive = false;
self.shieldEndTime = 0;
self.teleportCooldown = 0;
self.pulseTimer = 0; // For continuous pulsing animation
// Ultra boss shield ability - damage immunity
self.activateShield = function () {
self.shieldActive = true;
self.shieldEndTime = LK.ticks + 180; // 3 seconds
// Shield visual effect
tween(enemyGraphics, {
tint: 0x00FFFF,
scaleX: 3,
scaleY: 3
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
enemyGraphics.tint = 0x87CEEB; // Light blue while shielded
}
});
LK.effects.flashObject(self, 0x00FFFF, 500);
};
// Ultra boss teleport ability
self.teleportToPath = function () {
var randomIndex = Math.min(self.pathIndex + 3, enemyPath.length - 1);
var targetPos = enemyPath[randomIndex];
// Teleport effect
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 200,
onFinish: function onFinish() {
self.x = targetPos.x;
self.y = targetPos.y;
self.pathIndex = randomIndex;
tween(self, {
alpha: 1,
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
LK.effects.flashScreen(0x9932CC, 300);
};
// Ultra boss healing ability
self.healSelf = function () {
self.health = Math.min(self.maxHealth, self.health + self.healAmount);
self.updateHealthBar();
// Healing visual effect
tween(enemyGraphics, {
tint: 0x00FF00,
scaleX: 3.5,
scaleY: 3.5
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0x4B0082,
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 400,
easing: tween.easeIn
});
}
});
LK.effects.flashObject(self, 0x00FF00, 700);
};
// Ultra boss area damage ability
self.areaDamage = function () {
// Damage all nearby towers
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var dx = tower.x - self.x;
var dy = tower.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 250) {
// Disable tower temporarily and reduce level
tower.stunned = true;
tower.stunEndTime = LK.ticks + 300; // 5 seconds
if (tower.level > 1) {
tower.level--;
tower.damage = Math.max(10, tower.damage - 15);
}
// Visual effect
tween(tower, {
tint: 0x8B0000,
alpha: 0.3
}, {
duration: 300
});
}
}
// Ultra boss area damage visual effect
LK.effects.flashScreen(0x8B0000, 800);
};
self.takeDamage = function (damage, damageType) {
if (self.shieldActive) {
// No damage while shield is active
return;
}
var actualDamage = damage * 0.6; // Ultra boss takes 40% less damage
self.health -= actualDamage;
self.updateHealthBar();
if (self.health <= 0 && !self.isDead) {
self.isDead = true;
LK.getSound('enemyDeath').play();
currency += self.reward;
diamonds += 10; // Ultra boss drops more diamonds
updateUI();
// Epic ultra boss death animation
tween(enemyGraphics, {
scaleX: 4,
scaleY: 4,
tint: 0x9932CC,
rotation: Math.PI * 6
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 800,
easing: tween.easeIn
});
}
});
LK.effects.flashScreen(0x9932CC, 1500);
}
};
self.update = function () {
if (self.isDead || self.reachedBase) {
return;
}
// Continuous epic pulsing animation
self.pulseTimer++;
if (self.pulseTimer % 30 === 0) {
var pulseScale = 3.5 + Math.sin(LK.ticks * 0.1) * 0.3;
var pulseColor = [0x4B0082, 0x8B0082, 0xFF0082, 0x4B00FF][Math.floor(LK.ticks / 15) % 4];
tween(enemyGraphics, {
scaleX: pulseScale,
scaleY: pulseScale,
tint: pulseColor
}, {
duration: 500,
easing: tween.easeInOut
});
}
// Epic particle trail effect
if (LK.ticks % 10 === 0) {
var particle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
particle.x = self.x + (Math.random() - 0.5) * 100;
particle.y = self.y + (Math.random() - 0.5) * 100;
particle.tint = 0x4B0082;
game.addChild(particle);
tween(particle, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 3
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
particle.destroy();
}
});
}
// Check if shield should end
if (self.shieldActive && LK.ticks >= self.shieldEndTime) {
self.shieldActive = false;
enemyGraphics.tint = 0x4B0082; // Reset ultra boss tint
}
// Check if slow effect should end
if (self.isSlowed && LK.ticks >= self.slowEndTime) {
self.speed = self.originalSpeed;
self.isSlowed = false;
enemyGraphics.tint = self.shieldActive ? 0x87CEEB : 0x4B0082;
}
// Ultra boss special attacks (more frequent)
if (LK.ticks - self.lastSpecialAttack >= self.specialAttackCooldown) {
var specialType = Math.floor(Math.random() * 4);
if (specialType === 0) {
self.healSelf();
} else if (specialType === 1) {
self.activateShield();
} else if (specialType === 2 && self.teleportCooldown <= 0) {
self.teleportToPath();
self.teleportCooldown = 300; // Shorter cooldown for more teleporting
} else {
self.areaDamage();
}
self.lastSpecialAttack = LK.ticks;
}
if (self.teleportCooldown > 0) {
self.teleportCooldown--;
}
if (self.pathIndex < enemyPath.length) {
var target = enemyPath[self.pathIndex];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 20) {
self.pathIndex++;
if (self.pathIndex >= enemyPath.length) {
self.reachedBase = true;
lives -= 15; // Even more damage to base
updateUI();
return;
}
}
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
// Ground shake effect while moving
if (LK.ticks % 60 === 0) {
LK.effects.flashScreen(0x4B0082, 200);
}
}
};
return self;
});
var MagicWarrior = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace graphics with magic warrior
self.removeChildAt(0);
var enemyGraphics = self.attachAsset('magicWarrior', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 120;
self.health = self.maxHealth;
self.speed = 2.2;
self.originalSpeed = self.speed;
self.reward = 20;
self.enemyType = 'magic';
self.magicResistance = 0.5; // Takes 50% less damage from magic towers
self.takeDamage = function (damage, damageType) {
var actualDamage = damage;
if (damageType === 'magic') {
actualDamage = damage * self.magicResistance;
}
self.health -= actualDamage;
self.updateHealthBar();
if (self.health <= 0 && !self.isDead) {
self.isDead = true;
LK.getSound('enemyDeath').play();
currency += self.reward;
updateUI();
tween(enemyGraphics, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500
});
}
};
return self;
});
var HeavyWarrior = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace graphics with heavy warrior
self.removeChildAt(0);
var enemyGraphics = self.attachAsset('heavyWarrior', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 200;
self.health = self.maxHealth;
self.speed = 1.0;
self.originalSpeed = self.speed;
self.reward = 25;
self.enemyType = 'heavy';
return self;
});
var FastWarrior = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace graphics with fast warrior
self.removeChildAt(0);
var enemyGraphics = self.attachAsset('fastWarrior', {
anchorX: 0.5,
anchorY: 0.5
});
self.maxHealth = 60;
self.health = self.maxHealth;
self.speed = 3.5;
self.originalSpeed = self.speed;
self.reward = 15;
self.enemyType = 'fast';
return self;
});
var Boss = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace graphics with boss enemy
self.removeChildAt(0);
var enemyGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
self.maxHealth = 1000;
self.health = self.maxHealth;
self.speed = 1.0;
self.originalSpeed = self.speed;
self.reward = 100;
self.enemyType = 'boss';
self.isBoss = true;
self.lastSpecialAttack = 0;
self.specialAttackCooldown = 300; // 5 seconds at 60fps
self.healAmount = 50;
self.stun = false;
self.stunEndTime = 0;
// Boss special ability - healing
self.healSelf = function () {
self.health = Math.min(self.maxHealth, self.health + self.healAmount);
self.updateHealthBar();
// Healing visual effect
tween(enemyGraphics, {
tint: 0x00FF00,
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
tint: 0x8B0000,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
easing: tween.easeIn
});
}
});
LK.effects.flashObject(self, 0x00FF00, 500);
};
// Boss stun ability - temporarily disable nearby towers
self.stunTowers = function () {
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
var dx = tower.x - self.x;
var dy = tower.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 200) {
// Disable tower temporarily
tower.stunned = true;
tower.stunEndTime = LK.ticks + 180; // 3 seconds
// Visual effect
tween(tower, {
tint: 0x666666,
alpha: 0.5
}, {
duration: 200
});
}
}
// Boss stun visual effect
LK.effects.flashScreen(0xFF0000, 500);
};
self.takeDamage = function (damage, damageType) {
var actualDamage = damage * 0.8; // Boss takes 20% less damage
self.health -= actualDamage;
self.updateHealthBar();
if (self.health <= 0 && !self.isDead) {
self.isDead = true;
LK.getSound('enemyDeath').play();
currency += self.reward;
diamonds += 5; // Boss drops diamonds
updateUI();
// Epic boss death animation
tween(enemyGraphics, {
scaleX: 3,
scaleY: 3,
tint: 0xFFD700,
rotation: Math.PI * 4
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemyGraphics, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
easing: tween.easeIn
});
}
});
LK.effects.flashScreen(0xFFD700, 1000);
}
};
self.update = function () {
if (self.isDead || self.reachedBase) {
return;
}
// Check if slow effect should end
if (self.isSlowed && LK.ticks >= self.slowEndTime) {
self.speed = self.originalSpeed;
self.isSlowed = false;
enemyGraphics.tint = 0x8B0000; // Reset boss tint
}
// Boss special attacks
if (LK.ticks - self.lastSpecialAttack >= self.specialAttackCooldown) {
var specialType = Math.floor(Math.random() * 2);
if (specialType === 0) {
self.healSelf();
} else {
self.stunTowers();
}
self.lastSpecialAttack = LK.ticks;
}
if (self.pathIndex < enemyPath.length) {
var target = enemyPath[self.pathIndex];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 20) {
self.pathIndex++;
if (self.pathIndex >= enemyPath.length) {
self.reachedBase = true;
lives -= 5; // Boss deals more damage to base
updateUI();
return;
}
}
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
}
};
return self;
});
var Tower = Container.expand(function () {
var self = Container.call(this);
var towerGraphics = self.attachAsset('tower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 150;
self.damage = 25;
self.fireRate = 60;
self.lastFire = 0;
self.cost = 50;
self.level = 1;
self.maxLevel = 3;
self.showingRange = false;
self.upgradeCost = 75;
var rangeIndicator = self.attachAsset('towerRange', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.visible = false;
self.showRange = function () {
rangeIndicator.visible = true;
self.showingRange = true;
};
self.hideRange = function () {
rangeIndicator.visible = false;
self.showingRange = false;
};
self.findTarget = function () {
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
// Bullet spawn animation
bullet.alpha = 0;
bullet.scaleX = 0.5;
bullet.scaleY = 0.5;
bullets.push(bullet);
game.addChild(bullet);
// Enhanced bullet appearance with trail effect
tween(bullet, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
// Add bullet trail animation
tween(bullet, {
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.linear
});
// Tower fire animation
var originalScale = towerGraphics.scaleX;
tween(towerGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: originalScale,
scaleY: originalScale
}, {
duration: 100,
easing: tween.easeIn
});
}
});
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
self.damage += 15;
self.range += 25;
self.fireRate = Math.max(30, self.fireRate - 10);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
// Update range indicator
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
// Enhanced visual upgrade animation
tween(towerGraphics, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0x00ff00
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
var finalTint = self.level === 2 ? 0x3A7BD5 : 0x2E5BBA;
tween(towerGraphics, {
scaleX: 1,
scaleY: 1,
tint: finalTint
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Upgrade sparkle effect
LK.effects.flashObject(self, 0xffd700, 800);
updateUI();
return true;
};
self.down = function (x, y, obj) {
// Always start dragging on click
draggingTower = self;
selectedTower = self;
// Use x, y parameters directly instead of trying to convert coordinates
dragOffset.x = x - self.x;
dragOffset.y = y - self.y;
originalTowerPosition.x = self.x;
originalTowerPosition.y = self.y;
// Find original grid position
var gridPos = getGridPosition(self.x, self.y);
if (gridPos) {
originalGridPosition.x = gridPos.x;
originalGridPosition.y = gridPos.y;
grid[gridPos.x][gridPos.y].occupied = false;
}
// Add drag visual effect
tween(self, {
alpha: 0.7,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200
});
hideAllRanges();
self.showRange();
};
self.update = function () {
// Check if tower is stunned by boss
if (self.stunned && LK.ticks >= self.stunEndTime) {
self.stunned = false;
// Reset visual effects
tween(self, {
tint: 0xFFFFFF,
alpha: 1
}, {
duration: 300
});
}
if (self.stunned) {
return;
} // Skip firing when stunned
var target = self.findTarget();
if (target) {
self.fire(target);
}
};
return self;
});
var VoidTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with void tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('lightningTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x000080; // Dark blue for void tower
towerGraphics.scaleX = 1.6;
towerGraphics.scaleY = 1.6;
self.range = 400; // Void range
self.damage = 75000; // Void damage
self.fireRate = 150; // Void firing rate
self.cost = 75000; // Void cost
self.level = 1;
self.maxLevel = 6; // Void upgrades
self.upgradeCost = 30000;
self.towerType = 'void';
self.voidRifts = true; // Creates void rifts
self.timeStop = true; // Stops time for enemies
self.realityTear = true; // Tears reality
self.voidPull = true; // Pulls enemies into void
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x000080;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Void attack with reality distortion
target.takeDamage(self.damage);
// Create void rift at target location
var riftX = target.x;
var riftY = target.y;
var rift = LK.getAsset('towerRange', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
x: riftX,
y: riftY
});
rift.tint = 0x000080;
rift.alpha = 0.8;
game.addChild(rift);
// Void rift expansion animation
tween(rift, {
scaleX: 3,
scaleY: 3,
rotation: Math.PI * 8
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Void pull effect on all enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - riftX;
var dy = enemy.y - riftY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 200) {
enemy.takeDamage(self.damage * 0.8);
// Pull enemies toward void
tween(enemy, {
x: riftX,
y: riftY,
alpha: 0.3,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 800,
easing: tween.easeIn
});
}
}
tween(rift, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 600,
onFinish: function onFinish() {
rift.destroy();
}
});
}
});
// Void tower firing animation
tween(towerGraphics, {
scaleX: 2.2,
scaleY: 2.2,
tint: 0x000000,
rotation: Math.PI * 0.8
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.6,
scaleY: 1.6,
tint: 0x000080,
rotation: 0
}, {
duration: 1000,
easing: tween.easeIn
});
}
});
// Void screen distortion effect
LK.effects.flashScreen(0x000080, 1200);
self.lastFire = LK.ticks;
LK.getSound('lightning').play();
};
return self;
});
var TitanTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with titan tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x800080; // Dark purple for titan tower
towerGraphics.scaleX = 2.5;
towerGraphics.scaleY = 2.5;
self.range = 800; // Titan range covers most of the map
self.damage = 100000; // Titan damage
self.fireRate = 200; // Slow but devastating
self.cost = 100000; // Titan cost
self.level = 1;
self.maxLevel = 10; // Titan upgrades
self.upgradeCost = 50000;
self.towerType = 'titan';
self.titanWrath = true; // Devastating area attacks
self.earthShatter = true; // Shatters the ground
self.titanRoar = true; // Stuns all enemies
self.meteorStrike = true; // Calls down meteors
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x800080;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Titan wrath - massive area damage
var wrathRadius = 400;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - target.x;
var dy = enemy.y - target.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= wrathRadius) {
var wrathDamage = self.damage * (1 - distance / wrathRadius * 0.5);
enemy.takeDamage(wrathDamage);
// Titan wrath visual effect
tween(enemy, {
tint: 0x800080,
scaleX: 2,
scaleY: 2,
rotation: Math.PI
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1,
rotation: 0
}, {
duration: 800
});
}
});
}
}
// Meteor strike effect
for (var m = 0; m < 5; m++) {
var meteorX = target.x + (Math.random() - 0.5) * 600;
var meteorY = target.y + (Math.random() - 0.5) * 600;
var meteor = LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
x: meteorX,
y: meteorY - 800
});
meteor.tint = 0xFF4500;
game.addChild(meteor);
// Meteor fall animation
tween(meteor, {
y: meteorY,
scaleX: 2,
scaleY: 2,
rotation: Math.PI * 3
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
// Meteor impact damage
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - meteorX;
var dy = enemy.y - meteorY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 150) {
enemy.takeDamage(self.damage * 0.3);
}
}
tween(meteor, {
alpha: 0,
scaleX: 5,
scaleY: 5
}, {
duration: 500,
onFinish: function onFinish() {
meteor.destroy();
}
});
}
});
}
// Titan tower firing animation
tween(towerGraphics, {
scaleX: 3.5,
scaleY: 3.5,
tint: 0xFFFFFF,
rotation: Math.PI * 0.3
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0x800080,
rotation: 0
}, {
duration: 1200,
easing: tween.easeIn
});
}
});
// Massive screen effects for titan attack
LK.effects.flashScreen(0x800080, 3000);
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
// Titan roar ability - stuns all enemies
self.titanRoar = function () {
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
enemy.applySlow(0.1, 600); // 10 second stun
// Roar visual effect
tween(enemy, {
tint: 0x800080,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 600
});
}
});
}
LK.effects.flashScreen(0x800080, 1500);
};
self.update = function () {
// Check if tower is stunned by boss
if (self.stunned && LK.ticks >= self.stunEndTime) {
self.stunned = false;
// Reset visual effects
tween(self, {
tint: 0xFFFFFF,
alpha: 1
}, {
duration: 300
});
}
if (self.stunned) {
return;
} // Skip firing when stunned
// Titan roar every 5 seconds
if (LK.ticks % 300 === 0) {
self.titanRoar();
}
// Titan breathing animation
if (LK.ticks % 60 === 0) {
var breatheScale = 2.5 + Math.sin(LK.ticks * 0.02) * 0.3;
towerGraphics.scaleX = breatheScale;
towerGraphics.scaleY = breatheScale;
}
var target = self.findTarget();
if (target) {
self.fire(target);
}
};
return self;
});
var SuperTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with super tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0xFFD700; // Gold color for super tower
self.range = 500; // Increased range
self.damage = Infinity;
self.fireRate = 5; // Much faster firing
self.cost = 4000; // Expensive but powerful tower
self.level = 1;
self.maxLevel = 10; // More upgrade levels
self.upgradeCost = 1000;
self.towerType = 'super';
self.multiShot = 8; // Fires 8 bullets at once
self.piercing = true; // Bullets can hit multiple enemies
self.criticalChance = 1.0; // 100% critical hits
self.criticalMultiplier = 10; // Critical hits do 10x damage
self.isBuffed = true; // Super tower is now buffed
self.screenClearChance = 0.1; // 10% chance to clear entire screen
self.holyAura = true; // Damages all enemies continuously
self.timeWarp = true; // Slows down all enemies globally
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xFFD700;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Screen clear ability - 10% chance to obliterate all enemies
if (Math.random() < self.screenClearChance) {
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
if (!enemy.isDead && !enemy.reachedBase) {
enemy.takeDamage(Infinity);
// Epic obliteration animation
tween(enemy, {
alpha: 0,
scaleX: 3,
scaleY: 3,
rotation: Math.PI * 4,
tint: 0xFFFFFF
}, {
duration: 500,
easing: tween.easeOut
});
}
}
// Screen clear visual effect
LK.effects.flashScreen(0xFFD700, 1500);
}
// Multi-shot bullets with buffed critical hit system
for (var shot = 0; shot < self.multiShot; shot++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
// Buffed critical hit calculation (always critical now)
bullet.damage = self.damage * self.criticalMultiplier;
bullet.isPiercing = self.piercing;
bullet.hitTargets = []; // Track hit targets for piercing
bullet.isCritical = true;
// Spread bullets in a wider fan pattern
var angleOffset = (shot - Math.floor(self.multiShot / 2)) * 0.5;
bullet.angleOffset = angleOffset;
// Buffed super bullet visual - always epic
bullet.children[0].tint = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF, 0xFFD700][shot % 8];
bullet.children[0].scaleX = 3;
bullet.children[0].scaleY = 3;
// Add divine glow effect to bullets
tween(bullet.children[0], {
alpha: 0.7
}, {
duration: 100,
onFinish: function onFinish() {
tween(bullet.children[0], {
alpha: 1
}, {
duration: 100
});
}
});
bullets.push(bullet);
game.addChild(bullet);
}
// Enhanced super tower fire animation with divine energy pulse
var currentScale = 1.5 + (self.level - 1) * 0.2;
tween(towerGraphics, {
scaleX: currentScale + 1.5,
scaleY: currentScale + 1.5,
tint: 0xFFFFFF
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: currentScale,
scaleY: currentScale,
tint: 0xFFD700
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Add massive energy pulse ring animation
tween(rangeIndicator, {
alpha: 1.0,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(rangeIndicator, {
alpha: 0.3,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
});
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
// Add buffed update method for continuous abilities
self.update = function () {
// Check if tower is stunned by boss
if (self.stunned && LK.ticks >= self.stunEndTime) {
self.stunned = false;
// Reset visual effects
tween(self, {
tint: 0xFFFFFF,
alpha: 1
}, {
duration: 300
});
}
if (self.stunned) {
return;
} // Skip firing when stunned
// Holy Aura - continuously damage all enemies in massive range
if (self.holyAura && LK.ticks % 30 === 0) {
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
if (!enemy.isDead && !enemy.reachedBase) {
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 800) {
// Massive holy aura range
enemy.takeDamage(self.damage * 0.1); // Continuous damage
// Holy damage visual effect
tween(enemy, {
tint: 0xFFD700
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
}
}
}
}
// Time Warp - globally slow all enemies
if (self.timeWarp && LK.ticks % 60 === 0) {
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
if (!enemy.isDead && !enemy.reachedBase) {
enemy.applySlow(0.3, 180); // Slow all enemies significantly
}
}
// Time warp visual effect
LK.effects.flashScreen(0x0080FF, 200);
}
// Divine pulsing animation
if (LK.ticks % 60 === 0) {
var pulseColor = [0xFFD700, 0xFF8C00, 0xFFA500, 0xFFFF00][Math.floor(LK.ticks / 60) % 4];
var currentScale = 1.5 + (self.level - 1) * 0.2;
tween(towerGraphics, {
tint: pulseColor,
scaleX: currentScale + 0.3,
scaleY: currentScale + 0.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(towerGraphics, {
tint: 0xFFD700,
scaleX: currentScale,
scaleY: currentScale
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
var target = self.findTarget();
if (target) {
self.fire(target);
}
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
// Powerful level-based upgrades
self.damage += 100; // Massive damage increase
self.range += 75; // Significant range boost
self.fireRate = Math.max(5, self.fireRate - 2); // Faster firing
self.multiShot = Math.min(8, self.multiShot + 1); // More bullets
self.criticalChance = Math.min(0.8, self.criticalChance + 0.15); // Higher crit chance
self.criticalMultiplier += 0.5; // Higher crit damage
self.upgradeCost = Math.floor(self.upgradeCost * 2.2); // Exponential cost increase
// Special abilities per level
if (self.level === 2) {
// Level 2: Area damage
self.areaDamage = true;
self.areaRadius = 100;
} else if (self.level === 3) {
// Level 3: Improved area and slowing
self.areaRadius = 150;
self.slowingShots = true;
} else if (self.level === 4) {
// Level 4: Chain lightning effect
self.chainLightning = true;
self.chainCount = 3;
} else if (self.level === 5) {
// Level 5: Ultimate power - massive improvements
self.damage += 200;
self.multiShot = 10;
self.ultimateMode = true;
}
// Update range indicator
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
// Define level tints array
var levelTints = [0xFFD700, 0xFFA500, 0xFF8C00, 0xFF6347, 0xFF0000];
// Epic upgrade animation with increasing intensity
var newScale = 1.2 + (self.level - 1) * 0.1;
tween(towerGraphics, {
scaleX: newScale + 1.5,
scaleY: newScale + 1.5,
tint: 0xFFFFFF
}, {
duration: 600 + self.level * 100,
easing: tween.elasticOut,
onFinish: function onFinish() {
var levelTint = levelTints[self.level - 1];
tween(towerGraphics, {
scaleX: newScale,
scaleY: newScale,
tint: levelTint
}, {
duration: 400,
easing: tween.easeOut
});
}
});
// Upgrade visual effects based on level
if (self.level === 5) {
LK.effects.flashScreen(0xFF0000, 1500); // Red flash for ultimate level
} else {
LK.effects.flashObject(self, levelTints[self.level - 1], 1200);
}
updateUI();
return true;
};
return self;
});
var UltimateGodTower = SuperTower.expand(function () {
var self = SuperTower.call(this);
// Replace graphics with ultimate god tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0xFF0080; // Pink/purple god color
self.range = 500;
self.damage = Infinity;
self.fireRate = 5;
self.cost = 90000; // Ultimate tower costs 90000 gold
self.level = 1;
self.maxLevel = 10; // 10 upgrade levels
self.upgradeCost = 10000;
self.towerType = 'ultimategod';
self.multiShot = 10; // Fires 10 bullets at once
self.piercing = true;
self.criticalChance = 1.0; // 100% critical hits
self.criticalMultiplier = 10; // Critical hits do 10x damage
self.godPower = true;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xFF0080;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Ultimate god multi-shot with divine power
for (var shot = 0; shot < self.multiShot; shot++) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage * self.criticalMultiplier; // Always critical
bullet.isPiercing = self.piercing;
bullet.hitTargets = [];
bullet.isCritical = true;
// God bullets are larger and rainbow colored
bullet.children[0].tint = [0xFF0080, 0x80FF00, 0x0080FF, 0xFF8000][shot % 4];
bullet.children[0].scaleX = 3;
bullet.children[0].scaleY = 3;
bullets.push(bullet);
game.addChild(bullet);
}
// Epic god tower fire animation with divine energy
var currentScale = 2.0 + (self.level - 1) * 0.2;
tween(towerGraphics, {
scaleX: currentScale + 1.5,
scaleY: currentScale + 1.5,
tint: 0xFFFFFF
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: currentScale,
scaleY: currentScale,
tint: 0xFF0080
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Divine energy pulse animation
tween(rangeIndicator, {
alpha: 1.0,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(rangeIndicator, {
alpha: 0.3,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
});
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
return self;
});
var RocketTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with rocket tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('cannonTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0xFF4500; // Orange-red for rocket tower
self.range = 300; // Long range rocket launcher
self.damage = 500; // High damage rockets
self.fireRate = 120; // Slower firing rate for balance
self.cost = 0; // Free support tower
self.level = 1;
self.maxLevel = 5; // Can be upgraded
self.upgradeCost = 200;
self.towerType = 'rocket';
self.rocketSpeed = 4; // Slower rocket speed
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xFF4500;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Create rocket projectile
var rocket = new Bullet();
rocket.x = self.x;
rocket.y = self.y;
rocket.target = target;
rocket.damage = self.damage;
rocket.speed = self.rocketSpeed;
rocket.isRocket = true;
// Make rocket look different
rocket.children[0].tint = 0xFF4500;
rocket.children[0].scaleX = 2;
rocket.children[0].scaleY = 3;
// Add rocket trail effect
rocket.trailTimer = 0;
var originalUpdate = rocket.update;
rocket.update = function () {
if (originalUpdate) {
originalUpdate.call(this);
}
// Create rocket trail effects
rocket.trailTimer++;
if (rocket.trailTimer % 3 === 0) {
var trail = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
trail.x = rocket.x + (Math.random() - 0.5) * 10;
trail.y = rocket.y + (Math.random() - 0.5) * 10;
trail.tint = 0xFF4500;
game.addChild(trail);
tween(trail, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
trail.destroy();
}
});
}
};
bullets.push(rocket);
game.addChild(rocket);
// Epic rocket launch animation
tween(towerGraphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4500
}, {
duration: 300,
easing: tween.easeIn
});
}
});
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
self.damage += 200; // Significant damage increase
self.range += 50; // Range increase
self.fireRate = Math.max(80, self.fireRate - 10); // Faster firing
self.upgradeCost = Math.floor(self.upgradeCost * 1.8); // Higher upgrade cost
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
// Upgrade visual effects
var levelTints = [0xFF4500, 0xFF6500, 0xFF8500, 0xFFA500, 0xFFD700];
towerGraphics.tint = levelTints[self.level - 1];
tween(towerGraphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFFFFF
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: levelTints[self.level - 1]
}, {
duration: 300,
easing: tween.easeOut
});
}
});
LK.effects.flashObject(self, 0xFFD700, 800);
updateUI();
return true;
};
return self;
});
var QuantumTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with quantum tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('lightningTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x9900FF; // Purple for quantum tower
towerGraphics.scaleX = 1.4;
towerGraphics.scaleY = 1.4;
self.range = 500; // Quantum range
self.damage = 25000; // Quantum damage
self.fireRate = 100; // Quantum firing rate
self.cost = 35000; // Quantum technology cost
self.level = 1;
self.maxLevel = 7; // Quantum upgrades
self.upgradeCost = 18000;
self.towerType = 'quantum';
self.quantumField = true; // Creates quantum field
self.timeDistortion = true; // Distorts time around enemies
self.quantumTeleport = true; // Can teleport enemies
self.dimensionalRift = true; // Creates dimensional rifts
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x9900FF;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Quantum attack with multiple effects
target.takeDamage(self.damage);
// Quantum teleportation - teleport enemy backwards
if (self.quantumTeleport && target.pathIndex > 2) {
target.pathIndex -= 3;
var newPos = enemyPath[target.pathIndex];
target.x = newPos.x;
target.y = newPos.y;
// Teleport visual effect
tween(target, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 3
}, {
duration: 200,
onFinish: function onFinish() {
tween(target, {
alpha: 1,
scaleX: 1,
scaleY: 1,
rotation: 0
}, {
duration: 400,
easing: tween.bounceOut
});
}
});
}
// Quantum field effect on nearby enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range * 0.7) {
// Time distortion - slow enemies significantly
enemy.applySlow(0.2, 300);
// Quantum field visual effect
tween(enemy, {
tint: 0x9900FF,
alpha: 0.7
}, {
duration: 300,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF,
alpha: 1
}, {
duration: 500
});
}
});
}
}
// Quantum tower firing animation
tween(towerGraphics, {
scaleX: 1.8,
scaleY: 1.8,
tint: 0xFFFFFF,
rotation: Math.PI * 0.5
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0x9900FF,
rotation: 0
}, {
duration: 600,
easing: tween.easeIn
});
}
});
// Quantum screen distortion effect
LK.effects.flashScreen(0x9900FF, 800);
self.lastFire = LK.ticks;
LK.getSound('lightning').play();
};
// Quantum field continuous effects
self.update = function () {
// Check if tower is stunned by boss
if (self.stunned && LK.ticks >= self.stunEndTime) {
self.stunned = false;
// Reset visual effects
tween(self, {
tint: 0xFFFFFF,
alpha: 1
}, {
duration: 300
});
}
if (self.stunned) {
return;
} // Skip firing when stunned
// Dimensional rift creation every 180 ticks
if (LK.ticks % 180 === 0) {
var riftX = self.x + (Math.random() - 0.5) * 400;
var riftY = self.y + (Math.random() - 0.5) * 400;
var rift = LK.getAsset('towerRange', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
x: riftX,
y: riftY
});
rift.tint = 0x9900FF;
rift.alpha = 0.6;
game.addChild(rift);
// Rift expansion animation
tween(rift, {
scaleX: 2,
scaleY: 2,
rotation: Math.PI * 4
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Damage enemies caught in rift
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - riftX;
var dy = enemy.y - riftY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 100) {
enemy.takeDamage(self.damage * 0.5);
}
}
tween(rift, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 400,
onFinish: function onFinish() {
rift.destroy();
}
});
}
});
}
// Quantum pulsing animation
if (LK.ticks % 40 === 0) {
var pulseColor = [0x9900FF, 0xBB00FF, 0xDD00FF, 0xFF00FF][Math.floor(LK.ticks / 40) % 4];
towerGraphics.tint = pulseColor;
}
var target = self.findTarget();
if (target) {
self.fire(target);
}
};
return self;
});
var NuclearTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with nuclear tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0xFF0000; // Red for nuclear tower
towerGraphics.scaleX = 1.5;
towerGraphics.scaleY = 1.5;
self.range = 600; // Massive range for nuclear strikes
self.damage = 50000; // Nuclear damage
self.fireRate = 300; // Slow nuclear charges
self.cost = 50000; // Expensive nuclear technology
self.level = 1;
self.maxLevel = 8; // Nuclear upgrades
self.upgradeCost = 25000;
self.towerType = 'nuclear';
self.nuclearCharge = 0;
self.maxCharge = 180; // 3 seconds to charge
self.radiationDamage = 1000; // Continuous radiation damage
self.radiationRadius = 400; // Radiation area
self.nuclearExplosionRadius = 300; // Explosion radius
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xFF0000;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Nuclear explosion at target location
var explosionX = target.x;
var explosionY = target.y;
// Damage all enemies in massive explosion radius
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - explosionX;
var dy = enemy.y - explosionY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.nuclearExplosionRadius) {
var explosionDamage = self.damage * (1 - distance / self.nuclearExplosionRadius);
enemy.takeDamage(explosionDamage);
// Nuclear blast visual effect
tween(enemy, {
tint: 0xFF0000,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 500
});
}
});
}
}
// Nuclear explosion visual effect
var explosion = LK.getAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
x: explosionX,
y: explosionY
});
explosion.tint = 0xFF0000;
game.addChild(explosion);
tween(explosion, {
scaleX: 10,
scaleY: 10,
alpha: 0,
rotation: Math.PI * 4
}, {
duration: 1500,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Nuclear tower recoil animation
tween(towerGraphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF0000
}, {
duration: 800,
easing: tween.easeIn
});
}
});
// Massive screen flash for nuclear explosion
LK.effects.flashScreen(0xFF0000, 2000);
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
// Nuclear radiation continuous damage
self.update = function () {
// Check if tower is stunned by boss
if (self.stunned && LK.ticks >= self.stunEndTime) {
self.stunned = false;
// Reset visual effects
tween(self, {
tint: 0xFFFFFF,
alpha: 1
}, {
duration: 300
});
}
if (self.stunned) {
return;
} // Skip firing when stunned
// Continuous radiation damage every 30 ticks
if (LK.ticks % 30 === 0) {
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.radiationRadius) {
enemy.takeDamage(self.radiationDamage);
// Radiation visual effect
tween(enemy, {
tint: 0x00FF00
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF
}, {
duration: 300
});
}
});
}
}
}
// Nuclear charging animation
if (LK.ticks % 10 === 0) {
var chargeColor = [0xFF0000, 0xFF4000, 0xFF8000, 0xFFFF00][Math.floor(LK.ticks / 10) % 4];
towerGraphics.tint = chargeColor;
}
var target = self.findTarget();
if (target) {
self.fire(target);
}
};
return self;
});
var MagicTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with magic tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('magicTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 130;
self.damage = 20;
self.fireRate = 50;
self.cost = 80;
self.upgradeCost = 120;
self.towerType = 'magic';
self.slowEffect = 0.5;
self.slowDuration = 120;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xe67e22;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Create slowing bullet
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullet.slowEffect = self.slowEffect;
bullet.slowDuration = self.slowDuration;
bullet.isMagic = true;
bullets.push(bullet);
game.addChild(bullet);
// Add magical sparkle trail to bullet
bullet.sparkleTimer = 0;
var originalUpdate = bullet.update;
bullet.update = function () {
if (originalUpdate) {
originalUpdate.call(this);
}
// Create sparkle effects every few frames
bullet.sparkleTimer++;
if (bullet.sparkleTimer % 5 === 0) {
var sparkle = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
sparkle.x = bullet.x + (Math.random() - 0.5) * 20;
sparkle.y = bullet.y + (Math.random() - 0.5) * 20;
sparkle.tint = 0xe67e22;
game.addChild(sparkle);
tween(sparkle, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
sparkle.destroy();
}
});
}
};
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
self.damage += 12;
self.range += 25;
self.slowEffect = Math.max(0.2, self.slowEffect - 0.1);
self.slowDuration += 30;
self.fireRate = Math.max(30, self.fireRate - 10);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
towerGraphics.tint = self.level === 2 ? 0xD35400 : 0xA04000;
updateUI();
return true;
};
return self;
});
var LightningTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with lightning tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('lightningTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 140;
self.damage = 35;
self.fireRate = 80;
self.cost = 120;
self.upgradeCost = 180;
self.towerType = 'lightning';
self.chainCount = 3;
self.chainRadius = 100;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xf1c40f;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Lightning chain effect
var chainTargets = [target];
var currentTarget = target;
// Find chain targets
for (var c = 0; c < self.chainCount - 1; c++) {
var nextTarget = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
if (chainTargets.indexOf(enemy) !== -1) {
continue;
}
var dx = enemy.x - currentTarget.x;
var dy = enemy.y - currentTarget.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.chainRadius && distance < closestDistance) {
closestDistance = distance;
nextTarget = enemy;
}
}
if (nextTarget) {
chainTargets.push(nextTarget);
currentTarget = nextTarget;
}
}
// Apply damage to all chain targets
for (var i = 0; i < chainTargets.length; i++) {
var chainTarget = chainTargets[i];
var chainDamage = self.damage * (1 - i * 0.2); // Decreasing damage
chainTarget.takeDamage(chainDamage);
// Lightning effect animation
tween(chainTarget, {
tint: 0xf1c40f
}, {
duration: 100,
onFinish: function onFinish() {
tween(chainTarget, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
}
// Tower fire animation
tween(towerGraphics, {
tint: 0xf1c40f,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
self.lastFire = LK.ticks;
LK.getSound('lightning').play();
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
self.damage += 18;
self.range += 20;
self.chainCount++;
self.chainRadius += 20;
self.fireRate = Math.max(50, self.fireRate - 10);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
towerGraphics.tint = self.level === 2 ? 0xd4ac0d : 0xb7950b;
updateUI();
return true;
};
return self;
});
var LightningStormTower = LightningTower.expand(function () {
var self = LightningTower.call(this);
// Replace graphics with storm lightning tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('lightningTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x9932CC; // Purple for storm tower
towerGraphics.scaleX = 1.3;
towerGraphics.scaleY = 1.3;
self.range = 200;
self.damage = 80;
self.fireRate = 60;
self.cost = 300;
self.upgradeCost = 400;
self.towerType = 'stormLightning';
self.stormChains = 5; // More chain targets
self.stormRadius = 150;
self.stormDamage = 1.5; // Damage multiplier
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x9932CC;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Storm lightning with massive chain effect
var chainTargets = [target];
var currentTarget = target;
// Find more chain targets for storm effect
for (var c = 0; c < self.stormChains - 1; c++) {
var nextTarget = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
if (chainTargets.indexOf(enemy) !== -1) {
continue;
}
var dx = enemy.x - currentTarget.x;
var dy = enemy.y - currentTarget.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.stormRadius && distance < closestDistance) {
closestDistance = distance;
nextTarget = enemy;
}
}
if (nextTarget) {
chainTargets.push(nextTarget);
currentTarget = nextTarget;
}
}
// Apply storm damage to all chain targets
for (var i = 0; i < chainTargets.length; i++) {
var chainTarget = chainTargets[i];
var stormDamage = self.damage * self.stormDamage * (1 - i * 0.1);
chainTarget.takeDamage(stormDamage);
// Epic storm lightning effect
tween(chainTarget, {
tint: 0x9932CC,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(chainTarget, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
}
});
}
// Epic tower storm animation
tween(towerGraphics, {
tint: 0xFFFFFF,
scaleX: 1.8,
scaleY: 1.8,
rotation: Math.PI * 0.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
tint: 0x9932CC,
scaleX: 1.3,
scaleY: 1.3,
rotation: 0
}, {
duration: 400,
easing: tween.bounceOut
});
}
});
// Storm screen effect
LK.effects.flashScreen(0x9932CC, 400);
self.lastFire = LK.ticks;
LK.getSound('lightning').play();
};
return self;
});
var LaserTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with laser tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('laserTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 160;
self.damage = 8;
self.fireRate = 10;
self.cost = 110;
self.upgradeCost = 160;
self.towerType = 'laser';
self.currentTarget = null;
self.beamDuration = 0;
self.maxBeamDuration = 300;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xe74c3c;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Continuous laser beam
if (self.currentTarget === target) {
self.beamDuration++;
// Increasing damage over time
var damageMultiplier = 1 + self.beamDuration / 100;
target.takeDamage(self.damage * damageMultiplier);
} else {
self.currentTarget = target;
self.beamDuration = 0;
target.takeDamage(self.damage);
}
// Laser beam visual effect
tween(target, {
tint: 0xe74c3c
}, {
duration: 50,
onFinish: function onFinish() {
tween(target, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
// Tower rotation towards target
var angle = Math.atan2(target.y - self.y, target.x - self.x);
tween(towerGraphics, {
rotation: angle
}, {
duration: 100,
easing: tween.easeOut
});
self.lastFire = LK.ticks;
if (self.beamDuration % 30 === 0) {
LK.getSound('laser').play();
}
};
self.findTarget = function () {
// Prefer to keep current target if still in range
if (self.currentTarget && !self.currentTarget.isDead && !self.currentTarget.reachedBase) {
var dx = self.currentTarget.x - self.x;
var dy = self.currentTarget.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
return self.currentTarget;
}
}
// Find new target if current is lost
self.currentTarget = null;
self.beamDuration = 0;
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
return closestEnemy;
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
self.damage += 5;
self.range += 25;
self.maxBeamDuration += 100;
self.fireRate = Math.max(5, self.fireRate - 2);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
towerGraphics.tint = self.level === 2 ? 0xc0392b : 0xa93226;
updateUI();
return true;
};
return self;
});
var PlasmaTower = LaserTower.expand(function () {
var self = LaserTower.call(this);
// Replace graphics with plasma tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('laserTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x00FF80; // Green plasma color
towerGraphics.scaleX = 1.2;
towerGraphics.scaleY = 1.2;
self.range = 180;
self.damage = 12;
self.fireRate = 5; // Very fast continuous beam
self.cost = 250;
self.upgradeCost = 350;
self.towerType = 'plasma';
self.energyLevel = 0;
self.maxEnergy = 100;
self.energyBuildup = 2;
self.overchargeMode = false;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x00FF80;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Build up energy over time
self.energyLevel = Math.min(self.maxEnergy, self.energyLevel + self.energyBuildup);
// Damage increases with energy level
var energyMultiplier = 1 + self.energyLevel / self.maxEnergy * 2;
var finalDamage = self.damage * energyMultiplier;
// Overcharge mode at max energy
if (self.energyLevel >= self.maxEnergy && !self.overchargeMode) {
self.overchargeMode = true;
finalDamage *= 3; // Triple damage in overcharge
// Overcharge visual effect
tween(towerGraphics, {
tint: 0xFFFFFF,
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
tint: 0x00FF80,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800
});
}
});
LK.effects.flashScreen(0x00FF80, 600);
self.energyLevel = 0; // Reset energy after overcharge
}
target.takeDamage(finalDamage);
// Plasma beam visual effect with energy color
var energyColor = self.energyLevel < 50 ? 0x00FF80 : 0x00FFFF;
tween(target, {
tint: energyColor,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 60,
onFinish: function onFinish() {
tween(target, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 120
});
}
});
// Energy buildup animation on tower
var energyScale = 1.2 + self.energyLevel / self.maxEnergy * 0.3;
towerGraphics.scaleX = energyScale;
towerGraphics.scaleY = energyScale;
self.lastFire = LK.ticks;
if (self.energyLevel % 20 === 0) {
LK.getSound('laser').play();
}
};
return self;
});
var InfernalTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with infernal tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('cannonTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x8B0000; // Dark red for infernal tower
towerGraphics.scaleX = 1.7;
towerGraphics.scaleY = 1.7;
self.range = 350; // Infernal range
self.damage = 100000; // Infernal damage
self.fireRate = 120; // Infernal firing rate
self.cost = 120000; // Infernal cost
self.level = 1;
self.maxLevel = 7; // Infernal upgrades
self.upgradeCost = 45000;
self.towerType = 'infernal';
self.hellfire = true; // Hellfire attacks
self.demonSummon = true; // Summons demons
self.infernalBlast = true; // Infernal explosions
self.soulBurn = true; // Burns enemy souls
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x8B0000;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Hellfire attack
target.takeDamage(self.damage);
// Infernal blast at target location
var blastX = target.x;
var blastY = target.y;
var blast = LK.getAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
x: blastX,
y: blastY
});
blast.tint = 0x8B0000;
game.addChild(blast);
// Infernal blast expansion
tween(blast, {
scaleX: 8,
scaleY: 8,
alpha: 0.7,
rotation: Math.PI * 6
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Damage enemies in blast radius
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - blastX;
var dy = enemy.y - blastY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 250) {
enemy.takeDamage(self.damage * 0.7);
// Soul burn effect
tween(enemy, {
tint: 0x8B0000,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 400,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 800
});
}
});
}
}
tween(blast, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
onFinish: function onFinish() {
blast.destroy();
}
});
}
});
// Infernal tower firing animation
tween(towerGraphics, {
scaleX: 2.3,
scaleY: 2.3,
tint: 0xFF0000,
rotation: Math.PI * 0.6
}, {
duration: 350,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.7,
scaleY: 1.7,
tint: 0x8B0000,
rotation: 0
}, {
duration: 900,
easing: tween.easeIn
});
}
});
// Infernal screen effect
LK.effects.flashScreen(0x8B0000, 900);
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
return self;
});
var FreezeTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with freeze tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('freezeTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 120;
self.damage = 10;
self.fireRate = 120;
self.cost = 90;
self.upgradeCost = 140;
self.towerType = 'freeze';
self.freezeRadius = 80;
self.freezeDuration = 180;
self.freezeEffect = 0.1;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x7fb3d3;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Area freeze effect
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.freezeRadius) {
enemy.takeDamage(self.damage);
enemy.applySlow(self.freezeEffect, self.freezeDuration);
// Freeze effect animation
tween(enemy, {
tint: 0x7fb3d3
}, {
duration: 200,
onFinish: function onFinish() {
tween(enemy, {
tint: 0x3498db
}, {
duration: self.freezeDuration * 16
});
}
});
}
}
// Tower fire animation with pulse effect
tween(towerGraphics, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0x3498db
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
self.lastFire = LK.ticks;
LK.getSound('freeze').play();
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
self.damage += 8;
self.range += 15;
self.freezeRadius += 20;
self.freezeDuration += 60;
self.freezeEffect = Math.max(0.05, self.freezeEffect - 0.025);
self.fireRate = Math.max(80, self.fireRate - 15);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
towerGraphics.tint = self.level === 2 ? 0x5dade2 : 0x3498db;
updateUI();
return true;
};
return self;
});
var ChronoTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with chrono tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('freezeTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0x4169E1; // Blue for chrono tower
towerGraphics.scaleX = 1.5;
towerGraphics.scaleY = 1.5;
self.range = 300; // Chrono range
self.damage = 80000; // Chrono damage
self.fireRate = 90; // Chrono firing rate
self.cost = 80000; // Chrono cost
self.level = 1;
self.maxLevel = 6; // Chrono upgrades
self.upgradeCost = 35000;
self.towerType = 'chrono';
self.timeFreeze = true; // Freezes time
self.timeReverse = true; // Reverses enemy movement
self.temporalShield = true; // Temporal protection
self.chronoBlast = true; // Chrono explosions
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x4169E1;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Chrono attack
target.takeDamage(self.damage);
// Time freeze effect on all enemies in range
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range) {
// Time freeze - slow enemies dramatically
enemy.applySlow(0.05, 300);
// Time reverse effect
if (enemy.pathIndex > 0) {
enemy.pathIndex--;
var newPos = enemyPath[enemy.pathIndex];
tween(enemy, {
x: newPos.x,
y: newPos.y,
tint: 0x4169E1,
alpha: 0.6
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF,
alpha: 1
}, {
duration: 600
});
}
});
}
}
}
// Chrono tower firing animation
tween(towerGraphics, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0x00BFFF,
rotation: Math.PI * 0.4
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0x4169E1,
rotation: 0
}, {
duration: 700,
easing: tween.easeIn
});
}
});
// Chrono screen effect
LK.effects.flashScreen(0x4169E1, 700);
self.lastFire = LK.ticks;
LK.getSound('freeze').play();
};
return self;
});
var CelestialTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with celestial tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('superTower', {
anchorX: 0.5,
anchorY: 0.5
});
towerGraphics.tint = 0xFFFFFF; // White for celestial tower
towerGraphics.scaleX = 1.8;
towerGraphics.scaleY = 1.8;
self.range = 600; // Celestial range
self.damage = 150000; // Celestial damage
self.fireRate = 180; // Celestial firing rate
self.cost = 150000; // Celestial cost
self.level = 1;
self.maxLevel = 8; // Celestial upgrades
self.upgradeCost = 60000;
self.towerType = 'celestial';
self.divineBeam = true; // Divine beam attacks
self.healingAura = true; // Heals other towers
self.angelicWings = true; // Angelic protection
self.holyJudgment = true; // Divine judgment
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0xFFFFFF;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Divine beam attack
target.takeDamage(self.damage);
// Holy judgment on nearby enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (enemy.isDead || enemy.reachedBase) {
continue;
}
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range * 0.8) {
enemy.takeDamage(self.damage * 0.6);
// Divine judgment visual effect
tween(enemy, {
tint: 0xFFFFFF,
scaleX: 1.3,
scaleY: 1.3,
alpha: 0.7
}, {
duration: 300,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 800
});
}
});
}
}
// Celestial tower firing animation
tween(towerGraphics, {
scaleX: 2.5,
scaleY: 2.5,
tint: 0xFFD700,
rotation: Math.PI * 0.2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(towerGraphics, {
scaleX: 1.8,
scaleY: 1.8,
tint: 0xFFFFFF,
rotation: 0
}, {
duration: 1200,
easing: tween.easeIn
});
}
});
// Divine screen effect
LK.effects.flashScreen(0xFFFFFF, 1000);
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
return self;
});
var CannonTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with cannon tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('cannonTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 120;
self.damage = 40;
self.fireRate = 90;
self.cost = 100;
self.upgradeCost = 150;
self.towerType = 'cannon';
self.splashRadius = 80;
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x34495e;
self.fire = function (target) {
if (LK.ticks - self.lastFire < self.fireRate) {
return;
}
// Create splash damage bullet
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.target = target;
bullet.damage = self.damage;
bullet.splashRadius = self.splashRadius;
bullet.isSplash = true;
bullets.push(bullet);
game.addChild(bullet);
self.lastFire = LK.ticks;
LK.getSound('shoot').play();
};
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
self.damage += 20;
self.range += 20;
self.splashRadius += 20;
self.fireRate = Math.max(60, self.fireRate - 15);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
towerGraphics.tint = self.level === 2 ? 0x2C3E50 : 0x1B2631;
updateUI();
return true;
};
return self;
});
var ArcherTower = Tower.expand(function () {
var self = Tower.call(this);
// Replace graphics with archer tower
self.removeChildAt(0);
var towerGraphics = self.attachAsset('archerTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 200;
self.damage = 15;
self.fireRate = 40;
self.cost = 75;
self.upgradeCost = 100;
self.towerType = 'archer';
// Update range indicator
var rangeIndicator = self.children[self.children.length - 1];
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
rangeIndicator.tint = 0x8e44ad;
self.upgrade = function () {
if (self.level >= self.maxLevel || currency < self.upgradeCost) {
return false;
}
currency -= self.upgradeCost;
self.level++;
self.damage += 10;
self.range += 30;
self.fireRate = Math.max(25, self.fireRate - 5);
self.upgradeCost = Math.floor(self.upgradeCost * 1.5);
rangeIndicator.width = self.range * 2;
rangeIndicator.height = self.range * 2;
towerGraphics.tint = self.level === 2 ? 0x7D3C98 : 0x6C3483;
updateUI();
return true;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var gridSize = 100;
var mapWidth = 20;
var mapHeight = 25;
var currency = 390;
var diamonds = 0;
var lives = 20;
var wave = 1;
var enemiesInWave = 5;
var enemiesSpawned = 0;
var waveActive = false;
var gameOver = false;
var towers = [];
var enemies = [];
var bullets = [];
var grid = [];
var enemyPath = [];
var selectedTower = null;
var placingTower = false;
var selectedTowerType = 'basic';
var draggingTower = null;
var dragOffset = {
x: 0,
y: 0
};
var originalTowerPosition = {
x: 0,
y: 0
};
var originalGridPosition = {
x: 0,
y: 0
};
var rocketDelivered = false;
var superTowerUnlocked = true;
var gameMode = 'normal'; // Always normal mode
// Achievements system
var achievements = [{
id: 'first_victory',
name: 'First Victory',
description: 'Complete your first tower defense game',
icon: 'š',
unlocked: false
}, {
id: 'wave_master',
name: 'Wave Master',
description: 'Survive 20 waves in a single game',
icon: 'š',
unlocked: false
}, {
id: 'tower_commander',
name: 'Tower Commander',
description: 'Build 10 towers in a single game',
icon: 'š°',
unlocked: false
}, {
id: 'currency_collector',
name: 'Currency Collector',
description: 'Accumulate 5000 gold in a single game',
icon: 'š°',
unlocked: false
}, {
id: 'diamond_hunter',
name: 'Diamond Hunter',
description: 'Collect 50 diamonds in a single game',
icon: 'š',
unlocked: false
}, {
id: 'boss_slayer',
name: 'Boss Slayer',
description: 'Defeat 5 bosses in a single game',
icon: 'āļø',
unlocked: false
}, {
id: 'perfect_defense',
name: 'Perfect Defense',
description: 'Complete the game without losing a single life',
icon: 'š”ļø',
unlocked: false
}, {
id: 'ultimate_warrior',
name: 'Ultimate Warrior',
description: 'Defeat the final boss and complete all 31 waves',
icon: 'š',
unlocked: false
}];
// Load saved achievements
var savedAchievements = storage.achievements || {};
for (var i = 0; i < achievements.length; i++) {
if (savedAchievements[achievements[i].id]) {
achievements[i].unlocked = true;
}
}
// Achievement tracking variables
var gameStats = {
towersBuilt: 0,
bossesDefeated: 0,
maxCurrency: 0,
maxDiamonds: 0,
livesLost: 0
};
function checkAchievements() {
var newUnlocks = [];
// Check each achievement
for (var i = 0; i < achievements.length; i++) {
var achievement = achievements[i];
if (!achievement.unlocked) {
var shouldUnlock = false;
switch (achievement.id) {
case 'first_victory':
shouldUnlock = wave > 31;
break;
case 'wave_master':
shouldUnlock = wave >= 20;
break;
case 'tower_commander':
shouldUnlock = gameStats.towersBuilt >= 10;
break;
case 'currency_collector':
shouldUnlock = gameStats.maxCurrency >= 5000;
break;
case 'diamond_hunter':
shouldUnlock = gameStats.maxDiamonds >= 50;
break;
case 'boss_slayer':
shouldUnlock = gameStats.bossesDefeated >= 5;
break;
case 'perfect_defense':
shouldUnlock = wave > 31 && gameStats.livesLost === 0;
break;
case 'ultimate_warrior':
shouldUnlock = wave > 31;
break;
}
if (shouldUnlock) {
achievement.unlocked = true;
newUnlocks.push(achievement);
// Save achievement to storage
if (!savedAchievements[achievement.id]) {
savedAchievements[achievement.id] = true;
storage.achievements = savedAchievements;
}
}
}
}
return newUnlocks;
}
function showAchievementUnlock(achievement) {
// Create achievement notification
var achievementNotification = new Text2(achievement.icon + ' ' + achievement.name, {
size: 60,
fill: 0xFFD700
});
achievementNotification.anchor.set(0.5, 0.5);
achievementNotification.x = 2048 / 2;
achievementNotification.y = 200;
achievementNotification.alpha = 0;
achievementNotification.scaleX = 0.1;
achievementNotification.scaleY = 0.1;
game.addChild(achievementNotification);
// Create description text
var descriptionText = new Text2(achievement.description, {
size: 35,
fill: 0xFFFFFF
});
descriptionText.anchor.set(0.5, 0.5);
descriptionText.x = 2048 / 2;
descriptionText.y = 270;
descriptionText.alpha = 0;
descriptionText.scaleX = 0.1;
descriptionText.scaleY = 0.1;
game.addChild(descriptionText);
// Achievement unlock animation
tween(achievementNotification, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(achievementNotification, {
scaleX: 1,
scaleY: 1
}, {
duration: 400,
easing: tween.easeOut
});
}
});
tween(descriptionText, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Hold for 3 seconds then fade out
LK.setTimeout(function () {
tween(achievementNotification, {
alpha: 0,
y: 150
}, {
duration: 800,
onFinish: function onFinish() {
achievementNotification.destroy();
}
});
tween(descriptionText, {
alpha: 0,
y: 220
}, {
duration: 800,
onFinish: function onFinish() {
descriptionText.destroy();
}
});
}, 3000);
}
});
// Achievement unlock screen effect
LK.effects.flashScreen(0xFFD700, 1000);
}
function showCompletionAchievements() {
// Check for newly unlocked achievements
var newUnlocks = checkAchievements();
if (newUnlocks.length > 0) {
// Show each achievement with a delay
for (var i = 0; i < newUnlocks.length; i++) {
(function (achievement, delay) {
LK.setTimeout(function () {
showAchievementUnlock(achievement);
}, delay * 1500);
})(newUnlocks[i], i);
}
}
// Show all unlocked achievements summary after individual notifications
LK.setTimeout(function () {
showAchievementsSummary();
}, newUnlocks.length * 1500 + 2000);
}
function showAchievementsSummary() {
// Create achievements summary background
var summaryBg = LK.getAsset('grassTile', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 18,
scaleY: 20,
x: 2048 / 2,
y: 2732 / 2
});
summaryBg.tint = 0x000000;
summaryBg.alpha = 0;
game.addChild(summaryBg);
// Fade in background
tween(summaryBg, {
alpha: 0.8
}, {
duration: 500
});
// Create title
var titleText = new Text2('š ACHIEVEMENTS UNLOCKED! š', {
size: 80,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 400;
titleText.alpha = 0;
game.addChild(titleText);
tween(titleText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 600,
easing: tween.bounceOut
});
// Show unlocked achievements list
var unlockedCount = 0;
var yOffset = 600;
for (var i = 0; i < achievements.length; i++) {
if (achievements[i].unlocked) {
unlockedCount++;
var achievementText = new Text2(achievements[i].icon + ' ' + achievements[i].name, {
size: 45,
fill: 0x00FF00
});
achievementText.anchor.set(0.5, 0.5);
achievementText.x = 2048 / 2;
achievementText.y = yOffset;
achievementText.alpha = 0;
game.addChild(achievementText);
// Stagger the appearance of each achievement
(function (text, delay) {
LK.setTimeout(function () {
tween(text, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 400,
easing: tween.easeOut
});
}, delay * 200);
})(achievementText, i);
yOffset += 120;
}
}
// Show completion percentage
var completionText = new Text2('Completion: ' + unlockedCount + '/' + achievements.length + ' (' + Math.round(unlockedCount / achievements.length * 100) + '%)', {
size: 50,
fill: 0xFFFFFF
});
completionText.anchor.set(0.5, 0.5);
completionText.x = 2048 / 2;
completionText.y = yOffset + 100;
completionText.alpha = 0;
game.addChild(completionText);
LK.setTimeout(function () {
tween(completionText, {
alpha: 1,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 600,
easing: tween.bounceOut
});
}, achievements.length * 200 + 500);
}
// Create UI elements (initially hidden)
var currencyTxt = new Text2('Gold: 390', {
size: 35,
fill: 0xFFD700
});
currencyTxt.anchor.set(0, 0);
currencyTxt.x = 120;
currencyTxt.y = 20;
currencyTxt.visible = true;
LK.gui.topLeft.addChild(currencyTxt);
var diamondsTxt = new Text2('Diamonds: 0', {
size: 35,
fill: 0x00FFFF
});
diamondsTxt.anchor.set(0, 0);
diamondsTxt.x = 120;
diamondsTxt.y = 60;
diamondsTxt.visible = true;
LK.gui.topLeft.addChild(diamondsTxt);
var livesTxt = new Text2('Lives: 20', {
size: 35,
fill: 0xFF0000
});
livesTxt.anchor.set(0.5, 0);
livesTxt.visible = true;
LK.gui.top.addChild(livesTxt);
var waveTxt = new Text2('Wave: 1', {
size: 35,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
waveTxt.visible = true;
LK.gui.topRight.addChild(waveTxt);
var nextWaveTimer = 0;
var waveBreakDuration = 180; // 3 seconds at 60fps
var buyTowerBtn = new Text2('Basic Tower (20g)', {
size: 28,
fill: 0x4A90E2
});
buyTowerBtn.anchor.set(0, 1);
buyTowerBtn.x = 20;
buyTowerBtn.y = -20;
buyTowerBtn.visible = true;
LK.gui.bottomLeft.addChild(buyTowerBtn);
var buyArcherBtn = new Text2('Archer Tower (30g)', {
size: 28,
fill: 0x8e44ad
});
buyArcherBtn.anchor.set(0, 1);
buyArcherBtn.x = 20;
buyArcherBtn.y = -50;
buyArcherBtn.visible = true;
LK.gui.bottomLeft.addChild(buyArcherBtn);
var buyCannonBtn = new Text2('Cannon Tower (40g)', {
size: 28,
fill: 0x34495e
});
buyCannonBtn.anchor.set(0, 1);
buyCannonBtn.x = 20;
buyCannonBtn.y = -80;
buyCannonBtn.visible = true;
LK.gui.bottomLeft.addChild(buyCannonBtn);
var buyMagicBtn = new Text2('Magic Tower (35g)', {
size: 28,
fill: 0xe67e22
});
buyMagicBtn.anchor.set(0, 1);
buyMagicBtn.x = 20;
buyMagicBtn.y = -110;
buyMagicBtn.visible = true;
LK.gui.bottomLeft.addChild(buyMagicBtn);
var buyLightningBtn = new Text2('Lightning Tower (50g)', {
size: 28,
fill: 0xf1c40f
});
buyLightningBtn.anchor.set(0, 1);
buyLightningBtn.x = 20;
buyLightningBtn.y = -140;
buyLightningBtn.visible = true;
LK.gui.bottomLeft.addChild(buyLightningBtn);
var buyFreezeBtn = new Text2('Freeze Tower (40g)', {
size: 28,
fill: 0x7fb3d3
});
buyFreezeBtn.anchor.set(0, 1);
buyFreezeBtn.x = 20;
buyFreezeBtn.y = -170;
buyFreezeBtn.visible = true;
LK.gui.bottomLeft.addChild(buyFreezeBtn);
var buyLaserBtn = new Text2('Laser Tower (45g)', {
size: 28,
fill: 0xe74c3c
});
buyLaserBtn.anchor.set(0, 1);
buyLaserBtn.x = 20;
buyLaserBtn.y = -200;
buyLaserBtn.visible = true;
LK.gui.bottomLeft.addChild(buyLaserBtn);
var buySuperBtn = new Text2('SUPER TOWER (4000g)', {
size: 28,
fill: 0xFFD700
});
buySuperBtn.anchor.set(0, 1);
buySuperBtn.x = 20;
buySuperBtn.y = -230;
buySuperBtn.visible = true;
LK.gui.bottomLeft.addChild(buySuperBtn);
var buyUltimateBtn = new Text2('ULTIMATE GOD TOWER (90000g)', {
size: 28,
fill: 0xFF0080
});
buyUltimateBtn.anchor.set(0, 1);
buyUltimateBtn.x = 20;
buyUltimateBtn.y = -260;
buyUltimateBtn.visible = true;
LK.gui.bottomLeft.addChild(buyUltimateBtn);
var buyStormBtn = new Text2('Lightning Storm Tower (80g)', {
size: 28,
fill: 0x9932CC
});
buyStormBtn.anchor.set(0, 1);
buyStormBtn.x = 20;
buyStormBtn.y = -290;
buyStormBtn.visible = true;
LK.gui.bottomLeft.addChild(buyStormBtn);
var buyPlasmaBtn = new Text2('Plasma Tower (70g)', {
size: 28,
fill: 0x00FF80
});
buyPlasmaBtn.anchor.set(0, 1);
buyPlasmaBtn.x = 20;
buyPlasmaBtn.y = -320;
buyPlasmaBtn.visible = true;
LK.gui.bottomLeft.addChild(buyPlasmaBtn);
var buyNuclearBtn = new Text2('Nuclear Tower (1000g)', {
size: 28,
fill: 0xFF0000
});
buyNuclearBtn.anchor.set(0, 1);
buyNuclearBtn.x = 20;
buyNuclearBtn.y = -350;
buyNuclearBtn.visible = true;
LK.gui.bottomLeft.addChild(buyNuclearBtn);
var buyQuantumBtn = new Text2('Quantum Tower (800g)', {
size: 28,
fill: 0x9900FF
});
buyQuantumBtn.anchor.set(0, 1);
buyQuantumBtn.x = 20;
buyQuantumBtn.y = -380;
buyQuantumBtn.visible = true;
LK.gui.bottomLeft.addChild(buyQuantumBtn);
var buyTitanBtn = new Text2('TITAN TOWER (2500g)', {
size: 28,
fill: 0x800080
});
buyTitanBtn.anchor.set(0, 1);
buyTitanBtn.x = 20;
buyTitanBtn.y = -410;
buyTitanBtn.visible = true;
LK.gui.bottomLeft.addChild(buyTitanBtn);
var buyVoidBtn = new Text2('VOID TOWER (1500g)', {
size: 28,
fill: 0x000080
});
buyVoidBtn.anchor.set(0, 1);
buyVoidBtn.x = 20;
buyVoidBtn.y = -440;
buyVoidBtn.visible = true;
LK.gui.bottomLeft.addChild(buyVoidBtn);
var buyCelestialBtn = new Text2('CELESTIAL TOWER (3000g)', {
size: 28,
fill: 0xFFFFFF
});
buyCelestialBtn.anchor.set(0, 1);
buyCelestialBtn.x = 20;
buyCelestialBtn.y = -470;
buyCelestialBtn.visible = true;
LK.gui.bottomLeft.addChild(buyCelestialBtn);
var buyInfernalBtn = new Text2('INFERNAL TOWER (2200g)', {
size: 28,
fill: 0x8B0000
});
buyInfernalBtn.anchor.set(0, 1);
buyInfernalBtn.x = 20;
buyInfernalBtn.y = -500;
buyInfernalBtn.visible = true;
LK.gui.bottomLeft.addChild(buyInfernalBtn);
var buyChronoBtn = new Text2('CHRONO TOWER (1800g)', {
size: 28,
fill: 0x4169E1
});
buyChronoBtn.anchor.set(0, 1);
buyChronoBtn.x = 20;
buyChronoBtn.y = -530;
buyChronoBtn.visible = true;
LK.gui.bottomLeft.addChild(buyChronoBtn);
var upgradeTowerBtn = new Text2('Upgrade Tower', {
size: 32,
fill: 0xFF6B35
});
upgradeTowerBtn.anchor.set(0, 1);
upgradeTowerBtn.x = 20;
upgradeTowerBtn.y = -560;
upgradeTowerBtn.visible = false;
LK.gui.bottomLeft.addChild(upgradeTowerBtn);
var enhanceAllBtn = new Text2('Enhance All Towers (10ā¦)', {
size: 28,
fill: 0x00FFFF
});
enhanceAllBtn.anchor.set(1, 1);
enhanceAllBtn.x = -20;
enhanceAllBtn.y = -20;
enhanceAllBtn.visible = true;
LK.gui.bottomRight.addChild(enhanceAllBtn);
var superDamageBtn = new Text2('Super Damage (15ā¦)', {
size: 28,
fill: 0xFF6B35
});
superDamageBtn.anchor.set(1, 1);
superDamageBtn.x = -20;
superDamageBtn.y = -50;
superDamageBtn.visible = true;
LK.gui.bottomRight.addChild(superDamageBtn);
var rapidFireBtn = new Text2('Rapid Fire (12ā¦)', {
size: 28,
fill: 0xFFFF00
});
rapidFireBtn.anchor.set(1, 1);
rapidFireBtn.x = -20;
rapidFireBtn.y = -80;
rapidFireBtn.visible = true;
LK.gui.bottomRight.addChild(rapidFireBtn);
var skipWaveBtn = new Text2('Skip Wave (5ā¦)', {
size: 28,
fill: 0xFF00FF
});
skipWaveBtn.anchor.set(1, 1);
skipWaveBtn.x = -20;
skipWaveBtn.y = -110;
skipWaveBtn.visible = true;
LK.gui.bottomRight.addChild(skipWaveBtn);
// Initialize game directly in normal mode
initializeGrid();
createPath();
drawMap();
drawBase();
// Give free support tower at start with 567 damage
var supportTower = new Tower();
supportTower.x = 5 * gridSize + gridSize / 2;
supportTower.y = 5 * gridSize + gridSize / 2;
supportTower.damage = 567;
supportTower.range = 200;
supportTower.fireRate = 30;
towers.push(supportTower);
game.addChild(supportTower);
grid[5][5].occupied = true;
// Add entrance animation for support tower
supportTower.alpha = 0;
supportTower.scaleX = 0.1;
supportTower.scaleY = 0.1;
tween(supportTower, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2,
tint: 0x00FF00
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(supportTower, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 400
});
}
});
updateUI();
function updateUI() {
currencyTxt.setText('Gold: ' + currency);
diamondsTxt.setText('Diamonds: ' + diamonds);
livesTxt.setText('Lives: ' + lives);
waveTxt.setText('Wave: ' + wave);
// Track max currency and diamonds for achievements
gameStats.maxCurrency = Math.max(gameStats.maxCurrency, currency);
gameStats.maxDiamonds = Math.max(gameStats.maxDiamonds, diamonds);
if (currency >= 20) {
buyTowerBtn.tint = 0x4A90E2;
} else {
buyTowerBtn.tint = 0x666666;
}
if (currency >= 30) {
buyArcherBtn.tint = 0x8e44ad;
} else {
buyArcherBtn.tint = 0x666666;
}
if (currency >= 40) {
buyCannonBtn.tint = 0x34495e;
} else {
buyCannonBtn.tint = 0x666666;
}
if (currency >= 35) {
buyMagicBtn.tint = 0xe67e22;
} else {
buyMagicBtn.tint = 0x666666;
}
if (currency >= 50) {
buyLightningBtn.tint = 0xf1c40f;
} else {
buyLightningBtn.tint = 0x666666;
}
if (currency >= 40) {
buyFreezeBtn.tint = 0x7fb3d3;
} else {
buyFreezeBtn.tint = 0x666666;
}
if (currency >= 45) {
buyLaserBtn.tint = 0xe74c3c;
} else {
buyLaserBtn.tint = 0x666666;
}
// Update upgrade button visibility and state
if (selectedTower && selectedTower.level < selectedTower.maxLevel) {
upgradeTowerBtn.visible = true;
upgradeTowerBtn.setText('Upgrade Lv' + selectedTower.level + ' (' + selectedTower.upgradeCost + 'g)');
if (currency >= selectedTower.upgradeCost) {
upgradeTowerBtn.tint = 0xFF6B35;
} else {
upgradeTowerBtn.tint = 0x666666;
}
} else {
upgradeTowerBtn.visible = false;
}
// Update diamond enhancement buttons
if (diamonds >= 10) {
enhanceAllBtn.tint = 0x00FFFF;
} else {
enhanceAllBtn.tint = 0x666666;
}
if (diamonds >= 15) {
superDamageBtn.tint = 0xFF6B35;
} else {
superDamageBtn.tint = 0x666666;
}
if (diamonds >= 12) {
rapidFireBtn.tint = 0xFFFF00;
} else {
rapidFireBtn.tint = 0x666666;
}
// Update skip wave button
if (diamonds >= 5 && waveActive) {
skipWaveBtn.tint = 0xFF00FF;
} else {
skipWaveBtn.tint = 0x666666;
}
// Update super tower button visibility
buySuperBtn.visible = true;
buySuperBtn.setText('SUPER TOWER (500g)');
if (currency >= 500) {
buySuperBtn.tint = 0xFFD700;
} else {
buySuperBtn.tint = 0x666666;
}
// Update ultimate god tower button
buyUltimateBtn.setText('ULTIMATE GOD TOWER (2000g)');
if (currency >= 2000) {
buyUltimateBtn.tint = 0xFF0080;
} else {
buyUltimateBtn.tint = 0x666666;
}
// Update storm tower button
if (currency >= 80) {
buyStormBtn.tint = 0x9932CC;
} else {
buyStormBtn.tint = 0x666666;
}
// Update plasma tower button
if (currency >= 70) {
buyPlasmaBtn.tint = 0x00FF80;
} else {
buyPlasmaBtn.tint = 0x666666;
}
// Update nuclear tower button
if (currency >= 1000) {
buyNuclearBtn.tint = 0xFF0000;
} else {
buyNuclearBtn.tint = 0x666666;
}
// Update quantum tower button
if (currency >= 800) {
buyQuantumBtn.tint = 0x9900FF;
} else {
buyQuantumBtn.tint = 0x666666;
}
// Update titan tower button
if (currency >= 2500) {
buyTitanBtn.tint = 0x800080;
} else {
buyTitanBtn.tint = 0x666666;
}
// Update void tower button
if (currency >= 1500) {
buyVoidBtn.tint = 0x000080;
} else {
buyVoidBtn.tint = 0x666666;
}
// Update celestial tower button
if (currency >= 3000) {
buyCelestialBtn.tint = 0xFFFFFF;
} else {
buyCelestialBtn.tint = 0x666666;
}
// Update infernal tower button
if (currency >= 2200) {
buyInfernalBtn.tint = 0x8B0000;
} else {
buyInfernalBtn.tint = 0x666666;
}
// Update chrono tower button
if (currency >= 1800) {
buyChronoBtn.tint = 0x4169E1;
} else {
buyChronoBtn.tint = 0x666666;
}
}
function hideAllRanges() {
for (var i = 0; i < towers.length; i++) {
towers[i].hideRange();
}
}
function initializeGrid() {
for (var x = 0; x < mapWidth; x++) {
grid[x] = [];
for (var y = 0; y < mapHeight; y++) {
grid[x][y] = {
x: x * gridSize + gridSize / 2,
y: y * gridSize + gridSize / 2,
occupied: false,
isPath: false
};
}
}
}
function createPath() {
enemyPath = [];
var pathCoords = [{
x: 0,
y: 12
}, {
x: 1,
y: 12
}, {
x: 2,
y: 12
}, {
x: 3,
y: 12
}, {
x: 4,
y: 12
}, {
x: 5,
y: 12
}, {
x: 6,
y: 12
}, {
x: 7,
y: 12
}, {
x: 8,
y: 12
}, {
x: 8,
y: 11
}, {
x: 8,
y: 10
}, {
x: 8,
y: 9
}, {
x: 8,
y: 8
}, {
x: 9,
y: 8
}, {
x: 10,
y: 8
}, {
x: 11,
y: 8
}, {
x: 12,
y: 8
}, {
x: 12,
y: 9
}, {
x: 12,
y: 10
}, {
x: 12,
y: 11
}, {
x: 12,
y: 12
}, {
x: 13,
y: 12
}, {
x: 14,
y: 12
}, {
x: 15,
y: 12
}, {
x: 16,
y: 12
}, {
x: 17,
y: 12
}, {
x: 18,
y: 12
}, {
x: 19,
y: 12
}];
for (var i = 0; i < pathCoords.length; i++) {
var coord = pathCoords[i];
if (coord.x < mapWidth && coord.y < mapHeight) {
grid[coord.x][coord.y].isPath = true;
// Also mark adjacent tiles as path to make path wider
if (coord.y > 0) {
grid[coord.x][coord.y - 1].isPath = true;
}
if (coord.y < mapHeight - 1) {
grid[coord.x][coord.y + 1].isPath = true;
}
enemyPath.push({
x: coord.x * gridSize + gridSize / 2,
y: coord.y * gridSize + gridSize / 2
});
}
}
}
function drawMap() {
for (var x = 0; x < mapWidth; x++) {
for (var y = 0; y < mapHeight; y++) {
var tile;
if (grid[x][y].isPath) {
tile = LK.getAsset('pathTile', {
x: x * gridSize,
y: y * gridSize
});
} else {
tile = LK.getAsset('grassTile', {
x: x * gridSize,
y: y * gridSize
});
}
game.addChild(tile);
}
}
}
function drawBase() {
var base = LK.getAsset('base', {
anchorX: 0.5,
anchorY: 0.5,
x: (mapWidth - 1) * gridSize + gridSize / 2,
y: 12 * gridSize + gridSize / 2
});
game.addChild(base);
}
function spawnEnemy() {
if (enemiesSpawned >= enemiesInWave) {
return;
}
var enemy;
// Spawn ultra boss on wave 21 and give 4000 gold at wave start
if (wave === 21 && enemiesSpawned === 0) {
// Give 4000 gold when wave 21 starts
currency += 4000;
updateUI();
}
// Wave 10: Give ultra tower with 90999999999999 damage
if (wave === 10 && enemiesSpawned === 0) {
// Create ultra support tower with massive damage
var ultraTower = new Tower();
ultraTower.x = 7 * gridSize + gridSize / 2; // Place at grid position (7,7)
ultraTower.y = 7 * gridSize + gridSize / 2;
ultraTower.damage = 90999999999999; // Set damage to 90999999999999
ultraTower.range = 400; // Massive range for maximum support
ultraTower.fireRate = 5; // Ultra fast firing
towers.push(ultraTower);
game.addChild(ultraTower);
grid[7][7].occupied = true; // Mark grid position as occupied
// Add epic entrance animation for ultra tower
ultraTower.alpha = 0;
ultraTower.scaleX = 0.1;
ultraTower.scaleY = 0.1;
tween(ultraTower, {
alpha: 1,
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFD700
}, {
duration: 1500,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(ultraTower, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF0080
}, {
duration: 800
});
}
});
// Show ultra support message
var ultraMsg = new Text2('ULTRA SUPPORT TOWER DEPLOYED!', {
size: 60,
fill: 0xFFD700
});
ultraMsg.anchor.set(0.5, 0.5);
ultraMsg.x = 2048 / 2;
ultraMsg.y = 400;
ultraMsg.alpha = 0;
game.addChild(ultraMsg);
tween(ultraMsg, {
alpha: 1,
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 1800,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(ultraMsg, {
alpha: 0
}, {
duration: 2500,
onFinish: function onFinish() {
ultraMsg.destroy();
}
});
}
});
// Epic screen flash for ultra support arrival
LK.effects.flashScreen(0xFFD700, 2000);
updateUI();
}
// Wave 12: Gold rush bonus
if (wave === 12 && enemiesSpawned === 0) {
currency += 800;
diamonds += 8;
var goldMsg = new Text2('GOLD RUSH BONUS!', {
size: 50,
fill: 0xFFD700
});
goldMsg.anchor.set(0.5, 0.5);
goldMsg.x = 2048 / 2;
goldMsg.y = 350;
goldMsg.alpha = 0;
game.addChild(goldMsg);
tween(goldMsg, {
alpha: 1,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 1200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(goldMsg, {
alpha: 0
}, {
duration: 2000,
onFinish: function onFinish() {
goldMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0xFFD700, 1000);
updateUI();
}
// Wave 14: Lightning storm enhancement
if (wave === 14 && enemiesSpawned === 0) {
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
if (tower.towerType === 'lightning' || tower.towerType === 'stormLightning') {
tower.damage *= 3;
tower.chainCount += 2;
tower.chainRadius += 50;
tween(tower, {
tint: 0xFFFF00,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tower, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 600
});
}
});
}
}
var stormMsg = new Text2('LIGHTNING TOWERS SUPERCHARGED!', {
size: 100,
fill: 0xFFFF00
});
stormMsg.anchor.set(0.5, 0.5);
stormMsg.x = 2048 / 2;
stormMsg.y = 400;
stormMsg.alpha = 0;
game.addChild(stormMsg);
tween(stormMsg, {
alpha: 1,
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(stormMsg, {
alpha: 0
}, {
duration: 1800,
onFinish: function onFinish() {
stormMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0xFFFF00, 1200);
updateUI();
}
// Wave 16: Freeze enhancement
if (wave === 16 && enemiesSpawned === 0) {
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
if (tower.towerType === 'freeze') {
tower.damage *= 2.5;
tower.freezeRadius += 60;
tower.freezeDuration += 120;
tower.freezeEffect = Math.max(0.01, tower.freezeEffect - 0.05);
tween(tower, {
tint: 0x00FFFF,
scaleX: 1.4,
scaleY: 1.4
}, {
duration: 700,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tower, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 500
});
}
});
}
}
var freezeMsg = new Text2('FREEZE TOWERS ENHANCED!', {
size: 100,
fill: 0x00FFFF
});
freezeMsg.anchor.set(0.5, 0.5);
freezeMsg.x = 2048 / 2;
freezeMsg.y = 450;
freezeMsg.alpha = 0;
game.addChild(freezeMsg);
tween(freezeMsg, {
alpha: 1,
scaleX: 1.7,
scaleY: 1.7
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(freezeMsg, {
alpha: 0
}, {
duration: 1600,
onFinish: function onFinish() {
freezeMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0x00FFFF, 1000);
updateUI();
}
// Wave 18: Massive currency boost
if (wave === 18 && enemiesSpawned === 0) {
currency += 2000;
diamonds += 12;
var massiveMsg = new Text2('MASSIVE RESOURCE BOOST!', {
size: 130,
fill: 0x00FF00
});
massiveMsg.anchor.set(0.5, 0.5);
massiveMsg.x = 2048 / 2;
massiveMsg.y = 500;
massiveMsg.alpha = 0;
game.addChild(massiveMsg);
tween(massiveMsg, {
alpha: 1,
scaleX: 2.2,
scaleY: 2.2,
rotation: Math.PI * 0.1
}, {
duration: 1300,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(massiveMsg, {
alpha: 0
}, {
duration: 2200,
onFinish: function onFinish() {
massiveMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0x00FF00, 1500);
updateUI();
}
// Give free super rocket tower at wave 20
if (wave === 20 && enemiesSpawned === 0) {
// Create super rocket tower with high damage
var rocketTower = new RocketTower();
rocketTower.x = 3 * gridSize + gridSize / 2; // Place at grid position (3,3)
rocketTower.y = 3 * gridSize + gridSize / 2;
towers.push(rocketTower);
game.addChild(rocketTower);
grid[3][3].occupied = true; // Mark grid position as occupied
// Add epic entrance animation for rocket tower
rocketTower.alpha = 0;
rocketTower.scaleX = 0.1;
rocketTower.scaleY = 0.1;
tween(rocketTower, {
alpha: 1,
scaleX: 1.8,
scaleY: 1.8,
tint: 0xFFFFFF
}, {
duration: 1200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(rocketTower, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4500
}, {
duration: 600
});
}
});
// Show rocket support message
var rocketMsg = new Text2('SUPER ROCKET LAUNCHER DEPLOYED!', {
size: 120,
fill: 0xFF4500
});
rocketMsg.anchor.set(0.5, 0.5);
rocketMsg.x = 2048 / 2;
rocketMsg.y = 500;
rocketMsg.alpha = 0;
game.addChild(rocketMsg);
tween(rocketMsg, {
alpha: 1,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 1500,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(rocketMsg, {
alpha: 0
}, {
duration: 2000,
onFinish: function onFinish() {
rocketMsg.destroy();
}
});
}
});
// Epic screen flash for rocket support arrival
LK.effects.flashScreen(0xFF4500, 1800);
updateUI();
}
// Wave 22: Archer enhancement
if (wave === 22 && enemiesSpawned === 0) {
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
if (tower.towerType === 'archer') {
tower.damage *= 4;
tower.range += 100;
tower.fireRate = Math.max(10, tower.fireRate - 20);
tween(tower, {
tint: 0xFF00FF,
scaleX: 1.6,
scaleY: 1.6
}, {
duration: 900,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tower, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 700
});
}
});
}
}
var archerMsg = new Text2('ARCHER TOWERS PERFECTED!', {
size: 110,
fill: 0xFF00FF
});
archerMsg.anchor.set(0.5, 0.5);
archerMsg.x = 2048 / 2;
archerMsg.y = 420;
archerMsg.alpha = 0;
game.addChild(archerMsg);
tween(archerMsg, {
alpha: 1,
scaleX: 1.9,
scaleY: 1.9
}, {
duration: 1100,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(archerMsg, {
alpha: 0
}, {
duration: 1900,
onFinish: function onFinish() {
archerMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0xFF00FF, 1100);
updateUI();
}
// Wave 24: Laser enhancement
if (wave === 24 && enemiesSpawned === 0) {
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
if (tower.towerType === 'laser' || tower.towerType === 'plasma') {
tower.damage *= 5;
tower.range += 80;
tower.fireRate = Math.max(3, tower.fireRate - 5);
if (tower.towerType === 'plasma') {
tower.maxEnergy += 50;
tower.energyBuildup += 3;
}
tween(tower, {
tint: 0xFF0000,
scaleX: 1.7,
scaleY: 1.7
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tower, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 800
});
}
});
}
}
var laserMsg = new Text2('LASER SYSTEMS MAXIMIZED!', {
size: 115,
fill: 0xFF0000
});
laserMsg.anchor.set(0.5, 0.5);
laserMsg.x = 2048 / 2;
laserMsg.y = 470;
laserMsg.alpha = 0;
game.addChild(laserMsg);
tween(laserMsg, {
alpha: 1,
scaleX: 2.0,
scaleY: 2.0,
rotation: Math.PI * 0.05
}, {
duration: 1200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(laserMsg, {
alpha: 0
}, {
duration: 2000,
onFinish: function onFinish() {
laserMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0xFF0000, 1300);
updateUI();
}
// Wave 26: Cannon enhancement
if (wave === 26 && enemiesSpawned === 0) {
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
if (tower.towerType === 'cannon') {
tower.damage *= 6;
tower.splashRadius += 80;
tower.fireRate = Math.max(30, tower.fireRate - 30);
tween(tower, {
tint: 0xFFFF00,
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 1100,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tower, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 900
});
}
});
}
}
var cannonMsg = new Text2('CANNON TOWERS EXPLOSIVE!', {
size: 115,
fill: 0xFFFF00
});
cannonMsg.anchor.set(0.5, 0.5);
cannonMsg.x = 2048 / 2;
cannonMsg.y = 380;
cannonMsg.alpha = 0;
game.addChild(cannonMsg);
tween(cannonMsg, {
alpha: 1,
scaleX: 2.1,
scaleY: 2.1
}, {
duration: 1150,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(cannonMsg, {
alpha: 0
}, {
duration: 2100,
onFinish: function onFinish() {
cannonMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0xFFFF00, 1400);
updateUI();
}
// Wave 28: Magic enhancement
if (wave === 28 && enemiesSpawned === 0) {
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
if (tower.towerType === 'magic') {
tower.damage *= 7;
tower.range += 100;
tower.slowEffect = Math.max(0.01, tower.slowEffect - 0.1);
tower.slowDuration += 180;
tween(tower, {
tint: 0x9932CC,
scaleX: 1.9,
scaleY: 1.9
}, {
duration: 1200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tower, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 1000
});
}
});
}
}
var magicMsg = new Text2('MAGIC TOWERS ASCENDED!', {
size: 120,
fill: 0x9932CC
});
magicMsg.anchor.set(0.5, 0.5);
magicMsg.x = 2048 / 2;
magicMsg.y = 430;
magicMsg.alpha = 0;
game.addChild(magicMsg);
tween(magicMsg, {
alpha: 1,
scaleX: 2.3,
scaleY: 2.3,
rotation: Math.PI * 0.08
}, {
duration: 1300,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(magicMsg, {
alpha: 0
}, {
duration: 2300,
onFinish: function onFinish() {
magicMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0x9932CC, 1500);
updateUI();
}
// Wave 30: Give 90000 gold when wave 30 starts
if (wave === 30 && enemiesSpawned === 0) {
// Give 90000 gold when wave 30 starts
currency += 90000;
diamonds += 20;
// Add ultimate preparation message
var ultimateMsg = new Text2('ULTIMATE PREPARATION COMPLETE!', {
size: 140,
fill: 0xFFD700
});
ultimateMsg.anchor.set(0.5, 0.5);
ultimateMsg.x = 2048 / 2;
ultimateMsg.y = 500;
ultimateMsg.alpha = 0;
game.addChild(ultimateMsg);
tween(ultimateMsg, {
alpha: 1,
scaleX: 2.5,
scaleY: 2.5,
rotation: Math.PI * 0.1
}, {
duration: 1500,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(ultimateMsg, {
alpha: 0
}, {
duration: 2500,
onFinish: function onFinish() {
ultimateMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0xFFD700, 2000);
updateUI();
}
// Epic power surge at wave 25
if (wave === 25 && enemiesSpawned === 0) {
// Power surge all towers
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
tower.damage = Math.floor(tower.damage * 3);
tower.range = Math.floor(tower.range * 1.5);
tower.fireRate = Math.max(5, Math.floor(tower.fireRate * 0.3));
// Epic power surge animation
tween(tower, {
scaleX: 2.0,
scaleY: 2.0,
tint: 0xFFD700,
rotation: Math.PI * 2
}, {
duration: 1200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(tower, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFFFF,
rotation: 0
}, {
duration: 800
});
}
});
}
// Epic power surge notification
var surgeMsg = new Text2('POWER SURGE ACTIVATED!', {
size: 180,
fill: 0xFFD700
});
surgeMsg.anchor.set(0.5, 0.5);
surgeMsg.x = 2048 / 2;
surgeMsg.y = 600;
surgeMsg.alpha = 0;
game.addChild(surgeMsg);
tween(surgeMsg, {
alpha: 1,
scaleX: 3.0,
scaleY: 3.0,
rotation: Math.PI * 0.3
}, {
duration: 2000,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(surgeMsg, {
alpha: 0
}, {
duration: 1500,
onFinish: function onFinish() {
surgeMsg.destroy();
}
});
}
});
LK.effects.flashScreen(0xFFD700, 2500);
}
if (wave === 21 && enemiesSpawned === enemiesInWave - 1) {
// Create ultra boss taunt animation first
var tauntText = new Text2('YOU WILL BE DEFEATED!', {
size: 180,
fill: 0xFF0000
});
tauntText.anchor.set(0.5, 0.5);
tauntText.x = 2048 / 2;
tauntText.y = 2732 / 2;
tauntText.alpha = 0;
tauntText.scaleX = 0.1;
tauntText.scaleY = 0.1;
game.addChild(tauntText);
// Dramatic taunt entrance animation
tween(tauntText, {
alpha: 1,
scaleX: 2.5,
scaleY: 2.5,
rotation: Math.PI * 0.2
}, {
duration: 1500,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Hold the taunt for dramatic effect
LK.setTimeout(function () {
tween(tauntText, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
tauntText.destroy();
// Now spawn the ultra boss after taunt animation
enemy = new UltraBoss();
// Epic ultra boss entrance with massive effects
LK.effects.flashScreen(0x4B0082, 2000);
// Create epic announcement
var announcement = new Text2('ULTRA BOSS UNLEASHED!', {
size: 150,
fill: 0x4B0082
});
announcement.anchor.set(0.5, 0.5);
announcement.x = 2048 / 2;
announcement.y = 300;
announcement.alpha = 0;
game.addChild(announcement);
tween(announcement, {
alpha: 1,
scaleX: 2,
scaleY: 2,
rotation: Math.PI * 0.1
}, {
duration: 1000,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(announcement, {
alpha: 0,
y: 100
}, {
duration: 1500,
onFinish: function onFinish() {
announcement.destroy();
}
});
}
});
// Continue with enemy placement
enemy.x = gridSize / 2;
enemy.y = 12 * gridSize + gridSize / 2;
// Scale stats with wave
enemy.health = enemy.maxHealth + (wave - 1) * 20;
enemy.maxHealth = enemy.health;
enemy.speed = enemy.originalSpeed + (wave - 1) * 0.2;
enemy.originalSpeed = enemy.speed;
enemy.reward = enemy.reward + (wave - 1) * 2;
// Spawn animation
enemy.alpha = 0;
enemy.scaleX = 0.1;
enemy.scaleY = 0.1;
enemies.push(enemy);
game.addChild(enemy);
// Enhanced enemy entrance animation with rotation
var spawnAnimationType = Math.floor(Math.random() * 3);
if (spawnAnimationType === 0) {
// Bounce entrance
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.bounceOut
});
} else if (spawnAnimationType === 1) {
// Spiral entrance
enemy.rotation = Math.PI * 4;
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1,
rotation: 0
}, {
duration: 600,
easing: tween.easeOut
});
} else {
// Elastic entrance
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
}
// Special boss spawn effects
if (enemy.isBoss || enemy.isUltraBoss) {
// Screen flash and shake for boss spawn
LK.effects.flashScreen(0x8B0000, 800);
// Create warning text
var warningText = new Text2(enemy.isUltraBoss ? 'ULTRA BOSS INCOMING!' : 'BOSS INCOMING!', {
size: 50,
fill: 0xFF0000
});
warningText.anchor.set(0.5, 0.5);
warningText.x = 2048 / 2;
warningText.y = 300;
warningText.alpha = 0;
game.addChild(warningText);
tween(warningText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(warningText, {
alpha: 0,
y: 200
}, {
duration: 1000,
onFinish: function onFinish() {
warningText.destroy();
}
});
}
});
}
enemiesSpawned++;
return;
}
});
}, 2000); // Wait 2 seconds before removing taunt
}
});
return; // Exit function to prevent normal enemy spawning
} else if (wave > 10 && wave % 5 === 0 && enemiesSpawned === enemiesInWave - 1) {
enemy = new UltraBoss();
} else if (wave % 10 === 0 && enemiesSpawned === enemiesInWave - 1) {
// Spawn regular boss on wave 10 and every 10 waves
enemy = new Boss();
} else {
var enemyType = Math.floor(Math.random() * 4);
if (enemyType === 0) {
enemy = new Enemy();
} else if (enemyType === 1) {
enemy = new FastWarrior();
} else if (enemyType === 2) {
enemy = new HeavyWarrior();
} else {
enemy = new MagicWarrior();
}
}
enemy.x = gridSize / 2;
enemy.y = 12 * gridSize + gridSize / 2;
// Scale stats with wave
enemy.health = enemy.maxHealth + (wave - 1) * 20;
enemy.maxHealth = enemy.health;
enemy.speed = enemy.originalSpeed + (wave - 1) * 0.2;
enemy.originalSpeed = enemy.speed;
enemy.reward = enemy.reward + (wave - 1) * 2;
// Spawn animation
enemy.alpha = 0;
enemy.scaleX = 0.1;
enemy.scaleY = 0.1;
enemies.push(enemy);
game.addChild(enemy);
// Enhanced enemy entrance animation with rotation
var spawnAnimationType = Math.floor(Math.random() * 3);
if (spawnAnimationType === 0) {
// Bounce entrance
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.bounceOut
});
} else if (spawnAnimationType === 1) {
// Spiral entrance
enemy.rotation = Math.PI * 4;
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1,
rotation: 0
}, {
duration: 600,
easing: tween.easeOut
});
} else {
// Elastic entrance
tween(enemy, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
}
// Special boss spawn effects
if (enemy.isBoss || enemy.isUltraBoss) {
// Screen flash and shake for boss spawn
LK.effects.flashScreen(0x8B0000, 800);
// Create warning text
var warningText = new Text2(enemy.isUltraBoss ? 'ULTRA BOSS INCOMING!' : 'BOSS INCOMING!', {
size: 100,
fill: 0xFF0000
});
warningText.anchor.set(0.5, 0.5);
warningText.x = 2048 / 2;
warningText.y = 300;
warningText.alpha = 0;
game.addChild(warningText);
tween(warningText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(warningText, {
alpha: 0,
y: 200
}, {
duration: 1000,
onFinish: function onFinish() {
warningText.destroy();
}
});
}
});
}
enemiesSpawned++;
}
function getGridPosition(x, y) {
var gridX = Math.floor(x / gridSize);
var gridY = Math.floor(y / gridSize);
if (gridX >= 0 && gridX < mapWidth && gridY >= 0 && gridY < mapHeight) {
return {
x: gridX,
y: gridY
};
}
return null;
}
function canPlaceTower(gridX, gridY) {
return !grid[gridX][gridY].occupied && !grid[gridX][gridY].isPath;
}
function placeTower(gridX, gridY) {
var tower;
var cost;
if (selectedTowerType === 'basic') {
cost = 20;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new Tower();
} else if (selectedTowerType === 'archer') {
cost = 30;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new ArcherTower();
} else if (selectedTowerType === 'cannon') {
cost = 40;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new CannonTower();
} else if (selectedTowerType === 'magic') {
cost = 35;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new MagicTower();
} else if (selectedTowerType === 'lightning') {
cost = 50;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new LightningTower();
} else if (selectedTowerType === 'freeze') {
cost = 40;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new FreezeTower();
} else if (selectedTowerType === 'laser') {
cost = 45;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new LaserTower();
} else if (selectedTowerType === 'super') {
cost = 500; // Super tower costs 500 gold
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new SuperTower();
} else if (selectedTowerType === 'ultimategod') {
cost = 2000; // Ultimate god tower costs 2000 gold
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new UltimateGodTower();
} else if (selectedTowerType === 'stormLightning') {
cost = 80;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new LightningStormTower();
} else if (selectedTowerType === 'plasma') {
cost = 70;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new PlasmaTower();
} else if (selectedTowerType === 'nuclear') {
cost = 1000;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new NuclearTower();
} else if (selectedTowerType === 'quantum') {
cost = 800;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new QuantumTower();
} else if (selectedTowerType === 'titan') {
cost = 2500;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new TitanTower();
} else if (selectedTowerType === 'void') {
cost = 1500;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new VoidTower();
} else if (selectedTowerType === 'celestial') {
cost = 3000;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new CelestialTower();
} else if (selectedTowerType === 'infernal') {
cost = 2200;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new InfernalTower();
} else if (selectedTowerType === 'chrono') {
cost = 1800;
if (!canPlaceTower(gridX, gridY) || currency < cost) {
return false;
}
tower = new ChronoTower();
}
tower.x = gridX * gridSize + gridSize / 2;
tower.y = gridY * gridSize + gridSize / 2;
// Placement animation
tower.alpha = 0;
tower.scaleX = 0.1;
tower.scaleY = 0.1;
towers.push(tower);
game.addChild(tower);
// Animate tower placement
tween(tower, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(tower, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
grid[gridX][gridY].occupied = true;
currency -= cost;
placingTower = false;
// Track tower building for achievements
gameStats.towersBuilt++;
updateUI();
return true;
}
function startWave() {
if (waveActive) {
return;
}
waveActive = true;
enemiesSpawned = 0;
enemiesInWave = 5 + wave * 2;
// Special rocket animation for wave 20
if (wave === 20 && !rocketDelivered) {
deliverSuperTowerRocket();
rocketDelivered = true;
}
// Enhanced wave start effects with screen shake
LK.effects.flashScreen(0x00FF00, 300);
// Screen shake animation
var originalX = game.x;
var originalY = game.y;
var shakeIntensity = 10;
var shakeDuration = 500;
var shakeInterval = 50;
for (var i = 0; i < shakeDuration / shakeInterval; i++) {
LK.setTimeout(function () {
var shakeX = (Math.random() - 0.5) * shakeIntensity;
var shakeY = (Math.random() - 0.5) * shakeIntensity;
tween(game, {
x: originalX + shakeX,
y: originalY + shakeY
}, {
duration: shakeInterval / 2,
onFinish: function onFinish() {
tween(game, {
x: originalX,
y: originalY
}, {
duration: shakeInterval / 2
});
}
});
}, i * shakeInterval);
}
}
function deliverSuperTowerRocket() {
// Create rocket
var rocket = LK.getAsset('tower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 2,
x: 2048 / 2,
y: -100
});
rocket.tint = 0xFF4500;
rocket.rotation = Math.PI;
game.addChild(rocket);
// Rocket descent animation
tween(rocket, {
y: 2732 / 2,
rotation: 0
}, {
duration: 2000,
easing: tween.easeIn,
onFinish: function onFinish() {
// Explosion effect
LK.effects.flashScreen(0xFFD700, 1000);
// Remove rocket and show super tower unlock message
rocket.destroy();
superTowerUnlocked = true;
// Create super tower unlock notification
var unlockMsg = new Text2('SUPER TOWER UNLOCKED!', {
size: 120,
fill: 0xFFD700
});
unlockMsg.anchor.set(0.5, 0.5);
unlockMsg.x = 2048 / 2;
unlockMsg.y = 2732 / 2;
unlockMsg.alpha = 0;
game.addChild(unlockMsg);
// Animate unlock message
tween(unlockMsg, {
alpha: 1,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 800,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(unlockMsg, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
unlockMsg.destroy();
}
});
}
});
updateUI();
}
});
}
function checkWaveComplete() {
if (!waveActive) {
return;
}
var allEnemiesGone = true;
for (var i = 0; i < enemies.length; i++) {
if (!enemies[i].isDead && !enemies[i].reachedBase) {
allEnemiesGone = false;
break;
}
}
if (enemiesSpawned >= enemiesInWave && allEnemiesGone) {
waveActive = false;
wave++;
currency += 25;
diamonds += 5; // Award 5 diamonds per wave
nextWaveTimer = waveBreakDuration; // Start 3-second countdown
updateUI();
// Clean up dead enemies
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].isDead || enemies[i].reachedBase) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
}
}
updateUI();
// Event handlers
buyTowerBtn.down = function () {
if (currency >= 20) {
selectedTowerType = 'basic';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyArcherBtn.down = function () {
if (currency >= 75) {
selectedTowerType = 'archer';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyCannonBtn.down = function () {
if (currency >= 100) {
selectedTowerType = 'cannon';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyMagicBtn.down = function () {
if (currency >= 80) {
selectedTowerType = 'magic';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyLightningBtn.down = function () {
if (currency >= 120) {
selectedTowerType = 'lightning';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyFreezeBtn.down = function () {
if (currency >= 90) {
selectedTowerType = 'freeze';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyLaserBtn.down = function () {
if (currency >= 110) {
selectedTowerType = 'laser';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
upgradeTowerBtn.down = function () {
if (selectedTower && selectedTower.upgrade()) {
updateUI();
}
};
enhanceAllBtn.down = function () {
if (diamonds >= 10) {
diamonds -= 10;
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
tower.damage = Math.floor(tower.damage * 1.5);
tower.range = Math.floor(tower.range * 1.2);
// Visual enhancement effect
tween(tower, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0x00FFFF
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(tower, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 300
});
}
});
}
LK.effects.flashScreen(0x00FFFF, 500);
updateUI();
}
};
superDamageBtn.down = function () {
if (diamonds >= 15) {
diamonds -= 15;
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
tower.damage = Math.floor(tower.damage * 2.5);
// Super damage visual effect
tween(tower, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF6B35
}, {
duration: 500,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(tower, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 400
});
}
});
}
LK.effects.flashScreen(0xFF6B35, 800);
updateUI();
}
};
rapidFireBtn.down = function () {
if (diamonds >= 12) {
diamonds -= 12;
for (var i = 0; i < towers.length; i++) {
var tower = towers[i];
tower.fireRate = Math.max(10, Math.floor(tower.fireRate * 0.5));
// Rapid fire visual effect
tween(tower, {
tint: 0xFFFF00
}, {
duration: 200,
onFinish: function onFinish() {
tween(tower, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
}
LK.effects.flashScreen(0xFFFF00, 600);
updateUI();
}
};
buySuperBtn.down = function () {
if (currency >= 500) {
selectedTowerType = 'super';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyUltimateBtn.down = function () {
if (currency >= 2000) {
selectedTowerType = 'ultimategod';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
skipWaveBtn.down = function () {
if (diamonds >= 5 && waveActive) {
diamonds -= 5;
// Clear all enemies from the field
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Teleport animation for skip effect
tween(enemy, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1,
rotation: Math.PI * 2
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
if (enemy.parent) {
enemy.destroy();
}
}
});
enemies.splice(i, 1);
}
// Complete the wave immediately
waveActive = false;
wave++;
currency += 25;
diamonds += 5; // Award 5 diamonds per wave
nextWaveTimer = waveBreakDuration; // Start 3-second countdown
// Skip wave visual effect
LK.effects.flashScreen(0xFF00FF, 500);
updateUI();
}
};
buyStormBtn.down = function () {
if (currency >= 300) {
selectedTowerType = 'stormLightning';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyPlasmaBtn.down = function () {
if (currency >= 250) {
selectedTowerType = 'plasma';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyNuclearBtn.down = function () {
if (currency >= 50000) {
selectedTowerType = 'nuclear';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyQuantumBtn.down = function () {
if (currency >= 35000) {
selectedTowerType = 'quantum';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyTitanBtn.down = function () {
if (currency >= 100000) {
selectedTowerType = 'titan';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyVoidBtn.down = function () {
if (currency >= 75000) {
selectedTowerType = 'void';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyCelestialBtn.down = function () {
if (currency >= 150000) {
selectedTowerType = 'celestial';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyInfernalBtn.down = function () {
if (currency >= 120000) {
selectedTowerType = 'infernal';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
buyChronoBtn.down = function () {
if (currency >= 80000) {
selectedTowerType = 'chrono';
placingTower = true;
selectedTower = null;
hideAllRanges();
updateUI();
}
};
game.move = function (x, y, obj) {
if (draggingTower) {
draggingTower.x = x - dragOffset.x;
draggingTower.y = y - dragOffset.y;
// Visual feedback for valid/invalid placement
var gridPos = getGridPosition(draggingTower.x, draggingTower.y);
if (gridPos && gridPos.x >= 0 && gridPos.x < mapWidth && gridPos.y >= 0 && gridPos.y < mapHeight && grid[gridPos.x] && grid[gridPos.x][gridPos.y] && !grid[gridPos.x][gridPos.y].occupied && !grid[gridPos.x][gridPos.y].isPath) {
draggingTower.tint = 0x00FF00; // Green for valid
} else {
draggingTower.tint = 0xFF0000; // Red for invalid
}
}
};
game.down = function (x, y, obj) {
if (placingTower) {
var gridPos = getGridPosition(x, y);
if (gridPos) {
placeTower(gridPos.x, gridPos.y);
}
} else {
// Clear tower selection if clicking on empty space
var gridPos = getGridPosition(x, y);
if (gridPos && !grid[gridPos.x][gridPos.y].occupied) {
selectedTower = null;
hideAllRanges();
updateUI();
}
}
};
game.up = function (x, y, obj) {
if (draggingTower) {
var gridPos = getGridPosition(draggingTower.x, draggingTower.y);
var canPlace = gridPos && canPlaceTower(gridPos.x, gridPos.y);
if (canPlace) {
// Successfully place tower at new position
draggingTower.x = gridPos.x * gridSize + gridSize / 2;
draggingTower.y = gridPos.y * gridSize + gridSize / 2;
grid[gridPos.x][gridPos.y].occupied = true;
// Smooth placement animation
tween(draggingTower, {
alpha: 1,
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut
});
} else {
// Return to original position
tween(draggingTower, {
x: originalTowerPosition.x,
y: originalTowerPosition.y,
alpha: 1,
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 400,
easing: tween.elasticOut
});
// Restore original grid position
grid[originalGridPosition.x][originalGridPosition.y].occupied = true;
}
draggingTower = null;
}
};
// Main game loop
game.update = function () {
if (lives <= 0 && !gameOver) {
gameOver = true;
LK.showGameOver();
return;
}
if (wave > 31) {
// Show achievements before win screen
showCompletionAchievements();
// Delay showing win screen to allow achievements to display
LK.setTimeout(function () {
LK.showYouWin();
}, 8000);
return;
}
// Handle automatic wave progression
if (!waveActive && nextWaveTimer > 0) {
nextWaveTimer--;
if (nextWaveTimer <= 0) {
startWave();
}
}
// Start first wave immediately
if (wave === 1 && !waveActive && nextWaveTimer === 0) {
startWave();
}
// Spawn enemies during wave with decreasing interval
var spawnInterval = Math.max(45, 90 - wave * 2);
if (waveActive && LK.ticks % spawnInterval === 0) {
spawnEnemy();
}
// Clean up bullets that hit targets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.hasHit || !bullet.target || bullet.target.isDead) {
bullet.destroy();
bullets.splice(i, 1);
}
}
// Add breathing animation to towers when not firing
for (var t = 0; t < towers.length; t++) {
var tower = towers[t];
if (LK.ticks - tower.lastFire > 120) {
// If haven't fired for 2 seconds
if (!tower.isBreathing) {
tower.isBreathing = true;
var breatheScale = 1 + Math.sin(LK.ticks * 0.05) * 0.05;
tween(tower, {
scaleX: breatheScale,
scaleY: breatheScale
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tower.isBreathing = false;
}
});
}
} else {
tower.isBreathing = false;
}
}
checkWaveComplete();
// Check for achievement unlocks during gameplay
var newUnlocks = checkAchievements();
if (newUnlocks.length > 0) {
// Show achievement notifications during gameplay (except completion ones)
for (var i = 0; i < newUnlocks.length; i++) {
if (newUnlocks[i].id !== 'first_victory' && newUnlocks[i].id !== 'perfect_defense' && newUnlocks[i].id !== 'ultimate_warrior') {
showAchievementUnlock(newUnlocks[i]);
}
}
}
};