/**** 
* 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();
	}
};
 White circle with black outline. Blue background.. In-Game asset. 2d. High contrast. No shadows
 
 Light grey asphalt texture. Top view
 Armed off-road vehicle with camouflage livery. Top view.
 Military tank, top view
 Army Soldier with gun. Topview.
 Bomber Drone with spinning rotors, from top view.
 Army box,but no text needed on image. top view
 landmine from top view
 Sniper man from top view
 Rocket launcher cannon, from top view.
 
 Army soldier laying with machine gun, top view from back
 Missile, top view