User prompt
her wavede 5 elmas kazanalım
User prompt
oyuna boss ekle wave 10 da boss gelsin ve yeni para birimi elmas gelsin elmas sayesinde bütün towerleri güçlendirebilelim ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yeni kaleler ekle ve daha çok animasyon ve güçlendirme ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(enemyGraphics, {' Line Number: 207 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'toGlobal')' in or related to this line: 'var globalPos = obj.parent.toGlobal(obj.position);' Line Number: 364
User prompt
başta 390 altın ile başlayalım ve kuleleri tıklama ile taşıma ekle
User prompt
kule taşıma ve daha animasyon ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yeni kaleler ekle şavasçılar
User prompt
geliştir fuc king
Code edit (1 edits merged)
Please save this source code
User prompt
Tower Defense 3D
Initial prompt
tower defense 3d
/**** * 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]);
}
}
}
};