/****
* 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