/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Bullet = Container.expand(function (startX, startY, targetEnemy, damage, speed) {
	var self = Container.call(this);
	self.targetEnemy = targetEnemy;
	self.damage = damage || 10;
	self.speed = speed || 5;
	self.x = startX;
	self.y = startY;
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		// Handle enemy bullets targeting towers
		if (self.isEnemyBullet) {
			if (!self.targetEnemy || !self.targetEnemy.parent) {
				self.destroy();
				return;
			}
			var dx = self.targetEnemy.x - self.x;
			var dy = self.targetEnemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < self.speed) {
				// Damage the tower instead of an enemy
				var tower = self.targetEnemy;
				if (tower.takeDamage) {
					tower.takeDamage(self.damage);
				}
				self.destroy();
			} else {
				var angle = Math.atan2(dy, dx);
				self.x += Math.cos(angle) * self.speed;
				self.y += Math.sin(angle) * self.speed;
			}
			return;
		}
		// Original enemy targeting logic
		if (!self.targetEnemy || !self.targetEnemy.parent) {
			self.destroy();
			return;
		}
		var dx = self.targetEnemy.x - self.x;
		var dy = self.targetEnemy.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance < self.speed) {
			// Special handling for missiles hitting immune, flying, or tank enemies - destroy instantly
			if (self.type === 'slow' && (self.targetEnemy.isImmune || self.targetEnemy.isFlying || self.targetEnemy.type === 'tank')) {
				// Instantly destroy immune, flying, or tank enemy regardless of health
				self.targetEnemy.health = 0;
			} else if (self.type === 'tank' && (self.targetEnemy.isImmune || self.targetEnemy.isFlying || self.targetEnemy.type === 'tank' || self.targetEnemy.isBoss)) {
				// Tank weapons instantly destroy immune, flying, tank, and boss enemies
				self.targetEnemy.health = 0;
			} else {
				// Apply damage to target enemy normally
				self.targetEnemy.health -= self.damage;
				if (self.targetEnemy.health <= 0) {
					self.targetEnemy.health = 0;
				} else {
					self.targetEnemy.healthBar.width = self.targetEnemy.health / self.targetEnemy.maxHealth * 70;
				}
			}
			// Create explosion effect for missile hits
			if (self.type === 'slow') {
				// Store explosion position for area damage calculation
				var explosionX = self.targetEnemy.x;
				var explosionY = self.targetEnemy.y;
				// Increased explosion radius to destroy nearby enemies (especially fast enemies)
				var explosionRadius = CELL_SIZE * 2.5; // Increased from smaller radius to 2.5 cells
				// Apply area damage to all enemies within explosion radius
				for (var i = 0; i < enemies.length; i++) {
					var nearbyEnemy = enemies[i];
					if (nearbyEnemy !== self.targetEnemy) {
						var dx = nearbyEnemy.x - explosionX;
						var dy = nearbyEnemy.y - explosionY;
						var distance = Math.sqrt(dx * dx + dy * dy);
						if (distance <= explosionRadius) {
							// Instantly destroy fast enemies within explosion radius
							if (nearbyEnemy.type === 'fast') {
								nearbyEnemy.health = 0;
							} else {
								// Apply significant damage to other enemy types
								nearbyEnemy.health -= self.damage * 1.5; // 1.5x damage for area effect
								if (nearbyEnemy.health <= 0) {
									nearbyEnemy.health = 0;
								} else {
									nearbyEnemy.healthBar.width = nearbyEnemy.health / nearbyEnemy.maxHealth * 70;
								}
							}
							// Create individual explosion effect for each affected enemy
							var nearbyExplosion = new EffectIndicator(nearbyEnemy.x, nearbyEnemy.y, 'splash');
							nearbyExplosion.children[0].tint = 0xFF6600; // Orange-red for area damage
							nearbyExplosion.children[0].width = nearbyExplosion.children[0].height = CELL_SIZE * 1.5;
							nearbyExplosion.alpha = 0.8;
							nearbyExplosion.scaleX = 0.2;
							nearbyExplosion.scaleY = 0.2;
							game.addChild(nearbyExplosion);
							// Animate nearby explosion
							tween(nearbyExplosion, {
								scaleX: 1.2,
								scaleY: 1.2,
								alpha: 0.6
							}, {
								duration: 100,
								easing: tween.easeOut,
								onFinish: function onFinish() {
									tween(nearbyExplosion, {
										scaleX: 1.8,
										scaleY: 1.8,
										alpha: 0
									}, {
										duration: 200,
										easing: tween.easeIn,
										onFinish: function onFinish() {
											nearbyExplosion.destroy();
										}
									});
								}
							});
						}
					}
				}
				// Create MASSIVE tank weapon explosion with devastating area damage
				if (self.type === 'tank') {
					// Store explosion position for area damage calculation
					var explosionX = self.targetEnemy.x;
					var explosionY = self.targetEnemy.y;
					// MASSIVE explosion radius - much larger than missiles for devastating effect
					var explosionRadius = CELL_SIZE * 4.0; // 4 cell radius for tank weapons (60% larger than missiles)
					// Apply devastating area damage to all enemies within explosion radius
					for (var i = 0; i < enemies.length; i++) {
						var nearbyEnemy = enemies[i];
						if (nearbyEnemy !== self.targetEnemy) {
							var dx = nearbyEnemy.x - explosionX;
							var dy = nearbyEnemy.y - explosionY;
							var distance = Math.sqrt(dx * dx + dy * dy);
							if (distance <= explosionRadius) {
								// Tank weapons cause MASSIVE damage - instantly destroy most enemies
								if (nearbyEnemy.type === 'fast' || nearbyEnemy.type === 'flying' || nearbyEnemy.isFlying) {
									// Instantly destroy fast and flying enemies
									nearbyEnemy.health = 0;
								} else if (nearbyEnemy.type === 'immune' || nearbyEnemy.isImmune) {
									// Tank weapons instantly destroy immune enemies
									nearbyEnemy.health = 0;
								} else if (nearbyEnemy.type === 'tank') {
									// Tank weapons instantly destroy tank enemies
									nearbyEnemy.health = 0;
								} else if (nearbyEnemy.isBoss) {
									// Tank weapons instantly destroy boss enemies
									nearbyEnemy.health = 0;
								} else {
									// Massive damage to other enemy types
									nearbyEnemy.health -= self.damage * 3.0; // 3x damage for devastating effect
									if (nearbyEnemy.health <= 0) {
										nearbyEnemy.health = 0;
									} else {
										nearbyEnemy.healthBar.width = nearbyEnemy.health / nearbyEnemy.maxHealth * 70;
									}
								}
								// Create individual massive explosion effect for each affected enemy
								var nearbyExplosion = new EffectIndicator(nearbyEnemy.x, nearbyEnemy.y, 'splash');
								nearbyExplosion.children[0].tint = 0x8B4513; // Dark brown for tank explosion
								nearbyExplosion.children[0].width = nearbyExplosion.children[0].height = CELL_SIZE * 2.0; // Larger than missile explosions
								nearbyExplosion.alpha = 1.0;
								nearbyExplosion.scaleX = 0.3;
								nearbyExplosion.scaleY = 0.3;
								game.addChild(nearbyExplosion);
								// Animate massive nearby explosion
								tween(nearbyExplosion, {
									scaleX: 1.8,
									scaleY: 1.8,
									alpha: 0.8
								}, {
									duration: 150,
									easing: tween.easeOut,
									onFinish: function onFinish() {
										tween(nearbyExplosion, {
											scaleX: 2.5,
											scaleY: 2.5,
											alpha: 0
										}, {
											duration: 300,
											easing: tween.easeIn,
											onFinish: function onFinish() {
												nearbyExplosion.destroy();
											}
										});
									}
								});
							}
						}
					}
					// Create ULTRA-MASSIVE tank weapon explosion with enhanced visual effects
					// Stage 1: Initial massive impact flash - GIGANTIC white flash
					var impactFlash = new EffectIndicator(explosionX, explosionY, 'splash');
					impactFlash.children[0].tint = 0xFFFFFF; // Bright white impact flash
					impactFlash.children[0].width = impactFlash.children[0].height = CELL_SIZE * 6.0; // ENORMOUS initial flash
					impactFlash.alpha = 1;
					impactFlash.scaleX = 0.1;
					impactFlash.scaleY = 0.1;
					game.addChild(impactFlash);
					// Ultra-fast bright flash expansion
					tween(impactFlash, {
						scaleX: 8.0,
						// Much bigger than missile explosions
						scaleY: 8.0,
						alpha: 0
					}, {
						duration: 100,
						easing: tween.easeOut
					});
					// Stage 2: MASSIVE main tank explosion fireball - dark brown/orange core
					var mainExplosion = new EffectIndicator(explosionX, explosionY, 'splash');
					mainExplosion.children[0].tint = 0x8B4513; // Dark brown for tank explosion
					mainExplosion.children[0].width = mainExplosion.children[0].height = CELL_SIZE * 10.0; // ENORMOUS main explosion
					mainExplosion.alpha = 1;
					mainExplosion.scaleX = 0.2;
					mainExplosion.scaleY = 0.2;
					game.addChild(mainExplosion);
					// Dramatic MASSIVE fireball expansion
					tween(mainExplosion, {
						scaleX: 6.5,
						// Bigger than missile explosions
						scaleY: 6.5,
						alpha: 0.95
					}, {
						duration: 300,
						easing: tween.bounceOut,
						onFinish: function onFinish() {
							tween(mainExplosion, {
								scaleX: 10.0,
								// ENORMOUS final scale
								scaleY: 10.0,
								alpha: 0
							}, {
								duration: 800,
								easing: tween.easeIn,
								onFinish: function onFinish() {
									mainExplosion.destroy();
								}
							});
						}
					});
					// Stage 3: Create QUADRUPLE the explosion particles for MASSIVE debris effect
					for (var particleIndex = 0; particleIndex < 32; particleIndex++) {
						// More particles than missiles
						var explosionParticle = new EffectIndicator(explosionX, explosionY, 'splash');
						// Tank explosion colors - browns and oranges
						var particleColors = [0x8B4513, 0xA0522D, 0xD2691E, 0xFF8C00, 0xCD853F, 0xDEB887, 0x654321, 0x8B7355];
						explosionParticle.children[0].tint = particleColors[particleIndex % particleColors.length];
						explosionParticle.children[0].width = explosionParticle.children[0].height = CELL_SIZE * (2.2 + Math.random() * 1.8); // Bigger particles
						explosionParticle.alpha = 0.95;
						explosionParticle.scaleX = 0.6 + Math.random() * 0.5;
						explosionParticle.scaleY = 0.6 + Math.random() * 0.5;
						// Random direction for particle scatter with ULTRA-LONG distance
						var particleAngle = particleIndex / 32 * Math.PI * 2 + (Math.random() - 0.5) * 0.8;
						var particleDistance = CELL_SIZE * (4.5 + Math.random() * 3.5); // Ultra-far particle scatter
						var targetX = explosionX + Math.cos(particleAngle) * particleDistance;
						var targetY = explosionY + Math.sin(particleAngle) * particleDistance;
						game.addChild(explosionParticle);
						// Animate particles flying outward
						tween(explosionParticle, {
							x: targetX,
							y: targetY,
							scaleX: 4.0 + Math.random() * 1.5,
							// Much bigger final scale
							scaleY: 4.0 + Math.random() * 1.5,
							alpha: 0.8
						}, {
							duration: 400 + Math.random() * 300,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								tween(explosionParticle, {
									scaleX: 0.3,
									scaleY: 0.3,
									alpha: 0
								}, {
									duration: 500 + Math.random() * 250,
									easing: tween.easeIn,
									onFinish: function onFinish() {
										explosionParticle.destroy();
									}
								});
							}
						});
					}
					// Stage 4: QUINTUPLE shockwave rings for tank weapons
					var primaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
					primaryShockwave.children[0].tint = 0xDEB887; // Light brown shockwave
					primaryShockwave.children[0].alpha = 0.8;
					primaryShockwave.children[0].width = primaryShockwave.children[0].height = CELL_SIZE * 2.0;
					primaryShockwave.alpha = 1.0;
					game.addChild(primaryShockwave);
					// MASSIVE expanding primary shockwave
					tween(primaryShockwave, {
						scaleX: 15.0,
						// Bigger than missile shockwaves
						scaleY: 15.0,
						alpha: 0
					}, {
						duration: 900,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							primaryShockwave.destroy();
						}
					});
					// Multiple additional shockwaves for devastating effect
					for (var shockIndex = 1; shockIndex <= 4; shockIndex++) {
						var additionalShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
						additionalShockwave.children[0].tint = 0x8B7355; // Darker brown shockwave
						additionalShockwave.children[0].alpha = 0.6 - shockIndex * 0.1;
						additionalShockwave.children[0].width = additionalShockwave.children[0].height = CELL_SIZE * (2.0 - shockIndex * 0.2);
						additionalShockwave.alpha = 0.8 - shockIndex * 0.1;
						game.addChild(additionalShockwave);
						// Delayed massive shockwaves
						tween(additionalShockwave, {
							scaleX: 16.0 + shockIndex * 1.0,
							scaleY: 16.0 + shockIndex * 1.0,
							alpha: 0
						}, {
							duration: 1000 + shockIndex * 100,
							delay: shockIndex * 200,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								additionalShockwave.destroy();
							}
						});
					}
					// Stage 5: MASSIVE lingering smoke cloud
					var smokeCloud = new EffectIndicator(explosionX, explosionY, 'splash');
					smokeCloud.children[0].tint = 0x696969; // Dark gray smoke
					smokeCloud.children[0].alpha = 0.7;
					smokeCloud.children[0].width = smokeCloud.children[0].height = CELL_SIZE * 8.0; // Bigger smoke cloud
					smokeCloud.alpha = 0;
					smokeCloud.scaleX = 1.2;
					smokeCloud.scaleY = 1.2;
					game.addChild(smokeCloud);
					// Delayed massive smoke appearance
					tween(smokeCloud, {
						alpha: 1.0,
						scaleX: 8.0,
						scaleY: 8.0
					}, {
						duration: 500,
						delay: 500,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							// Smoke slowly dissipates over very long time
							tween(smokeCloud, {
								alpha: 0,
								scaleX: 14.0,
								// ENORMOUS final scale
								scaleY: 14.0
							}, {
								duration: 2000,
								// Very long dissipation time
								easing: tween.easeIn,
								onFinish: function onFinish() {
									smokeCloud.destroy();
								}
							});
						}
					});
				}
				// Create ULTRA-MASSIVE spectacular multi-stage missile explosion with ENHANCED particle effects
				// Stage 1: Initial impact flash - ULTRA bright white flash (GIGANTIC)
				var impactFlash = new EffectIndicator(explosionX, explosionY, 'splash');
				impactFlash.children[0].tint = 0xFFFFFF; // Bright white impact flash
				impactFlash.children[0].width = impactFlash.children[0].height = CELL_SIZE * 5.0; // GIGANTIC initial flash (increased from 3.5)
				impactFlash.alpha = 1;
				impactFlash.scaleX = 0.1;
				impactFlash.scaleY = 0.1;
				game.addChild(impactFlash);
				// Ultra-fast bright flash expansion (GIGANTIC SCALE)
				tween(impactFlash, {
					scaleX: 7.0,
					// MUCH bigger scale (increased from 4.5)
					scaleY: 7.0,
					alpha: 0
				}, {
					duration: 120,
					easing: tween.easeOut
				});
				// Stage 2: ULTRA-MASSIVE main explosion fireball - orange/red core (ENORMOUS)
				var mainExplosion = new EffectIndicator(explosionX, explosionY, 'splash');
				mainExplosion.children[0].tint = 0xFF4500; // Orange-red fireball
				mainExplosion.children[0].width = mainExplosion.children[0].height = CELL_SIZE * 8.0; // ENORMOUS main explosion (increased from 6.0)
				mainExplosion.alpha = 1;
				mainExplosion.scaleX = 0.2;
				mainExplosion.scaleY = 0.2;
				game.addChild(mainExplosion);
				// Dramatic ULTRA-MASSIVE fireball expansion with bounce effect
				tween(mainExplosion, {
					scaleX: 5.5,
					// Much bigger scale (increased from 3.8)
					scaleY: 5.5,
					alpha: 0.95
				}, {
					duration: 250,
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						tween(mainExplosion, {
							scaleX: 8.5,
							// ENORMOUS final scale (increased from 6.0)
							scaleY: 8.5,
							alpha: 0
						}, {
							duration: 700,
							easing: tween.easeIn,
							onFinish: function onFinish() {
								mainExplosion.destroy();
							}
						});
					}
				});
				// Stage 3: Create TRIPLE the explosion particles for ULTRA-MASSIVE debris effect (TRIPLED)
				for (var particleIndex = 0; particleIndex < 24; particleIndex++) {
					// Increased from 16 to 24
					var explosionParticle = new EffectIndicator(explosionX, explosionY, 'splash');
					// Vary particle colors for realistic explosion with MORE variety
					var particleColors = [0xFF6600, 0xFF4500, 0xFF8800, 0xFFAA00, 0xFF2200, 0xFFCC00, 0xFF3300, 0xFFDD00];
					explosionParticle.children[0].tint = particleColors[particleIndex % particleColors.length];
					explosionParticle.children[0].width = explosionParticle.children[0].height = CELL_SIZE * (1.8 + Math.random() * 1.5); // MUCH bigger particles (increased from 1.2 + 1.0)
					explosionParticle.alpha = 0.9;
					explosionParticle.scaleX = 0.5 + Math.random() * 0.4;
					explosionParticle.scaleY = 0.5 + Math.random() * 0.4;
					// Random direction for particle scatter with ULTRA-LONG distance
					var particleAngle = particleIndex / 24 * Math.PI * 2 + (Math.random() - 0.5) * 0.8;
					var particleDistance = CELL_SIZE * (3.5 + Math.random() * 3.0); // ULTRA-FAR particle scatter (increased from 2.5 + 2.0)
					var targetX = explosionX + Math.cos(particleAngle) * particleDistance;
					var targetY = explosionY + Math.sin(particleAngle) * particleDistance;
					game.addChild(explosionParticle);
					// Animate particles flying outward with ULTRA-enhanced physics
					tween(explosionParticle, {
						x: targetX,
						y: targetY,
						scaleX: 3.5 + Math.random() * 1.2,
						// Much bigger final scale (increased from 2.5 + 0.8)
						scaleY: 3.5 + Math.random() * 1.2,
						alpha: 0.7
					}, {
						duration: 350 + Math.random() * 250,
						// Longer duration
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(explosionParticle, {
								scaleX: 0.2,
								scaleY: 0.2,
								alpha: 0
							}, {
								duration: 450 + Math.random() * 200,
								// Longer fade duration
								easing: tween.easeIn,
								onFinish: function onFinish() {
									explosionParticle.destroy();
								}
							});
						}
					});
				}
				// Stage 4: ULTRA-MASSIVE enhanced shockwave with QUADRUPLE rings
				var primaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
				primaryShockwave.children[0].tint = 0xFFDDDD; // Light pink shockwave
				primaryShockwave.children[0].alpha = 0.7;
				primaryShockwave.children[0].width = primaryShockwave.children[0].height = CELL_SIZE * 1.5; // Bigger base
				primaryShockwave.alpha = 0.9;
				game.addChild(primaryShockwave);
				// ULTRA-HUGE expanding primary shockwave
				tween(primaryShockwave, {
					scaleX: 12.0,
					// ENORMOUS scale (increased from 8.5)
					scaleY: 12.0,
					alpha: 0
				}, {
					duration: 800,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						primaryShockwave.destroy();
					}
				});
				// Secondary ULTRA-MASSIVE shockwave
				var secondaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
				secondaryShockwave.children[0].tint = 0xFFFFFF; // White secondary wave
				secondaryShockwave.children[0].alpha = 0.5;
				secondaryShockwave.children[0].width = secondaryShockwave.children[0].height = CELL_SIZE * 1.0;
				secondaryShockwave.alpha = 0.8;
				game.addChild(secondaryShockwave);
				// Delayed ULTRA-MASSIVE secondary shockwave
				tween(secondaryShockwave, {
					scaleX: 13.0,
					// ENORMOUS scale (increased from 9.0)
					scaleY: 13.0,
					alpha: 0
				}, {
					duration: 900,
					delay: 150,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						secondaryShockwave.destroy();
					}
				});
				// Third shockwave for QUADRUPLE-ring ULTRA-MASSIVE effect
				var tertiaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
				tertiaryShockwave.children[0].tint = 0xFFAAAA; // Light red tertiary wave
				tertiaryShockwave.children[0].alpha = 0.3;
				tertiaryShockwave.children[0].width = tertiaryShockwave.children[0].height = CELL_SIZE * 0.8;
				tertiaryShockwave.alpha = 0.7;
				game.addChild(tertiaryShockwave);
				// Third delayed ULTRA-MASSIVE shockwave
				tween(tertiaryShockwave, {
					scaleX: 14.0,
					// ENORMOUS scale (increased from 10.0)
					scaleY: 14.0,
					alpha: 0
				}, {
					duration: 1000,
					delay: 300,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tertiaryShockwave.destroy();
					}
				});
				// Fourth shockwave for QUADRUPLE-ring effect (NEW!)
				var quaternaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
				quaternaryShockwave.children[0].tint = 0xFFCCCC; // Very light pink quaternary wave
				quaternaryShockwave.children[0].alpha = 0.2;
				quaternaryShockwave.children[0].width = quaternaryShockwave.children[0].height = CELL_SIZE * 0.6;
				quaternaryShockwave.alpha = 0.6;
				game.addChild(quaternaryShockwave);
				// Fourth delayed ULTRA-MASSIVE shockwave
				tween(quaternaryShockwave, {
					scaleX: 15.0,
					// ULTRA-ENORMOUS scale
					scaleY: 15.0,
					alpha: 0
				}, {
					duration: 1100,
					delay: 450,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						quaternaryShockwave.destroy();
					}
				});
				// Stage 5: ULTRA-MASSIVE smoke cloud effect - ENORMOUS and lingers much longer
				var smokeCloud = new EffectIndicator(explosionX, explosionY, 'splash');
				smokeCloud.children[0].tint = 0x666666; // Dark gray smoke
				smokeCloud.children[0].alpha = 0.6;
				smokeCloud.children[0].width = smokeCloud.children[0].height = CELL_SIZE * 6.0; // ENORMOUS smoke cloud (increased from 4.0)
				smokeCloud.alpha = 0;
				smokeCloud.scaleX = 1.0;
				smokeCloud.scaleY = 1.0;
				game.addChild(smokeCloud);
				// Delayed ULTRA-MASSIVE smoke appearance that grows slowly and lingers
				tween(smokeCloud, {
					alpha: 0.9,
					scaleX: 6.0,
					// Bigger initial expansion (increased from 4.0)
					scaleY: 6.0
				}, {
					duration: 450,
					delay: 400,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						// Smoke slowly dissipates over ULTRA-LONG time
						tween(smokeCloud, {
							alpha: 0,
							scaleX: 10.0,
							// ENORMOUS final scale (increased from 7.0)
							scaleY: 10.0
						}, {
							duration: 1500,
							// ULTRA-LONG dissipation time (increased from 1200)
							easing: tween.easeIn,
							onFinish: function onFinish() {
								smokeCloud.destroy();
							}
						});
					}
				});
			}
			// Apply special effects based on bullet type
			if (self.type === 'flamethrower') {
				// Create visual flame effect with enhanced animation
				var flameEffect = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'flamethrower');
				game.addChild(flameEffect);
				// Apply burning effect to target enemy
				if (!self.targetEnemy.isImmune) {
					self.targetEnemy.burning = true;
					self.targetEnemy.burnDamage = self.damage * 0.3; // 30% of original damage per tick
					self.targetEnemy.burnDuration = 180; // 3 seconds at 60 FPS
				}
				// Flame damage to enemies in a cone behind the target
				var coneRange = CELL_SIZE * 1.2;
				var targetAngle = Math.atan2(self.targetEnemy.y - self.y, self.targetEnemy.x - self.x);
				for (var i = 0; i < enemies.length; i++) {
					var otherEnemy = enemies[i];
					if (otherEnemy !== self.targetEnemy) {
						var flameDx = otherEnemy.x - self.targetEnemy.x;
						var flameDy = otherEnemy.y - self.targetEnemy.y;
						var flameDistance = Math.sqrt(flameDx * flameDx + flameDy * flameDy);
						var enemyAngle = Math.atan2(flameDy, flameDx);
						var angleDiff = Math.abs(enemyAngle - targetAngle);
						// Normalize angle difference
						while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
						while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
						angleDiff = Math.abs(angleDiff);
						// Check if enemy is within cone (45 degrees = PI/4 radians)
						if (flameDistance <= coneRange && angleDiff <= Math.PI / 4) {
							// Apply flame damage (40% of original damage)
							otherEnemy.health -= self.damage * 0.4;
							if (otherEnemy.health <= 0) {
								otherEnemy.health = 0;
							} else {
								otherEnemy.healthBar.width = otherEnemy.health / otherEnemy.maxHealth * 70;
							}
							// Apply burning effect
							if (!otherEnemy.isImmune) {
								otherEnemy.burning = true;
								otherEnemy.burnDamage = self.damage * 0.2;
								otherEnemy.burnDuration = 120; // 2 seconds for cone targets
							}
						}
					}
				}
			} else if (self.type === 'slow') {
				// Prevent slow effect on immune enemies
				if (!self.targetEnemy.isImmune) {
					// Create visual slow effect
					var slowEffect = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'slow');
					game.addChild(slowEffect);
					// Apply slow effect
					// Make slow percentage scale with tower level (default 50%, up to 80% at max level)
					var slowPct = 0.5;
					if (self.sourceTowerLevel !== undefined) {
						// Scale: 50% at level 1, 60% at 2, 65% at 3, 70% at 4, 75% at 5, 80% at 6
						var slowLevels = [0.5, 0.6, 0.65, 0.7, 0.75, 0.8];
						var idx = Math.max(0, Math.min(5, self.sourceTowerLevel - 1));
						slowPct = slowLevels[idx];
					}
					if (!self.targetEnemy.slowed) {
						self.targetEnemy.originalSpeed = self.targetEnemy.speed;
						self.targetEnemy.speed *= 1 - slowPct; // Slow by X%
						self.targetEnemy.slowed = true;
						self.targetEnemy.slowDuration = 180; // 3 seconds at 60 FPS
					} else {
						self.targetEnemy.slowDuration = 180; // Reset duration
					}
				}
			} else if (self.type === 'poison') {
				// Prevent poison effect on immune enemies
				if (!self.targetEnemy.isImmune) {
					// Create visual poison effect
					var poisonEffect = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'poison');
					game.addChild(poisonEffect);
					// Apply poison effect
					self.targetEnemy.poisoned = true;
					self.targetEnemy.poisonDamage = self.damage * 0.2; // 20% of original damage per tick
					self.targetEnemy.poisonDuration = 300; // 5 seconds at 60 FPS
				}
			} else if (self.type === 'sniper') {
				// Create visual critical hit effect for sniper
				var sniperEffect = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'sniper');
				game.addChild(sniperEffect);
			}
			self.destroy();
		} else {
			var angle = Math.atan2(dy, dx);
			// Apply spread angle for machine gun bullets
			if (self.type === 'trap' && self.spreadAngle !== undefined) {
				angle += self.spreadAngle;
			}
			// Rotate missile asset to face target direction
			if (self.type === 'slow' && self.children.length > 0) {
				var missileGraphics = self.children[0];
				if (missileGraphics.targetRotation === undefined) {
					missileGraphics.targetRotation = angle;
					missileGraphics.rotation = angle;
				} else {
					// Only rotate if angle difference is significant
					if (Math.abs(angle - missileGraphics.targetRotation) > 0.1) {
						tween.stop(missileGraphics, {
							rotation: true
						});
						// Calculate shortest rotation path
						var currentRotation = missileGraphics.rotation;
						var angleDiff = angle - currentRotation;
						// Normalize angle difference to -PI to PI range
						while (angleDiff > Math.PI) {
							angleDiff -= Math.PI * 2;
						}
						while (angleDiff < -Math.PI) {
							angleDiff += Math.PI * 2;
						}
						missileGraphics.targetRotation = angle;
						tween(missileGraphics, {
							rotation: currentRotation + angleDiff
						}, {
							duration: 100,
							easing: tween.easeOut
						});
					}
				}
			}
			self.x += Math.cos(angle) * self.speed;
			self.y += Math.sin(angle) * self.speed;
		}
	};
	return self;
});
// DebugCell class removed
var EffectIndicator = Container.expand(function (x, y, type) {
	var self = Container.call(this);
	self.x = x;
	self.y = y;
	var effectGraphics = self.attachAsset('rangeCircle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	effectGraphics.blendMode = 1;
	switch (type) {
		case 'splash':
			effectGraphics.tint = 0x33CC00;
			effectGraphics.width = effectGraphics.height = CELL_SIZE * 1.5;
			break;
		case 'slow':
			effectGraphics.tint = 0x9900FF;
			effectGraphics.width = effectGraphics.height = CELL_SIZE;
			break;
		case 'poison':
			effectGraphics.tint = 0x00FFAA;
			effectGraphics.width = effectGraphics.height = CELL_SIZE;
			break;
		case 'sniper':
			effectGraphics.tint = 0xFF5500;
			effectGraphics.width = effectGraphics.height = CELL_SIZE;
			break;
		case 'flamethrower':
			effectGraphics.tint = 0xFF4500;
			effectGraphics.width = CELL_SIZE * 1.5;
			effectGraphics.height = CELL_SIZE * 0.8; // Elongated flame effect
			break;
	}
	effectGraphics.alpha = 0.7;
	self.alpha = 0;
	// Animate the effect
	tween(self, {
		alpha: 0.8,
		scaleX: 1.5,
		scaleY: 1.5
	}, {
		duration: 200,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			tween(self, {
				alpha: 0,
				scaleX: 2,
				scaleY: 2
			}, {
				duration: 300,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					self.destroy();
				}
			});
		}
	});
	return self;
});
// Base enemy class for common functionality
var Enemy = Container.expand(function (type) {
	var self = Container.call(this);
	self.type = type || 'normal';
	self.speed = .02;
	self.cellX = 0;
	self.cellY = 0;
	self.currentCellX = 0;
	self.currentCellY = 0;
	self.currentTarget = undefined;
	self.maxHealth = 100;
	self.health = self.maxHealth;
	self.bulletsTargetingThis = [];
	self.waveNumber = currentWave;
	self.isFlying = false;
	self.isImmune = false;
	self.isBoss = false;
	self.collisionRadius = 25; // Base collision detection radius
	self.lastCollisionCheck = 0; // Performance optimization
	self.smokeEffectActive = false; // Track if smoke effect is already active
	self.lastHealthPercentage = 1.0; // Track last health percentage to detect transitions
	// Adjust collision radius based on enemy type
	switch (self.type) {
		case 'tank':
			self.collisionRadius = 40; // Larger radius for tank enemies
			break;
		case 'fast':
			self.collisionRadius = 20; // Smaller radius for fast enemies
			break;
		case 'flying':
			self.collisionRadius = 30; // Medium radius for flying enemies
			break;
		default:
			self.collisionRadius = 25; // Default radius
			break;
	}
	// Boss enemies have larger collision radius
	if (self.isBoss) {
		self.collisionRadius *= 1.5;
	}
	// Check if this is a boss wave
	// Check if this is a boss wave
	// Apply different stats based on enemy type
	switch (self.type) {
		case 'fast':
			self.speed *= 1; // Normal speed (half of previous 2x)
			// Speed boost for wave 5 fast enemies
			if (self.waveNumber === 5) {
				self.speed *= 1.2; // 1.2x speed for wave 5 fast enemies
			}
			// Speed boost for wave 6 fast enemies
			if (self.waveNumber === 6) {
				self.speed *= 1.1; // 1.1x speed for wave 6 fast enemies
			}
			self.maxHealth = 1;
			break;
		case 'immune':
			self.isImmune = true;
			self.maxHealth = 200;
			// Increase speed for wave 5 immune enemies only
			if (self.waveNumber === 5) {
				self.speed *= 3; // 3x speed for wave 5 immune enemies
			}
			// Speed boost for wave 2 immune enemies when they reach the second turn
			self.hasReachedSecondTurn = false;
			break;
		case 'flying':
			self.isFlying = true;
			self.speed *= 2; // 2x speed for flying enemies
			self.maxHealth = 80;
			break;
		case 'tank':
			self.speed *= 0.5; // Half speed for tank enemies
			self.maxHealth = 300; // Very high health for tank enemies
			break;
		default:
			// Default enemy uses fast values
			self.speed *= 1; // Normal speed (half of previous 2x)
			self.maxHealth = 1;
			break;
	}
	if (currentWave === totalWaves && type !== 'swarm') {
		self.isBoss = true;
		// Boss enemies have 20x health and are larger
		self.maxHealth *= 20;
		// Slower speed for bosses
		self.speed = self.speed * 0.7;
	}
	self.health = self.maxHealth;
	// Get appropriate asset for this enemy type
	var assetId = 'enemy';
	if (self.isBoss) {
		assetId = 'Boss';
	} else if (self.type === 'tank') {
		assetId = 'Tank';
	} else if (self.type !== 'normal') {
		assetId = 'enemy_' + self.type;
	}
	var enemyGraphics = self.attachAsset(assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Scale up boss enemies
	if (self.isBoss) {
		enemyGraphics.scaleX = 1.8;
		enemyGraphics.scaleY = 1.8;
	}
	// Fall back to regular enemy asset if specific type asset not found
	// Apply tint to differentiate enemy types
	/*switch (self.type) {
		case 'fast':
			enemyGraphics.tint = 0x00AAFF; // Blue for fast enemies
			break;
		case 'immune':
			enemyGraphics.tint = 0xAA0000; // Red for immune enemies
			break;
		case 'flying':
			enemyGraphics.tint = 0xFFFF00; // Yellow for flying enemies
			break;
		case 'swarm':
			enemyGraphics.tint = 0xFF00FF; // Pink for swarm enemies
			break;
	}*/
	// Create shadow for flying enemies
	if (self.isFlying) {
		// Create a shadow container that will be added to the shadow layer
		self.shadow = new Container();
		// Clone the enemy graphics for the shadow
		var shadowGraphics = self.shadow.attachAsset(assetId || 'enemy', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		// Apply shadow effect
		shadowGraphics.tint = 0x000000; // Black shadow
		shadowGraphics.alpha = 0.4; // Semi-transparent
		// If this is a boss, scale up the shadow to match
		if (self.isBoss) {
			shadowGraphics.scaleX = 1.8;
			shadowGraphics.scaleY = 1.8;
		}
		// Position shadow slightly offset
		self.shadow.x = 20; // Offset right
		self.shadow.y = 20; // Offset down
		// Ensure shadow has the same rotation as the enemy
		shadowGraphics.rotation = enemyGraphics.rotation;
	}
	var healthBarOutline = self.attachAsset('healthBarOutline', {
		anchorX: 0,
		anchorY: 0.5
	});
	var healthBarBG = self.attachAsset('healthBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	var healthBar = self.attachAsset('healthBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	healthBarBG.y = healthBarOutline.y = healthBar.y = -enemyGraphics.height / 2 - 10;
	healthBarOutline.x = -healthBarOutline.width / 2;
	healthBarBG.x = healthBar.x = -healthBar.width / 2 - .5;
	healthBar.tint = 0x00ff00;
	healthBarBG.tint = 0xff0000;
	self.healthBar = healthBar;
	self.update = function () {
		if (self.health <= 0) {
			self.health = 0;
			self.healthBar.width = 0;
		}
		// Check for 50% health threshold for smoke effect
		var currentHealthPercentage = self.health / self.maxHealth;
		if (!self.smokeEffectActive && self.lastHealthPercentage > 0.5 && currentHealthPercentage <= 0.5) {
			// Check if this enemy type should have smoke effect (Flying, BOSS, Immune, Tank)
			if (self.isFlying || self.isBoss || self.isImmune || self.type === 'tank') {
				self.smokeEffectActive = true;
				// Create animated smoke steam effect
				var smokeEffect = new Container();
				smokeEffect.x = self.x;
				smokeEffect.y = self.y - enemyGraphics.height / 2 - 10;
				// Create multiple smoke particles for realistic steam effect
				for (var smokeIndex = 0; smokeIndex < 5; smokeIndex++) {
					var smokeParticle = smokeEffect.attachAsset('rangeCircle', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					// Set smoke particle properties - scaled up to 2x size
					smokeParticle.width = (15 + Math.random() * 10) * 2;
					smokeParticle.height = (20 + Math.random() * 15) * 2;
					smokeParticle.tint = 0x666666; // Dark gray smoke
					smokeParticle.alpha = 0.6 + Math.random() * 0.3;
					// Position particles in a small cluster
					smokeParticle.x = (Math.random() - 0.5) * 20;
					smokeParticle.y = smokeIndex * -8;
					// Animate smoke particles rising and fading
					tween(smokeParticle, {
						y: smokeParticle.y - 60 - Math.random() * 40,
						x: smokeParticle.x + (Math.random() - 0.5) * 30,
						scaleX: 1.5 + Math.random() * 0.5,
						scaleY: 1.5 + Math.random() * 0.5,
						alpha: 0
					}, {
						duration: 2000 + Math.random() * 1000,
						delay: smokeIndex * 200,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							smokeParticle.destroy();
						}
					});
				}
				game.addChild(smokeEffect);
				// Create continuous smoke effect that follows the enemy
				self.continuousSmokeEffect = smokeEffect;
				// Set up repeating smoke generation
				self.smokeTimer = 0;
				self.smokeInterval = 60; // Generate new smoke every 60 frames (1 second)
			}
		}
		// Update continuous smoke effect position if active
		if (self.smokeEffectActive && self.continuousSmokeEffect && self.continuousSmokeEffect.parent) {
			self.continuousSmokeEffect.x = self.x;
			self.continuousSmokeEffect.y = self.y - enemyGraphics.height / 2 - 10;
			// Generate new smoke particles periodically
			self.smokeTimer++;
			if (self.smokeTimer >= self.smokeInterval) {
				self.smokeTimer = 0;
				// Create new smoke particle
				var newSmokeParticle = self.continuousSmokeEffect.attachAsset('rangeCircle', {
					anchorX: 0.5,
					anchorY: 0.5
				});
				newSmokeParticle.width = (12 + Math.random() * 8) * 2;
				newSmokeParticle.height = (16 + Math.random() * 12) * 2;
				newSmokeParticle.tint = 0x888888; // Lighter gray for continuous smoke
				newSmokeParticle.alpha = 0.4 + Math.random() * 0.2;
				newSmokeParticle.x = (Math.random() - 0.5) * 15;
				newSmokeParticle.y = 0;
				// Animate new smoke particle
				tween(newSmokeParticle, {
					y: -40 - Math.random() * 20,
					x: newSmokeParticle.x + (Math.random() - 0.5) * 20,
					scaleX: 1.2 + Math.random() * 0.3,
					scaleY: 1.2 + Math.random() * 0.3,
					alpha: 0
				}, {
					duration: 1500 + Math.random() * 500,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						newSmokeParticle.destroy();
					}
				});
			}
		}
		// Update last health percentage for next frame comparison
		self.lastHealthPercentage = currentHealthPercentage;
		// Handle slow effect
		if (self.isImmune) {
			// Immune enemies cannot be slowed, poisoned, or burned, clear any such effects
			self.slowed = false;
			self.slowEffect = false;
			self.poisoned = false;
			self.poisonEffect = false;
			self.burning = false;
			self.burnEffect = false;
			// Reset speed to original if needed
			if (self.originalSpeed !== undefined) {
				self.speed = self.originalSpeed;
			}
		} else {
			// Handle slow effect
			if (self.slowed) {
				// Visual indication of slowed status
				if (!self.slowEffect) {
					self.slowEffect = true;
				}
				self.slowDuration--;
				if (self.slowDuration <= 0) {
					self.speed = self.originalSpeed;
					self.slowed = false;
					self.slowEffect = false;
					// Only reset tint if not poisoned
					if (!self.poisoned) {
						enemyGraphics.tint = 0xFFFFFF; // Reset tint
					}
				}
			}
			// Handle poison effect
			if (self.poisoned) {
				// Visual indication of poisoned status
				if (!self.poisonEffect) {
					self.poisonEffect = true;
				}
				// Apply poison damage every 30 frames (twice per second)
				if (LK.ticks % 30 === 0) {
					self.health -= self.poisonDamage;
					if (self.health <= 0) {
						self.health = 0;
					}
					self.healthBar.width = self.health / self.maxHealth * 70;
				}
				self.poisonDuration--;
				if (self.poisonDuration <= 0) {
					self.poisoned = false;
					self.poisonEffect = false;
					// Only reset tint if not slowed
					if (!self.slowed) {
						enemyGraphics.tint = 0xFFFFFF; // Reset tint
					}
				}
			}
			// Handle burning effect from flamethrower
			if (self.burning) {
				// Visual indication of burning status
				if (!self.burnEffect) {
					self.burnEffect = true;
				}
				// Apply burn damage every 20 frames (3 times per second)
				if (LK.ticks % 20 === 0) {
					self.health -= self.burnDamage;
					if (self.health <= 0) {
						self.health = 0;
					}
					self.healthBar.width = self.health / self.maxHealth * 70;
				}
				self.burnDuration--;
				if (self.burnDuration <= 0) {
					self.burning = false;
					self.burnEffect = false;
					// Only reset tint if not slowed or poisoned
					if (!self.slowed && !self.poisoned) {
						enemyGraphics.tint = 0xFFFFFF; // Reset tint
					}
				}
			}
		}
		// Enemy overlap avoidance - check every frame for immune and tank enemies for better convoy formation
		if (self.type === 'immune' || self.type === 'tank' || LK.ticks % 3 === 0) {
			for (var i = 0; i < enemies.length; i++) {
				var otherEnemy = enemies[i];
				if (otherEnemy !== self && otherEnemy.parent) {
					// Prevent collision between flying and ground enemies (fast, immune, tank)
					if (self.isFlying && !otherEnemy.isFlying || !self.isFlying && otherEnemy.isFlying) {
						continue; // Skip collision detection between flying and ground enemies
					}
					var dx = otherEnemy.x - self.x;
					var dy = otherEnemy.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					var minDistance = (self.collisionRadius + otherEnemy.collisionRadius) * 1.4; // Increased buffer for better separation
					if (distance < minDistance && distance > 0) {
						// Much stronger separation force for immune and tank enemies
						var overlap = minDistance - distance;
						var separationForce;
						if (self.type === 'immune' || self.type === 'tank' || otherEnemy.type === 'immune' || otherEnemy.type === 'tank') {
							// Extra strong separation for immune/tank enemies to maintain convoy formation
							separationForce = Math.pow(overlap / minDistance, 1.5) * 4.0; // Stronger force with smoother scaling
						} else {
							separationForce = Math.pow(overlap / minDistance, 2) * 2.0; // Original force for other enemies
						}
						var separationX = dx / distance * separationForce;
						var separationY = dy / distance * separationForce;
						// Apply separation with stronger horizontal bias to maintain lanes
						self.currentCellX -= separationX;
						self.currentCellY -= separationY * 0.7; // Reduced Y separation to maintain forward movement
						// Apply weaker counter-force to maintain formation
						otherEnemy.currentCellX += separationX * 0.3;
						otherEnemy.currentCellY += separationY * 0.3;
						// Keep enemies within reasonable bounds
						self.currentCellX = Math.max(2, Math.min(22, self.currentCellX));
						self.currentCellY = Math.max(-20, Math.min(33, self.currentCellY));
						otherEnemy.currentCellX = Math.max(2, Math.min(22, otherEnemy.currentCellX));
						otherEnemy.currentCellY = Math.max(-20, Math.min(33, otherEnemy.currentCellY));
					}
				}
			}
		}
		// Fast enemy shooting capability
		if (self.type === 'fast') {
			// Initialize shooting properties if not already set
			if (self.shootingCooldown === undefined) {
				self.shootingCooldown = 0;
				self.shootingRange = 12 * CELL_SIZE; // 12 cell shooting range (3x increase)
				self.shootingDamage = 5;
				self.bulletSpeed = 3;
			}
			// Decrease shooting cooldown
			if (self.shootingCooldown > 0) {
				self.shootingCooldown--;
			}
			// Try to find and shoot at towers within range
			if (self.shootingCooldown <= 0 && self.currentCellY >= 4) {
				var targetTower = null;
				var closestDistance = self.shootingRange;
				// Find closest tower within shooting range
				for (var i = 0; i < towers.length; i++) {
					var tower = towers[i];
					// Skip landmine towers - enemies cannot see them
					if (tower.id === 'landmine') {
						continue;
					}
					// Allow targeting of all other tower types including trap/shooter towers
					var dx = tower.x - self.x;
					var dy = tower.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= self.shootingRange && distance < closestDistance) {
						closestDistance = distance;
						targetTower = tower;
					}
				}
				// Shoot at the target tower if found
				if (targetTower) {
					var bulletX = self.x;
					var bulletY = self.y;
					var enemyBullet = new Bullet(bulletX, bulletY, targetTower, self.shootingDamage, self.bulletSpeed);
					// Customize enemy bullet appearance
					if (enemyBullet.children[0]) {
						enemyBullet.children[0].tint = 0xFF0000; // Red color for enemy bullets
						enemyBullet.children[0].width = 20;
						enemyBullet.children[0].height = 20;
					}
					// Mark as enemy bullet to handle differently
					enemyBullet.isEnemyBullet = true;
					game.addChild(enemyBullet);
					bullets.push(enemyBullet);
					// Set cooldown (shoot every 1.5 seconds at 60 FPS)
					self.shootingCooldown = 90;
				}
			}
		}
		// Immune enemy shooting capability
		if (self.type === 'immune') {
			// Initialize shooting properties if not already set
			if (self.shootingCooldown === undefined) {
				self.shootingCooldown = 0;
				self.shootingRange = 8 * CELL_SIZE; // 8 cell shooting range for immune enemies
				self.shootingDamage = 8;
				self.bulletSpeed = 4;
			}
			// Decrease shooting cooldown
			if (self.shootingCooldown > 0) {
				self.shootingCooldown--;
			}
			// Try to find and shoot at towers within range
			if (self.shootingCooldown <= 0 && self.currentCellY >= 4) {
				var targetTower = null;
				var closestDistance = self.shootingRange;
				// Find closest tower within shooting range
				for (var i = 0; i < towers.length; i++) {
					var tower = towers[i];
					// Skip landmine towers - enemies cannot see them
					if (tower.id === 'landmine') {
						continue;
					}
					// Allow targeting of all other tower types including trap/shooter towers
					var dx = tower.x - self.x;
					var dy = tower.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= self.shootingRange && distance < closestDistance) {
						closestDistance = distance;
						targetTower = tower;
					}
				}
				// Shoot at the target tower if found
				if (targetTower) {
					var bulletX = self.x;
					var bulletY = self.y;
					var enemyBullet = new Bullet(bulletX, bulletY, targetTower, self.shootingDamage, self.bulletSpeed);
					// Customize immune enemy bullet appearance
					if (enemyBullet.children[0]) {
						enemyBullet.children[0].tint = 0xAA0000; // Dark red color for immune enemy bullets
						enemyBullet.children[0].width = 25;
						enemyBullet.children[0].height = 25;
					}
					// Mark as enemy bullet to handle differently
					enemyBullet.isEnemyBullet = true;
					game.addChild(enemyBullet);
					bullets.push(enemyBullet);
					// Set cooldown (shoot every 1 second at 60 FPS)
					self.shootingCooldown = 60;
				}
			}
		}
		// Immune enemy trap collision detection
		if (self.type === 'immune') {
			// Initialize trap contact tracking if not set
			if (self.trapContactMap === undefined) {
				self.trapContactMap = {};
			}
			// Check collision with trap towers every 10 frames for performance
			if (LK.ticks % 10 === 0) {
				for (var i = 0; i < towers.length; i++) {
					var tower = towers[i];
					if (tower.id === 'trap') {
						var dx = tower.x - self.x;
						var dy = tower.y - self.y;
						var distance = Math.sqrt(dx * dx + dy * dy);
						// Check if immune enemy is touching the trap (within 80 pixels)
						if (distance <= 80) {
							// Only reduce health if this trap hasn't been touched before
							var trapKey = tower.x + ',' + tower.y; // Unique identifier for this trap
							if (!self.trapContactMap[trapKey]) {
								self.trapContactMap[trapKey] = true;
								// Reduce immune enemy's health by half
								self.health = Math.floor(self.health / 2);
								if (self.health <= 0) {
									self.health = 0;
								}
								self.healthBar.width = self.health / self.maxHealth * 70;
								// Create visual effect for trap contact
								var trapEffect = new EffectIndicator(self.x, self.y, 'splash');
								trapEffect.children[0].tint = 0xAAAAAA; // Gray color for trap effect
								trapEffect.children[0].width = trapEffect.children[0].height = CELL_SIZE * 1.2;
								game.addChild(trapEffect);
							}
							// Break after first trap collision to avoid multiple hits per frame
							break;
						}
					}
				}
			}
		}
		// Tank enemy shooting capability
		if (self.type === 'tank') {
			// Initialize shooting properties if not already set
			if (self.shootingCooldown === undefined) {
				self.shootingCooldown = 0;
				self.shootingRange = 16 * CELL_SIZE; // 2x increased range for better targeting (was 8)
				self.shootingDamage = 15; // Increased damage for tank enemies
				self.bulletSpeed = 3; // Increased bullet speed
			}
			// Decrease shooting cooldown
			if (self.shootingCooldown > 0) {
				self.shootingCooldown--;
			}
			// Try to find and shoot at towers within range - tank enemies shoot when positioned
			if (self.shootingCooldown <= 0 && self.currentCellY >= 4 && self.tankMovementComplete) {
				var targetTower = null;
				var closestDistance = self.shootingRange;
				// Find closest tower within shooting range
				for (var i = 0; i < towers.length; i++) {
					var tower = towers[i];
					// Skip landmine towers - enemies cannot see them
					if (tower.id === 'landmine') {
						continue;
					}
					// Allow targeting of all other tower types including trap/shooter towers
					var dx = tower.x - self.x;
					var dy = tower.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= self.shootingRange && distance < closestDistance) {
						closestDistance = distance;
						targetTower = tower;
					}
				}
				// Shoot at the target tower if found
				if (targetTower) {
					var bulletX = self.x;
					var bulletY = self.y;
					var enemyBullet = new Bullet(bulletX, bulletY, targetTower, self.shootingDamage, self.bulletSpeed);
					// Customize tank enemy bullet appearance
					if (enemyBullet.children[0]) {
						enemyBullet.children[0].tint = 0x888888; // Gray color for tank enemy bullets
						enemyBullet.children[0].width = 35; // Larger bullets for tank enemies
						enemyBullet.children[0].height = 35;
					}
					// Mark as enemy bullet to handle differently
					enemyBullet.isEnemyBullet = true;
					game.addChild(enemyBullet);
					bullets.push(enemyBullet);
					// Set cooldown (shoot every 1.5 seconds at 60 FPS for more frequent shooting)
					self.shootingCooldown = 90;
				}
			}
		}
		// Convoy formation for immune and tank enemies - maintain proper spacing and formation
		if ((self.type === 'immune' || self.type === 'tank') && self.currentCellY >= 4) {
			// Find nearby same-type enemies to form convoy with
			var nearbyConvoyEnemies = [];
			for (var i = 0; i < enemies.length; i++) {
				var otherEnemy = enemies[i];
				if (otherEnemy !== self && otherEnemy.parent && otherEnemy.type === self.type) {
					var dx = otherEnemy.x - self.x;
					var dy = otherEnemy.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= CELL_SIZE * 4) {
						// Within 4 cells for convoy formation
						nearbyConvoyEnemies.push({
							enemy: otherEnemy,
							distance: distance,
							dx: dx,
							dy: dy
						});
					}
				}
			}
			// Apply convoy formation forces
			if (nearbyConvoyEnemies.length > 0) {
				for (var j = 0; j < nearbyConvoyEnemies.length; j++) {
					var convoyData = nearbyConvoyEnemies[j];
					var convoyEnemy = convoyData.enemy;
					var distance = convoyData.distance;
					var dx = convoyData.dx;
					var dy = convoyData.dy;
					var idealDistance = CELL_SIZE * 2.8; // Ideal convoy spacing
					if (distance < idealDistance) {
						// Too close - apply separation
						var separationForce = (idealDistance - distance) / idealDistance * 0.8;
						var separationX = dx / distance * separationForce;
						var separationY = dy / distance * separationForce * 0.4; // Less Y separation
						self.currentCellX -= separationX;
						self.currentCellY -= separationY;
					} else if (distance > idealDistance * 1.5) {
						// Too far - apply attraction to maintain convoy
						var attractionForce = (distance - idealDistance) / distance * 0.3;
						var attractionX = dx / distance * attractionForce;
						var attractionY = dy / distance * attractionForce * 0.2;
						self.currentCellX += attractionX;
						self.currentCellY += attractionY;
					}
				}
			}
			// Keep enemies within valid bounds
			self.currentCellX = Math.max(3, Math.min(21, self.currentCellX));
			self.currentCellY = Math.max(-20, Math.min(33, self.currentCellY));
		}
		// Set tint based on effect status
		if (self.isImmune) {
			enemyGraphics.tint = 0xFFFFFF;
		} else if (self.poisoned && self.slowed && self.burning) {
			// Combine all three effects
			enemyGraphics.tint = 0x8B4513; // Brown-ish mix
		} else if (self.poisoned && self.slowed) {
			// Combine poison (0x00FFAA) and slow (0x9900FF) colors
			// Simple average: R: (0+153)/2=76, G: (255+0)/2=127, B: (170+255)/2=212
			enemyGraphics.tint = 0x4C7FD4;
		} else if (self.poisoned && self.burning) {
			// Combine poison and burn
			enemyGraphics.tint = 0x8B7355; // Brownish-green mix
		} else if (self.slowed && self.burning) {
			// Combine slow and burn
			enemyGraphics.tint = 0xCC4500; // Orange-red mix
		} else if (self.burning) {
			enemyGraphics.tint = 0xFF4500; // Orange for burning
		} else if (self.poisoned) {
			enemyGraphics.tint = 0x00FFAA;
		} else if (self.slowed) {
			enemyGraphics.tint = 0x9900FF;
		} else {
			enemyGraphics.tint = 0xFFFFFF;
		}
		if (self.currentTarget) {
			var ox = self.currentTarget.x - self.currentCellX;
			var oy = self.currentTarget.y - self.currentCellY;
			if (ox !== 0 || oy !== 0) {
				var angle = Math.atan2(oy, ox) + Math.PI / 2;
				if (enemyGraphics.targetRotation === undefined) {
					enemyGraphics.targetRotation = angle;
					enemyGraphics.rotation = angle;
				} else {
					if (Math.abs(angle - enemyGraphics.targetRotation) > 0.25) {
						// Further increased threshold to reduce tween frequency
						tween.stop(enemyGraphics, {
							rotation: true
						});
						// Calculate the shortest angle to rotate
						var currentRotation = enemyGraphics.rotation;
						var angleDiff = angle - currentRotation;
						// Normalize angle difference to -PI to PI range for shortest path
						while (angleDiff > Math.PI) {
							angleDiff -= Math.PI * 2;
						}
						while (angleDiff < -Math.PI) {
							angleDiff += Math.PI * 2;
						}
						enemyGraphics.targetRotation = angle;
						tween(enemyGraphics, {
							rotation: currentRotation + angleDiff
						}, {
							duration: 150,
							// Reduced duration for faster rotation
							easing: tween.easeOut
						});
					}
				}
			}
		}
		// Keep health bars positioned below level indicators
		var healthBarY = CELL_SIZE * 0.7 + 25;
		if (self.towerHealthBarOutline) {
			self.towerHealthBarOutline.y = healthBarY;
			self.towerHealthBarBG.y = healthBarY;
			self.towerHealthBar.y = healthBarY;
		}
		healthBarOutline.y = healthBarBG.y = healthBar.y = -enemyGraphics.height / 2 - 10;
	};
	return self;
});
var GoldIndicator = Container.expand(function (value, x, y) {
	var self = Container.call(this);
	var shadowText = new Text2("+" + value, {
		size: 45,
		fill: 0x000000,
		weight: 800
	});
	shadowText.anchor.set(0.5, 0.5);
	shadowText.x = 2;
	shadowText.y = 2;
	self.addChild(shadowText);
	var goldText = new Text2("+" + value, {
		size: 45,
		fill: 0xFFD700,
		weight: 800
	});
	goldText.anchor.set(0.5, 0.5);
	self.addChild(goldText);
	self.x = x;
	self.y = y;
	self.alpha = 0;
	self.scaleX = 0.5;
	self.scaleY = 0.5;
	tween(self, {
		alpha: 1,
		scaleX: 1.2,
		scaleY: 1.2,
		y: y - 40
	}, {
		duration: 50,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			tween(self, {
				alpha: 0,
				scaleX: 1.5,
				scaleY: 1.5,
				y: y - 80
			}, {
				duration: 600,
				easing: tween.easeIn,
				delay: 800,
				onFinish: function onFinish() {
					self.destroy();
				}
			});
		}
	});
	return self;
});
var Grid = Container.expand(function (gridWidth, gridHeight) {
	var self = Container.call(this);
	self.cells = [];
	self.spawns = [];
	self.goals = [];
	for (var i = 0; i < gridWidth; i++) {
		self.cells[i] = [];
		for (var j = 0; j < gridHeight; j++) {
			self.cells[i][j] = {
				score: 0,
				pathId: 0,
				towersInRange: []
			};
		}
	}
	/*
				Cell Types
				0: Transparent floor
				1: Wall
				2: Spawn
				3: Goal
	*/
	// Create simplified straight road path waypoints with 3-cell width
	var pathWaypoints = [{
		x: 12,
		y: 0
	},
	// Start point (spawn)
	{
		x: 12,
		y: 8
	},
	// First horizontal road
	{
		x: 2,
		y: 8
	},
	// Turn down
	{
		x: 2,
		y: 15
	},
	// Second horizontal road
	{
		x: 22,
		y: 15
	},
	// Turn down
	{
		x: 22,
		y: 22
	},
	// Third horizontal road
	{
		x: 12,
		y: 22
	},
	// Final segment to goal
	{
		x: 12,
		y: gridHeight - 1
	} // End point (goal)
	];
	// Create path cells array to mark which cells are part of the road
	var pathCells = [];
	// Generate path between waypoints
	for (var w = 0; w < pathWaypoints.length - 1; w++) {
		var start = pathWaypoints[w];
		var end = pathWaypoints[w + 1];
		// Create straight line between waypoints
		var steps = Math.max(Math.abs(end.x - start.x), Math.abs(end.y - start.y));
		for (var s = 0; s <= steps; s++) {
			var t = steps === 0 ? 0 : s / steps;
			var pathX = Math.round(start.x + (end.x - start.x) * t);
			var pathY = Math.round(start.y + (end.y - start.y) * t);
			// Add path width - make road 7 cells wide horizontally, 3 cells wide vertically
			for (var offsetX = -3; offsetX <= 3; offsetX++) {
				for (var offsetY = -1; offsetY <= 1; offsetY++) {
					var cellX = pathX + offsetX;
					var cellY = pathY + offsetY;
					if (cellX >= 0 && cellX < gridWidth && cellY >= 0 && cellY < gridHeight) {
						var key = cellX + ',' + cellY;
						if (pathCells.indexOf(key) === -1) {
							pathCells.push(key);
						}
					}
				}
			}
		}
	}
	for (var i = 0; i < gridWidth; i++) {
		for (var j = 0; j < gridHeight; j++) {
			var cell = self.cells[i][j];
			var cellKey = i + ',' + j;
			var isOnPath = pathCells.indexOf(cellKey) !== -1;
			// Default to wall, then carve out path and other areas
			var cellType = 1; // Wall by default
			// Set path cells
			if (isOnPath) {
				cellType = 0; // Path
			}
			// Set spawn points at the start of the path
			if (i >= 11 && i <= 13 && j === 0) {
				cellType = 2; // Spawn
				self.spawns.push(cell);
			}
			// Set goal points at the end of the path
			if (i >= 11 && i <= 13 && j === gridHeight - 1) {
				cellType = 3; // Goal
				self.goals.push(cell);
			}
			// Keep borders as walls
			if (i === 0 || i === gridWidth - 1 || j === 0 || j === gridHeight - 1) {
				if (cellType !== 2 && cellType !== 3) {
					// Don't override spawn/goal
					cellType = 1; // Wall
				}
			}
			cell.type = cellType;
			cell.x = i;
			cell.y = j;
			cell.upLeft = self.cells[i - 1] && self.cells[i - 1][j - 1];
			cell.up = self.cells[i - 1] && self.cells[i - 1][j];
			cell.upRight = self.cells[i - 1] && self.cells[i - 1][j + 1];
			cell.left = self.cells[i][j - 1];
			cell.right = self.cells[i][j + 1];
			cell.downLeft = self.cells[i + 1] && self.cells[i + 1][j - 1];
			cell.down = self.cells[i + 1] && self.cells[i + 1][j];
			cell.downRight = self.cells[i + 1] && self.cells[i + 1][j + 1];
			cell.neighbors = [cell.upLeft, cell.up, cell.upRight, cell.right, cell.downRight, cell.down, cell.downLeft, cell.left];
			cell.targets = [];
			// Render road asset for path cells
			if (isOnPath) {
				var roadVisual = self.attachAsset('road', {
					anchorX: 0.5,
					anchorY: 0.6
				});
				roadVisual.x = i * CELL_SIZE + CELL_SIZE / 2;
				roadVisual.y = j * CELL_SIZE + CELL_SIZE / 2;
			}
			// Debug cells removed for performance
		}
	}
	self.getCell = function (x, y) {
		return self.cells[x] && self.cells[x][y];
	};
	self.pathFind = function () {
		var before = new Date().getTime();
		var toProcess = self.goals.concat([]);
		maxScore = 0;
		pathId += 1;
		for (var a = 0; a < toProcess.length; a++) {
			toProcess[a].pathId = pathId;
		}
		function processNode(node, targetValue, targetNode) {
			if (node && node.type != 1) {
				if (node.pathId < pathId || targetValue < node.score) {
					node.targets = [targetNode];
				} else if (node.pathId == pathId && targetValue == node.score) {
					node.targets.push(targetNode);
				}
				if (node.pathId < pathId || targetValue < node.score) {
					node.score = targetValue;
					if (node.pathId != pathId) {
						toProcess.push(node);
					}
					node.pathId = pathId;
					if (targetValue > maxScore) {
						maxScore = targetValue;
					}
				}
			}
		}
		while (toProcess.length) {
			var nodes = toProcess;
			toProcess = [];
			for (var a = 0; a < nodes.length; a++) {
				var node = nodes[a];
				var targetScore = node.score + 14142;
				if (node.up && node.left && node.up.type != 1 && node.left.type != 1) {
					processNode(node.upLeft, targetScore, node);
				}
				if (node.up && node.right && node.up.type != 1 && node.right.type != 1) {
					processNode(node.upRight, targetScore, node);
				}
				if (node.down && node.right && node.down.type != 1 && node.right.type != 1) {
					processNode(node.downRight, targetScore, node);
				}
				if (node.down && node.left && node.down.type != 1 && node.left.type != 1) {
					processNode(node.downLeft, targetScore, node);
				}
				targetScore = node.score + 10000;
				processNode(node.up, targetScore, node);
				processNode(node.right, targetScore, node);
				processNode(node.down, targetScore, node);
				processNode(node.left, targetScore, node);
			}
		}
		for (var a = 0; a < self.spawns.length; a++) {
			if (self.spawns[a].pathId != pathId) {
				console.warn("Spawn blocked");
				return true;
			}
		}
		for (var a = 0; a < enemies.length; a++) {
			var enemy = enemies[a];
			// Skip enemies that haven't entered the viewable area yet
			if (enemy.currentCellY < 4) {
				continue;
			}
			// Skip flying enemies from path check as they can fly over obstacles
			if (enemy.isFlying) {
				continue;
			}
			var target = self.getCell(enemy.cellX, enemy.cellY);
			if (enemy.currentTarget) {
				if (enemy.currentTarget.pathId != pathId) {
					if (!target || target.pathId != pathId) {
						console.warn("Enemy blocked 1 ");
						return true;
					}
				}
			} else if (!target || target.pathId != pathId) {
				console.warn("Enemy blocked 2");
				return true;
			}
		}
		console.log("Speed", new Date().getTime() - before);
	};
	self.renderDebug = function () {
		// Debug cells removed for performance
	};
	self.updateEnemy = function (enemy) {
		var cell = grid.getCell(enemy.cellX, enemy.cellY);
		if (cell && cell.type == 3) {
			// BOSS Enemy reached the goal - reduce lives by 100 (100% of 100 total lives)
			if (enemy.isBoss) {
				lives = Math.max(0, lives - 100);
			} else {
				// Regular enemy reached the goal - reduce lives by 10 (10% of 100 total lives)
				lives = Math.max(0, lives - 10);
			}
			updateUI();
			if (lives <= 0) {
				LK.showGameOver();
			}
			return true;
		}
		if (enemy.isFlying && enemy.shadow) {
			enemy.shadow.x = enemy.x + 20; // Match enemy x-position + offset
			enemy.shadow.y = enemy.y + 20; // Match enemy y-position + offset
			// Match shadow rotation with enemy rotation
			if (enemy.children[0] && enemy.shadow.children[0]) {
				enemy.shadow.children[0].rotation = enemy.children[0].rotation;
			}
		}
		// Check if the enemy has reached the entry area (y position is at least 5)
		var hasReachedEntryArea = enemy.currentCellY >= 4;
		// If enemy hasn't reached the entry area yet, just move down vertically
		if (!hasReachedEntryArea) {
			// Consistent movement speed for all enemy types during initial phase
			var initialSpeed = enemy.speed;
			if (enemy.type === 'tank') {
				initialSpeed = 0.03; // 3x faster than normal tank speed for smoother entry
			}
			// Move directly downward
			enemy.currentCellY += initialSpeed;
			// Rotate enemy graphic to face downward (PI/2 radians = 90 degrees) + 90 degrees right
			var angle = Math.PI / 2 + Math.PI / 2;
			if (enemy.children[0] && enemy.children[0].targetRotation === undefined) {
				enemy.children[0].targetRotation = angle;
				enemy.children[0].rotation = angle;
			} else if (enemy.children[0]) {
				if (Math.abs(angle - enemy.children[0].targetRotation) > 0.05) {
					tween.stop(enemy.children[0], {
						rotation: true
					});
					// Calculate the shortest angle to rotate
					var currentRotation = enemy.children[0].rotation;
					var angleDiff = angle - currentRotation;
					// Normalize angle difference to -PI to PI range for shortest path
					while (angleDiff > Math.PI) {
						angleDiff -= Math.PI * 2;
					}
					while (angleDiff < -Math.PI) {
						angleDiff += Math.PI * 2;
					}
					// Set target rotation and animate to it
					enemy.children[0].targetRotation = angle;
					tween(enemy.children[0], {
						rotation: currentRotation + angleDiff
					}, {
						duration: 250,
						easing: tween.easeOut
					});
				}
			}
			// Update enemy's position (reduce calculation frequency)
			if (LK.ticks % 2 === 0) {
				enemy.x = grid.x + enemy.currentCellX * CELL_SIZE;
				enemy.y = grid.y + enemy.currentCellY * CELL_SIZE;
			}
			// If enemy has now reached the entry area, update cell coordinates
			if (enemy.currentCellY >= 4) {
				enemy.cellX = Math.round(enemy.currentCellX);
				enemy.cellY = Math.round(enemy.currentCellY);
			}
			return false;
		}
		// After reaching entry area, handle flying enemies differently
		if (enemy.isFlying) {
			// Special movement for boss enemies - straight line down the middle
			if (enemy.isBoss) {
				// Boss enemies move straight down the middle column (x = 12)
				enemy.currentCellX = 12; // Always stay in middle column
				enemy.currentCellY += enemy.speed; // Move straight down
			} else {
				// Regular flying enemy logic
				// Initialize flying enemy direction if not set
				if (enemy.flyingDirection === undefined) {
					// Use the global alternating direction flag
					enemy.flyingDirection = lastDirectionWasRight ? 1 : -1; // 1 for right, -1 for left
					enemy.startX = enemy.currentCellX; // Remember starting X position
					enemy.hasChangedDirection = false; // Track if enemy has changed direction yet
				}
				// Assign flying enemies to one of 3 vertical lanes if not already assigned
				if (enemy.flyingLane === undefined) {
					// Determine lane based on initial direction instead of spawn position
					if (enemy.flyingDirection === -1) {
						// Flying left: start from right side lanes
						enemy.flyingLane = 2; // Right lane - x position 18
						enemy.targetX = 18;
					} else {
						// Flying right: start from left side lanes
						enemy.flyingLane = 0; // Left lane - x position 6
						enemy.targetX = 6;
					}
				}
				// Move straight down in the assigned lane
				enemy.currentCellY += enemy.speed;
				// Implement alternating direction movement for flying enemies
				if (!enemy.hasChangedDirection && enemy.currentCellY > 15) {
					// After reaching middle of map, start moving in assigned direction
					enemy.hasChangedDirection = true;
					// Set new target X based on direction - enemies move to opposite side
					if (enemy.flyingDirection > 0) {
						// Moving right - target right side of map
						enemy.targetX = 20;
					} else {
						// Moving left - target left side of map
						enemy.targetX = 4;
					}
				}
				// Gradually move to the target X position (lane center or direction target)
				var xDiff = enemy.targetX - enemy.currentCellX;
				if (Math.abs(xDiff) > 0.1) {
					enemy.currentCellX += xDiff * 0.05; // Gradual movement to target
				}
			}
			// Rotate enemy graphic to face downward
			var angle = Math.PI; // Face downward (180 degrees)
			if (enemy.children[0] && enemy.children[0].targetRotation === undefined) {
				enemy.children[0].targetRotation = angle;
				enemy.children[0].rotation = angle;
			} else if (enemy.children[0]) {
				if (Math.abs(angle - enemy.children[0].targetRotation) > 0.05) {
					tween.stop(enemy.children[0], {
						rotation: true
					});
					// Calculate the shortest angle to rotate
					var currentRotation = enemy.children[0].rotation;
					var angleDiff = angle - currentRotation;
					// Normalize angle difference to -PI to PI range for shortest path
					while (angleDiff > Math.PI) {
						angleDiff -= Math.PI * 2;
					}
					while (angleDiff < -Math.PI) {
						angleDiff += Math.PI * 2;
					}
					// Set target rotation and animate to it
					enemy.children[0].targetRotation = angle;
					tween(enemy.children[0], {
						rotation: currentRotation + angleDiff
					}, {
						duration: 250,
						easing: tween.easeOut
					});
				}
			}
			// Update the cell position to track where the flying enemy is
			enemy.cellX = Math.round(enemy.currentCellX);
			enemy.cellY = Math.round(enemy.currentCellY);
			// Update visual position
			enemy.x = grid.x + enemy.currentCellX * CELL_SIZE;
			enemy.y = grid.y + enemy.currentCellY * CELL_SIZE;
			// Check if enemy reached the bottom (goal)
			var cell = grid.getCell(enemy.cellX, enemy.cellY);
			if (cell && cell.type == 3) {
				// BOSS Flying enemy reached the goal - reduce lives by 100 (100% of 100 total lives)
				if (enemy.isBoss) {
					lives = Math.max(0, lives - 100);
				} else {
					// Flying enemy reached the goal - reduce lives by 10 (10% of 100 total lives)
					lives = Math.max(0, lives - 10);
				}
				updateUI();
				if (lives <= 0) {
					LK.showGameOver();
				}
				return true;
			}
			// Check if enemy has moved off the bottom of the screen
			if (enemy.currentCellY > 35) {
				// Grid height is 35 (29 + 6)
				// BOSS Enemy went off-screen - reduce lives by 100 (100% of 100 total lives)
				if (enemy.isBoss) {
					lives = Math.max(0, lives - 100);
				} else {
					// Enemy went off-screen - reduce lives by 10 (10% of 100 total lives)
					lives = Math.max(0, lives - 10);
				}
				updateUI();
				if (lives <= 0) {
					LK.showGameOver();
				}
				return true;
			}
			// Update shadow position if this is a flying enemy
			return false;
		}
		// Handle normal pathfinding enemies
		if (enemy.isBoss) {
			// Boss enemies move straight down the middle column regardless of type
			enemy.currentCellX = 12; // Always stay in middle column
			enemy.currentCellY += enemy.speed; // Move straight down
			// Force boss position to center immediately
			enemy.cellX = 12;
			enemy.cellX = Math.round(enemy.currentCellX);
			enemy.cellY = Math.round(enemy.currentCellY);
			// Set rotation to face straight down without animation
			if (enemy.children[0]) {
				enemy.children[0].rotation = Math.PI; // Face downward (180 degrees)
				enemy.children[0].targetRotation = Math.PI;
			}
		} else if (enemy.type === 'fast') {
			// Fast enemies move straight down without pathfinding or turning
			enemy.currentCellY += enemy.speed;
			enemy.cellX = Math.round(enemy.currentCellX);
			enemy.cellY = Math.round(enemy.currentCellY);
			// Set rotation to face straight down without animation
			if (enemy.children[0]) {
				enemy.children[0].rotation = Math.PI; // Face downward (180 degrees)
				enemy.children[0].targetRotation = Math.PI;
			}
		} else if (enemy.type === 'immune' && enemy.waveNumber === 2 && !enemy.hasReachedSecondTurn && enemy.currentCellY >= 15) {
			// Wave 2 immune enemies get speed boost when they reach the second turn (y >= 15)
			enemy.hasReachedSecondTurn = true;
			enemy.speed = 2.4 * 0.02; // Set speed to 2.4 times base speed (0.02)
		} else if (enemy.type === 'tank') {
			// Tank enemies move to upper quarter vertically and stop there, staying at their spawned x-position
			var upperQuarterY = (29 + 6) * 0.25; // Upper quarter of map (around row 8.75)
			var supportPositionY = Math.max(8, upperQuarterY); // Stop at upper quarter
			// Initialize tank target position if not set
			if (enemy.tankTargetX === undefined) {
				enemy.tankTargetX = enemy.currentCellX; // Store spawned x-position
				enemy.tankTargetY = supportPositionY; // Store target support position
				enemy.tankMovementComplete = false;
			}
			// Use smooth interpolation movement instead of tween animations
			if (!enemy.tankMovementComplete && enemy.currentCellY >= 4) {
				// Calculate distance to target
				var dx = enemy.tankTargetX - enemy.currentCellX;
				var dy = enemy.tankTargetY - enemy.currentCellY;
				var distanceToTarget = Math.sqrt(dx * dx + dy * dy);
				// Check if we've reached the target (within 0.1 cells)
				if (distanceToTarget < 0.1) {
					enemy.currentCellX = enemy.tankTargetX;
					enemy.currentCellY = enemy.tankTargetY;
					enemy.tankMovementComplete = true;
				} else {
					// Use smooth interpolation movement
					var speed = 0.04; // Movement speed in cells per frame
					var t = Math.min(1, speed / distanceToTarget);
					enemy.currentCellX = enemy.currentCellX + (enemy.tankTargetX - enemy.currentCellX) * t;
					enemy.currentCellY = enemy.currentCellY + (enemy.tankTargetY - enemy.currentCellY) * t;
				}
				// Tank enemies do not rotate - keep original rotation
			} else {
				// Tank has reached support position - stop moving and face downward to support convoy
				// Lock tank position at target location
				enemy.currentCellX = enemy.tankTargetX; // Stay at spawned x-position
				enemy.currentCellY = enemy.tankTargetY; // Lock at support position
				// Tank enemies do not rotate - keep original rotation
			}
			enemy.cellX = Math.round(enemy.currentCellX);
			enemy.cellY = Math.round(enemy.currentCellY);
		} else {
			// Handle normal pathfinding enemies
			if (!enemy.currentTarget && cell && cell.targets && cell.targets.length > 0) {
				enemy.currentTarget = cell.targets[0];
			}
			if (enemy.currentTarget) {
				// Check if current cell has a better target (closer to goal)
				if (cell && cell.targets && cell.targets.length > 0 && cell.score < enemy.currentTarget.score) {
					enemy.currentTarget = cell.targets[0];
				}
				var ox = enemy.currentTarget.x - enemy.currentCellX;
				var oy = enemy.currentTarget.y - enemy.currentCellY;
				var dist = Math.sqrt(ox * ox + oy * oy);
				if (dist < enemy.speed) {
					// Speed boost logic removed to prevent any tank speed boost effects
					enemy.cellX = Math.round(enemy.currentCellX);
					enemy.cellY = Math.round(enemy.currentCellY);
					enemy.currentTarget = undefined;
					return;
				}
				var angle = Math.atan2(oy, ox) + Math.PI / 2;
				enemy.currentCellX += Math.cos(angle - Math.PI / 2) * enemy.speed;
				enemy.currentCellY += Math.sin(angle - Math.PI / 2) * enemy.speed;
			} else if (cell && cell.targets && cell.targets.length > 0) {
				// If no current target, pick the first available target from current cell
				enemy.currentTarget = cell.targets[0];
			}
		}
		enemy.x = grid.x + enemy.currentCellX * CELL_SIZE;
		enemy.y = grid.y + enemy.currentCellY * CELL_SIZE;
		// Check if ground enemy has moved off the bottom of the screen
		if (enemy.currentCellY > 35) {
			// Grid height is 35 (29 + 6)
			// BOSS Enemy went off-screen - reduce lives by 100 (100% of 100 total lives)
			if (enemy.isBoss) {
				lives = Math.max(0, lives - 100);
			} else {
				// Enemy went off-screen - reduce lives by 10 (10% of 100 total lives)
				lives = Math.max(0, lives - 10);
			}
			updateUI();
			if (lives <= 0) {
				LK.showGameOver();
			}
			return true;
		}
	};
});
var NextWaveButton = Container.expand(function () {
	var self = Container.call(this);
	var buttonBackground = self.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	buttonBackground.width = 300;
	buttonBackground.height = 100;
	buttonBackground.tint = 0x0088FF;
	var buttonText = new Text2("Next Wave", {
		size: 50,
		fill: 0xFFFFFF,
		weight: 800
	});
	buttonText.anchor.set(0.5, 0.5);
	self.addChild(buttonText);
	self.enabled = false;
	self.visible = false;
	self.update = function () {
		if (waveIndicator && waveIndicator.gameStarted && currentWave < totalWaves) {
			self.enabled = true;
			self.visible = true;
			buttonBackground.tint = 0x0088FF;
			self.alpha = 1;
		} else {
			self.enabled = false;
			self.visible = false;
			buttonBackground.tint = 0x888888;
			self.alpha = 0.7;
		}
	};
	self.down = function () {
		if (!self.enabled) {
			return;
		}
		if (waveIndicator && waveIndicator.gameStarted && currentWave < totalWaves) {
			currentWave++; // Increment to the next wave directly
			waveTimer = 0; // Reset wave timer
			waveInProgress = true;
			waveSpawned = false;
			// Get the type of the current wave (which is now the next wave)
			var waveType = waveIndicator.getWaveTypeName(currentWave);
			var enemyCount = waveIndicator.getEnemyCount(currentWave);
			var notification = game.addChild(new Notification("Wave " + currentWave + " (" + waveType + " - " + enemyCount + " enemies) activated!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 150;
		}
	};
	return self;
});
var Notification = Container.expand(function (message) {
	var self = Container.call(this);
	var notificationGraphics = self.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var notificationText = new Text2(message, {
		size: 50,
		fill: 0x000000,
		weight: 800
	});
	notificationText.anchor.set(0.5, 0.5);
	notificationGraphics.width = notificationText.width + 30;
	self.addChild(notificationText);
	self.alpha = 1;
	var fadeOutTime = 120;
	self.update = function () {
		if (fadeOutTime > 0) {
			fadeOutTime--;
			self.alpha = Math.min(fadeOutTime / 120 * 2, 1);
		} else {
			self.destroy();
		}
	};
	return self;
});
var SourceTower = Container.expand(function (towerType) {
	var self = Container.call(this);
	self.towerType = towerType || 'trap';
	// Increase size of base for easier touch
	var baseGraphics = self.attachAsset('Box', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.3,
		scaleY: 1.3
	});
	switch (self.towerType) {
		case 'landmine':
			baseGraphics.tint = 0x9B8B6D; // Lighter tan/brown camouflage
			break;
		case 'sniper':
			baseGraphics.tint = 0x7A9B5F; // Lighter olive green camouflage
			break;
		case 'flamethrower':
			baseGraphics.tint = 0xBBA385; //{aO} // Lighter sandy brown camouflage
			break;
		case 'slow':
			baseGraphics.tint = 0x7F7F5F; //{aR} // Lighter olive drab camouflage
			break;
		case 'poison':
			baseGraphics.tint = 0x969696; //{aU} // Lighter gray camouflage
			break;
		case 'tank':
			baseGraphics.tint = 0x006400; // Dark green for tank
			break;
		default:
			baseGraphics.tint = 0x8C8C77;
		//{aX} // Lighter neutral camouflage green-gray
	}
	var towerCost = getTowerCost(self.towerType);
	// Add shadow for tower type label
	var displayTextShadow = self.towerType === 'flamethrower' ? 'Flame' : self.towerType === 'trap' ? 'Shooter' : self.towerType === 'slow' ? 'Missiles' : self.towerType === 'tank' ? 'Tank' : self.towerType.charAt(0).toUpperCase() + self.towerType.slice(1);
	var typeLabelShadow = new Text2(displayTextShadow, {
		size: 50,
		fill: 0x000000,
		weight: 800
	});
	typeLabelShadow.anchor.set(0.5, 0.5);
	typeLabelShadow.x = 4;
	typeLabelShadow.y = -20 + 4;
	self.addChild(typeLabelShadow);
	// Add tower type label
	var displayText = self.towerType === 'flamethrower' ? 'Flame' : self.towerType === 'trap' ? 'Shooter' : self.towerType === 'slow' ? 'Missiles' : self.towerType === 'tank' ? 'Tank' : self.towerType.charAt(0).toUpperCase() + self.towerType.slice(1);
	var typeLabel = new Text2(displayText, {
		size: 50,
		fill: 0xFFFFFF,
		weight: 800
	});
	typeLabel.anchor.set(0.5, 0.5);
	typeLabel.y = -20; // Position above center of tower
	self.addChild(typeLabel);
	// Add cost shadow
	var costLabelShadow = new Text2(towerCost, {
		size: 50,
		fill: 0x000000,
		weight: 800
	});
	costLabelShadow.anchor.set(0.5, 0.5);
	costLabelShadow.x = 4;
	costLabelShadow.y = 24 + 12;
	self.addChild(costLabelShadow);
	// Add cost label
	var costLabel = new Text2(towerCost, {
		size: 50,
		fill: 0xFFD700,
		weight: 800
	});
	costLabel.anchor.set(0.5, 0.5);
	costLabel.y = 20 + 12;
	self.addChild(costLabel);
	self.update = function () {
		// Check if player can afford this tower
		var canAfford = gold >= getTowerCost(self.towerType);
		// Set opacity based on affordability
		self.alpha = canAfford ? 1 : 0.5;
	};
	return self;
});
var Tower = Container.expand(function (id) {
	var self = Container.call(this);
	self.id = id || 'trap';
	self.level = 1;
	self.maxLevel = 6;
	self.gridX = 0;
	self.gridY = 0;
	self.range = 3 * CELL_SIZE;
	self.isPlaced = false; // Track if tower has been placed on grid
	// Standardized method to get the current range of the tower
	self.getRange = function () {
		// Always calculate range based on tower type and level
		switch (self.id) {
			case 'sniper':
				// Sniper: massive range to cover entire map from any position
				if (self.level === self.maxLevel) {
					return 75 * CELL_SIZE; // Extreme range for max level to cover entire map (1.5x increase)
				}
				return (22.5 + (self.level - 1) * 7.5) * CELL_SIZE;
			// Increased base and scaling (1.5x increase)
			case 'flamethrower':
				// Flamethrower: base 4.5, +0.5 per level for cone range (increased aiming distance)
				return (4.5 + (self.level - 1) * 0.5) * CELL_SIZE;
			case 'landmine':
				// Landmine: base 2.5, +0.5 per level
				return (2.5 + (self.level - 1) * 0.5) * CELL_SIZE;
			case 'slow':
				// Slow: base 8.75, +1.25 per level (2.5x increase)
				return (8.75 + (self.level - 1) * 1.25) * CELL_SIZE;
			case 'poison':
				// Poison: base 3.2, +0.5 per level
				return (3.2 + (self.level - 1) * 0.5) * CELL_SIZE;
			case 'tank':
				// Tank: base 14.0, +2.8 per level (3.5x increase)
				return (14.0 + (self.level - 1) * 2.8) * CELL_SIZE;
			default:
				// Trap: base 6, +1.0 per level (double range)
				return (6 + (self.level - 1) * 1.0) * CELL_SIZE;
		}
	};
	self.cellsInRange = [];
	self.fireRate = 60;
	self.bulletSpeed = 5;
	self.damage = 10;
	self.lastFired = 0;
	self.targetEnemy = null;
	// Continuous shooting variables for flamethrower
	self.isContinuousFiring = false;
	self.continuousFireTimer = 0;
	self.continuousFireDuration = 300; // 5 seconds at 60 FPS
	self.continuousReloadTimer = 0;
	self.continuousReloadDuration = 180; // 3 seconds at 60 FPS
	switch (self.id) {
		case 'landmine':
			self.fireRate = 30;
			self.damage = 5;
			self.range = 2.5 * CELL_SIZE;
			self.bulletSpeed = 7;
			break;
		case 'sniper':
			self.fireRate = 90;
			self.damage = 25;
			self.range = 5 * CELL_SIZE;
			self.bulletSpeed = 25;
			break;
		case 'flamethrower':
			self.fireRate = 2.5; // Very fast fire rate during continuous shooting (quarter of original delay)
			self.damage = 8; // Lower per-hit damage but continuous
			self.range = 2.5 * CELL_SIZE;
			self.bulletSpeed = 6;
			break;
		case 'slow':
			self.fireRate = 30;
			self.damage = 15; // Increased from 8 to 15 for stronger missiles
			self.range = 3.5 * CELL_SIZE;
			self.bulletSpeed = 5;
			break;
		case 'poison':
			self.fireRate = 70;
			self.damage = 12;
			self.range = 3.2 * CELL_SIZE;
			self.bulletSpeed = 5;
			break;
		case 'tank':
			self.fireRate = 90;
			self.damage = 50; // Increased base damage for tank
			self.range = 4.0 * CELL_SIZE;
			self.bulletSpeed = 4;
			break;
	}
	var assetToUse = self.id === 'landmine' ? 'landmine' : self.id === 'sniper' ? 'Sniper' : self.id === 'flamethrower' ? 'Flamethrower' : self.id === 'slow' ? 'Rocket' : self.id === 'trap' ? 'Shooter' : self.id === 'tank' ? 'Tank' : 'tower';
	var baseGraphics = self.attachAsset(assetToUse, {
		anchorX: 0.5,
		anchorY: self.id === 'sniper' ? 0.0 : 0.5
	});
	// Rotate sniper tower left by 40 degrees
	if (self.id === 'sniper') {
		baseGraphics.rotation = -40 * Math.PI / 180; // Convert 40 degrees to radians and make it negative for left rotation
	}
	// Flame effects removed for performance
	switch (self.id) {
		case 'landmine':
			// Remove tint to show natural landmine asset
			break;
		case 'sniper':
			// Remove tint to show natural sniper asset
			break;
		case 'flamethrower':
			// Remove tint to show natural flamethrower asset
			break;
		case 'slow':
			// Remove tint to show natural rocket asset
			break;
		case 'poison':
			baseGraphics.tint = 0x00FFAA;
			break;
		case 'tank':
			// Remove tint to show natural tank asset
			break;
		case 'trap':
			baseGraphics.tint = 0x555555; // Dark gray for machine gun
			break;
		default:
			baseGraphics.tint = 0xAAAAAA;
	}
	// Add health bar for towers that need them (excluding landmine)
	self.towerHealthBarOutline = null;
	self.towerHealthBarBG = null;
	self.towerHealthBar = null;
	if (self.id === 'flamethrower' || self.id === 'trap' || self.id === 'sniper' || self.id === 'slow' || self.id === 'tank') {
		// Create health bar outline
		self.towerHealthBarOutline = self.attachAsset('towerHealthBarOutline', {
			anchorX: 0,
			anchorY: 0.5
		});
		// Create health bar background (red)
		self.towerHealthBarBG = self.attachAsset('towerHealthBar', {
			anchorX: 0,
			anchorY: 0.5
		});
		self.towerHealthBarBG.tint = 0xff0000;
		// Create health bar foreground (green)
		self.towerHealthBar = self.attachAsset('towerHealthBar', {
			anchorX: 0,
			anchorY: 0.5
		});
		self.towerHealthBar.tint = 0x00ff00;
		// Position health bars below the level indicators to avoid overlap
		var healthBarY = CELL_SIZE * 0.7 + 25; // Position below level indicators with some spacing
		self.towerHealthBarOutline.y = healthBarY;
		self.towerHealthBarBG.y = healthBarY;
		self.towerHealthBar.y = healthBarY;
		// Center health bars horizontally
		self.towerHealthBarOutline.x = -self.towerHealthBarOutline.width / 2;
		self.towerHealthBarBG.x = -self.towerHealthBarBG.width / 2;
		self.towerHealthBar.x = -self.towerHealthBar.width / 2;
	}
	var levelIndicators = [];
	var maxDots = self.maxLevel;
	var dotSpacing = baseGraphics.width / (maxDots + 1);
	var dotSize = CELL_SIZE / 6;
	for (var i = 0; i < maxDots; i++) {
		var dot = new Container();
		var outlineCircle = dot.attachAsset('towerLevelIndicator', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		outlineCircle.width = dotSize + 4;
		outlineCircle.height = dotSize + 4;
		outlineCircle.tint = 0x000000;
		var towerLevelIndicator = dot.attachAsset('towerLevelIndicator', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		towerLevelIndicator.width = dotSize;
		towerLevelIndicator.height = dotSize;
		towerLevelIndicator.tint = 0xCCCCCC;
		dot.x = -CELL_SIZE + dotSpacing * (i + 1);
		dot.y = CELL_SIZE * 0.7;
		self.addChild(dot);
		levelIndicators.push(dot);
	}
	var gunContainer = new Container();
	self.addChild(gunContainer);
	self.updateLevelIndicators = function () {
		for (var i = 0; i < maxDots; i++) {
			var dot = levelIndicators[i];
			var towerLevelIndicator = dot.children[1];
			if (i < self.level) {
				towerLevelIndicator.tint = 0xFFFFFF;
			} else {
				switch (self.id) {
					case 'landmine':
						towerLevelIndicator.tint = 0x00AAFF;
						break;
					case 'sniper':
						towerLevelIndicator.tint = 0xFF5500;
						break;
					case 'flamethrower':
						towerLevelIndicator.tint = 0xFF4500;
						break;
					case 'slow':
						towerLevelIndicator.tint = 0x9900FF;
						break;
					case 'poison':
						towerLevelIndicator.tint = 0x00FFAA;
						break;
					default:
						towerLevelIndicator.tint = 0xAAAAAA;
				}
			}
		}
	};
	self.updateLevelIndicators();
	self.refreshCellsInRange = function () {
		for (var i = 0; i < self.cellsInRange.length; i++) {
			var cell = self.cellsInRange[i];
			var towerIndex = cell.towersInRange.indexOf(self);
			if (towerIndex !== -1) {
				cell.towersInRange.splice(towerIndex, 1);
			}
		}
		self.cellsInRange = [];
		var rangeRadius = self.getRange() / CELL_SIZE;
		var centerX = self.gridX + 1;
		var centerY = self.gridY + 1;
		var minI = Math.floor(centerX - rangeRadius - 0.5);
		var maxI = Math.ceil(centerX + rangeRadius + 0.5);
		var minJ = Math.floor(centerY - rangeRadius - 0.5);
		var maxJ = Math.ceil(centerY + rangeRadius + 0.5);
		for (var i = minI; i <= maxI; i++) {
			for (var j = minJ; j <= maxJ; j++) {
				var closestX = Math.max(i, Math.min(centerX, i + 1));
				var closestY = Math.max(j, Math.min(centerY, j + 1));
				var deltaX = closestX - centerX;
				var deltaY = closestY - centerY;
				var distanceSquared = deltaX * deltaX + deltaY * deltaY;
				if (distanceSquared <= rangeRadius * rangeRadius) {
					var cell = grid.getCell(i, j);
					if (cell) {
						self.cellsInRange.push(cell);
						cell.towersInRange.push(self);
					}
				}
			}
		}
		// Only render debug when tower is selected to improve performance
		if (selectedTower === self) {
			grid.renderDebug();
		}
	};
	self.getTotalValue = function () {
		var baseTowerCost = getTowerCost(self.id);
		var totalInvestment = baseTowerCost;
		var baseUpgradeCost = baseTowerCost; // Upgrade cost now scales with base tower cost
		for (var i = 1; i < self.level; i++) {
			totalInvestment += Math.floor(baseUpgradeCost * Math.pow(2, i - 1));
		}
		return totalInvestment;
	};
	self.upgrade = function () {
		if (self.level < self.maxLevel) {
			// Exponential upgrade cost: base cost * (2 ^ (level-1)), scaled by tower base cost
			var baseUpgradeCost = getTowerCost(self.id);
			var upgradeCost;
			// Make last upgrade level extra expensive
			if (self.level === self.maxLevel - 1) {
				upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.level - 1) * 3.5 / 2); // Half the cost for final upgrade
			} else {
				upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.level - 1));
			}
			if (gold >= upgradeCost) {
				setGold(gold - upgradeCost);
				self.level++;
				// No need to update self.range here; getRange() is now the source of truth
				// Apply tower-specific upgrades based on type
				if (self.id === 'landmine') {
					if (self.level === self.maxLevel) {
						// Extra powerful last upgrade (double the effect)
						self.fireRate = Math.max(4, 30 - self.level * 9); // double the effect
						self.damage = 5 + self.level * 10; // double the effect
						self.bulletSpeed = 7 + self.level * 2.4; // double the effect
					} else {
						self.fireRate = Math.max(15, 30 - self.level * 3); // Fast tower gets faster with upgrades
						self.damage = 5 + self.level * 3;
						self.bulletSpeed = 7 + self.level * 0.7;
					}
				} else {
					// Special scaling for missiles towers
					if (self.id === 'slow') {
						if (self.level === self.maxLevel) {
							// Extra powerful last upgrade for missiles (triple the effect)
							self.fireRate = Math.max(3, 30 - self.level * 15); // Much faster fire rate
							self.damage = 15 + self.level * 30; // Much higher damage scaling
							self.bulletSpeed = 5 + self.level * 3; // Faster missiles
						} else {
							self.fireRate = Math.max(10, 30 - self.level * 5); // Faster than base scaling
							self.damage = 15 + self.level * 10; // Higher damage per level
							self.bulletSpeed = 5 + self.level * 1;
						}
					} else {
						if (self.level === self.maxLevel) {
							// Extra powerful last upgrade for all other towers (double the effect)
							self.fireRate = Math.max(5, 60 - self.level * 24); // double the effect
							self.damage = 10 + self.level * 20; // double the effect
							self.bulletSpeed = 5 + self.level * 2.4; // double the effect
						} else {
							self.fireRate = Math.max(20, 60 - self.level * 8);
							self.damage = 10 + self.level * 5;
							self.bulletSpeed = 5 + self.level * 0.5;
						}
					}
				}
				self.refreshCellsInRange();
				self.updateLevelIndicators();
				if (self.level > 1) {
					var levelDot = levelIndicators[self.level - 1].children[1];
					tween(levelDot, {
						scaleX: 1.5,
						scaleY: 1.5
					}, {
						duration: 300,
						easing: tween.elasticOut,
						onFinish: function onFinish() {
							tween(levelDot, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 200,
								easing: tween.easeOut
							});
						}
					});
				}
				return true;
			} else {
				var notification = game.addChild(new Notification("Not enough gold to upgrade!"));
				notification.x = 2048 / 2;
				notification.y = grid.height - 50;
				return false;
			}
		}
		return false;
	};
	self.findTarget = function () {
		var closestEnemy = null;
		var closestScore = Infinity;
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			var dx = enemy.x - self.x;
			var dy = enemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Check if enemy is in range
			if (distance <= self.getRange()) {
				// Handle flying enemies differently - they can be targeted regardless of path
				if (enemy.isFlying) {
					// For flying enemies, prioritize by distance to the goal
					if (enemy.flyingTarget) {
						var goalX = enemy.flyingTarget.x;
						var goalY = enemy.flyingTarget.y;
						var distToGoal = Math.sqrt((goalX - enemy.cellX) * (goalX - enemy.cellX) + (goalY - enemy.cellY) * (goalY - enemy.cellY));
						// Use distance to goal as score
						if (distToGoal < closestScore) {
							closestScore = distToGoal;
							closestEnemy = enemy;
						}
					} else {
						// If no flying target yet (shouldn't happen), prioritize by distance to tower
						if (distance < closestScore) {
							closestScore = distance;
							closestEnemy = enemy;
						}
					}
				} else {
					// For ground enemies, landmine towers target any ground enemy in range
					if (self.id === 'landmine') {
						// Landmine targets any ground enemy by distance
						if (distance < closestScore) {
							closestScore = distance;
							closestEnemy = enemy;
						}
					} else {
						// For sniper and other towers, use the original path-based targeting
						// Get the cell for this enemy
						var cell = grid.getCell(enemy.cellX, enemy.cellY);
						// Allow targeting of tank enemies even if they're not on the main path (they're in support positions)
						if (enemy.type === 'tank' || cell && cell.pathId === pathId) {
							// For tank enemies, use distance-based targeting since they may not be on the main path
							var targetScore = enemy.type === 'tank' ? distance : cell.score;
							// Use the cell's score (distance to exit) for prioritization
							// Lower score means closer to exit
							if (targetScore < closestScore) {
								closestScore = targetScore;
								closestEnemy = enemy;
							}
						}
					}
				}
			}
		}
		if (!closestEnemy) {
			self.targetEnemy = null;
		}
		return closestEnemy;
	};
	self.update = function () {
		// Only find targets every 3 frames to reduce performance impact
		if (LK.ticks % 3 === 0) {
			self.targetEnemy = self.findTarget();
		}
		// Clean up targeted enemies list for rocket launcher towers
		if (self.id === 'slow' && self.targetedEnemies) {
			// Remove enemies that are dead or out of range
			for (var i = self.targetedEnemies.length - 1; i >= 0; i--) {
				var targetedEnemy = self.targetedEnemies[i];
				if (!targetedEnemy.parent || targetedEnemy.health <= 0 || !self.isInRange(targetedEnemy)) {
					self.targetedEnemies.splice(i, 1);
				}
			}
		}
		// Flame animation removed for flamethrower towers
		// Special handling for landmine towers - explode on contact
		if (self.id === 'landmine' && self.targetEnemy) {
			var dx = self.targetEnemy.x - self.x;
			var dy = self.targetEnemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Check if enemy is close enough to trigger explosion (within 50 pixels) and is ground-based
			if (distance <= 50 && !self.targetEnemy.isFlying) {
				// Create landmine explosion effect with enhanced animation
				var landmineExplosion = new EffectIndicator(self.x, self.y, 'splash');
				landmineExplosion.children[0].tint = 0xFF4500; // Orange explosion color
				landmineExplosion.children[0].width = landmineExplosion.children[0].height = CELL_SIZE * 2.5;
				landmineExplosion.scaleX = 0.3;
				landmineExplosion.scaleY = 0.3;
				landmineExplosion.alpha = 1;
				game.addChild(landmineExplosion);
				// Multi-stage landmine explosion animation
				tween(landmineExplosion, {
					scaleX: 1.8,
					scaleY: 1.8,
					alpha: 0.9
				}, {
					duration: 150,
					easing: tween.elasticOut,
					onFinish: function onFinish() {
						tween(landmineExplosion, {
							scaleX: 2.5,
							scaleY: 2.5,
							alpha: 0
						}, {
							duration: 300,
							easing: tween.easeIn,
							onFinish: function onFinish() {
								landmineExplosion.destroy();
							}
						});
					}
				});
				// Create enemy explosion effect with enhanced animation
				var enemyExplosion = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'splash');
				enemyExplosion.children[0].tint = 0xFF0000; // Red explosion color
				enemyExplosion.children[0].width = enemyExplosion.children[0].height = CELL_SIZE * 2;
				enemyExplosion.scaleX = 0.2;
				enemyExplosion.scaleY = 0.2;
				enemyExplosion.alpha = 1;
				game.addChild(enemyExplosion);
				// Multi-stage enemy explosion animation
				tween(enemyExplosion, {
					scaleX: 1.5,
					scaleY: 1.5,
					alpha: 0.8
				}, {
					duration: 120,
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						tween(enemyExplosion, {
							scaleX: 2.2,
							scaleY: 2.2,
							alpha: 0
						}, {
							duration: 250,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								enemyExplosion.destroy();
							}
						});
					}
				});
				// Create additional shockwave effect for landmine
				var shockwave = new EffectIndicator(self.x, self.y, 'splash');
				shockwave.children[0].tint = 0xFFFFFF;
				shockwave.children[0].alpha = 0.3;
				shockwave.children[0].width = shockwave.children[0].height = CELL_SIZE * 0.5;
				shockwave.alpha = 0.8;
				game.addChild(shockwave);
				// Animate shockwave expanding rapidly
				tween(shockwave, {
					scaleX: 4,
					scaleY: 4,
					alpha: 0
				}, {
					duration: 400,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						shockwave.destroy();
					}
				});
				// Mark enemy for destruction
				self.targetEnemy.health = 0;
				// Mark landmine tower for destruction
				self.shouldDestroy = true;
				return;
			}
		}
		if (self.targetEnemy && self.id !== 'landmine') {
			var dx = self.targetEnemy.x - self.x;
			var dy = self.targetEnemy.y - self.y;
			var angle = Math.atan2(dy, dx);
			// Special rotation handling for sniper towers
			if (self.id === 'sniper') {
				// Use the main tower graphics (baseGraphics) for sniper rotation
				var sniperGraphics = self.children[0]; // The sniper asset
				if (sniperGraphics.targetRotation === undefined) {
					sniperGraphics.targetRotation = angle;
					sniperGraphics.rotation = angle;
				} else {
					if (Math.abs(angle - sniperGraphics.targetRotation) > 0.1) {
						// Stop any ongoing rotation tweens
						tween.stop(sniperGraphics, {
							rotation: true
						});
						// Calculate the shortest angle to rotate
						var currentRotation = sniperGraphics.rotation;
						var angleDiff = angle - currentRotation;
						// Normalize angle difference to -PI to PI range for shortest path
						while (angleDiff > Math.PI) {
							angleDiff -= Math.PI * 2;
						}
						while (angleDiff < -Math.PI) {
							angleDiff += Math.PI * 2;
						}
						sniperGraphics.targetRotation = angle;
						tween(sniperGraphics, {
							rotation: currentRotation + angleDiff
						}, {
							duration: 200,
							easing: tween.easeOut
						});
					}
				}
			} else {
				gunContainer.rotation = angle;
			}
			// Special continuous firing logic for flamethrower
			if (self.id === 'flamethrower') {
				// Handle continuous reload timer
				if (self.continuousReloadTimer > 0) {
					self.continuousReloadTimer--;
				} else if (!self.isContinuousFiring && self.targetEnemy) {
					// Start continuous firing
					self.isContinuousFiring = true;
					self.continuousFireTimer = self.continuousFireDuration;
				} else if (self.isContinuousFiring) {
					// Continue firing during the continuous period
					if (self.continuousFireTimer > 0) {
						self.continuousFireTimer--;
						// Fire at the fast rate during continuous shooting
						if (LK.ticks - self.lastFired >= self.fireRate) {
							self.fire();
							self.lastFired = LK.ticks;
						}
					} else {
						// End continuous firing, start reload
						self.isContinuousFiring = false;
						self.continuousReloadTimer = self.continuousReloadDuration;
					}
				}
			} else {
				// Normal firing logic for other tower types
				if (LK.ticks - self.lastFired >= self.fireRate) {
					self.fire();
					self.lastFired = LK.ticks;
				}
			}
		}
	};
	self.down = function (x, y, obj) {
		var existingMenus = game.children.filter(function (child) {
			return child instanceof UpgradeMenu;
		});
		var hasOwnMenu = false;
		var rangeCircle = null;
		for (var i = 0; i < game.children.length; i++) {
			if (game.children[i].isTowerRange && game.children[i].tower === self) {
				rangeCircle = game.children[i];
				break;
			}
		}
		for (var i = 0; i < existingMenus.length; i++) {
			if (existingMenus[i].tower === self) {
				hasOwnMenu = true;
				break;
			}
		}
		if (hasOwnMenu) {
			for (var i = 0; i < existingMenus.length; i++) {
				if (existingMenus[i].tower === self) {
					hideUpgradeMenu(existingMenus[i]);
				}
			}
			if (rangeCircle) {
				game.removeChild(rangeCircle);
			}
			selectedTower = null;
			grid.renderDebug();
			return;
		}
		for (var i = 0; i < existingMenus.length; i++) {
			existingMenus[i].destroy();
		}
		for (var i = game.children.length - 1; i >= 0; i--) {
			if (game.children[i].isTowerRange) {
				game.removeChild(game.children[i]);
			}
		}
		selectedTower = self;
		var rangeIndicator = new Container();
		rangeIndicator.isTowerRange = true;
		rangeIndicator.tower = self;
		game.addChild(rangeIndicator);
		rangeIndicator.x = self.x;
		rangeIndicator.y = self.y;
		var rangeGraphics = rangeIndicator.attachAsset('rangeCircle', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		rangeGraphics.width = rangeGraphics.height = self.getRange() * 2;
		rangeGraphics.alpha = 0.3;
		var upgradeMenu = new UpgradeMenu(self);
		game.addChild(upgradeMenu);
		upgradeMenu.x = 2048 / 2;
		tween(upgradeMenu, {
			y: 2732 - 225
		}, {
			duration: 200,
			easing: tween.backOut
		});
		grid.renderDebug();
	};
	self.isInRange = function (enemy) {
		if (!enemy) {
			return false;
		}
		var dx = enemy.x - self.x;
		var dy = enemy.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		return distance <= self.getRange();
	};
	// Initialize tower health based on tower type
	if (self.id === 'flamethrower' || self.id === 'trap' || self.id === 'sniper' || self.id === 'slow' || self.id === 'tank') {
		// Set health values based on tower type
		if (self.id === 'slow') {
			self.towerHealth = 300; // 3x base health for missiles
			self.maxTowerHealth = 300;
		} else if (self.id === 'tank') {
			self.towerHealth = 500; // 5x base health for tank towers - very strong
			self.maxTowerHealth = 500;
		} else if (self.id === 'sniper') {
			self.towerHealth = 150; // Medium health for sniper
			self.maxTowerHealth = 150;
		} else if (self.id === 'flamethrower') {
			self.towerHealth = 120; // Medium health for flamethrower
			self.maxTowerHealth = 120;
		} else {
			self.towerHealth = 100; // Base tower health for trap/shooter
			self.maxTowerHealth = 100;
		}
	}
	// Method to handle damage from enemy bullets
	self.takeDamage = function (damage) {
		// Special handling for sniper towers - track hits instead of health
		if (self.id === 'sniper') {
			// Initialize hit counter if not set
			if (self.hitCount === undefined) {
				self.hitCount = 0;
			}
			self.hitCount++;
			// Create hit indicator effect
			var hitEffect = new EffectIndicator(self.x, self.y, 'sniper');
			hitEffect.children[0].tint = 0xFF0000; // Red hit indicator
			hitEffect.children[0].width = hitEffect.children[0].height = CELL_SIZE;
			game.addChild(hitEffect);
			// Update health bar
			if (self.towerHealthBar) {
				var healthPercentage = Math.max(0, (5 - self.hitCount) / 5);
				self.towerHealthBar.width = 60 * healthPercentage;
			}
			// Destroy sniper after 5 hits
			if (self.hitCount >= 5) {
				// Mark sniper for destruction
				self.shouldDestroy = true;
				// Create destruction effect
				var destructionEffect = new EffectIndicator(self.x, self.y, 'splash');
				destructionEffect.children[0].tint = 0xFF4500; // Orange destruction color
				destructionEffect.children[0].width = destructionEffect.children[0].height = CELL_SIZE * 2;
				game.addChild(destructionEffect);
			}
		} else {
			// Initialize tower health if not set for non-sniper towers
			if (self.towerHealth === undefined) {
				// Missiles towers have much higher health to make them stronger
				if (self.id === 'slow') {
					self.towerHealth = 300; // 3x base health for missiles
					self.maxTowerHealth = 300;
				} else if (self.id === 'tank') {
					self.towerHealth = 500; // 5x base health for tank towers - very strong
					self.maxTowerHealth = 500;
				} else {
					self.towerHealth = 100; // Base tower health
					self.maxTowerHealth = 100;
				}
			}
			self.towerHealth -= damage;
			// Update health bar
			if (self.towerHealthBar && self.maxTowerHealth > 0) {
				var healthPercentage = Math.max(0, self.towerHealth / self.maxTowerHealth);
				self.towerHealthBar.width = 60 * healthPercentage;
			}
			if (self.towerHealth <= 0) {
				self.towerHealth = 0;
				// Mark tower for destruction
				self.shouldDestroy = true;
				// Create destruction effect
				var destructionEffect = new EffectIndicator(self.x, self.y, 'splash');
				destructionEffect.children[0].tint = 0xFF4500; // Orange destruction color
				destructionEffect.children[0].width = destructionEffect.children[0].height = CELL_SIZE * 2;
				game.addChild(destructionEffect);
			}
		}
	};
	self.fire = function () {
		// Landmine towers cannot shoot normally
		if (self.id === 'landmine') {
			return;
		}
		// Machine gun shooting function
		if (self.id === 'trap') {
			if (self.targetEnemy) {
				// Fire multiple bullets in rapid succession for higher ammunition density
				var bulletsToFire = 3; // Fire 3 bullets per shot for higher density
				for (var bulletIndex = 0; bulletIndex < bulletsToFire; bulletIndex++) {
					var bulletX = self.x + Math.cos(gunContainer.rotation) * 40;
					var bulletY = self.y + Math.sin(gunContainer.rotation) * 40;
					var bullet = new Bullet(bulletX, bulletY, self.targetEnemy, self.damage, self.bulletSpeed);
					// Set bullet type for machine gun
					bullet.type = 'trap';
					// Machine gun bullets are smaller and faster
					bullet.children[0].tint = 0x555555; // Dark gray for machine gun bullets
					bullet.children[0].width = 25;
					bullet.children[0].height = 25;
					// Add slight delay between bullets for visual effect
					if (bulletIndex > 0) {
						bullet.x += (Math.random() - 0.5) * 10; // Small random offset
						bullet.y += (Math.random() - 0.5) * 10;
					}
					game.addChild(bullet);
					bullets.push(bullet);
					self.targetEnemy.bulletsTargetingThis.push(bullet);
				}
				// Machine gun recoil effect
				tween.stop(gunContainer, {
					x: true,
					y: true,
					scaleX: true,
					scaleY: true
				});
				if (gunContainer._restX === undefined) {
					gunContainer._restX = 0;
				}
				if (gunContainer._restY === undefined) {
					gunContainer._restY = 0;
				}
				if (gunContainer._restScaleX === undefined) {
					gunContainer._restScaleX = 1;
				}
				if (gunContainer._restScaleY === undefined) {
					gunContainer._restScaleY = 1;
				}
				gunContainer.x = gunContainer._restX;
				gunContainer.y = gunContainer._restY;
				gunContainer.scaleX = gunContainer._restScaleX;
				gunContainer.scaleY = gunContainer._restScaleY;
				var recoilDistance = 6;
				var recoilX = -Math.cos(gunContainer.rotation) * recoilDistance;
				var recoilY = -Math.sin(gunContainer.rotation) * recoilDistance;
				tween(gunContainer, {
					x: gunContainer._restX + recoilX,
					y: gunContainer._restY + recoilY
				}, {
					duration: 40,
					easing: tween.cubicOut,
					onFinish: function onFinish() {
						tween(gunContainer, {
							x: gunContainer._restX,
							y: gunContainer._restY
						}, {
							duration: 60,
							easing: tween.cubicIn
						});
					}
				});
			}
			return;
		}
		if (self.targetEnemy) {
			var potentialDamage = 0;
			for (var i = 0; i < self.targetEnemy.bulletsTargetingThis.length; i++) {
				potentialDamage += self.targetEnemy.bulletsTargetingThis[i].damage;
			}
			// For rocket launcher (slow) towers, check if we've already fired at this target
			if (self.id === 'slow') {
				// Initialize targeted enemies array if not exists
				if (!self.targetedEnemies) {
					self.targetedEnemies = [];
				}
				// Check if we've already targeted this enemy
				var alreadyTargeted = false;
				for (var i = 0; i < self.targetedEnemies.length; i++) {
					if (self.targetedEnemies[i] === self.targetEnemy) {
						alreadyTargeted = true;
						break;
					}
				}
				// If already targeted, don't fire again
				if (alreadyTargeted) {
					return;
				}
				// Add this enemy to our targeted list
				self.targetedEnemies.push(self.targetEnemy);
			}
			// Always fire if we have a target enemy - removed health vs potential damage check that was blocking boss attacks
			if (self.targetEnemy) {
				// Special handling for flamethrower - create continuous flame spray
				if (self.id === 'flamethrower') {
					// Create multiple flame particles for continuous spray effect
					var flamesToCreate = 3; // Create multiple flames for denser spray
					for (var flameIndex = 0; flameIndex < flamesToCreate; flameIndex++) {
						var flameParticle = new Container();
						var flameGraphics = flameParticle.attachAsset('rangeCircle', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						flameGraphics.width = 25 + Math.random() * 15;
						flameGraphics.height = 35 + Math.random() * 20;
						flameGraphics.tint = Math.random() > 0.5 ? 0xFF4500 : 0xFF6600;
						flameGraphics.alpha = 0.7 + Math.random() * 0.3;
						// Position flame particle at tower with slight spread
						var spreadAngle = (Math.random() - 0.5) * 0.4; // 20 degree spread
						var startAngle = gunContainer.rotation + spreadAngle;
						var startDistance = 30 + Math.random() * 10;
						flameParticle.x = self.x + Math.cos(startAngle) * startDistance;
						flameParticle.y = self.y + Math.sin(startAngle) * startDistance;
						// Calculate target position with spread
						var targetDistance = self.getRange() * (0.6 + Math.random() * 0.4);
						var targetX = self.x + Math.cos(startAngle) * targetDistance;
						var targetY = self.y + Math.sin(startAngle) * targetDistance;
						// Store damage info for area effect
						flameParticle.damage = self.damage;
						flameParticle.sourceTowerLevel = self.level;
						game.addChild(flameParticle);
						// Animate flame particle moving toward target area
						tween(flameParticle, {
							x: targetX,
							y: targetY,
							scaleX: 1.5,
							scaleY: 1.5
						}, {
							duration: 400 + Math.random() * 200,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								// Apply area damage when flame reaches target area
								var coneRange = CELL_SIZE * 1.2;
								for (var i = 0; i < enemies.length; i++) {
									var enemy = enemies[i];
									var dx = enemy.x - flameParticle.x;
									var dy = enemy.y - flameParticle.y;
									var distance = Math.sqrt(dx * dx + dy * dy);
									if (distance <= coneRange) {
										// Apply flame damage
										enemy.health -= flameParticle.damage * 0.8;
										if (enemy.health <= 0) {
											enemy.health = 0;
										} else {
											enemy.healthBar.width = enemy.health / enemy.maxHealth * 70;
										}
										// Apply burning effect
										if (!enemy.isImmune) {
											enemy.burning = true;
											enemy.burnDamage = flameParticle.damage * 0.3;
											enemy.burnDuration = 180;
										}
										// Create visual flame effect
										var flameEffect = new EffectIndicator(enemy.x, enemy.y, 'flamethrower');
										game.addChild(flameEffect);
									}
								}
								// Fade out flame particle
								tween(flameParticle, {
									alpha: 0,
									scaleX: 0.5,
									scaleY: 0.5
								}, {
									duration: 200,
									easing: tween.easeIn,
									onFinish: function onFinish() {
										flameParticle.destroy();
									}
								});
							}
						});
					}
				} else {
					// Regular bullet creation for other tower types
					var bulletX = self.x + Math.cos(gunContainer.rotation) * 40;
					var bulletY = self.y + Math.sin(gunContainer.rotation) * 40;
					var bullet = new Bullet(bulletX, bulletY, self.targetEnemy, self.damage, self.bulletSpeed);
					// Set bullet type based on tower type
					bullet.type = self.id;
					// For slow tower, pass level for scaling slow effect
					if (self.id === 'slow') {
						bullet.sourceTowerLevel = self.level;
					}
					// Customize bullet appearance based on tower type
					switch (self.id) {
						case 'sniper':
							bullet.children[0].tint = 0xFF5500;
							bullet.children[0].width = 15;
							bullet.children[0].height = 15;
							break;
						case 'slow':
							// Replace bullet graphics with missile asset
							var missileGraphics = bullet.attachAsset('missiles', {
								anchorX: 0.5,
								anchorY: 0.5
							});
							// Remove the original bullet graphics
							bullet.removeChild(bullet.children[0]);
							break;
						case 'poison':
							bullet.children[0].tint = 0x00FFAA;
							bullet.children[0].width = 35;
							bullet.children[0].height = 35;
							break;
						case 'tank':
							bullet.children[0].tint = 0x8B4513;
							bullet.children[0].width = 40;
							bullet.children[0].height = 40;
							break;
					}
					game.addChild(bullet);
					bullets.push(bullet);
					self.targetEnemy.bulletsTargetingThis.push(bullet);
				}
				// --- Fire recoil effect for gunContainer ---
				// Stop any ongoing recoil tweens before starting a new one
				tween.stop(gunContainer, {
					x: true,
					y: true,
					scaleX: true,
					scaleY: true
				});
				// Always use the original resting position for recoil, never accumulate offset
				if (gunContainer._restX === undefined) {
					gunContainer._restX = 0;
				}
				if (gunContainer._restY === undefined) {
					gunContainer._restY = 0;
				}
				if (gunContainer._restScaleX === undefined) {
					gunContainer._restScaleX = 1;
				}
				if (gunContainer._restScaleY === undefined) {
					gunContainer._restScaleY = 1;
				}
				// Reset to resting position before animating (in case of interrupted tweens)
				gunContainer.x = gunContainer._restX;
				gunContainer.y = gunContainer._restY;
				gunContainer.scaleX = gunContainer._restScaleX;
				gunContainer.scaleY = gunContainer._restScaleY;
				// Calculate recoil offset (recoil back along the gun's rotation)
				var recoilDistance = 8;
				var recoilX = -Math.cos(gunContainer.rotation) * recoilDistance;
				var recoilY = -Math.sin(gunContainer.rotation) * recoilDistance;
				// Animate recoil back from the resting position
				tween(gunContainer, {
					x: gunContainer._restX + recoilX,
					y: gunContainer._restY + recoilY
				}, {
					duration: 60,
					easing: tween.cubicOut,
					onFinish: function onFinish() {
						// Animate return to original position/scale
						tween(gunContainer, {
							x: gunContainer._restX,
							y: gunContainer._restY
						}, {
							duration: 90,
							easing: tween.cubicIn
						});
					}
				});
			}
		}
	};
	self.placeOnGrid = function (gridX, gridY) {
		self.gridX = gridX;
		self.gridY = gridY;
		self.x = grid.x + gridX * CELL_SIZE + CELL_SIZE / 2;
		self.y = grid.y + gridY * CELL_SIZE + CELL_SIZE / 2;
		self.isPlaced = true;
		for (var i = 0; i < 2; i++) {
			for (var j = 0; j < 2; j++) {
				var cell = grid.getCell(gridX + i, gridY + j);
				if (cell) {
					// Store original type before placing tower
					cell.originalType = cell.type;
					// Allow placement on any cell type - don't force to wall type
				}
			}
		}
		self.refreshCellsInRange();
	};
	return self;
});
var TowerPreview = Container.expand(function () {
	var self = Container.call(this);
	var towerRange = 3;
	var rangeInPixels = towerRange * CELL_SIZE;
	self.towerType = 'trap';
	self.hasEnoughGold = true;
	var rangeIndicator = new Container();
	self.addChild(rangeIndicator);
	var rangeGraphics = rangeIndicator.attachAsset('rangeCircle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	rangeGraphics.alpha = 0.3;
	var previewGraphics = self.attachAsset('Box', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	previewGraphics.width = CELL_SIZE * 2;
	previewGraphics.height = CELL_SIZE * 2;
	self.canPlace = false;
	self.gridX = 0;
	self.gridY = 0;
	self.blockedByEnemy = false;
	var updateCounter = 0;
	self.update = function () {
		// Only check every 10 frames to reduce performance impact
		updateCounter++;
		if (updateCounter % 10 === 0) {
			var previousHasEnoughGold = self.hasEnoughGold;
			self.hasEnoughGold = gold >= getTowerCost(self.towerType);
			// Only update appearance if the affordability status has changed
			if (previousHasEnoughGold !== self.hasEnoughGold) {
				self.updateAppearance();
			}
		}
	};
	self.updateAppearance = function () {
		// Use Tower class to get the source of truth for range without placing it
		var tempTower = new Tower(self.towerType);
		var previewRange = tempTower.getRange();
		// Clean up tempTower immediately without placing it on grid
		tempTower.destroy();
		// Set range indicator using unified range logic
		rangeGraphics.width = rangeGraphics.height = previewRange * 2;
		// Color preview box based on placement validity
		if (self.canPlace && self.hasEnoughGold) {
			// Green for valid placement (including tank towers)
			previewGraphics.tint = 0x00FF00;
			// Animate green pulsing for valid placement
			tween.stop(previewGraphics, {
				alpha: true
			});
			tween(previewGraphics, {
				alpha: 0.7
			}, {
				duration: 500,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					tween(previewGraphics, {
						alpha: 1.0
					}, {
						duration: 500,
						easing: tween.easeInOut
					});
				}
			});
		} else {
			// Red for invalid placement or insufficient gold
			previewGraphics.tint = 0xFF0000;
			// Stop any ongoing animations for invalid placement
			tween.stop(previewGraphics, {
				alpha: true
			});
			previewGraphics.alpha = 1.0;
		}
	};
	self.updatePlacementStatus = function () {
		var validGridPlacement = true;
		// Prevent placement in upper sixth of screen (y < 455)
		var screenY = grid.y + self.gridY * CELL_SIZE;
		if (screenY < 455) {
			validGridPlacement = false;
		} else {
			// For tank weapons, only allow placement in lower half of screen
			if (self.towerType === 'tank') {
				var screenCenterY = grid.y + (29 + 6) * CELL_SIZE / 2; // Grid height / 2
				if (screenY < screenCenterY) {
					validGridPlacement = false;
				}
			}
			// Allow placement anywhere else on the grid
			for (var i = 0; i < 2; i++) {
				for (var j = 0; j < 2; j++) {
					var cell = grid.getCell(self.gridX + i, self.gridY + j);
					if (!cell) {
						validGridPlacement = false;
						break;
					}
				}
				if (!validGridPlacement) {
					break;
				}
			}
		}
		self.blockedByEnemy = false;
		if (validGridPlacement) {
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				if (enemy.currentCellY < 4) {
					continue;
				}
				// Only check non-flying enemies, flying enemies can pass over towers
				if (!enemy.isFlying) {
					if (enemy.cellX >= self.gridX && enemy.cellX < self.gridX + 2 && enemy.cellY >= self.gridY && enemy.cellY < self.gridY + 2) {
						self.blockedByEnemy = true;
						break;
					}
					if (enemy.currentTarget) {
						var targetX = enemy.currentTarget.x;
						var targetY = enemy.currentTarget.y;
						if (targetX >= self.gridX && targetX < self.gridX + 2 && targetY >= self.gridY && targetY < self.gridY + 2) {
							self.blockedByEnemy = true;
							break;
						}
					}
				}
			}
		}
		self.canPlace = validGridPlacement && !self.blockedByEnemy;
		self.hasEnoughGold = gold >= getTowerCost(self.towerType);
		self.updateAppearance();
	};
	self.checkPlacement = function () {
		self.updatePlacementStatus();
	};
	self.snapToGrid = function (x, y) {
		var gridPosX = x - grid.x;
		var gridPosY = y - grid.y;
		self.gridX = Math.floor(gridPosX / CELL_SIZE);
		self.gridY = Math.floor(gridPosY / CELL_SIZE);
		self.x = grid.x + self.gridX * CELL_SIZE + CELL_SIZE / 2;
		self.y = grid.y + self.gridY * CELL_SIZE + CELL_SIZE / 2;
		self.checkPlacement();
	};
	return self;
});
var UpgradeMenu = Container.expand(function (tower) {
	var self = Container.call(this);
	self.tower = tower;
	self.y = 2732 + 225;
	var menuBackground = self.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	menuBackground.width = 2048;
	menuBackground.height = 500;
	menuBackground.tint = 0x444444;
	menuBackground.alpha = 0.9;
	var towerTypeName = self.tower.id === 'slow' ? 'Missiles' : self.tower.id === 'tank' ? 'Tank' : self.tower.id.charAt(0).toUpperCase() + self.tower.id.slice(1);
	var towerTypeText = new Text2(towerTypeName + ' Tower', {
		size: 80,
		fill: 0xFFFFFF,
		weight: 800
	});
	towerTypeText.anchor.set(0, 0);
	towerTypeText.x = -840;
	towerTypeText.y = -160;
	self.addChild(towerTypeText);
	var statsText = new Text2('Level: ' + self.tower.level + '/' + self.tower.maxLevel + '\nDamage: ' + self.tower.damage + '\nFire Rate: ' + (60 / self.tower.fireRate).toFixed(1) + '/s', {
		size: 70,
		fill: 0xFFFFFF,
		weight: 400
	});
	statsText.anchor.set(0, 0.5);
	statsText.x = -840;
	statsText.y = 50;
	self.addChild(statsText);
	var buttonsContainer = new Container();
	buttonsContainer.x = 500;
	self.addChild(buttonsContainer);
	var upgradeButton = new Container();
	buttonsContainer.addChild(upgradeButton);
	var buttonBackground = upgradeButton.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	buttonBackground.width = 500;
	buttonBackground.height = 150;
	var isMaxLevel = self.tower.level >= self.tower.maxLevel;
	// Exponential upgrade cost: base cost * (2 ^ (level-1)), scaled by tower base cost
	var baseUpgradeCost = getTowerCost(self.tower.id);
	var upgradeCost;
	if (isMaxLevel) {
		upgradeCost = 0;
	} else if (self.tower.level === self.tower.maxLevel - 1) {
		upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1) * 3.5 / 2);
	} else {
		upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1));
	}
	buttonBackground.tint = isMaxLevel ? 0x888888 : gold >= upgradeCost ? 0x00AA00 : 0x888888;
	var buttonText = new Text2(isMaxLevel ? 'Max Level' : 'Upgrade: ' + upgradeCost + ' gold', {
		size: 60,
		fill: 0xFFFFFF,
		weight: 800
	});
	buttonText.anchor.set(0.5, 0.5);
	upgradeButton.addChild(buttonText);
	var sellButton = new Container();
	buttonsContainer.addChild(sellButton);
	var sellButtonBackground = sellButton.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	sellButtonBackground.width = 500;
	sellButtonBackground.height = 150;
	sellButtonBackground.tint = 0xCC0000;
	var totalInvestment = self.tower.getTotalValue ? self.tower.getTotalValue() : 0;
	var sellValue = getTowerSellValue(totalInvestment);
	var sellButtonText = new Text2('Sell: +' + sellValue + ' gold', {
		size: 60,
		fill: 0xFFFFFF,
		weight: 800
	});
	sellButtonText.anchor.set(0.5, 0.5);
	sellButton.addChild(sellButtonText);
	upgradeButton.y = -85;
	sellButton.y = 85;
	var closeButton = new Container();
	self.addChild(closeButton);
	var closeBackground = closeButton.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	closeBackground.width = 90;
	closeBackground.height = 90;
	closeBackground.tint = 0xAA0000;
	var closeText = new Text2('X', {
		size: 68,
		fill: 0xFFFFFF,
		weight: 800
	});
	closeText.anchor.set(0.5, 0.5);
	closeButton.addChild(closeText);
	closeButton.x = menuBackground.width / 2 - 57;
	closeButton.y = -menuBackground.height / 2 + 57;
	upgradeButton.down = function (x, y, obj) {
		if (self.tower.level >= self.tower.maxLevel) {
			var notification = game.addChild(new Notification("Tower is already at max level!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 50;
			return;
		}
		if (self.tower.upgrade()) {
			// Exponential upgrade cost: base cost * (2 ^ (level-1)), scaled by tower base cost
			var baseUpgradeCost = getTowerCost(self.tower.id);
			if (self.tower.level >= self.tower.maxLevel) {
				upgradeCost = 0;
			} else if (self.tower.level === self.tower.maxLevel - 1) {
				upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1) * 3.5 / 2);
			} else {
				upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1));
			}
			statsText.setText('Level: ' + self.tower.level + '/' + self.tower.maxLevel + '\nDamage: ' + self.tower.damage + '\nFire Rate: ' + (60 / self.tower.fireRate).toFixed(1) + '/s');
			buttonText.setText('Upgrade: ' + upgradeCost + ' gold');
			var totalInvestment = self.tower.getTotalValue ? self.tower.getTotalValue() : 0;
			var sellValue = Math.floor(totalInvestment * 0.6);
			sellButtonText.setText('Sell: +' + sellValue + ' gold');
			if (self.tower.level >= self.tower.maxLevel) {
				buttonBackground.tint = 0x888888;
				buttonText.setText('Max Level');
			}
			var rangeCircle = null;
			for (var i = 0; i < game.children.length; i++) {
				if (game.children[i].isTowerRange && game.children[i].tower === self.tower) {
					rangeCircle = game.children[i];
					break;
				}
			}
			if (rangeCircle) {
				var rangeGraphics = rangeCircle.children[0];
				rangeGraphics.width = rangeGraphics.height = self.tower.getRange() * 2;
			} else {
				var newRangeIndicator = new Container();
				newRangeIndicator.isTowerRange = true;
				newRangeIndicator.tower = self.tower;
				game.addChildAt(newRangeIndicator, 0);
				newRangeIndicator.x = self.tower.x;
				newRangeIndicator.y = self.tower.y;
				var rangeGraphics = newRangeIndicator.attachAsset('rangeCircle', {
					anchorX: 0.5,
					anchorY: 0.5
				});
				rangeGraphics.width = rangeGraphics.height = self.tower.getRange() * 2;
				rangeGraphics.alpha = 0.3;
			}
			tween(self, {
				scaleX: 1.05,
				scaleY: 1.05
			}, {
				duration: 100,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					tween(self, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 100,
						easing: tween.easeIn
					});
				}
			});
		}
	};
	sellButton.down = function (x, y, obj) {
		var totalInvestment = self.tower.getTotalValue ? self.tower.getTotalValue() : 0;
		var sellValue = getTowerSellValue(totalInvestment);
		setGold(gold + sellValue);
		var notification = game.addChild(new Notification("Tower sold for " + sellValue + " gold!"));
		notification.x = 2048 / 2;
		notification.y = grid.height - 50;
		var gridX = self.tower.gridX;
		var gridY = self.tower.gridY;
		for (var i = 0; i < 2; i++) {
			for (var j = 0; j < 2; j++) {
				var cell = grid.getCell(gridX + i, gridY + j);
				if (cell) {
					// Restore original cell type or default to ground (type 1) if no original type stored
					cell.type = cell.originalType !== undefined ? cell.originalType : 1;
					var towerIndex = cell.towersInRange.indexOf(self.tower);
					if (towerIndex !== -1) {
						cell.towersInRange.splice(towerIndex, 1);
					}
				}
			}
		}
		if (selectedTower === self.tower) {
			selectedTower = null;
		}
		var towerIndex = towers.indexOf(self.tower);
		if (towerIndex !== -1) {
			towers.splice(towerIndex, 1);
		}
		towerLayer.removeChild(self.tower);
		grid.pathFind();
		grid.renderDebug();
		self.destroy();
		for (var i = 0; i < game.children.length; i++) {
			if (game.children[i].isTowerRange && game.children[i].tower === self.tower) {
				game.removeChild(game.children[i]);
				break;
			}
		}
	};
	closeButton.down = function (x, y, obj) {
		hideUpgradeMenu(self);
		selectedTower = null;
		grid.renderDebug();
	};
	self.update = function () {
		if (self.tower.level >= self.tower.maxLevel) {
			if (buttonText.text !== 'Max Level') {
				buttonText.setText('Max Level');
				buttonBackground.tint = 0x888888;
			}
			return;
		}
		// Exponential upgrade cost: base cost * (2 ^ (level-1)), scaled by tower base cost
		var baseUpgradeCost = getTowerCost(self.tower.id);
		var currentUpgradeCost;
		if (self.tower.level >= self.tower.maxLevel) {
			currentUpgradeCost = 0;
		} else if (self.tower.level === self.tower.maxLevel - 1) {
			currentUpgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1) * 3.5 / 2);
		} else {
			currentUpgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1));
		}
		var canAfford = gold >= currentUpgradeCost;
		buttonBackground.tint = canAfford ? 0x00AA00 : 0x888888;
		var newText = 'Upgrade: ' + currentUpgradeCost + ' gold';
		if (buttonText.text !== newText) {
			buttonText.setText(newText);
		}
	};
	return self;
});
var WaveIndicator = Container.expand(function () {
	var self = Container.call(this);
	self.gameStarted = false;
	self.waveMarkers = [];
	self.waveTypes = [];
	self.enemyCounts = [];
	self.indicatorWidth = 0;
	self.lastBossType = null; // Track the last boss type to avoid repeating
	var blockWidth = 400;
	var totalBlocksWidth = blockWidth * totalWaves;
	var startMarker = new Container();
	var startBlock = startMarker.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	startBlock.width = blockWidth - 10;
	startBlock.height = 70 * 2;
	startBlock.tint = 0xffad0e;
	// Add shadow for start text
	var startTextShadow = new Text2("Start Battle", {
		size: 50,
		fill: 0x000000,
		weight: 800
	});
	startTextShadow.anchor.set(0.5, 0.5);
	startTextShadow.x = 4;
	startTextShadow.y = 4;
	startMarker.addChild(startTextShadow);
	var startText = new Text2("Start Battle", {
		size: 50,
		fill: 0xFFFFFF,
		weight: 800
	});
	startText.anchor.set(0.5, 0.5);
	startMarker.addChild(startText);
	startMarker.x = -self.indicatorWidth;
	self.addChild(startMarker);
	self.waveMarkers.push(startMarker);
	startMarker.down = function () {
		if (!self.gameStarted) {
			self.gameStarted = true;
			currentWave = 0;
			waveTimer = nextWaveTime;
			startBlock.tint = 0xffad0e;
			startText.setText("Started!");
			startTextShadow.setText("Started!");
			// Make sure shadow position remains correct after text change
			startTextShadow.x = 4;
			startTextShadow.y = 4;
			var notification = game.addChild(new Notification("Game started! Wave 1 incoming!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 150;
		}
	};
	for (var i = 0; i < totalWaves; i++) {
		var marker = new Container();
		var block = marker.attachAsset('notification', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		block.width = blockWidth - 10;
		block.height = 70 * 2;
		// --- Begin new unified wave logic ---
		var waveType = "normal";
		var enemyType = "normal";
		var enemyCount = 10;
		var isBossWave = i + 1 === totalWaves;
		// Ensure all types appear in early waves
		if (i === 0) {
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		} else if (i === 1) {
			block.tint = 0x2F4F2F;
			waveType = "Immune";
			enemyType = "immune";
			enemyCount = 2;
		} else if (i === 2) {
			block.tint = 0x006400;
			waveType = "Flying";
			enemyType = "flying";
			enemyCount = 3;
		} else if (i === 3) {
			block.tint = 0x3B5323;
			waveType = "Tank";
			enemyType = "tank";
			enemyCount = 1;
		} else if (i === 4) {
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		} else if (i === 8) {
			// Wave 9 - Immune
			block.tint = 0x4A6B4A;
			waveType = "Immune";
			enemyType = "immune";
			enemyCount = 2;
		} else if (i === 9) {
			// Wave 10 - Flying
			block.tint = 0x006B40;
			waveType = "Flying";
			enemyType = "flying";
			enemyCount = 3;
		} else if (i === 10) {
			// Wave 11 - Tank (changed from immune)
			block.tint = 0x556B22;
			waveType = "Tank";
			enemyType = "tank";
			enemyCount = 1;
		} else if (isBossWave) {
			// Boss waves: cycle through all boss types, last boss is always flying
			var bossTypes = ['fast', 'immune', 'flying'];
			var bossTypeIndex = Math.floor((i + 1) / 10) - 1;
			if (i === totalWaves - 1) {
				// Last boss is always flying
				enemyType = 'flying';
				waveType = "Boss Flying";
				block.tint = 0x006B22;
			} else {
				enemyType = bossTypes[bossTypeIndex % bossTypes.length];
				switch (enemyType) {
					case 'fast':
						block.tint = 0x228B22;
						waveType = "Boss Fast";
						break;
					case 'immune':
						block.tint = 0x4A6B4A;
						waveType = "Boss Immune";
						break;
					case 'flying':
						block.tint = 0x006B40;
						waveType = "Boss Flying";
						break;
				}
			}
			enemyCount = 1;
			// Make the wave indicator for boss waves stand out
			// Set boss wave color to black
			block.tint = 0x000000;
		} else if ((i + 1) % 5 === 0) {
			// Every 5th non-boss wave is fast
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		} else if ((i + 1) % 4 === 0) {
			// Every 4th non-boss wave is tank
			block.tint = 0x4B6000;
			waveType = "Tank";
			enemyType = "tank";
			enemyCount = 1;
		} else if ((i + 1) % 7 === 0) {
			// Every 7th non-boss wave is flying
			block.tint = 0x006B56;
			waveType = "Flying";
			enemyType = "flying";
			enemyCount = 3;
		} else if ((i + 1) % 3 === 0) {
			// Every 3rd non-boss wave is fast
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		} else {
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		}
		// --- End new unified wave logic ---
		// Mark boss waves with a special visual indicator
		if (isBossWave) {
			// Change the wave type text to indicate boss
			waveType = "BOSS";
		}
		// Store the wave type and enemy count
		self.waveTypes[i] = enemyType;
		self.enemyCounts[i] = enemyCount;
		// Add shadow for wave type - 30% smaller than before
		var waveTypeShadow = new Text2(waveType, {
			size: 56,
			fill: 0x000000,
			weight: 800
		});
		waveTypeShadow.anchor.set(0.5, 0.5);
		waveTypeShadow.x = 4;
		waveTypeShadow.y = 4;
		marker.addChild(waveTypeShadow);
		// Add wave type text - 30% smaller than before
		var waveTypeText = new Text2(waveType, {
			size: 56,
			fill: 0xFFFFFF,
			weight: 800
		});
		waveTypeText.anchor.set(0.5, 0.5);
		waveTypeText.y = 0;
		marker.addChild(waveTypeText);
		// Add shadow for wave number - 20% larger than before
		var waveNumShadow = new Text2((i + 1).toString(), {
			size: 48,
			fill: 0x000000,
			weight: 800
		});
		waveNumShadow.anchor.set(1.0, 1.0);
		waveNumShadow.x = blockWidth / 2 - 16 + 5;
		waveNumShadow.y = block.height / 2 - 12 + 5;
		marker.addChild(waveNumShadow);
		// Main wave number text - 20% larger than before
		var waveNum = new Text2((i + 1).toString(), {
			size: 48,
			fill: 0xFFFFFF,
			weight: 800
		});
		waveNum.anchor.set(1.0, 1.0);
		waveNum.x = blockWidth / 2 - 16;
		waveNum.y = block.height / 2 - 12;
		marker.addChild(waveNum);
		marker.x = -self.indicatorWidth + (i + 1) * blockWidth;
		self.addChild(marker);
		self.waveMarkers.push(marker);
	}
	// Get wave type for a specific wave number
	self.getWaveType = function (waveNumber) {
		if (waveNumber < 1 || waveNumber > totalWaves) {
			return "fast";
		}
		// If this is a boss wave (waveNumber % 10 === 0), and the type is the same as lastBossType
		// then we should return a different boss type
		var waveType = self.waveTypes[waveNumber - 1];
		return waveType;
	};
	// Get enemy count for a specific wave number
	self.getEnemyCount = function (waveNumber) {
		if (waveNumber < 1 || waveNumber > totalWaves) {
			return 10;
		}
		return self.enemyCounts[waveNumber - 1];
	};
	// Get display name for a wave type
	self.getWaveTypeName = function (waveNumber) {
		var type = self.getWaveType(waveNumber);
		var typeName = type.charAt(0).toUpperCase() + type.slice(1);
		// Add boss prefix for boss waves (final wave)
		if (waveNumber === totalWaves) {
			typeName = "BOSS";
		}
		return typeName;
	};
	self.positionIndicator = new Container();
	var indicator = self.positionIndicator.attachAsset('towerLevelIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	indicator.width = blockWidth - 10;
	indicator.height = 16;
	indicator.tint = 0xffad0e;
	indicator.y = -65;
	var indicator2 = self.positionIndicator.attachAsset('towerLevelIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	indicator2.width = blockWidth - 10;
	indicator2.height = 16;
	indicator2.tint = 0xffad0e;
	indicator2.y = 65;
	var leftWall = self.positionIndicator.attachAsset('towerLevelIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	leftWall.width = 16;
	leftWall.height = 146;
	leftWall.tint = 0xffad0e;
	leftWall.x = -(blockWidth - 16) / 2;
	var rightWall = self.positionIndicator.attachAsset('towerLevelIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	rightWall.width = 16;
	rightWall.height = 146;
	rightWall.tint = 0xffad0e;
	rightWall.x = (blockWidth - 16) / 2;
	self.addChild(self.positionIndicator);
	self.update = function () {
		var progress = waveTimer / nextWaveTime;
		var moveAmount = (progress + currentWave) * blockWidth;
		for (var i = 0; i < self.waveMarkers.length; i++) {
			var marker = self.waveMarkers[i];
			marker.x = -moveAmount + i * blockWidth;
		}
		self.positionIndicator.x = 0;
		for (var i = 0; i < totalWaves + 1; i++) {
			var marker = self.waveMarkers[i];
			if (i === 0) {
				continue;
			}
			var block = marker.children[0];
			if (i - 1 < currentWave) {
				block.alpha = .5;
			}
		}
		self.handleWaveProgression = function () {
			if (!self.gameStarted) {
				return;
			}
			if (currentWave < totalWaves) {
				waveTimer++;
				if (waveTimer >= nextWaveTime) {
					waveTimer = 0;
					currentWave++;
					waveInProgress = true;
					waveSpawned = false;
					if (currentWave != 1) {
						var waveType = self.getWaveTypeName(currentWave);
						var enemyCount = self.getEnemyCount(currentWave);
						var notification = game.addChild(new Notification("Wave " + currentWave + " (" + waveType + " - " + enemyCount + " enemies) incoming!"));
						notification.x = 2048 / 2;
						notification.y = grid.height - 150;
					}
				}
			}
		};
		self.handleWaveProgression();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0xD2B48C
});
/**** 
* Game Code
****/ 
var gameState = 'menu'; // 'menu', 'playing'
var isHidingUpgradeMenu = false;
// Global flag for alternating fly direction
var lastDirectionWasRight = false;
function spawnFly() {
	lastDirectionWasRight = !lastDirectionWasRight;
	// You would set fly.vx and fly.vy here based on your fly object
	// fly.vx = (lastDirectionWasRight ? 1 : -1) * horizontalSpeed;
	// fly.vy = downSpeed;
	// For this tower defense game, we can apply this pattern to flying enemies
	// by modifying their target lanes based on direction
	console.log("Fly spawning with direction:", lastDirectionWasRight ? "right" : "left");
}
// Mobile detection and sniper tower blocking
(function blockSniperTowers() {
	// Safe mobile detection without navigator.userAgent
	var isMobile = false;
	try {
		if (typeof window !== 'undefined' && window.navigator && window.navigator.userAgent) {
			isMobile = /Mobi|Android/i.test(window.navigator.userAgent);
		} else {
			// Fallback: assume mobile if screen dimensions suggest mobile device
			isMobile = typeof window !== 'undefined' && window.innerWidth && window.innerWidth < 1024;
		}
	} catch (e) {
		// If all else fails, default to false (desktop)
		isMobile = false;
	}
	if (!isMobile) return; // Only activate on mobile
	// Override tower creation to block sniper towers
	var originalTowerConstructor = Tower;
	Tower = Container.expand(function (id) {
		// Block sniper tower creation on mobile
		if (id === 'sniper') {
			console.warn("[BLOCKED] Sniper tower creation prevented on mobile.");
			// Return a basic trap tower instead
			return originalTowerConstructor.call(this, 'trap');
		}
		// Use original constructor for other tower types
		return originalTowerConstructor.call(this, id);
	});
	// Override getTowerCost to return 0 for sniper on mobile (making it unavailable)
	var originalGetTowerCost = getTowerCost;
	getTowerCost = function getTowerCost(towerType) {
		if (towerType === 'sniper') {
			return 999999; // Make sniper prohibitively expensive on mobile
		}
		return originalGetTowerCost(towerType);
	};
	console.log("[INFO] Sniper tower blocking activated for mobile device.");
})();
function hideUpgradeMenu(menu) {
	if (isHidingUpgradeMenu) {
		return;
	}
	isHidingUpgradeMenu = true;
	tween(menu, {
		y: 2732 + 225
	}, {
		duration: 150,
		easing: tween.easeIn,
		onFinish: function onFinish() {
			menu.destroy();
			isHidingUpgradeMenu = false;
		}
	});
}
var CELL_SIZE = 76;
var pathId = 1;
var maxScore = 0;
var enemies = [];
var towers = [];
// Ensure no pre-placed towers exist - clear any that might have been created
function clearPrePlacedTowers() {
	// This function is now only used for initial game setup cleanup
	// It should not aggressively remove player-placed towers during gameplay
	// Only clear references, don't destroy actual towers during gameplay
	selectedTower = null;
	// Only clear grid cell references if grid exists and game is not in playing state
	if (grid && grid.cells && gameState !== 'playing') {
		for (var i = 0; i < grid.cells.length; i++) {
			for (var j = 0; j < grid.cells[i].length; j++) {
				var cell = grid.cells[i][j];
				if (cell && cell.towersInRange) {
					cell.towersInRange.length = 0;
				}
			}
		}
	}
}
// Call this function to ensure clean slate - but only after towerLayer is created
// clearPrePlacedTowers(); // Moved this call to after towerLayer creation
var bullets = [];
var defenses = [];
var selectedTower = null;
var gold = 100;
var lives = 100;
var score = 0;
var currentWave = 0;
var selectedDifficulty = null;
var totalWaves = 12;
var waveTimer = 0;
var waveInProgress = false;
var waveSpawned = false;
var nextWaveTime = 600; // Reduced from 1500 to 600 frames (10 seconds instead of 25)
var sourceTower = null;
var enemiesToSpawn = 10; // Default number of enemies per wave
var goldText = new Text2('Gold: ' + gold, {
	size: 60,
	fill: 0xFFD700,
	weight: 800
});
goldText.anchor.set(0.5, 0.5);
var livesText = new Text2('Lives: ' + lives, {
	size: 60,
	fill: 0x00FF00,
	weight: 800
});
livesText.anchor.set(0.5, 0.5);
var scoreText = new Text2('Score: ' + score, {
	size: 60,
	fill: 0xFF0000,
	weight: 800
});
scoreText.anchor.set(0.5, 0.5);
var topMargin = 50;
var centerX = 2048 / 2;
var spacing = 400;
// Create UI container for game elements
var gameUIContainer = new Container();
gameUIContainer.addChild(goldText);
gameUIContainer.addChild(livesText);
gameUIContainer.addChild(scoreText);
livesText.x = 0;
livesText.y = topMargin;
goldText.x = -spacing;
goldText.y = topMargin;
scoreText.x = spacing;
scoreText.y = topMargin;
// Initially hide game UI
gameUIContainer.visible = false;
LK.gui.top.addChild(gameUIContainer);
var lastGold = -1;
var lastLives = -1;
var lastScore = -1;
function updateUI() {
	if (gold !== lastGold) {
		goldText.setText('Gold: ' + gold);
		lastGold = gold;
	}
	if (lives !== lastLives) {
		livesText.setText('Lives: ' + lives);
		lastLives = lives;
	}
	if (score !== lastScore) {
		scoreText.setText('Score: ' + score);
		lastScore = score;
	}
}
function setGold(value) {
	gold = value;
	updateUI();
}
var debugLayer = new Container();
var towerLayer = new Container();
// Initialize empty towers array
towers = [];
// Clear any pre-placed towers that might have been loaded with the map
clearPrePlacedTowers();
// Fast enemy can shoot - already implemented
// This functionality is already working in the Enemy class update method
// Fast enemies have shooting range, damage, cooldown, and create red bullets targeting towers
var enemyLayerBottom = new Container(); // For normal enemies
var enemyLayerMiddle = new Container(); // For shadows
var enemyLayerTop = new Container(); // For flying enemies
var enemyLayer = new Container(); // Main container to hold all enemy layers
// Add layers in correct order (bottom first, then middle for shadows, then top)
enemyLayer.addChild(enemyLayerBottom);
enemyLayer.addChild(enemyLayerMiddle);
enemyLayer.addChild(enemyLayerTop);
var grid = new Grid(24, 29 + 6);
grid.x = 150;
grid.y = 200 - CELL_SIZE * 4;
grid.pathFind();
grid.renderDebug();
debugLayer.addChild(grid);
// Create menu container
var menuContainer = new Container();
game.addChild(menuContainer);
// Create game container for all game elements
var gameContainer = new Container();
gameContainer.addChild(debugLayer);
gameContainer.addChild(towerLayer);
gameContainer.addChild(enemyLayer);
game.addChild(gameContainer);
// Initially hide game elements
gameContainer.visible = false;
var offset = 0;
var towerPreview = new TowerPreview();
game.addChild(towerPreview);
towerPreview.visible = false;
var isDragging = false;
function wouldBlockPath(gridX, gridY) {
	var cells = [];
	for (var i = 0; i < 2; i++) {
		for (var j = 0; j < 2; j++) {
			var cell = grid.getCell(gridX + i, gridY + j);
			if (cell) {
				cells.push({
					cell: cell,
					originalType: cell.type
				});
				// Only set to blocking type if it's currently a path (type 0)
				// Ground cells (type 1) can be built on without blocking paths
				if (cell.type === 0) {
					cell.type = 1;
				}
			}
		}
	}
	var blocked = grid.pathFind();
	for (var i = 0; i < cells.length; i++) {
		cells[i].cell.type = cells[i].originalType;
	}
	grid.pathFind();
	grid.renderDebug();
	return blocked;
}
function getTowerCost(towerType) {
	var cost = 30;
	switch (towerType) {
		case 'landmine':
			cost = 10;
			break;
		case 'sniper':
			cost = 40;
			break;
		case 'flamethrower':
			cost = 20;
			break;
		case 'slow':
			cost = 50;
			break;
		case 'poison':
			cost = 55;
			break;
		case 'tank':
			cost = 60;
			break;
	}
	return cost;
}
function getTowerSellValue(totalValue) {
	return waveIndicator && waveIndicator.gameStarted ? Math.floor(totalValue * 0.6) : totalValue;
}
function placeTower(gridX, gridY, towerType) {
	var towerCost = getTowerCost(towerType);
	if (gold >= towerCost) {
		var tower = new Tower(towerType || 'trap');
		tower.placeOnGrid(gridX, gridY);
		towerLayer.addChild(tower);
		towers.push(tower);
		setGold(gold - towerCost);
		// Only recalculate pathfinding if needed
		if (!grid.pathFind()) {
			grid.renderDebug();
		}
		return true;
	} else {
		var notification = game.addChild(new Notification("Not enough gold!"));
		notification.x = 2048 / 2;
		notification.y = grid.height - 50;
		return false;
	}
}
game.down = function (x, y, obj) {
	// Prevent any clicks on game elements when in menu state
	if (gameState !== 'playing') {
		return;
	}
	var upgradeMenuVisible = game.children.some(function (child) {
		return child instanceof UpgradeMenu;
	});
	if (upgradeMenuVisible) {
		return;
	}
	for (var i = 0; i < sourceTowers.length; i++) {
		var tower = sourceTowers[i];
		if (x >= tower.x - tower.width / 2 && x <= tower.x + tower.width / 2 && y >= tower.y - tower.height / 2 && y <= tower.y + tower.height / 2) {
			towerPreview.visible = true;
			isDragging = true;
			towerPreview.towerType = tower.towerType;
			towerPreview.updateAppearance();
			// Apply the same offset as in move handler to ensure consistency when starting drag
			towerPreview.snapToGrid(x, y - CELL_SIZE * 1.5);
			break;
		}
	}
};
game.move = function (x, y, obj) {
	if (isDragging) {
		// Shift the y position upward by 1.5 tiles to show preview above finger
		towerPreview.snapToGrid(x, y - CELL_SIZE * 1.5);
	}
};
game.up = function (x, y, obj) {
	var clickedOnTower = false;
	for (var i = 0; i < towers.length; i++) {
		var tower = towers[i];
		var towerLeft = tower.x - tower.width / 2;
		var towerRight = tower.x + tower.width / 2;
		var towerTop = tower.y - tower.height / 2;
		var towerBottom = tower.y + tower.height / 2;
		if (x >= towerLeft && x <= towerRight && y >= towerTop && y <= towerBottom) {
			clickedOnTower = true;
			break;
		}
	}
	var upgradeMenus = game.children.filter(function (child) {
		return child instanceof UpgradeMenu;
	});
	if (upgradeMenus.length > 0 && !isDragging && !clickedOnTower) {
		var clickedOnMenu = false;
		for (var i = 0; i < upgradeMenus.length; i++) {
			var menu = upgradeMenus[i];
			var menuWidth = 2048;
			var menuHeight = 450;
			var menuLeft = menu.x - menuWidth / 2;
			var menuRight = menu.x + menuWidth / 2;
			var menuTop = menu.y - menuHeight / 2;
			var menuBottom = menu.y + menuHeight / 2;
			if (x >= menuLeft && x <= menuRight && y >= menuTop && y <= menuBottom) {
				clickedOnMenu = true;
				break;
			}
		}
		if (!clickedOnMenu) {
			for (var i = 0; i < upgradeMenus.length; i++) {
				var menu = upgradeMenus[i];
				hideUpgradeMenu(menu);
			}
			for (var i = game.children.length - 1; i >= 0; i--) {
				if (game.children[i].isTowerRange) {
					game.removeChild(game.children[i]);
				}
			}
			selectedTower = null;
			grid.renderDebug();
		}
	}
	if (isDragging) {
		isDragging = false;
		if (towerPreview.canPlace) {
			placeTower(towerPreview.gridX, towerPreview.gridY, towerPreview.towerType);
		} else if (towerPreview.blockedByEnemy) {
			var notification = game.addChild(new Notification("Cannot build: Enemy in the way!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 50;
		} else if (towerPreview.visible) {
			var notification = game.addChild(new Notification("Cannot build here!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 50;
		}
		towerPreview.visible = false;
		if (isDragging) {
			var upgradeMenus = game.children.filter(function (child) {
				return child instanceof UpgradeMenu;
			});
			for (var i = 0; i < upgradeMenus.length; i++) {
				upgradeMenus[i].destroy();
			}
		}
	}
};
var waveIndicator = null; // Initialize as null, will be created when game starts
// Function to create wave indicator with current totalWaves
function createWaveIndicator() {
	if (waveIndicator) {
		gameContainer.removeChild(waveIndicator);
	}
	waveIndicator = new WaveIndicator();
	waveIndicator.x = 2048 / 2;
	waveIndicator.y = 2732 - 80;
	gameContainer.addChild(waveIndicator);
}
var nextWaveButtonContainer = new Container();
var nextWaveButton = new NextWaveButton();
nextWaveButton.x = 2048 - 200;
nextWaveButton.y = 2732 - 100 + 20;
nextWaveButtonContainer.addChild(nextWaveButton);
// Add to game instead of gameContainer to ensure it appears on top of all map elements
game.addChild(nextWaveButtonContainer);
var towerTypes = ['landmine', 'flamethrower', 'trap', 'sniper', 'slow', 'tank'];
// Filter out sniper tower on mobile devices
var isMobile = false;
try {
	if (typeof window !== 'undefined' && window.navigator && window.navigator.userAgent) {
		isMobile = /Mobi|Android/i.test(window.navigator.userAgent);
	} else {
		// Fallback: assume mobile if screen dimensions suggest mobile device
		isMobile = typeof window !== 'undefined' && window.innerWidth && window.innerWidth < 1024;
	}
} catch (e) {
	// If all else fails, default to false (desktop)
	isMobile = false;
}
if (isMobile) {
	towerTypes = towerTypes.filter(function (type) {
		return type !== 'sniper';
	});
	console.log("[INFO] Sniper tower removed from available towers on mobile.");
}
var sourceTowers = [];
var towerSpacing = 350; // Increase spacing for larger towers
var startX = 2048 / 2 - towerTypes.length * towerSpacing / 2 + towerSpacing / 2;
var towerY = 2732 - CELL_SIZE * 3 - 90;
for (var i = 0; i < towerTypes.length; i++) {
	var tower = new SourceTower(towerTypes[i]);
	tower.x = startX + i * towerSpacing;
	tower.y = towerY;
	game.addChild(tower); // Add to game instead of towerLayer to prevent it from being a placeable tower
	sourceTowers.push(tower);
}
sourceTower = null;
enemiesToSpawn = 10;
// Hide weapon boxes initially
for (var i = 0; i < sourceTowers.length; i++) {
	sourceTowers[i].visible = false;
}
// Create new difficulty selection menu
// Menu background panel
var menuBg = new Container();
var menuBgGraphics = menuBg.attachAsset('MW', {
	anchorX: 0.5,
	anchorY: 0.5
});
menuBgGraphics.width = 2050;
menuBgGraphics.height = 2732;
menuBg.x = 2048 / 2 + 1;
menuBg.y = 2732 / 2;
menuContainer.addChild(menuBg);
// Play menu music automatically when menu is loaded
LK.playMusic('Menu1');
// Title - using TDT asset
var title = new Container();
var titleGraphics = title.attachAsset('TDT', {
	anchorX: 0.5,
	anchorY: 0.5
});
title.x = 2048 / 2;
title.y = 2732 * 0.1 + 333;
menuContainer.addChild(title);
// Difficulty buttons data
var difficulties = [{
	label: 'HARD β 48 WAVES',
	level: 'HARD',
	waves: 48
}, {
	label: 'MEDIUM β 24 WAVES',
	level: 'MEDIUM',
	waves: 24
}, {
	label: 'EASY β 12 WAVES',
	level: 'EASY',
	waves: 12
}];
var difficultyButtons = [];
var playButton = null;
// Create difficulty buttons
for (var i = 0; i < difficulties.length; i++) {
	var diff = difficulties[i];
	var btn = new Container();
	var btnBg = btn.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	btnBg.width = 1600;
	btnBg.height = 240;
	btnBg.tint = 0x004B00; // Darker green
	btnBg.alpha = 0.8;
	var btnText = new Text2(diff.label, {
		size: 120,
		fill: 0x00FF00,
		weight: 800
	});
	btnText.anchor.set(0.5, 0.5);
	btn.addChild(btnText);
	btn.x = 2048 / 2;
	btn.y = 2732 * (0.25 + i * 0.1) + 333 + 333;
	btn.difficulty = diff;
	menuContainer.addChild(btn);
	difficultyButtons.push(btn);
	// Add click handler to difficulty button
	btn.down = function () {
		selectedDifficulty = this.difficulty.level;
		totalWaves = this.difficulty.waves;
		// Hide instruction text once a difficulty is selected
		if (difficultyInstructionText && difficultyInstructionText.visible) {
			difficultyInstructionText.visible = false;
		}
		// Update all button appearances
		for (var j = 0; j < difficultyButtons.length; j++) {
			var button = difficultyButtons[j];
			var bg = button.children[0];
			if (button.difficulty.level === selectedDifficulty) {
				bg.tint = 0x006600; // Darker green for selected
				bg.alpha = 1.0;
			} else {
				bg.tint = 0x004B00; // Darker green for unselected
				bg.alpha = 0.8;
			}
		}
		// Show play button
		if (playButton) {
			playButton.visible = true;
		}
	};
}
// Difficulty instruction text
var difficultyInstructionText = new Text2('Please choose a difficulty level!', {
	size: 80,
	fill: 0xFFFFFF,
	weight: 800
});
difficultyInstructionText.anchor.set(0.5, 1.0);
difficultyInstructionText.x = 2048 / 2;
difficultyInstructionText.y = 2732 - 50;
menuContainer.addChild(difficultyInstructionText);
// PLAY button - initially hidden
playButton = new Container();
var playButtonBg = playButton.attachAsset('notification', {
	anchorX: 0.5,
	anchorY: 0.5
});
playButtonBg.width = 800;
playButtonBg.height = 240;
playButtonBg.tint = 0x00AA00;
var playButtonText = new Text2('PLAY', {
	size: 160,
	fill: 0x00FF00,
	weight: 800
});
playButtonText.anchor.set(0.5, 0.5);
playButton.addChild(playButtonText);
playButton.x = 2048 / 2;
playButton.y = (2732 * 0.45 + 666 + 2732) / 2 + 69;
playButton.visible = false;
menuContainer.addChild(playButton);
playButton.down = function () {
	if (selectedDifficulty) {
		// Stop menu music when starting game
		LK.stopMusic();
		// Generate waves based on selected difficulty
		generateWaves(totalWaves);
		// Create wave indicator with selected difficulty
		createWaveIndicator();
		// Transition from menu to game
		gameState = 'playing';
		menuContainer.visible = false;
		gameContainer.visible = true;
		gameUIContainer.visible = true;
		// Show weapon boxes when game starts
		for (var i = 0; i < sourceTowers.length; i++) {
			sourceTowers[i].visible = true;
		}
	}
};
// Wave generation function
function generateWaves(count) {
	// The existing wave system will handle wave generation
	// We just need to set totalWaves which is already done above
	// The WaveIndicator class will use the totalWaves value
	console.log('Generated', count, 'waves for difficulty:', selectedDifficulty);
}
// Function to show menu
function showMenu() {
	gameState = 'menu';
	menuContainer.visible = true;
	gameContainer.visible = false;
	gameUIContainer.visible = false;
}
// Function to show game
function showGame() {
	gameState = 'playing';
	menuContainer.visible = false;
	gameContainer.visible = true;
	gameUIContainer.visible = true;
}
function onGameStart(callback) {
	// Store the callback to be executed when game starts
	if (waveIndicator && waveIndicator.gameStarted) {
		callback();
	} else {
		// Wait for game to start, then execute callback
		var checkGameStart = LK.setInterval(function () {
			if (waveIndicator && waveIndicator.gameStarted) {
				LK.clearInterval(checkGameStart);
				callback();
			}
		}, 100);
	}
}
// Tank spawning is now handled by the main wave system in game.update
// No manual spawning needed here
game.update = function () {
	// Only run game logic when in playing state
	if (gameState !== 'playing') {
		return;
	}
	if (waveInProgress && waveIndicator) {
		if (!waveSpawned) {
			waveSpawned = true;
			// Get wave type and enemy count from the wave indicator
			var waveType = waveIndicator.getWaveType(currentWave);
			var enemyCount = waveIndicator.getEnemyCount(currentWave);
			// Check if this is a boss wave
			var isBossWave = currentWave === totalWaves;
			if (isBossWave) {
				// Boss waves have just 1 enemy regardless of what the wave indicator says
				enemyCount = 1;
				// Show boss announcement
				var notification = game.addChild(new Notification("β οΈ BOSS WAVE! β οΈ"));
				notification.x = 2048 / 2;
				notification.y = grid.height - 200;
			}
			// Spawn the appropriate number of enemies
			for (var i = 0; i < enemyCount; i++) {
				var enemy = new Enemy(waveType);
				// Initialize flying enemy direction using global alternating flag
				if (enemy.isFlying) {
					// Call the spawnFly function to update the global direction flag
					spawnFly();
					// Set the flying enemy's initial direction based on the global flag
					enemy.flyingDirection = lastDirectionWasRight ? 1 : -1; // 1 for right, -1 for left
				}
				// Add enemy to the appropriate layer based on type for proper display order
				if (enemy.isFlying) {
					// Add flying enemy to the top layer to ensure they appear above all other enemies
					enemyLayerTop.addChild(enemy);
					// If it's a flying enemy, add its shadow to the middle layer
					if (enemy.shadow) {
						enemyLayerMiddle.addChild(enemy.shadow);
					}
				} else if (enemy.type === 'fast') {
					// Add fast enemies to the bottom layer to ensure flying enemies appear above them
					enemyLayerBottom.addChild(enemy);
				} else {
					// Add other ground enemies (immune, tank, etc.) to the middle layer
					enemyLayerMiddle.addChild(enemy);
				}
				// Scale difficulty with wave number but don't apply to boss
				// as bosses already have their health multiplier
				// Use exponential scaling for health
				var healthMultiplier = Math.pow(1.12, currentWave); // ~20% increase per wave
				enemy.maxHealth = Math.round(enemy.maxHealth * healthMultiplier);
				enemy.health = enemy.maxHealth;
				// Increment speed slightly with wave number
				//enemy.speed = enemy.speed + currentWave * 0.002;
				// Assign specific lanes for different enemy types to prevent overlapping
				var gridWidth = 24;
				var midPoint = Math.floor(gridWidth / 2); // 12
				var spawnX;
				// Define strict non-overlapping lanes with buffer zones for different enemy types
				if (waveType === 'fast') {
					// Fast enemies spawn in horizontal lines
					var enemiesPerLine = 5; // Number of enemies per horizontal line
					var lineNumber = Math.floor(i / enemiesPerLine); // Which horizontal line this enemy belongs to
					var positionInLine = i % enemiesPerLine; // Position within the line (0-4)
					var lineColumns = [6, 9, 12, 15, 18]; // Available columns for horizontal lines - moved left
					spawnX = lineColumns[positionInLine]; // Position enemy in the line
				} else if (waveType === 'immune') {
					// Immune enemies use center-left lanes (columns 11-12) with buffer from fast and tank
					var immuneColumns = [11, 12];
					var availableImmuneColumns = [];
					for (var col = 0; col < immuneColumns.length; col++) {
						var columnOccupied = false;
						for (var e = 0; e < enemies.length; e++) {
							if (enemies[e].cellX === immuneColumns[col] && enemies[e].currentCellY < 8) {
								columnOccupied = true;
								break;
							}
						}
						if (!columnOccupied) {
							availableImmuneColumns.push(immuneColumns[col]);
						}
					}
					// If no columns available, queue the enemy by using the first column
					spawnX = availableImmuneColumns.length > 0 ? availableImmuneColumns[Math.floor(Math.random() * availableImmuneColumns.length)] : immuneColumns[0];
				} else if (waveType === 'tank') {
					// Tank enemies spawn positioning based on wave
					if (currentWave === 4) {
						// Wave 4: Left side
						var tankColumns = [3]; // Left side lane for wave 4 tank enemies
					} else if (currentWave === 8) {
						// Wave 8: Right side
						var tankColumns = [21]; // Right side lane for wave 8 tank enemies
					} else if (currentWave === 11) {
						// Wave 11: Center
						var tankColumns = [12]; // Center lane for wave 11 tank enemies
					} else {
						// Default for other waves: right side of road
						var tankColumns = [21, 22]; // Right edge lanes for tank enemies
					}
					spawnX = tankColumns[i % tankColumns.length]; // Cycle through assigned lanes
				} else {
					// Flying and other enemy types use middle lanes (columns 12-14) avoiding other types
					var flyingColumns = [12, 13, 14];
					var availableColumns = [];
					for (var col = 0; col < flyingColumns.length; col++) {
						var columnOccupied = false;
						// Check if any enemy is already in this column but not yet in view
						for (var e = 0; e < enemies.length; e++) {
							if (enemies[e].cellX === flyingColumns[col] && enemies[e].currentCellY < 8) {
								columnOccupied = true;
								break;
							}
						}
						if (!columnOccupied) {
							availableColumns.push(flyingColumns[col]);
						}
					}
					// If no columns available, use the center column
					spawnX = availableColumns.length > 0 ? availableColumns[Math.floor(Math.random() * availableColumns.length)] : flyingColumns[1];
				}
				// Calculate spawn position with much larger spacing to ensure no visual overlap
				// Convert units to cell units (pixels / 76 pixels per cell)
				var enemySpacing;
				if (waveType === 'fast') {
					// Calculate spacing between horizontal lines (not individual enemies)
					var lineSpacing = 300 / CELL_SIZE; // Reduced spacing between horizontal lines (~3.9 cells)
					var lineNumber = Math.floor(i / 5); // Which horizontal line this enemy belongs to
					enemySpacing = lineSpacing;
					// Position fast enemies in their assigned column without horizontal offset
					enemy.cellX = isBossWave ? 12 : spawnX;
					enemy.cellY = 5; // Position after entry
					enemy.currentCellX = isBossWave ? 12 : spawnX;
					enemy.currentCellY = -1 - lineNumber * enemySpacing; // Each line spawns with line spacing, not individual spacing
				} else {
					if (waveType === 'tank') {
						enemySpacing = 800 / CELL_SIZE; // Reduced spacing for tank enemies with better lane distribution (~10.5 cells)
					} else if (waveType === 'immune') {
						enemySpacing = 400 / CELL_SIZE; // Reduced spacing for immune enemies (~5.3 cells)
					} else {
						enemySpacing = 900 / CELL_SIZE; // Large spacing for other enemies (~11.8 cells)
					}
					var spawnY = -1 - i * enemySpacing; // Each enemy spawns based on enemy type spacing
					enemy.cellX = isBossWave ? 12 : spawnX;
					enemy.cellY = 5; // Position after entry
					enemy.currentCellX = isBossWave ? 12 : spawnX;
					enemy.currentCellY = spawnY;
				}
				enemy.waveNumber = currentWave;
				enemies.push(enemy);
			}
		}
		var currentWaveEnemiesRemaining = false;
		for (var i = 0; i < enemies.length; i++) {
			if (enemies[i].waveNumber === currentWave) {
				currentWaveEnemiesRemaining = true;
				break;
			}
		}
		if (waveSpawned && !currentWaveEnemiesRemaining) {
			waveInProgress = false;
			waveSpawned = false;
		}
	}
	for (var a = enemies.length - 1; a >= 0; a--) {
		var enemy = enemies[a];
		if (enemy.health <= 0) {
			for (var i = 0; i < enemy.bulletsTargetingThis.length; i++) {
				var bullet = enemy.bulletsTargetingThis[i];
				bullet.targetEnemy = null;
			}
			// Remove all flame particles and smoke effects from the map when enemy is destroyed
			for (var flameIndex = game.children.length - 1; flameIndex >= 0; flameIndex--) {
				var child = game.children[flameIndex];
				// Remove EffectIndicator flame effects
				if (child instanceof EffectIndicator) {
					var dx = child.x - enemy.x;
					var dy = child.y - enemy.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= CELL_SIZE * 3) {
						child.destroy();
					}
				}
				// Remove flame particles (Container objects with flame graphics)
				else if (child.children && child.children.length > 0 && child.children[0].tint !== undefined) {
					var flameGraphics = child.children[0];
					// Check for flame particles by tint colors and properties
					if ((flameGraphics.tint === 0xFF4500 || flameGraphics.tint === 0xFF6600) && flameGraphics.width && flameGraphics.height) {
						// Stop any ongoing tweens and destroy all flame particles
						tween.stop(child);
						child.destroy();
					}
				}
				// Remove flame particles that have damage property (flamethrower particles)
				else if (child.damage !== undefined && child.sourceTowerLevel !== undefined) {
					// Stop any ongoing tweens and destroy flamethrower particles
					tween.stop(child);
					child.destroy();
				}
			}
			// Clean up continuous smoke effect if it exists
			if (enemy.continuousSmokeEffect && enemy.continuousSmokeEffect.parent) {
				// Stop any ongoing smoke particle tweens
				for (var smokeChildIndex = 0; smokeChildIndex < enemy.continuousSmokeEffect.children.length; smokeChildIndex++) {
					var smokeChild = enemy.continuousSmokeEffect.children[smokeChildIndex];
					tween.stop(smokeChild);
				}
				enemy.continuousSmokeEffect.destroy();
				enemy.continuousSmokeEffect = null;
			}
			// Create MASSIVE spectacular death explosion for all enemies except fast enemies (but always for bosses)
			if (enemy.type !== 'fast' || enemy.isBoss) {
				// Stage 1: Initial massive impact flash
				var deathFlash = new EffectIndicator(enemy.x, enemy.y, 'splash');
				deathFlash.children[0].tint = 0xFFFFFF; // Bright white impact flash
				// Scale flash size based on boss status - use Boss asset size for scaling
				var flashScale = enemy.isBoss ? 4.8 : enemy.type === 'tank' ? 2.4 : 2.0; // Boss uses 4.8x (scaled to boss asset size)
				deathFlash.children[0].width = deathFlash.children[0].height = CELL_SIZE * flashScale;
				deathFlash.alpha = 1;
				deathFlash.scaleX = 0.1;
				deathFlash.scaleY = 0.1;
				game.addChild(deathFlash);
				// Ultra-fast bright flash expansion - scale based on enemy type
				var flashExpansionScale = enemy.isBoss ? 5.76 : enemy.type === 'tank' ? 2.88 : 2.4; // Boss uses 5.76x (scaled to boss asset size)
				tween(deathFlash, {
					scaleX: flashExpansionScale,
					scaleY: flashExpansionScale,
					alpha: 0
				}, {
					duration: 80,
					// Faster than weapon explosions for more impact
					easing: tween.easeOut
				});
				// Stage 2: ENORMOUS main death explosion fireball - bigger than any weapon
				var mainDeathExplosion = new EffectIndicator(enemy.x, enemy.y, 'splash');
				// Color based on enemy type
				if (enemy.isBoss) {
					mainDeathExplosion.children[0].tint = 0xFF0000; // Bright red for boss death
				} else if (enemy.type === 'tank') {
					mainDeathExplosion.children[0].tint = 0x8B4513; // Brown for tank enemies
				} else if (enemy.type === 'immune') {
					mainDeathExplosion.children[0].tint = 0xAA0000; // Dark red for immune enemies
				} else if (enemy.isFlying) {
					mainDeathExplosion.children[0].tint = 0xFFFF00; // Yellow for flying enemies
				} else {
					mainDeathExplosion.children[0].tint = 0xFF4500; // Orange for other enemies
				}
				mainDeathExplosion.children[0].width = mainDeathExplosion.children[0].height = CELL_SIZE * (enemy.isBoss ? 3.75 : enemy.type === 'tank' ? 3.0 : 2.5); // ENORMOUS - bigger than tank weapons
				mainDeathExplosion.alpha = 1;
				mainDeathExplosion.scaleX = 0.2;
				mainDeathExplosion.scaleY = 0.2;
				game.addChild(mainDeathExplosion);
				// Dramatic ENORMOUS fireball expansion with intense bounce effect
				tween(mainDeathExplosion, {
					scaleX: enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 2.52 : 2.1,
					// Much bigger than tank weapon explosions
					scaleY: enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 2.52 : 2.1,
					alpha: 0.95
				}, {
					duration: enemy.isBoss ? 400 : 300,
					// Longer for bosses
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						tween(mainDeathExplosion, {
							scaleX: enemy.isBoss ? 4.5 : enemy.type === 'tank' ? 4.32 : 3.6,
							// ENORMOUS final scale - biggest explosions in game
							scaleY: enemy.isBoss ? 4.5 : enemy.type === 'tank' ? 4.32 : 3.6,
							alpha: 0
						}, {
							duration: enemy.isBoss ? 1000 : 800,
							// Very long for dramatic effect
							easing: tween.easeIn,
							onFinish: function onFinish() {
								mainDeathExplosion.destroy();
							}
						});
					}
				});
				// Stage 3: Create ENORMOUS debris particle field - much more particles than weapons
				var particleCount = enemy.isBoss ? 48 : 32; // More particles than tank weapons
				for (var particleIndex = 0; particleIndex < particleCount; particleIndex++) {
					var deathParticle = new EffectIndicator(enemy.x, enemy.y, 'splash');
					// Varied particle colors based on enemy type
					var particleColors;
					if (enemy.isBoss) {
						particleColors = [0xFF0000, 0xFF3300, 0xFF6600, 0xFF9900, 0xFFCC00, 0xFFFF00, 0xFF0033, 0xFF0066];
					} else if (enemy.type === 'tank') {
						particleColors = [0x8B4513, 0xA0522D, 0xD2691E, 0xFF8C00, 0xCD853F, 0xDEB887, 0x654321, 0x8B7355];
					} else if (enemy.type === 'immune') {
						particleColors = [0xAA0000, 0xBB0000, 0xCC0000, 0xDD0000, 0xEE0000, 0xFF0000, 0x990000, 0x880000];
					} else if (enemy.isFlying) {
						particleColors = [0xFFFF00, 0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFFFFFF, 0xFFCC00, 0xFF9900];
					} else {
						particleColors = [0xFF4500, 0xFF6600, 0xFF8800, 0xFFAA00, 0xFF2200, 0xFFCC00, 0xFF3300, 0xFFDD00];
					}
					deathParticle.children[0].tint = particleColors[particleIndex % particleColors.length];
					deathParticle.children[0].width = deathParticle.children[0].height = CELL_SIZE * (enemy.type === 'tank' ? 0.75 + Math.random() * 0.6 : 0.625 + Math.random() * 0.5); // ENORMOUS particles - bigger than tank weapons
					deathParticle.alpha = 1.0;
					deathParticle.scaleX = 0.8 + Math.random() * 0.6;
					deathParticle.scaleY = 0.8 + Math.random() * 0.6;
					// ULTRA-MASSIVE particle scatter distance - bigger than tank weapons
					var particleAngle = particleIndex / particleCount * Math.PI * 2 + (Math.random() - 0.5) * 1.0;
					var particleDistance = CELL_SIZE * (1.5 + Math.random() * 1.0); // ULTRA-far scatter - bigger than tank weapons
					if (enemy.isBoss) {
						particleDistance *= 1.5; // Even further for bosses
					}
					var targetX = enemy.x + Math.cos(particleAngle) * particleDistance;
					var targetY = enemy.y + Math.sin(particleAngle) * particleDistance;
					game.addChild(deathParticle);
					// Animate particles with ENORMOUS final scale
					tween(deathParticle, {
						x: targetX,
						y: targetY,
						scaleX: enemy.type === 'tank' ? 1.8 + Math.random() * 0.72 : 1.5 + Math.random() * 0.6,
						// ENORMOUS final scale - bigger than tank weapons
						scaleY: enemy.type === 'tank' ? 1.8 + Math.random() * 0.72 : 1.5 + Math.random() * 0.6,
						alpha: 0.8
					}, {
						duration: 500 + Math.random() * 400,
						// Longer duration
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(deathParticle, {
								scaleX: 0.2,
								scaleY: 0.2,
								alpha: 0
							}, {
								duration: 600 + Math.random() * 300,
								// Long fade
								easing: tween.easeIn,
								onFinish: function onFinish() {
									deathParticle.destroy();
								}
							});
						}
					});
				}
				// Stage 4: ENORMOUS multiple shockwaves - bigger than tank weapon shockwaves
				var primaryDeathShockwave = new EffectIndicator(enemy.x, enemy.y, 'splash');
				primaryDeathShockwave.children[0].tint = enemy.isBoss ? 0xFF6666 : 0xFFAAAA; // Light red/pink shockwave
				primaryDeathShockwave.children[0].alpha = 0.8;
				primaryDeathShockwave.children[0].width = primaryDeathShockwave.children[0].height = CELL_SIZE * 2.5;
				primaryDeathShockwave.alpha = 1.0;
				game.addChild(primaryDeathShockwave);
				// ENORMOUS expanding death shockwave - bigger than tank weapons
				tween(primaryDeathShockwave, {
					scaleX: enemy.isBoss ? 6.0 : enemy.type === 'tank' ? 5.76 : 4.8,
					// ENORMOUS scale - bigger than tank weapon shockwaves
					scaleY: enemy.isBoss ? 6.0 : enemy.type === 'tank' ? 5.76 : 4.8,
					alpha: 0
				}, {
					duration: enemy.isBoss ? 1200 : 1000,
					// Very long expansion
					easing: tween.easeOut,
					onFinish: function onFinish() {
						primaryDeathShockwave.destroy();
					}
				});
				// Multiple additional death shockwaves for ULTRA-MASSIVE effect
				var shockwaveCount = enemy.isBoss ? 6 : 4; // More shockwaves for bosses
				for (var shockIndex = 1; shockIndex <= shockwaveCount; shockIndex++) {
					var additionalDeathShockwave = new EffectIndicator(enemy.x, enemy.y, 'splash');
					additionalDeathShockwave.children[0].tint = enemy.isBoss ? 0xFF4444 : 0xFF8888; // Darker red shockwave
					additionalDeathShockwave.children[0].alpha = 0.6 - shockIndex * 0.08;
					additionalDeathShockwave.children[0].width = additionalDeathShockwave.children[0].height = CELL_SIZE * (2.5 - shockIndex * 0.2);
					additionalDeathShockwave.alpha = 0.8 - shockIndex * 0.1;
					game.addChild(additionalDeathShockwave);
					// Delayed ENORMOUS death shockwaves
					tween(additionalDeathShockwave, {
						scaleX: (enemy.isBoss ? 6.6 : enemy.type === 'tank' ? 6.48 : 5.4) + shockIndex * (enemy.type === 'tank' ? 0.54 : 0.45),
						// ENORMOUS expanding scale
						scaleY: (enemy.isBoss ? 6.6 : enemy.type === 'tank' ? 6.48 : 5.4) + shockIndex * (enemy.type === 'tank' ? 0.54 : 0.45),
						alpha: 0
					}, {
						duration: (enemy.isBoss ? 1300 : 1100) + shockIndex * 150,
						delay: shockIndex * (enemy.isBoss ? 300 : 250),
						easing: tween.easeOut,
						onFinish: function onFinish() {
							additionalDeathShockwave.destroy();
						}
					});
				}
				// Stage 5: ENORMOUS lingering death smoke cloud - bigger and longer than tank weapons
				var deathSmokeCloud = new EffectIndicator(enemy.x, enemy.y, 'splash');
				deathSmokeCloud.children[0].tint = 0x444444; // Dark gray death smoke
				deathSmokeCloud.children[0].alpha = 0.8;
				deathSmokeCloud.children[0].width = deathSmokeCloud.children[0].height = CELL_SIZE * (enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 3.0 : 2.5); // ENORMOUS smoke cloud
				deathSmokeCloud.alpha = 0;
				deathSmokeCloud.scaleX = 1.5;
				deathSmokeCloud.scaleY = 1.5;
				game.addChild(deathSmokeCloud);
				// Delayed ENORMOUS death smoke appearance
				tween(deathSmokeCloud, {
					alpha: 1.0,
					scaleX: enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 2.88 : 2.4,
					// Bigger initial expansion than tank weapons
					scaleY: enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 2.88 : 2.4
				}, {
					duration: 600,
					delay: 600,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						// Death smoke slowly dissipates over ULTRA-LONG time
						tween(deathSmokeCloud, {
							alpha: 0,
							scaleX: enemy.isBoss ? 5.4 : enemy.type === 'tank' ? 5.76 : 4.8,
							// ENORMOUS final scale - bigger than tank weapons
							scaleY: enemy.isBoss ? 5.4 : enemy.type === 'tank' ? 5.76 : 4.8
						}, {
							duration: enemy.isBoss ? 3000 : 2500,
							// ULTRA-LONG dissipation - longer than tank weapons
							easing: tween.easeIn,
							onFinish: function onFinish() {
								deathSmokeCloud.destroy();
							}
						});
					}
				});
			}
			// Special boss explosion effect and sound
			if (enemy.isBoss) {
				// Create massive boss explosion effect
				var bossExplosion = new EffectIndicator(enemy.x, enemy.y, 'splash');
				bossExplosion.children[0].tint = 0xFFA500; // Orange explosion color
				bossExplosion.children[0].width = bossExplosion.children[0].height = 150; // Large explosion radius
				bossExplosion.alpha = 1.0;
				bossExplosion.scaleX = 0.5;
				bossExplosion.scaleY = 0.5;
				game.addChild(bossExplosion);
				// Multi-stage boss explosion animation
				tween(bossExplosion, {
					scaleX: 3.0,
					scaleY: 3.0,
					alpha: 0.8
				}, {
					duration: 300,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tween(bossExplosion, {
							scaleX: 5.0,
							scaleY: 5.0,
							alpha: 0
						}, {
							duration: 700,
							easing: tween.easeIn,
							onFinish: function onFinish() {
								bossExplosion.destroy();
							}
						});
					}
				});
				// Play boss explosion sound effect
				try {
					var explosionSound = new Audio();
					explosionSound.src = "https://cdn.pixabay.com/download/audio/2022/03/02/audio_f27e2020ce.mp3?filename=explosion-6075.mp3";
					explosionSound.volume = 1.0;
					explosionSound.play()["catch"](function (error) {
						console.log("Could not play boss explosion sound:", error);
					});
				} catch (error) {
					console.log("Boss explosion sound not available:", error);
				}
			}
			// Boss enemies give more gold and score - significantly increased rewards
			var goldEarned = enemy.isBoss ? Math.floor(200 + (enemy.waveNumber - 1) * 25) : Math.floor(15 + (enemy.waveNumber - 1) * 3);
			var goldIndicator = new GoldIndicator(goldEarned, enemy.x, enemy.y);
			game.addChild(goldIndicator);
			setGold(gold + goldEarned);
			// Give more score for defeating a boss
			var scoreValue = enemy.isBoss ? 100 : 5;
			score += scoreValue;
			// Add a notification for boss defeat
			if (enemy.isBoss) {
				var notification = game.addChild(new Notification("Boss defeated! +" + goldEarned + " gold!"));
				notification.x = 2048 / 2;
				notification.y = grid.height - 150;
			}
			updateUI();
			// Clean up shadow if it's a flying enemy
			if (enemy.isFlying && enemy.shadow) {
				enemyLayerMiddle.removeChild(enemy.shadow);
				enemy.shadow = null;
			}
			// Remove enemy from the appropriate layer
			if (enemy.isFlying) {
				enemyLayerTop.removeChild(enemy);
			} else if (enemy.type === 'fast') {
				enemyLayerBottom.removeChild(enemy);
			} else {
				enemyLayerMiddle.removeChild(enemy);
			}
			enemies.splice(a, 1);
			continue;
		}
		// Only update enemy position every few frames to reduce performance impact
		if (LK.ticks % 2 === 0) {
			if (grid.updateEnemy(enemy)) {
				// Clean up shadow if it's a flying enemy
				if (enemy.isFlying && enemy.shadow) {
					enemyLayerMiddle.removeChild(enemy.shadow);
					enemy.shadow = null;
				}
				// Remove enemy from the appropriate layer
				if (enemy.isFlying) {
					enemyLayerTop.removeChild(enemy);
				} else if (enemy.type === 'fast') {
					enemyLayerBottom.removeChild(enemy);
				} else {
					enemyLayerMiddle.removeChild(enemy);
				}
				enemies.splice(a, 1);
				// BOSS Enemy reached the goal - reduce lives by 100 (100% of 100 total lives)
				if (enemy.isBoss) {
					lives = Math.max(0, lives - 100);
				} else {
					// Each individual enemy reduces lives by 10 (10% of 100 total lives)
					lives = Math.max(0, lives - 10);
				}
				updateUI();
				if (lives <= 0) {
					LK.showGameOver();
				}
			}
		}
	}
	// Only clean bullets every 5 frames to reduce processing
	if (LK.ticks % 5 === 0) {
		for (var i = bullets.length - 1; i >= 0; i--) {
			var bullet = bullets[i];
			if (!bullet.parent) {
				if (bullet.targetEnemy) {
					var targetEnemy = bullet.targetEnemy;
					if (targetEnemy && targetEnemy.bulletsTargetingThis) {
						var bulletIndex = targetEnemy.bulletsTargetingThis.indexOf(bullet);
						if (bulletIndex !== -1) {
							targetEnemy.bulletsTargetingThis.splice(bulletIndex, 1);
						}
					}
				}
				// Clear bullet references
				bullet.targetEnemy = null;
				bullets.splice(i, 1);
			}
		}
	}
	// Check for landmine towers that need to be destroyed after explosion
	for (var i = towers.length - 1; i >= 0; i--) {
		var tower = towers[i];
		if (tower.shouldDestroy) {
			// Remove from grid cells
			var gridX = tower.gridX;
			var gridY = tower.gridY;
			for (var j = 0; j < 2; j++) {
				for (var k = 0; k < 2; k++) {
					var cell = grid.getCell(gridX + j, gridY + k);
					if (cell) {
						// Restore original cell type or default to ground (type 1) if no original type stored
						cell.type = cell.originalType !== undefined ? cell.originalType : 1;
						var towerIndex = cell.towersInRange.indexOf(tower);
						if (towerIndex !== -1) {
							cell.towersInRange.splice(towerIndex, 1);
						}
					}
				}
			}
			// Remove from towers array and tower layer
			towers.splice(i, 1);
			towerLayer.removeChild(tower);
			// Clean up any upgrade menus or range indicators
			if (selectedTower === tower) {
				selectedTower = null;
			}
			// Remove any upgrade menus for this tower
			var upgradeMenus = game.children.filter(function (child) {
				return child instanceof UpgradeMenu && child.tower === tower;
			});
			for (var menuIndex = 0; menuIndex < upgradeMenus.length; menuIndex++) {
				upgradeMenus[menuIndex].destroy();
			}
			// Remove any range indicators for this tower
			for (var rangeIndex = game.children.length - 1; rangeIndex >= 0; rangeIndex--) {
				if (game.children[rangeIndex].isTowerRange && game.children[rangeIndex].tower === tower) {
					game.removeChild(game.children[rangeIndex]);
				}
			}
			// Recalculate pathfinding
			grid.pathFind();
			grid.renderDebug();
		}
	}
	if (towerPreview.visible) {
		towerPreview.checkPlacement();
	}
	if (currentWave >= totalWaves && enemies.length === 0 && !waveInProgress) {
		LK.showYouWin();
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Bullet = Container.expand(function (startX, startY, targetEnemy, damage, speed) {
	var self = Container.call(this);
	self.targetEnemy = targetEnemy;
	self.damage = damage || 10;
	self.speed = speed || 5;
	self.x = startX;
	self.y = startY;
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		// Handle enemy bullets targeting towers
		if (self.isEnemyBullet) {
			if (!self.targetEnemy || !self.targetEnemy.parent) {
				self.destroy();
				return;
			}
			var dx = self.targetEnemy.x - self.x;
			var dy = self.targetEnemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			if (distance < self.speed) {
				// Damage the tower instead of an enemy
				var tower = self.targetEnemy;
				if (tower.takeDamage) {
					tower.takeDamage(self.damage);
				}
				self.destroy();
			} else {
				var angle = Math.atan2(dy, dx);
				self.x += Math.cos(angle) * self.speed;
				self.y += Math.sin(angle) * self.speed;
			}
			return;
		}
		// Original enemy targeting logic
		if (!self.targetEnemy || !self.targetEnemy.parent) {
			self.destroy();
			return;
		}
		var dx = self.targetEnemy.x - self.x;
		var dy = self.targetEnemy.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance < self.speed) {
			// Special handling for missiles hitting immune, flying, or tank enemies - destroy instantly
			if (self.type === 'slow' && (self.targetEnemy.isImmune || self.targetEnemy.isFlying || self.targetEnemy.type === 'tank')) {
				// Instantly destroy immune, flying, or tank enemy regardless of health
				self.targetEnemy.health = 0;
			} else if (self.type === 'tank' && (self.targetEnemy.isImmune || self.targetEnemy.isFlying || self.targetEnemy.type === 'tank' || self.targetEnemy.isBoss)) {
				// Tank weapons instantly destroy immune, flying, tank, and boss enemies
				self.targetEnemy.health = 0;
			} else {
				// Apply damage to target enemy normally
				self.targetEnemy.health -= self.damage;
				if (self.targetEnemy.health <= 0) {
					self.targetEnemy.health = 0;
				} else {
					self.targetEnemy.healthBar.width = self.targetEnemy.health / self.targetEnemy.maxHealth * 70;
				}
			}
			// Create explosion effect for missile hits
			if (self.type === 'slow') {
				// Store explosion position for area damage calculation
				var explosionX = self.targetEnemy.x;
				var explosionY = self.targetEnemy.y;
				// Increased explosion radius to destroy nearby enemies (especially fast enemies)
				var explosionRadius = CELL_SIZE * 2.5; // Increased from smaller radius to 2.5 cells
				// Apply area damage to all enemies within explosion radius
				for (var i = 0; i < enemies.length; i++) {
					var nearbyEnemy = enemies[i];
					if (nearbyEnemy !== self.targetEnemy) {
						var dx = nearbyEnemy.x - explosionX;
						var dy = nearbyEnemy.y - explosionY;
						var distance = Math.sqrt(dx * dx + dy * dy);
						if (distance <= explosionRadius) {
							// Instantly destroy fast enemies within explosion radius
							if (nearbyEnemy.type === 'fast') {
								nearbyEnemy.health = 0;
							} else {
								// Apply significant damage to other enemy types
								nearbyEnemy.health -= self.damage * 1.5; // 1.5x damage for area effect
								if (nearbyEnemy.health <= 0) {
									nearbyEnemy.health = 0;
								} else {
									nearbyEnemy.healthBar.width = nearbyEnemy.health / nearbyEnemy.maxHealth * 70;
								}
							}
							// Create individual explosion effect for each affected enemy
							var nearbyExplosion = new EffectIndicator(nearbyEnemy.x, nearbyEnemy.y, 'splash');
							nearbyExplosion.children[0].tint = 0xFF6600; // Orange-red for area damage
							nearbyExplosion.children[0].width = nearbyExplosion.children[0].height = CELL_SIZE * 1.5;
							nearbyExplosion.alpha = 0.8;
							nearbyExplosion.scaleX = 0.2;
							nearbyExplosion.scaleY = 0.2;
							game.addChild(nearbyExplosion);
							// Animate nearby explosion
							tween(nearbyExplosion, {
								scaleX: 1.2,
								scaleY: 1.2,
								alpha: 0.6
							}, {
								duration: 100,
								easing: tween.easeOut,
								onFinish: function onFinish() {
									tween(nearbyExplosion, {
										scaleX: 1.8,
										scaleY: 1.8,
										alpha: 0
									}, {
										duration: 200,
										easing: tween.easeIn,
										onFinish: function onFinish() {
											nearbyExplosion.destroy();
										}
									});
								}
							});
						}
					}
				}
				// Create MASSIVE tank weapon explosion with devastating area damage
				if (self.type === 'tank') {
					// Store explosion position for area damage calculation
					var explosionX = self.targetEnemy.x;
					var explosionY = self.targetEnemy.y;
					// MASSIVE explosion radius - much larger than missiles for devastating effect
					var explosionRadius = CELL_SIZE * 4.0; // 4 cell radius for tank weapons (60% larger than missiles)
					// Apply devastating area damage to all enemies within explosion radius
					for (var i = 0; i < enemies.length; i++) {
						var nearbyEnemy = enemies[i];
						if (nearbyEnemy !== self.targetEnemy) {
							var dx = nearbyEnemy.x - explosionX;
							var dy = nearbyEnemy.y - explosionY;
							var distance = Math.sqrt(dx * dx + dy * dy);
							if (distance <= explosionRadius) {
								// Tank weapons cause MASSIVE damage - instantly destroy most enemies
								if (nearbyEnemy.type === 'fast' || nearbyEnemy.type === 'flying' || nearbyEnemy.isFlying) {
									// Instantly destroy fast and flying enemies
									nearbyEnemy.health = 0;
								} else if (nearbyEnemy.type === 'immune' || nearbyEnemy.isImmune) {
									// Tank weapons instantly destroy immune enemies
									nearbyEnemy.health = 0;
								} else if (nearbyEnemy.type === 'tank') {
									// Tank weapons instantly destroy tank enemies
									nearbyEnemy.health = 0;
								} else if (nearbyEnemy.isBoss) {
									// Tank weapons instantly destroy boss enemies
									nearbyEnemy.health = 0;
								} else {
									// Massive damage to other enemy types
									nearbyEnemy.health -= self.damage * 3.0; // 3x damage for devastating effect
									if (nearbyEnemy.health <= 0) {
										nearbyEnemy.health = 0;
									} else {
										nearbyEnemy.healthBar.width = nearbyEnemy.health / nearbyEnemy.maxHealth * 70;
									}
								}
								// Create individual massive explosion effect for each affected enemy
								var nearbyExplosion = new EffectIndicator(nearbyEnemy.x, nearbyEnemy.y, 'splash');
								nearbyExplosion.children[0].tint = 0x8B4513; // Dark brown for tank explosion
								nearbyExplosion.children[0].width = nearbyExplosion.children[0].height = CELL_SIZE * 2.0; // Larger than missile explosions
								nearbyExplosion.alpha = 1.0;
								nearbyExplosion.scaleX = 0.3;
								nearbyExplosion.scaleY = 0.3;
								game.addChild(nearbyExplosion);
								// Animate massive nearby explosion
								tween(nearbyExplosion, {
									scaleX: 1.8,
									scaleY: 1.8,
									alpha: 0.8
								}, {
									duration: 150,
									easing: tween.easeOut,
									onFinish: function onFinish() {
										tween(nearbyExplosion, {
											scaleX: 2.5,
											scaleY: 2.5,
											alpha: 0
										}, {
											duration: 300,
											easing: tween.easeIn,
											onFinish: function onFinish() {
												nearbyExplosion.destroy();
											}
										});
									}
								});
							}
						}
					}
					// Create ULTRA-MASSIVE tank weapon explosion with enhanced visual effects
					// Stage 1: Initial massive impact flash - GIGANTIC white flash
					var impactFlash = new EffectIndicator(explosionX, explosionY, 'splash');
					impactFlash.children[0].tint = 0xFFFFFF; // Bright white impact flash
					impactFlash.children[0].width = impactFlash.children[0].height = CELL_SIZE * 6.0; // ENORMOUS initial flash
					impactFlash.alpha = 1;
					impactFlash.scaleX = 0.1;
					impactFlash.scaleY = 0.1;
					game.addChild(impactFlash);
					// Ultra-fast bright flash expansion
					tween(impactFlash, {
						scaleX: 8.0,
						// Much bigger than missile explosions
						scaleY: 8.0,
						alpha: 0
					}, {
						duration: 100,
						easing: tween.easeOut
					});
					// Stage 2: MASSIVE main tank explosion fireball - dark brown/orange core
					var mainExplosion = new EffectIndicator(explosionX, explosionY, 'splash');
					mainExplosion.children[0].tint = 0x8B4513; // Dark brown for tank explosion
					mainExplosion.children[0].width = mainExplosion.children[0].height = CELL_SIZE * 10.0; // ENORMOUS main explosion
					mainExplosion.alpha = 1;
					mainExplosion.scaleX = 0.2;
					mainExplosion.scaleY = 0.2;
					game.addChild(mainExplosion);
					// Dramatic MASSIVE fireball expansion
					tween(mainExplosion, {
						scaleX: 6.5,
						// Bigger than missile explosions
						scaleY: 6.5,
						alpha: 0.95
					}, {
						duration: 300,
						easing: tween.bounceOut,
						onFinish: function onFinish() {
							tween(mainExplosion, {
								scaleX: 10.0,
								// ENORMOUS final scale
								scaleY: 10.0,
								alpha: 0
							}, {
								duration: 800,
								easing: tween.easeIn,
								onFinish: function onFinish() {
									mainExplosion.destroy();
								}
							});
						}
					});
					// Stage 3: Create QUADRUPLE the explosion particles for MASSIVE debris effect
					for (var particleIndex = 0; particleIndex < 32; particleIndex++) {
						// More particles than missiles
						var explosionParticle = new EffectIndicator(explosionX, explosionY, 'splash');
						// Tank explosion colors - browns and oranges
						var particleColors = [0x8B4513, 0xA0522D, 0xD2691E, 0xFF8C00, 0xCD853F, 0xDEB887, 0x654321, 0x8B7355];
						explosionParticle.children[0].tint = particleColors[particleIndex % particleColors.length];
						explosionParticle.children[0].width = explosionParticle.children[0].height = CELL_SIZE * (2.2 + Math.random() * 1.8); // Bigger particles
						explosionParticle.alpha = 0.95;
						explosionParticle.scaleX = 0.6 + Math.random() * 0.5;
						explosionParticle.scaleY = 0.6 + Math.random() * 0.5;
						// Random direction for particle scatter with ULTRA-LONG distance
						var particleAngle = particleIndex / 32 * Math.PI * 2 + (Math.random() - 0.5) * 0.8;
						var particleDistance = CELL_SIZE * (4.5 + Math.random() * 3.5); // Ultra-far particle scatter
						var targetX = explosionX + Math.cos(particleAngle) * particleDistance;
						var targetY = explosionY + Math.sin(particleAngle) * particleDistance;
						game.addChild(explosionParticle);
						// Animate particles flying outward
						tween(explosionParticle, {
							x: targetX,
							y: targetY,
							scaleX: 4.0 + Math.random() * 1.5,
							// Much bigger final scale
							scaleY: 4.0 + Math.random() * 1.5,
							alpha: 0.8
						}, {
							duration: 400 + Math.random() * 300,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								tween(explosionParticle, {
									scaleX: 0.3,
									scaleY: 0.3,
									alpha: 0
								}, {
									duration: 500 + Math.random() * 250,
									easing: tween.easeIn,
									onFinish: function onFinish() {
										explosionParticle.destroy();
									}
								});
							}
						});
					}
					// Stage 4: QUINTUPLE shockwave rings for tank weapons
					var primaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
					primaryShockwave.children[0].tint = 0xDEB887; // Light brown shockwave
					primaryShockwave.children[0].alpha = 0.8;
					primaryShockwave.children[0].width = primaryShockwave.children[0].height = CELL_SIZE * 2.0;
					primaryShockwave.alpha = 1.0;
					game.addChild(primaryShockwave);
					// MASSIVE expanding primary shockwave
					tween(primaryShockwave, {
						scaleX: 15.0,
						// Bigger than missile shockwaves
						scaleY: 15.0,
						alpha: 0
					}, {
						duration: 900,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							primaryShockwave.destroy();
						}
					});
					// Multiple additional shockwaves for devastating effect
					for (var shockIndex = 1; shockIndex <= 4; shockIndex++) {
						var additionalShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
						additionalShockwave.children[0].tint = 0x8B7355; // Darker brown shockwave
						additionalShockwave.children[0].alpha = 0.6 - shockIndex * 0.1;
						additionalShockwave.children[0].width = additionalShockwave.children[0].height = CELL_SIZE * (2.0 - shockIndex * 0.2);
						additionalShockwave.alpha = 0.8 - shockIndex * 0.1;
						game.addChild(additionalShockwave);
						// Delayed massive shockwaves
						tween(additionalShockwave, {
							scaleX: 16.0 + shockIndex * 1.0,
							scaleY: 16.0 + shockIndex * 1.0,
							alpha: 0
						}, {
							duration: 1000 + shockIndex * 100,
							delay: shockIndex * 200,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								additionalShockwave.destroy();
							}
						});
					}
					// Stage 5: MASSIVE lingering smoke cloud
					var smokeCloud = new EffectIndicator(explosionX, explosionY, 'splash');
					smokeCloud.children[0].tint = 0x696969; // Dark gray smoke
					smokeCloud.children[0].alpha = 0.7;
					smokeCloud.children[0].width = smokeCloud.children[0].height = CELL_SIZE * 8.0; // Bigger smoke cloud
					smokeCloud.alpha = 0;
					smokeCloud.scaleX = 1.2;
					smokeCloud.scaleY = 1.2;
					game.addChild(smokeCloud);
					// Delayed massive smoke appearance
					tween(smokeCloud, {
						alpha: 1.0,
						scaleX: 8.0,
						scaleY: 8.0
					}, {
						duration: 500,
						delay: 500,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							// Smoke slowly dissipates over very long time
							tween(smokeCloud, {
								alpha: 0,
								scaleX: 14.0,
								// ENORMOUS final scale
								scaleY: 14.0
							}, {
								duration: 2000,
								// Very long dissipation time
								easing: tween.easeIn,
								onFinish: function onFinish() {
									smokeCloud.destroy();
								}
							});
						}
					});
				}
				// Create ULTRA-MASSIVE spectacular multi-stage missile explosion with ENHANCED particle effects
				// Stage 1: Initial impact flash - ULTRA bright white flash (GIGANTIC)
				var impactFlash = new EffectIndicator(explosionX, explosionY, 'splash');
				impactFlash.children[0].tint = 0xFFFFFF; // Bright white impact flash
				impactFlash.children[0].width = impactFlash.children[0].height = CELL_SIZE * 5.0; // GIGANTIC initial flash (increased from 3.5)
				impactFlash.alpha = 1;
				impactFlash.scaleX = 0.1;
				impactFlash.scaleY = 0.1;
				game.addChild(impactFlash);
				// Ultra-fast bright flash expansion (GIGANTIC SCALE)
				tween(impactFlash, {
					scaleX: 7.0,
					// MUCH bigger scale (increased from 4.5)
					scaleY: 7.0,
					alpha: 0
				}, {
					duration: 120,
					easing: tween.easeOut
				});
				// Stage 2: ULTRA-MASSIVE main explosion fireball - orange/red core (ENORMOUS)
				var mainExplosion = new EffectIndicator(explosionX, explosionY, 'splash');
				mainExplosion.children[0].tint = 0xFF4500; // Orange-red fireball
				mainExplosion.children[0].width = mainExplosion.children[0].height = CELL_SIZE * 8.0; // ENORMOUS main explosion (increased from 6.0)
				mainExplosion.alpha = 1;
				mainExplosion.scaleX = 0.2;
				mainExplosion.scaleY = 0.2;
				game.addChild(mainExplosion);
				// Dramatic ULTRA-MASSIVE fireball expansion with bounce effect
				tween(mainExplosion, {
					scaleX: 5.5,
					// Much bigger scale (increased from 3.8)
					scaleY: 5.5,
					alpha: 0.95
				}, {
					duration: 250,
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						tween(mainExplosion, {
							scaleX: 8.5,
							// ENORMOUS final scale (increased from 6.0)
							scaleY: 8.5,
							alpha: 0
						}, {
							duration: 700,
							easing: tween.easeIn,
							onFinish: function onFinish() {
								mainExplosion.destroy();
							}
						});
					}
				});
				// Stage 3: Create TRIPLE the explosion particles for ULTRA-MASSIVE debris effect (TRIPLED)
				for (var particleIndex = 0; particleIndex < 24; particleIndex++) {
					// Increased from 16 to 24
					var explosionParticle = new EffectIndicator(explosionX, explosionY, 'splash');
					// Vary particle colors for realistic explosion with MORE variety
					var particleColors = [0xFF6600, 0xFF4500, 0xFF8800, 0xFFAA00, 0xFF2200, 0xFFCC00, 0xFF3300, 0xFFDD00];
					explosionParticle.children[0].tint = particleColors[particleIndex % particleColors.length];
					explosionParticle.children[0].width = explosionParticle.children[0].height = CELL_SIZE * (1.8 + Math.random() * 1.5); // MUCH bigger particles (increased from 1.2 + 1.0)
					explosionParticle.alpha = 0.9;
					explosionParticle.scaleX = 0.5 + Math.random() * 0.4;
					explosionParticle.scaleY = 0.5 + Math.random() * 0.4;
					// Random direction for particle scatter with ULTRA-LONG distance
					var particleAngle = particleIndex / 24 * Math.PI * 2 + (Math.random() - 0.5) * 0.8;
					var particleDistance = CELL_SIZE * (3.5 + Math.random() * 3.0); // ULTRA-FAR particle scatter (increased from 2.5 + 2.0)
					var targetX = explosionX + Math.cos(particleAngle) * particleDistance;
					var targetY = explosionY + Math.sin(particleAngle) * particleDistance;
					game.addChild(explosionParticle);
					// Animate particles flying outward with ULTRA-enhanced physics
					tween(explosionParticle, {
						x: targetX,
						y: targetY,
						scaleX: 3.5 + Math.random() * 1.2,
						// Much bigger final scale (increased from 2.5 + 0.8)
						scaleY: 3.5 + Math.random() * 1.2,
						alpha: 0.7
					}, {
						duration: 350 + Math.random() * 250,
						// Longer duration
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(explosionParticle, {
								scaleX: 0.2,
								scaleY: 0.2,
								alpha: 0
							}, {
								duration: 450 + Math.random() * 200,
								// Longer fade duration
								easing: tween.easeIn,
								onFinish: function onFinish() {
									explosionParticle.destroy();
								}
							});
						}
					});
				}
				// Stage 4: ULTRA-MASSIVE enhanced shockwave with QUADRUPLE rings
				var primaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
				primaryShockwave.children[0].tint = 0xFFDDDD; // Light pink shockwave
				primaryShockwave.children[0].alpha = 0.7;
				primaryShockwave.children[0].width = primaryShockwave.children[0].height = CELL_SIZE * 1.5; // Bigger base
				primaryShockwave.alpha = 0.9;
				game.addChild(primaryShockwave);
				// ULTRA-HUGE expanding primary shockwave
				tween(primaryShockwave, {
					scaleX: 12.0,
					// ENORMOUS scale (increased from 8.5)
					scaleY: 12.0,
					alpha: 0
				}, {
					duration: 800,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						primaryShockwave.destroy();
					}
				});
				// Secondary ULTRA-MASSIVE shockwave
				var secondaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
				secondaryShockwave.children[0].tint = 0xFFFFFF; // White secondary wave
				secondaryShockwave.children[0].alpha = 0.5;
				secondaryShockwave.children[0].width = secondaryShockwave.children[0].height = CELL_SIZE * 1.0;
				secondaryShockwave.alpha = 0.8;
				game.addChild(secondaryShockwave);
				// Delayed ULTRA-MASSIVE secondary shockwave
				tween(secondaryShockwave, {
					scaleX: 13.0,
					// ENORMOUS scale (increased from 9.0)
					scaleY: 13.0,
					alpha: 0
				}, {
					duration: 900,
					delay: 150,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						secondaryShockwave.destroy();
					}
				});
				// Third shockwave for QUADRUPLE-ring ULTRA-MASSIVE effect
				var tertiaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
				tertiaryShockwave.children[0].tint = 0xFFAAAA; // Light red tertiary wave
				tertiaryShockwave.children[0].alpha = 0.3;
				tertiaryShockwave.children[0].width = tertiaryShockwave.children[0].height = CELL_SIZE * 0.8;
				tertiaryShockwave.alpha = 0.7;
				game.addChild(tertiaryShockwave);
				// Third delayed ULTRA-MASSIVE shockwave
				tween(tertiaryShockwave, {
					scaleX: 14.0,
					// ENORMOUS scale (increased from 10.0)
					scaleY: 14.0,
					alpha: 0
				}, {
					duration: 1000,
					delay: 300,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tertiaryShockwave.destroy();
					}
				});
				// Fourth shockwave for QUADRUPLE-ring effect (NEW!)
				var quaternaryShockwave = new EffectIndicator(explosionX, explosionY, 'splash');
				quaternaryShockwave.children[0].tint = 0xFFCCCC; // Very light pink quaternary wave
				quaternaryShockwave.children[0].alpha = 0.2;
				quaternaryShockwave.children[0].width = quaternaryShockwave.children[0].height = CELL_SIZE * 0.6;
				quaternaryShockwave.alpha = 0.6;
				game.addChild(quaternaryShockwave);
				// Fourth delayed ULTRA-MASSIVE shockwave
				tween(quaternaryShockwave, {
					scaleX: 15.0,
					// ULTRA-ENORMOUS scale
					scaleY: 15.0,
					alpha: 0
				}, {
					duration: 1100,
					delay: 450,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						quaternaryShockwave.destroy();
					}
				});
				// Stage 5: ULTRA-MASSIVE smoke cloud effect - ENORMOUS and lingers much longer
				var smokeCloud = new EffectIndicator(explosionX, explosionY, 'splash');
				smokeCloud.children[0].tint = 0x666666; // Dark gray smoke
				smokeCloud.children[0].alpha = 0.6;
				smokeCloud.children[0].width = smokeCloud.children[0].height = CELL_SIZE * 6.0; // ENORMOUS smoke cloud (increased from 4.0)
				smokeCloud.alpha = 0;
				smokeCloud.scaleX = 1.0;
				smokeCloud.scaleY = 1.0;
				game.addChild(smokeCloud);
				// Delayed ULTRA-MASSIVE smoke appearance that grows slowly and lingers
				tween(smokeCloud, {
					alpha: 0.9,
					scaleX: 6.0,
					// Bigger initial expansion (increased from 4.0)
					scaleY: 6.0
				}, {
					duration: 450,
					delay: 400,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						// Smoke slowly dissipates over ULTRA-LONG time
						tween(smokeCloud, {
							alpha: 0,
							scaleX: 10.0,
							// ENORMOUS final scale (increased from 7.0)
							scaleY: 10.0
						}, {
							duration: 1500,
							// ULTRA-LONG dissipation time (increased from 1200)
							easing: tween.easeIn,
							onFinish: function onFinish() {
								smokeCloud.destroy();
							}
						});
					}
				});
			}
			// Apply special effects based on bullet type
			if (self.type === 'flamethrower') {
				// Create visual flame effect with enhanced animation
				var flameEffect = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'flamethrower');
				game.addChild(flameEffect);
				// Apply burning effect to target enemy
				if (!self.targetEnemy.isImmune) {
					self.targetEnemy.burning = true;
					self.targetEnemy.burnDamage = self.damage * 0.3; // 30% of original damage per tick
					self.targetEnemy.burnDuration = 180; // 3 seconds at 60 FPS
				}
				// Flame damage to enemies in a cone behind the target
				var coneRange = CELL_SIZE * 1.2;
				var targetAngle = Math.atan2(self.targetEnemy.y - self.y, self.targetEnemy.x - self.x);
				for (var i = 0; i < enemies.length; i++) {
					var otherEnemy = enemies[i];
					if (otherEnemy !== self.targetEnemy) {
						var flameDx = otherEnemy.x - self.targetEnemy.x;
						var flameDy = otherEnemy.y - self.targetEnemy.y;
						var flameDistance = Math.sqrt(flameDx * flameDx + flameDy * flameDy);
						var enemyAngle = Math.atan2(flameDy, flameDx);
						var angleDiff = Math.abs(enemyAngle - targetAngle);
						// Normalize angle difference
						while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
						while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
						angleDiff = Math.abs(angleDiff);
						// Check if enemy is within cone (45 degrees = PI/4 radians)
						if (flameDistance <= coneRange && angleDiff <= Math.PI / 4) {
							// Apply flame damage (40% of original damage)
							otherEnemy.health -= self.damage * 0.4;
							if (otherEnemy.health <= 0) {
								otherEnemy.health = 0;
							} else {
								otherEnemy.healthBar.width = otherEnemy.health / otherEnemy.maxHealth * 70;
							}
							// Apply burning effect
							if (!otherEnemy.isImmune) {
								otherEnemy.burning = true;
								otherEnemy.burnDamage = self.damage * 0.2;
								otherEnemy.burnDuration = 120; // 2 seconds for cone targets
							}
						}
					}
				}
			} else if (self.type === 'slow') {
				// Prevent slow effect on immune enemies
				if (!self.targetEnemy.isImmune) {
					// Create visual slow effect
					var slowEffect = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'slow');
					game.addChild(slowEffect);
					// Apply slow effect
					// Make slow percentage scale with tower level (default 50%, up to 80% at max level)
					var slowPct = 0.5;
					if (self.sourceTowerLevel !== undefined) {
						// Scale: 50% at level 1, 60% at 2, 65% at 3, 70% at 4, 75% at 5, 80% at 6
						var slowLevels = [0.5, 0.6, 0.65, 0.7, 0.75, 0.8];
						var idx = Math.max(0, Math.min(5, self.sourceTowerLevel - 1));
						slowPct = slowLevels[idx];
					}
					if (!self.targetEnemy.slowed) {
						self.targetEnemy.originalSpeed = self.targetEnemy.speed;
						self.targetEnemy.speed *= 1 - slowPct; // Slow by X%
						self.targetEnemy.slowed = true;
						self.targetEnemy.slowDuration = 180; // 3 seconds at 60 FPS
					} else {
						self.targetEnemy.slowDuration = 180; // Reset duration
					}
				}
			} else if (self.type === 'poison') {
				// Prevent poison effect on immune enemies
				if (!self.targetEnemy.isImmune) {
					// Create visual poison effect
					var poisonEffect = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'poison');
					game.addChild(poisonEffect);
					// Apply poison effect
					self.targetEnemy.poisoned = true;
					self.targetEnemy.poisonDamage = self.damage * 0.2; // 20% of original damage per tick
					self.targetEnemy.poisonDuration = 300; // 5 seconds at 60 FPS
				}
			} else if (self.type === 'sniper') {
				// Create visual critical hit effect for sniper
				var sniperEffect = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'sniper');
				game.addChild(sniperEffect);
			}
			self.destroy();
		} else {
			var angle = Math.atan2(dy, dx);
			// Apply spread angle for machine gun bullets
			if (self.type === 'trap' && self.spreadAngle !== undefined) {
				angle += self.spreadAngle;
			}
			// Rotate missile asset to face target direction
			if (self.type === 'slow' && self.children.length > 0) {
				var missileGraphics = self.children[0];
				if (missileGraphics.targetRotation === undefined) {
					missileGraphics.targetRotation = angle;
					missileGraphics.rotation = angle;
				} else {
					// Only rotate if angle difference is significant
					if (Math.abs(angle - missileGraphics.targetRotation) > 0.1) {
						tween.stop(missileGraphics, {
							rotation: true
						});
						// Calculate shortest rotation path
						var currentRotation = missileGraphics.rotation;
						var angleDiff = angle - currentRotation;
						// Normalize angle difference to -PI to PI range
						while (angleDiff > Math.PI) {
							angleDiff -= Math.PI * 2;
						}
						while (angleDiff < -Math.PI) {
							angleDiff += Math.PI * 2;
						}
						missileGraphics.targetRotation = angle;
						tween(missileGraphics, {
							rotation: currentRotation + angleDiff
						}, {
							duration: 100,
							easing: tween.easeOut
						});
					}
				}
			}
			self.x += Math.cos(angle) * self.speed;
			self.y += Math.sin(angle) * self.speed;
		}
	};
	return self;
});
// DebugCell class removed
var EffectIndicator = Container.expand(function (x, y, type) {
	var self = Container.call(this);
	self.x = x;
	self.y = y;
	var effectGraphics = self.attachAsset('rangeCircle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	effectGraphics.blendMode = 1;
	switch (type) {
		case 'splash':
			effectGraphics.tint = 0x33CC00;
			effectGraphics.width = effectGraphics.height = CELL_SIZE * 1.5;
			break;
		case 'slow':
			effectGraphics.tint = 0x9900FF;
			effectGraphics.width = effectGraphics.height = CELL_SIZE;
			break;
		case 'poison':
			effectGraphics.tint = 0x00FFAA;
			effectGraphics.width = effectGraphics.height = CELL_SIZE;
			break;
		case 'sniper':
			effectGraphics.tint = 0xFF5500;
			effectGraphics.width = effectGraphics.height = CELL_SIZE;
			break;
		case 'flamethrower':
			effectGraphics.tint = 0xFF4500;
			effectGraphics.width = CELL_SIZE * 1.5;
			effectGraphics.height = CELL_SIZE * 0.8; // Elongated flame effect
			break;
	}
	effectGraphics.alpha = 0.7;
	self.alpha = 0;
	// Animate the effect
	tween(self, {
		alpha: 0.8,
		scaleX: 1.5,
		scaleY: 1.5
	}, {
		duration: 200,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			tween(self, {
				alpha: 0,
				scaleX: 2,
				scaleY: 2
			}, {
				duration: 300,
				easing: tween.easeIn,
				onFinish: function onFinish() {
					self.destroy();
				}
			});
		}
	});
	return self;
});
// Base enemy class for common functionality
var Enemy = Container.expand(function (type) {
	var self = Container.call(this);
	self.type = type || 'normal';
	self.speed = .02;
	self.cellX = 0;
	self.cellY = 0;
	self.currentCellX = 0;
	self.currentCellY = 0;
	self.currentTarget = undefined;
	self.maxHealth = 100;
	self.health = self.maxHealth;
	self.bulletsTargetingThis = [];
	self.waveNumber = currentWave;
	self.isFlying = false;
	self.isImmune = false;
	self.isBoss = false;
	self.collisionRadius = 25; // Base collision detection radius
	self.lastCollisionCheck = 0; // Performance optimization
	self.smokeEffectActive = false; // Track if smoke effect is already active
	self.lastHealthPercentage = 1.0; // Track last health percentage to detect transitions
	// Adjust collision radius based on enemy type
	switch (self.type) {
		case 'tank':
			self.collisionRadius = 40; // Larger radius for tank enemies
			break;
		case 'fast':
			self.collisionRadius = 20; // Smaller radius for fast enemies
			break;
		case 'flying':
			self.collisionRadius = 30; // Medium radius for flying enemies
			break;
		default:
			self.collisionRadius = 25; // Default radius
			break;
	}
	// Boss enemies have larger collision radius
	if (self.isBoss) {
		self.collisionRadius *= 1.5;
	}
	// Check if this is a boss wave
	// Check if this is a boss wave
	// Apply different stats based on enemy type
	switch (self.type) {
		case 'fast':
			self.speed *= 1; // Normal speed (half of previous 2x)
			// Speed boost for wave 5 fast enemies
			if (self.waveNumber === 5) {
				self.speed *= 1.2; // 1.2x speed for wave 5 fast enemies
			}
			// Speed boost for wave 6 fast enemies
			if (self.waveNumber === 6) {
				self.speed *= 1.1; // 1.1x speed for wave 6 fast enemies
			}
			self.maxHealth = 1;
			break;
		case 'immune':
			self.isImmune = true;
			self.maxHealth = 200;
			// Increase speed for wave 5 immune enemies only
			if (self.waveNumber === 5) {
				self.speed *= 3; // 3x speed for wave 5 immune enemies
			}
			// Speed boost for wave 2 immune enemies when they reach the second turn
			self.hasReachedSecondTurn = false;
			break;
		case 'flying':
			self.isFlying = true;
			self.speed *= 2; // 2x speed for flying enemies
			self.maxHealth = 80;
			break;
		case 'tank':
			self.speed *= 0.5; // Half speed for tank enemies
			self.maxHealth = 300; // Very high health for tank enemies
			break;
		default:
			// Default enemy uses fast values
			self.speed *= 1; // Normal speed (half of previous 2x)
			self.maxHealth = 1;
			break;
	}
	if (currentWave === totalWaves && type !== 'swarm') {
		self.isBoss = true;
		// Boss enemies have 20x health and are larger
		self.maxHealth *= 20;
		// Slower speed for bosses
		self.speed = self.speed * 0.7;
	}
	self.health = self.maxHealth;
	// Get appropriate asset for this enemy type
	var assetId = 'enemy';
	if (self.isBoss) {
		assetId = 'Boss';
	} else if (self.type === 'tank') {
		assetId = 'Tank';
	} else if (self.type !== 'normal') {
		assetId = 'enemy_' + self.type;
	}
	var enemyGraphics = self.attachAsset(assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Scale up boss enemies
	if (self.isBoss) {
		enemyGraphics.scaleX = 1.8;
		enemyGraphics.scaleY = 1.8;
	}
	// Fall back to regular enemy asset if specific type asset not found
	// Apply tint to differentiate enemy types
	/*switch (self.type) {
		case 'fast':
			enemyGraphics.tint = 0x00AAFF; // Blue for fast enemies
			break;
		case 'immune':
			enemyGraphics.tint = 0xAA0000; // Red for immune enemies
			break;
		case 'flying':
			enemyGraphics.tint = 0xFFFF00; // Yellow for flying enemies
			break;
		case 'swarm':
			enemyGraphics.tint = 0xFF00FF; // Pink for swarm enemies
			break;
	}*/
	// Create shadow for flying enemies
	if (self.isFlying) {
		// Create a shadow container that will be added to the shadow layer
		self.shadow = new Container();
		// Clone the enemy graphics for the shadow
		var shadowGraphics = self.shadow.attachAsset(assetId || 'enemy', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		// Apply shadow effect
		shadowGraphics.tint = 0x000000; // Black shadow
		shadowGraphics.alpha = 0.4; // Semi-transparent
		// If this is a boss, scale up the shadow to match
		if (self.isBoss) {
			shadowGraphics.scaleX = 1.8;
			shadowGraphics.scaleY = 1.8;
		}
		// Position shadow slightly offset
		self.shadow.x = 20; // Offset right
		self.shadow.y = 20; // Offset down
		// Ensure shadow has the same rotation as the enemy
		shadowGraphics.rotation = enemyGraphics.rotation;
	}
	var healthBarOutline = self.attachAsset('healthBarOutline', {
		anchorX: 0,
		anchorY: 0.5
	});
	var healthBarBG = self.attachAsset('healthBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	var healthBar = self.attachAsset('healthBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	healthBarBG.y = healthBarOutline.y = healthBar.y = -enemyGraphics.height / 2 - 10;
	healthBarOutline.x = -healthBarOutline.width / 2;
	healthBarBG.x = healthBar.x = -healthBar.width / 2 - .5;
	healthBar.tint = 0x00ff00;
	healthBarBG.tint = 0xff0000;
	self.healthBar = healthBar;
	self.update = function () {
		if (self.health <= 0) {
			self.health = 0;
			self.healthBar.width = 0;
		}
		// Check for 50% health threshold for smoke effect
		var currentHealthPercentage = self.health / self.maxHealth;
		if (!self.smokeEffectActive && self.lastHealthPercentage > 0.5 && currentHealthPercentage <= 0.5) {
			// Check if this enemy type should have smoke effect (Flying, BOSS, Immune, Tank)
			if (self.isFlying || self.isBoss || self.isImmune || self.type === 'tank') {
				self.smokeEffectActive = true;
				// Create animated smoke steam effect
				var smokeEffect = new Container();
				smokeEffect.x = self.x;
				smokeEffect.y = self.y - enemyGraphics.height / 2 - 10;
				// Create multiple smoke particles for realistic steam effect
				for (var smokeIndex = 0; smokeIndex < 5; smokeIndex++) {
					var smokeParticle = smokeEffect.attachAsset('rangeCircle', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					// Set smoke particle properties - scaled up to 2x size
					smokeParticle.width = (15 + Math.random() * 10) * 2;
					smokeParticle.height = (20 + Math.random() * 15) * 2;
					smokeParticle.tint = 0x666666; // Dark gray smoke
					smokeParticle.alpha = 0.6 + Math.random() * 0.3;
					// Position particles in a small cluster
					smokeParticle.x = (Math.random() - 0.5) * 20;
					smokeParticle.y = smokeIndex * -8;
					// Animate smoke particles rising and fading
					tween(smokeParticle, {
						y: smokeParticle.y - 60 - Math.random() * 40,
						x: smokeParticle.x + (Math.random() - 0.5) * 30,
						scaleX: 1.5 + Math.random() * 0.5,
						scaleY: 1.5 + Math.random() * 0.5,
						alpha: 0
					}, {
						duration: 2000 + Math.random() * 1000,
						delay: smokeIndex * 200,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							smokeParticle.destroy();
						}
					});
				}
				game.addChild(smokeEffect);
				// Create continuous smoke effect that follows the enemy
				self.continuousSmokeEffect = smokeEffect;
				// Set up repeating smoke generation
				self.smokeTimer = 0;
				self.smokeInterval = 60; // Generate new smoke every 60 frames (1 second)
			}
		}
		// Update continuous smoke effect position if active
		if (self.smokeEffectActive && self.continuousSmokeEffect && self.continuousSmokeEffect.parent) {
			self.continuousSmokeEffect.x = self.x;
			self.continuousSmokeEffect.y = self.y - enemyGraphics.height / 2 - 10;
			// Generate new smoke particles periodically
			self.smokeTimer++;
			if (self.smokeTimer >= self.smokeInterval) {
				self.smokeTimer = 0;
				// Create new smoke particle
				var newSmokeParticle = self.continuousSmokeEffect.attachAsset('rangeCircle', {
					anchorX: 0.5,
					anchorY: 0.5
				});
				newSmokeParticle.width = (12 + Math.random() * 8) * 2;
				newSmokeParticle.height = (16 + Math.random() * 12) * 2;
				newSmokeParticle.tint = 0x888888; // Lighter gray for continuous smoke
				newSmokeParticle.alpha = 0.4 + Math.random() * 0.2;
				newSmokeParticle.x = (Math.random() - 0.5) * 15;
				newSmokeParticle.y = 0;
				// Animate new smoke particle
				tween(newSmokeParticle, {
					y: -40 - Math.random() * 20,
					x: newSmokeParticle.x + (Math.random() - 0.5) * 20,
					scaleX: 1.2 + Math.random() * 0.3,
					scaleY: 1.2 + Math.random() * 0.3,
					alpha: 0
				}, {
					duration: 1500 + Math.random() * 500,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						newSmokeParticle.destroy();
					}
				});
			}
		}
		// Update last health percentage for next frame comparison
		self.lastHealthPercentage = currentHealthPercentage;
		// Handle slow effect
		if (self.isImmune) {
			// Immune enemies cannot be slowed, poisoned, or burned, clear any such effects
			self.slowed = false;
			self.slowEffect = false;
			self.poisoned = false;
			self.poisonEffect = false;
			self.burning = false;
			self.burnEffect = false;
			// Reset speed to original if needed
			if (self.originalSpeed !== undefined) {
				self.speed = self.originalSpeed;
			}
		} else {
			// Handle slow effect
			if (self.slowed) {
				// Visual indication of slowed status
				if (!self.slowEffect) {
					self.slowEffect = true;
				}
				self.slowDuration--;
				if (self.slowDuration <= 0) {
					self.speed = self.originalSpeed;
					self.slowed = false;
					self.slowEffect = false;
					// Only reset tint if not poisoned
					if (!self.poisoned) {
						enemyGraphics.tint = 0xFFFFFF; // Reset tint
					}
				}
			}
			// Handle poison effect
			if (self.poisoned) {
				// Visual indication of poisoned status
				if (!self.poisonEffect) {
					self.poisonEffect = true;
				}
				// Apply poison damage every 30 frames (twice per second)
				if (LK.ticks % 30 === 0) {
					self.health -= self.poisonDamage;
					if (self.health <= 0) {
						self.health = 0;
					}
					self.healthBar.width = self.health / self.maxHealth * 70;
				}
				self.poisonDuration--;
				if (self.poisonDuration <= 0) {
					self.poisoned = false;
					self.poisonEffect = false;
					// Only reset tint if not slowed
					if (!self.slowed) {
						enemyGraphics.tint = 0xFFFFFF; // Reset tint
					}
				}
			}
			// Handle burning effect from flamethrower
			if (self.burning) {
				// Visual indication of burning status
				if (!self.burnEffect) {
					self.burnEffect = true;
				}
				// Apply burn damage every 20 frames (3 times per second)
				if (LK.ticks % 20 === 0) {
					self.health -= self.burnDamage;
					if (self.health <= 0) {
						self.health = 0;
					}
					self.healthBar.width = self.health / self.maxHealth * 70;
				}
				self.burnDuration--;
				if (self.burnDuration <= 0) {
					self.burning = false;
					self.burnEffect = false;
					// Only reset tint if not slowed or poisoned
					if (!self.slowed && !self.poisoned) {
						enemyGraphics.tint = 0xFFFFFF; // Reset tint
					}
				}
			}
		}
		// Enemy overlap avoidance - check every frame for immune and tank enemies for better convoy formation
		if (self.type === 'immune' || self.type === 'tank' || LK.ticks % 3 === 0) {
			for (var i = 0; i < enemies.length; i++) {
				var otherEnemy = enemies[i];
				if (otherEnemy !== self && otherEnemy.parent) {
					// Prevent collision between flying and ground enemies (fast, immune, tank)
					if (self.isFlying && !otherEnemy.isFlying || !self.isFlying && otherEnemy.isFlying) {
						continue; // Skip collision detection between flying and ground enemies
					}
					var dx = otherEnemy.x - self.x;
					var dy = otherEnemy.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					var minDistance = (self.collisionRadius + otherEnemy.collisionRadius) * 1.4; // Increased buffer for better separation
					if (distance < minDistance && distance > 0) {
						// Much stronger separation force for immune and tank enemies
						var overlap = minDistance - distance;
						var separationForce;
						if (self.type === 'immune' || self.type === 'tank' || otherEnemy.type === 'immune' || otherEnemy.type === 'tank') {
							// Extra strong separation for immune/tank enemies to maintain convoy formation
							separationForce = Math.pow(overlap / minDistance, 1.5) * 4.0; // Stronger force with smoother scaling
						} else {
							separationForce = Math.pow(overlap / minDistance, 2) * 2.0; // Original force for other enemies
						}
						var separationX = dx / distance * separationForce;
						var separationY = dy / distance * separationForce;
						// Apply separation with stronger horizontal bias to maintain lanes
						self.currentCellX -= separationX;
						self.currentCellY -= separationY * 0.7; // Reduced Y separation to maintain forward movement
						// Apply weaker counter-force to maintain formation
						otherEnemy.currentCellX += separationX * 0.3;
						otherEnemy.currentCellY += separationY * 0.3;
						// Keep enemies within reasonable bounds
						self.currentCellX = Math.max(2, Math.min(22, self.currentCellX));
						self.currentCellY = Math.max(-20, Math.min(33, self.currentCellY));
						otherEnemy.currentCellX = Math.max(2, Math.min(22, otherEnemy.currentCellX));
						otherEnemy.currentCellY = Math.max(-20, Math.min(33, otherEnemy.currentCellY));
					}
				}
			}
		}
		// Fast enemy shooting capability
		if (self.type === 'fast') {
			// Initialize shooting properties if not already set
			if (self.shootingCooldown === undefined) {
				self.shootingCooldown = 0;
				self.shootingRange = 12 * CELL_SIZE; // 12 cell shooting range (3x increase)
				self.shootingDamage = 5;
				self.bulletSpeed = 3;
			}
			// Decrease shooting cooldown
			if (self.shootingCooldown > 0) {
				self.shootingCooldown--;
			}
			// Try to find and shoot at towers within range
			if (self.shootingCooldown <= 0 && self.currentCellY >= 4) {
				var targetTower = null;
				var closestDistance = self.shootingRange;
				// Find closest tower within shooting range
				for (var i = 0; i < towers.length; i++) {
					var tower = towers[i];
					// Skip landmine towers - enemies cannot see them
					if (tower.id === 'landmine') {
						continue;
					}
					// Allow targeting of all other tower types including trap/shooter towers
					var dx = tower.x - self.x;
					var dy = tower.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= self.shootingRange && distance < closestDistance) {
						closestDistance = distance;
						targetTower = tower;
					}
				}
				// Shoot at the target tower if found
				if (targetTower) {
					var bulletX = self.x;
					var bulletY = self.y;
					var enemyBullet = new Bullet(bulletX, bulletY, targetTower, self.shootingDamage, self.bulletSpeed);
					// Customize enemy bullet appearance
					if (enemyBullet.children[0]) {
						enemyBullet.children[0].tint = 0xFF0000; // Red color for enemy bullets
						enemyBullet.children[0].width = 20;
						enemyBullet.children[0].height = 20;
					}
					// Mark as enemy bullet to handle differently
					enemyBullet.isEnemyBullet = true;
					game.addChild(enemyBullet);
					bullets.push(enemyBullet);
					// Set cooldown (shoot every 1.5 seconds at 60 FPS)
					self.shootingCooldown = 90;
				}
			}
		}
		// Immune enemy shooting capability
		if (self.type === 'immune') {
			// Initialize shooting properties if not already set
			if (self.shootingCooldown === undefined) {
				self.shootingCooldown = 0;
				self.shootingRange = 8 * CELL_SIZE; // 8 cell shooting range for immune enemies
				self.shootingDamage = 8;
				self.bulletSpeed = 4;
			}
			// Decrease shooting cooldown
			if (self.shootingCooldown > 0) {
				self.shootingCooldown--;
			}
			// Try to find and shoot at towers within range
			if (self.shootingCooldown <= 0 && self.currentCellY >= 4) {
				var targetTower = null;
				var closestDistance = self.shootingRange;
				// Find closest tower within shooting range
				for (var i = 0; i < towers.length; i++) {
					var tower = towers[i];
					// Skip landmine towers - enemies cannot see them
					if (tower.id === 'landmine') {
						continue;
					}
					// Allow targeting of all other tower types including trap/shooter towers
					var dx = tower.x - self.x;
					var dy = tower.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= self.shootingRange && distance < closestDistance) {
						closestDistance = distance;
						targetTower = tower;
					}
				}
				// Shoot at the target tower if found
				if (targetTower) {
					var bulletX = self.x;
					var bulletY = self.y;
					var enemyBullet = new Bullet(bulletX, bulletY, targetTower, self.shootingDamage, self.bulletSpeed);
					// Customize immune enemy bullet appearance
					if (enemyBullet.children[0]) {
						enemyBullet.children[0].tint = 0xAA0000; // Dark red color for immune enemy bullets
						enemyBullet.children[0].width = 25;
						enemyBullet.children[0].height = 25;
					}
					// Mark as enemy bullet to handle differently
					enemyBullet.isEnemyBullet = true;
					game.addChild(enemyBullet);
					bullets.push(enemyBullet);
					// Set cooldown (shoot every 1 second at 60 FPS)
					self.shootingCooldown = 60;
				}
			}
		}
		// Immune enemy trap collision detection
		if (self.type === 'immune') {
			// Initialize trap contact tracking if not set
			if (self.trapContactMap === undefined) {
				self.trapContactMap = {};
			}
			// Check collision with trap towers every 10 frames for performance
			if (LK.ticks % 10 === 0) {
				for (var i = 0; i < towers.length; i++) {
					var tower = towers[i];
					if (tower.id === 'trap') {
						var dx = tower.x - self.x;
						var dy = tower.y - self.y;
						var distance = Math.sqrt(dx * dx + dy * dy);
						// Check if immune enemy is touching the trap (within 80 pixels)
						if (distance <= 80) {
							// Only reduce health if this trap hasn't been touched before
							var trapKey = tower.x + ',' + tower.y; // Unique identifier for this trap
							if (!self.trapContactMap[trapKey]) {
								self.trapContactMap[trapKey] = true;
								// Reduce immune enemy's health by half
								self.health = Math.floor(self.health / 2);
								if (self.health <= 0) {
									self.health = 0;
								}
								self.healthBar.width = self.health / self.maxHealth * 70;
								// Create visual effect for trap contact
								var trapEffect = new EffectIndicator(self.x, self.y, 'splash');
								trapEffect.children[0].tint = 0xAAAAAA; // Gray color for trap effect
								trapEffect.children[0].width = trapEffect.children[0].height = CELL_SIZE * 1.2;
								game.addChild(trapEffect);
							}
							// Break after first trap collision to avoid multiple hits per frame
							break;
						}
					}
				}
			}
		}
		// Tank enemy shooting capability
		if (self.type === 'tank') {
			// Initialize shooting properties if not already set
			if (self.shootingCooldown === undefined) {
				self.shootingCooldown = 0;
				self.shootingRange = 16 * CELL_SIZE; // 2x increased range for better targeting (was 8)
				self.shootingDamage = 15; // Increased damage for tank enemies
				self.bulletSpeed = 3; // Increased bullet speed
			}
			// Decrease shooting cooldown
			if (self.shootingCooldown > 0) {
				self.shootingCooldown--;
			}
			// Try to find and shoot at towers within range - tank enemies shoot when positioned
			if (self.shootingCooldown <= 0 && self.currentCellY >= 4 && self.tankMovementComplete) {
				var targetTower = null;
				var closestDistance = self.shootingRange;
				// Find closest tower within shooting range
				for (var i = 0; i < towers.length; i++) {
					var tower = towers[i];
					// Skip landmine towers - enemies cannot see them
					if (tower.id === 'landmine') {
						continue;
					}
					// Allow targeting of all other tower types including trap/shooter towers
					var dx = tower.x - self.x;
					var dy = tower.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= self.shootingRange && distance < closestDistance) {
						closestDistance = distance;
						targetTower = tower;
					}
				}
				// Shoot at the target tower if found
				if (targetTower) {
					var bulletX = self.x;
					var bulletY = self.y;
					var enemyBullet = new Bullet(bulletX, bulletY, targetTower, self.shootingDamage, self.bulletSpeed);
					// Customize tank enemy bullet appearance
					if (enemyBullet.children[0]) {
						enemyBullet.children[0].tint = 0x888888; // Gray color for tank enemy bullets
						enemyBullet.children[0].width = 35; // Larger bullets for tank enemies
						enemyBullet.children[0].height = 35;
					}
					// Mark as enemy bullet to handle differently
					enemyBullet.isEnemyBullet = true;
					game.addChild(enemyBullet);
					bullets.push(enemyBullet);
					// Set cooldown (shoot every 1.5 seconds at 60 FPS for more frequent shooting)
					self.shootingCooldown = 90;
				}
			}
		}
		// Convoy formation for immune and tank enemies - maintain proper spacing and formation
		if ((self.type === 'immune' || self.type === 'tank') && self.currentCellY >= 4) {
			// Find nearby same-type enemies to form convoy with
			var nearbyConvoyEnemies = [];
			for (var i = 0; i < enemies.length; i++) {
				var otherEnemy = enemies[i];
				if (otherEnemy !== self && otherEnemy.parent && otherEnemy.type === self.type) {
					var dx = otherEnemy.x - self.x;
					var dy = otherEnemy.y - self.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= CELL_SIZE * 4) {
						// Within 4 cells for convoy formation
						nearbyConvoyEnemies.push({
							enemy: otherEnemy,
							distance: distance,
							dx: dx,
							dy: dy
						});
					}
				}
			}
			// Apply convoy formation forces
			if (nearbyConvoyEnemies.length > 0) {
				for (var j = 0; j < nearbyConvoyEnemies.length; j++) {
					var convoyData = nearbyConvoyEnemies[j];
					var convoyEnemy = convoyData.enemy;
					var distance = convoyData.distance;
					var dx = convoyData.dx;
					var dy = convoyData.dy;
					var idealDistance = CELL_SIZE * 2.8; // Ideal convoy spacing
					if (distance < idealDistance) {
						// Too close - apply separation
						var separationForce = (idealDistance - distance) / idealDistance * 0.8;
						var separationX = dx / distance * separationForce;
						var separationY = dy / distance * separationForce * 0.4; // Less Y separation
						self.currentCellX -= separationX;
						self.currentCellY -= separationY;
					} else if (distance > idealDistance * 1.5) {
						// Too far - apply attraction to maintain convoy
						var attractionForce = (distance - idealDistance) / distance * 0.3;
						var attractionX = dx / distance * attractionForce;
						var attractionY = dy / distance * attractionForce * 0.2;
						self.currentCellX += attractionX;
						self.currentCellY += attractionY;
					}
				}
			}
			// Keep enemies within valid bounds
			self.currentCellX = Math.max(3, Math.min(21, self.currentCellX));
			self.currentCellY = Math.max(-20, Math.min(33, self.currentCellY));
		}
		// Set tint based on effect status
		if (self.isImmune) {
			enemyGraphics.tint = 0xFFFFFF;
		} else if (self.poisoned && self.slowed && self.burning) {
			// Combine all three effects
			enemyGraphics.tint = 0x8B4513; // Brown-ish mix
		} else if (self.poisoned && self.slowed) {
			// Combine poison (0x00FFAA) and slow (0x9900FF) colors
			// Simple average: R: (0+153)/2=76, G: (255+0)/2=127, B: (170+255)/2=212
			enemyGraphics.tint = 0x4C7FD4;
		} else if (self.poisoned && self.burning) {
			// Combine poison and burn
			enemyGraphics.tint = 0x8B7355; // Brownish-green mix
		} else if (self.slowed && self.burning) {
			// Combine slow and burn
			enemyGraphics.tint = 0xCC4500; // Orange-red mix
		} else if (self.burning) {
			enemyGraphics.tint = 0xFF4500; // Orange for burning
		} else if (self.poisoned) {
			enemyGraphics.tint = 0x00FFAA;
		} else if (self.slowed) {
			enemyGraphics.tint = 0x9900FF;
		} else {
			enemyGraphics.tint = 0xFFFFFF;
		}
		if (self.currentTarget) {
			var ox = self.currentTarget.x - self.currentCellX;
			var oy = self.currentTarget.y - self.currentCellY;
			if (ox !== 0 || oy !== 0) {
				var angle = Math.atan2(oy, ox) + Math.PI / 2;
				if (enemyGraphics.targetRotation === undefined) {
					enemyGraphics.targetRotation = angle;
					enemyGraphics.rotation = angle;
				} else {
					if (Math.abs(angle - enemyGraphics.targetRotation) > 0.25) {
						// Further increased threshold to reduce tween frequency
						tween.stop(enemyGraphics, {
							rotation: true
						});
						// Calculate the shortest angle to rotate
						var currentRotation = enemyGraphics.rotation;
						var angleDiff = angle - currentRotation;
						// Normalize angle difference to -PI to PI range for shortest path
						while (angleDiff > Math.PI) {
							angleDiff -= Math.PI * 2;
						}
						while (angleDiff < -Math.PI) {
							angleDiff += Math.PI * 2;
						}
						enemyGraphics.targetRotation = angle;
						tween(enemyGraphics, {
							rotation: currentRotation + angleDiff
						}, {
							duration: 150,
							// Reduced duration for faster rotation
							easing: tween.easeOut
						});
					}
				}
			}
		}
		// Keep health bars positioned below level indicators
		var healthBarY = CELL_SIZE * 0.7 + 25;
		if (self.towerHealthBarOutline) {
			self.towerHealthBarOutline.y = healthBarY;
			self.towerHealthBarBG.y = healthBarY;
			self.towerHealthBar.y = healthBarY;
		}
		healthBarOutline.y = healthBarBG.y = healthBar.y = -enemyGraphics.height / 2 - 10;
	};
	return self;
});
var GoldIndicator = Container.expand(function (value, x, y) {
	var self = Container.call(this);
	var shadowText = new Text2("+" + value, {
		size: 45,
		fill: 0x000000,
		weight: 800
	});
	shadowText.anchor.set(0.5, 0.5);
	shadowText.x = 2;
	shadowText.y = 2;
	self.addChild(shadowText);
	var goldText = new Text2("+" + value, {
		size: 45,
		fill: 0xFFD700,
		weight: 800
	});
	goldText.anchor.set(0.5, 0.5);
	self.addChild(goldText);
	self.x = x;
	self.y = y;
	self.alpha = 0;
	self.scaleX = 0.5;
	self.scaleY = 0.5;
	tween(self, {
		alpha: 1,
		scaleX: 1.2,
		scaleY: 1.2,
		y: y - 40
	}, {
		duration: 50,
		easing: tween.easeOut,
		onFinish: function onFinish() {
			tween(self, {
				alpha: 0,
				scaleX: 1.5,
				scaleY: 1.5,
				y: y - 80
			}, {
				duration: 600,
				easing: tween.easeIn,
				delay: 800,
				onFinish: function onFinish() {
					self.destroy();
				}
			});
		}
	});
	return self;
});
var Grid = Container.expand(function (gridWidth, gridHeight) {
	var self = Container.call(this);
	self.cells = [];
	self.spawns = [];
	self.goals = [];
	for (var i = 0; i < gridWidth; i++) {
		self.cells[i] = [];
		for (var j = 0; j < gridHeight; j++) {
			self.cells[i][j] = {
				score: 0,
				pathId: 0,
				towersInRange: []
			};
		}
	}
	/*
				Cell Types
				0: Transparent floor
				1: Wall
				2: Spawn
				3: Goal
	*/
	// Create simplified straight road path waypoints with 3-cell width
	var pathWaypoints = [{
		x: 12,
		y: 0
	},
	// Start point (spawn)
	{
		x: 12,
		y: 8
	},
	// First horizontal road
	{
		x: 2,
		y: 8
	},
	// Turn down
	{
		x: 2,
		y: 15
	},
	// Second horizontal road
	{
		x: 22,
		y: 15
	},
	// Turn down
	{
		x: 22,
		y: 22
	},
	// Third horizontal road
	{
		x: 12,
		y: 22
	},
	// Final segment to goal
	{
		x: 12,
		y: gridHeight - 1
	} // End point (goal)
	];
	// Create path cells array to mark which cells are part of the road
	var pathCells = [];
	// Generate path between waypoints
	for (var w = 0; w < pathWaypoints.length - 1; w++) {
		var start = pathWaypoints[w];
		var end = pathWaypoints[w + 1];
		// Create straight line between waypoints
		var steps = Math.max(Math.abs(end.x - start.x), Math.abs(end.y - start.y));
		for (var s = 0; s <= steps; s++) {
			var t = steps === 0 ? 0 : s / steps;
			var pathX = Math.round(start.x + (end.x - start.x) * t);
			var pathY = Math.round(start.y + (end.y - start.y) * t);
			// Add path width - make road 7 cells wide horizontally, 3 cells wide vertically
			for (var offsetX = -3; offsetX <= 3; offsetX++) {
				for (var offsetY = -1; offsetY <= 1; offsetY++) {
					var cellX = pathX + offsetX;
					var cellY = pathY + offsetY;
					if (cellX >= 0 && cellX < gridWidth && cellY >= 0 && cellY < gridHeight) {
						var key = cellX + ',' + cellY;
						if (pathCells.indexOf(key) === -1) {
							pathCells.push(key);
						}
					}
				}
			}
		}
	}
	for (var i = 0; i < gridWidth; i++) {
		for (var j = 0; j < gridHeight; j++) {
			var cell = self.cells[i][j];
			var cellKey = i + ',' + j;
			var isOnPath = pathCells.indexOf(cellKey) !== -1;
			// Default to wall, then carve out path and other areas
			var cellType = 1; // Wall by default
			// Set path cells
			if (isOnPath) {
				cellType = 0; // Path
			}
			// Set spawn points at the start of the path
			if (i >= 11 && i <= 13 && j === 0) {
				cellType = 2; // Spawn
				self.spawns.push(cell);
			}
			// Set goal points at the end of the path
			if (i >= 11 && i <= 13 && j === gridHeight - 1) {
				cellType = 3; // Goal
				self.goals.push(cell);
			}
			// Keep borders as walls
			if (i === 0 || i === gridWidth - 1 || j === 0 || j === gridHeight - 1) {
				if (cellType !== 2 && cellType !== 3) {
					// Don't override spawn/goal
					cellType = 1; // Wall
				}
			}
			cell.type = cellType;
			cell.x = i;
			cell.y = j;
			cell.upLeft = self.cells[i - 1] && self.cells[i - 1][j - 1];
			cell.up = self.cells[i - 1] && self.cells[i - 1][j];
			cell.upRight = self.cells[i - 1] && self.cells[i - 1][j + 1];
			cell.left = self.cells[i][j - 1];
			cell.right = self.cells[i][j + 1];
			cell.downLeft = self.cells[i + 1] && self.cells[i + 1][j - 1];
			cell.down = self.cells[i + 1] && self.cells[i + 1][j];
			cell.downRight = self.cells[i + 1] && self.cells[i + 1][j + 1];
			cell.neighbors = [cell.upLeft, cell.up, cell.upRight, cell.right, cell.downRight, cell.down, cell.downLeft, cell.left];
			cell.targets = [];
			// Render road asset for path cells
			if (isOnPath) {
				var roadVisual = self.attachAsset('road', {
					anchorX: 0.5,
					anchorY: 0.6
				});
				roadVisual.x = i * CELL_SIZE + CELL_SIZE / 2;
				roadVisual.y = j * CELL_SIZE + CELL_SIZE / 2;
			}
			// Debug cells removed for performance
		}
	}
	self.getCell = function (x, y) {
		return self.cells[x] && self.cells[x][y];
	};
	self.pathFind = function () {
		var before = new Date().getTime();
		var toProcess = self.goals.concat([]);
		maxScore = 0;
		pathId += 1;
		for (var a = 0; a < toProcess.length; a++) {
			toProcess[a].pathId = pathId;
		}
		function processNode(node, targetValue, targetNode) {
			if (node && node.type != 1) {
				if (node.pathId < pathId || targetValue < node.score) {
					node.targets = [targetNode];
				} else if (node.pathId == pathId && targetValue == node.score) {
					node.targets.push(targetNode);
				}
				if (node.pathId < pathId || targetValue < node.score) {
					node.score = targetValue;
					if (node.pathId != pathId) {
						toProcess.push(node);
					}
					node.pathId = pathId;
					if (targetValue > maxScore) {
						maxScore = targetValue;
					}
				}
			}
		}
		while (toProcess.length) {
			var nodes = toProcess;
			toProcess = [];
			for (var a = 0; a < nodes.length; a++) {
				var node = nodes[a];
				var targetScore = node.score + 14142;
				if (node.up && node.left && node.up.type != 1 && node.left.type != 1) {
					processNode(node.upLeft, targetScore, node);
				}
				if (node.up && node.right && node.up.type != 1 && node.right.type != 1) {
					processNode(node.upRight, targetScore, node);
				}
				if (node.down && node.right && node.down.type != 1 && node.right.type != 1) {
					processNode(node.downRight, targetScore, node);
				}
				if (node.down && node.left && node.down.type != 1 && node.left.type != 1) {
					processNode(node.downLeft, targetScore, node);
				}
				targetScore = node.score + 10000;
				processNode(node.up, targetScore, node);
				processNode(node.right, targetScore, node);
				processNode(node.down, targetScore, node);
				processNode(node.left, targetScore, node);
			}
		}
		for (var a = 0; a < self.spawns.length; a++) {
			if (self.spawns[a].pathId != pathId) {
				console.warn("Spawn blocked");
				return true;
			}
		}
		for (var a = 0; a < enemies.length; a++) {
			var enemy = enemies[a];
			// Skip enemies that haven't entered the viewable area yet
			if (enemy.currentCellY < 4) {
				continue;
			}
			// Skip flying enemies from path check as they can fly over obstacles
			if (enemy.isFlying) {
				continue;
			}
			var target = self.getCell(enemy.cellX, enemy.cellY);
			if (enemy.currentTarget) {
				if (enemy.currentTarget.pathId != pathId) {
					if (!target || target.pathId != pathId) {
						console.warn("Enemy blocked 1 ");
						return true;
					}
				}
			} else if (!target || target.pathId != pathId) {
				console.warn("Enemy blocked 2");
				return true;
			}
		}
		console.log("Speed", new Date().getTime() - before);
	};
	self.renderDebug = function () {
		// Debug cells removed for performance
	};
	self.updateEnemy = function (enemy) {
		var cell = grid.getCell(enemy.cellX, enemy.cellY);
		if (cell && cell.type == 3) {
			// BOSS Enemy reached the goal - reduce lives by 100 (100% of 100 total lives)
			if (enemy.isBoss) {
				lives = Math.max(0, lives - 100);
			} else {
				// Regular enemy reached the goal - reduce lives by 10 (10% of 100 total lives)
				lives = Math.max(0, lives - 10);
			}
			updateUI();
			if (lives <= 0) {
				LK.showGameOver();
			}
			return true;
		}
		if (enemy.isFlying && enemy.shadow) {
			enemy.shadow.x = enemy.x + 20; // Match enemy x-position + offset
			enemy.shadow.y = enemy.y + 20; // Match enemy y-position + offset
			// Match shadow rotation with enemy rotation
			if (enemy.children[0] && enemy.shadow.children[0]) {
				enemy.shadow.children[0].rotation = enemy.children[0].rotation;
			}
		}
		// Check if the enemy has reached the entry area (y position is at least 5)
		var hasReachedEntryArea = enemy.currentCellY >= 4;
		// If enemy hasn't reached the entry area yet, just move down vertically
		if (!hasReachedEntryArea) {
			// Consistent movement speed for all enemy types during initial phase
			var initialSpeed = enemy.speed;
			if (enemy.type === 'tank') {
				initialSpeed = 0.03; // 3x faster than normal tank speed for smoother entry
			}
			// Move directly downward
			enemy.currentCellY += initialSpeed;
			// Rotate enemy graphic to face downward (PI/2 radians = 90 degrees) + 90 degrees right
			var angle = Math.PI / 2 + Math.PI / 2;
			if (enemy.children[0] && enemy.children[0].targetRotation === undefined) {
				enemy.children[0].targetRotation = angle;
				enemy.children[0].rotation = angle;
			} else if (enemy.children[0]) {
				if (Math.abs(angle - enemy.children[0].targetRotation) > 0.05) {
					tween.stop(enemy.children[0], {
						rotation: true
					});
					// Calculate the shortest angle to rotate
					var currentRotation = enemy.children[0].rotation;
					var angleDiff = angle - currentRotation;
					// Normalize angle difference to -PI to PI range for shortest path
					while (angleDiff > Math.PI) {
						angleDiff -= Math.PI * 2;
					}
					while (angleDiff < -Math.PI) {
						angleDiff += Math.PI * 2;
					}
					// Set target rotation and animate to it
					enemy.children[0].targetRotation = angle;
					tween(enemy.children[0], {
						rotation: currentRotation + angleDiff
					}, {
						duration: 250,
						easing: tween.easeOut
					});
				}
			}
			// Update enemy's position (reduce calculation frequency)
			if (LK.ticks % 2 === 0) {
				enemy.x = grid.x + enemy.currentCellX * CELL_SIZE;
				enemy.y = grid.y + enemy.currentCellY * CELL_SIZE;
			}
			// If enemy has now reached the entry area, update cell coordinates
			if (enemy.currentCellY >= 4) {
				enemy.cellX = Math.round(enemy.currentCellX);
				enemy.cellY = Math.round(enemy.currentCellY);
			}
			return false;
		}
		// After reaching entry area, handle flying enemies differently
		if (enemy.isFlying) {
			// Special movement for boss enemies - straight line down the middle
			if (enemy.isBoss) {
				// Boss enemies move straight down the middle column (x = 12)
				enemy.currentCellX = 12; // Always stay in middle column
				enemy.currentCellY += enemy.speed; // Move straight down
			} else {
				// Regular flying enemy logic
				// Initialize flying enemy direction if not set
				if (enemy.flyingDirection === undefined) {
					// Use the global alternating direction flag
					enemy.flyingDirection = lastDirectionWasRight ? 1 : -1; // 1 for right, -1 for left
					enemy.startX = enemy.currentCellX; // Remember starting X position
					enemy.hasChangedDirection = false; // Track if enemy has changed direction yet
				}
				// Assign flying enemies to one of 3 vertical lanes if not already assigned
				if (enemy.flyingLane === undefined) {
					// Determine lane based on initial direction instead of spawn position
					if (enemy.flyingDirection === -1) {
						// Flying left: start from right side lanes
						enemy.flyingLane = 2; // Right lane - x position 18
						enemy.targetX = 18;
					} else {
						// Flying right: start from left side lanes
						enemy.flyingLane = 0; // Left lane - x position 6
						enemy.targetX = 6;
					}
				}
				// Move straight down in the assigned lane
				enemy.currentCellY += enemy.speed;
				// Implement alternating direction movement for flying enemies
				if (!enemy.hasChangedDirection && enemy.currentCellY > 15) {
					// After reaching middle of map, start moving in assigned direction
					enemy.hasChangedDirection = true;
					// Set new target X based on direction - enemies move to opposite side
					if (enemy.flyingDirection > 0) {
						// Moving right - target right side of map
						enemy.targetX = 20;
					} else {
						// Moving left - target left side of map
						enemy.targetX = 4;
					}
				}
				// Gradually move to the target X position (lane center or direction target)
				var xDiff = enemy.targetX - enemy.currentCellX;
				if (Math.abs(xDiff) > 0.1) {
					enemy.currentCellX += xDiff * 0.05; // Gradual movement to target
				}
			}
			// Rotate enemy graphic to face downward
			var angle = Math.PI; // Face downward (180 degrees)
			if (enemy.children[0] && enemy.children[0].targetRotation === undefined) {
				enemy.children[0].targetRotation = angle;
				enemy.children[0].rotation = angle;
			} else if (enemy.children[0]) {
				if (Math.abs(angle - enemy.children[0].targetRotation) > 0.05) {
					tween.stop(enemy.children[0], {
						rotation: true
					});
					// Calculate the shortest angle to rotate
					var currentRotation = enemy.children[0].rotation;
					var angleDiff = angle - currentRotation;
					// Normalize angle difference to -PI to PI range for shortest path
					while (angleDiff > Math.PI) {
						angleDiff -= Math.PI * 2;
					}
					while (angleDiff < -Math.PI) {
						angleDiff += Math.PI * 2;
					}
					// Set target rotation and animate to it
					enemy.children[0].targetRotation = angle;
					tween(enemy.children[0], {
						rotation: currentRotation + angleDiff
					}, {
						duration: 250,
						easing: tween.easeOut
					});
				}
			}
			// Update the cell position to track where the flying enemy is
			enemy.cellX = Math.round(enemy.currentCellX);
			enemy.cellY = Math.round(enemy.currentCellY);
			// Update visual position
			enemy.x = grid.x + enemy.currentCellX * CELL_SIZE;
			enemy.y = grid.y + enemy.currentCellY * CELL_SIZE;
			// Check if enemy reached the bottom (goal)
			var cell = grid.getCell(enemy.cellX, enemy.cellY);
			if (cell && cell.type == 3) {
				// BOSS Flying enemy reached the goal - reduce lives by 100 (100% of 100 total lives)
				if (enemy.isBoss) {
					lives = Math.max(0, lives - 100);
				} else {
					// Flying enemy reached the goal - reduce lives by 10 (10% of 100 total lives)
					lives = Math.max(0, lives - 10);
				}
				updateUI();
				if (lives <= 0) {
					LK.showGameOver();
				}
				return true;
			}
			// Check if enemy has moved off the bottom of the screen
			if (enemy.currentCellY > 35) {
				// Grid height is 35 (29 + 6)
				// BOSS Enemy went off-screen - reduce lives by 100 (100% of 100 total lives)
				if (enemy.isBoss) {
					lives = Math.max(0, lives - 100);
				} else {
					// Enemy went off-screen - reduce lives by 10 (10% of 100 total lives)
					lives = Math.max(0, lives - 10);
				}
				updateUI();
				if (lives <= 0) {
					LK.showGameOver();
				}
				return true;
			}
			// Update shadow position if this is a flying enemy
			return false;
		}
		// Handle normal pathfinding enemies
		if (enemy.isBoss) {
			// Boss enemies move straight down the middle column regardless of type
			enemy.currentCellX = 12; // Always stay in middle column
			enemy.currentCellY += enemy.speed; // Move straight down
			// Force boss position to center immediately
			enemy.cellX = 12;
			enemy.cellX = Math.round(enemy.currentCellX);
			enemy.cellY = Math.round(enemy.currentCellY);
			// Set rotation to face straight down without animation
			if (enemy.children[0]) {
				enemy.children[0].rotation = Math.PI; // Face downward (180 degrees)
				enemy.children[0].targetRotation = Math.PI;
			}
		} else if (enemy.type === 'fast') {
			// Fast enemies move straight down without pathfinding or turning
			enemy.currentCellY += enemy.speed;
			enemy.cellX = Math.round(enemy.currentCellX);
			enemy.cellY = Math.round(enemy.currentCellY);
			// Set rotation to face straight down without animation
			if (enemy.children[0]) {
				enemy.children[0].rotation = Math.PI; // Face downward (180 degrees)
				enemy.children[0].targetRotation = Math.PI;
			}
		} else if (enemy.type === 'immune' && enemy.waveNumber === 2 && !enemy.hasReachedSecondTurn && enemy.currentCellY >= 15) {
			// Wave 2 immune enemies get speed boost when they reach the second turn (y >= 15)
			enemy.hasReachedSecondTurn = true;
			enemy.speed = 2.4 * 0.02; // Set speed to 2.4 times base speed (0.02)
		} else if (enemy.type === 'tank') {
			// Tank enemies move to upper quarter vertically and stop there, staying at their spawned x-position
			var upperQuarterY = (29 + 6) * 0.25; // Upper quarter of map (around row 8.75)
			var supportPositionY = Math.max(8, upperQuarterY); // Stop at upper quarter
			// Initialize tank target position if not set
			if (enemy.tankTargetX === undefined) {
				enemy.tankTargetX = enemy.currentCellX; // Store spawned x-position
				enemy.tankTargetY = supportPositionY; // Store target support position
				enemy.tankMovementComplete = false;
			}
			// Use smooth interpolation movement instead of tween animations
			if (!enemy.tankMovementComplete && enemy.currentCellY >= 4) {
				// Calculate distance to target
				var dx = enemy.tankTargetX - enemy.currentCellX;
				var dy = enemy.tankTargetY - enemy.currentCellY;
				var distanceToTarget = Math.sqrt(dx * dx + dy * dy);
				// Check if we've reached the target (within 0.1 cells)
				if (distanceToTarget < 0.1) {
					enemy.currentCellX = enemy.tankTargetX;
					enemy.currentCellY = enemy.tankTargetY;
					enemy.tankMovementComplete = true;
				} else {
					// Use smooth interpolation movement
					var speed = 0.04; // Movement speed in cells per frame
					var t = Math.min(1, speed / distanceToTarget);
					enemy.currentCellX = enemy.currentCellX + (enemy.tankTargetX - enemy.currentCellX) * t;
					enemy.currentCellY = enemy.currentCellY + (enemy.tankTargetY - enemy.currentCellY) * t;
				}
				// Tank enemies do not rotate - keep original rotation
			} else {
				// Tank has reached support position - stop moving and face downward to support convoy
				// Lock tank position at target location
				enemy.currentCellX = enemy.tankTargetX; // Stay at spawned x-position
				enemy.currentCellY = enemy.tankTargetY; // Lock at support position
				// Tank enemies do not rotate - keep original rotation
			}
			enemy.cellX = Math.round(enemy.currentCellX);
			enemy.cellY = Math.round(enemy.currentCellY);
		} else {
			// Handle normal pathfinding enemies
			if (!enemy.currentTarget && cell && cell.targets && cell.targets.length > 0) {
				enemy.currentTarget = cell.targets[0];
			}
			if (enemy.currentTarget) {
				// Check if current cell has a better target (closer to goal)
				if (cell && cell.targets && cell.targets.length > 0 && cell.score < enemy.currentTarget.score) {
					enemy.currentTarget = cell.targets[0];
				}
				var ox = enemy.currentTarget.x - enemy.currentCellX;
				var oy = enemy.currentTarget.y - enemy.currentCellY;
				var dist = Math.sqrt(ox * ox + oy * oy);
				if (dist < enemy.speed) {
					// Speed boost logic removed to prevent any tank speed boost effects
					enemy.cellX = Math.round(enemy.currentCellX);
					enemy.cellY = Math.round(enemy.currentCellY);
					enemy.currentTarget = undefined;
					return;
				}
				var angle = Math.atan2(oy, ox) + Math.PI / 2;
				enemy.currentCellX += Math.cos(angle - Math.PI / 2) * enemy.speed;
				enemy.currentCellY += Math.sin(angle - Math.PI / 2) * enemy.speed;
			} else if (cell && cell.targets && cell.targets.length > 0) {
				// If no current target, pick the first available target from current cell
				enemy.currentTarget = cell.targets[0];
			}
		}
		enemy.x = grid.x + enemy.currentCellX * CELL_SIZE;
		enemy.y = grid.y + enemy.currentCellY * CELL_SIZE;
		// Check if ground enemy has moved off the bottom of the screen
		if (enemy.currentCellY > 35) {
			// Grid height is 35 (29 + 6)
			// BOSS Enemy went off-screen - reduce lives by 100 (100% of 100 total lives)
			if (enemy.isBoss) {
				lives = Math.max(0, lives - 100);
			} else {
				// Enemy went off-screen - reduce lives by 10 (10% of 100 total lives)
				lives = Math.max(0, lives - 10);
			}
			updateUI();
			if (lives <= 0) {
				LK.showGameOver();
			}
			return true;
		}
	};
});
var NextWaveButton = Container.expand(function () {
	var self = Container.call(this);
	var buttonBackground = self.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	buttonBackground.width = 300;
	buttonBackground.height = 100;
	buttonBackground.tint = 0x0088FF;
	var buttonText = new Text2("Next Wave", {
		size: 50,
		fill: 0xFFFFFF,
		weight: 800
	});
	buttonText.anchor.set(0.5, 0.5);
	self.addChild(buttonText);
	self.enabled = false;
	self.visible = false;
	self.update = function () {
		if (waveIndicator && waveIndicator.gameStarted && currentWave < totalWaves) {
			self.enabled = true;
			self.visible = true;
			buttonBackground.tint = 0x0088FF;
			self.alpha = 1;
		} else {
			self.enabled = false;
			self.visible = false;
			buttonBackground.tint = 0x888888;
			self.alpha = 0.7;
		}
	};
	self.down = function () {
		if (!self.enabled) {
			return;
		}
		if (waveIndicator && waveIndicator.gameStarted && currentWave < totalWaves) {
			currentWave++; // Increment to the next wave directly
			waveTimer = 0; // Reset wave timer
			waveInProgress = true;
			waveSpawned = false;
			// Get the type of the current wave (which is now the next wave)
			var waveType = waveIndicator.getWaveTypeName(currentWave);
			var enemyCount = waveIndicator.getEnemyCount(currentWave);
			var notification = game.addChild(new Notification("Wave " + currentWave + " (" + waveType + " - " + enemyCount + " enemies) activated!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 150;
		}
	};
	return self;
});
var Notification = Container.expand(function (message) {
	var self = Container.call(this);
	var notificationGraphics = self.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var notificationText = new Text2(message, {
		size: 50,
		fill: 0x000000,
		weight: 800
	});
	notificationText.anchor.set(0.5, 0.5);
	notificationGraphics.width = notificationText.width + 30;
	self.addChild(notificationText);
	self.alpha = 1;
	var fadeOutTime = 120;
	self.update = function () {
		if (fadeOutTime > 0) {
			fadeOutTime--;
			self.alpha = Math.min(fadeOutTime / 120 * 2, 1);
		} else {
			self.destroy();
		}
	};
	return self;
});
var SourceTower = Container.expand(function (towerType) {
	var self = Container.call(this);
	self.towerType = towerType || 'trap';
	// Increase size of base for easier touch
	var baseGraphics = self.attachAsset('Box', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.3,
		scaleY: 1.3
	});
	switch (self.towerType) {
		case 'landmine':
			baseGraphics.tint = 0x9B8B6D; // Lighter tan/brown camouflage
			break;
		case 'sniper':
			baseGraphics.tint = 0x7A9B5F; // Lighter olive green camouflage
			break;
		case 'flamethrower':
			baseGraphics.tint = 0xBBA385; //{aO} // Lighter sandy brown camouflage
			break;
		case 'slow':
			baseGraphics.tint = 0x7F7F5F; //{aR} // Lighter olive drab camouflage
			break;
		case 'poison':
			baseGraphics.tint = 0x969696; //{aU} // Lighter gray camouflage
			break;
		case 'tank':
			baseGraphics.tint = 0x006400; // Dark green for tank
			break;
		default:
			baseGraphics.tint = 0x8C8C77;
		//{aX} // Lighter neutral camouflage green-gray
	}
	var towerCost = getTowerCost(self.towerType);
	// Add shadow for tower type label
	var displayTextShadow = self.towerType === 'flamethrower' ? 'Flame' : self.towerType === 'trap' ? 'Shooter' : self.towerType === 'slow' ? 'Missiles' : self.towerType === 'tank' ? 'Tank' : self.towerType.charAt(0).toUpperCase() + self.towerType.slice(1);
	var typeLabelShadow = new Text2(displayTextShadow, {
		size: 50,
		fill: 0x000000,
		weight: 800
	});
	typeLabelShadow.anchor.set(0.5, 0.5);
	typeLabelShadow.x = 4;
	typeLabelShadow.y = -20 + 4;
	self.addChild(typeLabelShadow);
	// Add tower type label
	var displayText = self.towerType === 'flamethrower' ? 'Flame' : self.towerType === 'trap' ? 'Shooter' : self.towerType === 'slow' ? 'Missiles' : self.towerType === 'tank' ? 'Tank' : self.towerType.charAt(0).toUpperCase() + self.towerType.slice(1);
	var typeLabel = new Text2(displayText, {
		size: 50,
		fill: 0xFFFFFF,
		weight: 800
	});
	typeLabel.anchor.set(0.5, 0.5);
	typeLabel.y = -20; // Position above center of tower
	self.addChild(typeLabel);
	// Add cost shadow
	var costLabelShadow = new Text2(towerCost, {
		size: 50,
		fill: 0x000000,
		weight: 800
	});
	costLabelShadow.anchor.set(0.5, 0.5);
	costLabelShadow.x = 4;
	costLabelShadow.y = 24 + 12;
	self.addChild(costLabelShadow);
	// Add cost label
	var costLabel = new Text2(towerCost, {
		size: 50,
		fill: 0xFFD700,
		weight: 800
	});
	costLabel.anchor.set(0.5, 0.5);
	costLabel.y = 20 + 12;
	self.addChild(costLabel);
	self.update = function () {
		// Check if player can afford this tower
		var canAfford = gold >= getTowerCost(self.towerType);
		// Set opacity based on affordability
		self.alpha = canAfford ? 1 : 0.5;
	};
	return self;
});
var Tower = Container.expand(function (id) {
	var self = Container.call(this);
	self.id = id || 'trap';
	self.level = 1;
	self.maxLevel = 6;
	self.gridX = 0;
	self.gridY = 0;
	self.range = 3 * CELL_SIZE;
	self.isPlaced = false; // Track if tower has been placed on grid
	// Standardized method to get the current range of the tower
	self.getRange = function () {
		// Always calculate range based on tower type and level
		switch (self.id) {
			case 'sniper':
				// Sniper: massive range to cover entire map from any position
				if (self.level === self.maxLevel) {
					return 75 * CELL_SIZE; // Extreme range for max level to cover entire map (1.5x increase)
				}
				return (22.5 + (self.level - 1) * 7.5) * CELL_SIZE;
			// Increased base and scaling (1.5x increase)
			case 'flamethrower':
				// Flamethrower: base 4.5, +0.5 per level for cone range (increased aiming distance)
				return (4.5 + (self.level - 1) * 0.5) * CELL_SIZE;
			case 'landmine':
				// Landmine: base 2.5, +0.5 per level
				return (2.5 + (self.level - 1) * 0.5) * CELL_SIZE;
			case 'slow':
				// Slow: base 8.75, +1.25 per level (2.5x increase)
				return (8.75 + (self.level - 1) * 1.25) * CELL_SIZE;
			case 'poison':
				// Poison: base 3.2, +0.5 per level
				return (3.2 + (self.level - 1) * 0.5) * CELL_SIZE;
			case 'tank':
				// Tank: base 14.0, +2.8 per level (3.5x increase)
				return (14.0 + (self.level - 1) * 2.8) * CELL_SIZE;
			default:
				// Trap: base 6, +1.0 per level (double range)
				return (6 + (self.level - 1) * 1.0) * CELL_SIZE;
		}
	};
	self.cellsInRange = [];
	self.fireRate = 60;
	self.bulletSpeed = 5;
	self.damage = 10;
	self.lastFired = 0;
	self.targetEnemy = null;
	// Continuous shooting variables for flamethrower
	self.isContinuousFiring = false;
	self.continuousFireTimer = 0;
	self.continuousFireDuration = 300; // 5 seconds at 60 FPS
	self.continuousReloadTimer = 0;
	self.continuousReloadDuration = 180; // 3 seconds at 60 FPS
	switch (self.id) {
		case 'landmine':
			self.fireRate = 30;
			self.damage = 5;
			self.range = 2.5 * CELL_SIZE;
			self.bulletSpeed = 7;
			break;
		case 'sniper':
			self.fireRate = 90;
			self.damage = 25;
			self.range = 5 * CELL_SIZE;
			self.bulletSpeed = 25;
			break;
		case 'flamethrower':
			self.fireRate = 2.5; // Very fast fire rate during continuous shooting (quarter of original delay)
			self.damage = 8; // Lower per-hit damage but continuous
			self.range = 2.5 * CELL_SIZE;
			self.bulletSpeed = 6;
			break;
		case 'slow':
			self.fireRate = 30;
			self.damage = 15; // Increased from 8 to 15 for stronger missiles
			self.range = 3.5 * CELL_SIZE;
			self.bulletSpeed = 5;
			break;
		case 'poison':
			self.fireRate = 70;
			self.damage = 12;
			self.range = 3.2 * CELL_SIZE;
			self.bulletSpeed = 5;
			break;
		case 'tank':
			self.fireRate = 90;
			self.damage = 50; // Increased base damage for tank
			self.range = 4.0 * CELL_SIZE;
			self.bulletSpeed = 4;
			break;
	}
	var assetToUse = self.id === 'landmine' ? 'landmine' : self.id === 'sniper' ? 'Sniper' : self.id === 'flamethrower' ? 'Flamethrower' : self.id === 'slow' ? 'Rocket' : self.id === 'trap' ? 'Shooter' : self.id === 'tank' ? 'Tank' : 'tower';
	var baseGraphics = self.attachAsset(assetToUse, {
		anchorX: 0.5,
		anchorY: self.id === 'sniper' ? 0.0 : 0.5
	});
	// Rotate sniper tower left by 40 degrees
	if (self.id === 'sniper') {
		baseGraphics.rotation = -40 * Math.PI / 180; // Convert 40 degrees to radians and make it negative for left rotation
	}
	// Flame effects removed for performance
	switch (self.id) {
		case 'landmine':
			// Remove tint to show natural landmine asset
			break;
		case 'sniper':
			// Remove tint to show natural sniper asset
			break;
		case 'flamethrower':
			// Remove tint to show natural flamethrower asset
			break;
		case 'slow':
			// Remove tint to show natural rocket asset
			break;
		case 'poison':
			baseGraphics.tint = 0x00FFAA;
			break;
		case 'tank':
			// Remove tint to show natural tank asset
			break;
		case 'trap':
			baseGraphics.tint = 0x555555; // Dark gray for machine gun
			break;
		default:
			baseGraphics.tint = 0xAAAAAA;
	}
	// Add health bar for towers that need them (excluding landmine)
	self.towerHealthBarOutline = null;
	self.towerHealthBarBG = null;
	self.towerHealthBar = null;
	if (self.id === 'flamethrower' || self.id === 'trap' || self.id === 'sniper' || self.id === 'slow' || self.id === 'tank') {
		// Create health bar outline
		self.towerHealthBarOutline = self.attachAsset('towerHealthBarOutline', {
			anchorX: 0,
			anchorY: 0.5
		});
		// Create health bar background (red)
		self.towerHealthBarBG = self.attachAsset('towerHealthBar', {
			anchorX: 0,
			anchorY: 0.5
		});
		self.towerHealthBarBG.tint = 0xff0000;
		// Create health bar foreground (green)
		self.towerHealthBar = self.attachAsset('towerHealthBar', {
			anchorX: 0,
			anchorY: 0.5
		});
		self.towerHealthBar.tint = 0x00ff00;
		// Position health bars below the level indicators to avoid overlap
		var healthBarY = CELL_SIZE * 0.7 + 25; // Position below level indicators with some spacing
		self.towerHealthBarOutline.y = healthBarY;
		self.towerHealthBarBG.y = healthBarY;
		self.towerHealthBar.y = healthBarY;
		// Center health bars horizontally
		self.towerHealthBarOutline.x = -self.towerHealthBarOutline.width / 2;
		self.towerHealthBarBG.x = -self.towerHealthBarBG.width / 2;
		self.towerHealthBar.x = -self.towerHealthBar.width / 2;
	}
	var levelIndicators = [];
	var maxDots = self.maxLevel;
	var dotSpacing = baseGraphics.width / (maxDots + 1);
	var dotSize = CELL_SIZE / 6;
	for (var i = 0; i < maxDots; i++) {
		var dot = new Container();
		var outlineCircle = dot.attachAsset('towerLevelIndicator', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		outlineCircle.width = dotSize + 4;
		outlineCircle.height = dotSize + 4;
		outlineCircle.tint = 0x000000;
		var towerLevelIndicator = dot.attachAsset('towerLevelIndicator', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		towerLevelIndicator.width = dotSize;
		towerLevelIndicator.height = dotSize;
		towerLevelIndicator.tint = 0xCCCCCC;
		dot.x = -CELL_SIZE + dotSpacing * (i + 1);
		dot.y = CELL_SIZE * 0.7;
		self.addChild(dot);
		levelIndicators.push(dot);
	}
	var gunContainer = new Container();
	self.addChild(gunContainer);
	self.updateLevelIndicators = function () {
		for (var i = 0; i < maxDots; i++) {
			var dot = levelIndicators[i];
			var towerLevelIndicator = dot.children[1];
			if (i < self.level) {
				towerLevelIndicator.tint = 0xFFFFFF;
			} else {
				switch (self.id) {
					case 'landmine':
						towerLevelIndicator.tint = 0x00AAFF;
						break;
					case 'sniper':
						towerLevelIndicator.tint = 0xFF5500;
						break;
					case 'flamethrower':
						towerLevelIndicator.tint = 0xFF4500;
						break;
					case 'slow':
						towerLevelIndicator.tint = 0x9900FF;
						break;
					case 'poison':
						towerLevelIndicator.tint = 0x00FFAA;
						break;
					default:
						towerLevelIndicator.tint = 0xAAAAAA;
				}
			}
		}
	};
	self.updateLevelIndicators();
	self.refreshCellsInRange = function () {
		for (var i = 0; i < self.cellsInRange.length; i++) {
			var cell = self.cellsInRange[i];
			var towerIndex = cell.towersInRange.indexOf(self);
			if (towerIndex !== -1) {
				cell.towersInRange.splice(towerIndex, 1);
			}
		}
		self.cellsInRange = [];
		var rangeRadius = self.getRange() / CELL_SIZE;
		var centerX = self.gridX + 1;
		var centerY = self.gridY + 1;
		var minI = Math.floor(centerX - rangeRadius - 0.5);
		var maxI = Math.ceil(centerX + rangeRadius + 0.5);
		var minJ = Math.floor(centerY - rangeRadius - 0.5);
		var maxJ = Math.ceil(centerY + rangeRadius + 0.5);
		for (var i = minI; i <= maxI; i++) {
			for (var j = minJ; j <= maxJ; j++) {
				var closestX = Math.max(i, Math.min(centerX, i + 1));
				var closestY = Math.max(j, Math.min(centerY, j + 1));
				var deltaX = closestX - centerX;
				var deltaY = closestY - centerY;
				var distanceSquared = deltaX * deltaX + deltaY * deltaY;
				if (distanceSquared <= rangeRadius * rangeRadius) {
					var cell = grid.getCell(i, j);
					if (cell) {
						self.cellsInRange.push(cell);
						cell.towersInRange.push(self);
					}
				}
			}
		}
		// Only render debug when tower is selected to improve performance
		if (selectedTower === self) {
			grid.renderDebug();
		}
	};
	self.getTotalValue = function () {
		var baseTowerCost = getTowerCost(self.id);
		var totalInvestment = baseTowerCost;
		var baseUpgradeCost = baseTowerCost; // Upgrade cost now scales with base tower cost
		for (var i = 1; i < self.level; i++) {
			totalInvestment += Math.floor(baseUpgradeCost * Math.pow(2, i - 1));
		}
		return totalInvestment;
	};
	self.upgrade = function () {
		if (self.level < self.maxLevel) {
			// Exponential upgrade cost: base cost * (2 ^ (level-1)), scaled by tower base cost
			var baseUpgradeCost = getTowerCost(self.id);
			var upgradeCost;
			// Make last upgrade level extra expensive
			if (self.level === self.maxLevel - 1) {
				upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.level - 1) * 3.5 / 2); // Half the cost for final upgrade
			} else {
				upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.level - 1));
			}
			if (gold >= upgradeCost) {
				setGold(gold - upgradeCost);
				self.level++;
				// No need to update self.range here; getRange() is now the source of truth
				// Apply tower-specific upgrades based on type
				if (self.id === 'landmine') {
					if (self.level === self.maxLevel) {
						// Extra powerful last upgrade (double the effect)
						self.fireRate = Math.max(4, 30 - self.level * 9); // double the effect
						self.damage = 5 + self.level * 10; // double the effect
						self.bulletSpeed = 7 + self.level * 2.4; // double the effect
					} else {
						self.fireRate = Math.max(15, 30 - self.level * 3); // Fast tower gets faster with upgrades
						self.damage = 5 + self.level * 3;
						self.bulletSpeed = 7 + self.level * 0.7;
					}
				} else {
					// Special scaling for missiles towers
					if (self.id === 'slow') {
						if (self.level === self.maxLevel) {
							// Extra powerful last upgrade for missiles (triple the effect)
							self.fireRate = Math.max(3, 30 - self.level * 15); // Much faster fire rate
							self.damage = 15 + self.level * 30; // Much higher damage scaling
							self.bulletSpeed = 5 + self.level * 3; // Faster missiles
						} else {
							self.fireRate = Math.max(10, 30 - self.level * 5); // Faster than base scaling
							self.damage = 15 + self.level * 10; // Higher damage per level
							self.bulletSpeed = 5 + self.level * 1;
						}
					} else {
						if (self.level === self.maxLevel) {
							// Extra powerful last upgrade for all other towers (double the effect)
							self.fireRate = Math.max(5, 60 - self.level * 24); // double the effect
							self.damage = 10 + self.level * 20; // double the effect
							self.bulletSpeed = 5 + self.level * 2.4; // double the effect
						} else {
							self.fireRate = Math.max(20, 60 - self.level * 8);
							self.damage = 10 + self.level * 5;
							self.bulletSpeed = 5 + self.level * 0.5;
						}
					}
				}
				self.refreshCellsInRange();
				self.updateLevelIndicators();
				if (self.level > 1) {
					var levelDot = levelIndicators[self.level - 1].children[1];
					tween(levelDot, {
						scaleX: 1.5,
						scaleY: 1.5
					}, {
						duration: 300,
						easing: tween.elasticOut,
						onFinish: function onFinish() {
							tween(levelDot, {
								scaleX: 1,
								scaleY: 1
							}, {
								duration: 200,
								easing: tween.easeOut
							});
						}
					});
				}
				return true;
			} else {
				var notification = game.addChild(new Notification("Not enough gold to upgrade!"));
				notification.x = 2048 / 2;
				notification.y = grid.height - 50;
				return false;
			}
		}
		return false;
	};
	self.findTarget = function () {
		var closestEnemy = null;
		var closestScore = Infinity;
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			var dx = enemy.x - self.x;
			var dy = enemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Check if enemy is in range
			if (distance <= self.getRange()) {
				// Handle flying enemies differently - they can be targeted regardless of path
				if (enemy.isFlying) {
					// For flying enemies, prioritize by distance to the goal
					if (enemy.flyingTarget) {
						var goalX = enemy.flyingTarget.x;
						var goalY = enemy.flyingTarget.y;
						var distToGoal = Math.sqrt((goalX - enemy.cellX) * (goalX - enemy.cellX) + (goalY - enemy.cellY) * (goalY - enemy.cellY));
						// Use distance to goal as score
						if (distToGoal < closestScore) {
							closestScore = distToGoal;
							closestEnemy = enemy;
						}
					} else {
						// If no flying target yet (shouldn't happen), prioritize by distance to tower
						if (distance < closestScore) {
							closestScore = distance;
							closestEnemy = enemy;
						}
					}
				} else {
					// For ground enemies, landmine towers target any ground enemy in range
					if (self.id === 'landmine') {
						// Landmine targets any ground enemy by distance
						if (distance < closestScore) {
							closestScore = distance;
							closestEnemy = enemy;
						}
					} else {
						// For sniper and other towers, use the original path-based targeting
						// Get the cell for this enemy
						var cell = grid.getCell(enemy.cellX, enemy.cellY);
						// Allow targeting of tank enemies even if they're not on the main path (they're in support positions)
						if (enemy.type === 'tank' || cell && cell.pathId === pathId) {
							// For tank enemies, use distance-based targeting since they may not be on the main path
							var targetScore = enemy.type === 'tank' ? distance : cell.score;
							// Use the cell's score (distance to exit) for prioritization
							// Lower score means closer to exit
							if (targetScore < closestScore) {
								closestScore = targetScore;
								closestEnemy = enemy;
							}
						}
					}
				}
			}
		}
		if (!closestEnemy) {
			self.targetEnemy = null;
		}
		return closestEnemy;
	};
	self.update = function () {
		// Only find targets every 3 frames to reduce performance impact
		if (LK.ticks % 3 === 0) {
			self.targetEnemy = self.findTarget();
		}
		// Clean up targeted enemies list for rocket launcher towers
		if (self.id === 'slow' && self.targetedEnemies) {
			// Remove enemies that are dead or out of range
			for (var i = self.targetedEnemies.length - 1; i >= 0; i--) {
				var targetedEnemy = self.targetedEnemies[i];
				if (!targetedEnemy.parent || targetedEnemy.health <= 0 || !self.isInRange(targetedEnemy)) {
					self.targetedEnemies.splice(i, 1);
				}
			}
		}
		// Flame animation removed for flamethrower towers
		// Special handling for landmine towers - explode on contact
		if (self.id === 'landmine' && self.targetEnemy) {
			var dx = self.targetEnemy.x - self.x;
			var dy = self.targetEnemy.y - self.y;
			var distance = Math.sqrt(dx * dx + dy * dy);
			// Check if enemy is close enough to trigger explosion (within 50 pixels) and is ground-based
			if (distance <= 50 && !self.targetEnemy.isFlying) {
				// Create landmine explosion effect with enhanced animation
				var landmineExplosion = new EffectIndicator(self.x, self.y, 'splash');
				landmineExplosion.children[0].tint = 0xFF4500; // Orange explosion color
				landmineExplosion.children[0].width = landmineExplosion.children[0].height = CELL_SIZE * 2.5;
				landmineExplosion.scaleX = 0.3;
				landmineExplosion.scaleY = 0.3;
				landmineExplosion.alpha = 1;
				game.addChild(landmineExplosion);
				// Multi-stage landmine explosion animation
				tween(landmineExplosion, {
					scaleX: 1.8,
					scaleY: 1.8,
					alpha: 0.9
				}, {
					duration: 150,
					easing: tween.elasticOut,
					onFinish: function onFinish() {
						tween(landmineExplosion, {
							scaleX: 2.5,
							scaleY: 2.5,
							alpha: 0
						}, {
							duration: 300,
							easing: tween.easeIn,
							onFinish: function onFinish() {
								landmineExplosion.destroy();
							}
						});
					}
				});
				// Create enemy explosion effect with enhanced animation
				var enemyExplosion = new EffectIndicator(self.targetEnemy.x, self.targetEnemy.y, 'splash');
				enemyExplosion.children[0].tint = 0xFF0000; // Red explosion color
				enemyExplosion.children[0].width = enemyExplosion.children[0].height = CELL_SIZE * 2;
				enemyExplosion.scaleX = 0.2;
				enemyExplosion.scaleY = 0.2;
				enemyExplosion.alpha = 1;
				game.addChild(enemyExplosion);
				// Multi-stage enemy explosion animation
				tween(enemyExplosion, {
					scaleX: 1.5,
					scaleY: 1.5,
					alpha: 0.8
				}, {
					duration: 120,
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						tween(enemyExplosion, {
							scaleX: 2.2,
							scaleY: 2.2,
							alpha: 0
						}, {
							duration: 250,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								enemyExplosion.destroy();
							}
						});
					}
				});
				// Create additional shockwave effect for landmine
				var shockwave = new EffectIndicator(self.x, self.y, 'splash');
				shockwave.children[0].tint = 0xFFFFFF;
				shockwave.children[0].alpha = 0.3;
				shockwave.children[0].width = shockwave.children[0].height = CELL_SIZE * 0.5;
				shockwave.alpha = 0.8;
				game.addChild(shockwave);
				// Animate shockwave expanding rapidly
				tween(shockwave, {
					scaleX: 4,
					scaleY: 4,
					alpha: 0
				}, {
					duration: 400,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						shockwave.destroy();
					}
				});
				// Mark enemy for destruction
				self.targetEnemy.health = 0;
				// Mark landmine tower for destruction
				self.shouldDestroy = true;
				return;
			}
		}
		if (self.targetEnemy && self.id !== 'landmine') {
			var dx = self.targetEnemy.x - self.x;
			var dy = self.targetEnemy.y - self.y;
			var angle = Math.atan2(dy, dx);
			// Special rotation handling for sniper towers
			if (self.id === 'sniper') {
				// Use the main tower graphics (baseGraphics) for sniper rotation
				var sniperGraphics = self.children[0]; // The sniper asset
				if (sniperGraphics.targetRotation === undefined) {
					sniperGraphics.targetRotation = angle;
					sniperGraphics.rotation = angle;
				} else {
					if (Math.abs(angle - sniperGraphics.targetRotation) > 0.1) {
						// Stop any ongoing rotation tweens
						tween.stop(sniperGraphics, {
							rotation: true
						});
						// Calculate the shortest angle to rotate
						var currentRotation = sniperGraphics.rotation;
						var angleDiff = angle - currentRotation;
						// Normalize angle difference to -PI to PI range for shortest path
						while (angleDiff > Math.PI) {
							angleDiff -= Math.PI * 2;
						}
						while (angleDiff < -Math.PI) {
							angleDiff += Math.PI * 2;
						}
						sniperGraphics.targetRotation = angle;
						tween(sniperGraphics, {
							rotation: currentRotation + angleDiff
						}, {
							duration: 200,
							easing: tween.easeOut
						});
					}
				}
			} else {
				gunContainer.rotation = angle;
			}
			// Special continuous firing logic for flamethrower
			if (self.id === 'flamethrower') {
				// Handle continuous reload timer
				if (self.continuousReloadTimer > 0) {
					self.continuousReloadTimer--;
				} else if (!self.isContinuousFiring && self.targetEnemy) {
					// Start continuous firing
					self.isContinuousFiring = true;
					self.continuousFireTimer = self.continuousFireDuration;
				} else if (self.isContinuousFiring) {
					// Continue firing during the continuous period
					if (self.continuousFireTimer > 0) {
						self.continuousFireTimer--;
						// Fire at the fast rate during continuous shooting
						if (LK.ticks - self.lastFired >= self.fireRate) {
							self.fire();
							self.lastFired = LK.ticks;
						}
					} else {
						// End continuous firing, start reload
						self.isContinuousFiring = false;
						self.continuousReloadTimer = self.continuousReloadDuration;
					}
				}
			} else {
				// Normal firing logic for other tower types
				if (LK.ticks - self.lastFired >= self.fireRate) {
					self.fire();
					self.lastFired = LK.ticks;
				}
			}
		}
	};
	self.down = function (x, y, obj) {
		var existingMenus = game.children.filter(function (child) {
			return child instanceof UpgradeMenu;
		});
		var hasOwnMenu = false;
		var rangeCircle = null;
		for (var i = 0; i < game.children.length; i++) {
			if (game.children[i].isTowerRange && game.children[i].tower === self) {
				rangeCircle = game.children[i];
				break;
			}
		}
		for (var i = 0; i < existingMenus.length; i++) {
			if (existingMenus[i].tower === self) {
				hasOwnMenu = true;
				break;
			}
		}
		if (hasOwnMenu) {
			for (var i = 0; i < existingMenus.length; i++) {
				if (existingMenus[i].tower === self) {
					hideUpgradeMenu(existingMenus[i]);
				}
			}
			if (rangeCircle) {
				game.removeChild(rangeCircle);
			}
			selectedTower = null;
			grid.renderDebug();
			return;
		}
		for (var i = 0; i < existingMenus.length; i++) {
			existingMenus[i].destroy();
		}
		for (var i = game.children.length - 1; i >= 0; i--) {
			if (game.children[i].isTowerRange) {
				game.removeChild(game.children[i]);
			}
		}
		selectedTower = self;
		var rangeIndicator = new Container();
		rangeIndicator.isTowerRange = true;
		rangeIndicator.tower = self;
		game.addChild(rangeIndicator);
		rangeIndicator.x = self.x;
		rangeIndicator.y = self.y;
		var rangeGraphics = rangeIndicator.attachAsset('rangeCircle', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		rangeGraphics.width = rangeGraphics.height = self.getRange() * 2;
		rangeGraphics.alpha = 0.3;
		var upgradeMenu = new UpgradeMenu(self);
		game.addChild(upgradeMenu);
		upgradeMenu.x = 2048 / 2;
		tween(upgradeMenu, {
			y: 2732 - 225
		}, {
			duration: 200,
			easing: tween.backOut
		});
		grid.renderDebug();
	};
	self.isInRange = function (enemy) {
		if (!enemy) {
			return false;
		}
		var dx = enemy.x - self.x;
		var dy = enemy.y - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		return distance <= self.getRange();
	};
	// Initialize tower health based on tower type
	if (self.id === 'flamethrower' || self.id === 'trap' || self.id === 'sniper' || self.id === 'slow' || self.id === 'tank') {
		// Set health values based on tower type
		if (self.id === 'slow') {
			self.towerHealth = 300; // 3x base health for missiles
			self.maxTowerHealth = 300;
		} else if (self.id === 'tank') {
			self.towerHealth = 500; // 5x base health for tank towers - very strong
			self.maxTowerHealth = 500;
		} else if (self.id === 'sniper') {
			self.towerHealth = 150; // Medium health for sniper
			self.maxTowerHealth = 150;
		} else if (self.id === 'flamethrower') {
			self.towerHealth = 120; // Medium health for flamethrower
			self.maxTowerHealth = 120;
		} else {
			self.towerHealth = 100; // Base tower health for trap/shooter
			self.maxTowerHealth = 100;
		}
	}
	// Method to handle damage from enemy bullets
	self.takeDamage = function (damage) {
		// Special handling for sniper towers - track hits instead of health
		if (self.id === 'sniper') {
			// Initialize hit counter if not set
			if (self.hitCount === undefined) {
				self.hitCount = 0;
			}
			self.hitCount++;
			// Create hit indicator effect
			var hitEffect = new EffectIndicator(self.x, self.y, 'sniper');
			hitEffect.children[0].tint = 0xFF0000; // Red hit indicator
			hitEffect.children[0].width = hitEffect.children[0].height = CELL_SIZE;
			game.addChild(hitEffect);
			// Update health bar
			if (self.towerHealthBar) {
				var healthPercentage = Math.max(0, (5 - self.hitCount) / 5);
				self.towerHealthBar.width = 60 * healthPercentage;
			}
			// Destroy sniper after 5 hits
			if (self.hitCount >= 5) {
				// Mark sniper for destruction
				self.shouldDestroy = true;
				// Create destruction effect
				var destructionEffect = new EffectIndicator(self.x, self.y, 'splash');
				destructionEffect.children[0].tint = 0xFF4500; // Orange destruction color
				destructionEffect.children[0].width = destructionEffect.children[0].height = CELL_SIZE * 2;
				game.addChild(destructionEffect);
			}
		} else {
			// Initialize tower health if not set for non-sniper towers
			if (self.towerHealth === undefined) {
				// Missiles towers have much higher health to make them stronger
				if (self.id === 'slow') {
					self.towerHealth = 300; // 3x base health for missiles
					self.maxTowerHealth = 300;
				} else if (self.id === 'tank') {
					self.towerHealth = 500; // 5x base health for tank towers - very strong
					self.maxTowerHealth = 500;
				} else {
					self.towerHealth = 100; // Base tower health
					self.maxTowerHealth = 100;
				}
			}
			self.towerHealth -= damage;
			// Update health bar
			if (self.towerHealthBar && self.maxTowerHealth > 0) {
				var healthPercentage = Math.max(0, self.towerHealth / self.maxTowerHealth);
				self.towerHealthBar.width = 60 * healthPercentage;
			}
			if (self.towerHealth <= 0) {
				self.towerHealth = 0;
				// Mark tower for destruction
				self.shouldDestroy = true;
				// Create destruction effect
				var destructionEffect = new EffectIndicator(self.x, self.y, 'splash');
				destructionEffect.children[0].tint = 0xFF4500; // Orange destruction color
				destructionEffect.children[0].width = destructionEffect.children[0].height = CELL_SIZE * 2;
				game.addChild(destructionEffect);
			}
		}
	};
	self.fire = function () {
		// Landmine towers cannot shoot normally
		if (self.id === 'landmine') {
			return;
		}
		// Machine gun shooting function
		if (self.id === 'trap') {
			if (self.targetEnemy) {
				// Fire multiple bullets in rapid succession for higher ammunition density
				var bulletsToFire = 3; // Fire 3 bullets per shot for higher density
				for (var bulletIndex = 0; bulletIndex < bulletsToFire; bulletIndex++) {
					var bulletX = self.x + Math.cos(gunContainer.rotation) * 40;
					var bulletY = self.y + Math.sin(gunContainer.rotation) * 40;
					var bullet = new Bullet(bulletX, bulletY, self.targetEnemy, self.damage, self.bulletSpeed);
					// Set bullet type for machine gun
					bullet.type = 'trap';
					// Machine gun bullets are smaller and faster
					bullet.children[0].tint = 0x555555; // Dark gray for machine gun bullets
					bullet.children[0].width = 25;
					bullet.children[0].height = 25;
					// Add slight delay between bullets for visual effect
					if (bulletIndex > 0) {
						bullet.x += (Math.random() - 0.5) * 10; // Small random offset
						bullet.y += (Math.random() - 0.5) * 10;
					}
					game.addChild(bullet);
					bullets.push(bullet);
					self.targetEnemy.bulletsTargetingThis.push(bullet);
				}
				// Machine gun recoil effect
				tween.stop(gunContainer, {
					x: true,
					y: true,
					scaleX: true,
					scaleY: true
				});
				if (gunContainer._restX === undefined) {
					gunContainer._restX = 0;
				}
				if (gunContainer._restY === undefined) {
					gunContainer._restY = 0;
				}
				if (gunContainer._restScaleX === undefined) {
					gunContainer._restScaleX = 1;
				}
				if (gunContainer._restScaleY === undefined) {
					gunContainer._restScaleY = 1;
				}
				gunContainer.x = gunContainer._restX;
				gunContainer.y = gunContainer._restY;
				gunContainer.scaleX = gunContainer._restScaleX;
				gunContainer.scaleY = gunContainer._restScaleY;
				var recoilDistance = 6;
				var recoilX = -Math.cos(gunContainer.rotation) * recoilDistance;
				var recoilY = -Math.sin(gunContainer.rotation) * recoilDistance;
				tween(gunContainer, {
					x: gunContainer._restX + recoilX,
					y: gunContainer._restY + recoilY
				}, {
					duration: 40,
					easing: tween.cubicOut,
					onFinish: function onFinish() {
						tween(gunContainer, {
							x: gunContainer._restX,
							y: gunContainer._restY
						}, {
							duration: 60,
							easing: tween.cubicIn
						});
					}
				});
			}
			return;
		}
		if (self.targetEnemy) {
			var potentialDamage = 0;
			for (var i = 0; i < self.targetEnemy.bulletsTargetingThis.length; i++) {
				potentialDamage += self.targetEnemy.bulletsTargetingThis[i].damage;
			}
			// For rocket launcher (slow) towers, check if we've already fired at this target
			if (self.id === 'slow') {
				// Initialize targeted enemies array if not exists
				if (!self.targetedEnemies) {
					self.targetedEnemies = [];
				}
				// Check if we've already targeted this enemy
				var alreadyTargeted = false;
				for (var i = 0; i < self.targetedEnemies.length; i++) {
					if (self.targetedEnemies[i] === self.targetEnemy) {
						alreadyTargeted = true;
						break;
					}
				}
				// If already targeted, don't fire again
				if (alreadyTargeted) {
					return;
				}
				// Add this enemy to our targeted list
				self.targetedEnemies.push(self.targetEnemy);
			}
			// Always fire if we have a target enemy - removed health vs potential damage check that was blocking boss attacks
			if (self.targetEnemy) {
				// Special handling for flamethrower - create continuous flame spray
				if (self.id === 'flamethrower') {
					// Create multiple flame particles for continuous spray effect
					var flamesToCreate = 3; // Create multiple flames for denser spray
					for (var flameIndex = 0; flameIndex < flamesToCreate; flameIndex++) {
						var flameParticle = new Container();
						var flameGraphics = flameParticle.attachAsset('rangeCircle', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						flameGraphics.width = 25 + Math.random() * 15;
						flameGraphics.height = 35 + Math.random() * 20;
						flameGraphics.tint = Math.random() > 0.5 ? 0xFF4500 : 0xFF6600;
						flameGraphics.alpha = 0.7 + Math.random() * 0.3;
						// Position flame particle at tower with slight spread
						var spreadAngle = (Math.random() - 0.5) * 0.4; // 20 degree spread
						var startAngle = gunContainer.rotation + spreadAngle;
						var startDistance = 30 + Math.random() * 10;
						flameParticle.x = self.x + Math.cos(startAngle) * startDistance;
						flameParticle.y = self.y + Math.sin(startAngle) * startDistance;
						// Calculate target position with spread
						var targetDistance = self.getRange() * (0.6 + Math.random() * 0.4);
						var targetX = self.x + Math.cos(startAngle) * targetDistance;
						var targetY = self.y + Math.sin(startAngle) * targetDistance;
						// Store damage info for area effect
						flameParticle.damage = self.damage;
						flameParticle.sourceTowerLevel = self.level;
						game.addChild(flameParticle);
						// Animate flame particle moving toward target area
						tween(flameParticle, {
							x: targetX,
							y: targetY,
							scaleX: 1.5,
							scaleY: 1.5
						}, {
							duration: 400 + Math.random() * 200,
							easing: tween.easeOut,
							onFinish: function onFinish() {
								// Apply area damage when flame reaches target area
								var coneRange = CELL_SIZE * 1.2;
								for (var i = 0; i < enemies.length; i++) {
									var enemy = enemies[i];
									var dx = enemy.x - flameParticle.x;
									var dy = enemy.y - flameParticle.y;
									var distance = Math.sqrt(dx * dx + dy * dy);
									if (distance <= coneRange) {
										// Apply flame damage
										enemy.health -= flameParticle.damage * 0.8;
										if (enemy.health <= 0) {
											enemy.health = 0;
										} else {
											enemy.healthBar.width = enemy.health / enemy.maxHealth * 70;
										}
										// Apply burning effect
										if (!enemy.isImmune) {
											enemy.burning = true;
											enemy.burnDamage = flameParticle.damage * 0.3;
											enemy.burnDuration = 180;
										}
										// Create visual flame effect
										var flameEffect = new EffectIndicator(enemy.x, enemy.y, 'flamethrower');
										game.addChild(flameEffect);
									}
								}
								// Fade out flame particle
								tween(flameParticle, {
									alpha: 0,
									scaleX: 0.5,
									scaleY: 0.5
								}, {
									duration: 200,
									easing: tween.easeIn,
									onFinish: function onFinish() {
										flameParticle.destroy();
									}
								});
							}
						});
					}
				} else {
					// Regular bullet creation for other tower types
					var bulletX = self.x + Math.cos(gunContainer.rotation) * 40;
					var bulletY = self.y + Math.sin(gunContainer.rotation) * 40;
					var bullet = new Bullet(bulletX, bulletY, self.targetEnemy, self.damage, self.bulletSpeed);
					// Set bullet type based on tower type
					bullet.type = self.id;
					// For slow tower, pass level for scaling slow effect
					if (self.id === 'slow') {
						bullet.sourceTowerLevel = self.level;
					}
					// Customize bullet appearance based on tower type
					switch (self.id) {
						case 'sniper':
							bullet.children[0].tint = 0xFF5500;
							bullet.children[0].width = 15;
							bullet.children[0].height = 15;
							break;
						case 'slow':
							// Replace bullet graphics with missile asset
							var missileGraphics = bullet.attachAsset('missiles', {
								anchorX: 0.5,
								anchorY: 0.5
							});
							// Remove the original bullet graphics
							bullet.removeChild(bullet.children[0]);
							break;
						case 'poison':
							bullet.children[0].tint = 0x00FFAA;
							bullet.children[0].width = 35;
							bullet.children[0].height = 35;
							break;
						case 'tank':
							bullet.children[0].tint = 0x8B4513;
							bullet.children[0].width = 40;
							bullet.children[0].height = 40;
							break;
					}
					game.addChild(bullet);
					bullets.push(bullet);
					self.targetEnemy.bulletsTargetingThis.push(bullet);
				}
				// --- Fire recoil effect for gunContainer ---
				// Stop any ongoing recoil tweens before starting a new one
				tween.stop(gunContainer, {
					x: true,
					y: true,
					scaleX: true,
					scaleY: true
				});
				// Always use the original resting position for recoil, never accumulate offset
				if (gunContainer._restX === undefined) {
					gunContainer._restX = 0;
				}
				if (gunContainer._restY === undefined) {
					gunContainer._restY = 0;
				}
				if (gunContainer._restScaleX === undefined) {
					gunContainer._restScaleX = 1;
				}
				if (gunContainer._restScaleY === undefined) {
					gunContainer._restScaleY = 1;
				}
				// Reset to resting position before animating (in case of interrupted tweens)
				gunContainer.x = gunContainer._restX;
				gunContainer.y = gunContainer._restY;
				gunContainer.scaleX = gunContainer._restScaleX;
				gunContainer.scaleY = gunContainer._restScaleY;
				// Calculate recoil offset (recoil back along the gun's rotation)
				var recoilDistance = 8;
				var recoilX = -Math.cos(gunContainer.rotation) * recoilDistance;
				var recoilY = -Math.sin(gunContainer.rotation) * recoilDistance;
				// Animate recoil back from the resting position
				tween(gunContainer, {
					x: gunContainer._restX + recoilX,
					y: gunContainer._restY + recoilY
				}, {
					duration: 60,
					easing: tween.cubicOut,
					onFinish: function onFinish() {
						// Animate return to original position/scale
						tween(gunContainer, {
							x: gunContainer._restX,
							y: gunContainer._restY
						}, {
							duration: 90,
							easing: tween.cubicIn
						});
					}
				});
			}
		}
	};
	self.placeOnGrid = function (gridX, gridY) {
		self.gridX = gridX;
		self.gridY = gridY;
		self.x = grid.x + gridX * CELL_SIZE + CELL_SIZE / 2;
		self.y = grid.y + gridY * CELL_SIZE + CELL_SIZE / 2;
		self.isPlaced = true;
		for (var i = 0; i < 2; i++) {
			for (var j = 0; j < 2; j++) {
				var cell = grid.getCell(gridX + i, gridY + j);
				if (cell) {
					// Store original type before placing tower
					cell.originalType = cell.type;
					// Allow placement on any cell type - don't force to wall type
				}
			}
		}
		self.refreshCellsInRange();
	};
	return self;
});
var TowerPreview = Container.expand(function () {
	var self = Container.call(this);
	var towerRange = 3;
	var rangeInPixels = towerRange * CELL_SIZE;
	self.towerType = 'trap';
	self.hasEnoughGold = true;
	var rangeIndicator = new Container();
	self.addChild(rangeIndicator);
	var rangeGraphics = rangeIndicator.attachAsset('rangeCircle', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	rangeGraphics.alpha = 0.3;
	var previewGraphics = self.attachAsset('Box', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	previewGraphics.width = CELL_SIZE * 2;
	previewGraphics.height = CELL_SIZE * 2;
	self.canPlace = false;
	self.gridX = 0;
	self.gridY = 0;
	self.blockedByEnemy = false;
	var updateCounter = 0;
	self.update = function () {
		// Only check every 10 frames to reduce performance impact
		updateCounter++;
		if (updateCounter % 10 === 0) {
			var previousHasEnoughGold = self.hasEnoughGold;
			self.hasEnoughGold = gold >= getTowerCost(self.towerType);
			// Only update appearance if the affordability status has changed
			if (previousHasEnoughGold !== self.hasEnoughGold) {
				self.updateAppearance();
			}
		}
	};
	self.updateAppearance = function () {
		// Use Tower class to get the source of truth for range without placing it
		var tempTower = new Tower(self.towerType);
		var previewRange = tempTower.getRange();
		// Clean up tempTower immediately without placing it on grid
		tempTower.destroy();
		// Set range indicator using unified range logic
		rangeGraphics.width = rangeGraphics.height = previewRange * 2;
		// Color preview box based on placement validity
		if (self.canPlace && self.hasEnoughGold) {
			// Green for valid placement (including tank towers)
			previewGraphics.tint = 0x00FF00;
			// Animate green pulsing for valid placement
			tween.stop(previewGraphics, {
				alpha: true
			});
			tween(previewGraphics, {
				alpha: 0.7
			}, {
				duration: 500,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					tween(previewGraphics, {
						alpha: 1.0
					}, {
						duration: 500,
						easing: tween.easeInOut
					});
				}
			});
		} else {
			// Red for invalid placement or insufficient gold
			previewGraphics.tint = 0xFF0000;
			// Stop any ongoing animations for invalid placement
			tween.stop(previewGraphics, {
				alpha: true
			});
			previewGraphics.alpha = 1.0;
		}
	};
	self.updatePlacementStatus = function () {
		var validGridPlacement = true;
		// Prevent placement in upper sixth of screen (y < 455)
		var screenY = grid.y + self.gridY * CELL_SIZE;
		if (screenY < 455) {
			validGridPlacement = false;
		} else {
			// For tank weapons, only allow placement in lower half of screen
			if (self.towerType === 'tank') {
				var screenCenterY = grid.y + (29 + 6) * CELL_SIZE / 2; // Grid height / 2
				if (screenY < screenCenterY) {
					validGridPlacement = false;
				}
			}
			// Allow placement anywhere else on the grid
			for (var i = 0; i < 2; i++) {
				for (var j = 0; j < 2; j++) {
					var cell = grid.getCell(self.gridX + i, self.gridY + j);
					if (!cell) {
						validGridPlacement = false;
						break;
					}
				}
				if (!validGridPlacement) {
					break;
				}
			}
		}
		self.blockedByEnemy = false;
		if (validGridPlacement) {
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				if (enemy.currentCellY < 4) {
					continue;
				}
				// Only check non-flying enemies, flying enemies can pass over towers
				if (!enemy.isFlying) {
					if (enemy.cellX >= self.gridX && enemy.cellX < self.gridX + 2 && enemy.cellY >= self.gridY && enemy.cellY < self.gridY + 2) {
						self.blockedByEnemy = true;
						break;
					}
					if (enemy.currentTarget) {
						var targetX = enemy.currentTarget.x;
						var targetY = enemy.currentTarget.y;
						if (targetX >= self.gridX && targetX < self.gridX + 2 && targetY >= self.gridY && targetY < self.gridY + 2) {
							self.blockedByEnemy = true;
							break;
						}
					}
				}
			}
		}
		self.canPlace = validGridPlacement && !self.blockedByEnemy;
		self.hasEnoughGold = gold >= getTowerCost(self.towerType);
		self.updateAppearance();
	};
	self.checkPlacement = function () {
		self.updatePlacementStatus();
	};
	self.snapToGrid = function (x, y) {
		var gridPosX = x - grid.x;
		var gridPosY = y - grid.y;
		self.gridX = Math.floor(gridPosX / CELL_SIZE);
		self.gridY = Math.floor(gridPosY / CELL_SIZE);
		self.x = grid.x + self.gridX * CELL_SIZE + CELL_SIZE / 2;
		self.y = grid.y + self.gridY * CELL_SIZE + CELL_SIZE / 2;
		self.checkPlacement();
	};
	return self;
});
var UpgradeMenu = Container.expand(function (tower) {
	var self = Container.call(this);
	self.tower = tower;
	self.y = 2732 + 225;
	var menuBackground = self.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	menuBackground.width = 2048;
	menuBackground.height = 500;
	menuBackground.tint = 0x444444;
	menuBackground.alpha = 0.9;
	var towerTypeName = self.tower.id === 'slow' ? 'Missiles' : self.tower.id === 'tank' ? 'Tank' : self.tower.id.charAt(0).toUpperCase() + self.tower.id.slice(1);
	var towerTypeText = new Text2(towerTypeName + ' Tower', {
		size: 80,
		fill: 0xFFFFFF,
		weight: 800
	});
	towerTypeText.anchor.set(0, 0);
	towerTypeText.x = -840;
	towerTypeText.y = -160;
	self.addChild(towerTypeText);
	var statsText = new Text2('Level: ' + self.tower.level + '/' + self.tower.maxLevel + '\nDamage: ' + self.tower.damage + '\nFire Rate: ' + (60 / self.tower.fireRate).toFixed(1) + '/s', {
		size: 70,
		fill: 0xFFFFFF,
		weight: 400
	});
	statsText.anchor.set(0, 0.5);
	statsText.x = -840;
	statsText.y = 50;
	self.addChild(statsText);
	var buttonsContainer = new Container();
	buttonsContainer.x = 500;
	self.addChild(buttonsContainer);
	var upgradeButton = new Container();
	buttonsContainer.addChild(upgradeButton);
	var buttonBackground = upgradeButton.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	buttonBackground.width = 500;
	buttonBackground.height = 150;
	var isMaxLevel = self.tower.level >= self.tower.maxLevel;
	// Exponential upgrade cost: base cost * (2 ^ (level-1)), scaled by tower base cost
	var baseUpgradeCost = getTowerCost(self.tower.id);
	var upgradeCost;
	if (isMaxLevel) {
		upgradeCost = 0;
	} else if (self.tower.level === self.tower.maxLevel - 1) {
		upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1) * 3.5 / 2);
	} else {
		upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1));
	}
	buttonBackground.tint = isMaxLevel ? 0x888888 : gold >= upgradeCost ? 0x00AA00 : 0x888888;
	var buttonText = new Text2(isMaxLevel ? 'Max Level' : 'Upgrade: ' + upgradeCost + ' gold', {
		size: 60,
		fill: 0xFFFFFF,
		weight: 800
	});
	buttonText.anchor.set(0.5, 0.5);
	upgradeButton.addChild(buttonText);
	var sellButton = new Container();
	buttonsContainer.addChild(sellButton);
	var sellButtonBackground = sellButton.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	sellButtonBackground.width = 500;
	sellButtonBackground.height = 150;
	sellButtonBackground.tint = 0xCC0000;
	var totalInvestment = self.tower.getTotalValue ? self.tower.getTotalValue() : 0;
	var sellValue = getTowerSellValue(totalInvestment);
	var sellButtonText = new Text2('Sell: +' + sellValue + ' gold', {
		size: 60,
		fill: 0xFFFFFF,
		weight: 800
	});
	sellButtonText.anchor.set(0.5, 0.5);
	sellButton.addChild(sellButtonText);
	upgradeButton.y = -85;
	sellButton.y = 85;
	var closeButton = new Container();
	self.addChild(closeButton);
	var closeBackground = closeButton.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	closeBackground.width = 90;
	closeBackground.height = 90;
	closeBackground.tint = 0xAA0000;
	var closeText = new Text2('X', {
		size: 68,
		fill: 0xFFFFFF,
		weight: 800
	});
	closeText.anchor.set(0.5, 0.5);
	closeButton.addChild(closeText);
	closeButton.x = menuBackground.width / 2 - 57;
	closeButton.y = -menuBackground.height / 2 + 57;
	upgradeButton.down = function (x, y, obj) {
		if (self.tower.level >= self.tower.maxLevel) {
			var notification = game.addChild(new Notification("Tower is already at max level!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 50;
			return;
		}
		if (self.tower.upgrade()) {
			// Exponential upgrade cost: base cost * (2 ^ (level-1)), scaled by tower base cost
			var baseUpgradeCost = getTowerCost(self.tower.id);
			if (self.tower.level >= self.tower.maxLevel) {
				upgradeCost = 0;
			} else if (self.tower.level === self.tower.maxLevel - 1) {
				upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1) * 3.5 / 2);
			} else {
				upgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1));
			}
			statsText.setText('Level: ' + self.tower.level + '/' + self.tower.maxLevel + '\nDamage: ' + self.tower.damage + '\nFire Rate: ' + (60 / self.tower.fireRate).toFixed(1) + '/s');
			buttonText.setText('Upgrade: ' + upgradeCost + ' gold');
			var totalInvestment = self.tower.getTotalValue ? self.tower.getTotalValue() : 0;
			var sellValue = Math.floor(totalInvestment * 0.6);
			sellButtonText.setText('Sell: +' + sellValue + ' gold');
			if (self.tower.level >= self.tower.maxLevel) {
				buttonBackground.tint = 0x888888;
				buttonText.setText('Max Level');
			}
			var rangeCircle = null;
			for (var i = 0; i < game.children.length; i++) {
				if (game.children[i].isTowerRange && game.children[i].tower === self.tower) {
					rangeCircle = game.children[i];
					break;
				}
			}
			if (rangeCircle) {
				var rangeGraphics = rangeCircle.children[0];
				rangeGraphics.width = rangeGraphics.height = self.tower.getRange() * 2;
			} else {
				var newRangeIndicator = new Container();
				newRangeIndicator.isTowerRange = true;
				newRangeIndicator.tower = self.tower;
				game.addChildAt(newRangeIndicator, 0);
				newRangeIndicator.x = self.tower.x;
				newRangeIndicator.y = self.tower.y;
				var rangeGraphics = newRangeIndicator.attachAsset('rangeCircle', {
					anchorX: 0.5,
					anchorY: 0.5
				});
				rangeGraphics.width = rangeGraphics.height = self.tower.getRange() * 2;
				rangeGraphics.alpha = 0.3;
			}
			tween(self, {
				scaleX: 1.05,
				scaleY: 1.05
			}, {
				duration: 100,
				easing: tween.easeOut,
				onFinish: function onFinish() {
					tween(self, {
						scaleX: 1,
						scaleY: 1
					}, {
						duration: 100,
						easing: tween.easeIn
					});
				}
			});
		}
	};
	sellButton.down = function (x, y, obj) {
		var totalInvestment = self.tower.getTotalValue ? self.tower.getTotalValue() : 0;
		var sellValue = getTowerSellValue(totalInvestment);
		setGold(gold + sellValue);
		var notification = game.addChild(new Notification("Tower sold for " + sellValue + " gold!"));
		notification.x = 2048 / 2;
		notification.y = grid.height - 50;
		var gridX = self.tower.gridX;
		var gridY = self.tower.gridY;
		for (var i = 0; i < 2; i++) {
			for (var j = 0; j < 2; j++) {
				var cell = grid.getCell(gridX + i, gridY + j);
				if (cell) {
					// Restore original cell type or default to ground (type 1) if no original type stored
					cell.type = cell.originalType !== undefined ? cell.originalType : 1;
					var towerIndex = cell.towersInRange.indexOf(self.tower);
					if (towerIndex !== -1) {
						cell.towersInRange.splice(towerIndex, 1);
					}
				}
			}
		}
		if (selectedTower === self.tower) {
			selectedTower = null;
		}
		var towerIndex = towers.indexOf(self.tower);
		if (towerIndex !== -1) {
			towers.splice(towerIndex, 1);
		}
		towerLayer.removeChild(self.tower);
		grid.pathFind();
		grid.renderDebug();
		self.destroy();
		for (var i = 0; i < game.children.length; i++) {
			if (game.children[i].isTowerRange && game.children[i].tower === self.tower) {
				game.removeChild(game.children[i]);
				break;
			}
		}
	};
	closeButton.down = function (x, y, obj) {
		hideUpgradeMenu(self);
		selectedTower = null;
		grid.renderDebug();
	};
	self.update = function () {
		if (self.tower.level >= self.tower.maxLevel) {
			if (buttonText.text !== 'Max Level') {
				buttonText.setText('Max Level');
				buttonBackground.tint = 0x888888;
			}
			return;
		}
		// Exponential upgrade cost: base cost * (2 ^ (level-1)), scaled by tower base cost
		var baseUpgradeCost = getTowerCost(self.tower.id);
		var currentUpgradeCost;
		if (self.tower.level >= self.tower.maxLevel) {
			currentUpgradeCost = 0;
		} else if (self.tower.level === self.tower.maxLevel - 1) {
			currentUpgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1) * 3.5 / 2);
		} else {
			currentUpgradeCost = Math.floor(baseUpgradeCost * Math.pow(2, self.tower.level - 1));
		}
		var canAfford = gold >= currentUpgradeCost;
		buttonBackground.tint = canAfford ? 0x00AA00 : 0x888888;
		var newText = 'Upgrade: ' + currentUpgradeCost + ' gold';
		if (buttonText.text !== newText) {
			buttonText.setText(newText);
		}
	};
	return self;
});
var WaveIndicator = Container.expand(function () {
	var self = Container.call(this);
	self.gameStarted = false;
	self.waveMarkers = [];
	self.waveTypes = [];
	self.enemyCounts = [];
	self.indicatorWidth = 0;
	self.lastBossType = null; // Track the last boss type to avoid repeating
	var blockWidth = 400;
	var totalBlocksWidth = blockWidth * totalWaves;
	var startMarker = new Container();
	var startBlock = startMarker.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	startBlock.width = blockWidth - 10;
	startBlock.height = 70 * 2;
	startBlock.tint = 0xffad0e;
	// Add shadow for start text
	var startTextShadow = new Text2("Start Battle", {
		size: 50,
		fill: 0x000000,
		weight: 800
	});
	startTextShadow.anchor.set(0.5, 0.5);
	startTextShadow.x = 4;
	startTextShadow.y = 4;
	startMarker.addChild(startTextShadow);
	var startText = new Text2("Start Battle", {
		size: 50,
		fill: 0xFFFFFF,
		weight: 800
	});
	startText.anchor.set(0.5, 0.5);
	startMarker.addChild(startText);
	startMarker.x = -self.indicatorWidth;
	self.addChild(startMarker);
	self.waveMarkers.push(startMarker);
	startMarker.down = function () {
		if (!self.gameStarted) {
			self.gameStarted = true;
			currentWave = 0;
			waveTimer = nextWaveTime;
			startBlock.tint = 0xffad0e;
			startText.setText("Started!");
			startTextShadow.setText("Started!");
			// Make sure shadow position remains correct after text change
			startTextShadow.x = 4;
			startTextShadow.y = 4;
			var notification = game.addChild(new Notification("Game started! Wave 1 incoming!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 150;
		}
	};
	for (var i = 0; i < totalWaves; i++) {
		var marker = new Container();
		var block = marker.attachAsset('notification', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		block.width = blockWidth - 10;
		block.height = 70 * 2;
		// --- Begin new unified wave logic ---
		var waveType = "normal";
		var enemyType = "normal";
		var enemyCount = 10;
		var isBossWave = i + 1 === totalWaves;
		// Ensure all types appear in early waves
		if (i === 0) {
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		} else if (i === 1) {
			block.tint = 0x2F4F2F;
			waveType = "Immune";
			enemyType = "immune";
			enemyCount = 2;
		} else if (i === 2) {
			block.tint = 0x006400;
			waveType = "Flying";
			enemyType = "flying";
			enemyCount = 3;
		} else if (i === 3) {
			block.tint = 0x3B5323;
			waveType = "Tank";
			enemyType = "tank";
			enemyCount = 1;
		} else if (i === 4) {
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		} else if (i === 8) {
			// Wave 9 - Immune
			block.tint = 0x4A6B4A;
			waveType = "Immune";
			enemyType = "immune";
			enemyCount = 2;
		} else if (i === 9) {
			// Wave 10 - Flying
			block.tint = 0x006B40;
			waveType = "Flying";
			enemyType = "flying";
			enemyCount = 3;
		} else if (i === 10) {
			// Wave 11 - Tank (changed from immune)
			block.tint = 0x556B22;
			waveType = "Tank";
			enemyType = "tank";
			enemyCount = 1;
		} else if (isBossWave) {
			// Boss waves: cycle through all boss types, last boss is always flying
			var bossTypes = ['fast', 'immune', 'flying'];
			var bossTypeIndex = Math.floor((i + 1) / 10) - 1;
			if (i === totalWaves - 1) {
				// Last boss is always flying
				enemyType = 'flying';
				waveType = "Boss Flying";
				block.tint = 0x006B22;
			} else {
				enemyType = bossTypes[bossTypeIndex % bossTypes.length];
				switch (enemyType) {
					case 'fast':
						block.tint = 0x228B22;
						waveType = "Boss Fast";
						break;
					case 'immune':
						block.tint = 0x4A6B4A;
						waveType = "Boss Immune";
						break;
					case 'flying':
						block.tint = 0x006B40;
						waveType = "Boss Flying";
						break;
				}
			}
			enemyCount = 1;
			// Make the wave indicator for boss waves stand out
			// Set boss wave color to black
			block.tint = 0x000000;
		} else if ((i + 1) % 5 === 0) {
			// Every 5th non-boss wave is fast
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		} else if ((i + 1) % 4 === 0) {
			// Every 4th non-boss wave is tank
			block.tint = 0x4B6000;
			waveType = "Tank";
			enemyType = "tank";
			enemyCount = 1;
		} else if ((i + 1) % 7 === 0) {
			// Every 7th non-boss wave is flying
			block.tint = 0x006B56;
			waveType = "Flying";
			enemyType = "flying";
			enemyCount = 3;
		} else if ((i + 1) % 3 === 0) {
			// Every 3rd non-boss wave is fast
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		} else {
			block.tint = 0x228B22;
			waveType = "Fast";
			enemyType = "fast";
			enemyCount = 10;
		}
		// --- End new unified wave logic ---
		// Mark boss waves with a special visual indicator
		if (isBossWave) {
			// Change the wave type text to indicate boss
			waveType = "BOSS";
		}
		// Store the wave type and enemy count
		self.waveTypes[i] = enemyType;
		self.enemyCounts[i] = enemyCount;
		// Add shadow for wave type - 30% smaller than before
		var waveTypeShadow = new Text2(waveType, {
			size: 56,
			fill: 0x000000,
			weight: 800
		});
		waveTypeShadow.anchor.set(0.5, 0.5);
		waveTypeShadow.x = 4;
		waveTypeShadow.y = 4;
		marker.addChild(waveTypeShadow);
		// Add wave type text - 30% smaller than before
		var waveTypeText = new Text2(waveType, {
			size: 56,
			fill: 0xFFFFFF,
			weight: 800
		});
		waveTypeText.anchor.set(0.5, 0.5);
		waveTypeText.y = 0;
		marker.addChild(waveTypeText);
		// Add shadow for wave number - 20% larger than before
		var waveNumShadow = new Text2((i + 1).toString(), {
			size: 48,
			fill: 0x000000,
			weight: 800
		});
		waveNumShadow.anchor.set(1.0, 1.0);
		waveNumShadow.x = blockWidth / 2 - 16 + 5;
		waveNumShadow.y = block.height / 2 - 12 + 5;
		marker.addChild(waveNumShadow);
		// Main wave number text - 20% larger than before
		var waveNum = new Text2((i + 1).toString(), {
			size: 48,
			fill: 0xFFFFFF,
			weight: 800
		});
		waveNum.anchor.set(1.0, 1.0);
		waveNum.x = blockWidth / 2 - 16;
		waveNum.y = block.height / 2 - 12;
		marker.addChild(waveNum);
		marker.x = -self.indicatorWidth + (i + 1) * blockWidth;
		self.addChild(marker);
		self.waveMarkers.push(marker);
	}
	// Get wave type for a specific wave number
	self.getWaveType = function (waveNumber) {
		if (waveNumber < 1 || waveNumber > totalWaves) {
			return "fast";
		}
		// If this is a boss wave (waveNumber % 10 === 0), and the type is the same as lastBossType
		// then we should return a different boss type
		var waveType = self.waveTypes[waveNumber - 1];
		return waveType;
	};
	// Get enemy count for a specific wave number
	self.getEnemyCount = function (waveNumber) {
		if (waveNumber < 1 || waveNumber > totalWaves) {
			return 10;
		}
		return self.enemyCounts[waveNumber - 1];
	};
	// Get display name for a wave type
	self.getWaveTypeName = function (waveNumber) {
		var type = self.getWaveType(waveNumber);
		var typeName = type.charAt(0).toUpperCase() + type.slice(1);
		// Add boss prefix for boss waves (final wave)
		if (waveNumber === totalWaves) {
			typeName = "BOSS";
		}
		return typeName;
	};
	self.positionIndicator = new Container();
	var indicator = self.positionIndicator.attachAsset('towerLevelIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	indicator.width = blockWidth - 10;
	indicator.height = 16;
	indicator.tint = 0xffad0e;
	indicator.y = -65;
	var indicator2 = self.positionIndicator.attachAsset('towerLevelIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	indicator2.width = blockWidth - 10;
	indicator2.height = 16;
	indicator2.tint = 0xffad0e;
	indicator2.y = 65;
	var leftWall = self.positionIndicator.attachAsset('towerLevelIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	leftWall.width = 16;
	leftWall.height = 146;
	leftWall.tint = 0xffad0e;
	leftWall.x = -(blockWidth - 16) / 2;
	var rightWall = self.positionIndicator.attachAsset('towerLevelIndicator', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	rightWall.width = 16;
	rightWall.height = 146;
	rightWall.tint = 0xffad0e;
	rightWall.x = (blockWidth - 16) / 2;
	self.addChild(self.positionIndicator);
	self.update = function () {
		var progress = waveTimer / nextWaveTime;
		var moveAmount = (progress + currentWave) * blockWidth;
		for (var i = 0; i < self.waveMarkers.length; i++) {
			var marker = self.waveMarkers[i];
			marker.x = -moveAmount + i * blockWidth;
		}
		self.positionIndicator.x = 0;
		for (var i = 0; i < totalWaves + 1; i++) {
			var marker = self.waveMarkers[i];
			if (i === 0) {
				continue;
			}
			var block = marker.children[0];
			if (i - 1 < currentWave) {
				block.alpha = .5;
			}
		}
		self.handleWaveProgression = function () {
			if (!self.gameStarted) {
				return;
			}
			if (currentWave < totalWaves) {
				waveTimer++;
				if (waveTimer >= nextWaveTime) {
					waveTimer = 0;
					currentWave++;
					waveInProgress = true;
					waveSpawned = false;
					if (currentWave != 1) {
						var waveType = self.getWaveTypeName(currentWave);
						var enemyCount = self.getEnemyCount(currentWave);
						var notification = game.addChild(new Notification("Wave " + currentWave + " (" + waveType + " - " + enemyCount + " enemies) incoming!"));
						notification.x = 2048 / 2;
						notification.y = grid.height - 150;
					}
				}
			}
		};
		self.handleWaveProgression();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0xD2B48C
});
/**** 
* Game Code
****/ 
var gameState = 'menu'; // 'menu', 'playing'
var isHidingUpgradeMenu = false;
// Global flag for alternating fly direction
var lastDirectionWasRight = false;
function spawnFly() {
	lastDirectionWasRight = !lastDirectionWasRight;
	// You would set fly.vx and fly.vy here based on your fly object
	// fly.vx = (lastDirectionWasRight ? 1 : -1) * horizontalSpeed;
	// fly.vy = downSpeed;
	// For this tower defense game, we can apply this pattern to flying enemies
	// by modifying their target lanes based on direction
	console.log("Fly spawning with direction:", lastDirectionWasRight ? "right" : "left");
}
// Mobile detection and sniper tower blocking
(function blockSniperTowers() {
	// Safe mobile detection without navigator.userAgent
	var isMobile = false;
	try {
		if (typeof window !== 'undefined' && window.navigator && window.navigator.userAgent) {
			isMobile = /Mobi|Android/i.test(window.navigator.userAgent);
		} else {
			// Fallback: assume mobile if screen dimensions suggest mobile device
			isMobile = typeof window !== 'undefined' && window.innerWidth && window.innerWidth < 1024;
		}
	} catch (e) {
		// If all else fails, default to false (desktop)
		isMobile = false;
	}
	if (!isMobile) return; // Only activate on mobile
	// Override tower creation to block sniper towers
	var originalTowerConstructor = Tower;
	Tower = Container.expand(function (id) {
		// Block sniper tower creation on mobile
		if (id === 'sniper') {
			console.warn("[BLOCKED] Sniper tower creation prevented on mobile.");
			// Return a basic trap tower instead
			return originalTowerConstructor.call(this, 'trap');
		}
		// Use original constructor for other tower types
		return originalTowerConstructor.call(this, id);
	});
	// Override getTowerCost to return 0 for sniper on mobile (making it unavailable)
	var originalGetTowerCost = getTowerCost;
	getTowerCost = function getTowerCost(towerType) {
		if (towerType === 'sniper') {
			return 999999; // Make sniper prohibitively expensive on mobile
		}
		return originalGetTowerCost(towerType);
	};
	console.log("[INFO] Sniper tower blocking activated for mobile device.");
})();
function hideUpgradeMenu(menu) {
	if (isHidingUpgradeMenu) {
		return;
	}
	isHidingUpgradeMenu = true;
	tween(menu, {
		y: 2732 + 225
	}, {
		duration: 150,
		easing: tween.easeIn,
		onFinish: function onFinish() {
			menu.destroy();
			isHidingUpgradeMenu = false;
		}
	});
}
var CELL_SIZE = 76;
var pathId = 1;
var maxScore = 0;
var enemies = [];
var towers = [];
// Ensure no pre-placed towers exist - clear any that might have been created
function clearPrePlacedTowers() {
	// This function is now only used for initial game setup cleanup
	// It should not aggressively remove player-placed towers during gameplay
	// Only clear references, don't destroy actual towers during gameplay
	selectedTower = null;
	// Only clear grid cell references if grid exists and game is not in playing state
	if (grid && grid.cells && gameState !== 'playing') {
		for (var i = 0; i < grid.cells.length; i++) {
			for (var j = 0; j < grid.cells[i].length; j++) {
				var cell = grid.cells[i][j];
				if (cell && cell.towersInRange) {
					cell.towersInRange.length = 0;
				}
			}
		}
	}
}
// Call this function to ensure clean slate - but only after towerLayer is created
// clearPrePlacedTowers(); // Moved this call to after towerLayer creation
var bullets = [];
var defenses = [];
var selectedTower = null;
var gold = 100;
var lives = 100;
var score = 0;
var currentWave = 0;
var selectedDifficulty = null;
var totalWaves = 12;
var waveTimer = 0;
var waveInProgress = false;
var waveSpawned = false;
var nextWaveTime = 600; // Reduced from 1500 to 600 frames (10 seconds instead of 25)
var sourceTower = null;
var enemiesToSpawn = 10; // Default number of enemies per wave
var goldText = new Text2('Gold: ' + gold, {
	size: 60,
	fill: 0xFFD700,
	weight: 800
});
goldText.anchor.set(0.5, 0.5);
var livesText = new Text2('Lives: ' + lives, {
	size: 60,
	fill: 0x00FF00,
	weight: 800
});
livesText.anchor.set(0.5, 0.5);
var scoreText = new Text2('Score: ' + score, {
	size: 60,
	fill: 0xFF0000,
	weight: 800
});
scoreText.anchor.set(0.5, 0.5);
var topMargin = 50;
var centerX = 2048 / 2;
var spacing = 400;
// Create UI container for game elements
var gameUIContainer = new Container();
gameUIContainer.addChild(goldText);
gameUIContainer.addChild(livesText);
gameUIContainer.addChild(scoreText);
livesText.x = 0;
livesText.y = topMargin;
goldText.x = -spacing;
goldText.y = topMargin;
scoreText.x = spacing;
scoreText.y = topMargin;
// Initially hide game UI
gameUIContainer.visible = false;
LK.gui.top.addChild(gameUIContainer);
var lastGold = -1;
var lastLives = -1;
var lastScore = -1;
function updateUI() {
	if (gold !== lastGold) {
		goldText.setText('Gold: ' + gold);
		lastGold = gold;
	}
	if (lives !== lastLives) {
		livesText.setText('Lives: ' + lives);
		lastLives = lives;
	}
	if (score !== lastScore) {
		scoreText.setText('Score: ' + score);
		lastScore = score;
	}
}
function setGold(value) {
	gold = value;
	updateUI();
}
var debugLayer = new Container();
var towerLayer = new Container();
// Initialize empty towers array
towers = [];
// Clear any pre-placed towers that might have been loaded with the map
clearPrePlacedTowers();
// Fast enemy can shoot - already implemented
// This functionality is already working in the Enemy class update method
// Fast enemies have shooting range, damage, cooldown, and create red bullets targeting towers
var enemyLayerBottom = new Container(); // For normal enemies
var enemyLayerMiddle = new Container(); // For shadows
var enemyLayerTop = new Container(); // For flying enemies
var enemyLayer = new Container(); // Main container to hold all enemy layers
// Add layers in correct order (bottom first, then middle for shadows, then top)
enemyLayer.addChild(enemyLayerBottom);
enemyLayer.addChild(enemyLayerMiddle);
enemyLayer.addChild(enemyLayerTop);
var grid = new Grid(24, 29 + 6);
grid.x = 150;
grid.y = 200 - CELL_SIZE * 4;
grid.pathFind();
grid.renderDebug();
debugLayer.addChild(grid);
// Create menu container
var menuContainer = new Container();
game.addChild(menuContainer);
// Create game container for all game elements
var gameContainer = new Container();
gameContainer.addChild(debugLayer);
gameContainer.addChild(towerLayer);
gameContainer.addChild(enemyLayer);
game.addChild(gameContainer);
// Initially hide game elements
gameContainer.visible = false;
var offset = 0;
var towerPreview = new TowerPreview();
game.addChild(towerPreview);
towerPreview.visible = false;
var isDragging = false;
function wouldBlockPath(gridX, gridY) {
	var cells = [];
	for (var i = 0; i < 2; i++) {
		for (var j = 0; j < 2; j++) {
			var cell = grid.getCell(gridX + i, gridY + j);
			if (cell) {
				cells.push({
					cell: cell,
					originalType: cell.type
				});
				// Only set to blocking type if it's currently a path (type 0)
				// Ground cells (type 1) can be built on without blocking paths
				if (cell.type === 0) {
					cell.type = 1;
				}
			}
		}
	}
	var blocked = grid.pathFind();
	for (var i = 0; i < cells.length; i++) {
		cells[i].cell.type = cells[i].originalType;
	}
	grid.pathFind();
	grid.renderDebug();
	return blocked;
}
function getTowerCost(towerType) {
	var cost = 30;
	switch (towerType) {
		case 'landmine':
			cost = 10;
			break;
		case 'sniper':
			cost = 40;
			break;
		case 'flamethrower':
			cost = 20;
			break;
		case 'slow':
			cost = 50;
			break;
		case 'poison':
			cost = 55;
			break;
		case 'tank':
			cost = 60;
			break;
	}
	return cost;
}
function getTowerSellValue(totalValue) {
	return waveIndicator && waveIndicator.gameStarted ? Math.floor(totalValue * 0.6) : totalValue;
}
function placeTower(gridX, gridY, towerType) {
	var towerCost = getTowerCost(towerType);
	if (gold >= towerCost) {
		var tower = new Tower(towerType || 'trap');
		tower.placeOnGrid(gridX, gridY);
		towerLayer.addChild(tower);
		towers.push(tower);
		setGold(gold - towerCost);
		// Only recalculate pathfinding if needed
		if (!grid.pathFind()) {
			grid.renderDebug();
		}
		return true;
	} else {
		var notification = game.addChild(new Notification("Not enough gold!"));
		notification.x = 2048 / 2;
		notification.y = grid.height - 50;
		return false;
	}
}
game.down = function (x, y, obj) {
	// Prevent any clicks on game elements when in menu state
	if (gameState !== 'playing') {
		return;
	}
	var upgradeMenuVisible = game.children.some(function (child) {
		return child instanceof UpgradeMenu;
	});
	if (upgradeMenuVisible) {
		return;
	}
	for (var i = 0; i < sourceTowers.length; i++) {
		var tower = sourceTowers[i];
		if (x >= tower.x - tower.width / 2 && x <= tower.x + tower.width / 2 && y >= tower.y - tower.height / 2 && y <= tower.y + tower.height / 2) {
			towerPreview.visible = true;
			isDragging = true;
			towerPreview.towerType = tower.towerType;
			towerPreview.updateAppearance();
			// Apply the same offset as in move handler to ensure consistency when starting drag
			towerPreview.snapToGrid(x, y - CELL_SIZE * 1.5);
			break;
		}
	}
};
game.move = function (x, y, obj) {
	if (isDragging) {
		// Shift the y position upward by 1.5 tiles to show preview above finger
		towerPreview.snapToGrid(x, y - CELL_SIZE * 1.5);
	}
};
game.up = function (x, y, obj) {
	var clickedOnTower = false;
	for (var i = 0; i < towers.length; i++) {
		var tower = towers[i];
		var towerLeft = tower.x - tower.width / 2;
		var towerRight = tower.x + tower.width / 2;
		var towerTop = tower.y - tower.height / 2;
		var towerBottom = tower.y + tower.height / 2;
		if (x >= towerLeft && x <= towerRight && y >= towerTop && y <= towerBottom) {
			clickedOnTower = true;
			break;
		}
	}
	var upgradeMenus = game.children.filter(function (child) {
		return child instanceof UpgradeMenu;
	});
	if (upgradeMenus.length > 0 && !isDragging && !clickedOnTower) {
		var clickedOnMenu = false;
		for (var i = 0; i < upgradeMenus.length; i++) {
			var menu = upgradeMenus[i];
			var menuWidth = 2048;
			var menuHeight = 450;
			var menuLeft = menu.x - menuWidth / 2;
			var menuRight = menu.x + menuWidth / 2;
			var menuTop = menu.y - menuHeight / 2;
			var menuBottom = menu.y + menuHeight / 2;
			if (x >= menuLeft && x <= menuRight && y >= menuTop && y <= menuBottom) {
				clickedOnMenu = true;
				break;
			}
		}
		if (!clickedOnMenu) {
			for (var i = 0; i < upgradeMenus.length; i++) {
				var menu = upgradeMenus[i];
				hideUpgradeMenu(menu);
			}
			for (var i = game.children.length - 1; i >= 0; i--) {
				if (game.children[i].isTowerRange) {
					game.removeChild(game.children[i]);
				}
			}
			selectedTower = null;
			grid.renderDebug();
		}
	}
	if (isDragging) {
		isDragging = false;
		if (towerPreview.canPlace) {
			placeTower(towerPreview.gridX, towerPreview.gridY, towerPreview.towerType);
		} else if (towerPreview.blockedByEnemy) {
			var notification = game.addChild(new Notification("Cannot build: Enemy in the way!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 50;
		} else if (towerPreview.visible) {
			var notification = game.addChild(new Notification("Cannot build here!"));
			notification.x = 2048 / 2;
			notification.y = grid.height - 50;
		}
		towerPreview.visible = false;
		if (isDragging) {
			var upgradeMenus = game.children.filter(function (child) {
				return child instanceof UpgradeMenu;
			});
			for (var i = 0; i < upgradeMenus.length; i++) {
				upgradeMenus[i].destroy();
			}
		}
	}
};
var waveIndicator = null; // Initialize as null, will be created when game starts
// Function to create wave indicator with current totalWaves
function createWaveIndicator() {
	if (waveIndicator) {
		gameContainer.removeChild(waveIndicator);
	}
	waveIndicator = new WaveIndicator();
	waveIndicator.x = 2048 / 2;
	waveIndicator.y = 2732 - 80;
	gameContainer.addChild(waveIndicator);
}
var nextWaveButtonContainer = new Container();
var nextWaveButton = new NextWaveButton();
nextWaveButton.x = 2048 - 200;
nextWaveButton.y = 2732 - 100 + 20;
nextWaveButtonContainer.addChild(nextWaveButton);
// Add to game instead of gameContainer to ensure it appears on top of all map elements
game.addChild(nextWaveButtonContainer);
var towerTypes = ['landmine', 'flamethrower', 'trap', 'sniper', 'slow', 'tank'];
// Filter out sniper tower on mobile devices
var isMobile = false;
try {
	if (typeof window !== 'undefined' && window.navigator && window.navigator.userAgent) {
		isMobile = /Mobi|Android/i.test(window.navigator.userAgent);
	} else {
		// Fallback: assume mobile if screen dimensions suggest mobile device
		isMobile = typeof window !== 'undefined' && window.innerWidth && window.innerWidth < 1024;
	}
} catch (e) {
	// If all else fails, default to false (desktop)
	isMobile = false;
}
if (isMobile) {
	towerTypes = towerTypes.filter(function (type) {
		return type !== 'sniper';
	});
	console.log("[INFO] Sniper tower removed from available towers on mobile.");
}
var sourceTowers = [];
var towerSpacing = 350; // Increase spacing for larger towers
var startX = 2048 / 2 - towerTypes.length * towerSpacing / 2 + towerSpacing / 2;
var towerY = 2732 - CELL_SIZE * 3 - 90;
for (var i = 0; i < towerTypes.length; i++) {
	var tower = new SourceTower(towerTypes[i]);
	tower.x = startX + i * towerSpacing;
	tower.y = towerY;
	game.addChild(tower); // Add to game instead of towerLayer to prevent it from being a placeable tower
	sourceTowers.push(tower);
}
sourceTower = null;
enemiesToSpawn = 10;
// Hide weapon boxes initially
for (var i = 0; i < sourceTowers.length; i++) {
	sourceTowers[i].visible = false;
}
// Create new difficulty selection menu
// Menu background panel
var menuBg = new Container();
var menuBgGraphics = menuBg.attachAsset('MW', {
	anchorX: 0.5,
	anchorY: 0.5
});
menuBgGraphics.width = 2050;
menuBgGraphics.height = 2732;
menuBg.x = 2048 / 2 + 1;
menuBg.y = 2732 / 2;
menuContainer.addChild(menuBg);
// Play menu music automatically when menu is loaded
LK.playMusic('Menu1');
// Title - using TDT asset
var title = new Container();
var titleGraphics = title.attachAsset('TDT', {
	anchorX: 0.5,
	anchorY: 0.5
});
title.x = 2048 / 2;
title.y = 2732 * 0.1 + 333;
menuContainer.addChild(title);
// Difficulty buttons data
var difficulties = [{
	label: 'HARD β 48 WAVES',
	level: 'HARD',
	waves: 48
}, {
	label: 'MEDIUM β 24 WAVES',
	level: 'MEDIUM',
	waves: 24
}, {
	label: 'EASY β 12 WAVES',
	level: 'EASY',
	waves: 12
}];
var difficultyButtons = [];
var playButton = null;
// Create difficulty buttons
for (var i = 0; i < difficulties.length; i++) {
	var diff = difficulties[i];
	var btn = new Container();
	var btnBg = btn.attachAsset('notification', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	btnBg.width = 1600;
	btnBg.height = 240;
	btnBg.tint = 0x004B00; // Darker green
	btnBg.alpha = 0.8;
	var btnText = new Text2(diff.label, {
		size: 120,
		fill: 0x00FF00,
		weight: 800
	});
	btnText.anchor.set(0.5, 0.5);
	btn.addChild(btnText);
	btn.x = 2048 / 2;
	btn.y = 2732 * (0.25 + i * 0.1) + 333 + 333;
	btn.difficulty = diff;
	menuContainer.addChild(btn);
	difficultyButtons.push(btn);
	// Add click handler to difficulty button
	btn.down = function () {
		selectedDifficulty = this.difficulty.level;
		totalWaves = this.difficulty.waves;
		// Hide instruction text once a difficulty is selected
		if (difficultyInstructionText && difficultyInstructionText.visible) {
			difficultyInstructionText.visible = false;
		}
		// Update all button appearances
		for (var j = 0; j < difficultyButtons.length; j++) {
			var button = difficultyButtons[j];
			var bg = button.children[0];
			if (button.difficulty.level === selectedDifficulty) {
				bg.tint = 0x006600; // Darker green for selected
				bg.alpha = 1.0;
			} else {
				bg.tint = 0x004B00; // Darker green for unselected
				bg.alpha = 0.8;
			}
		}
		// Show play button
		if (playButton) {
			playButton.visible = true;
		}
	};
}
// Difficulty instruction text
var difficultyInstructionText = new Text2('Please choose a difficulty level!', {
	size: 80,
	fill: 0xFFFFFF,
	weight: 800
});
difficultyInstructionText.anchor.set(0.5, 1.0);
difficultyInstructionText.x = 2048 / 2;
difficultyInstructionText.y = 2732 - 50;
menuContainer.addChild(difficultyInstructionText);
// PLAY button - initially hidden
playButton = new Container();
var playButtonBg = playButton.attachAsset('notification', {
	anchorX: 0.5,
	anchorY: 0.5
});
playButtonBg.width = 800;
playButtonBg.height = 240;
playButtonBg.tint = 0x00AA00;
var playButtonText = new Text2('PLAY', {
	size: 160,
	fill: 0x00FF00,
	weight: 800
});
playButtonText.anchor.set(0.5, 0.5);
playButton.addChild(playButtonText);
playButton.x = 2048 / 2;
playButton.y = (2732 * 0.45 + 666 + 2732) / 2 + 69;
playButton.visible = false;
menuContainer.addChild(playButton);
playButton.down = function () {
	if (selectedDifficulty) {
		// Stop menu music when starting game
		LK.stopMusic();
		// Generate waves based on selected difficulty
		generateWaves(totalWaves);
		// Create wave indicator with selected difficulty
		createWaveIndicator();
		// Transition from menu to game
		gameState = 'playing';
		menuContainer.visible = false;
		gameContainer.visible = true;
		gameUIContainer.visible = true;
		// Show weapon boxes when game starts
		for (var i = 0; i < sourceTowers.length; i++) {
			sourceTowers[i].visible = true;
		}
	}
};
// Wave generation function
function generateWaves(count) {
	// The existing wave system will handle wave generation
	// We just need to set totalWaves which is already done above
	// The WaveIndicator class will use the totalWaves value
	console.log('Generated', count, 'waves for difficulty:', selectedDifficulty);
}
// Function to show menu
function showMenu() {
	gameState = 'menu';
	menuContainer.visible = true;
	gameContainer.visible = false;
	gameUIContainer.visible = false;
}
// Function to show game
function showGame() {
	gameState = 'playing';
	menuContainer.visible = false;
	gameContainer.visible = true;
	gameUIContainer.visible = true;
}
function onGameStart(callback) {
	// Store the callback to be executed when game starts
	if (waveIndicator && waveIndicator.gameStarted) {
		callback();
	} else {
		// Wait for game to start, then execute callback
		var checkGameStart = LK.setInterval(function () {
			if (waveIndicator && waveIndicator.gameStarted) {
				LK.clearInterval(checkGameStart);
				callback();
			}
		}, 100);
	}
}
// Tank spawning is now handled by the main wave system in game.update
// No manual spawning needed here
game.update = function () {
	// Only run game logic when in playing state
	if (gameState !== 'playing') {
		return;
	}
	if (waveInProgress && waveIndicator) {
		if (!waveSpawned) {
			waveSpawned = true;
			// Get wave type and enemy count from the wave indicator
			var waveType = waveIndicator.getWaveType(currentWave);
			var enemyCount = waveIndicator.getEnemyCount(currentWave);
			// Check if this is a boss wave
			var isBossWave = currentWave === totalWaves;
			if (isBossWave) {
				// Boss waves have just 1 enemy regardless of what the wave indicator says
				enemyCount = 1;
				// Show boss announcement
				var notification = game.addChild(new Notification("β οΈ BOSS WAVE! β οΈ"));
				notification.x = 2048 / 2;
				notification.y = grid.height - 200;
			}
			// Spawn the appropriate number of enemies
			for (var i = 0; i < enemyCount; i++) {
				var enemy = new Enemy(waveType);
				// Initialize flying enemy direction using global alternating flag
				if (enemy.isFlying) {
					// Call the spawnFly function to update the global direction flag
					spawnFly();
					// Set the flying enemy's initial direction based on the global flag
					enemy.flyingDirection = lastDirectionWasRight ? 1 : -1; // 1 for right, -1 for left
				}
				// Add enemy to the appropriate layer based on type for proper display order
				if (enemy.isFlying) {
					// Add flying enemy to the top layer to ensure they appear above all other enemies
					enemyLayerTop.addChild(enemy);
					// If it's a flying enemy, add its shadow to the middle layer
					if (enemy.shadow) {
						enemyLayerMiddle.addChild(enemy.shadow);
					}
				} else if (enemy.type === 'fast') {
					// Add fast enemies to the bottom layer to ensure flying enemies appear above them
					enemyLayerBottom.addChild(enemy);
				} else {
					// Add other ground enemies (immune, tank, etc.) to the middle layer
					enemyLayerMiddle.addChild(enemy);
				}
				// Scale difficulty with wave number but don't apply to boss
				// as bosses already have their health multiplier
				// Use exponential scaling for health
				var healthMultiplier = Math.pow(1.12, currentWave); // ~20% increase per wave
				enemy.maxHealth = Math.round(enemy.maxHealth * healthMultiplier);
				enemy.health = enemy.maxHealth;
				// Increment speed slightly with wave number
				//enemy.speed = enemy.speed + currentWave * 0.002;
				// Assign specific lanes for different enemy types to prevent overlapping
				var gridWidth = 24;
				var midPoint = Math.floor(gridWidth / 2); // 12
				var spawnX;
				// Define strict non-overlapping lanes with buffer zones for different enemy types
				if (waveType === 'fast') {
					// Fast enemies spawn in horizontal lines
					var enemiesPerLine = 5; // Number of enemies per horizontal line
					var lineNumber = Math.floor(i / enemiesPerLine); // Which horizontal line this enemy belongs to
					var positionInLine = i % enemiesPerLine; // Position within the line (0-4)
					var lineColumns = [6, 9, 12, 15, 18]; // Available columns for horizontal lines - moved left
					spawnX = lineColumns[positionInLine]; // Position enemy in the line
				} else if (waveType === 'immune') {
					// Immune enemies use center-left lanes (columns 11-12) with buffer from fast and tank
					var immuneColumns = [11, 12];
					var availableImmuneColumns = [];
					for (var col = 0; col < immuneColumns.length; col++) {
						var columnOccupied = false;
						for (var e = 0; e < enemies.length; e++) {
							if (enemies[e].cellX === immuneColumns[col] && enemies[e].currentCellY < 8) {
								columnOccupied = true;
								break;
							}
						}
						if (!columnOccupied) {
							availableImmuneColumns.push(immuneColumns[col]);
						}
					}
					// If no columns available, queue the enemy by using the first column
					spawnX = availableImmuneColumns.length > 0 ? availableImmuneColumns[Math.floor(Math.random() * availableImmuneColumns.length)] : immuneColumns[0];
				} else if (waveType === 'tank') {
					// Tank enemies spawn positioning based on wave
					if (currentWave === 4) {
						// Wave 4: Left side
						var tankColumns = [3]; // Left side lane for wave 4 tank enemies
					} else if (currentWave === 8) {
						// Wave 8: Right side
						var tankColumns = [21]; // Right side lane for wave 8 tank enemies
					} else if (currentWave === 11) {
						// Wave 11: Center
						var tankColumns = [12]; // Center lane for wave 11 tank enemies
					} else {
						// Default for other waves: right side of road
						var tankColumns = [21, 22]; // Right edge lanes for tank enemies
					}
					spawnX = tankColumns[i % tankColumns.length]; // Cycle through assigned lanes
				} else {
					// Flying and other enemy types use middle lanes (columns 12-14) avoiding other types
					var flyingColumns = [12, 13, 14];
					var availableColumns = [];
					for (var col = 0; col < flyingColumns.length; col++) {
						var columnOccupied = false;
						// Check if any enemy is already in this column but not yet in view
						for (var e = 0; e < enemies.length; e++) {
							if (enemies[e].cellX === flyingColumns[col] && enemies[e].currentCellY < 8) {
								columnOccupied = true;
								break;
							}
						}
						if (!columnOccupied) {
							availableColumns.push(flyingColumns[col]);
						}
					}
					// If no columns available, use the center column
					spawnX = availableColumns.length > 0 ? availableColumns[Math.floor(Math.random() * availableColumns.length)] : flyingColumns[1];
				}
				// Calculate spawn position with much larger spacing to ensure no visual overlap
				// Convert units to cell units (pixels / 76 pixels per cell)
				var enemySpacing;
				if (waveType === 'fast') {
					// Calculate spacing between horizontal lines (not individual enemies)
					var lineSpacing = 300 / CELL_SIZE; // Reduced spacing between horizontal lines (~3.9 cells)
					var lineNumber = Math.floor(i / 5); // Which horizontal line this enemy belongs to
					enemySpacing = lineSpacing;
					// Position fast enemies in their assigned column without horizontal offset
					enemy.cellX = isBossWave ? 12 : spawnX;
					enemy.cellY = 5; // Position after entry
					enemy.currentCellX = isBossWave ? 12 : spawnX;
					enemy.currentCellY = -1 - lineNumber * enemySpacing; // Each line spawns with line spacing, not individual spacing
				} else {
					if (waveType === 'tank') {
						enemySpacing = 800 / CELL_SIZE; // Reduced spacing for tank enemies with better lane distribution (~10.5 cells)
					} else if (waveType === 'immune') {
						enemySpacing = 400 / CELL_SIZE; // Reduced spacing for immune enemies (~5.3 cells)
					} else {
						enemySpacing = 900 / CELL_SIZE; // Large spacing for other enemies (~11.8 cells)
					}
					var spawnY = -1 - i * enemySpacing; // Each enemy spawns based on enemy type spacing
					enemy.cellX = isBossWave ? 12 : spawnX;
					enemy.cellY = 5; // Position after entry
					enemy.currentCellX = isBossWave ? 12 : spawnX;
					enemy.currentCellY = spawnY;
				}
				enemy.waveNumber = currentWave;
				enemies.push(enemy);
			}
		}
		var currentWaveEnemiesRemaining = false;
		for (var i = 0; i < enemies.length; i++) {
			if (enemies[i].waveNumber === currentWave) {
				currentWaveEnemiesRemaining = true;
				break;
			}
		}
		if (waveSpawned && !currentWaveEnemiesRemaining) {
			waveInProgress = false;
			waveSpawned = false;
		}
	}
	for (var a = enemies.length - 1; a >= 0; a--) {
		var enemy = enemies[a];
		if (enemy.health <= 0) {
			for (var i = 0; i < enemy.bulletsTargetingThis.length; i++) {
				var bullet = enemy.bulletsTargetingThis[i];
				bullet.targetEnemy = null;
			}
			// Remove all flame particles and smoke effects from the map when enemy is destroyed
			for (var flameIndex = game.children.length - 1; flameIndex >= 0; flameIndex--) {
				var child = game.children[flameIndex];
				// Remove EffectIndicator flame effects
				if (child instanceof EffectIndicator) {
					var dx = child.x - enemy.x;
					var dy = child.y - enemy.y;
					var distance = Math.sqrt(dx * dx + dy * dy);
					if (distance <= CELL_SIZE * 3) {
						child.destroy();
					}
				}
				// Remove flame particles (Container objects with flame graphics)
				else if (child.children && child.children.length > 0 && child.children[0].tint !== undefined) {
					var flameGraphics = child.children[0];
					// Check for flame particles by tint colors and properties
					if ((flameGraphics.tint === 0xFF4500 || flameGraphics.tint === 0xFF6600) && flameGraphics.width && flameGraphics.height) {
						// Stop any ongoing tweens and destroy all flame particles
						tween.stop(child);
						child.destroy();
					}
				}
				// Remove flame particles that have damage property (flamethrower particles)
				else if (child.damage !== undefined && child.sourceTowerLevel !== undefined) {
					// Stop any ongoing tweens and destroy flamethrower particles
					tween.stop(child);
					child.destroy();
				}
			}
			// Clean up continuous smoke effect if it exists
			if (enemy.continuousSmokeEffect && enemy.continuousSmokeEffect.parent) {
				// Stop any ongoing smoke particle tweens
				for (var smokeChildIndex = 0; smokeChildIndex < enemy.continuousSmokeEffect.children.length; smokeChildIndex++) {
					var smokeChild = enemy.continuousSmokeEffect.children[smokeChildIndex];
					tween.stop(smokeChild);
				}
				enemy.continuousSmokeEffect.destroy();
				enemy.continuousSmokeEffect = null;
			}
			// Create MASSIVE spectacular death explosion for all enemies except fast enemies (but always for bosses)
			if (enemy.type !== 'fast' || enemy.isBoss) {
				// Stage 1: Initial massive impact flash
				var deathFlash = new EffectIndicator(enemy.x, enemy.y, 'splash');
				deathFlash.children[0].tint = 0xFFFFFF; // Bright white impact flash
				// Scale flash size based on boss status - use Boss asset size for scaling
				var flashScale = enemy.isBoss ? 4.8 : enemy.type === 'tank' ? 2.4 : 2.0; // Boss uses 4.8x (scaled to boss asset size)
				deathFlash.children[0].width = deathFlash.children[0].height = CELL_SIZE * flashScale;
				deathFlash.alpha = 1;
				deathFlash.scaleX = 0.1;
				deathFlash.scaleY = 0.1;
				game.addChild(deathFlash);
				// Ultra-fast bright flash expansion - scale based on enemy type
				var flashExpansionScale = enemy.isBoss ? 5.76 : enemy.type === 'tank' ? 2.88 : 2.4; // Boss uses 5.76x (scaled to boss asset size)
				tween(deathFlash, {
					scaleX: flashExpansionScale,
					scaleY: flashExpansionScale,
					alpha: 0
				}, {
					duration: 80,
					// Faster than weapon explosions for more impact
					easing: tween.easeOut
				});
				// Stage 2: ENORMOUS main death explosion fireball - bigger than any weapon
				var mainDeathExplosion = new EffectIndicator(enemy.x, enemy.y, 'splash');
				// Color based on enemy type
				if (enemy.isBoss) {
					mainDeathExplosion.children[0].tint = 0xFF0000; // Bright red for boss death
				} else if (enemy.type === 'tank') {
					mainDeathExplosion.children[0].tint = 0x8B4513; // Brown for tank enemies
				} else if (enemy.type === 'immune') {
					mainDeathExplosion.children[0].tint = 0xAA0000; // Dark red for immune enemies
				} else if (enemy.isFlying) {
					mainDeathExplosion.children[0].tint = 0xFFFF00; // Yellow for flying enemies
				} else {
					mainDeathExplosion.children[0].tint = 0xFF4500; // Orange for other enemies
				}
				mainDeathExplosion.children[0].width = mainDeathExplosion.children[0].height = CELL_SIZE * (enemy.isBoss ? 3.75 : enemy.type === 'tank' ? 3.0 : 2.5); // ENORMOUS - bigger than tank weapons
				mainDeathExplosion.alpha = 1;
				mainDeathExplosion.scaleX = 0.2;
				mainDeathExplosion.scaleY = 0.2;
				game.addChild(mainDeathExplosion);
				// Dramatic ENORMOUS fireball expansion with intense bounce effect
				tween(mainDeathExplosion, {
					scaleX: enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 2.52 : 2.1,
					// Much bigger than tank weapon explosions
					scaleY: enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 2.52 : 2.1,
					alpha: 0.95
				}, {
					duration: enemy.isBoss ? 400 : 300,
					// Longer for bosses
					easing: tween.bounceOut,
					onFinish: function onFinish() {
						tween(mainDeathExplosion, {
							scaleX: enemy.isBoss ? 4.5 : enemy.type === 'tank' ? 4.32 : 3.6,
							// ENORMOUS final scale - biggest explosions in game
							scaleY: enemy.isBoss ? 4.5 : enemy.type === 'tank' ? 4.32 : 3.6,
							alpha: 0
						}, {
							duration: enemy.isBoss ? 1000 : 800,
							// Very long for dramatic effect
							easing: tween.easeIn,
							onFinish: function onFinish() {
								mainDeathExplosion.destroy();
							}
						});
					}
				});
				// Stage 3: Create ENORMOUS debris particle field - much more particles than weapons
				var particleCount = enemy.isBoss ? 48 : 32; // More particles than tank weapons
				for (var particleIndex = 0; particleIndex < particleCount; particleIndex++) {
					var deathParticle = new EffectIndicator(enemy.x, enemy.y, 'splash');
					// Varied particle colors based on enemy type
					var particleColors;
					if (enemy.isBoss) {
						particleColors = [0xFF0000, 0xFF3300, 0xFF6600, 0xFF9900, 0xFFCC00, 0xFFFF00, 0xFF0033, 0xFF0066];
					} else if (enemy.type === 'tank') {
						particleColors = [0x8B4513, 0xA0522D, 0xD2691E, 0xFF8C00, 0xCD853F, 0xDEB887, 0x654321, 0x8B7355];
					} else if (enemy.type === 'immune') {
						particleColors = [0xAA0000, 0xBB0000, 0xCC0000, 0xDD0000, 0xEE0000, 0xFF0000, 0x990000, 0x880000];
					} else if (enemy.isFlying) {
						particleColors = [0xFFFF00, 0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFFFFFF, 0xFFCC00, 0xFF9900];
					} else {
						particleColors = [0xFF4500, 0xFF6600, 0xFF8800, 0xFFAA00, 0xFF2200, 0xFFCC00, 0xFF3300, 0xFFDD00];
					}
					deathParticle.children[0].tint = particleColors[particleIndex % particleColors.length];
					deathParticle.children[0].width = deathParticle.children[0].height = CELL_SIZE * (enemy.type === 'tank' ? 0.75 + Math.random() * 0.6 : 0.625 + Math.random() * 0.5); // ENORMOUS particles - bigger than tank weapons
					deathParticle.alpha = 1.0;
					deathParticle.scaleX = 0.8 + Math.random() * 0.6;
					deathParticle.scaleY = 0.8 + Math.random() * 0.6;
					// ULTRA-MASSIVE particle scatter distance - bigger than tank weapons
					var particleAngle = particleIndex / particleCount * Math.PI * 2 + (Math.random() - 0.5) * 1.0;
					var particleDistance = CELL_SIZE * (1.5 + Math.random() * 1.0); // ULTRA-far scatter - bigger than tank weapons
					if (enemy.isBoss) {
						particleDistance *= 1.5; // Even further for bosses
					}
					var targetX = enemy.x + Math.cos(particleAngle) * particleDistance;
					var targetY = enemy.y + Math.sin(particleAngle) * particleDistance;
					game.addChild(deathParticle);
					// Animate particles with ENORMOUS final scale
					tween(deathParticle, {
						x: targetX,
						y: targetY,
						scaleX: enemy.type === 'tank' ? 1.8 + Math.random() * 0.72 : 1.5 + Math.random() * 0.6,
						// ENORMOUS final scale - bigger than tank weapons
						scaleY: enemy.type === 'tank' ? 1.8 + Math.random() * 0.72 : 1.5 + Math.random() * 0.6,
						alpha: 0.8
					}, {
						duration: 500 + Math.random() * 400,
						// Longer duration
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(deathParticle, {
								scaleX: 0.2,
								scaleY: 0.2,
								alpha: 0
							}, {
								duration: 600 + Math.random() * 300,
								// Long fade
								easing: tween.easeIn,
								onFinish: function onFinish() {
									deathParticle.destroy();
								}
							});
						}
					});
				}
				// Stage 4: ENORMOUS multiple shockwaves - bigger than tank weapon shockwaves
				var primaryDeathShockwave = new EffectIndicator(enemy.x, enemy.y, 'splash');
				primaryDeathShockwave.children[0].tint = enemy.isBoss ? 0xFF6666 : 0xFFAAAA; // Light red/pink shockwave
				primaryDeathShockwave.children[0].alpha = 0.8;
				primaryDeathShockwave.children[0].width = primaryDeathShockwave.children[0].height = CELL_SIZE * 2.5;
				primaryDeathShockwave.alpha = 1.0;
				game.addChild(primaryDeathShockwave);
				// ENORMOUS expanding death shockwave - bigger than tank weapons
				tween(primaryDeathShockwave, {
					scaleX: enemy.isBoss ? 6.0 : enemy.type === 'tank' ? 5.76 : 4.8,
					// ENORMOUS scale - bigger than tank weapon shockwaves
					scaleY: enemy.isBoss ? 6.0 : enemy.type === 'tank' ? 5.76 : 4.8,
					alpha: 0
				}, {
					duration: enemy.isBoss ? 1200 : 1000,
					// Very long expansion
					easing: tween.easeOut,
					onFinish: function onFinish() {
						primaryDeathShockwave.destroy();
					}
				});
				// Multiple additional death shockwaves for ULTRA-MASSIVE effect
				var shockwaveCount = enemy.isBoss ? 6 : 4; // More shockwaves for bosses
				for (var shockIndex = 1; shockIndex <= shockwaveCount; shockIndex++) {
					var additionalDeathShockwave = new EffectIndicator(enemy.x, enemy.y, 'splash');
					additionalDeathShockwave.children[0].tint = enemy.isBoss ? 0xFF4444 : 0xFF8888; // Darker red shockwave
					additionalDeathShockwave.children[0].alpha = 0.6 - shockIndex * 0.08;
					additionalDeathShockwave.children[0].width = additionalDeathShockwave.children[0].height = CELL_SIZE * (2.5 - shockIndex * 0.2);
					additionalDeathShockwave.alpha = 0.8 - shockIndex * 0.1;
					game.addChild(additionalDeathShockwave);
					// Delayed ENORMOUS death shockwaves
					tween(additionalDeathShockwave, {
						scaleX: (enemy.isBoss ? 6.6 : enemy.type === 'tank' ? 6.48 : 5.4) + shockIndex * (enemy.type === 'tank' ? 0.54 : 0.45),
						// ENORMOUS expanding scale
						scaleY: (enemy.isBoss ? 6.6 : enemy.type === 'tank' ? 6.48 : 5.4) + shockIndex * (enemy.type === 'tank' ? 0.54 : 0.45),
						alpha: 0
					}, {
						duration: (enemy.isBoss ? 1300 : 1100) + shockIndex * 150,
						delay: shockIndex * (enemy.isBoss ? 300 : 250),
						easing: tween.easeOut,
						onFinish: function onFinish() {
							additionalDeathShockwave.destroy();
						}
					});
				}
				// Stage 5: ENORMOUS lingering death smoke cloud - bigger and longer than tank weapons
				var deathSmokeCloud = new EffectIndicator(enemy.x, enemy.y, 'splash');
				deathSmokeCloud.children[0].tint = 0x444444; // Dark gray death smoke
				deathSmokeCloud.children[0].alpha = 0.8;
				deathSmokeCloud.children[0].width = deathSmokeCloud.children[0].height = CELL_SIZE * (enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 3.0 : 2.5); // ENORMOUS smoke cloud
				deathSmokeCloud.alpha = 0;
				deathSmokeCloud.scaleX = 1.5;
				deathSmokeCloud.scaleY = 1.5;
				game.addChild(deathSmokeCloud);
				// Delayed ENORMOUS death smoke appearance
				tween(deathSmokeCloud, {
					alpha: 1.0,
					scaleX: enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 2.88 : 2.4,
					// Bigger initial expansion than tank weapons
					scaleY: enemy.isBoss ? 3.0 : enemy.type === 'tank' ? 2.88 : 2.4
				}, {
					duration: 600,
					delay: 600,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						// Death smoke slowly dissipates over ULTRA-LONG time
						tween(deathSmokeCloud, {
							alpha: 0,
							scaleX: enemy.isBoss ? 5.4 : enemy.type === 'tank' ? 5.76 : 4.8,
							// ENORMOUS final scale - bigger than tank weapons
							scaleY: enemy.isBoss ? 5.4 : enemy.type === 'tank' ? 5.76 : 4.8
						}, {
							duration: enemy.isBoss ? 3000 : 2500,
							// ULTRA-LONG dissipation - longer than tank weapons
							easing: tween.easeIn,
							onFinish: function onFinish() {
								deathSmokeCloud.destroy();
							}
						});
					}
				});
			}
			// Special boss explosion effect and sound
			if (enemy.isBoss) {
				// Create massive boss explosion effect
				var bossExplosion = new EffectIndicator(enemy.x, enemy.y, 'splash');
				bossExplosion.children[0].tint = 0xFFA500; // Orange explosion color
				bossExplosion.children[0].width = bossExplosion.children[0].height = 150; // Large explosion radius
				bossExplosion.alpha = 1.0;
				bossExplosion.scaleX = 0.5;
				bossExplosion.scaleY = 0.5;
				game.addChild(bossExplosion);
				// Multi-stage boss explosion animation
				tween(bossExplosion, {
					scaleX: 3.0,
					scaleY: 3.0,
					alpha: 0.8
				}, {
					duration: 300,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						tween(bossExplosion, {
							scaleX: 5.0,
							scaleY: 5.0,
							alpha: 0
						}, {
							duration: 700,
							easing: tween.easeIn,
							onFinish: function onFinish() {
								bossExplosion.destroy();
							}
						});
					}
				});
				// Play boss explosion sound effect
				try {
					var explosionSound = new Audio();
					explosionSound.src = "https://cdn.pixabay.com/download/audio/2022/03/02/audio_f27e2020ce.mp3?filename=explosion-6075.mp3";
					explosionSound.volume = 1.0;
					explosionSound.play()["catch"](function (error) {
						console.log("Could not play boss explosion sound:", error);
					});
				} catch (error) {
					console.log("Boss explosion sound not available:", error);
				}
			}
			// Boss enemies give more gold and score - significantly increased rewards
			var goldEarned = enemy.isBoss ? Math.floor(200 + (enemy.waveNumber - 1) * 25) : Math.floor(15 + (enemy.waveNumber - 1) * 3);
			var goldIndicator = new GoldIndicator(goldEarned, enemy.x, enemy.y);
			game.addChild(goldIndicator);
			setGold(gold + goldEarned);
			// Give more score for defeating a boss
			var scoreValue = enemy.isBoss ? 100 : 5;
			score += scoreValue;
			// Add a notification for boss defeat
			if (enemy.isBoss) {
				var notification = game.addChild(new Notification("Boss defeated! +" + goldEarned + " gold!"));
				notification.x = 2048 / 2;
				notification.y = grid.height - 150;
			}
			updateUI();
			// Clean up shadow if it's a flying enemy
			if (enemy.isFlying && enemy.shadow) {
				enemyLayerMiddle.removeChild(enemy.shadow);
				enemy.shadow = null;
			}
			// Remove enemy from the appropriate layer
			if (enemy.isFlying) {
				enemyLayerTop.removeChild(enemy);
			} else if (enemy.type === 'fast') {
				enemyLayerBottom.removeChild(enemy);
			} else {
				enemyLayerMiddle.removeChild(enemy);
			}
			enemies.splice(a, 1);
			continue;
		}
		// Only update enemy position every few frames to reduce performance impact
		if (LK.ticks % 2 === 0) {
			if (grid.updateEnemy(enemy)) {
				// Clean up shadow if it's a flying enemy
				if (enemy.isFlying && enemy.shadow) {
					enemyLayerMiddle.removeChild(enemy.shadow);
					enemy.shadow = null;
				}
				// Remove enemy from the appropriate layer
				if (enemy.isFlying) {
					enemyLayerTop.removeChild(enemy);
				} else if (enemy.type === 'fast') {
					enemyLayerBottom.removeChild(enemy);
				} else {
					enemyLayerMiddle.removeChild(enemy);
				}
				enemies.splice(a, 1);
				// BOSS Enemy reached the goal - reduce lives by 100 (100% of 100 total lives)
				if (enemy.isBoss) {
					lives = Math.max(0, lives - 100);
				} else {
					// Each individual enemy reduces lives by 10 (10% of 100 total lives)
					lives = Math.max(0, lives - 10);
				}
				updateUI();
				if (lives <= 0) {
					LK.showGameOver();
				}
			}
		}
	}
	// Only clean bullets every 5 frames to reduce processing
	if (LK.ticks % 5 === 0) {
		for (var i = bullets.length - 1; i >= 0; i--) {
			var bullet = bullets[i];
			if (!bullet.parent) {
				if (bullet.targetEnemy) {
					var targetEnemy = bullet.targetEnemy;
					if (targetEnemy && targetEnemy.bulletsTargetingThis) {
						var bulletIndex = targetEnemy.bulletsTargetingThis.indexOf(bullet);
						if (bulletIndex !== -1) {
							targetEnemy.bulletsTargetingThis.splice(bulletIndex, 1);
						}
					}
				}
				// Clear bullet references
				bullet.targetEnemy = null;
				bullets.splice(i, 1);
			}
		}
	}
	// Check for landmine towers that need to be destroyed after explosion
	for (var i = towers.length - 1; i >= 0; i--) {
		var tower = towers[i];
		if (tower.shouldDestroy) {
			// Remove from grid cells
			var gridX = tower.gridX;
			var gridY = tower.gridY;
			for (var j = 0; j < 2; j++) {
				for (var k = 0; k < 2; k++) {
					var cell = grid.getCell(gridX + j, gridY + k);
					if (cell) {
						// Restore original cell type or default to ground (type 1) if no original type stored
						cell.type = cell.originalType !== undefined ? cell.originalType : 1;
						var towerIndex = cell.towersInRange.indexOf(tower);
						if (towerIndex !== -1) {
							cell.towersInRange.splice(towerIndex, 1);
						}
					}
				}
			}
			// Remove from towers array and tower layer
			towers.splice(i, 1);
			towerLayer.removeChild(tower);
			// Clean up any upgrade menus or range indicators
			if (selectedTower === tower) {
				selectedTower = null;
			}
			// Remove any upgrade menus for this tower
			var upgradeMenus = game.children.filter(function (child) {
				return child instanceof UpgradeMenu && child.tower === tower;
			});
			for (var menuIndex = 0; menuIndex < upgradeMenus.length; menuIndex++) {
				upgradeMenus[menuIndex].destroy();
			}
			// Remove any range indicators for this tower
			for (var rangeIndex = game.children.length - 1; rangeIndex >= 0; rangeIndex--) {
				if (game.children[rangeIndex].isTowerRange && game.children[rangeIndex].tower === tower) {
					game.removeChild(game.children[rangeIndex]);
				}
			}
			// Recalculate pathfinding
			grid.pathFind();
			grid.renderDebug();
		}
	}
	if (towerPreview.visible) {
		towerPreview.checkPlacement();
	}
	if (currentWave >= totalWaves && enemies.length === 0 && !waveInProgress) {
		LK.showYouWin();
	}
};
:quality(85)/https://cdn.frvr.ai/682dc1755a2fa73fef156d33.png%3F3) 
 White circle with black outline. Blue background.. In-Game asset. 2d. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/687d3fd36abc931f9db9aa90.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/687d406ceec7e75544ba1ab3.png%3F3) 
 Light grey asphalt texture. Top view
:quality(85)/https://cdn.frvr.ai/687e9f0b3ebf2411a695114d.png%3F3) 
 Armed off-road vehicle with camouflage livery. Top view.
:quality(85)/https://cdn.frvr.ai/687ea50f3ebf2411a69511c9.png%3F3) 
 Military tank, top view
:quality(85)/https://cdn.frvr.ai/6881f40f9b83bc54a2df1380.png%3F3) 
 Army Soldier with gun. Topview.
:quality(85)/https://cdn.frvr.ai/6881ff199b83bc54a2df1423.png%3F3) 
 Bomber Drone with spinning rotors, from top view.
:quality(85)/https://cdn.frvr.ai/6882ad3170095fe7e2196b3d.png%3F3) 
 Army box,but no text needed on image. top view
:quality(85)/https://cdn.frvr.ai/6883ec3235de2538e540f1f4.png%3F3) 
 landmine from top view
:quality(85)/https://cdn.frvr.ai/6883f4c135de2538e540f21a.png%3F3) 
 Sniper man from top view
:quality(85)/https://cdn.frvr.ai/68840eb635de2538e540f2a0.png%3F3) 
 Rocket launcher cannon, from top view.
:quality(85)/https://cdn.frvr.ai/68848b8f14f1f314492ce450.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6884920014f1f314492ce48c.png%3F3) 
 Army soldier laying with machine gun, top view from back
:quality(85)/https://cdn.frvr.ai/6884e05e6a8f4f077923be1a.png%3F3) 
 Missile, top view
:quality(85)/https://cdn.frvr.ai/6887ef3a6be67a388fbb75ad.png%3F3) 
 :quality(85)/https://cdn.frvr.ai/6887efbe2e5ea7660f3b9778.png%3F3)