/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var CanonShell = Container.expand(function () {
	var self = Container.call(this);
	self.speed = 3.2; // 4x normal zombie speed (0.8 * 4)
	self.damage = 20;
	self.hasExploded = false;
	self.hasReachedColumn6 = false;
	self.gridY = 0;
	var graphics = self.attachAsset('canonShell', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		// Move left towards plants
		self.x -= self.speed;
		// Check if reached column 3
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		if (cellX <= 2 && !self.hasReachedColumn6) {
			self.hasReachedColumn6 = true;
			self.explode();
			return;
		}
		// Check collision with plants
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		if (cellX >= 0 && cellX < gridCols && plants[self.gridY] && plants[self.gridY][cellX]) {
			var plant = plants[self.gridY][cellX];
			if (self.intersects(plant)) {
				plant.takeDamage(self.damage);
				self.explode();
				return;
			}
		}
		// Remove if goes off screen
		if (self.x < -100) {
			self.removeFromGame();
		}
	};
	self.explode = function () {
		if (self.hasExploded) {
			return;
		}
		self.hasExploded = true;
		// Create explosion effect
		var explosion = LK.getAsset('explosion', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y,
			scaleX: 1.5,
			scaleY: 1.5
		});
		game.addChild(explosion);
		// Animate explosion and remove it
		tween(explosion, {
			scaleX: 0.1,
			scaleY: 0.1,
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		// Transform shell into normal zombidito at current position
		var zombidito = new Zombidito();
		zombidito.x = self.x;
		zombidito.y = self.y;
		zombidito.gridY = self.gridY;
		enemies.push(zombidito);
		game.addChild(zombidito);
		// Remove shell
		self.removeFromGame();
	};
	self.removeFromGame = function () {
		for (var i = 0; i < canonShells.length; i++) {
			if (canonShells[i] === self) {
				canonShells.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	return self;
});
var Lawnmower = Container.expand(function (row) {
	var self = Container.call(this);
	self.gridY = row;
	self.speed = 0;
	self.isActivated = false;
	self.x = gridStartX - 100;
	self.y = gridStartY + row * cellSize;
	var graphics = self.attachAsset('lawnmower', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function () {
		if (!self.isActivated) {
			self.isActivated = true;
			self.speed = 6.4;
		}
	};
	self.update = function () {
		if (self.isActivated) {
			self.x += self.speed;
			// Check collision with zombies
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				if (enemy.gridY === self.gridY && self.intersects(enemy)) {
					enemy.die();
					// Count as player kill for score tracking
					enemiesKilled++;
				}
			}
			// Remove lawnmower when it reaches right edge
			if (self.x > 2148) {
				self.removeFromGame();
			}
		}
	};
	self.removeFromGame = function () {
		for (var i = 0; i < lawnmowers.length; i++) {
			if (lawnmowers[i] === self) {
				lawnmowers.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	return self;
});
var PlantBase = Container.expand(function (plantType) {
	var self = Container.call(this);
	self.plantType = plantType;
	self.health = 100;
	self.maxHealth = 100;
	self.cost = 50;
	self.shootTimer = 0;
	self.shootDelay = 72;
	self.gridX = 0;
	self.gridY = 0;
	self.level = 1;
	var graphics = self.attachAsset(plantType, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xFF0000, 200);
		if (self.health <= 0) {
			self.die();
		}
	};
	self.die = function () {
		// Clean up projectile tracking for this plant
		var plantId = self.gridX + '_' + self.gridY;
		if (plantProjectileCount[plantId]) {
			delete plantProjectileCount[plantId];
		}
		plants[self.gridY][self.gridX] = null;
		self.destroy();
	};
	return self;
});
var Wallnut = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'wallnut');
	self.cost = 50;
	self.health = 300;
	self.maxHealth = 300;
	self.isDamaged = false;
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		originalTakeDamage(damage);
		// Check if wallnut should switch to damaged appearance
		if (self.health < 150 && !self.isDamaged) {
			self.isDamaged = true;
			// Remove current graphics and add damaged version
			self.removeChild(self.children[0]);
			var damagedGraphics = self.attachAsset('wallnut_damaged', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	return self;
});
var Sunflower = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'sunflower');
	self.cost = 50;
	self.sunTimer = 0;
	self.update = function () {
		self.sunTimer++;
		if (self.sunTimer >= 1080) {
			// 18 seconds
			var sun = new Sun(self.x, self.y - 60);
			suns.push(sun);
			game.addChild(sun);
			self.sunTimer = 0;
			LK.effects.flashObject(self, 0xFFFF00, 300);
		}
	};
	return self;
});
var SnowPea = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'snowpea');
	self.cost = 175;
	self.health = 120;
	self.maxHealth = 120;
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			var target = self.findTarget();
			if (target) {
				self.shoot(target);
				self.shootTimer = 0;
			}
		}
	};
	self.findTarget = function () {
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && enemy.x > self.x) {
				return enemy;
			}
		}
		return null;
	};
	self.shoot = function (target) {
		var plantId = self.gridX + '_' + self.gridY; // Unique plant identifier
		var pea = createProjectile('snowshot', self.x, self.y, 5.12, 25 * self.level, plantId); // 6.4 * 0.8 = 5.12 (20% slower)
		if (pea) {
			LK.getSound('shoot').play();
		}
	};
	return self;
});
var Repetidora = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'repetidora');
	self.cost = 200;
	self.isTrackingFirstPea = false;
	self.firstPea = null;
	self.firstPeaStartX = 0;
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			var target = self.findTarget();
			if (target && !self.isTrackingFirstPea) {
				var firstPea = self.shoot(target);
				if (firstPea) {
					self.firstPea = firstPea;
					self.firstPeaStartX = firstPea.x;
					self.isTrackingFirstPea = true;
				}
				self.shootTimer = 0;
			}
		}
		// Handle second pea timing based on first pea position
		if (self.isTrackingFirstPea && self.firstPea) {
			// Check if first pea has advanced half a cell (72 pixels)
			if (self.firstPea.x >= self.firstPeaStartX + 72) {
				var target = self.findTarget();
				if (target) {
					self.shoot(target);
				}
				// Stop tracking to prevent lag
				self.isTrackingFirstPea = false;
				self.firstPea = null;
			}
			// Also stop tracking if first pea no longer exists
			else if (!self.firstPea.parent) {
				self.isTrackingFirstPea = false;
				self.firstPea = null;
			}
		}
	};
	self.findTarget = function () {
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && enemy.x > self.x) {
				return enemy;
			}
		}
		return null;
	};
	self.shoot = function (target) {
		var plantId = self.gridX + '_' + self.gridY; // Unique plant identifier
		var pea = createProjectile('pea', self.x, self.y, 8.64, 20 * self.level, plantId);
		if (pea) {
			LK.getSound('shoot').play();
		}
		return pea; // Return the pea for tracking
	};
	return self;
});
var Rapaz = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'rapaz');
	self.cost = 325;
	self.health = 425;
	self.maxHealth = 425;
	self.damageTimer = 0; // Timer for dealing damage to high-HP zombies
	self.cooldownTimer = 0; // Timer for cooldown after killing zombie <400 HP
	self.isOnCooldown = false; // Track if rapaz is on cooldown
	self.targetZombie = null; // Track zombie being consumed
	var graphics = self.children[0]; // Reference to graphics for color changes
	self.update = function () {
		// Handle cooldown timer
		if (self.isOnCooldown && self.cooldownTimer > 0) {
			self.cooldownTimer--;
			if (self.cooldownTimer === 0) {
				// End cooldown - restore normal color
				self.isOnCooldown = false;
				tween(graphics, {
					tint: 0xFFFFFF
				}, {
					duration: 200,
					easing: tween.easeOut
				});
			}
			return; // Don't attack while on cooldown
		}
		self.damageTimer++;
		// Check every 60 ticks (1 second) for zombies to attack
		if (self.damageTimer >= 60) {
			// Skip if rapaz is already consuming a zombie
			if (self.targetZombie && self.targetZombie.parent) {
				return; // Don't attack while already consuming
			}
			var targetZombies = self.findTargetZombies();
			for (var i = 0; i < targetZombies.length; i++) {
				var zombie = targetZombies[i];
				// Skip zombies already being consumed
				if (zombie.beingConsumed) {
					continue;
				}
				if (zombie.health < 400) {
					// Mark zombie as being consumed and make it move toward rapaz
					zombie.beingConsumed = true;
					zombie.consumingPlant = self;
					self.targetZombie = zombie;
					zombie.speed = 0.8 * 4; // 4x normal zombie speed
					zombie.damage = 0; // Stop attacking while being consumed
					// Start continuous rotation while moving
					zombie.rotationSpeed = 0.15; // Rotation speed per frame
					break; // Only consume one zombie per cycle
				} else {
					// Deal 25 damage to zombie with ≥400 HP
					zombie.takeDamage(25);
					// Add flashing effect to zombie when taking damage from rapaz
					tween(zombie, {
						tint: 0xFF0000
					}, {
						duration: 100,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(zombie, {
								tint: 0xFFFFFF
							}, {
								duration: 100,
								easing: tween.easeOut
							});
						}
					});
					// Check if zombie now has <400 HP and should be consumed
					if (zombie.health < 400 && zombie.parent) {
						// Mark zombie as being consumed
						zombie.beingConsumed = true;
						zombie.consumingPlant = self;
						self.targetZombie = zombie;
						zombie.speed = 0.8 * 4; // 4x normal zombie speed
						zombie.damage = 0; // Stop attacking while being consumed
						// Start continuous rotation while moving
						zombie.rotationSpeed = 0.15; // Rotation speed per frame
						break; // Only consume one zombie per cycle
					}
				}
			}
			self.damageTimer = 0;
		}
		// Check if target zombie has collided with rapaz
		if (self.targetZombie && self.targetZombie.parent) {
			// Check for collision between rapaz and consuming zombie
			if (self.intersects(self.targetZombie)) {
				// Zombie reached rapaz - consume it immediately
				// First remove zombie from enemies array to prevent other systems from accessing it
				for (var i = 0; i < enemies.length; i++) {
					if (enemies[i] === self.targetZombie) {
						enemies.splice(i, 1);
						break;
					}
				}
				// Destroy the zombie
				self.targetZombie.destroy();
				enemiesKilled++;
				self.targetZombie = null;
				// Start 10 second cooldown and gray out the plant
				self.isOnCooldown = true;
				self.cooldownTimer = 600; // 10 seconds at 60fps
				tween(graphics, {
					tint: 0x888888 // Gray tint
				}, {
					duration: 200,
					easing: tween.easeOut
				});
			}
		} else if (self.targetZombie && !self.targetZombie.parent) {
			// Target zombie was destroyed, clear reference
			self.targetZombie = null;
		}
	};
	self.findTargetZombies = function () {
		var targets = [];
		// Check current cell and seven cells in front (8 total cells)
		for (var checkX = self.gridX; checkX <= self.gridX + 7 && checkX < gridCols; checkX++) {
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				var enemyGridX = Math.floor((enemy.x - gridStartX + cellSize / 2) / cellSize);
				// Check if zombie is in the target cell
				if (enemy.gridY === self.gridY && enemyGridX === checkX) {
					targets.push(enemy);
				}
			}
		}
		return targets;
	};
	// Override die to clean up consumed zombie
	var originalDie = self.die;
	self.die = function () {
		// If consuming a zombie, release it from consumption
		if (self.targetZombie && self.targetZombie.parent) {
			self.targetZombie.beingConsumed = false;
			self.targetZombie.consumingPlant = null;
			self.targetZombie.speed = self.targetZombie.originalSpeed;
			self.targetZombie.damage = 25; // Restore normal damage
			self.targetZombie.rotationSpeed = 0; // Stop continuous rotation
			if (self.targetZombie.children[0]) {
				self.targetZombie.children[0].rotation = 0; // Reset rotation
			}
		}
		originalDie();
	};
	return self;
});
var Plantorcha = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'plantorcha');
	self.cost = 175;
	self.health = 300;
	self.maxHealth = 300;
	// Plantorcha doesn't shoot - it only converts projectiles
	self.update = function () {
		// No shooting behavior - just exists to convert projectiles
	};
	return self;
});
var Petacereza = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'petacereza');
	self.cost = 150;
	self.health = 1; // Very low health since it explodes
	self.maxHealth = 1;
	self.isArmed = false; // Zombies ignore it until armed
	self.armTimer = 90; // 1.5 seconds at 60fps
	self.update = function () {
		if (self.armTimer > 0) {
			self.armTimer--;
			if (self.armTimer === 0) {
				// Arm the petacereza and explode
				self.isArmed = true;
				self.explode();
			}
		}
	};
	self.explode = function () {
		// Create explosion effect
		var explosion = LK.getAsset('explosion', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y,
			scaleX: 3,
			// Larger explosion for 3x3 area
			scaleY: 3
		});
		game.addChild(explosion);
		// Animate explosion and remove it
		tween(explosion, {
			scaleX: 0.1,
			scaleY: 0.1,
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		// Damage all zombies in 3x3 grid area around petacereza
		var centerGridX = self.gridX;
		var centerGridY = self.gridY;
		var damagedEnemies = []; // Track enemies to damage
		// First pass: identify all enemies in range
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			var enemyGridX = Math.floor((enemy.x - gridStartX + cellSize / 2) / cellSize);
			var enemyGridY = enemy.gridY;
			// Check if enemy is within 3x3 area (center ± 1 in both directions)
			var deltaX = Math.abs(enemyGridX - centerGridX);
			var deltaY = Math.abs(enemyGridY - centerGridY);
			if (deltaX <= 1 && deltaY <= 1) {
				damagedEnemies.push(enemy);
			}
		}
		// Second pass: damage all identified enemies
		for (var j = 0; j < damagedEnemies.length; j++) {
			damagedEnemies[j].takeDamage(325);
		}
		// Remove petacereza after explosion
		self.die();
	};
	// Override getPlantInFront for zombies to ignore unarmed petacereza
	self.shouldBeIgnoredByZombies = function () {
		return !self.isArmed;
	};
	return self;
});
var Peashooter = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'peashooter');
	self.cost = 100;
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			var target = self.findTarget();
			if (target) {
				self.shoot(target);
				self.shootTimer = 0;
			}
		}
	};
	self.findTarget = function () {
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && enemy.x > self.x) {
				return enemy;
			}
		}
		return null;
	};
	self.shoot = function (target) {
		var plantId = self.gridX + '_' + self.gridY; // Unique plant identifier
		var pea = createProjectile('pea', self.x, self.y, 6.4, 20 * self.level, plantId);
		if (pea) {
			LK.getSound('shoot').play();
		}
	};
	return self;
});
var NuezPrimitiva = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'nuezPrimitiva');
	self.cost = 125;
	self.health = 625;
	self.maxHealth = 625;
	self.hasChangedToWallnut = false;
	self.hasChangedToDamaged = false;
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		originalTakeDamage(damage);
		// Check if should switch to normal wallnut appearance (< 300 hp)
		if (self.health < 300 && !self.hasChangedToWallnut) {
			self.hasChangedToWallnut = true;
			// Remove current graphics and add wallnut version
			self.removeChild(self.children[0]);
			var wallnutGraphics = self.attachAsset('wallnut', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		// Check if should switch to damaged wallnut appearance (< 150 hp)  
		else if (self.health < 150 && !self.hasChangedToDamaged) {
			self.hasChangedToDamaged = true;
			// Remove current graphics and add damaged version
			self.removeChild(self.children[0]);
			var damagedGraphics = self.attachAsset('wallnut_damaged', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	return self;
});
var Fireshot = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'fireshot');
	self.cost = 100;
	self.health = 150;
	self.maxHealth = 150;
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			var target = self.findTarget();
			if (target) {
				self.shoot(target);
				self.shootTimer = 0;
			}
		}
	};
	self.findTarget = function () {
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && enemy.x > self.x) {
				return enemy;
			}
		}
		return null;
	};
	self.shoot = function (target) {
		var plantId = self.gridX + '_' + self.gridY; // Unique plant identifier
		// Calculate damage based on target type
		var damage = 35 * self.level;
		if (target.zombieType === 'cone_zombie' || target.zombieType === 'bucket_zombie') {
			damage = 50 * self.level;
		}
		var pea = createProjectile('shotfire', self.x, self.y, 6.4, damage, plantId);
		if (pea) {
			LK.getSound('shoot').play();
		}
	};
	return self;
});
var Carnivora = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'carnivora');
	self.cost = 25;
	self.health = 300;
	self.maxHealth = 300;
	self.damageTimer = 0; // Timer for dealing damage to high-HP zombies
	self.cooldownTimer = 0; // Timer for cooldown after killing zombie <400 HP
	self.isOnCooldown = false; // Track if carnivora is on cooldown
	var graphics = self.children[0]; // Reference to graphics for color changes
	self.update = function () {
		// Handle cooldown timer
		if (self.isOnCooldown && self.cooldownTimer > 0) {
			self.cooldownTimer--;
			if (self.cooldownTimer === 0) {
				// End cooldown - restore normal color
				self.isOnCooldown = false;
				tween(graphics, {
					tint: 0xFFFFFF
				}, {
					duration: 200,
					easing: tween.easeOut
				});
			}
			return; // Don't attack while on cooldown
		}
		self.damageTimer++;
		// Check every 60 ticks (1 second) for zombies to attack
		if (self.damageTimer >= 60) {
			var targetZombies = self.findTargetZombies();
			for (var i = 0; i < targetZombies.length; i++) {
				var zombie = targetZombies[i];
				if (zombie.health < 400) {
					// Instantly kill zombie with <400 HP
					zombie.die();
					enemiesKilled++;
					// Start 15 second cooldown and gray out the plant
					self.isOnCooldown = true;
					self.cooldownTimer = 900; // 15 seconds at 60fps
					tween(graphics, {
						tint: 0x888888 // Gray tint
					}, {
						duration: 200,
						easing: tween.easeOut
					});
					break; // Only kill one zombie per cycle
				} else {
					// Deal 25 damage to zombie with ≥400 HP
					zombie.takeDamage(25);
					// Add flashing effect to zombie when taking damage from carnivora
					tween(zombie, {
						tint: 0xFF0000
					}, {
						duration: 100,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(zombie, {
								tint: 0xFFFFFF
							}, {
								duration: 100,
								easing: tween.easeOut
							});
						}
					});
					// Check if zombie now has <400 HP and kill it
					if (zombie.health < 400 && zombie.parent) {
						zombie.die();
						enemiesKilled++;
						// Start 15 second cooldown and gray out the plant
						self.isOnCooldown = true;
						self.cooldownTimer = 900; // 15 seconds at 60fps
						tween(graphics, {
							tint: 0x888888 // Gray tint
						}, {
							duration: 200,
							easing: tween.easeOut
						});
						break; // Only kill one zombie per cycle
					}
				}
			}
			self.damageTimer = 0;
		}
	};
	self.findTargetZombies = function () {
		var targets = [];
		// Check current cell and cell in front
		for (var checkX = self.gridX; checkX <= self.gridX + 1 && checkX < gridCols; checkX++) {
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				var enemyGridX = Math.floor((enemy.x - gridStartX + cellSize / 2) / cellSize);
				// Check if zombie is in the target cell
				if (enemy.gridY === self.gridY && enemyGridX === checkX) {
					targets.push(enemy);
				}
			}
		}
		return targets;
	};
	return self;
});
var Birasol = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'birasol');
	self.cost = 125;
	self.health = 125;
	self.maxHealth = 125;
	self.sunTimer = 0;
	self.update = function () {
		self.sunTimer++;
		if (self.sunTimer >= 900) {
			// 15 seconds (900 ticks at 60fps)
			var sun1 = new Sun(self.x - 30, self.y - 60);
			var sun2 = new Sun(self.x + 30, self.y - 60);
			suns.push(sun1);
			suns.push(sun2);
			game.addChild(sun1);
			game.addChild(sun2);
			self.sunTimer = 0;
			LK.effects.flashObject(self, 0xFFFF00, 300);
		}
	};
	return self;
});
var Projectile = Container.expand(function (type, startX, startY, speed, damage) {
	var self = Container.call(this);
	self.speed = speed;
	self.damage = damage;
	self.x = startX;
	self.y = startY;
	self.type = type;
	self.gridY = Math.floor((startY - gridStartY + cellSize / 2) / cellSize);
	self.ownerId = null; // Plant that owns this projectile
	var graphics = self.attachAsset(type, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		self.x += self.speed;
		if (self.x > 2048) {
			self.removeFromGame();
			return;
		}
		// Check collision with plantorcha to convert pea to fire projectile
		if (self.type === 'pea') {
			var projectileGridX = Math.floor((self.x - gridStartX + cellSize / 2) / cellSize);
			var projectileGridY = self.gridY;
			if (projectileGridX >= 0 && projectileGridX < gridCols && projectileGridY >= 0 && projectileGridY < gridRows) {
				var plantInCell = plants[projectileGridY][projectileGridX];
				if (plantInCell && plantInCell.plantType === 'plantorcha' && self.intersects(plantInCell)) {
					// Convert pea to shotfire and add 10 damage
					self.removeChild(self.children[0]);
					var fireGraphics = self.attachAsset('shotfire', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					self.type = 'shotfire';
					self.damage += 10;
					// Continue with normal movement
				}
			}
		}
		// Only check collisions with zombies in same row and within 100px range
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && Math.abs(enemy.x - self.x) <= 100 && self.intersects(enemy)) {
				// Skip damage if zombie is being consumed by rapaz unless projectile is from rapaz
				if (!enemy.beingConsumed || enemy.beingConsumed && enemy.consumingPlant && self.ownerId && self.ownerId.includes(enemy.consumingPlant.gridX + '_' + enemy.consumingPlant.gridY)) {
					enemy.takeDamage(self.damage);
					// Apply ice effect if this is a snowshot
					if (self.type === 'snowshot') {
						enemy.applyIceEffect();
					}
					self.removeFromGame();
					break;
				}
			}
		}
	};
	self.removeFromGame = function () {
		// Decrease projectile count for the plant that owns this projectile
		if (self.ownerId && plantProjectileCount[self.ownerId]) {
			plantProjectileCount[self.ownerId]--;
		}
		for (var i = 0; i < projectiles.length; i++) {
			if (projectiles[i] === self) {
				projectiles.splice(i, 1);
				break;
			}
		}
		// Return to pool instead of destroying
		self.returnToPool();
	};
	self.returnToPool = function () {
		if (projectilePool.length < maxPoolSize) {
			self.removeChildren();
			if (self.parent) {
				self.parent.removeChild(self);
			}
			projectilePool.push(self);
		} else {
			self.destroy();
		}
	};
	return self;
});
var SlowProjectile = Projectile.expand(function (type, startX, startY, speed, damage) {
	var self = Projectile.call(this, type, startX, startY, speed, damage);
	var originalUpdate = self.update;
	self.update = function () {
		originalUpdate();
		// Only check collisions with zombies in same row and within 100px range
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && Math.abs(enemy.x - self.x) <= 100 && self.intersects(enemy)) {
				enemy.applySlowEffect();
				break;
			}
		}
	};
	return self;
});
var Sun = Container.expand(function (x, y) {
	var self = Container.call(this);
	self.x = x;
	self.y = y;
	self.value = 25;
	self.collectTimer = 0;
	self.isBeingAttracted = false;
	self.attractedBy = null;
	var graphics = self.attachAsset('sun', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.down = function (x, y, obj) {
		// If being attracted by zombie sol, stop the attraction
		if (self.isBeingAttracted && self.attractedBy) {
			tween.stop(self);
			self.attractedBy.targetSun = null;
			self.attractedBy.isAttractingSun = false;
			self.attractedBy.speed = self.attractedBy.originalSpeed;
			self.isBeingAttracted = false;
			self.attractedBy = null;
		}
		sunPoints += self.value;
		updateSunDisplay();
		self.collect();
	};
	self.collect = function () {
		// Clean up attraction if being collected
		if (self.isBeingAttracted && self.attractedBy) {
			tween.stop(self);
			self.attractedBy.targetSun = null;
			self.attractedBy.isAttractingSun = false;
			self.attractedBy.speed = self.attractedBy.originalSpeed;
		}
		for (var i = 0; i < suns.length; i++) {
			if (suns[i] === self) {
				suns.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	self.update = function () {
		self.collectTimer++;
		if (self.collectTimer > 720) {
			// 12 seconds timeout
			self.collect();
		}
	};
	return self;
});
var ZombieBase = Container.expand(function (zombieType) {
	var self = Container.call(this);
	self.zombieType = zombieType;
	self.health = 190;
	self.maxHealth = 190;
	self.speed = 0.8;
	self.damage = 25;
	self.gridY = 0;
	self.attackTimer = 0;
	self.slowTimer = 0;
	self.iceTimer = 0;
	self.isIced = false;
	self.originalSpeed = self.speed;
	self.beingConsumed = false; // Track if zombie is being consumed by rapaz
	self.consumingPlant = null; // Reference to the plant consuming this zombie
	var graphics = self.attachAsset(zombieType, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xFF0000, 200);
		LK.getSound('zombie_hit').play();
		if (self.health <= 0) {
			self.die();
		}
	};
	self.die = function () {
		// Check if this is Zombiestein being killed
		if (self.zombieType === 'zombiestein') {
			zombiesteinAlive = false;
		}
		for (var i = 0; i < enemies.length; i++) {
			if (enemies[i] === self) {
				enemies.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	self.applySlowEffect = function () {
		self.slowTimer = 180;
		self.speed = self.originalSpeed * 0.5;
		graphics.tint = 0x81C784;
	};
	self.applyIceEffect = function () {
		// Set ice effect timer for 3 seconds if not already active or extend it
		self.iceTimer = 180; // 3 seconds at 60fps
		self.speed = self.originalSpeed * 0.8; // 20% slower
		// Only start the visual tween if not already iced
		if (!self.isIced) {
			self.isIced = true;
			// Calculate 35% blue tint (mix current color with blue)
			var blueColor = 0x5555FF; // Blue color
			// Apply blue tint
			tween(graphics, {
				tint: blueColor
			}, {
				duration: 100,
				easing: tween.easeOut
			});
		}
	};
	self.update = function () {
		// Handle being consumed by rapaz - move toward the consuming plant
		if (self.beingConsumed && self.consumingPlant) {
			// Apply continuous rotation while moving
			if (self.rotationSpeed && self.children[0]) {
				self.children[0].rotation += self.rotationSpeed;
			}
			// Move toward the rapaz plant position
			var targetX = self.consumingPlant.x;
			if (self.x > targetX) {
				self.x -= self.speed; // Move left toward rapaz
			} else {
				// Reached rapaz position, let rapaz handle consumption
			}
			return; // Skip normal update logic when being consumed
		}
		if (self.slowTimer > 0) {
			self.slowTimer--;
			if (self.slowTimer === 0) {
				self.speed = self.originalSpeed;
				graphics.tint = 0xFFFFFF;
			}
		}
		// Handle ice effect timer
		if (self.iceTimer > 0) {
			self.iceTimer--;
			if (self.iceTimer === 0) {
				// Ice effect ends
				self.isIced = false;
				self.speed = self.originalSpeed;
				// Return to normal color
				tween(graphics, {
					tint: 0xFFFFFF
				}, {
					duration: 200,
					easing: tween.easeOut
				});
			}
		}
		var plantInFront = self.getPlantInFront();
		if (plantInFront) {
			self.attackTimer++;
			if (self.attackTimer >= 72) {
				plantInFront.takeDamage(self.damage);
				self.attackTimer = 0;
			}
		} else {
			self.x -= self.speed;
			// Check if zombie reached left screen edge
			if (self.x < 0) {
				LK.effects.flashScreen(0xFF0000, 1000);
				LK.showGameOver();
				return;
			}
			// Check collision with lawnmower
			for (var i = 0; i < lawnmowers.length; i++) {
				var lawnmower = lawnmowers[i];
				if (lawnmower.gridY === self.gridY && self.x <= lawnmower.x + 60 && !lawnmower.isActivated) {
					lawnmower.activate();
				}
			}
		}
	};
	self.getPlantInFront = function () {
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		if (cellX >= 0 && cellX < gridCols && plants[self.gridY] && plants[self.gridY][cellX]) {
			var plant = plants[self.gridY][cellX];
			// Check if this is an unarmed petacereza that should be ignored
			if (plant.shouldBeIgnoredByZombies && plant.shouldBeIgnoredByZombies()) {
				return null; // Ignore unarmed petacereza
			}
			return plant;
		}
		return null;
	};
	return self;
});
var Zombiestein = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombiestein');
	self.health = 2250;
	self.maxHealth = 2250;
	self.speed = 0.414; // 10% slower than 0.46
	self.originalSpeed = 0.414;
	self.damage = 500; // 500 damage per second
	self.isSummoning = false;
	self.hasSpawnedZombidito = false;
	self.originalUpdate = self.update;
	self.update = function () {
		// Check if health is below 1500 and hasn't spawned Zombidito yet
		if (self.health < 1500 && !self.hasSpawnedZombidito && !self.isSummoning) {
			self.isSummoning = true;
			self.speed = 0; // Stop moving completely
			// Wait 1.5 seconds then spawn Zombidito
			LK.setTimeout(function () {
				// Resume movement
				self.speed = self.originalSpeed;
				self.isSummoning = false;
				self.hasSpawnedZombidito = true;
				// Calculate position 3 cells ahead (in front of Zombiestein)
				var spawnX = self.x - 3 * cellSize;
				var spawnY = self.y;
				// Create Zombidito with explosion effect
				var zombidito = new Zombidito();
				zombidito.x = spawnX;
				zombidito.y = spawnY;
				zombidito.gridY = self.gridY;
				enemies.push(zombidito);
				game.addChild(zombidito);
				// Create explosion effect like miner zombie
				var explosion = LK.getAsset('explosion', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: spawnX,
					y: spawnY,
					scaleX: 2,
					scaleY: 2
				});
				game.addChild(explosion);
				// Animate explosion and remove it
				tween(explosion, {
					scaleX: 0.1,
					scaleY: 0.1,
					alpha: 0
				}, {
					duration: 800,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						explosion.destroy();
					}
				});
			}, 1500);
		}
		// Call original update only if not summoning (stopped)
		if (!self.isSummoning) {
			self.originalUpdate();
		}
	};
	return self;
});
var ZombieSarcofago = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombie_sarcofago');
	self.health = 500;
	self.maxHealth = 500;
	self.speed = 0.6; // Slightly slower than normal zombie
	self.originalSpeed = 0.6;
	// Override die function to spawn normal zombie at death location
	var originalDie = self.die;
	self.die = function () {
		// Create spawned zombie at current position with 2x speed and 225 HP
		var spawnedZombie = new SpawnedZombie();
		spawnedZombie.x = self.x;
		spawnedZombie.y = self.y;
		spawnedZombie.gridY = self.gridY;
		enemies.push(spawnedZombie);
		game.addChild(spawnedZombie);
		// Call original die function
		originalDie();
	};
	return self;
});
var ZombieRa = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombieRa');
	self.health = 190;
	self.maxHealth = 190;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.isAttractingSun = false;
	self.targetSun = null;
	// Override update to handle sun attraction
	var originalUpdate = self.update;
	self.update = function () {
		// Look for uncollected suns to attract
		if (!self.isAttractingSun && !self.targetSun) {
			var closestSun = null;
			var closestDistance = Infinity;
			// Find the closest sun that isn't already being attracted
			for (var i = 0; i < suns.length; i++) {
				var sun = suns[i];
				if (!sun.isBeingAttracted) {
					var distance = Math.abs(sun.x - self.x) + Math.abs(sun.y - self.y);
					if (distance < closestDistance) {
						closestDistance = distance;
						closestSun = sun;
					}
				}
			}
			// If found a sun, start attracting it
			if (closestSun) {
				self.targetSun = closestSun;
				self.isAttractingSun = true;
				self.speed = 0; // Stop moving while attracting
				// Mark sun as being attracted so other zombie sols don't target it
				closestSun.isBeingAttracted = true;
				closestSun.attractedBy = self;
				// Start tweening sun towards zombie
				tween(closestSun, {
					x: self.x,
					y: self.y
				}, {
					duration: closestDistance / 0.6,
					// Speed reduced by 300% (was 2.4, now 0.6 = 4x slower)
					easing: tween.linear,
					onFinish: function onFinish() {
						// Sun reached zombie - consume it
						if (self.targetSun && self.targetSun.parent) {
							self.consumeSun();
						}
					}
				});
			}
		}
		// Check if sun reached zombie (collision detection)
		if (self.isAttractingSun && self.targetSun && self.targetSun.parent) {
			var distance = Math.abs(self.targetSun.x - self.x) + Math.abs(self.targetSun.y - self.y);
			if (distance < 50) {
				// Close enough to consume
				self.consumeSun();
			}
		}
		// Call original update only if not attracting sun
		if (!self.isAttractingSun) {
			originalUpdate();
		}
	};
	self.consumeSun = function () {
		if (self.targetSun && self.targetSun.parent) {
			// Remove sun from game without giving points to player
			for (var i = 0; i < suns.length; i++) {
				if (suns[i] === self.targetSun) {
					suns.splice(i, 1);
					break;
				}
			}
			self.targetSun.destroy();
			self.targetSun = null;
			self.isAttractingSun = false;
			self.speed = self.originalSpeed; // Resume movement
		}
	};
	// Override die to stop any sun attraction
	var originalDie = self.die;
	self.die = function () {
		// If attracting a sun, stop the tween and release the sun
		if (self.targetSun && self.targetSun.parent) {
			tween.stop(self.targetSun);
			self.targetSun.isBeingAttracted = false;
			self.targetSun.attractedBy = null;
		}
		originalDie();
	};
	return self;
});
var ZombieCascanueces = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'cascanueces');
	self.health = 1000;
	self.maxHealth = 1000;
	self.speed = 0.96; // Normal zombie speed (0.8) * 1.2
	self.originalSpeed = 0.96;
	self.damage = 35; // 35 damage per second
	self.isParalyzed = false;
	self.paralysisTimer = 0;
	self.paralysisTime = 600; // 10 seconds at 60fps
	self.hasReachedColumn6 = false;
	self.hasReachedColumn4 = false;
	var originalUpdate = self.update;
	self.update = function () {
		// Handle paralysis timer
		if (self.isParalyzed) {
			self.paralysisTimer--;
			if (self.paralysisTimer <= 0) {
				// Wake up from paralysis
				self.isParalyzed = false;
				self.speed = self.originalSpeed;
				// Flash animation when waking up
				tween(self, {
					alpha: 0.3
				}, {
					duration: 200,
					easing: tween.easeInOut,
					onFinish: function onFinish() {
						tween(self, {
							alpha: 1.0
						}, {
							duration: 200,
							easing: tween.easeInOut,
							onFinish: function onFinish() {
								// Second flash
								tween(self, {
									alpha: 0.3
								}, {
									duration: 200,
									easing: tween.easeInOut,
									onFinish: function onFinish() {
										tween(self, {
											alpha: 1.0
										}, {
											duration: 200,
											easing: tween.easeInOut
										});
									}
								});
							}
						});
					}
				});
			}
			return; // Don't move while paralyzed
		}
		// Check current column position
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		// Check if reached column 6 and hasn't been paralyzed there yet
		if (cellX <= 6 && !self.hasReachedColumn6 && !self.isParalyzed) {
			self.hasReachedColumn6 = true;
			self.isParalyzed = true;
			self.paralysisTimer = self.paralysisTime;
			self.speed = 0; // Stop moving
			return; // Don't move this frame
		}
		// Check if reached column 4 and hasn't been paralyzed there yet (and already passed column 6)
		if (cellX <= 4 && !self.hasReachedColumn4 && self.hasReachedColumn6 && !self.isParalyzed) {
			self.hasReachedColumn4 = true;
			self.isParalyzed = true;
			self.paralysisTimer = self.paralysisTime;
			self.speed = 0; // Stop moving
			return; // Don't move this frame
		}
		// Call original update only if not paralyzed
		if (!self.isParalyzed) {
			originalUpdate();
		}
	};
	return self;
});
var ZombieCanon = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'canon');
	self.health = 500;
	self.maxHealth = 500;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.hasReachedPosition = false;
	self.shootTimer = 0;
	self.shootDelay = 600; // 10 seconds at 60fps
	self.firstShot = true; // Track if this is the first shot
	self.damage = 0; // Canon doesn't do regular damage
	var originalUpdate = self.update;
	self.update = function () {
		// Move until reaching ninth column
		if (!self.hasReachedPosition) {
			var cellX = Math.floor((self.x - gridStartX) / cellSize);
			if (cellX <= 8) {
				self.hasReachedPosition = true;
				self.speed = 0; // Stop moving
				// Position exactly at ninth column
				self.x = gridStartX + 8 * cellSize;
			}
		}
		// If reached position, handle shooting
		if (self.hasReachedPosition) {
			self.shootTimer++;
			var currentDelay = self.firstShot ? 180 : self.shootDelay; // 3 seconds for first shot, 10 seconds for subsequent
			if (self.shootTimer >= currentDelay) {
				self.shootShell();
				self.shootTimer = 0;
				self.firstShot = false; // After first shot, use normal delay
			}
		} else {
			// Call original update to move normally
			originalUpdate();
		}
	};
	self.shootShell = function () {
		// Create zombidito shell
		var shell = new CanonShell();
		shell.x = self.x;
		shell.y = self.y;
		shell.gridY = self.gridY;
		canonShells.push(shell);
		game.addChild(shell);
	};
	return self;
});
var Zombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombie');
	self.health = 190;
	self.maxHealth = 190;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	return self;
});
var Zombidito = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombidito');
	self.health = 250;
	self.maxHealth = 250;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.damage = 50; // 50 damage per second
	// Scale down the graphics to make it smaller
	var graphics = self.children[0];
	if (graphics) {
		graphics.scaleX = 0.7;
		graphics.scaleY = 0.7;
	}
	return self;
});
var SunZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'sun_zombie');
	self.health = 190;
	self.maxHealth = 190;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	// Override die function to drop a sun when killed
	var originalDie = self.die;
	self.die = function () {
		// Create a sun at zombie's position
		var droppedSun = new Sun(self.x, self.y);
		suns.push(droppedSun);
		game.addChild(droppedSun);
		// Call original die function
		originalDie();
	};
	return self;
});
var SpawnedZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombie');
	self.health = 225;
	self.maxHealth = 225;
	self.speed = 1.6; // 2x normal zombie speed (0.8 * 2)
	self.originalSpeed = 1.6;
	return self;
});
var RugbyZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'rugby');
	self.health = 300;
	self.maxHealth = 300;
	self.speed = 2.4; // 3x normal zombie speed
	self.originalSpeed = 2.4;
	self.hasContactedPlant = false;
	self.damage = 0; // No regular damage since it kills instantly
	// Override getPlantInFront to handle instant kill
	self.getPlantInFront = function () {
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		if (cellX >= 0 && cellX < gridCols && plants[self.gridY] && plants[self.gridY][cellX]) {
			return plants[self.gridY][cellX];
		}
		return null;
	};
	// Override update to handle 500 damage to plants
	var originalUpdate = self.update;
	self.update = function () {
		var plantInFront = self.getPlantInFront();
		if (plantInFront && !self.hasContactedPlant) {
			// Deal 500 damage to the plant
			plantInFront.takeDamage(500);
			// Reduce speed to normal zombie speed
			self.hasContactedPlant = true;
			self.speed = 0; // Stop for 2 seconds
			self.originalSpeed = 0.8;
			// Flash effect to show speed change
			LK.effects.flashObject(self, 0xFFFF00, 500);
			// Resume normal speed after 2 seconds
			LK.setTimeout(function () {
				self.speed = 0.8;
			}, 2000);
		}
		// Call original update logic
		originalUpdate();
	};
	return self;
});
var MinerZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'miner_zombie');
	self.health = 100;
	self.maxHealth = 100;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.damage = 15;
	// Override the initialization to spawn at 5th column and show explosion
	self.initializeMiner = function (row) {
		self.gridY = row;
		// Position at 5th column (index 4)
		self.x = gridStartX + 4 * cellSize;
		self.y = gridStartY + row * cellSize;
		// Create explosion effect
		var explosion = LK.getAsset('explosion', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y,
			scaleX: 2,
			scaleY: 2
		});
		game.addChild(explosion);
		// Animate explosion and remove it
		tween(explosion, {
			scaleX: 0.1,
			scaleY: 0.1,
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
	};
	return self;
});
var ConeZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'cone_zombie');
	self.health = 300;
	self.maxHealth = 300;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.hasChangedAsset = false;
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		originalTakeDamage(damage);
		// Check if cone zombie should switch to normal zombie appearance
		if (self.health < 191 && !self.hasChangedAsset) {
			self.hasChangedAsset = true;
			// Remove current graphics and add normal zombie version
			self.removeChild(self.children[0]);
			var normalGraphics = self.attachAsset('zombie', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	return self;
});
var BucketZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'bucket_zombie');
	self.health = 375;
	self.maxHealth = 375;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.hasChangedAsset = false;
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		originalTakeDamage(damage);
		// Check if bucket zombie should switch to normal zombie appearance
		if (self.health < 191 && !self.hasChangedAsset) {
			self.hasChangedAsset = true;
			// Remove current graphics and add normal zombie version
			self.removeChild(self.children[0]);
			var normalGraphics = self.attachAsset('zombie', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1B5E20
});
/**** 
* Game Code
****/ 
// Sounds
// UI and grid
// Undead enemies
// Projectiles
// Plant defenders
// Grid setup - bigger grid centered on screen
var gridRows = 5;
var gridCols = 9;
var cellSize = 144;
var gridStartX = (2048 - gridCols * cellSize) / 2;
var gridStartY = (2732 - gridRows * cellSize) / 2;
// Game state
var plants = [];
var enemies = [];
var projectiles = [];
var suns = [];
var canonShells = [];
var lawnmowers = [];
var sunPoints = 500;
var lives = 3;
var currentWave = 1;
var wavesCompleted = 0;
var totalWaves = 10;
var gameMode = null; // 'normal' or 'endless'
var gameModeSelected = false;
var zombieSelectionActive = false;
var selectedZombieTypes = [];
var customWaveConfigs = {}; // Store custom wave configurations
var currentCustomizingWave = 1;
var availableZombieTypes = [{
	type: 'zombie',
	name: 'Normal Zombie',
	asset: 'zombie'
}, {
	type: 'cone_zombie',
	name: 'Cone Zombie',
	asset: 'cone_zombie'
}, {
	type: 'bucket_zombie',
	name: 'Bucket Zombie',
	asset: 'bucket_zombie'
}, {
	type: 'sun_zombie',
	name: 'Sun Zombie',
	asset: 'sun_zombie'
}, {
	type: 'zombie_ra',
	name: 'Zombie Ra',
	asset: 'zombieRa'
}, {
	type: 'zombie_canon',
	name: 'Zombie Canon',
	asset: 'canon'
}, {
	type: 'miner_zombie',
	name: 'Miner Zombie',
	asset: 'miner_zombie'
}, {
	type: 'rugby_zombie',
	name: 'Rugby Zombie',
	asset: 'rugby'
}, {
	type: 'zombiestein',
	name: 'Zombiestein',
	asset: 'zombiestein'
}, {
	type: 'zombie_cascanueces',
	name: 'Zombie Cascanueces',
	asset: 'cascanueces'
}, {
	type: 'zombie_sarcofago',
	name: 'Zombie Sarcófago',
	asset: 'zombie_sarcofago'
}];
var baseEnemiesInWave = 0; // Store base enemy count for endless mode scaling
var waveInProgress = false;
var enemiesInWave = 0;
var enemiesKilled = 0;
var sunTimer = 0;
var waveStartTick = 0;
var nextWaveScheduled = false;
var sunZombieSpawnedThisWave = false;
// Spawn collision tracking for waves 1-2
var lastSpawnTime = {};
var lastSpawnRow = {};
// Miner zombie tracking
var minerZombiesSpawnedThisWave = 0;
var maxMinerZombiesPerWave = 1;
// Zombiestein tracking
var zombiesteinSpawned = false;
var zombiesteinAlive = false;
// Performance optimization variables
var maxObjectsPerType = 50;
var cleanupCounter = 0;
var lagOptimizationActive = false;
// Projectile pool for object reuse
var projectilePool = [];
var maxPoolSize = 20;
// Track active projectiles per plant
var plantProjectileCount = {};
// Selected plant type
var selectedPlantType = null;
var plantTypes = ['sunflower', 'birasol', 'peashooter', 'snowpea', 'fireshot', 'repetidora', 'wallnut', 'nuezPrimitiva', 'petacereza', 'carnivora', 'rapaz'];
var plantCosts = {
	'peashooter': 100,
	'sunflower': 50,
	'birasol': 225,
	'snowpea': 175,
	'fireshot': 175,
	'plantorcha': 175,
	'wallnut': 50,
	'repetidora': 200,
	'nuezPrimitiva': 125,
	'petacereza': 150,
	'carnivora': 200,
	'rapaz': 325
};
// Wallnut cooldown system
var wallnutCooldown = 0;
var wallnutCooldownTime = 720; // 12 seconds at 60fps
// Nuez primitiva cooldown system
var nuezPrimitivaCooldown = 0;
var nuezPrimitivaCooldownTime = 180; // 3 seconds at 60fps
// Petacereza cooldown system
var petacerezaCooldown = 0;
var petacerezaCooldownTime = 900; // 15 seconds at 60fps
// Ghost plant for preview
var ghostPlant = null;
// Initialize grid cells array
var gridCells = [];
// Initialize grid
for (var row = 0; row < gridRows; row++) {
	plants[row] = [];
	gridCells[row] = [];
	for (var col = 0; col < gridCols; col++) {
		plants[row][col] = null;
		var cell = LK.getAsset('gridcell', {
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.3,
			x: gridStartX + col * cellSize,
			y: gridStartY + row * cellSize
		});
		gridCells[row][col] = cell;
		game.addChild(cell);
	}
}
// Initialize lawnmowers
for (var row = 0; row < gridRows; row++) {
	var lawnmower = new Lawnmower(row);
	lawnmowers.push(lawnmower);
	game.addChild(lawnmower);
}
// Game mode selection UI
var modeSelectionContainer = new Container();
modeSelectionContainer.x = 2048 / 2;
modeSelectionContainer.y = 2732 / 2;
var modeTitle = new Text2('Select Game Mode', {
	size: 80,
	fill: 0xFFFFFF
});
modeTitle.anchor.set(0.5, 0.5);
modeTitle.y = -200;
modeSelectionContainer.addChild(modeTitle);
// Normal mode button
var normalModeButton = LK.getAsset('gridcell', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: -240,
	y: -50,
	scaleX: 2,
	scaleY: 1.5,
	color: 0x4CAF50
});
normalModeButton.interactive = true;
normalModeButton.buttonMode = true;
normalModeButton.down = function (x, y, obj) {
	gameMode = 'normal';
	totalWaves = 10;
	selectGameMode();
};
modeSelectionContainer.addChild(normalModeButton);
var normalModeText = new Text2('Normal', {
	size: 60,
	fill: 0xFFFFFF
});
normalModeText.anchor.set(0.5, 0.5);
normalModeText.x = -320;
normalModeText.y = -50;
modeSelectionContainer.addChild(normalModeText);
var normalModeSubtext = new Text2('(10 waves)', {
	size: 40,
	fill: 0xCCCCCC
});
normalModeSubtext.anchor.set(0.5, 0.5);
normalModeSubtext.x = -240;
normalModeSubtext.y = 10;
modeSelectionContainer.addChild(normalModeSubtext);
// Personalize mode button
var personalizeModeButton = LK.getAsset('gridcell', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 0,
	y: -50,
	scaleX: 2,
	scaleY: 1.5,
	color: 0xFF9800
});
personalizeModeButton.interactive = true;
personalizeModeButton.buttonMode = true;
personalizeModeButton.down = function (x, y, obj) {
	gameMode = 'personalize';
	totalWaves = 20;
	showZombieSelection();
};
modeSelectionContainer.addChild(personalizeModeButton);
var personalizeModeText = new Text2('Personalize', {
	size: 60,
	fill: 0xFFFFFF
});
personalizeModeText.anchor.set(0.5, 0.5);
personalizeModeText.x = 0;
personalizeModeText.y = -50;
modeSelectionContainer.addChild(personalizeModeText);
var personalizeModeSubtext = new Text2('(20 waves)', {
	size: 40,
	fill: 0xCCCCCC
});
personalizeModeSubtext.anchor.set(0.5, 0.5);
personalizeModeSubtext.x = 0;
personalizeModeSubtext.y = 10;
modeSelectionContainer.addChild(personalizeModeSubtext);
// Endless mode button
var endlessModeButton = LK.getAsset('gridcell', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 360,
	y: -50,
	scaleX: 2,
	scaleY: 1.5,
	color: 0x9C27B0
});
endlessModeButton.interactive = true;
endlessModeButton.buttonMode = true;
endlessModeButton.down = function (x, y, obj) {
	gameMode = 'endless';
	totalWaves = 999; // Large number for display purposes
	selectGameMode();
};
modeSelectionContainer.addChild(endlessModeButton);
var endlessModeText = new Text2('Endless', {
	size: 60,
	fill: 0xFFFFFF
});
endlessModeText.anchor.set(0.5, 0.5);
endlessModeText.x = 360;
endlessModeText.y = -50;
modeSelectionContainer.addChild(endlessModeText);
var endlessModeSubtext = new Text2('(infinite waves)', {
	size: 40,
	fill: 0xCCCCCC
});
endlessModeSubtext.anchor.set(0.5, 0.5);
endlessModeSubtext.x = 360;
endlessModeSubtext.y = 10;
modeSelectionContainer.addChild(endlessModeSubtext);
game.addChild(modeSelectionContainer);
function selectGameMode() {
	gameModeSelected = true;
	modeSelectionContainer.destroy();
	updateWaveDisplay();
	// Create skip wave button only for endless mode
	if (gameMode === 'endless') {
		createSkipWaveButton();
	}
	// Start first wave after mode selection
	LK.setTimeout(function () {
		startWave();
	}, 3000);
}
function showZombieSelection() {
	zombieSelectionActive = true;
	modeSelectionContainer.destroy();
	// Create zombie selection container
	var zombieSelectionContainer = new Container();
	zombieSelectionContainer.x = 2048 / 2;
	zombieSelectionContainer.y = 2732 / 2;
	game.addChild(zombieSelectionContainer);
	// Title
	var selectionTitle = new Text2('Select Zombies for Endless Mode', {
		size: 60,
		fill: 0xFFFFFF
	});
	selectionTitle.anchor.set(0.5, 0.5);
	selectionTitle.y = -350;
	zombieSelectionContainer.addChild(selectionTitle);
	// Instructions
	var instructions = new Text2('Click zombies to toggle selection (min 3 required)', {
		size: 40,
		fill: 0xCCCCCC
	});
	instructions.anchor.set(0.5, 0.5);
	instructions.y = -300;
	zombieSelectionContainer.addChild(instructions);
	// Create zombie selection buttons
	var zombieButtons = [];
	var cols = 4;
	var rows = Math.ceil(availableZombieTypes.length / cols);
	for (var i = 0; i < availableZombieTypes.length; i++) {
		var zombieType = availableZombieTypes[i];
		var col = i % cols;
		var row = Math.floor(i / cols);
		// Zombie button
		var zombieButton = LK.getAsset(zombieType.asset, {
			anchorX: 0.5,
			anchorY: 0.5,
			x: (col - (cols - 1) / 2) * 200,
			y: (row - (rows - 1) / 2) * 160 - 50,
			scaleX: 1.5,
			scaleY: 1.5
		});
		zombieButton.zombieType = zombieType.type;
		zombieButton.isSelected = false;
		zombieButton.interactive = true;
		zombieButton.buttonMode = true;
		zombieButton.alpha = 0.5; // Start unselected
		zombieButton.down = function (x, y, obj) {
			toggleZombieSelection(this);
		};
		zombieSelectionContainer.addChild(zombieButton);
		zombieButtons.push(zombieButton);
		// Zombie name
		var nameText = new Text2(zombieType.name, {
			size: 30,
			fill: 0xFFFFFF
		});
		nameText.anchor.set(0.5, 0.5);
		nameText.x = zombieButton.x;
		nameText.y = zombieButton.y + 80;
		zombieSelectionContainer.addChild(nameText);
	}
	// Start button
	var startButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 0,
		y: 250,
		scaleX: 3,
		scaleY: 1.5,
		color: 0x4CAF50
	});
	startButton.interactive = true;
	startButton.buttonMode = true;
	startButton.alpha = 0.5; // Start disabled
	startButton.down = function (x, y, obj) {
		if (selectedZombieTypes.length >= 3) {
			zombieSelectionContainer.destroy();
			showWaveCustomization();
		}
	};
	zombieSelectionContainer.addChild(startButton);
	var startButtonText = new Text2('Customize Waves', {
		size: 50,
		fill: 0xFFFFFF
	});
	startButtonText.anchor.set(0.5, 0.5);
	startButtonText.y = 250;
	zombieSelectionContainer.addChild(startButtonText);
	// Store references for updates
	zombieSelectionContainer.zombieButtons = zombieButtons;
	zombieSelectionContainer.startButton = startButton;
	zombieSelectionContainer.startButtonText = startButtonText;
	game.zombieSelectionContainer = zombieSelectionContainer;
}
function toggleZombieSelection(button) {
	if (button.isSelected) {
		// Deselect
		button.isSelected = false;
		button.alpha = 0.5;
		button.tint = 0xFFFFFF;
		// Remove from selected array
		for (var i = 0; i < selectedZombieTypes.length; i++) {
			if (selectedZombieTypes[i] === button.zombieType) {
				selectedZombieTypes.splice(i, 1);
				break;
			}
		}
	} else {
		// Select
		button.isSelected = true;
		button.alpha = 1.0;
		button.tint = 0x00FF00;
		selectedZombieTypes.push(button.zombieType);
	}
	updateStartButton();
}
function updateStartButton() {
	var container = game.zombieSelectionContainer;
	if (!container) {
		return;
	}
	if (selectedZombieTypes.length >= 3) {
		container.startButton.alpha = 1.0;
		container.startButton.tint = 0x4CAF50;
		container.startButtonText.setText('Customize Waves (' + selectedZombieTypes.length + ' selected)');
	} else {
		container.startButton.alpha = 0.5;
		container.startButton.tint = 0x888888;
		container.startButtonText.setText('Select at least 3 zombies (' + selectedZombieTypes.length + '/3)');
	}
}
function showWaveCustomization() {
	// Initialize default configurations for all 20 waves
	for (var wave = 1; wave <= 20; wave++) {
		if (!customWaveConfigs[wave]) {
			customWaveConfigs[wave] = {};
			for (var i = 0; i < selectedZombieTypes.length; i++) {
				customWaveConfigs[wave][selectedZombieTypes[i]] = wave <= 2 ? 2 : Math.min(wave, 8); // Default quantities
			}
		}
	}
	currentCustomizingWave = 1;
	showWaveConfigUI();
}
function showWaveConfigUI() {
	// Remove existing wave config container if any
	if (game.waveConfigContainer) {
		game.waveConfigContainer.destroy();
	}
	// Create wave customization container
	var waveConfigContainer = new Container();
	waveConfigContainer.x = 2048 / 2;
	waveConfigContainer.y = 2732 / 2;
	game.addChild(waveConfigContainer);
	game.waveConfigContainer = waveConfigContainer;
	// Title
	var configTitle = new Text2('Wave ' + currentCustomizingWave + ' Configuration', {
		size: 60,
		fill: 0xFFFFFF
	});
	configTitle.anchor.set(0.5, 0.5);
	configTitle.y = -350;
	waveConfigContainer.addChild(configTitle);
	// Instructions
	var configInstructions = new Text2('Set zombie quantities for Wave ' + currentCustomizingWave + ' (1-20)', {
		size: 40,
		fill: 0xCCCCCC
	});
	configInstructions.anchor.set(0.5, 0.5);
	configInstructions.y = -300;
	waveConfigContainer.addChild(configInstructions);
	// Wave navigation buttons - positioned slightly higher
	var prevWaveButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: -400,
		y: -250,
		scaleX: 1.5,
		scaleY: 1.0,
		color: currentCustomizingWave > 1 ? 0x2196F3 : 0x666666
	});
	prevWaveButton.interactive = currentCustomizingWave > 1;
	prevWaveButton.buttonMode = currentCustomizingWave > 1;
	if (currentCustomizingWave > 1) {
		prevWaveButton.down = function () {
			currentCustomizingWave--;
			showWaveConfigUI();
		};
	}
	waveConfigContainer.addChild(prevWaveButton);
	var prevWaveText = new Text2('◀ Previous', {
		size: 40,
		fill: 0xFFFFFF
	});
	prevWaveText.anchor.set(0.5, 0.5);
	prevWaveText.x = -400;
	prevWaveText.y = -250;
	waveConfigContainer.addChild(prevWaveText);
	var nextWaveButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 400,
		y: -250,
		scaleX: 1.5,
		scaleY: 1.0,
		color: currentCustomizingWave < 20 ? 0x2196F3 : 0x666666
	});
	nextWaveButton.interactive = currentCustomizingWave < 20;
	nextWaveButton.buttonMode = currentCustomizingWave < 20;
	if (currentCustomizingWave < 20) {
		nextWaveButton.down = function () {
			currentCustomizingWave++;
			showWaveConfigUI();
		};
	}
	waveConfigContainer.addChild(nextWaveButton);
	var nextWaveText = new Text2('Next ▶', {
		size: 40,
		fill: 0xFFFFFF
	});
	nextWaveText.anchor.set(0.5, 0.5);
	nextWaveText.x = 400;
	nextWaveText.y = -250;
	waveConfigContainer.addChild(nextWaveText);
	// Add "All to 0" and "All to 1" buttons on the left side
	var allToZeroButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: -700,
		y: -50,
		scaleX: 1.5,
		scaleY: 1.0,
		color: 0xF44336
	});
	allToZeroButton.interactive = true;
	allToZeroButton.buttonMode = true;
	allToZeroButton.down = function () {
		// Set all zombie quantities to 0 for current wave
		for (var i = 0; i < selectedZombieTypes.length; i++) {
			customWaveConfigs[currentCustomizingWave][selectedZombieTypes[i]] = 0;
		}
		showWaveConfigUI(); // Refresh UI
	};
	waveConfigContainer.addChild(allToZeroButton);
	var allToZeroText = new Text2('All to 0', {
		size: 35,
		fill: 0xFFFFFF
	});
	allToZeroText.anchor.set(0.5, 0.5);
	allToZeroText.x = -700;
	allToZeroText.y = -50;
	waveConfigContainer.addChild(allToZeroText);
	var allToOneButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: -700,
		y: 20,
		scaleX: 1.5,
		scaleY: 1.0,
		color: 0x4CAF50
	});
	allToOneButton.interactive = true;
	allToOneButton.buttonMode = true;
	allToOneButton.down = function () {
		// Set all zombie quantities to 1 for current wave
		for (var i = 0; i < selectedZombieTypes.length; i++) {
			customWaveConfigs[currentCustomizingWave][selectedZombieTypes[i]] = 1;
		}
		showWaveConfigUI(); // Refresh UI
	};
	waveConfigContainer.addChild(allToOneButton);
	var allToOneText = new Text2('All to 1', {
		size: 35,
		fill: 0xFFFFFF
	});
	allToOneText.anchor.set(0.5, 0.5);
	allToOneText.x = -700;
	allToOneText.y = 20;
	waveConfigContainer.addChild(allToOneText);
	// Zombie quantity controls
	var yOffset = -100;
	var zombieControls = [];
	for (var i = 0; i < selectedZombieTypes.length; i++) {
		var zombieType = selectedZombieTypes[i];
		var zombieAsset = null;
		for (var j = 0; j < availableZombieTypes.length; j++) {
			if (availableZombieTypes[j].type === zombieType) {
				zombieAsset = availableZombieTypes[j].asset;
				break;
			}
		}
		if (zombieAsset) {
			// Zombie icon
			var zombieIcon = LK.getAsset(zombieAsset, {
				anchorX: 0.5,
				anchorY: 0.5,
				x: -300,
				y: yOffset,
				scaleX: 1.2,
				scaleY: 1.2
			});
			waveConfigContainer.addChild(zombieIcon);
			// Decrease button
			var decreaseButton = LK.getAsset('gridcell', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: -100,
				y: yOffset,
				scaleX: 0.8,
				scaleY: 0.8,
				color: 0xF44336
			});
			decreaseButton.zombieType = zombieType;
			decreaseButton.interactive = true;
			decreaseButton.buttonMode = true;
			decreaseButton.down = function () {
				var currentQty = customWaveConfigs[currentCustomizingWave][this.zombieType] || 0;
				if (currentQty > 0) {
					customWaveConfigs[currentCustomizingWave][this.zombieType] = currentQty - 1;
					showWaveConfigUI();
				}
			};
			waveConfigContainer.addChild(decreaseButton);
			var decreaseText = new Text2('-', {
				size: 50,
				fill: 0xFFFFFF
			});
			decreaseText.anchor.set(0.5, 0.5);
			decreaseText.x = -100;
			decreaseText.y = yOffset;
			waveConfigContainer.addChild(decreaseText);
			// Quantity display
			var quantity = customWaveConfigs[currentCustomizingWave][zombieType] || 0;
			var quantityText = new Text2(quantity.toString(), {
				size: 45,
				fill: 0xFFFFFF
			});
			quantityText.anchor.set(0.5, 0.5);
			quantityText.x = 0;
			quantityText.y = yOffset;
			waveConfigContainer.addChild(quantityText);
			// Increase button
			var increaseButton = LK.getAsset('gridcell', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: 100,
				y: yOffset,
				scaleX: 0.8,
				scaleY: 0.8,
				color: 0x4CAF50
			});
			increaseButton.zombieType = zombieType;
			increaseButton.interactive = true;
			increaseButton.buttonMode = true;
			increaseButton.down = function () {
				var currentQty = customWaveConfigs[currentCustomizingWave][this.zombieType] || 0;
				if (currentQty < 15) {
					// Max 15 zombies per type per wave
					customWaveConfigs[currentCustomizingWave][this.zombieType] = currentQty + 1;
					showWaveConfigUI();
				}
			};
			waveConfigContainer.addChild(increaseButton);
			var increaseText = new Text2('+', {
				size: 40,
				fill: 0xFFFFFF
			});
			increaseText.anchor.set(0.5, 0.5);
			increaseText.x = 100;
			increaseText.y = yOffset;
			waveConfigContainer.addChild(increaseText);
			// Zombie name
			var zombieName = null;
			for (var k = 0; k < availableZombieTypes.length; k++) {
				if (availableZombieTypes[k].type === zombieType) {
					zombieName = availableZombieTypes[k].name;
					break;
				}
			}
			var nameText = new Text2(zombieName || zombieType, {
				size: 30,
				fill: 0xCCCCCC
			});
			nameText.anchor.set(0.5, 0.5);
			nameText.x = 300;
			nameText.y = yOffset;
			waveConfigContainer.addChild(nameText);
			yOffset += 70;
		}
	}
	// Finish customization button - positioned at bottom right
	var finishButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 600,
		y: 350,
		scaleX: 3,
		scaleY: 1.5,
		color: 0x4CAF50
	});
	finishButton.interactive = true;
	finishButton.buttonMode = true;
	finishButton.down = function () {
		waveConfigContainer.destroy();
		selectGameMode();
	};
	waveConfigContainer.addChild(finishButton);
	var finishButtonText = new Text2('Start Game', {
		size: 50,
		fill: 0xFFFFFF
	});
	finishButtonText.anchor.set(0.5, 0.5);
	finishButtonText.x = 600;
	finishButtonText.y = 350;
	waveConfigContainer.addChild(finishButtonText);
}
// Shovel tool for removing plants
var selectedTool = null; // 'shovel' or null
var shovelButton = LK.getAsset('shovel', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 100,
	scaleX: 1.5,
	scaleY: 1.5
});
shovelButton.interactive = true;
shovelButton.buttonMode = true;
shovelButton.down = function (x, y, obj) {
	console.log("Shovel button clicked");
	if (selectedTool === 'shovel') {
		selectedTool = null;
		shovelButton.alpha = 0.8;
		shovelButton.scaleX = shovelButton.scaleY = 1.5;
	} else {
		selectedTool = 'shovel';
		selectedPlantType = null;
		shovelButton.alpha = 1.0;
		shovelButton.scaleX = shovelButton.scaleY = 1.8;
		updatePlantSelection();
	}
};
shovelButton.alpha = 0.8;
game.addChild(shovelButton);
// UI Elements
var sunDisplay = new Text2('Sun: ' + sunPoints, {
	size: 60,
	fill: 0xFFEB3B
});
sunDisplay.anchor.set(0, 0);
sunDisplay.x = 120; // Offset from left edge to avoid menu icon
LK.gui.topLeft.addChild(sunDisplay);
var livesDisplay = new Text2('Lives: ' + lives, {
	size: 60,
	fill: 0xF44336
});
livesDisplay.anchor.set(0, 0);
livesDisplay.y = 80;
LK.gui.topRight.addChild(livesDisplay);
var waveDisplay = new Text2('Wave: ' + currentWave + '/' + totalWaves, {
	size: 50,
	fill: 0x4CAF50
});
waveDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(waveDisplay);
// Plant selection UI at bottom
var plantButtons = [];
var uiY = 2732 - 150;
for (var i = 0; i < plantTypes.length; i++) {
	var plantType = plantTypes[i];
	var yPos = uiY;
	var xPos = 200 + i * 220;
	// Special positioning for carnivora - place it above peashooter
	if (plantType === 'carnivora') {
		xPos = 640; // Same x position as peashooter
		yPos = uiY - 266; // Above peashooter
	}
	// Special positioning for petacereza - place it above birasol
	else if (plantType === 'petacereza') {
		xPos = 420; // Same x position as birasol
		yPos = uiY - 266; // Above birasol, 10% higher than previous position (242 * 1.1 = 266)
	}
	// Special positioning for rapaz - place it above snowpea
	else if (plantType === 'rapaz') {
		xPos = 860; // Same x position as snowpea
		yPos = uiY - 266; // Above snowpea
	}
	var button = LK.getAsset(plantType, {
		anchorX: 0.5,
		anchorY: 0.5,
		x: xPos,
		y: yPos,
		scaleX: 2.25,
		scaleY: 2.25
	});
	button.plantType = plantType;
	button.interactive = true; // Enable button interactivity
	button.buttonMode = true; // Make it behave like a button
	button.down = function (x, y, obj) {
		console.log("Plant button clicked:", this.plantType, "Cost:", plantCosts[this.plantType], "Current suns:", sunPoints);
		// Check wallnut cooldown
		if (this.plantType === 'wallnut' && wallnutCooldown > 0) {
			return; // Don't allow selection during cooldown
		}
		// Check nuez primitiva cooldown
		if (this.plantType === 'nuezPrimitiva' && nuezPrimitivaCooldown > 0) {
			return; // Don't allow selection during cooldown
		}
		// Check petacereza cooldown
		if (this.plantType === 'petacereza' && petacerezaCooldown > 0) {
			return; // Don't allow selection during cooldown
		}
		if (sunPoints >= plantCosts[this.plantType]) {
			selectedPlantType = this.plantType;
			selectedTool = null;
			shovelButton.alpha = 0.8;
			shovelButton.scaleX = shovelButton.scaleY = 1.5;
			updatePlantSelection();
		}
	};
	game.addChild(button);
	plantButtons.push(button);
	// Add cost text
	var costText = new Text2(plantCosts[plantType], {
		size: 40,
		fill: 0xFFFFFF
	});
	costText.anchor.set(0.5, 0);
	costText.x = button.x;
	costText.y = button.y + 80;
	game.addChild(costText);
}
// Add plantorcha button above sunflower
var plantorchaButton = LK.getAsset('plantorcha', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 200,
	// Same x as sunflower
	y: uiY - 351,
	// Above sunflower with 10% more space above previous position (319 * 1.1 = 351)
	scaleX: 2.25,
	scaleY: 2.25
});
plantorchaButton.plantType = 'plantorcha';
plantorchaButton.interactive = true;
plantorchaButton.buttonMode = true;
plantorchaButton.down = function (x, y, obj) {
	console.log("Plant button clicked:", this.plantType, "Cost:", plantCosts[this.plantType], "Current suns:", sunPoints);
	if (sunPoints >= plantCosts[this.plantType]) {
		selectedPlantType = this.plantType;
		selectedTool = null;
		shovelButton.alpha = 0.8;
		shovelButton.scaleX = shovelButton.scaleY = 1.5;
		updatePlantSelection();
	}
};
game.addChild(plantorchaButton);
plantButtons.push(plantorchaButton);
// Add plantorcha cost text
var plantorchaCostText = new Text2(plantCosts['plantorcha'], {
	size: 40,
	fill: 0xFFFFFF
});
plantorchaCostText.anchor.set(0.5, 0);
plantorchaCostText.x = plantorchaButton.x;
plantorchaCostText.y = plantorchaButton.y + 80;
game.addChild(plantorchaCostText);
function updatePlantSelection() {
	for (var i = 0; i < plantButtons.length; i++) {
		if (plantButtons[i].plantType === selectedPlantType) {
			plantButtons[i].alpha = 1.0;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.55;
		} else if (plantButtons[i].plantType === 'wallnut' && wallnutCooldown > 0) {
			// Gray out wallnut during cooldown
			plantButtons[i].alpha = 0.3;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.25;
			plantButtons[i].tint = 0x888888;
		} else if (plantButtons[i].plantType === 'nuezPrimitiva' && nuezPrimitivaCooldown > 0) {
			// Gray out nuez primitiva during cooldown
			plantButtons[i].alpha = 0.3;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.25;
			plantButtons[i].tint = 0x888888;
		} else if (plantButtons[i].plantType === 'petacereza' && petacerezaCooldown > 0) {
			// Gray out petacereza during cooldown
			plantButtons[i].alpha = 0.3;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.25;
			plantButtons[i].tint = 0x888888;
		} else {
			plantButtons[i].alpha = 0.6;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.25;
			plantButtons[i].tint = 0xFFFFFF;
		}
	}
	// Remove existing ghost plant
	if (ghostPlant) {
		ghostPlant.destroy();
		ghostPlant = null;
	}
	// Create new ghost plant if a type is selected
	if (selectedPlantType) {
		ghostPlant = LK.getAsset(selectedPlantType, {
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.6,
			tint: 0x88FF88
		});
		game.addChild(ghostPlant);
	}
	// Highlight valid placement squares
	for (var row = 0; row < gridRows; row++) {
		for (var col = 0; col < gridCols; col++) {
			if (selectedPlantType && canPlacePlant(col, row, selectedPlantType)) {
				// Green highlight for valid empty squares
				gridCells[row][col].tint = 0x00FF00;
				gridCells[row][col].alpha = 0.7;
			} else if (selectedPlantType && plants[row][col] !== null) {
				// Red highlight for occupied squares when plant is selected
				gridCells[row][col].tint = 0xFF0000;
				gridCells[row][col].alpha = 0.5;
			} else if (selectedTool === 'shovel' && plants[row][col] !== null) {
				// Yellow highlight for plants that can be removed with shovel
				gridCells[row][col].tint = 0xFFFF00;
				gridCells[row][col].alpha = 0.7;
			} else {
				// Normal appearance for unselected or invalid squares
				gridCells[row][col].tint = 0xFFFFFF;
				gridCells[row][col].alpha = 0.3;
			}
		}
	}
}
function updateSunDisplay() {
	sunDisplay.setText('Sun: ' + sunPoints);
}
function updateLivesDisplay() {
	livesDisplay.setText('Lives: ' + lives);
}
function updateWaveDisplay() {
	if (gameMode === 'endless') {
		waveDisplay.setText('Wave: ' + currentWave + ' / ∞');
	} else if (gameMode === 'personalize') {
		waveDisplay.setText('Wave: ' + currentWave + '/' + totalWaves);
	} else {
		waveDisplay.setText('Wave: ' + currentWave + '/' + totalWaves);
	}
}
function createProjectile(type, startX, startY, speed, damage, plantId) {
	// Check if plant already has 2 active projectiles
	if (!plantProjectileCount[plantId]) {
		plantProjectileCount[plantId] = 0;
	}
	if (plantProjectileCount[plantId] >= 2) {
		return null; // Don't create projectile if plant already has 2
	}
	var projectile;
	if (projectilePool.length > 0) {
		// Reuse from pool
		projectile = projectilePool.pop();
		projectile.speed = speed;
		projectile.damage = damage;
		projectile.x = startX;
		projectile.y = startY;
		projectile.type = type;
		projectile.gridY = Math.floor((startY - gridStartY + cellSize / 2) / cellSize);
		projectile.ownerId = plantId;
		// Re-add graphics
		var graphics = projectile.attachAsset(type, {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		// Create new projectile
		projectile = new Projectile(type, startX, startY, speed, damage);
		projectile.ownerId = plantId;
	}
	plantProjectileCount[plantId]++;
	projectiles.push(projectile);
	game.addChild(projectile);
	return projectile;
}
function performanceCleanup() {
	// Clean up destroyed objects that might still be in arrays
	for (var i = enemies.length - 1; i >= 0; i--) {
		if (!enemies[i].parent) {
			enemies.splice(i, 1);
		}
	}
	for (var i = projectiles.length - 1; i >= 0; i--) {
		if (!projectiles[i].parent) {
			projectiles.splice(i, 1);
		}
	}
	for (var i = suns.length - 1; i >= 0; i--) {
		if (!suns[i].parent) {
			suns.splice(i, 1);
		}
	}
	for (var i = canonShells.length - 1; i >= 0; i--) {
		if (!canonShells[i].parent) {
			canonShells.splice(i, 1);
		}
	}
	// Clean up projectile tracking for destroyed plants
	for (var plantId in plantProjectileCount) {
		var coords = plantId.split('_');
		var x = parseInt(coords[0]);
		var y = parseInt(coords[1]);
		if (y >= 0 && y < gridRows && x >= 0 && x < gridCols && !plants[y][x]) {
			delete plantProjectileCount[plantId];
		}
	}
	// Limit maximum objects if we have too many
	if (enemies.length > maxObjectsPerType) {
		for (var i = 0; i < enemies.length - maxObjectsPerType; i++) {
			if (enemies[i]) {
				enemies[i].destroy();
			}
		}
	}
	if (projectiles.length > maxObjectsPerType) {
		for (var i = 0; i < projectiles.length - maxObjectsPerType; i++) {
			if (projectiles[i]) {
				projectiles[i].removeFromGame();
			}
		}
	}
	if (suns.length > 20) {
		for (var i = 0; i < suns.length - 20; i++) {
			if (suns[i]) {
				suns[i].destroy();
			}
		}
	}
	// Limit projectile pool size
	if (projectilePool.length > maxPoolSize) {
		for (var i = maxPoolSize; i < projectilePool.length; i++) {
			if (projectilePool[i]) {
				projectilePool[i].destroy();
			}
		}
		projectilePool.length = maxPoolSize;
	}
}
function getGridPosition(x, y) {
	var gridX = Math.floor((x - gridStartX + cellSize / 2) / cellSize);
	var gridY = Math.floor((y - gridStartY + cellSize / 2) / cellSize);
	if (gridX >= 0 && gridX < gridCols && gridY >= 0 && gridY < gridRows) {
		return {
			x: gridX,
			y: gridY
		};
	}
	return null;
}
function canPlacePlant(gridX, gridY, plantType) {
	// Check if grid position is valid
	if (gridX < 0 || gridX >= gridCols || gridY < 0 || gridY >= gridRows) {
		return false;
	}
	// Check wallnut cooldown
	if (plantType === 'wallnut' && wallnutCooldown > 0) {
		return false;
	}
	// Check nuez primitiva cooldown
	if (plantType === 'nuezPrimitiva' && nuezPrimitivaCooldown > 0) {
		return false;
	}
	// Check petacereza cooldown
	if (plantType === 'petacereza' && petacerezaCooldown > 0) {
		return false;
	}
	// Check if square is empty and player has enough suns
	return plants[gridY][gridX] === null && sunPoints >= plantCosts[plantType];
}
function placePlant(gridX, gridY, plantType) {
	// Double-check that placement is valid before proceeding
	if (!canPlacePlant(gridX, gridY, plantType)) {
		return false;
	}
	var plant;
	switch (plantType) {
		case 'peashooter':
			plant = new Peashooter();
			break;
		case 'sunflower':
			plant = new Sunflower();
			break;
		case 'birasol':
			plant = new Birasol();
			break;
		case 'snowpea':
			plant = new SnowPea();
			break;
		case 'fireshot':
			plant = new Fireshot();
			break;
		case 'plantorcha':
			plant = new Plantorcha();
			break;
		case 'wallnut':
			plant = new Wallnut();
			break;
		case 'snowpea':
			plant = new SnowPea();
			break;
		case 'repetidora':
			plant = new Repetidora();
			break;
		case 'nuezPrimitiva':
			plant = new NuezPrimitiva();
			break;
		case 'petacereza':
			plant = new Petacereza();
			break;
		case 'carnivora':
			plant = new Carnivora();
			break;
		case 'rapaz':
			plant = new Rapaz();
			break;
		default:
			return false;
	}
	// Set plant position and grid reference
	plant.gridX = gridX;
	plant.gridY = gridY;
	plant.x = gridStartX + gridX * cellSize;
	plant.y = gridStartY + gridY * cellSize;
	// Place plant in grid and add to game
	plants[gridY][gridX] = plant;
	game.addChild(plant);
	// Deduct cost and update UI
	sunPoints -= plantCosts[plantType];
	updateSunDisplay();
	LK.getSound('plant').play();
	// Start wallnut cooldown if placing wallnut
	if (plantType === 'wallnut') {
		wallnutCooldown = wallnutCooldownTime;
		selectedPlantType = null; // Deselect wallnut after placing
		updatePlantSelection();
	}
	// Start nuez primitiva cooldown if placing nuez primitiva
	if (plantType === 'nuezPrimitiva') {
		nuezPrimitivaCooldown = nuezPrimitivaCooldownTime;
		selectedPlantType = null; // Deselect nuez primitiva after placing
		updatePlantSelection();
	}
	// Start petacereza cooldown if placing petacereza
	if (plantType === 'petacereza') {
		petacerezaCooldown = petacerezaCooldownTime;
		selectedPlantType = null; // Deselect petacereza after placing
		updatePlantSelection();
	}
	// Flash the grid cell to show successful placement
	LK.effects.flashObject(gridCells[gridY][gridX], 0x00FF00, 300);
	return true;
}
function canSpawnWithoutCollision(row) {
	// Only apply collision detection for waves 1-2
	if (currentWave > 2) {
		return true;
	}
	var currentTime = LK.ticks;
	var oneSecond = 60; // 60 ticks = 1 second at 60fps
	// Check if same row was used in last second
	if (lastSpawnRow[row] && currentTime - lastSpawnRow[row] < oneSecond) {
		return false;
	}
	// Check if any zombie was spawned in last second
	for (var checkRow in lastSpawnTime) {
		if (currentTime - lastSpawnTime[checkRow] < oneSecond) {
			return false;
		}
	}
	return true;
}
function spawnZombie(type, row) {
	var zombie;
	switch (type) {
		case 'zombie':
			zombie = new Zombie();
			break;
		case 'cone_zombie':
			zombie = new ConeZombie();
			break;
		case 'bucket_zombie':
			zombie = new BucketZombie();
			break;
		case 'sun_zombie':
			zombie = new SunZombie();
			break;
		case 'zombie_ra':
			zombie = new ZombieRa();
			break;
		case 'zombie_canon':
			zombie = new ZombieCanon();
			break;
		case 'miner_zombie':
			zombie = new MinerZombie();
			// Special positioning for miner
			zombie.initializeMiner(row);
			// Apply health bonus for endless mode after wave 10
			if (gameMode === 'endless' && currentWave > 10) {
				var healthMultiplier = 1 + (currentWave - 10) * 0.05;
				zombie.health = Math.floor(zombie.health * healthMultiplier);
				zombie.maxHealth = Math.floor(zombie.maxHealth * healthMultiplier);
			}
			enemies.push(zombie);
			game.addChild(zombie);
			return;
		// Return early since positioning is handled
		case 'zombiestein':
			zombie = new Zombiestein();
			break;
		case 'rugby_zombie':
			zombie = new RugbyZombie();
			break;
		case 'zombie_cascanueces':
			zombie = new ZombieCascanueces();
			break;
		case 'zombie_sarcofago':
			zombie = new ZombieSarcofago();
			break;
		default:
			return;
	}
	zombie.gridY = row;
	zombie.x = 2100;
	zombie.y = gridStartY + row * cellSize;
	// Apply health bonus for endless mode after wave 10
	if (gameMode === 'endless' && currentWave > 10) {
		var healthMultiplier = 1 + (currentWave - 10) * 0.05;
		zombie.health = Math.floor(zombie.health * healthMultiplier);
		zombie.maxHealth = Math.floor(zombie.maxHealth * healthMultiplier);
	}
	enemies.push(zombie);
	game.addChild(zombie);
}
function startWave() {
	if (waveInProgress) {
		return;
	}
	waveInProgress = true;
	waveStartTick = LK.ticks; // Record when wave started
	sunZombieSpawnedThisWave = false; // Reset sun zombie spawn flag for this wave
	// Reset and update miner zombie tracking for this wave
	minerZombiesSpawnedThisWave = 0;
	if (currentWave >= 8) {
		maxMinerZombiesPerWave = 2;
	} else {
		maxMinerZombiesPerWave = 1;
	}
	var bucketZombiesLeft = 0;
	// Handle custom wave configurations for waves 1-20 in personalize mode
	if (gameMode === 'personalize' && currentWave <= 20 && customWaveConfigs[currentWave]) {
		var waveConfig = customWaveConfigs[currentWave];
		var totalZombies = 0;
		var spawnQueue = [];
		// Build spawn queue from custom configuration
		for (var zombieType in waveConfig) {
			var quantity = waveConfig[zombieType];
			for (var i = 0; i < quantity; i++) {
				spawnQueue.push(zombieType);
				totalZombies++;
			}
		}
		enemiesInWave = totalZombies;
		enemiesKilled = 0;
		// Spawn zombies from custom configuration
		if (spawnQueue.length > 0) {
			var spawnIndex = 0;
			var customSpawnTimer = LK.setInterval(function () {
				if (spawnIndex < spawnQueue.length) {
					var zombieType = spawnQueue[spawnIndex];
					var row = Math.floor(Math.random() * gridRows);
					spawnZombie(zombieType, row);
					spawnIndex++;
				} else {
					LK.clearInterval(customSpawnTimer);
				}
			}, 800); // Spawn every 800ms
		}
		return; // Exit early for custom waves
	}
	// Handle endless mode waves (but not personalize mode)
	if (gameMode === 'endless' && currentWave > 10) {
		// For endless mode waves 11+, spawn Zombiestein every 5 waves
		if (currentWave % 5 === 0) {
			// Calculate number of Zombiesteins to spawn based on wave
			var zombiesteinCount = Math.floor((currentWave - 10) / 5) + 1;
			for (var z = 0; z < zombiesteinCount; z++) {
				var zombiesteinRow = Math.floor(Math.random() * gridRows);
				spawnZombie('zombiestein', zombiesteinRow);
			}
			zombiesteinSpawned = true;
			zombiesteinAlive = true;
			enemiesInWave += zombiesteinCount - 1; // Adjust enemy count for additional Zombiesteins
		}
		// Zombie Sarcófago spawning logic for endless mode waves 15+
		if (currentWave >= 15) {
			// Count bucket zombies in this wave to determine if we can spawn sarcófago
			var bucketZombieCount = Math.floor(scaledEnemyCount * 0.6);
			// 50% chance to spawn if at least 2 bucket zombies
			if (bucketZombieCount >= 2 && Math.random() < 0.5) {
				// Calculate max sarcófagos: 1 + (waves past 15) / 5
				var maxSarcofagos = 1 + Math.floor((currentWave - 15) / 5);
				var sarcofagosToSpawn = Math.min(maxSarcofagos, 1); // Start with 1, increase every 5 waves
				for (var s = 0; s < sarcofagosToSpawn; s++) {
					var sarcofagoRow = Math.floor(Math.random() * gridRows);
					spawnZombie('zombie_sarcofago', sarcofagoRow);
					enemiesInWave++; // Add to enemy count
				}
			}
		}
		// Calculate enemy count with 5% increase per wave after wave 10
		var waveMultiplier = 1 + (currentWave - 10) * 0.05;
		var baseCount = 7; // Base count similar to wave 10
		var scaledEnemyCount = Math.floor(baseCount * waveMultiplier);
		bucketZombiesLeft = Math.floor(scaledEnemyCount * 0.6); // 60% bucket zombies
		// Calculate rugby zombies for endless mode (every 5 waves adds 1 more)
		var rugbyZombiesLeft = 0;
		if (currentWave >= 11) {
			var rugbyBaseCount = 3; // Base count for waves 11-15
			var additionalRugby = Math.floor((currentWave - 11) / 5); // +1 every 5 waves
			rugbyZombiesLeft = rugbyBaseCount + additionalRugby;
		}
		enemiesInWave = scaledEnemyCount + rugbyZombiesLeft + (currentWave % 5 === 0 ? 1 : 0); // Add rugby and Zombiestein if applicable
		enemiesKilled = 0;
		// Set up spawn timer for endless waves
		var normalZombiesLeft = Math.floor(scaledEnemyCount * 0.15); // 15% normal
		var coneZombiesLeft = Math.floor(scaledEnemyCount * 0.25); // 25% cone
		var spawnTimer = LK.setInterval(function () {
			if (enemiesInWave > 0) {
				var row = Math.floor(Math.random() * gridRows);
				var zombieType = null;
				// Miner zombie spawning (every wave in endless mode) - only if selected
				var shouldSpawnMinerZombie = minerZombiesSpawnedThisWave < maxMinerZombiesPerWave && selectedZombieTypes.indexOf('miner_zombie') !== -1 && Math.random() < 0.3;
				// Check if we should spawn a rugby zombie for endless mode (only if selected)
				var shouldSpawnRugbyZombie = rugbyZombiesLeft > 0 && selectedZombieTypes.indexOf('rugby_zombie') !== -1 && Math.random() < 0.2;
				// Check if we should spawn a zombie ra (odd waves excluding 1 and 3) in endless mode (only if selected)
				var shouldSpawnZombieRa = currentWave % 2 === 1 && currentWave > 3 && selectedZombieTypes.indexOf('zombie_ra') !== -1 && Math.random() < 0.25;
				// Check if we should spawn a zombie canon (wave 9+) in endless mode (only if selected)
				var shouldSpawnZombieCanon = currentWave >= 9 && selectedZombieTypes.indexOf('zombie_canon') !== -1 && Math.random() < 0.3;
				if (shouldSpawnMinerZombie) {
					zombieType = 'miner_zombie';
					minerZombiesSpawnedThisWave++;
				} else if (shouldSpawnZombieCanon) {
					zombieType = 'zombie_canon';
				} else if (shouldSpawnRugbyZombie) {
					zombieType = 'rugby_zombie';
					rugbyZombiesLeft--;
				} else if (shouldSpawnZombieRa) {
					zombieType = 'zombie_ra';
				} else {
					// Pick random zombie type from selected types (excluding special zombies)
					var availableTypes = [];
					if (selectedZombieTypes.indexOf('zombie') !== -1) {
						availableTypes.push('zombie');
					}
					if (selectedZombieTypes.indexOf('cone_zombie') !== -1) {
						availableTypes.push('cone_zombie');
					}
					if (selectedZombieTypes.indexOf('bucket_zombie') !== -1) {
						availableTypes.push('bucket_zombie');
					}
					if (selectedZombieTypes.indexOf('sun_zombie') !== -1) {
						availableTypes.push('sun_zombie');
					}
					if (selectedZombieTypes.indexOf('zombie_canon') !== -1) {
						availableTypes.push('zombie_canon');
					}
					if (selectedZombieTypes.indexOf('zombie_cascanueces') !== -1) {
						availableTypes.push('zombie_cascanueces');
					}
					if (availableTypes.length > 0) {
						var randomIndex = Math.floor(Math.random() * availableTypes.length);
						zombieType = availableTypes[randomIndex];
					}
				}
				// Only spawn if we have a valid zombie type
				if (zombieType) {
					spawnZombie(zombieType, row);
				}
				enemiesInWave--;
			} else {
				LK.clearInterval(spawnTimer);
			}
		}, 800); // Faster spawn rate for endless mode
		return; // Exit function early for endless mode
	}
	if (currentWave === 1) {
		// Wave 1: 3-4 normal zombies with collision detection
		var normalCount = Math.floor(Math.random() * 2) + 3;
		var spawnQueue = [];
		for (var i = 0; i < normalCount; i++) {
			var row = Math.floor(Math.random() * gridRows);
			// For personalize mode, check if zombie type is selected, otherwise use normal zombie
			var zombieType = 'zombie';
			if (gameMode === 'personalize' && selectedZombieTypes.indexOf('zombie') === -1) {
				// If normal zombie not selected, pick a random selected type
				if (selectedZombieTypes.length > 0) {
					var availableEndlessTypes = selectedZombieTypes.filter(function (type) {
						return type !== 'miner_zombie' && type !== 'rugby_zombie' && type !== 'zombiestein' && type !== 'zombie_sol' && type !== 'zombie_canon';
					});
					if (availableEndlessTypes.length > 0) {
						var randomIndex = Math.floor(Math.random() * availableEndlessTypes.length);
						zombieType = availableEndlessTypes[randomIndex];
					} else {
						zombieType = selectedZombieTypes[Math.floor(Math.random() * selectedZombieTypes.length)];
					}
				}
			}
			spawnQueue.push({
				type: zombieType,
				row: row,
				delay: 0
			});
		}
		// Process spawn queue with collision detection
		var spawnIndex = 0;
		var spawnProcessor = LK.setInterval(function () {
			if (spawnIndex < spawnQueue.length) {
				var spawn = spawnQueue[spawnIndex];
				if (canSpawnWithoutCollision(spawn.row)) {
					spawnZombie(spawn.type, spawn.row);
					lastSpawnTime[spawn.row] = LK.ticks;
					lastSpawnRow[spawn.row] = LK.ticks;
					spawnIndex++;
				} else {
					// Add 1 second delay
					spawn.delay += 60;
				}
			} else {
				LK.clearInterval(spawnProcessor);
			}
		}, 60); // Check every second
		enemiesInWave = normalCount;
	} else if (currentWave === 2) {
		// Wave 2: 3-4 normal zombies, 75% chance for 1 sun zombie, 1 cone zombie with collision detection
		var normalCount = Math.floor(Math.random() * 2) + 3;
		var sunZombieCount = gameMode === 'endless' && selectedZombieTypes.indexOf('sun_zombie') === -1 ? 0 : Math.random() < 0.75 ? 1 : 0;
		var coneCount = gameMode === 'endless' && selectedZombieTypes.indexOf('cone_zombie') === -1 ? 0 : 1;
		var spawnQueue = [];
		// Add normal zombies to queue
		for (var i = 0; i < normalCount; i++) {
			var row = Math.floor(Math.random() * gridRows);
			// For endless mode, check if zombie type is selected
			var zombieType = 'zombie';
			if (gameMode === 'endless' && selectedZombieTypes.indexOf('zombie') === -1) {
				// If normal zombie not selected, pick a random selected type
				if (selectedZombieTypes.length > 0) {
					var randomIndex = Math.floor(Math.random() * selectedZombieTypes.length);
					zombieType = selectedZombieTypes[randomIndex];
				}
			}
			spawnQueue.push({
				type: zombieType,
				row: row,
				delay: 0
			});
		}
		// Add sun zombie if chance succeeds and selected in endless mode
		if (sunZombieCount > 0) {
			var row = Math.floor(Math.random() * gridRows);
			spawnQueue.push({
				type: 'sun_zombie',
				row: row,
				delay: 0
			});
			sunZombieSpawnedThisWave = true;
		}
		// Add cone zombie if selected in endless mode
		if (coneCount > 0) {
			var row = Math.floor(Math.random() * gridRows);
			spawnQueue.push({
				type: 'cone_zombie',
				row: row,
				delay: 0
			});
		}
		// Process spawn queue with collision detection
		var spawnIndex = 0;
		var spawnProcessor = LK.setInterval(function () {
			if (spawnIndex < spawnQueue.length) {
				var spawn = spawnQueue[spawnIndex];
				if (canSpawnWithoutCollision(spawn.row)) {
					spawnZombie(spawn.type, spawn.row);
					lastSpawnTime[spawn.row] = LK.ticks;
					lastSpawnRow[spawn.row] = LK.ticks;
					spawnIndex++;
				} else {
					// Add 1 second delay
					spawn.delay += 60;
				}
			} else {
				LK.clearInterval(spawnProcessor);
			}
		}, 60); // Check every second
		enemiesInWave = normalCount + sunZombieCount + coneCount;
	} else if (currentWave === 3) {
		bucketZombiesLeft = gameMode === 'personalize' && selectedZombieTypes.indexOf('bucket_zombie') === -1 ? 0 : 1; // Only 1 bucket zombie in wave 3 if selected
		enemiesInWave = Math.floor(Math.random() * 2) + 3 + Math.floor(Math.random() * 2) + 1 + bucketZombiesLeft; // normal + cone + bucket
	} else if (currentWave === 4) {
		bucketZombiesLeft = gameMode === 'personalize' && selectedZombieTypes.indexOf('bucket_zombie') === -1 ? 0 : Math.floor(Math.random() * 2) + 2; // 2-3 bucket zombies if selected
		enemiesInWave = Math.floor(Math.random() * 2) + 3 + Math.floor(Math.random() * 2) + 1 + bucketZombiesLeft;
	} else if (currentWave === 5) {
		bucketZombiesLeft = gameMode === 'personalize' && selectedZombieTypes.indexOf('bucket_zombie') === -1 ? 0 : Math.floor(Math.random() * 2) + 3; // 3-4 bucket zombies if selected
		enemiesInWave = Math.floor(Math.random() * 2) + 3 + Math.floor(Math.random() * 2) + 1 + bucketZombiesLeft;
	} else {
		// From wave 6+: spawn 50% fewer zombies but increase cone/bucket probability by 25%
		bucketZombiesLeft = gameMode === 'personalize' && selectedZombieTypes.indexOf('bucket_zombie') === -1 ? 0 : Math.floor((Math.floor(Math.random() * 2) + 4 + (currentWave - 6)) * 0.5); // 50% fewer bucket zombies if selected
		enemiesInWave = Math.floor((5 + currentWave * 2) * 0.5); // 50% fewer total enemies
		// Add rugby zombies for waves 8-10
		var rugbyZombiesLeft = 0;
		if (currentWave >= 8 && currentWave <= 9 && (gameMode === 'normal' || selectedZombieTypes.indexOf('rugby_zombie') !== -1)) {
			rugbyZombiesLeft = 1;
		} else if (currentWave === 10 && (gameMode === 'normal' || selectedZombieTypes.indexOf('rugby_zombie') !== -1)) {
			rugbyZombiesLeft = 2;
		}
		enemiesInWave += rugbyZombiesLeft;
		// Spawn Zombiestein in wave 10 (only once per game)
		if (currentWave === 10 && !zombiesteinSpawned && (gameMode === 'normal' || selectedZombieTypes.indexOf('zombiestein') !== -1)) {
			var zombiesteinRow = Math.floor(Math.random() * gridRows);
			spawnZombie('zombiestein', zombiesteinRow);
			zombiesteinSpawned = true;
			zombiesteinAlive = true;
			enemiesInWave++; // Add Zombiestein to enemy count
		}
	}
	enemiesKilled = 0;
	// Only set up spawn timer for waves 3 and above (waves 1-2 spawn immediately)
	if (currentWave >= 3) {
		var normalZombiesLeft = Math.floor(Math.random() * 2) + 3;
		var coneZombiesLeft = Math.floor(Math.random() * 2) + 1;
		var spawnTimer = LK.setInterval(function () {
			if (enemiesInWave > 0) {
				var row = Math.floor(Math.random() * gridRows);
				var zombieType;
				// Determine sun zombie probability based on wave
				var sunZombieProbability = 0;
				if (currentWave === 3) {
					sunZombieProbability = 0.50;
				} else if (currentWave === 4) {
					sunZombieProbability = 0.25;
				}
				// Check if we should spawn a sun zombie (only waves 3-4, max 1 per wave)
				var shouldSpawnSunZombie = currentWave >= 3 && currentWave <= 4 && !sunZombieSpawnedThisWave && Math.random() < sunZombieProbability && (gameMode === 'normal' || selectedZombieTypes.indexOf('sun_zombie') !== -1);
				// Check if we should spawn a miner zombie (waves 6+, 100% chance, max per wave limit)
				var shouldSpawnMinerZombie = currentWave >= 6 && minerZombiesSpawnedThisWave < maxMinerZombiesPerWave && Math.random() < 1.0 && (gameMode === 'normal' || selectedZombieTypes.indexOf('miner_zombie') !== -1);
				// Check if we should spawn a rugby zombie (waves 8-10)
				var shouldSpawnRugbyZombie = currentWave >= 8 && currentWave <= 10 && rugbyZombiesLeft > 0 && Math.random() < 0.3 && (gameMode === 'normal' || selectedZombieTypes.indexOf('rugby_zombie') !== -1);
				// Check if we should spawn a zombie ra (odd waves excluding 1 and 3)
				var shouldSpawnZombieRa = currentWave % 2 === 1 && currentWave > 3 && Math.random() < 0.25 && (gameMode === 'normal' || selectedZombieTypes.indexOf('zombie_ra') !== -1);
				// Check if we should spawn a zombie canon (wave 9+, before zombiestein wave)
				var shouldSpawnZombieCanon = currentWave >= 9 && currentWave < (zombiesteinSpawned ? currentWave : 10) && Math.random() < 0.3 && (gameMode === 'normal' || selectedZombieTypes.indexOf('zombie_canon') !== -1);
				// Check if we should spawn a zombie cascanueces (waves 12, 17, 22, 27, 32, etc.)
				var shouldSpawnZombieCascanueces = (currentWave - 12) % 5 === 0 && currentWave >= 12 && Math.random() < 0.3 && (gameMode === 'normal' || selectedZombieTypes.indexOf('zombie_cascanueces') !== -1);
				if (shouldSpawnSunZombie) {
					zombieType = 'sun_zombie';
					sunZombieSpawnedThisWave = true; // Mark that sun zombie has been spawned this wave
				} else if (shouldSpawnMinerZombie) {
					zombieType = 'miner_zombie';
					minerZombiesSpawnedThisWave++; // Increment miner count for this wave
				} else if (shouldSpawnRugbyZombie) {
					zombieType = 'rugby_zombie';
					rugbyZombiesLeft--;
				} else if (shouldSpawnZombieRa) {
					zombieType = 'zombie_ra';
				} else if (shouldSpawnZombieCanon) {
					zombieType = 'zombie_canon';
				} else if (shouldSpawnZombieCascanueces) {
					zombieType = 'zombie_cascanueces';
				} else if (currentWave >= 3) {
					// From wave 3 onwards, include bucket zombies
					// For personalize mode, only spawn selected zombie types
					if (gameMode === 'personalize') {
						// Pick random zombie type from selected types (excluding special zombies)
						var availableTypes = [];
						if (selectedZombieTypes.indexOf('zombie') !== -1 && normalZombiesLeft > 0) {
							availableTypes.push('zombie');
						}
						if (selectedZombieTypes.indexOf('cone_zombie') !== -1 && coneZombiesLeft > 0) {
							availableTypes.push('cone_zombie');
						}
						if (selectedZombieTypes.indexOf('bucket_zombie') !== -1 && bucketZombiesLeft > 0) {
							availableTypes.push('bucket_zombie');
						}
						if (selectedZombieTypes.indexOf('sun_zombie') !== -1) {
							availableTypes.push('sun_zombie');
						}
						if (selectedZombieTypes.indexOf('zombie_canon') !== -1) {
							availableTypes.push('zombie_canon');
						}
						if (selectedZombieTypes.indexOf('zombie_cascanueces') !== -1) {
							availableTypes.push('zombie_cascanueces');
						}
						if (availableTypes.length > 0) {
							var randomIndex = Math.floor(Math.random() * availableTypes.length);
							zombieType = availableTypes[randomIndex];
							// Decrement counters
							if (zombieType === 'zombie') {
								normalZombiesLeft--;
							} else if (zombieType === 'cone_zombie') {
								coneZombiesLeft--;
							} else if (zombieType === 'bucket_zombie') {
								bucketZombiesLeft--;
							}
						} else {
							zombieType = 'zombie'; // fallback
						}
					} else {
						// Original logic for normal mode
						// For wave 6+, increase cone and bucket zombie probability by 25%
						if (normalZombiesLeft > 0 && coneZombiesLeft > 0 && bucketZombiesLeft > 0) {
							var rand = Math.random();
							if (currentWave >= 6) {
								// Wave 6+: 25% normal, 37.5% cone, 37.5% bucket (25% more cone/bucket)
								if (rand < 0.25) {
									zombieType = 'zombie';
									normalZombiesLeft--;
								} else if (rand < 0.625) {
									zombieType = 'cone_zombie';
									coneZombiesLeft--;
								} else {
									zombieType = 'bucket_zombie';
									bucketZombiesLeft--;
								}
							} else {
								// Wave 3-5: original probabilities
								if (rand < 0.4) {
									zombieType = 'zombie';
									normalZombiesLeft--;
								} else if (rand < 0.7) {
									zombieType = 'cone_zombie';
									coneZombiesLeft--;
								} else {
									zombieType = 'bucket_zombie';
									bucketZombiesLeft--;
								}
							}
						} else if (normalZombiesLeft > 0 && coneZombiesLeft > 0) {
							if (currentWave >= 6) {
								// Wave 6+: 35% normal, 65% cone (25% more cone)
								zombieType = Math.random() < 0.35 ? 'zombie' : 'cone_zombie';
							} else {
								// Wave 3-5: original 60/40 split
								zombieType = Math.random() < 0.6 ? 'zombie' : 'cone_zombie';
							}
							if (zombieType === 'zombie') {
								normalZombiesLeft--;
							} else {
								coneZombiesLeft--;
							}
						} else if (normalZombiesLeft > 0 && bucketZombiesLeft > 0) {
							if (currentWave >= 6) {
								// Wave 6+: 35% normal, 65% bucket (25% more bucket)
								zombieType = Math.random() < 0.35 ? 'zombie' : 'bucket_zombie';
							} else {
								// Wave 3-5: original 60/40 split
								zombieType = Math.random() < 0.6 ? 'zombie' : 'bucket_zombie';
							}
							if (zombieType === 'zombie') {
								normalZombiesLeft--;
							} else {
								bucketZombiesLeft--;
							}
						} else if (coneZombiesLeft > 0 && bucketZombiesLeft > 0) {
							zombieType = Math.random() < 0.5 ? 'cone_zombie' : 'bucket_zombie';
							if (zombieType === 'cone_zombie') {
								coneZombiesLeft--;
							} else {
								bucketZombiesLeft--;
							}
						} else if (normalZombiesLeft > 0) {
							zombieType = 'zombie';
							normalZombiesLeft--;
						} else if (coneZombiesLeft > 0) {
							zombieType = 'cone_zombie';
							coneZombiesLeft--;
						} else if (bucketZombiesLeft > 0) {
							zombieType = 'bucket_zombie';
							bucketZombiesLeft--;
						} else {
							zombieType = 'zombie'; // fallback
						}
					}
				} else {
					// Fallback for other waves
					if (gameMode === 'personalize') {
						// Pick from selected types
						var availableTypes = [];
						if (selectedZombieTypes.indexOf('zombie') !== -1) {
							availableTypes.push('zombie');
						}
						if (selectedZombieTypes.indexOf('cone_zombie') !== -1) {
							availableTypes.push('cone_zombie');
						}
						if (availableTypes.length > 0) {
							var randomIndex = Math.floor(Math.random() * availableTypes.length);
							zombieType = availableTypes[randomIndex];
						} else {
							zombieType = 'zombie'; // fallback
						}
					} else {
						zombieType = Math.random() < 0.5 ? 'zombie' : 'cone_zombie';
					}
				}
				spawnZombie(zombieType, row);
				enemiesInWave--;
			} else {
				LK.clearInterval(spawnTimer);
			}
		}, 1200);
	} // Close the if (currentWave >= 3) block
}
// Mouse move handler to update ghost plant position
game.move = function (x, y, obj) {
	if (ghostPlant && selectedPlantType) {
		var gridPos = getGridPosition(x, y);
		if (gridPos) {
			// Snap to grid position
			ghostPlant.x = gridStartX + gridPos.x * cellSize;
			ghostPlant.y = gridStartY + gridPos.y * cellSize;
			// Change color based on validity
			if (canPlacePlant(gridPos.x, gridPos.y, selectedPlantType)) {
				ghostPlant.tint = 0x88FF88; // Green tint for valid placement
			} else {
				ghostPlant.tint = 0xFF8888; // Red tint for invalid placement
			}
		} else {
			// Follow cursor if outside grid
			ghostPlant.x = x;
			ghostPlant.y = y;
			ghostPlant.tint = 0xFF8888; // Red tint when outside grid
		}
	}
};
// Game input handling
game.down = function (x, y, obj) {
	// Check if clicking on a sun
	for (var i = 0; i < suns.length; i++) {
		if (suns[i].intersects({
			x: x,
			y: y,
			width: 1,
			height: 1
		})) {
			return; // Let sun handle its own click
		}
	}
	// Check if using shovel to remove plant
	if (selectedTool === 'shovel') {
		var gridPos = getGridPosition(x, y);
		if (gridPos && plants[gridPos.y][gridPos.x] !== null) {
			// Remove the plant
			var plant = plants[gridPos.y][gridPos.x];
			plant.destroy();
			plants[gridPos.y][gridPos.x] = null;
			LK.effects.flashObject(gridCells[gridPos.y][gridPos.x], 0xFFFF00, 300);
			updatePlantSelection();
			return;
		} else if (gridPos) {
			// Flash red if trying to remove from empty square
			LK.effects.flashObject(gridCells[gridPos.y][gridPos.x], 0xFF0000, 300);
		} else {
			// Clicking outside grid cancels shovel selection
			selectedTool = null;
			shovelButton.alpha = 0.8;
			shovelButton.scaleX = shovelButton.scaleY = 1.5;
			updatePlantSelection();
		}
	}
	// Check if placing a plant
	else if (selectedPlantType) {
		var gridPos = getGridPosition(x, y);
		if (gridPos) {
			if (canPlacePlant(gridPos.x, gridPos.y, selectedPlantType)) {
				// Successfully place the plant
				if (placePlant(gridPos.x, gridPos.y, selectedPlantType)) {
					selectedPlantType = null;
					updatePlantSelection();
					return;
				}
			} else if (plants[gridPos.y][gridPos.x] !== null) {
				// Flash red if trying to place on occupied square
				LK.effects.flashObject(gridCells[gridPos.y][gridPos.x], 0xFF0000, 300);
			} else if (sunPoints < plantCosts[selectedPlantType]) {
				// Flash yellow if not enough suns
				LK.effects.flashObject(gridCells[gridPos.y][gridPos.x], 0xFFFF00, 300);
			}
		} else {
			// Clicking outside grid cancels selection
			selectedPlantType = null;
			updatePlantSelection();
		}
	}
};
// Initialize UI
updatePlantSelection();
updateSunDisplay();
updateLivesDisplay();
updateWaveDisplay();
// Skip wave button for endless mode
var skipWaveButton = null;
function createSkipWaveButton() {
	if (gameMode === 'endless' && !skipWaveButton) {
		skipWaveButton = LK.getAsset('gridcell', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 1800,
			y: 100,
			scaleX: 2,
			scaleY: 1,
			color: 0x888888 // Start gray
		});
		skipWaveButton.interactive = true;
		skipWaveButton.buttonMode = true;
		skipWaveButton.alpha = 0.5; // Start disabled
		skipWaveButton.down = function (x, y, obj) {
			if (waveInProgress) {
				// Force end current wave and start next one
				waveInProgress = false;
				wavesCompleted++;
				currentWave++;
				updateWaveDisplay();
				updateSkipWaveButton();
				// Start next wave immediately
				LK.setTimeout(function () {
					startWave();
				}, 500);
			}
		};
		game.addChild(skipWaveButton);
		var skipWaveText = new Text2('Skip Wave', {
			size: 40,
			fill: 0xFFFFFF
		});
		skipWaveText.anchor.set(0.5, 0.5);
		skipWaveText.x = 1800;
		skipWaveText.y = 100;
		game.addChild(skipWaveText);
		skipWaveButton.textElement = skipWaveText;
	}
}
function canSkipWave() {
	// Check if all zombies for current wave have been spawned
	return waveInProgress && enemiesInWave <= 0;
}
function updateSkipWaveButton() {
	if (skipWaveButton && gameMode === 'endless') {
		if (waveInProgress) {
			// Enable button - wave is in progress
			skipWaveButton.alpha = 1.0;
			skipWaveButton.tint = 0x4CAF50; // Green
			skipWaveButton.interactive = true;
		} else {
			// Disable button - no wave in progress
			skipWaveButton.alpha = 0.5;
			skipWaveButton.tint = 0x888888; // Gray
			skipWaveButton.interactive = false;
		}
	}
}
// Game will start after mode selection
// Main game loop
game.update = function () {
	// Enable lag optimization from wave 8 onwards
	if (currentWave >= 8 && !lagOptimizationActive) {
		lagOptimizationActive = true;
		console.log("Lag optimization activated for wave", currentWave);
	}
	// Performance cleanup every 3 seconds when lag optimization is active
	if (lagOptimizationActive) {
		cleanupCounter++;
		if (cleanupCounter >= 180) {
			// Every 3 seconds at 60fps
			performanceCleanup();
			cleanupCounter = 0;
		}
	}
	// Update wallnut cooldown
	if (wallnutCooldown > 0) {
		wallnutCooldown--;
		if (wallnutCooldown === 0) {
			updatePlantSelection(); // Refresh button appearance when cooldown ends
		}
	}
	// Update nuez primitiva cooldown
	if (nuezPrimitivaCooldown > 0) {
		nuezPrimitivaCooldown--;
		if (nuezPrimitivaCooldown === 0) {
			updatePlantSelection(); // Refresh button appearance when cooldown ends
		}
	}
	// Update petacereza cooldown
	if (petacerezaCooldown > 0) {
		petacerezaCooldown--;
		if (petacerezaCooldown === 0) {
			updatePlantSelection(); // Refresh button appearance when cooldown ends
		}
	}
	// Falling sun system - every 10 seconds (optimized for high waves)
	sunTimer++;
	var sunInterval = lagOptimizationActive ? 1080 : 720; // 18 seconds when optimized, 12 seconds normally
	if (sunTimer >= sunInterval) {
		// Only spawn sun if we don't have too many already
		if (suns.length < (lagOptimizationActive ? 8 : 15)) {
			var fallingSun = new Sun(Math.random() * (gridStartX + gridCols * cellSize - gridStartX) + gridStartX, -50);
			suns.push(fallingSun);
			game.addChild(fallingSun);
			// Animate falling sun
			tween(fallingSun, {
				y: Math.random() * 200 + 300
			}, {
				duration: 2400,
				easing: tween.easeOut
			});
		}
		sunTimer = 0;
	}
	// Check if current wave should end (22 seconds timer-based)
	if (waveInProgress && LK.ticks - waveStartTick >= 1584) {
		// 26.4 seconds at 60fps
		waveInProgress = false;
		wavesCompleted++;
		if (gameMode === 'normal' && wavesCompleted >= totalWaves) {
			// Check if Zombiestein was spawned and is still alive
			if (zombiesteinSpawned && zombiesteinAlive) {
				// Don't end game until Zombiestein is defeated
				console.log("All waves completed but Zombiestein still alive!");
				return;
			}
			LK.effects.flashScreen(0x4CAF50, 1000);
			LK.showYouWin();
			return;
		} else if (gameMode === 'endless') {
			// For endless mode, just continue to next wave
			// Reset Zombiestein spawn flag for next potential spawn
			if (currentWave % 5 === 0) {
				zombiesteinSpawned = false;
				zombiesteinAlive = false;
			}
		}
		currentWave++;
		updateWaveDisplay();
		// Start next wave after delay
		LK.setTimeout(function () {
			startWave();
		}, 3000);
	}
	// Update skip wave button state
	if (gameMode === 'endless') {
		updateSkipWaveButton();
	}
	// Auto-start next wave if no wave in progress and we haven't completed all waves (and mode is selected)
	if (gameModeSelected && !waveInProgress && (gameMode === 'endless' || wavesCompleted < totalWaves) && !nextWaveScheduled) {
		nextWaveScheduled = true;
		LK.setTimeout(function () {
			nextWaveScheduled = false;
			startWave();
		}, 1000);
	}
}; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var CanonShell = Container.expand(function () {
	var self = Container.call(this);
	self.speed = 3.2; // 4x normal zombie speed (0.8 * 4)
	self.damage = 20;
	self.hasExploded = false;
	self.hasReachedColumn6 = false;
	self.gridY = 0;
	var graphics = self.attachAsset('canonShell', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		// Move left towards plants
		self.x -= self.speed;
		// Check if reached column 3
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		if (cellX <= 2 && !self.hasReachedColumn6) {
			self.hasReachedColumn6 = true;
			self.explode();
			return;
		}
		// Check collision with plants
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		if (cellX >= 0 && cellX < gridCols && plants[self.gridY] && plants[self.gridY][cellX]) {
			var plant = plants[self.gridY][cellX];
			if (self.intersects(plant)) {
				plant.takeDamage(self.damage);
				self.explode();
				return;
			}
		}
		// Remove if goes off screen
		if (self.x < -100) {
			self.removeFromGame();
		}
	};
	self.explode = function () {
		if (self.hasExploded) {
			return;
		}
		self.hasExploded = true;
		// Create explosion effect
		var explosion = LK.getAsset('explosion', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y,
			scaleX: 1.5,
			scaleY: 1.5
		});
		game.addChild(explosion);
		// Animate explosion and remove it
		tween(explosion, {
			scaleX: 0.1,
			scaleY: 0.1,
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		// Transform shell into normal zombidito at current position
		var zombidito = new Zombidito();
		zombidito.x = self.x;
		zombidito.y = self.y;
		zombidito.gridY = self.gridY;
		enemies.push(zombidito);
		game.addChild(zombidito);
		// Remove shell
		self.removeFromGame();
	};
	self.removeFromGame = function () {
		for (var i = 0; i < canonShells.length; i++) {
			if (canonShells[i] === self) {
				canonShells.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	return self;
});
var Lawnmower = Container.expand(function (row) {
	var self = Container.call(this);
	self.gridY = row;
	self.speed = 0;
	self.isActivated = false;
	self.x = gridStartX - 100;
	self.y = gridStartY + row * cellSize;
	var graphics = self.attachAsset('lawnmower', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.activate = function () {
		if (!self.isActivated) {
			self.isActivated = true;
			self.speed = 6.4;
		}
	};
	self.update = function () {
		if (self.isActivated) {
			self.x += self.speed;
			// Check collision with zombies
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				if (enemy.gridY === self.gridY && self.intersects(enemy)) {
					enemy.die();
					// Count as player kill for score tracking
					enemiesKilled++;
				}
			}
			// Remove lawnmower when it reaches right edge
			if (self.x > 2148) {
				self.removeFromGame();
			}
		}
	};
	self.removeFromGame = function () {
		for (var i = 0; i < lawnmowers.length; i++) {
			if (lawnmowers[i] === self) {
				lawnmowers.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	return self;
});
var PlantBase = Container.expand(function (plantType) {
	var self = Container.call(this);
	self.plantType = plantType;
	self.health = 100;
	self.maxHealth = 100;
	self.cost = 50;
	self.shootTimer = 0;
	self.shootDelay = 72;
	self.gridX = 0;
	self.gridY = 0;
	self.level = 1;
	var graphics = self.attachAsset(plantType, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xFF0000, 200);
		if (self.health <= 0) {
			self.die();
		}
	};
	self.die = function () {
		// Clean up projectile tracking for this plant
		var plantId = self.gridX + '_' + self.gridY;
		if (plantProjectileCount[plantId]) {
			delete plantProjectileCount[plantId];
		}
		plants[self.gridY][self.gridX] = null;
		self.destroy();
	};
	return self;
});
var Wallnut = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'wallnut');
	self.cost = 50;
	self.health = 300;
	self.maxHealth = 300;
	self.isDamaged = false;
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		originalTakeDamage(damage);
		// Check if wallnut should switch to damaged appearance
		if (self.health < 150 && !self.isDamaged) {
			self.isDamaged = true;
			// Remove current graphics and add damaged version
			self.removeChild(self.children[0]);
			var damagedGraphics = self.attachAsset('wallnut_damaged', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	return self;
});
var Sunflower = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'sunflower');
	self.cost = 50;
	self.sunTimer = 0;
	self.update = function () {
		self.sunTimer++;
		if (self.sunTimer >= 1080) {
			// 18 seconds
			var sun = new Sun(self.x, self.y - 60);
			suns.push(sun);
			game.addChild(sun);
			self.sunTimer = 0;
			LK.effects.flashObject(self, 0xFFFF00, 300);
		}
	};
	return self;
});
var SnowPea = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'snowpea');
	self.cost = 175;
	self.health = 120;
	self.maxHealth = 120;
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			var target = self.findTarget();
			if (target) {
				self.shoot(target);
				self.shootTimer = 0;
			}
		}
	};
	self.findTarget = function () {
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && enemy.x > self.x) {
				return enemy;
			}
		}
		return null;
	};
	self.shoot = function (target) {
		var plantId = self.gridX + '_' + self.gridY; // Unique plant identifier
		var pea = createProjectile('snowshot', self.x, self.y, 5.12, 25 * self.level, plantId); // 6.4 * 0.8 = 5.12 (20% slower)
		if (pea) {
			LK.getSound('shoot').play();
		}
	};
	return self;
});
var Repetidora = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'repetidora');
	self.cost = 200;
	self.isTrackingFirstPea = false;
	self.firstPea = null;
	self.firstPeaStartX = 0;
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			var target = self.findTarget();
			if (target && !self.isTrackingFirstPea) {
				var firstPea = self.shoot(target);
				if (firstPea) {
					self.firstPea = firstPea;
					self.firstPeaStartX = firstPea.x;
					self.isTrackingFirstPea = true;
				}
				self.shootTimer = 0;
			}
		}
		// Handle second pea timing based on first pea position
		if (self.isTrackingFirstPea && self.firstPea) {
			// Check if first pea has advanced half a cell (72 pixels)
			if (self.firstPea.x >= self.firstPeaStartX + 72) {
				var target = self.findTarget();
				if (target) {
					self.shoot(target);
				}
				// Stop tracking to prevent lag
				self.isTrackingFirstPea = false;
				self.firstPea = null;
			}
			// Also stop tracking if first pea no longer exists
			else if (!self.firstPea.parent) {
				self.isTrackingFirstPea = false;
				self.firstPea = null;
			}
		}
	};
	self.findTarget = function () {
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && enemy.x > self.x) {
				return enemy;
			}
		}
		return null;
	};
	self.shoot = function (target) {
		var plantId = self.gridX + '_' + self.gridY; // Unique plant identifier
		var pea = createProjectile('pea', self.x, self.y, 8.64, 20 * self.level, plantId);
		if (pea) {
			LK.getSound('shoot').play();
		}
		return pea; // Return the pea for tracking
	};
	return self;
});
var Rapaz = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'rapaz');
	self.cost = 325;
	self.health = 425;
	self.maxHealth = 425;
	self.damageTimer = 0; // Timer for dealing damage to high-HP zombies
	self.cooldownTimer = 0; // Timer for cooldown after killing zombie <400 HP
	self.isOnCooldown = false; // Track if rapaz is on cooldown
	self.targetZombie = null; // Track zombie being consumed
	var graphics = self.children[0]; // Reference to graphics for color changes
	self.update = function () {
		// Handle cooldown timer
		if (self.isOnCooldown && self.cooldownTimer > 0) {
			self.cooldownTimer--;
			if (self.cooldownTimer === 0) {
				// End cooldown - restore normal color
				self.isOnCooldown = false;
				tween(graphics, {
					tint: 0xFFFFFF
				}, {
					duration: 200,
					easing: tween.easeOut
				});
			}
			return; // Don't attack while on cooldown
		}
		self.damageTimer++;
		// Check every 60 ticks (1 second) for zombies to attack
		if (self.damageTimer >= 60) {
			// Skip if rapaz is already consuming a zombie
			if (self.targetZombie && self.targetZombie.parent) {
				return; // Don't attack while already consuming
			}
			var targetZombies = self.findTargetZombies();
			for (var i = 0; i < targetZombies.length; i++) {
				var zombie = targetZombies[i];
				// Skip zombies already being consumed
				if (zombie.beingConsumed) {
					continue;
				}
				if (zombie.health < 400) {
					// Mark zombie as being consumed and make it move toward rapaz
					zombie.beingConsumed = true;
					zombie.consumingPlant = self;
					self.targetZombie = zombie;
					zombie.speed = 0.8 * 4; // 4x normal zombie speed
					zombie.damage = 0; // Stop attacking while being consumed
					// Start continuous rotation while moving
					zombie.rotationSpeed = 0.15; // Rotation speed per frame
					break; // Only consume one zombie per cycle
				} else {
					// Deal 25 damage to zombie with ≥400 HP
					zombie.takeDamage(25);
					// Add flashing effect to zombie when taking damage from rapaz
					tween(zombie, {
						tint: 0xFF0000
					}, {
						duration: 100,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(zombie, {
								tint: 0xFFFFFF
							}, {
								duration: 100,
								easing: tween.easeOut
							});
						}
					});
					// Check if zombie now has <400 HP and should be consumed
					if (zombie.health < 400 && zombie.parent) {
						// Mark zombie as being consumed
						zombie.beingConsumed = true;
						zombie.consumingPlant = self;
						self.targetZombie = zombie;
						zombie.speed = 0.8 * 4; // 4x normal zombie speed
						zombie.damage = 0; // Stop attacking while being consumed
						// Start continuous rotation while moving
						zombie.rotationSpeed = 0.15; // Rotation speed per frame
						break; // Only consume one zombie per cycle
					}
				}
			}
			self.damageTimer = 0;
		}
		// Check if target zombie has collided with rapaz
		if (self.targetZombie && self.targetZombie.parent) {
			// Check for collision between rapaz and consuming zombie
			if (self.intersects(self.targetZombie)) {
				// Zombie reached rapaz - consume it immediately
				// First remove zombie from enemies array to prevent other systems from accessing it
				for (var i = 0; i < enemies.length; i++) {
					if (enemies[i] === self.targetZombie) {
						enemies.splice(i, 1);
						break;
					}
				}
				// Destroy the zombie
				self.targetZombie.destroy();
				enemiesKilled++;
				self.targetZombie = null;
				// Start 10 second cooldown and gray out the plant
				self.isOnCooldown = true;
				self.cooldownTimer = 600; // 10 seconds at 60fps
				tween(graphics, {
					tint: 0x888888 // Gray tint
				}, {
					duration: 200,
					easing: tween.easeOut
				});
			}
		} else if (self.targetZombie && !self.targetZombie.parent) {
			// Target zombie was destroyed, clear reference
			self.targetZombie = null;
		}
	};
	self.findTargetZombies = function () {
		var targets = [];
		// Check current cell and seven cells in front (8 total cells)
		for (var checkX = self.gridX; checkX <= self.gridX + 7 && checkX < gridCols; checkX++) {
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				var enemyGridX = Math.floor((enemy.x - gridStartX + cellSize / 2) / cellSize);
				// Check if zombie is in the target cell
				if (enemy.gridY === self.gridY && enemyGridX === checkX) {
					targets.push(enemy);
				}
			}
		}
		return targets;
	};
	// Override die to clean up consumed zombie
	var originalDie = self.die;
	self.die = function () {
		// If consuming a zombie, release it from consumption
		if (self.targetZombie && self.targetZombie.parent) {
			self.targetZombie.beingConsumed = false;
			self.targetZombie.consumingPlant = null;
			self.targetZombie.speed = self.targetZombie.originalSpeed;
			self.targetZombie.damage = 25; // Restore normal damage
			self.targetZombie.rotationSpeed = 0; // Stop continuous rotation
			if (self.targetZombie.children[0]) {
				self.targetZombie.children[0].rotation = 0; // Reset rotation
			}
		}
		originalDie();
	};
	return self;
});
var Plantorcha = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'plantorcha');
	self.cost = 175;
	self.health = 300;
	self.maxHealth = 300;
	// Plantorcha doesn't shoot - it only converts projectiles
	self.update = function () {
		// No shooting behavior - just exists to convert projectiles
	};
	return self;
});
var Petacereza = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'petacereza');
	self.cost = 150;
	self.health = 1; // Very low health since it explodes
	self.maxHealth = 1;
	self.isArmed = false; // Zombies ignore it until armed
	self.armTimer = 90; // 1.5 seconds at 60fps
	self.update = function () {
		if (self.armTimer > 0) {
			self.armTimer--;
			if (self.armTimer === 0) {
				// Arm the petacereza and explode
				self.isArmed = true;
				self.explode();
			}
		}
	};
	self.explode = function () {
		// Create explosion effect
		var explosion = LK.getAsset('explosion', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y,
			scaleX: 3,
			// Larger explosion for 3x3 area
			scaleY: 3
		});
		game.addChild(explosion);
		// Animate explosion and remove it
		tween(explosion, {
			scaleX: 0.1,
			scaleY: 0.1,
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
		// Damage all zombies in 3x3 grid area around petacereza
		var centerGridX = self.gridX;
		var centerGridY = self.gridY;
		var damagedEnemies = []; // Track enemies to damage
		// First pass: identify all enemies in range
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			var enemyGridX = Math.floor((enemy.x - gridStartX + cellSize / 2) / cellSize);
			var enemyGridY = enemy.gridY;
			// Check if enemy is within 3x3 area (center ± 1 in both directions)
			var deltaX = Math.abs(enemyGridX - centerGridX);
			var deltaY = Math.abs(enemyGridY - centerGridY);
			if (deltaX <= 1 && deltaY <= 1) {
				damagedEnemies.push(enemy);
			}
		}
		// Second pass: damage all identified enemies
		for (var j = 0; j < damagedEnemies.length; j++) {
			damagedEnemies[j].takeDamage(325);
		}
		// Remove petacereza after explosion
		self.die();
	};
	// Override getPlantInFront for zombies to ignore unarmed petacereza
	self.shouldBeIgnoredByZombies = function () {
		return !self.isArmed;
	};
	return self;
});
var Peashooter = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'peashooter');
	self.cost = 100;
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			var target = self.findTarget();
			if (target) {
				self.shoot(target);
				self.shootTimer = 0;
			}
		}
	};
	self.findTarget = function () {
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && enemy.x > self.x) {
				return enemy;
			}
		}
		return null;
	};
	self.shoot = function (target) {
		var plantId = self.gridX + '_' + self.gridY; // Unique plant identifier
		var pea = createProjectile('pea', self.x, self.y, 6.4, 20 * self.level, plantId);
		if (pea) {
			LK.getSound('shoot').play();
		}
	};
	return self;
});
var NuezPrimitiva = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'nuezPrimitiva');
	self.cost = 125;
	self.health = 625;
	self.maxHealth = 625;
	self.hasChangedToWallnut = false;
	self.hasChangedToDamaged = false;
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		originalTakeDamage(damage);
		// Check if should switch to normal wallnut appearance (< 300 hp)
		if (self.health < 300 && !self.hasChangedToWallnut) {
			self.hasChangedToWallnut = true;
			// Remove current graphics and add wallnut version
			self.removeChild(self.children[0]);
			var wallnutGraphics = self.attachAsset('wallnut', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
		// Check if should switch to damaged wallnut appearance (< 150 hp)  
		else if (self.health < 150 && !self.hasChangedToDamaged) {
			self.hasChangedToDamaged = true;
			// Remove current graphics and add damaged version
			self.removeChild(self.children[0]);
			var damagedGraphics = self.attachAsset('wallnut_damaged', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	return self;
});
var Fireshot = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'fireshot');
	self.cost = 100;
	self.health = 150;
	self.maxHealth = 150;
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			var target = self.findTarget();
			if (target) {
				self.shoot(target);
				self.shootTimer = 0;
			}
		}
	};
	self.findTarget = function () {
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && enemy.x > self.x) {
				return enemy;
			}
		}
		return null;
	};
	self.shoot = function (target) {
		var plantId = self.gridX + '_' + self.gridY; // Unique plant identifier
		// Calculate damage based on target type
		var damage = 35 * self.level;
		if (target.zombieType === 'cone_zombie' || target.zombieType === 'bucket_zombie') {
			damage = 50 * self.level;
		}
		var pea = createProjectile('shotfire', self.x, self.y, 6.4, damage, plantId);
		if (pea) {
			LK.getSound('shoot').play();
		}
	};
	return self;
});
var Carnivora = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'carnivora');
	self.cost = 25;
	self.health = 300;
	self.maxHealth = 300;
	self.damageTimer = 0; // Timer for dealing damage to high-HP zombies
	self.cooldownTimer = 0; // Timer for cooldown after killing zombie <400 HP
	self.isOnCooldown = false; // Track if carnivora is on cooldown
	var graphics = self.children[0]; // Reference to graphics for color changes
	self.update = function () {
		// Handle cooldown timer
		if (self.isOnCooldown && self.cooldownTimer > 0) {
			self.cooldownTimer--;
			if (self.cooldownTimer === 0) {
				// End cooldown - restore normal color
				self.isOnCooldown = false;
				tween(graphics, {
					tint: 0xFFFFFF
				}, {
					duration: 200,
					easing: tween.easeOut
				});
			}
			return; // Don't attack while on cooldown
		}
		self.damageTimer++;
		// Check every 60 ticks (1 second) for zombies to attack
		if (self.damageTimer >= 60) {
			var targetZombies = self.findTargetZombies();
			for (var i = 0; i < targetZombies.length; i++) {
				var zombie = targetZombies[i];
				if (zombie.health < 400) {
					// Instantly kill zombie with <400 HP
					zombie.die();
					enemiesKilled++;
					// Start 15 second cooldown and gray out the plant
					self.isOnCooldown = true;
					self.cooldownTimer = 900; // 15 seconds at 60fps
					tween(graphics, {
						tint: 0x888888 // Gray tint
					}, {
						duration: 200,
						easing: tween.easeOut
					});
					break; // Only kill one zombie per cycle
				} else {
					// Deal 25 damage to zombie with ≥400 HP
					zombie.takeDamage(25);
					// Add flashing effect to zombie when taking damage from carnivora
					tween(zombie, {
						tint: 0xFF0000
					}, {
						duration: 100,
						easing: tween.easeOut,
						onFinish: function onFinish() {
							tween(zombie, {
								tint: 0xFFFFFF
							}, {
								duration: 100,
								easing: tween.easeOut
							});
						}
					});
					// Check if zombie now has <400 HP and kill it
					if (zombie.health < 400 && zombie.parent) {
						zombie.die();
						enemiesKilled++;
						// Start 15 second cooldown and gray out the plant
						self.isOnCooldown = true;
						self.cooldownTimer = 900; // 15 seconds at 60fps
						tween(graphics, {
							tint: 0x888888 // Gray tint
						}, {
							duration: 200,
							easing: tween.easeOut
						});
						break; // Only kill one zombie per cycle
					}
				}
			}
			self.damageTimer = 0;
		}
	};
	self.findTargetZombies = function () {
		var targets = [];
		// Check current cell and cell in front
		for (var checkX = self.gridX; checkX <= self.gridX + 1 && checkX < gridCols; checkX++) {
			for (var i = 0; i < enemies.length; i++) {
				var enemy = enemies[i];
				var enemyGridX = Math.floor((enemy.x - gridStartX + cellSize / 2) / cellSize);
				// Check if zombie is in the target cell
				if (enemy.gridY === self.gridY && enemyGridX === checkX) {
					targets.push(enemy);
				}
			}
		}
		return targets;
	};
	return self;
});
var Birasol = PlantBase.expand(function () {
	var self = PlantBase.call(this, 'birasol');
	self.cost = 125;
	self.health = 125;
	self.maxHealth = 125;
	self.sunTimer = 0;
	self.update = function () {
		self.sunTimer++;
		if (self.sunTimer >= 900) {
			// 15 seconds (900 ticks at 60fps)
			var sun1 = new Sun(self.x - 30, self.y - 60);
			var sun2 = new Sun(self.x + 30, self.y - 60);
			suns.push(sun1);
			suns.push(sun2);
			game.addChild(sun1);
			game.addChild(sun2);
			self.sunTimer = 0;
			LK.effects.flashObject(self, 0xFFFF00, 300);
		}
	};
	return self;
});
var Projectile = Container.expand(function (type, startX, startY, speed, damage) {
	var self = Container.call(this);
	self.speed = speed;
	self.damage = damage;
	self.x = startX;
	self.y = startY;
	self.type = type;
	self.gridY = Math.floor((startY - gridStartY + cellSize / 2) / cellSize);
	self.ownerId = null; // Plant that owns this projectile
	var graphics = self.attachAsset(type, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		self.x += self.speed;
		if (self.x > 2048) {
			self.removeFromGame();
			return;
		}
		// Check collision with plantorcha to convert pea to fire projectile
		if (self.type === 'pea') {
			var projectileGridX = Math.floor((self.x - gridStartX + cellSize / 2) / cellSize);
			var projectileGridY = self.gridY;
			if (projectileGridX >= 0 && projectileGridX < gridCols && projectileGridY >= 0 && projectileGridY < gridRows) {
				var plantInCell = plants[projectileGridY][projectileGridX];
				if (plantInCell && plantInCell.plantType === 'plantorcha' && self.intersects(plantInCell)) {
					// Convert pea to shotfire and add 10 damage
					self.removeChild(self.children[0]);
					var fireGraphics = self.attachAsset('shotfire', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					self.type = 'shotfire';
					self.damage += 10;
					// Continue with normal movement
				}
			}
		}
		// Only check collisions with zombies in same row and within 100px range
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && Math.abs(enemy.x - self.x) <= 100 && self.intersects(enemy)) {
				// Skip damage if zombie is being consumed by rapaz unless projectile is from rapaz
				if (!enemy.beingConsumed || enemy.beingConsumed && enemy.consumingPlant && self.ownerId && self.ownerId.includes(enemy.consumingPlant.gridX + '_' + enemy.consumingPlant.gridY)) {
					enemy.takeDamage(self.damage);
					// Apply ice effect if this is a snowshot
					if (self.type === 'snowshot') {
						enemy.applyIceEffect();
					}
					self.removeFromGame();
					break;
				}
			}
		}
	};
	self.removeFromGame = function () {
		// Decrease projectile count for the plant that owns this projectile
		if (self.ownerId && plantProjectileCount[self.ownerId]) {
			plantProjectileCount[self.ownerId]--;
		}
		for (var i = 0; i < projectiles.length; i++) {
			if (projectiles[i] === self) {
				projectiles.splice(i, 1);
				break;
			}
		}
		// Return to pool instead of destroying
		self.returnToPool();
	};
	self.returnToPool = function () {
		if (projectilePool.length < maxPoolSize) {
			self.removeChildren();
			if (self.parent) {
				self.parent.removeChild(self);
			}
			projectilePool.push(self);
		} else {
			self.destroy();
		}
	};
	return self;
});
var SlowProjectile = Projectile.expand(function (type, startX, startY, speed, damage) {
	var self = Projectile.call(this, type, startX, startY, speed, damage);
	var originalUpdate = self.update;
	self.update = function () {
		originalUpdate();
		// Only check collisions with zombies in same row and within 100px range
		for (var i = 0; i < enemies.length; i++) {
			var enemy = enemies[i];
			if (enemy.gridY === self.gridY && Math.abs(enemy.x - self.x) <= 100 && self.intersects(enemy)) {
				enemy.applySlowEffect();
				break;
			}
		}
	};
	return self;
});
var Sun = Container.expand(function (x, y) {
	var self = Container.call(this);
	self.x = x;
	self.y = y;
	self.value = 25;
	self.collectTimer = 0;
	self.isBeingAttracted = false;
	self.attractedBy = null;
	var graphics = self.attachAsset('sun', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.down = function (x, y, obj) {
		// If being attracted by zombie sol, stop the attraction
		if (self.isBeingAttracted && self.attractedBy) {
			tween.stop(self);
			self.attractedBy.targetSun = null;
			self.attractedBy.isAttractingSun = false;
			self.attractedBy.speed = self.attractedBy.originalSpeed;
			self.isBeingAttracted = false;
			self.attractedBy = null;
		}
		sunPoints += self.value;
		updateSunDisplay();
		self.collect();
	};
	self.collect = function () {
		// Clean up attraction if being collected
		if (self.isBeingAttracted && self.attractedBy) {
			tween.stop(self);
			self.attractedBy.targetSun = null;
			self.attractedBy.isAttractingSun = false;
			self.attractedBy.speed = self.attractedBy.originalSpeed;
		}
		for (var i = 0; i < suns.length; i++) {
			if (suns[i] === self) {
				suns.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	self.update = function () {
		self.collectTimer++;
		if (self.collectTimer > 720) {
			// 12 seconds timeout
			self.collect();
		}
	};
	return self;
});
var ZombieBase = Container.expand(function (zombieType) {
	var self = Container.call(this);
	self.zombieType = zombieType;
	self.health = 190;
	self.maxHealth = 190;
	self.speed = 0.8;
	self.damage = 25;
	self.gridY = 0;
	self.attackTimer = 0;
	self.slowTimer = 0;
	self.iceTimer = 0;
	self.isIced = false;
	self.originalSpeed = self.speed;
	self.beingConsumed = false; // Track if zombie is being consumed by rapaz
	self.consumingPlant = null; // Reference to the plant consuming this zombie
	var graphics = self.attachAsset(zombieType, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xFF0000, 200);
		LK.getSound('zombie_hit').play();
		if (self.health <= 0) {
			self.die();
		}
	};
	self.die = function () {
		// Check if this is Zombiestein being killed
		if (self.zombieType === 'zombiestein') {
			zombiesteinAlive = false;
		}
		for (var i = 0; i < enemies.length; i++) {
			if (enemies[i] === self) {
				enemies.splice(i, 1);
				break;
			}
		}
		self.destroy();
	};
	self.applySlowEffect = function () {
		self.slowTimer = 180;
		self.speed = self.originalSpeed * 0.5;
		graphics.tint = 0x81C784;
	};
	self.applyIceEffect = function () {
		// Set ice effect timer for 3 seconds if not already active or extend it
		self.iceTimer = 180; // 3 seconds at 60fps
		self.speed = self.originalSpeed * 0.8; // 20% slower
		// Only start the visual tween if not already iced
		if (!self.isIced) {
			self.isIced = true;
			// Calculate 35% blue tint (mix current color with blue)
			var blueColor = 0x5555FF; // Blue color
			// Apply blue tint
			tween(graphics, {
				tint: blueColor
			}, {
				duration: 100,
				easing: tween.easeOut
			});
		}
	};
	self.update = function () {
		// Handle being consumed by rapaz - move toward the consuming plant
		if (self.beingConsumed && self.consumingPlant) {
			// Apply continuous rotation while moving
			if (self.rotationSpeed && self.children[0]) {
				self.children[0].rotation += self.rotationSpeed;
			}
			// Move toward the rapaz plant position
			var targetX = self.consumingPlant.x;
			if (self.x > targetX) {
				self.x -= self.speed; // Move left toward rapaz
			} else {
				// Reached rapaz position, let rapaz handle consumption
			}
			return; // Skip normal update logic when being consumed
		}
		if (self.slowTimer > 0) {
			self.slowTimer--;
			if (self.slowTimer === 0) {
				self.speed = self.originalSpeed;
				graphics.tint = 0xFFFFFF;
			}
		}
		// Handle ice effect timer
		if (self.iceTimer > 0) {
			self.iceTimer--;
			if (self.iceTimer === 0) {
				// Ice effect ends
				self.isIced = false;
				self.speed = self.originalSpeed;
				// Return to normal color
				tween(graphics, {
					tint: 0xFFFFFF
				}, {
					duration: 200,
					easing: tween.easeOut
				});
			}
		}
		var plantInFront = self.getPlantInFront();
		if (plantInFront) {
			self.attackTimer++;
			if (self.attackTimer >= 72) {
				plantInFront.takeDamage(self.damage);
				self.attackTimer = 0;
			}
		} else {
			self.x -= self.speed;
			// Check if zombie reached left screen edge
			if (self.x < 0) {
				LK.effects.flashScreen(0xFF0000, 1000);
				LK.showGameOver();
				return;
			}
			// Check collision with lawnmower
			for (var i = 0; i < lawnmowers.length; i++) {
				var lawnmower = lawnmowers[i];
				if (lawnmower.gridY === self.gridY && self.x <= lawnmower.x + 60 && !lawnmower.isActivated) {
					lawnmower.activate();
				}
			}
		}
	};
	self.getPlantInFront = function () {
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		if (cellX >= 0 && cellX < gridCols && plants[self.gridY] && plants[self.gridY][cellX]) {
			var plant = plants[self.gridY][cellX];
			// Check if this is an unarmed petacereza that should be ignored
			if (plant.shouldBeIgnoredByZombies && plant.shouldBeIgnoredByZombies()) {
				return null; // Ignore unarmed petacereza
			}
			return plant;
		}
		return null;
	};
	return self;
});
var Zombiestein = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombiestein');
	self.health = 2250;
	self.maxHealth = 2250;
	self.speed = 0.414; // 10% slower than 0.46
	self.originalSpeed = 0.414;
	self.damage = 500; // 500 damage per second
	self.isSummoning = false;
	self.hasSpawnedZombidito = false;
	self.originalUpdate = self.update;
	self.update = function () {
		// Check if health is below 1500 and hasn't spawned Zombidito yet
		if (self.health < 1500 && !self.hasSpawnedZombidito && !self.isSummoning) {
			self.isSummoning = true;
			self.speed = 0; // Stop moving completely
			// Wait 1.5 seconds then spawn Zombidito
			LK.setTimeout(function () {
				// Resume movement
				self.speed = self.originalSpeed;
				self.isSummoning = false;
				self.hasSpawnedZombidito = true;
				// Calculate position 3 cells ahead (in front of Zombiestein)
				var spawnX = self.x - 3 * cellSize;
				var spawnY = self.y;
				// Create Zombidito with explosion effect
				var zombidito = new Zombidito();
				zombidito.x = spawnX;
				zombidito.y = spawnY;
				zombidito.gridY = self.gridY;
				enemies.push(zombidito);
				game.addChild(zombidito);
				// Create explosion effect like miner zombie
				var explosion = LK.getAsset('explosion', {
					anchorX: 0.5,
					anchorY: 0.5,
					x: spawnX,
					y: spawnY,
					scaleX: 2,
					scaleY: 2
				});
				game.addChild(explosion);
				// Animate explosion and remove it
				tween(explosion, {
					scaleX: 0.1,
					scaleY: 0.1,
					alpha: 0
				}, {
					duration: 800,
					easing: tween.easeOut,
					onFinish: function onFinish() {
						explosion.destroy();
					}
				});
			}, 1500);
		}
		// Call original update only if not summoning (stopped)
		if (!self.isSummoning) {
			self.originalUpdate();
		}
	};
	return self;
});
var ZombieSarcofago = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombie_sarcofago');
	self.health = 500;
	self.maxHealth = 500;
	self.speed = 0.6; // Slightly slower than normal zombie
	self.originalSpeed = 0.6;
	// Override die function to spawn normal zombie at death location
	var originalDie = self.die;
	self.die = function () {
		// Create spawned zombie at current position with 2x speed and 225 HP
		var spawnedZombie = new SpawnedZombie();
		spawnedZombie.x = self.x;
		spawnedZombie.y = self.y;
		spawnedZombie.gridY = self.gridY;
		enemies.push(spawnedZombie);
		game.addChild(spawnedZombie);
		// Call original die function
		originalDie();
	};
	return self;
});
var ZombieRa = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombieRa');
	self.health = 190;
	self.maxHealth = 190;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.isAttractingSun = false;
	self.targetSun = null;
	// Override update to handle sun attraction
	var originalUpdate = self.update;
	self.update = function () {
		// Look for uncollected suns to attract
		if (!self.isAttractingSun && !self.targetSun) {
			var closestSun = null;
			var closestDistance = Infinity;
			// Find the closest sun that isn't already being attracted
			for (var i = 0; i < suns.length; i++) {
				var sun = suns[i];
				if (!sun.isBeingAttracted) {
					var distance = Math.abs(sun.x - self.x) + Math.abs(sun.y - self.y);
					if (distance < closestDistance) {
						closestDistance = distance;
						closestSun = sun;
					}
				}
			}
			// If found a sun, start attracting it
			if (closestSun) {
				self.targetSun = closestSun;
				self.isAttractingSun = true;
				self.speed = 0; // Stop moving while attracting
				// Mark sun as being attracted so other zombie sols don't target it
				closestSun.isBeingAttracted = true;
				closestSun.attractedBy = self;
				// Start tweening sun towards zombie
				tween(closestSun, {
					x: self.x,
					y: self.y
				}, {
					duration: closestDistance / 0.6,
					// Speed reduced by 300% (was 2.4, now 0.6 = 4x slower)
					easing: tween.linear,
					onFinish: function onFinish() {
						// Sun reached zombie - consume it
						if (self.targetSun && self.targetSun.parent) {
							self.consumeSun();
						}
					}
				});
			}
		}
		// Check if sun reached zombie (collision detection)
		if (self.isAttractingSun && self.targetSun && self.targetSun.parent) {
			var distance = Math.abs(self.targetSun.x - self.x) + Math.abs(self.targetSun.y - self.y);
			if (distance < 50) {
				// Close enough to consume
				self.consumeSun();
			}
		}
		// Call original update only if not attracting sun
		if (!self.isAttractingSun) {
			originalUpdate();
		}
	};
	self.consumeSun = function () {
		if (self.targetSun && self.targetSun.parent) {
			// Remove sun from game without giving points to player
			for (var i = 0; i < suns.length; i++) {
				if (suns[i] === self.targetSun) {
					suns.splice(i, 1);
					break;
				}
			}
			self.targetSun.destroy();
			self.targetSun = null;
			self.isAttractingSun = false;
			self.speed = self.originalSpeed; // Resume movement
		}
	};
	// Override die to stop any sun attraction
	var originalDie = self.die;
	self.die = function () {
		// If attracting a sun, stop the tween and release the sun
		if (self.targetSun && self.targetSun.parent) {
			tween.stop(self.targetSun);
			self.targetSun.isBeingAttracted = false;
			self.targetSun.attractedBy = null;
		}
		originalDie();
	};
	return self;
});
var ZombieCascanueces = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'cascanueces');
	self.health = 1000;
	self.maxHealth = 1000;
	self.speed = 0.96; // Normal zombie speed (0.8) * 1.2
	self.originalSpeed = 0.96;
	self.damage = 35; // 35 damage per second
	self.isParalyzed = false;
	self.paralysisTimer = 0;
	self.paralysisTime = 600; // 10 seconds at 60fps
	self.hasReachedColumn6 = false;
	self.hasReachedColumn4 = false;
	var originalUpdate = self.update;
	self.update = function () {
		// Handle paralysis timer
		if (self.isParalyzed) {
			self.paralysisTimer--;
			if (self.paralysisTimer <= 0) {
				// Wake up from paralysis
				self.isParalyzed = false;
				self.speed = self.originalSpeed;
				// Flash animation when waking up
				tween(self, {
					alpha: 0.3
				}, {
					duration: 200,
					easing: tween.easeInOut,
					onFinish: function onFinish() {
						tween(self, {
							alpha: 1.0
						}, {
							duration: 200,
							easing: tween.easeInOut,
							onFinish: function onFinish() {
								// Second flash
								tween(self, {
									alpha: 0.3
								}, {
									duration: 200,
									easing: tween.easeInOut,
									onFinish: function onFinish() {
										tween(self, {
											alpha: 1.0
										}, {
											duration: 200,
											easing: tween.easeInOut
										});
									}
								});
							}
						});
					}
				});
			}
			return; // Don't move while paralyzed
		}
		// Check current column position
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		// Check if reached column 6 and hasn't been paralyzed there yet
		if (cellX <= 6 && !self.hasReachedColumn6 && !self.isParalyzed) {
			self.hasReachedColumn6 = true;
			self.isParalyzed = true;
			self.paralysisTimer = self.paralysisTime;
			self.speed = 0; // Stop moving
			return; // Don't move this frame
		}
		// Check if reached column 4 and hasn't been paralyzed there yet (and already passed column 6)
		if (cellX <= 4 && !self.hasReachedColumn4 && self.hasReachedColumn6 && !self.isParalyzed) {
			self.hasReachedColumn4 = true;
			self.isParalyzed = true;
			self.paralysisTimer = self.paralysisTime;
			self.speed = 0; // Stop moving
			return; // Don't move this frame
		}
		// Call original update only if not paralyzed
		if (!self.isParalyzed) {
			originalUpdate();
		}
	};
	return self;
});
var ZombieCanon = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'canon');
	self.health = 500;
	self.maxHealth = 500;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.hasReachedPosition = false;
	self.shootTimer = 0;
	self.shootDelay = 600; // 10 seconds at 60fps
	self.firstShot = true; // Track if this is the first shot
	self.damage = 0; // Canon doesn't do regular damage
	var originalUpdate = self.update;
	self.update = function () {
		// Move until reaching ninth column
		if (!self.hasReachedPosition) {
			var cellX = Math.floor((self.x - gridStartX) / cellSize);
			if (cellX <= 8) {
				self.hasReachedPosition = true;
				self.speed = 0; // Stop moving
				// Position exactly at ninth column
				self.x = gridStartX + 8 * cellSize;
			}
		}
		// If reached position, handle shooting
		if (self.hasReachedPosition) {
			self.shootTimer++;
			var currentDelay = self.firstShot ? 180 : self.shootDelay; // 3 seconds for first shot, 10 seconds for subsequent
			if (self.shootTimer >= currentDelay) {
				self.shootShell();
				self.shootTimer = 0;
				self.firstShot = false; // After first shot, use normal delay
			}
		} else {
			// Call original update to move normally
			originalUpdate();
		}
	};
	self.shootShell = function () {
		// Create zombidito shell
		var shell = new CanonShell();
		shell.x = self.x;
		shell.y = self.y;
		shell.gridY = self.gridY;
		canonShells.push(shell);
		game.addChild(shell);
	};
	return self;
});
var Zombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombie');
	self.health = 190;
	self.maxHealth = 190;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	return self;
});
var Zombidito = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombidito');
	self.health = 250;
	self.maxHealth = 250;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.damage = 50; // 50 damage per second
	// Scale down the graphics to make it smaller
	var graphics = self.children[0];
	if (graphics) {
		graphics.scaleX = 0.7;
		graphics.scaleY = 0.7;
	}
	return self;
});
var SunZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'sun_zombie');
	self.health = 190;
	self.maxHealth = 190;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	// Override die function to drop a sun when killed
	var originalDie = self.die;
	self.die = function () {
		// Create a sun at zombie's position
		var droppedSun = new Sun(self.x, self.y);
		suns.push(droppedSun);
		game.addChild(droppedSun);
		// Call original die function
		originalDie();
	};
	return self;
});
var SpawnedZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'zombie');
	self.health = 225;
	self.maxHealth = 225;
	self.speed = 1.6; // 2x normal zombie speed (0.8 * 2)
	self.originalSpeed = 1.6;
	return self;
});
var RugbyZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'rugby');
	self.health = 300;
	self.maxHealth = 300;
	self.speed = 2.4; // 3x normal zombie speed
	self.originalSpeed = 2.4;
	self.hasContactedPlant = false;
	self.damage = 0; // No regular damage since it kills instantly
	// Override getPlantInFront to handle instant kill
	self.getPlantInFront = function () {
		var cellX = Math.floor((self.x - gridStartX) / cellSize);
		if (cellX >= 0 && cellX < gridCols && plants[self.gridY] && plants[self.gridY][cellX]) {
			return plants[self.gridY][cellX];
		}
		return null;
	};
	// Override update to handle 500 damage to plants
	var originalUpdate = self.update;
	self.update = function () {
		var plantInFront = self.getPlantInFront();
		if (plantInFront && !self.hasContactedPlant) {
			// Deal 500 damage to the plant
			plantInFront.takeDamage(500);
			// Reduce speed to normal zombie speed
			self.hasContactedPlant = true;
			self.speed = 0; // Stop for 2 seconds
			self.originalSpeed = 0.8;
			// Flash effect to show speed change
			LK.effects.flashObject(self, 0xFFFF00, 500);
			// Resume normal speed after 2 seconds
			LK.setTimeout(function () {
				self.speed = 0.8;
			}, 2000);
		}
		// Call original update logic
		originalUpdate();
	};
	return self;
});
var MinerZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'miner_zombie');
	self.health = 100;
	self.maxHealth = 100;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.damage = 15;
	// Override the initialization to spawn at 5th column and show explosion
	self.initializeMiner = function (row) {
		self.gridY = row;
		// Position at 5th column (index 4)
		self.x = gridStartX + 4 * cellSize;
		self.y = gridStartY + row * cellSize;
		// Create explosion effect
		var explosion = LK.getAsset('explosion', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: self.x,
			y: self.y,
			scaleX: 2,
			scaleY: 2
		});
		game.addChild(explosion);
		// Animate explosion and remove it
		tween(explosion, {
			scaleX: 0.1,
			scaleY: 0.1,
			alpha: 0
		}, {
			duration: 800,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				explosion.destroy();
			}
		});
	};
	return self;
});
var ConeZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'cone_zombie');
	self.health = 300;
	self.maxHealth = 300;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.hasChangedAsset = false;
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		originalTakeDamage(damage);
		// Check if cone zombie should switch to normal zombie appearance
		if (self.health < 191 && !self.hasChangedAsset) {
			self.hasChangedAsset = true;
			// Remove current graphics and add normal zombie version
			self.removeChild(self.children[0]);
			var normalGraphics = self.attachAsset('zombie', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	return self;
});
var BucketZombie = ZombieBase.expand(function () {
	var self = ZombieBase.call(this, 'bucket_zombie');
	self.health = 375;
	self.maxHealth = 375;
	self.speed = 0.8;
	self.originalSpeed = 0.8;
	self.hasChangedAsset = false;
	var originalTakeDamage = self.takeDamage;
	self.takeDamage = function (damage) {
		originalTakeDamage(damage);
		// Check if bucket zombie should switch to normal zombie appearance
		if (self.health < 191 && !self.hasChangedAsset) {
			self.hasChangedAsset = true;
			// Remove current graphics and add normal zombie version
			self.removeChild(self.children[0]);
			var normalGraphics = self.attachAsset('zombie', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1B5E20
});
/**** 
* Game Code
****/ 
// Sounds
// UI and grid
// Undead enemies
// Projectiles
// Plant defenders
// Grid setup - bigger grid centered on screen
var gridRows = 5;
var gridCols = 9;
var cellSize = 144;
var gridStartX = (2048 - gridCols * cellSize) / 2;
var gridStartY = (2732 - gridRows * cellSize) / 2;
// Game state
var plants = [];
var enemies = [];
var projectiles = [];
var suns = [];
var canonShells = [];
var lawnmowers = [];
var sunPoints = 500;
var lives = 3;
var currentWave = 1;
var wavesCompleted = 0;
var totalWaves = 10;
var gameMode = null; // 'normal' or 'endless'
var gameModeSelected = false;
var zombieSelectionActive = false;
var selectedZombieTypes = [];
var customWaveConfigs = {}; // Store custom wave configurations
var currentCustomizingWave = 1;
var availableZombieTypes = [{
	type: 'zombie',
	name: 'Normal Zombie',
	asset: 'zombie'
}, {
	type: 'cone_zombie',
	name: 'Cone Zombie',
	asset: 'cone_zombie'
}, {
	type: 'bucket_zombie',
	name: 'Bucket Zombie',
	asset: 'bucket_zombie'
}, {
	type: 'sun_zombie',
	name: 'Sun Zombie',
	asset: 'sun_zombie'
}, {
	type: 'zombie_ra',
	name: 'Zombie Ra',
	asset: 'zombieRa'
}, {
	type: 'zombie_canon',
	name: 'Zombie Canon',
	asset: 'canon'
}, {
	type: 'miner_zombie',
	name: 'Miner Zombie',
	asset: 'miner_zombie'
}, {
	type: 'rugby_zombie',
	name: 'Rugby Zombie',
	asset: 'rugby'
}, {
	type: 'zombiestein',
	name: 'Zombiestein',
	asset: 'zombiestein'
}, {
	type: 'zombie_cascanueces',
	name: 'Zombie Cascanueces',
	asset: 'cascanueces'
}, {
	type: 'zombie_sarcofago',
	name: 'Zombie Sarcófago',
	asset: 'zombie_sarcofago'
}];
var baseEnemiesInWave = 0; // Store base enemy count for endless mode scaling
var waveInProgress = false;
var enemiesInWave = 0;
var enemiesKilled = 0;
var sunTimer = 0;
var waveStartTick = 0;
var nextWaveScheduled = false;
var sunZombieSpawnedThisWave = false;
// Spawn collision tracking for waves 1-2
var lastSpawnTime = {};
var lastSpawnRow = {};
// Miner zombie tracking
var minerZombiesSpawnedThisWave = 0;
var maxMinerZombiesPerWave = 1;
// Zombiestein tracking
var zombiesteinSpawned = false;
var zombiesteinAlive = false;
// Performance optimization variables
var maxObjectsPerType = 50;
var cleanupCounter = 0;
var lagOptimizationActive = false;
// Projectile pool for object reuse
var projectilePool = [];
var maxPoolSize = 20;
// Track active projectiles per plant
var plantProjectileCount = {};
// Selected plant type
var selectedPlantType = null;
var plantTypes = ['sunflower', 'birasol', 'peashooter', 'snowpea', 'fireshot', 'repetidora', 'wallnut', 'nuezPrimitiva', 'petacereza', 'carnivora', 'rapaz'];
var plantCosts = {
	'peashooter': 100,
	'sunflower': 50,
	'birasol': 225,
	'snowpea': 175,
	'fireshot': 175,
	'plantorcha': 175,
	'wallnut': 50,
	'repetidora': 200,
	'nuezPrimitiva': 125,
	'petacereza': 150,
	'carnivora': 200,
	'rapaz': 325
};
// Wallnut cooldown system
var wallnutCooldown = 0;
var wallnutCooldownTime = 720; // 12 seconds at 60fps
// Nuez primitiva cooldown system
var nuezPrimitivaCooldown = 0;
var nuezPrimitivaCooldownTime = 180; // 3 seconds at 60fps
// Petacereza cooldown system
var petacerezaCooldown = 0;
var petacerezaCooldownTime = 900; // 15 seconds at 60fps
// Ghost plant for preview
var ghostPlant = null;
// Initialize grid cells array
var gridCells = [];
// Initialize grid
for (var row = 0; row < gridRows; row++) {
	plants[row] = [];
	gridCells[row] = [];
	for (var col = 0; col < gridCols; col++) {
		plants[row][col] = null;
		var cell = LK.getAsset('gridcell', {
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.3,
			x: gridStartX + col * cellSize,
			y: gridStartY + row * cellSize
		});
		gridCells[row][col] = cell;
		game.addChild(cell);
	}
}
// Initialize lawnmowers
for (var row = 0; row < gridRows; row++) {
	var lawnmower = new Lawnmower(row);
	lawnmowers.push(lawnmower);
	game.addChild(lawnmower);
}
// Game mode selection UI
var modeSelectionContainer = new Container();
modeSelectionContainer.x = 2048 / 2;
modeSelectionContainer.y = 2732 / 2;
var modeTitle = new Text2('Select Game Mode', {
	size: 80,
	fill: 0xFFFFFF
});
modeTitle.anchor.set(0.5, 0.5);
modeTitle.y = -200;
modeSelectionContainer.addChild(modeTitle);
// Normal mode button
var normalModeButton = LK.getAsset('gridcell', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: -240,
	y: -50,
	scaleX: 2,
	scaleY: 1.5,
	color: 0x4CAF50
});
normalModeButton.interactive = true;
normalModeButton.buttonMode = true;
normalModeButton.down = function (x, y, obj) {
	gameMode = 'normal';
	totalWaves = 10;
	selectGameMode();
};
modeSelectionContainer.addChild(normalModeButton);
var normalModeText = new Text2('Normal', {
	size: 60,
	fill: 0xFFFFFF
});
normalModeText.anchor.set(0.5, 0.5);
normalModeText.x = -320;
normalModeText.y = -50;
modeSelectionContainer.addChild(normalModeText);
var normalModeSubtext = new Text2('(10 waves)', {
	size: 40,
	fill: 0xCCCCCC
});
normalModeSubtext.anchor.set(0.5, 0.5);
normalModeSubtext.x = -240;
normalModeSubtext.y = 10;
modeSelectionContainer.addChild(normalModeSubtext);
// Personalize mode button
var personalizeModeButton = LK.getAsset('gridcell', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 0,
	y: -50,
	scaleX: 2,
	scaleY: 1.5,
	color: 0xFF9800
});
personalizeModeButton.interactive = true;
personalizeModeButton.buttonMode = true;
personalizeModeButton.down = function (x, y, obj) {
	gameMode = 'personalize';
	totalWaves = 20;
	showZombieSelection();
};
modeSelectionContainer.addChild(personalizeModeButton);
var personalizeModeText = new Text2('Personalize', {
	size: 60,
	fill: 0xFFFFFF
});
personalizeModeText.anchor.set(0.5, 0.5);
personalizeModeText.x = 0;
personalizeModeText.y = -50;
modeSelectionContainer.addChild(personalizeModeText);
var personalizeModeSubtext = new Text2('(20 waves)', {
	size: 40,
	fill: 0xCCCCCC
});
personalizeModeSubtext.anchor.set(0.5, 0.5);
personalizeModeSubtext.x = 0;
personalizeModeSubtext.y = 10;
modeSelectionContainer.addChild(personalizeModeSubtext);
// Endless mode button
var endlessModeButton = LK.getAsset('gridcell', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 360,
	y: -50,
	scaleX: 2,
	scaleY: 1.5,
	color: 0x9C27B0
});
endlessModeButton.interactive = true;
endlessModeButton.buttonMode = true;
endlessModeButton.down = function (x, y, obj) {
	gameMode = 'endless';
	totalWaves = 999; // Large number for display purposes
	selectGameMode();
};
modeSelectionContainer.addChild(endlessModeButton);
var endlessModeText = new Text2('Endless', {
	size: 60,
	fill: 0xFFFFFF
});
endlessModeText.anchor.set(0.5, 0.5);
endlessModeText.x = 360;
endlessModeText.y = -50;
modeSelectionContainer.addChild(endlessModeText);
var endlessModeSubtext = new Text2('(infinite waves)', {
	size: 40,
	fill: 0xCCCCCC
});
endlessModeSubtext.anchor.set(0.5, 0.5);
endlessModeSubtext.x = 360;
endlessModeSubtext.y = 10;
modeSelectionContainer.addChild(endlessModeSubtext);
game.addChild(modeSelectionContainer);
function selectGameMode() {
	gameModeSelected = true;
	modeSelectionContainer.destroy();
	updateWaveDisplay();
	// Create skip wave button only for endless mode
	if (gameMode === 'endless') {
		createSkipWaveButton();
	}
	// Start first wave after mode selection
	LK.setTimeout(function () {
		startWave();
	}, 3000);
}
function showZombieSelection() {
	zombieSelectionActive = true;
	modeSelectionContainer.destroy();
	// Create zombie selection container
	var zombieSelectionContainer = new Container();
	zombieSelectionContainer.x = 2048 / 2;
	zombieSelectionContainer.y = 2732 / 2;
	game.addChild(zombieSelectionContainer);
	// Title
	var selectionTitle = new Text2('Select Zombies for Endless Mode', {
		size: 60,
		fill: 0xFFFFFF
	});
	selectionTitle.anchor.set(0.5, 0.5);
	selectionTitle.y = -350;
	zombieSelectionContainer.addChild(selectionTitle);
	// Instructions
	var instructions = new Text2('Click zombies to toggle selection (min 3 required)', {
		size: 40,
		fill: 0xCCCCCC
	});
	instructions.anchor.set(0.5, 0.5);
	instructions.y = -300;
	zombieSelectionContainer.addChild(instructions);
	// Create zombie selection buttons
	var zombieButtons = [];
	var cols = 4;
	var rows = Math.ceil(availableZombieTypes.length / cols);
	for (var i = 0; i < availableZombieTypes.length; i++) {
		var zombieType = availableZombieTypes[i];
		var col = i % cols;
		var row = Math.floor(i / cols);
		// Zombie button
		var zombieButton = LK.getAsset(zombieType.asset, {
			anchorX: 0.5,
			anchorY: 0.5,
			x: (col - (cols - 1) / 2) * 200,
			y: (row - (rows - 1) / 2) * 160 - 50,
			scaleX: 1.5,
			scaleY: 1.5
		});
		zombieButton.zombieType = zombieType.type;
		zombieButton.isSelected = false;
		zombieButton.interactive = true;
		zombieButton.buttonMode = true;
		zombieButton.alpha = 0.5; // Start unselected
		zombieButton.down = function (x, y, obj) {
			toggleZombieSelection(this);
		};
		zombieSelectionContainer.addChild(zombieButton);
		zombieButtons.push(zombieButton);
		// Zombie name
		var nameText = new Text2(zombieType.name, {
			size: 30,
			fill: 0xFFFFFF
		});
		nameText.anchor.set(0.5, 0.5);
		nameText.x = zombieButton.x;
		nameText.y = zombieButton.y + 80;
		zombieSelectionContainer.addChild(nameText);
	}
	// Start button
	var startButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 0,
		y: 250,
		scaleX: 3,
		scaleY: 1.5,
		color: 0x4CAF50
	});
	startButton.interactive = true;
	startButton.buttonMode = true;
	startButton.alpha = 0.5; // Start disabled
	startButton.down = function (x, y, obj) {
		if (selectedZombieTypes.length >= 3) {
			zombieSelectionContainer.destroy();
			showWaveCustomization();
		}
	};
	zombieSelectionContainer.addChild(startButton);
	var startButtonText = new Text2('Customize Waves', {
		size: 50,
		fill: 0xFFFFFF
	});
	startButtonText.anchor.set(0.5, 0.5);
	startButtonText.y = 250;
	zombieSelectionContainer.addChild(startButtonText);
	// Store references for updates
	zombieSelectionContainer.zombieButtons = zombieButtons;
	zombieSelectionContainer.startButton = startButton;
	zombieSelectionContainer.startButtonText = startButtonText;
	game.zombieSelectionContainer = zombieSelectionContainer;
}
function toggleZombieSelection(button) {
	if (button.isSelected) {
		// Deselect
		button.isSelected = false;
		button.alpha = 0.5;
		button.tint = 0xFFFFFF;
		// Remove from selected array
		for (var i = 0; i < selectedZombieTypes.length; i++) {
			if (selectedZombieTypes[i] === button.zombieType) {
				selectedZombieTypes.splice(i, 1);
				break;
			}
		}
	} else {
		// Select
		button.isSelected = true;
		button.alpha = 1.0;
		button.tint = 0x00FF00;
		selectedZombieTypes.push(button.zombieType);
	}
	updateStartButton();
}
function updateStartButton() {
	var container = game.zombieSelectionContainer;
	if (!container) {
		return;
	}
	if (selectedZombieTypes.length >= 3) {
		container.startButton.alpha = 1.0;
		container.startButton.tint = 0x4CAF50;
		container.startButtonText.setText('Customize Waves (' + selectedZombieTypes.length + ' selected)');
	} else {
		container.startButton.alpha = 0.5;
		container.startButton.tint = 0x888888;
		container.startButtonText.setText('Select at least 3 zombies (' + selectedZombieTypes.length + '/3)');
	}
}
function showWaveCustomization() {
	// Initialize default configurations for all 20 waves
	for (var wave = 1; wave <= 20; wave++) {
		if (!customWaveConfigs[wave]) {
			customWaveConfigs[wave] = {};
			for (var i = 0; i < selectedZombieTypes.length; i++) {
				customWaveConfigs[wave][selectedZombieTypes[i]] = wave <= 2 ? 2 : Math.min(wave, 8); // Default quantities
			}
		}
	}
	currentCustomizingWave = 1;
	showWaveConfigUI();
}
function showWaveConfigUI() {
	// Remove existing wave config container if any
	if (game.waveConfigContainer) {
		game.waveConfigContainer.destroy();
	}
	// Create wave customization container
	var waveConfigContainer = new Container();
	waveConfigContainer.x = 2048 / 2;
	waveConfigContainer.y = 2732 / 2;
	game.addChild(waveConfigContainer);
	game.waveConfigContainer = waveConfigContainer;
	// Title
	var configTitle = new Text2('Wave ' + currentCustomizingWave + ' Configuration', {
		size: 60,
		fill: 0xFFFFFF
	});
	configTitle.anchor.set(0.5, 0.5);
	configTitle.y = -350;
	waveConfigContainer.addChild(configTitle);
	// Instructions
	var configInstructions = new Text2('Set zombie quantities for Wave ' + currentCustomizingWave + ' (1-20)', {
		size: 40,
		fill: 0xCCCCCC
	});
	configInstructions.anchor.set(0.5, 0.5);
	configInstructions.y = -300;
	waveConfigContainer.addChild(configInstructions);
	// Wave navigation buttons - positioned slightly higher
	var prevWaveButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: -400,
		y: -250,
		scaleX: 1.5,
		scaleY: 1.0,
		color: currentCustomizingWave > 1 ? 0x2196F3 : 0x666666
	});
	prevWaveButton.interactive = currentCustomizingWave > 1;
	prevWaveButton.buttonMode = currentCustomizingWave > 1;
	if (currentCustomizingWave > 1) {
		prevWaveButton.down = function () {
			currentCustomizingWave--;
			showWaveConfigUI();
		};
	}
	waveConfigContainer.addChild(prevWaveButton);
	var prevWaveText = new Text2('◀ Previous', {
		size: 40,
		fill: 0xFFFFFF
	});
	prevWaveText.anchor.set(0.5, 0.5);
	prevWaveText.x = -400;
	prevWaveText.y = -250;
	waveConfigContainer.addChild(prevWaveText);
	var nextWaveButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 400,
		y: -250,
		scaleX: 1.5,
		scaleY: 1.0,
		color: currentCustomizingWave < 20 ? 0x2196F3 : 0x666666
	});
	nextWaveButton.interactive = currentCustomizingWave < 20;
	nextWaveButton.buttonMode = currentCustomizingWave < 20;
	if (currentCustomizingWave < 20) {
		nextWaveButton.down = function () {
			currentCustomizingWave++;
			showWaveConfigUI();
		};
	}
	waveConfigContainer.addChild(nextWaveButton);
	var nextWaveText = new Text2('Next ▶', {
		size: 40,
		fill: 0xFFFFFF
	});
	nextWaveText.anchor.set(0.5, 0.5);
	nextWaveText.x = 400;
	nextWaveText.y = -250;
	waveConfigContainer.addChild(nextWaveText);
	// Add "All to 0" and "All to 1" buttons on the left side
	var allToZeroButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: -700,
		y: -50,
		scaleX: 1.5,
		scaleY: 1.0,
		color: 0xF44336
	});
	allToZeroButton.interactive = true;
	allToZeroButton.buttonMode = true;
	allToZeroButton.down = function () {
		// Set all zombie quantities to 0 for current wave
		for (var i = 0; i < selectedZombieTypes.length; i++) {
			customWaveConfigs[currentCustomizingWave][selectedZombieTypes[i]] = 0;
		}
		showWaveConfigUI(); // Refresh UI
	};
	waveConfigContainer.addChild(allToZeroButton);
	var allToZeroText = new Text2('All to 0', {
		size: 35,
		fill: 0xFFFFFF
	});
	allToZeroText.anchor.set(0.5, 0.5);
	allToZeroText.x = -700;
	allToZeroText.y = -50;
	waveConfigContainer.addChild(allToZeroText);
	var allToOneButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: -700,
		y: 20,
		scaleX: 1.5,
		scaleY: 1.0,
		color: 0x4CAF50
	});
	allToOneButton.interactive = true;
	allToOneButton.buttonMode = true;
	allToOneButton.down = function () {
		// Set all zombie quantities to 1 for current wave
		for (var i = 0; i < selectedZombieTypes.length; i++) {
			customWaveConfigs[currentCustomizingWave][selectedZombieTypes[i]] = 1;
		}
		showWaveConfigUI(); // Refresh UI
	};
	waveConfigContainer.addChild(allToOneButton);
	var allToOneText = new Text2('All to 1', {
		size: 35,
		fill: 0xFFFFFF
	});
	allToOneText.anchor.set(0.5, 0.5);
	allToOneText.x = -700;
	allToOneText.y = 20;
	waveConfigContainer.addChild(allToOneText);
	// Zombie quantity controls
	var yOffset = -100;
	var zombieControls = [];
	for (var i = 0; i < selectedZombieTypes.length; i++) {
		var zombieType = selectedZombieTypes[i];
		var zombieAsset = null;
		for (var j = 0; j < availableZombieTypes.length; j++) {
			if (availableZombieTypes[j].type === zombieType) {
				zombieAsset = availableZombieTypes[j].asset;
				break;
			}
		}
		if (zombieAsset) {
			// Zombie icon
			var zombieIcon = LK.getAsset(zombieAsset, {
				anchorX: 0.5,
				anchorY: 0.5,
				x: -300,
				y: yOffset,
				scaleX: 1.2,
				scaleY: 1.2
			});
			waveConfigContainer.addChild(zombieIcon);
			// Decrease button
			var decreaseButton = LK.getAsset('gridcell', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: -100,
				y: yOffset,
				scaleX: 0.8,
				scaleY: 0.8,
				color: 0xF44336
			});
			decreaseButton.zombieType = zombieType;
			decreaseButton.interactive = true;
			decreaseButton.buttonMode = true;
			decreaseButton.down = function () {
				var currentQty = customWaveConfigs[currentCustomizingWave][this.zombieType] || 0;
				if (currentQty > 0) {
					customWaveConfigs[currentCustomizingWave][this.zombieType] = currentQty - 1;
					showWaveConfigUI();
				}
			};
			waveConfigContainer.addChild(decreaseButton);
			var decreaseText = new Text2('-', {
				size: 50,
				fill: 0xFFFFFF
			});
			decreaseText.anchor.set(0.5, 0.5);
			decreaseText.x = -100;
			decreaseText.y = yOffset;
			waveConfigContainer.addChild(decreaseText);
			// Quantity display
			var quantity = customWaveConfigs[currentCustomizingWave][zombieType] || 0;
			var quantityText = new Text2(quantity.toString(), {
				size: 45,
				fill: 0xFFFFFF
			});
			quantityText.anchor.set(0.5, 0.5);
			quantityText.x = 0;
			quantityText.y = yOffset;
			waveConfigContainer.addChild(quantityText);
			// Increase button
			var increaseButton = LK.getAsset('gridcell', {
				anchorX: 0.5,
				anchorY: 0.5,
				x: 100,
				y: yOffset,
				scaleX: 0.8,
				scaleY: 0.8,
				color: 0x4CAF50
			});
			increaseButton.zombieType = zombieType;
			increaseButton.interactive = true;
			increaseButton.buttonMode = true;
			increaseButton.down = function () {
				var currentQty = customWaveConfigs[currentCustomizingWave][this.zombieType] || 0;
				if (currentQty < 15) {
					// Max 15 zombies per type per wave
					customWaveConfigs[currentCustomizingWave][this.zombieType] = currentQty + 1;
					showWaveConfigUI();
				}
			};
			waveConfigContainer.addChild(increaseButton);
			var increaseText = new Text2('+', {
				size: 40,
				fill: 0xFFFFFF
			});
			increaseText.anchor.set(0.5, 0.5);
			increaseText.x = 100;
			increaseText.y = yOffset;
			waveConfigContainer.addChild(increaseText);
			// Zombie name
			var zombieName = null;
			for (var k = 0; k < availableZombieTypes.length; k++) {
				if (availableZombieTypes[k].type === zombieType) {
					zombieName = availableZombieTypes[k].name;
					break;
				}
			}
			var nameText = new Text2(zombieName || zombieType, {
				size: 30,
				fill: 0xCCCCCC
			});
			nameText.anchor.set(0.5, 0.5);
			nameText.x = 300;
			nameText.y = yOffset;
			waveConfigContainer.addChild(nameText);
			yOffset += 70;
		}
	}
	// Finish customization button - positioned at bottom right
	var finishButton = LK.getAsset('gridcell', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 600,
		y: 350,
		scaleX: 3,
		scaleY: 1.5,
		color: 0x4CAF50
	});
	finishButton.interactive = true;
	finishButton.buttonMode = true;
	finishButton.down = function () {
		waveConfigContainer.destroy();
		selectGameMode();
	};
	waveConfigContainer.addChild(finishButton);
	var finishButtonText = new Text2('Start Game', {
		size: 50,
		fill: 0xFFFFFF
	});
	finishButtonText.anchor.set(0.5, 0.5);
	finishButtonText.x = 600;
	finishButtonText.y = 350;
	waveConfigContainer.addChild(finishButtonText);
}
// Shovel tool for removing plants
var selectedTool = null; // 'shovel' or null
var shovelButton = LK.getAsset('shovel', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 100,
	scaleX: 1.5,
	scaleY: 1.5
});
shovelButton.interactive = true;
shovelButton.buttonMode = true;
shovelButton.down = function (x, y, obj) {
	console.log("Shovel button clicked");
	if (selectedTool === 'shovel') {
		selectedTool = null;
		shovelButton.alpha = 0.8;
		shovelButton.scaleX = shovelButton.scaleY = 1.5;
	} else {
		selectedTool = 'shovel';
		selectedPlantType = null;
		shovelButton.alpha = 1.0;
		shovelButton.scaleX = shovelButton.scaleY = 1.8;
		updatePlantSelection();
	}
};
shovelButton.alpha = 0.8;
game.addChild(shovelButton);
// UI Elements
var sunDisplay = new Text2('Sun: ' + sunPoints, {
	size: 60,
	fill: 0xFFEB3B
});
sunDisplay.anchor.set(0, 0);
sunDisplay.x = 120; // Offset from left edge to avoid menu icon
LK.gui.topLeft.addChild(sunDisplay);
var livesDisplay = new Text2('Lives: ' + lives, {
	size: 60,
	fill: 0xF44336
});
livesDisplay.anchor.set(0, 0);
livesDisplay.y = 80;
LK.gui.topRight.addChild(livesDisplay);
var waveDisplay = new Text2('Wave: ' + currentWave + '/' + totalWaves, {
	size: 50,
	fill: 0x4CAF50
});
waveDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(waveDisplay);
// Plant selection UI at bottom
var plantButtons = [];
var uiY = 2732 - 150;
for (var i = 0; i < plantTypes.length; i++) {
	var plantType = plantTypes[i];
	var yPos = uiY;
	var xPos = 200 + i * 220;
	// Special positioning for carnivora - place it above peashooter
	if (plantType === 'carnivora') {
		xPos = 640; // Same x position as peashooter
		yPos = uiY - 266; // Above peashooter
	}
	// Special positioning for petacereza - place it above birasol
	else if (plantType === 'petacereza') {
		xPos = 420; // Same x position as birasol
		yPos = uiY - 266; // Above birasol, 10% higher than previous position (242 * 1.1 = 266)
	}
	// Special positioning for rapaz - place it above snowpea
	else if (plantType === 'rapaz') {
		xPos = 860; // Same x position as snowpea
		yPos = uiY - 266; // Above snowpea
	}
	var button = LK.getAsset(plantType, {
		anchorX: 0.5,
		anchorY: 0.5,
		x: xPos,
		y: yPos,
		scaleX: 2.25,
		scaleY: 2.25
	});
	button.plantType = plantType;
	button.interactive = true; // Enable button interactivity
	button.buttonMode = true; // Make it behave like a button
	button.down = function (x, y, obj) {
		console.log("Plant button clicked:", this.plantType, "Cost:", plantCosts[this.plantType], "Current suns:", sunPoints);
		// Check wallnut cooldown
		if (this.plantType === 'wallnut' && wallnutCooldown > 0) {
			return; // Don't allow selection during cooldown
		}
		// Check nuez primitiva cooldown
		if (this.plantType === 'nuezPrimitiva' && nuezPrimitivaCooldown > 0) {
			return; // Don't allow selection during cooldown
		}
		// Check petacereza cooldown
		if (this.plantType === 'petacereza' && petacerezaCooldown > 0) {
			return; // Don't allow selection during cooldown
		}
		if (sunPoints >= plantCosts[this.plantType]) {
			selectedPlantType = this.plantType;
			selectedTool = null;
			shovelButton.alpha = 0.8;
			shovelButton.scaleX = shovelButton.scaleY = 1.5;
			updatePlantSelection();
		}
	};
	game.addChild(button);
	plantButtons.push(button);
	// Add cost text
	var costText = new Text2(plantCosts[plantType], {
		size: 40,
		fill: 0xFFFFFF
	});
	costText.anchor.set(0.5, 0);
	costText.x = button.x;
	costText.y = button.y + 80;
	game.addChild(costText);
}
// Add plantorcha button above sunflower
var plantorchaButton = LK.getAsset('plantorcha', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 200,
	// Same x as sunflower
	y: uiY - 351,
	// Above sunflower with 10% more space above previous position (319 * 1.1 = 351)
	scaleX: 2.25,
	scaleY: 2.25
});
plantorchaButton.plantType = 'plantorcha';
plantorchaButton.interactive = true;
plantorchaButton.buttonMode = true;
plantorchaButton.down = function (x, y, obj) {
	console.log("Plant button clicked:", this.plantType, "Cost:", plantCosts[this.plantType], "Current suns:", sunPoints);
	if (sunPoints >= plantCosts[this.plantType]) {
		selectedPlantType = this.plantType;
		selectedTool = null;
		shovelButton.alpha = 0.8;
		shovelButton.scaleX = shovelButton.scaleY = 1.5;
		updatePlantSelection();
	}
};
game.addChild(plantorchaButton);
plantButtons.push(plantorchaButton);
// Add plantorcha cost text
var plantorchaCostText = new Text2(plantCosts['plantorcha'], {
	size: 40,
	fill: 0xFFFFFF
});
plantorchaCostText.anchor.set(0.5, 0);
plantorchaCostText.x = plantorchaButton.x;
plantorchaCostText.y = plantorchaButton.y + 80;
game.addChild(plantorchaCostText);
function updatePlantSelection() {
	for (var i = 0; i < plantButtons.length; i++) {
		if (plantButtons[i].plantType === selectedPlantType) {
			plantButtons[i].alpha = 1.0;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.55;
		} else if (plantButtons[i].plantType === 'wallnut' && wallnutCooldown > 0) {
			// Gray out wallnut during cooldown
			plantButtons[i].alpha = 0.3;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.25;
			plantButtons[i].tint = 0x888888;
		} else if (plantButtons[i].plantType === 'nuezPrimitiva' && nuezPrimitivaCooldown > 0) {
			// Gray out nuez primitiva during cooldown
			plantButtons[i].alpha = 0.3;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.25;
			plantButtons[i].tint = 0x888888;
		} else if (plantButtons[i].plantType === 'petacereza' && petacerezaCooldown > 0) {
			// Gray out petacereza during cooldown
			plantButtons[i].alpha = 0.3;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.25;
			plantButtons[i].tint = 0x888888;
		} else {
			plantButtons[i].alpha = 0.6;
			plantButtons[i].scaleX = plantButtons[i].scaleY = 2.25;
			plantButtons[i].tint = 0xFFFFFF;
		}
	}
	// Remove existing ghost plant
	if (ghostPlant) {
		ghostPlant.destroy();
		ghostPlant = null;
	}
	// Create new ghost plant if a type is selected
	if (selectedPlantType) {
		ghostPlant = LK.getAsset(selectedPlantType, {
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.6,
			tint: 0x88FF88
		});
		game.addChild(ghostPlant);
	}
	// Highlight valid placement squares
	for (var row = 0; row < gridRows; row++) {
		for (var col = 0; col < gridCols; col++) {
			if (selectedPlantType && canPlacePlant(col, row, selectedPlantType)) {
				// Green highlight for valid empty squares
				gridCells[row][col].tint = 0x00FF00;
				gridCells[row][col].alpha = 0.7;
			} else if (selectedPlantType && plants[row][col] !== null) {
				// Red highlight for occupied squares when plant is selected
				gridCells[row][col].tint = 0xFF0000;
				gridCells[row][col].alpha = 0.5;
			} else if (selectedTool === 'shovel' && plants[row][col] !== null) {
				// Yellow highlight for plants that can be removed with shovel
				gridCells[row][col].tint = 0xFFFF00;
				gridCells[row][col].alpha = 0.7;
			} else {
				// Normal appearance for unselected or invalid squares
				gridCells[row][col].tint = 0xFFFFFF;
				gridCells[row][col].alpha = 0.3;
			}
		}
	}
}
function updateSunDisplay() {
	sunDisplay.setText('Sun: ' + sunPoints);
}
function updateLivesDisplay() {
	livesDisplay.setText('Lives: ' + lives);
}
function updateWaveDisplay() {
	if (gameMode === 'endless') {
		waveDisplay.setText('Wave: ' + currentWave + ' / ∞');
	} else if (gameMode === 'personalize') {
		waveDisplay.setText('Wave: ' + currentWave + '/' + totalWaves);
	} else {
		waveDisplay.setText('Wave: ' + currentWave + '/' + totalWaves);
	}
}
function createProjectile(type, startX, startY, speed, damage, plantId) {
	// Check if plant already has 2 active projectiles
	if (!plantProjectileCount[plantId]) {
		plantProjectileCount[plantId] = 0;
	}
	if (plantProjectileCount[plantId] >= 2) {
		return null; // Don't create projectile if plant already has 2
	}
	var projectile;
	if (projectilePool.length > 0) {
		// Reuse from pool
		projectile = projectilePool.pop();
		projectile.speed = speed;
		projectile.damage = damage;
		projectile.x = startX;
		projectile.y = startY;
		projectile.type = type;
		projectile.gridY = Math.floor((startY - gridStartY + cellSize / 2) / cellSize);
		projectile.ownerId = plantId;
		// Re-add graphics
		var graphics = projectile.attachAsset(type, {
			anchorX: 0.5,
			anchorY: 0.5
		});
	} else {
		// Create new projectile
		projectile = new Projectile(type, startX, startY, speed, damage);
		projectile.ownerId = plantId;
	}
	plantProjectileCount[plantId]++;
	projectiles.push(projectile);
	game.addChild(projectile);
	return projectile;
}
function performanceCleanup() {
	// Clean up destroyed objects that might still be in arrays
	for (var i = enemies.length - 1; i >= 0; i--) {
		if (!enemies[i].parent) {
			enemies.splice(i, 1);
		}
	}
	for (var i = projectiles.length - 1; i >= 0; i--) {
		if (!projectiles[i].parent) {
			projectiles.splice(i, 1);
		}
	}
	for (var i = suns.length - 1; i >= 0; i--) {
		if (!suns[i].parent) {
			suns.splice(i, 1);
		}
	}
	for (var i = canonShells.length - 1; i >= 0; i--) {
		if (!canonShells[i].parent) {
			canonShells.splice(i, 1);
		}
	}
	// Clean up projectile tracking for destroyed plants
	for (var plantId in plantProjectileCount) {
		var coords = plantId.split('_');
		var x = parseInt(coords[0]);
		var y = parseInt(coords[1]);
		if (y >= 0 && y < gridRows && x >= 0 && x < gridCols && !plants[y][x]) {
			delete plantProjectileCount[plantId];
		}
	}
	// Limit maximum objects if we have too many
	if (enemies.length > maxObjectsPerType) {
		for (var i = 0; i < enemies.length - maxObjectsPerType; i++) {
			if (enemies[i]) {
				enemies[i].destroy();
			}
		}
	}
	if (projectiles.length > maxObjectsPerType) {
		for (var i = 0; i < projectiles.length - maxObjectsPerType; i++) {
			if (projectiles[i]) {
				projectiles[i].removeFromGame();
			}
		}
	}
	if (suns.length > 20) {
		for (var i = 0; i < suns.length - 20; i++) {
			if (suns[i]) {
				suns[i].destroy();
			}
		}
	}
	// Limit projectile pool size
	if (projectilePool.length > maxPoolSize) {
		for (var i = maxPoolSize; i < projectilePool.length; i++) {
			if (projectilePool[i]) {
				projectilePool[i].destroy();
			}
		}
		projectilePool.length = maxPoolSize;
	}
}
function getGridPosition(x, y) {
	var gridX = Math.floor((x - gridStartX + cellSize / 2) / cellSize);
	var gridY = Math.floor((y - gridStartY + cellSize / 2) / cellSize);
	if (gridX >= 0 && gridX < gridCols && gridY >= 0 && gridY < gridRows) {
		return {
			x: gridX,
			y: gridY
		};
	}
	return null;
}
function canPlacePlant(gridX, gridY, plantType) {
	// Check if grid position is valid
	if (gridX < 0 || gridX >= gridCols || gridY < 0 || gridY >= gridRows) {
		return false;
	}
	// Check wallnut cooldown
	if (plantType === 'wallnut' && wallnutCooldown > 0) {
		return false;
	}
	// Check nuez primitiva cooldown
	if (plantType === 'nuezPrimitiva' && nuezPrimitivaCooldown > 0) {
		return false;
	}
	// Check petacereza cooldown
	if (plantType === 'petacereza' && petacerezaCooldown > 0) {
		return false;
	}
	// Check if square is empty and player has enough suns
	return plants[gridY][gridX] === null && sunPoints >= plantCosts[plantType];
}
function placePlant(gridX, gridY, plantType) {
	// Double-check that placement is valid before proceeding
	if (!canPlacePlant(gridX, gridY, plantType)) {
		return false;
	}
	var plant;
	switch (plantType) {
		case 'peashooter':
			plant = new Peashooter();
			break;
		case 'sunflower':
			plant = new Sunflower();
			break;
		case 'birasol':
			plant = new Birasol();
			break;
		case 'snowpea':
			plant = new SnowPea();
			break;
		case 'fireshot':
			plant = new Fireshot();
			break;
		case 'plantorcha':
			plant = new Plantorcha();
			break;
		case 'wallnut':
			plant = new Wallnut();
			break;
		case 'snowpea':
			plant = new SnowPea();
			break;
		case 'repetidora':
			plant = new Repetidora();
			break;
		case 'nuezPrimitiva':
			plant = new NuezPrimitiva();
			break;
		case 'petacereza':
			plant = new Petacereza();
			break;
		case 'carnivora':
			plant = new Carnivora();
			break;
		case 'rapaz':
			plant = new Rapaz();
			break;
		default:
			return false;
	}
	// Set plant position and grid reference
	plant.gridX = gridX;
	plant.gridY = gridY;
	plant.x = gridStartX + gridX * cellSize;
	plant.y = gridStartY + gridY * cellSize;
	// Place plant in grid and add to game
	plants[gridY][gridX] = plant;
	game.addChild(plant);
	// Deduct cost and update UI
	sunPoints -= plantCosts[plantType];
	updateSunDisplay();
	LK.getSound('plant').play();
	// Start wallnut cooldown if placing wallnut
	if (plantType === 'wallnut') {
		wallnutCooldown = wallnutCooldownTime;
		selectedPlantType = null; // Deselect wallnut after placing
		updatePlantSelection();
	}
	// Start nuez primitiva cooldown if placing nuez primitiva
	if (plantType === 'nuezPrimitiva') {
		nuezPrimitivaCooldown = nuezPrimitivaCooldownTime;
		selectedPlantType = null; // Deselect nuez primitiva after placing
		updatePlantSelection();
	}
	// Start petacereza cooldown if placing petacereza
	if (plantType === 'petacereza') {
		petacerezaCooldown = petacerezaCooldownTime;
		selectedPlantType = null; // Deselect petacereza after placing
		updatePlantSelection();
	}
	// Flash the grid cell to show successful placement
	LK.effects.flashObject(gridCells[gridY][gridX], 0x00FF00, 300);
	return true;
}
function canSpawnWithoutCollision(row) {
	// Only apply collision detection for waves 1-2
	if (currentWave > 2) {
		return true;
	}
	var currentTime = LK.ticks;
	var oneSecond = 60; // 60 ticks = 1 second at 60fps
	// Check if same row was used in last second
	if (lastSpawnRow[row] && currentTime - lastSpawnRow[row] < oneSecond) {
		return false;
	}
	// Check if any zombie was spawned in last second
	for (var checkRow in lastSpawnTime) {
		if (currentTime - lastSpawnTime[checkRow] < oneSecond) {
			return false;
		}
	}
	return true;
}
function spawnZombie(type, row) {
	var zombie;
	switch (type) {
		case 'zombie':
			zombie = new Zombie();
			break;
		case 'cone_zombie':
			zombie = new ConeZombie();
			break;
		case 'bucket_zombie':
			zombie = new BucketZombie();
			break;
		case 'sun_zombie':
			zombie = new SunZombie();
			break;
		case 'zombie_ra':
			zombie = new ZombieRa();
			break;
		case 'zombie_canon':
			zombie = new ZombieCanon();
			break;
		case 'miner_zombie':
			zombie = new MinerZombie();
			// Special positioning for miner
			zombie.initializeMiner(row);
			// Apply health bonus for endless mode after wave 10
			if (gameMode === 'endless' && currentWave > 10) {
				var healthMultiplier = 1 + (currentWave - 10) * 0.05;
				zombie.health = Math.floor(zombie.health * healthMultiplier);
				zombie.maxHealth = Math.floor(zombie.maxHealth * healthMultiplier);
			}
			enemies.push(zombie);
			game.addChild(zombie);
			return;
		// Return early since positioning is handled
		case 'zombiestein':
			zombie = new Zombiestein();
			break;
		case 'rugby_zombie':
			zombie = new RugbyZombie();
			break;
		case 'zombie_cascanueces':
			zombie = new ZombieCascanueces();
			break;
		case 'zombie_sarcofago':
			zombie = new ZombieSarcofago();
			break;
		default:
			return;
	}
	zombie.gridY = row;
	zombie.x = 2100;
	zombie.y = gridStartY + row * cellSize;
	// Apply health bonus for endless mode after wave 10
	if (gameMode === 'endless' && currentWave > 10) {
		var healthMultiplier = 1 + (currentWave - 10) * 0.05;
		zombie.health = Math.floor(zombie.health * healthMultiplier);
		zombie.maxHealth = Math.floor(zombie.maxHealth * healthMultiplier);
	}
	enemies.push(zombie);
	game.addChild(zombie);
}
function startWave() {
	if (waveInProgress) {
		return;
	}
	waveInProgress = true;
	waveStartTick = LK.ticks; // Record when wave started
	sunZombieSpawnedThisWave = false; // Reset sun zombie spawn flag for this wave
	// Reset and update miner zombie tracking for this wave
	minerZombiesSpawnedThisWave = 0;
	if (currentWave >= 8) {
		maxMinerZombiesPerWave = 2;
	} else {
		maxMinerZombiesPerWave = 1;
	}
	var bucketZombiesLeft = 0;
	// Handle custom wave configurations for waves 1-20 in personalize mode
	if (gameMode === 'personalize' && currentWave <= 20 && customWaveConfigs[currentWave]) {
		var waveConfig = customWaveConfigs[currentWave];
		var totalZombies = 0;
		var spawnQueue = [];
		// Build spawn queue from custom configuration
		for (var zombieType in waveConfig) {
			var quantity = waveConfig[zombieType];
			for (var i = 0; i < quantity; i++) {
				spawnQueue.push(zombieType);
				totalZombies++;
			}
		}
		enemiesInWave = totalZombies;
		enemiesKilled = 0;
		// Spawn zombies from custom configuration
		if (spawnQueue.length > 0) {
			var spawnIndex = 0;
			var customSpawnTimer = LK.setInterval(function () {
				if (spawnIndex < spawnQueue.length) {
					var zombieType = spawnQueue[spawnIndex];
					var row = Math.floor(Math.random() * gridRows);
					spawnZombie(zombieType, row);
					spawnIndex++;
				} else {
					LK.clearInterval(customSpawnTimer);
				}
			}, 800); // Spawn every 800ms
		}
		return; // Exit early for custom waves
	}
	// Handle endless mode waves (but not personalize mode)
	if (gameMode === 'endless' && currentWave > 10) {
		// For endless mode waves 11+, spawn Zombiestein every 5 waves
		if (currentWave % 5 === 0) {
			// Calculate number of Zombiesteins to spawn based on wave
			var zombiesteinCount = Math.floor((currentWave - 10) / 5) + 1;
			for (var z = 0; z < zombiesteinCount; z++) {
				var zombiesteinRow = Math.floor(Math.random() * gridRows);
				spawnZombie('zombiestein', zombiesteinRow);
			}
			zombiesteinSpawned = true;
			zombiesteinAlive = true;
			enemiesInWave += zombiesteinCount - 1; // Adjust enemy count for additional Zombiesteins
		}
		// Zombie Sarcófago spawning logic for endless mode waves 15+
		if (currentWave >= 15) {
			// Count bucket zombies in this wave to determine if we can spawn sarcófago
			var bucketZombieCount = Math.floor(scaledEnemyCount * 0.6);
			// 50% chance to spawn if at least 2 bucket zombies
			if (bucketZombieCount >= 2 && Math.random() < 0.5) {
				// Calculate max sarcófagos: 1 + (waves past 15) / 5
				var maxSarcofagos = 1 + Math.floor((currentWave - 15) / 5);
				var sarcofagosToSpawn = Math.min(maxSarcofagos, 1); // Start with 1, increase every 5 waves
				for (var s = 0; s < sarcofagosToSpawn; s++) {
					var sarcofagoRow = Math.floor(Math.random() * gridRows);
					spawnZombie('zombie_sarcofago', sarcofagoRow);
					enemiesInWave++; // Add to enemy count
				}
			}
		}
		// Calculate enemy count with 5% increase per wave after wave 10
		var waveMultiplier = 1 + (currentWave - 10) * 0.05;
		var baseCount = 7; // Base count similar to wave 10
		var scaledEnemyCount = Math.floor(baseCount * waveMultiplier);
		bucketZombiesLeft = Math.floor(scaledEnemyCount * 0.6); // 60% bucket zombies
		// Calculate rugby zombies for endless mode (every 5 waves adds 1 more)
		var rugbyZombiesLeft = 0;
		if (currentWave >= 11) {
			var rugbyBaseCount = 3; // Base count for waves 11-15
			var additionalRugby = Math.floor((currentWave - 11) / 5); // +1 every 5 waves
			rugbyZombiesLeft = rugbyBaseCount + additionalRugby;
		}
		enemiesInWave = scaledEnemyCount + rugbyZombiesLeft + (currentWave % 5 === 0 ? 1 : 0); // Add rugby and Zombiestein if applicable
		enemiesKilled = 0;
		// Set up spawn timer for endless waves
		var normalZombiesLeft = Math.floor(scaledEnemyCount * 0.15); // 15% normal
		var coneZombiesLeft = Math.floor(scaledEnemyCount * 0.25); // 25% cone
		var spawnTimer = LK.setInterval(function () {
			if (enemiesInWave > 0) {
				var row = Math.floor(Math.random() * gridRows);
				var zombieType = null;
				// Miner zombie spawning (every wave in endless mode) - only if selected
				var shouldSpawnMinerZombie = minerZombiesSpawnedThisWave < maxMinerZombiesPerWave && selectedZombieTypes.indexOf('miner_zombie') !== -1 && Math.random() < 0.3;
				// Check if we should spawn a rugby zombie for endless mode (only if selected)
				var shouldSpawnRugbyZombie = rugbyZombiesLeft > 0 && selectedZombieTypes.indexOf('rugby_zombie') !== -1 && Math.random() < 0.2;
				// Check if we should spawn a zombie ra (odd waves excluding 1 and 3) in endless mode (only if selected)
				var shouldSpawnZombieRa = currentWave % 2 === 1 && currentWave > 3 && selectedZombieTypes.indexOf('zombie_ra') !== -1 && Math.random() < 0.25;
				// Check if we should spawn a zombie canon (wave 9+) in endless mode (only if selected)
				var shouldSpawnZombieCanon = currentWave >= 9 && selectedZombieTypes.indexOf('zombie_canon') !== -1 && Math.random() < 0.3;
				if (shouldSpawnMinerZombie) {
					zombieType = 'miner_zombie';
					minerZombiesSpawnedThisWave++;
				} else if (shouldSpawnZombieCanon) {
					zombieType = 'zombie_canon';
				} else if (shouldSpawnRugbyZombie) {
					zombieType = 'rugby_zombie';
					rugbyZombiesLeft--;
				} else if (shouldSpawnZombieRa) {
					zombieType = 'zombie_ra';
				} else {
					// Pick random zombie type from selected types (excluding special zombies)
					var availableTypes = [];
					if (selectedZombieTypes.indexOf('zombie') !== -1) {
						availableTypes.push('zombie');
					}
					if (selectedZombieTypes.indexOf('cone_zombie') !== -1) {
						availableTypes.push('cone_zombie');
					}
					if (selectedZombieTypes.indexOf('bucket_zombie') !== -1) {
						availableTypes.push('bucket_zombie');
					}
					if (selectedZombieTypes.indexOf('sun_zombie') !== -1) {
						availableTypes.push('sun_zombie');
					}
					if (selectedZombieTypes.indexOf('zombie_canon') !== -1) {
						availableTypes.push('zombie_canon');
					}
					if (selectedZombieTypes.indexOf('zombie_cascanueces') !== -1) {
						availableTypes.push('zombie_cascanueces');
					}
					if (availableTypes.length > 0) {
						var randomIndex = Math.floor(Math.random() * availableTypes.length);
						zombieType = availableTypes[randomIndex];
					}
				}
				// Only spawn if we have a valid zombie type
				if (zombieType) {
					spawnZombie(zombieType, row);
				}
				enemiesInWave--;
			} else {
				LK.clearInterval(spawnTimer);
			}
		}, 800); // Faster spawn rate for endless mode
		return; // Exit function early for endless mode
	}
	if (currentWave === 1) {
		// Wave 1: 3-4 normal zombies with collision detection
		var normalCount = Math.floor(Math.random() * 2) + 3;
		var spawnQueue = [];
		for (var i = 0; i < normalCount; i++) {
			var row = Math.floor(Math.random() * gridRows);
			// For personalize mode, check if zombie type is selected, otherwise use normal zombie
			var zombieType = 'zombie';
			if (gameMode === 'personalize' && selectedZombieTypes.indexOf('zombie') === -1) {
				// If normal zombie not selected, pick a random selected type
				if (selectedZombieTypes.length > 0) {
					var availableEndlessTypes = selectedZombieTypes.filter(function (type) {
						return type !== 'miner_zombie' && type !== 'rugby_zombie' && type !== 'zombiestein' && type !== 'zombie_sol' && type !== 'zombie_canon';
					});
					if (availableEndlessTypes.length > 0) {
						var randomIndex = Math.floor(Math.random() * availableEndlessTypes.length);
						zombieType = availableEndlessTypes[randomIndex];
					} else {
						zombieType = selectedZombieTypes[Math.floor(Math.random() * selectedZombieTypes.length)];
					}
				}
			}
			spawnQueue.push({
				type: zombieType,
				row: row,
				delay: 0
			});
		}
		// Process spawn queue with collision detection
		var spawnIndex = 0;
		var spawnProcessor = LK.setInterval(function () {
			if (spawnIndex < spawnQueue.length) {
				var spawn = spawnQueue[spawnIndex];
				if (canSpawnWithoutCollision(spawn.row)) {
					spawnZombie(spawn.type, spawn.row);
					lastSpawnTime[spawn.row] = LK.ticks;
					lastSpawnRow[spawn.row] = LK.ticks;
					spawnIndex++;
				} else {
					// Add 1 second delay
					spawn.delay += 60;
				}
			} else {
				LK.clearInterval(spawnProcessor);
			}
		}, 60); // Check every second
		enemiesInWave = normalCount;
	} else if (currentWave === 2) {
		// Wave 2: 3-4 normal zombies, 75% chance for 1 sun zombie, 1 cone zombie with collision detection
		var normalCount = Math.floor(Math.random() * 2) + 3;
		var sunZombieCount = gameMode === 'endless' && selectedZombieTypes.indexOf('sun_zombie') === -1 ? 0 : Math.random() < 0.75 ? 1 : 0;
		var coneCount = gameMode === 'endless' && selectedZombieTypes.indexOf('cone_zombie') === -1 ? 0 : 1;
		var spawnQueue = [];
		// Add normal zombies to queue
		for (var i = 0; i < normalCount; i++) {
			var row = Math.floor(Math.random() * gridRows);
			// For endless mode, check if zombie type is selected
			var zombieType = 'zombie';
			if (gameMode === 'endless' && selectedZombieTypes.indexOf('zombie') === -1) {
				// If normal zombie not selected, pick a random selected type
				if (selectedZombieTypes.length > 0) {
					var randomIndex = Math.floor(Math.random() * selectedZombieTypes.length);
					zombieType = selectedZombieTypes[randomIndex];
				}
			}
			spawnQueue.push({
				type: zombieType,
				row: row,
				delay: 0
			});
		}
		// Add sun zombie if chance succeeds and selected in endless mode
		if (sunZombieCount > 0) {
			var row = Math.floor(Math.random() * gridRows);
			spawnQueue.push({
				type: 'sun_zombie',
				row: row,
				delay: 0
			});
			sunZombieSpawnedThisWave = true;
		}
		// Add cone zombie if selected in endless mode
		if (coneCount > 0) {
			var row = Math.floor(Math.random() * gridRows);
			spawnQueue.push({
				type: 'cone_zombie',
				row: row,
				delay: 0
			});
		}
		// Process spawn queue with collision detection
		var spawnIndex = 0;
		var spawnProcessor = LK.setInterval(function () {
			if (spawnIndex < spawnQueue.length) {
				var spawn = spawnQueue[spawnIndex];
				if (canSpawnWithoutCollision(spawn.row)) {
					spawnZombie(spawn.type, spawn.row);
					lastSpawnTime[spawn.row] = LK.ticks;
					lastSpawnRow[spawn.row] = LK.ticks;
					spawnIndex++;
				} else {
					// Add 1 second delay
					spawn.delay += 60;
				}
			} else {
				LK.clearInterval(spawnProcessor);
			}
		}, 60); // Check every second
		enemiesInWave = normalCount + sunZombieCount + coneCount;
	} else if (currentWave === 3) {
		bucketZombiesLeft = gameMode === 'personalize' && selectedZombieTypes.indexOf('bucket_zombie') === -1 ? 0 : 1; // Only 1 bucket zombie in wave 3 if selected
		enemiesInWave = Math.floor(Math.random() * 2) + 3 + Math.floor(Math.random() * 2) + 1 + bucketZombiesLeft; // normal + cone + bucket
	} else if (currentWave === 4) {
		bucketZombiesLeft = gameMode === 'personalize' && selectedZombieTypes.indexOf('bucket_zombie') === -1 ? 0 : Math.floor(Math.random() * 2) + 2; // 2-3 bucket zombies if selected
		enemiesInWave = Math.floor(Math.random() * 2) + 3 + Math.floor(Math.random() * 2) + 1 + bucketZombiesLeft;
	} else if (currentWave === 5) {
		bucketZombiesLeft = gameMode === 'personalize' && selectedZombieTypes.indexOf('bucket_zombie') === -1 ? 0 : Math.floor(Math.random() * 2) + 3; // 3-4 bucket zombies if selected
		enemiesInWave = Math.floor(Math.random() * 2) + 3 + Math.floor(Math.random() * 2) + 1 + bucketZombiesLeft;
	} else {
		// From wave 6+: spawn 50% fewer zombies but increase cone/bucket probability by 25%
		bucketZombiesLeft = gameMode === 'personalize' && selectedZombieTypes.indexOf('bucket_zombie') === -1 ? 0 : Math.floor((Math.floor(Math.random() * 2) + 4 + (currentWave - 6)) * 0.5); // 50% fewer bucket zombies if selected
		enemiesInWave = Math.floor((5 + currentWave * 2) * 0.5); // 50% fewer total enemies
		// Add rugby zombies for waves 8-10
		var rugbyZombiesLeft = 0;
		if (currentWave >= 8 && currentWave <= 9 && (gameMode === 'normal' || selectedZombieTypes.indexOf('rugby_zombie') !== -1)) {
			rugbyZombiesLeft = 1;
		} else if (currentWave === 10 && (gameMode === 'normal' || selectedZombieTypes.indexOf('rugby_zombie') !== -1)) {
			rugbyZombiesLeft = 2;
		}
		enemiesInWave += rugbyZombiesLeft;
		// Spawn Zombiestein in wave 10 (only once per game)
		if (currentWave === 10 && !zombiesteinSpawned && (gameMode === 'normal' || selectedZombieTypes.indexOf('zombiestein') !== -1)) {
			var zombiesteinRow = Math.floor(Math.random() * gridRows);
			spawnZombie('zombiestein', zombiesteinRow);
			zombiesteinSpawned = true;
			zombiesteinAlive = true;
			enemiesInWave++; // Add Zombiestein to enemy count
		}
	}
	enemiesKilled = 0;
	// Only set up spawn timer for waves 3 and above (waves 1-2 spawn immediately)
	if (currentWave >= 3) {
		var normalZombiesLeft = Math.floor(Math.random() * 2) + 3;
		var coneZombiesLeft = Math.floor(Math.random() * 2) + 1;
		var spawnTimer = LK.setInterval(function () {
			if (enemiesInWave > 0) {
				var row = Math.floor(Math.random() * gridRows);
				var zombieType;
				// Determine sun zombie probability based on wave
				var sunZombieProbability = 0;
				if (currentWave === 3) {
					sunZombieProbability = 0.50;
				} else if (currentWave === 4) {
					sunZombieProbability = 0.25;
				}
				// Check if we should spawn a sun zombie (only waves 3-4, max 1 per wave)
				var shouldSpawnSunZombie = currentWave >= 3 && currentWave <= 4 && !sunZombieSpawnedThisWave && Math.random() < sunZombieProbability && (gameMode === 'normal' || selectedZombieTypes.indexOf('sun_zombie') !== -1);
				// Check if we should spawn a miner zombie (waves 6+, 100% chance, max per wave limit)
				var shouldSpawnMinerZombie = currentWave >= 6 && minerZombiesSpawnedThisWave < maxMinerZombiesPerWave && Math.random() < 1.0 && (gameMode === 'normal' || selectedZombieTypes.indexOf('miner_zombie') !== -1);
				// Check if we should spawn a rugby zombie (waves 8-10)
				var shouldSpawnRugbyZombie = currentWave >= 8 && currentWave <= 10 && rugbyZombiesLeft > 0 && Math.random() < 0.3 && (gameMode === 'normal' || selectedZombieTypes.indexOf('rugby_zombie') !== -1);
				// Check if we should spawn a zombie ra (odd waves excluding 1 and 3)
				var shouldSpawnZombieRa = currentWave % 2 === 1 && currentWave > 3 && Math.random() < 0.25 && (gameMode === 'normal' || selectedZombieTypes.indexOf('zombie_ra') !== -1);
				// Check if we should spawn a zombie canon (wave 9+, before zombiestein wave)
				var shouldSpawnZombieCanon = currentWave >= 9 && currentWave < (zombiesteinSpawned ? currentWave : 10) && Math.random() < 0.3 && (gameMode === 'normal' || selectedZombieTypes.indexOf('zombie_canon') !== -1);
				// Check if we should spawn a zombie cascanueces (waves 12, 17, 22, 27, 32, etc.)
				var shouldSpawnZombieCascanueces = (currentWave - 12) % 5 === 0 && currentWave >= 12 && Math.random() < 0.3 && (gameMode === 'normal' || selectedZombieTypes.indexOf('zombie_cascanueces') !== -1);
				if (shouldSpawnSunZombie) {
					zombieType = 'sun_zombie';
					sunZombieSpawnedThisWave = true; // Mark that sun zombie has been spawned this wave
				} else if (shouldSpawnMinerZombie) {
					zombieType = 'miner_zombie';
					minerZombiesSpawnedThisWave++; // Increment miner count for this wave
				} else if (shouldSpawnRugbyZombie) {
					zombieType = 'rugby_zombie';
					rugbyZombiesLeft--;
				} else if (shouldSpawnZombieRa) {
					zombieType = 'zombie_ra';
				} else if (shouldSpawnZombieCanon) {
					zombieType = 'zombie_canon';
				} else if (shouldSpawnZombieCascanueces) {
					zombieType = 'zombie_cascanueces';
				} else if (currentWave >= 3) {
					// From wave 3 onwards, include bucket zombies
					// For personalize mode, only spawn selected zombie types
					if (gameMode === 'personalize') {
						// Pick random zombie type from selected types (excluding special zombies)
						var availableTypes = [];
						if (selectedZombieTypes.indexOf('zombie') !== -1 && normalZombiesLeft > 0) {
							availableTypes.push('zombie');
						}
						if (selectedZombieTypes.indexOf('cone_zombie') !== -1 && coneZombiesLeft > 0) {
							availableTypes.push('cone_zombie');
						}
						if (selectedZombieTypes.indexOf('bucket_zombie') !== -1 && bucketZombiesLeft > 0) {
							availableTypes.push('bucket_zombie');
						}
						if (selectedZombieTypes.indexOf('sun_zombie') !== -1) {
							availableTypes.push('sun_zombie');
						}
						if (selectedZombieTypes.indexOf('zombie_canon') !== -1) {
							availableTypes.push('zombie_canon');
						}
						if (selectedZombieTypes.indexOf('zombie_cascanueces') !== -1) {
							availableTypes.push('zombie_cascanueces');
						}
						if (availableTypes.length > 0) {
							var randomIndex = Math.floor(Math.random() * availableTypes.length);
							zombieType = availableTypes[randomIndex];
							// Decrement counters
							if (zombieType === 'zombie') {
								normalZombiesLeft--;
							} else if (zombieType === 'cone_zombie') {
								coneZombiesLeft--;
							} else if (zombieType === 'bucket_zombie') {
								bucketZombiesLeft--;
							}
						} else {
							zombieType = 'zombie'; // fallback
						}
					} else {
						// Original logic for normal mode
						// For wave 6+, increase cone and bucket zombie probability by 25%
						if (normalZombiesLeft > 0 && coneZombiesLeft > 0 && bucketZombiesLeft > 0) {
							var rand = Math.random();
							if (currentWave >= 6) {
								// Wave 6+: 25% normal, 37.5% cone, 37.5% bucket (25% more cone/bucket)
								if (rand < 0.25) {
									zombieType = 'zombie';
									normalZombiesLeft--;
								} else if (rand < 0.625) {
									zombieType = 'cone_zombie';
									coneZombiesLeft--;
								} else {
									zombieType = 'bucket_zombie';
									bucketZombiesLeft--;
								}
							} else {
								// Wave 3-5: original probabilities
								if (rand < 0.4) {
									zombieType = 'zombie';
									normalZombiesLeft--;
								} else if (rand < 0.7) {
									zombieType = 'cone_zombie';
									coneZombiesLeft--;
								} else {
									zombieType = 'bucket_zombie';
									bucketZombiesLeft--;
								}
							}
						} else if (normalZombiesLeft > 0 && coneZombiesLeft > 0) {
							if (currentWave >= 6) {
								// Wave 6+: 35% normal, 65% cone (25% more cone)
								zombieType = Math.random() < 0.35 ? 'zombie' : 'cone_zombie';
							} else {
								// Wave 3-5: original 60/40 split
								zombieType = Math.random() < 0.6 ? 'zombie' : 'cone_zombie';
							}
							if (zombieType === 'zombie') {
								normalZombiesLeft--;
							} else {
								coneZombiesLeft--;
							}
						} else if (normalZombiesLeft > 0 && bucketZombiesLeft > 0) {
							if (currentWave >= 6) {
								// Wave 6+: 35% normal, 65% bucket (25% more bucket)
								zombieType = Math.random() < 0.35 ? 'zombie' : 'bucket_zombie';
							} else {
								// Wave 3-5: original 60/40 split
								zombieType = Math.random() < 0.6 ? 'zombie' : 'bucket_zombie';
							}
							if (zombieType === 'zombie') {
								normalZombiesLeft--;
							} else {
								bucketZombiesLeft--;
							}
						} else if (coneZombiesLeft > 0 && bucketZombiesLeft > 0) {
							zombieType = Math.random() < 0.5 ? 'cone_zombie' : 'bucket_zombie';
							if (zombieType === 'cone_zombie') {
								coneZombiesLeft--;
							} else {
								bucketZombiesLeft--;
							}
						} else if (normalZombiesLeft > 0) {
							zombieType = 'zombie';
							normalZombiesLeft--;
						} else if (coneZombiesLeft > 0) {
							zombieType = 'cone_zombie';
							coneZombiesLeft--;
						} else if (bucketZombiesLeft > 0) {
							zombieType = 'bucket_zombie';
							bucketZombiesLeft--;
						} else {
							zombieType = 'zombie'; // fallback
						}
					}
				} else {
					// Fallback for other waves
					if (gameMode === 'personalize') {
						// Pick from selected types
						var availableTypes = [];
						if (selectedZombieTypes.indexOf('zombie') !== -1) {
							availableTypes.push('zombie');
						}
						if (selectedZombieTypes.indexOf('cone_zombie') !== -1) {
							availableTypes.push('cone_zombie');
						}
						if (availableTypes.length > 0) {
							var randomIndex = Math.floor(Math.random() * availableTypes.length);
							zombieType = availableTypes[randomIndex];
						} else {
							zombieType = 'zombie'; // fallback
						}
					} else {
						zombieType = Math.random() < 0.5 ? 'zombie' : 'cone_zombie';
					}
				}
				spawnZombie(zombieType, row);
				enemiesInWave--;
			} else {
				LK.clearInterval(spawnTimer);
			}
		}, 1200);
	} // Close the if (currentWave >= 3) block
}
// Mouse move handler to update ghost plant position
game.move = function (x, y, obj) {
	if (ghostPlant && selectedPlantType) {
		var gridPos = getGridPosition(x, y);
		if (gridPos) {
			// Snap to grid position
			ghostPlant.x = gridStartX + gridPos.x * cellSize;
			ghostPlant.y = gridStartY + gridPos.y * cellSize;
			// Change color based on validity
			if (canPlacePlant(gridPos.x, gridPos.y, selectedPlantType)) {
				ghostPlant.tint = 0x88FF88; // Green tint for valid placement
			} else {
				ghostPlant.tint = 0xFF8888; // Red tint for invalid placement
			}
		} else {
			// Follow cursor if outside grid
			ghostPlant.x = x;
			ghostPlant.y = y;
			ghostPlant.tint = 0xFF8888; // Red tint when outside grid
		}
	}
};
// Game input handling
game.down = function (x, y, obj) {
	// Check if clicking on a sun
	for (var i = 0; i < suns.length; i++) {
		if (suns[i].intersects({
			x: x,
			y: y,
			width: 1,
			height: 1
		})) {
			return; // Let sun handle its own click
		}
	}
	// Check if using shovel to remove plant
	if (selectedTool === 'shovel') {
		var gridPos = getGridPosition(x, y);
		if (gridPos && plants[gridPos.y][gridPos.x] !== null) {
			// Remove the plant
			var plant = plants[gridPos.y][gridPos.x];
			plant.destroy();
			plants[gridPos.y][gridPos.x] = null;
			LK.effects.flashObject(gridCells[gridPos.y][gridPos.x], 0xFFFF00, 300);
			updatePlantSelection();
			return;
		} else if (gridPos) {
			// Flash red if trying to remove from empty square
			LK.effects.flashObject(gridCells[gridPos.y][gridPos.x], 0xFF0000, 300);
		} else {
			// Clicking outside grid cancels shovel selection
			selectedTool = null;
			shovelButton.alpha = 0.8;
			shovelButton.scaleX = shovelButton.scaleY = 1.5;
			updatePlantSelection();
		}
	}
	// Check if placing a plant
	else if (selectedPlantType) {
		var gridPos = getGridPosition(x, y);
		if (gridPos) {
			if (canPlacePlant(gridPos.x, gridPos.y, selectedPlantType)) {
				// Successfully place the plant
				if (placePlant(gridPos.x, gridPos.y, selectedPlantType)) {
					selectedPlantType = null;
					updatePlantSelection();
					return;
				}
			} else if (plants[gridPos.y][gridPos.x] !== null) {
				// Flash red if trying to place on occupied square
				LK.effects.flashObject(gridCells[gridPos.y][gridPos.x], 0xFF0000, 300);
			} else if (sunPoints < plantCosts[selectedPlantType]) {
				// Flash yellow if not enough suns
				LK.effects.flashObject(gridCells[gridPos.y][gridPos.x], 0xFFFF00, 300);
			}
		} else {
			// Clicking outside grid cancels selection
			selectedPlantType = null;
			updatePlantSelection();
		}
	}
};
// Initialize UI
updatePlantSelection();
updateSunDisplay();
updateLivesDisplay();
updateWaveDisplay();
// Skip wave button for endless mode
var skipWaveButton = null;
function createSkipWaveButton() {
	if (gameMode === 'endless' && !skipWaveButton) {
		skipWaveButton = LK.getAsset('gridcell', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 1800,
			y: 100,
			scaleX: 2,
			scaleY: 1,
			color: 0x888888 // Start gray
		});
		skipWaveButton.interactive = true;
		skipWaveButton.buttonMode = true;
		skipWaveButton.alpha = 0.5; // Start disabled
		skipWaveButton.down = function (x, y, obj) {
			if (waveInProgress) {
				// Force end current wave and start next one
				waveInProgress = false;
				wavesCompleted++;
				currentWave++;
				updateWaveDisplay();
				updateSkipWaveButton();
				// Start next wave immediately
				LK.setTimeout(function () {
					startWave();
				}, 500);
			}
		};
		game.addChild(skipWaveButton);
		var skipWaveText = new Text2('Skip Wave', {
			size: 40,
			fill: 0xFFFFFF
		});
		skipWaveText.anchor.set(0.5, 0.5);
		skipWaveText.x = 1800;
		skipWaveText.y = 100;
		game.addChild(skipWaveText);
		skipWaveButton.textElement = skipWaveText;
	}
}
function canSkipWave() {
	// Check if all zombies for current wave have been spawned
	return waveInProgress && enemiesInWave <= 0;
}
function updateSkipWaveButton() {
	if (skipWaveButton && gameMode === 'endless') {
		if (waveInProgress) {
			// Enable button - wave is in progress
			skipWaveButton.alpha = 1.0;
			skipWaveButton.tint = 0x4CAF50; // Green
			skipWaveButton.interactive = true;
		} else {
			// Disable button - no wave in progress
			skipWaveButton.alpha = 0.5;
			skipWaveButton.tint = 0x888888; // Gray
			skipWaveButton.interactive = false;
		}
	}
}
// Game will start after mode selection
// Main game loop
game.update = function () {
	// Enable lag optimization from wave 8 onwards
	if (currentWave >= 8 && !lagOptimizationActive) {
		lagOptimizationActive = true;
		console.log("Lag optimization activated for wave", currentWave);
	}
	// Performance cleanup every 3 seconds when lag optimization is active
	if (lagOptimizationActive) {
		cleanupCounter++;
		if (cleanupCounter >= 180) {
			// Every 3 seconds at 60fps
			performanceCleanup();
			cleanupCounter = 0;
		}
	}
	// Update wallnut cooldown
	if (wallnutCooldown > 0) {
		wallnutCooldown--;
		if (wallnutCooldown === 0) {
			updatePlantSelection(); // Refresh button appearance when cooldown ends
		}
	}
	// Update nuez primitiva cooldown
	if (nuezPrimitivaCooldown > 0) {
		nuezPrimitivaCooldown--;
		if (nuezPrimitivaCooldown === 0) {
			updatePlantSelection(); // Refresh button appearance when cooldown ends
		}
	}
	// Update petacereza cooldown
	if (petacerezaCooldown > 0) {
		petacerezaCooldown--;
		if (petacerezaCooldown === 0) {
			updatePlantSelection(); // Refresh button appearance when cooldown ends
		}
	}
	// Falling sun system - every 10 seconds (optimized for high waves)
	sunTimer++;
	var sunInterval = lagOptimizationActive ? 1080 : 720; // 18 seconds when optimized, 12 seconds normally
	if (sunTimer >= sunInterval) {
		// Only spawn sun if we don't have too many already
		if (suns.length < (lagOptimizationActive ? 8 : 15)) {
			var fallingSun = new Sun(Math.random() * (gridStartX + gridCols * cellSize - gridStartX) + gridStartX, -50);
			suns.push(fallingSun);
			game.addChild(fallingSun);
			// Animate falling sun
			tween(fallingSun, {
				y: Math.random() * 200 + 300
			}, {
				duration: 2400,
				easing: tween.easeOut
			});
		}
		sunTimer = 0;
	}
	// Check if current wave should end (22 seconds timer-based)
	if (waveInProgress && LK.ticks - waveStartTick >= 1584) {
		// 26.4 seconds at 60fps
		waveInProgress = false;
		wavesCompleted++;
		if (gameMode === 'normal' && wavesCompleted >= totalWaves) {
			// Check if Zombiestein was spawned and is still alive
			if (zombiesteinSpawned && zombiesteinAlive) {
				// Don't end game until Zombiestein is defeated
				console.log("All waves completed but Zombiestein still alive!");
				return;
			}
			LK.effects.flashScreen(0x4CAF50, 1000);
			LK.showYouWin();
			return;
		} else if (gameMode === 'endless') {
			// For endless mode, just continue to next wave
			// Reset Zombiestein spawn flag for next potential spawn
			if (currentWave % 5 === 0) {
				zombiesteinSpawned = false;
				zombiesteinAlive = false;
			}
		}
		currentWave++;
		updateWaveDisplay();
		// Start next wave after delay
		LK.setTimeout(function () {
			startWave();
		}, 3000);
	}
	// Update skip wave button state
	if (gameMode === 'endless') {
		updateSkipWaveButton();
	}
	// Auto-start next wave if no wave in progress and we haven't completed all waves (and mode is selected)
	if (gameModeSelected && !waveInProgress && (gameMode === 'endless' || wavesCompleted < totalWaves) && !nextWaveScheduled) {
		nextWaveScheduled = true;
		LK.setTimeout(function () {
			nextWaveScheduled = false;
			startWave();
		}, 1000);
	}
};