/**** * 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; // Set drag offset to 0 so tower follows mouse exactly dragOffset.x = 0; dragOffset.y = 0; 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 = []; // Create a longer, winding path across the map var pathCoords = [ // Starting from left side { x: 0, y: 12 }, { x: 1, y: 12 }, { x: 2, y: 12 }, { x: 3, y: 12 }, { x: 4, y: 12 }, // First curve upward { x: 5, y: 11 }, { x: 6, y: 10 }, { x: 7, y: 9 }, { x: 8, y: 8 }, { x: 9, y: 7 }, // Horizontal section { x: 10, y: 7 }, { x: 11, y: 7 }, { x: 12, y: 7 }, { x: 13, y: 7 }, // Second curve downward { x: 14, y: 8 }, { x: 15, y: 9 }, { x: 16, y: 10 }, { x: 17, y: 11 }, { x: 18, y: 12 }, // Continue to the right { x: 19, y: 12 }]; // Create smooth dirt path segments for (var i = 0; i < pathCoords.length; i++) { var coord = pathCoords[i]; if (coord.x < mapWidth && coord.y < mapHeight) { // Mark main path grid[coord.x][coord.y].isPath = true; // Create wider dirt path 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; } if (coord.x > 0) { grid[coord.x - 1][coord.y].isPath = true; } if (coord.x < mapWidth - 1) { grid[coord.x + 1][coord.y].isPath = true; } enemyPath.push({ x: coord.x * gridSize + gridSize / 2, y: coord.y * gridSize + gridSize / 2 }); } } } function drawMap() { // Draw grass background first for (var x = 0; x < mapWidth; x++) { for (var y = 0; y < mapHeight; y++) { var tile = LK.getAsset('grassTile', { x: x * gridSize, y: y * gridSize }); game.addChild(tile); } } // Draw seamless dirt path on top for (var x = 0; x < mapWidth; x++) { for (var y = 0; y < mapHeight; y++) { if (grid[x][y].isPath) { var pathTile = LK.getAsset('pathTile', { x: x * gridSize, y: y * gridSize }); pathTile.tint = 0x8B4513; // Brown dirt color game.addChild(pathTile); } } } } 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) { // Make tower follow mouse cursor exactly draggingTower.x = x; draggingTower.y = 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]); } } } };
===================================================================
--- original.js
+++ change.js
@@ -852,11 +852,11 @@
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;
+ // Set drag offset to 0 so tower follows mouse exactly
+ dragOffset.x = 0;
+ dragOffset.y = 0;
originalTowerPosition.x = self.x;
originalTowerPosition.y = self.y;
// Find original grid position
var gridPos = getGridPosition(self.x, self.y);
@@ -3910,9 +3910,12 @@
}
}
function createPath() {
enemyPath = [];
- var pathCoords = [{
+ // Create a longer, winding path across the map
+ var pathCoords = [
+ // Starting from left side
+ {
x: 0,
y: 12
}, {
x: 1,
@@ -3925,112 +3928,110 @@
y: 12
}, {
x: 4,
y: 12
- }, {
+ },
+ // First curve upward
+ {
x: 5,
- y: 12
- }, {
- x: 6,
- y: 12
- }, {
- x: 7,
- y: 12
- }, {
- x: 8,
- y: 12
- }, {
- x: 8,
y: 11
}, {
- x: 8,
+ x: 6,
y: 10
}, {
- x: 8,
+ x: 7,
y: 9
}, {
x: 8,
y: 8
}, {
x: 9,
- y: 8
- }, {
+ y: 7
+ },
+ // Horizontal section
+ {
x: 10,
- y: 8
+ y: 7
}, {
x: 11,
- y: 8
+ y: 7
}, {
x: 12,
- y: 8
+ y: 7
}, {
- x: 12,
- y: 9
- }, {
- x: 12,
- y: 10
- }, {
- x: 12,
- y: 11
- }, {
- x: 12,
- y: 12
- }, {
x: 13,
- y: 12
- }, {
+ y: 7
+ },
+ // Second curve downward
+ {
x: 14,
- y: 12
+ y: 8
}, {
x: 15,
- y: 12
+ y: 9
}, {
x: 16,
- y: 12
+ y: 10
}, {
x: 17,
- y: 12
+ y: 11
}, {
x: 18,
y: 12
- }, {
+ },
+ // Continue to the right
+ {
x: 19,
y: 12
}];
+ // Create smooth dirt path segments
for (var i = 0; i < pathCoords.length; i++) {
var coord = pathCoords[i];
if (coord.x < mapWidth && coord.y < mapHeight) {
+ // Mark main path
grid[coord.x][coord.y].isPath = true;
- // Also mark adjacent tiles as path to make path wider
+ // Create wider dirt path
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;
}
+ if (coord.x > 0) {
+ grid[coord.x - 1][coord.y].isPath = true;
+ }
+ if (coord.x < mapWidth - 1) {
+ grid[coord.x + 1][coord.y].isPath = true;
+ }
enemyPath.push({
x: coord.x * gridSize + gridSize / 2,
y: coord.y * gridSize + gridSize / 2
});
}
}
}
function drawMap() {
+ // Draw grass background first
for (var x = 0; x < mapWidth; x++) {
for (var y = 0; y < mapHeight; y++) {
- var tile;
+ var tile = LK.getAsset('grassTile', {
+ x: x * gridSize,
+ y: y * gridSize
+ });
+ game.addChild(tile);
+ }
+ }
+ // Draw seamless dirt path on top
+ for (var x = 0; x < mapWidth; x++) {
+ for (var y = 0; y < mapHeight; y++) {
if (grid[x][y].isPath) {
- tile = LK.getAsset('pathTile', {
+ var pathTile = LK.getAsset('pathTile', {
x: x * gridSize,
y: y * gridSize
});
- } else {
- tile = LK.getAsset('grassTile', {
- x: x * gridSize,
- y: y * gridSize
- });
+ pathTile.tint = 0x8B4513; // Brown dirt color
+ game.addChild(pathTile);
}
- game.addChild(tile);
}
}
}
function drawBase() {
@@ -5535,10 +5536,11 @@
}
};
game.move = function (x, y, obj) {
if (draggingTower) {
- draggingTower.x = x - dragOffset.x;
- draggingTower.y = y - dragOffset.y;
+ // Make tower follow mouse cursor exactly
+ draggingTower.x = x;
+ draggingTower.y = 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