User prompt
Creates a plant called puffshroom that costs 0 suns and shoots spores and creates a separate resource for the spore and has a range to detect a zombie of 3 tiles and can only be used from wave 11 onwards and appears on page 2 of the plant selector βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the repeater plant appear on the first page of the plant selector.
User prompt
Make the left arrow of the plant selector go further to the left so that the repeater plant comes in after the chomper plant in the plant selector on the first page.
User prompt
Make the gargantuar spawn a fastzombie 3 squares further away from the gargantuar
User prompt
Make the arrow button further to the left and on the first page of the plant selector, have Peashooter, Sunflower, Cherrypopper, Wallnut, Potatomine, Snowshooter, Chomper, and Repeater in that order.
User prompt
Make the gargantuar unable to be eaten by the chomper plant
User prompt
Make the chomper plant eat the nearest zombie and make the minerzombie take 5 seconds instead of 3 βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Also make the chomper plant adjust when it is black when it can't eat another zombie and return to its normal color when it can eat another zombie βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the first zombie spawn in wave 1 after 10 seconds.
User prompt
Sets the chomper to a two-tile range and a 15 second cooldown. βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
fix the bug that causes the potatomine plant to explode without eliminating the zombie that touched it and make the potatomine plant take 15 seconds to charge, not 5 anymore, make it so that when the potatomine explodes with a newspaperzombie and gargantuar it leaves it at half health βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
creates a plant called potatomine that costs 25 suns and will take 5 seconds to be charged to explode when a zombie touches it this plant will explode and while it is on cooldown when placed it will be black and when it is charged it will return to its normal color βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move the plant selector a little to the left and create a plant called chomper that eats the nearby zombie in a range of one square and has a cooldown to be able to eat another zombie and costs 150 soles and when it is on cooldown it has a black color βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Now make different plant selectors with different plants and make splitpea appear in the second plant selector and for now let there only be 2 plant selectors and when pressing the right arrow button it changes to the second plant selector and when pressing the left arrow it returns to the previous plant selector
User prompt
Add two arrows, one on the left side of the plant selector and the other on the right side of the plant selector, which for now has no function.
User prompt
Make the suns bigger and have the suns that appear without a sunflower have an animation that says they are falling from the top to the bottom of the screen. βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the shovel at the top right of the screen and make it bigger.
User prompt
Make the letters of the sun costs of the plants black and remove the black outline.
User prompt
Make the letters of the sole costs of the plants even bigger.
User prompt
Make the sun counter have a black outline and make the plant and shovel cost letters larger.
User prompt
make the sun letters have a black outline
User prompt
Modify Splitpea so that it can also detect zombies that are behind
User prompt
Create a plant called splitpea that costs 125 soles and shoots one pea forward and two peas backward.
User prompt
Create a plant called repeater that costs 200 soles and shoots two peas.
User prompt
create an asset for the minerzombie
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var BackwardPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint green to show it's from splitpea
	graphics.tint = 0x44ff44;
	self.speed = -8; // Negative speed to go backwards 
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies 
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie 
				if (zombie.isJester) {
					// Create reflected pea going forward 
					var reflectedPea = new ReflectedPea();
					reflectedPea.x = zombie.x + 50;
					reflectedPea.y = zombie.y;
					reflectedPea.gridY = zombie.gridY;
					reflectedpeas.push(reflectedPea);
					game.addChild(reflectedPea);
					// Flash jester zombie to show deflection 
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'pea');
				}
				self.destroy();
				for (var j = 0; j < backwardpeas.length; j++) {
					if (backwardpeas[j] === self) {
						backwardpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side) 
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < backwardpeas.length; k++) {
				if (backwardpeas[k] === self) {
					backwardpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var BasicZombie = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('basicZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 100;
	self.maxHealth = 100;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.update = function () {
		// Check if there's a plant to attack
		var plantToAttack = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
				plantToAttack = plant;
				break;
			}
		}
		if (plantToAttack) {
			self.attackTimer++;
			if (self.attackTimer >= self.attackDelay) {
				if (plantToAttack.takeDamage) {
					plantToAttack.takeDamage(self.damage);
				}
				self.attackTimer = 0;
			}
		} else {
			self.x -= self.speed;
			self.attackTimer = 0;
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombie_hit').play();
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
			zombiesKilled++;
		}
	};
	return self;
});
var Zomboni = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with zomboni asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('zomboni', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 1.5; // Fast movement
	self.health = 150;
	self.maxHealth = 150;
	self.damage = 100;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 30; // Faster elimination
	self.update = function () {
		// Move forward continuously
		self.x -= self.speed;
		// Check for plants to eliminate (in a wider area due to size)
		for (var i = plants.length - 1; i >= 0; i--) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 100) {
				// Instantly eliminate the plant
				LK.effects.flashObject(plant, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plant.gridX + ',' + plant.gridY;
				delete plantGrid[gridKey];
				plant.destroy();
				plants.splice(i, 1);
			}
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var TankZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with tank zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('tankZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.3;
	self.health = 200;
	self.maxHealth = 200;
	self.damage = 80;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	return self;
});
var NewspaperZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with newspaper zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('newspaperZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 100;
	self.maxHealth = 100;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.hasRaged = false;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		LK.getSound('zombie_hit').play();
		// Check if health dropped to half or below and hasn't raged yet
		if (self.health <= self.maxHealth / 2 && !self.hasRaged) {
			self.hasRaged = true;
			// Increase speed and damage
			self.speed = 1.5;
			self.damage = 80;
			// Visual effect for rage mode - flash red and change tint
			LK.effects.flashObject(self, 0xff0000, 500);
			tween(graphics, {
				tint: 0xff4444
			}, {
				duration: 300,
				easing: tween.easeOut
			});
		}
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
			zombiesKilled++;
		}
	};
	return self;
});
var MinerZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with miner zombie asset (appears as normal zombie)
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('minerZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.5;
	self.health = 80;
	self.maxHealth = 80;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.teleportTimer = 0;
	self.teleportDelay = 300; // 5 seconds at 60fps
	self.hasTeleported = false;
	self.update = function () {
		// If not teleported yet, count down to teleport
		if (!self.hasTeleported) {
			self.teleportTimer++;
			if (self.teleportTimer >= self.teleportDelay) {
				self.teleport();
			} else {
				// Move normally before teleporting
				self.x -= self.speed;
			}
		} else {
			// After teleporting, behave like normal zombie but attacking from behind
			var plantToAttack = null;
			for (var i = 0; i < plants.length; i++) {
				var plant = plants[i];
				if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
					plantToAttack = plant;
					break;
				}
			}
			if (plantToAttack) {
				self.attackTimer++;
				if (self.attackTimer >= self.attackDelay) {
					if (plantToAttack.takeDamage) {
						plantToAttack.takeDamage(self.damage);
					}
					self.attackTimer = 0;
				}
			} else {
				self.x += self.speed; // Move forward (right) after teleporting
				self.attackTimer = 0;
			}
		}
		// Check if reached house (only matters before teleporting)
		if (!self.hasTeleported && self.x < 150) {
			LK.showGameOver();
		}
		// Check if moved off screen after teleporting
		if (self.hasTeleported && self.x > 2200) {
			self.destroy();
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i] === self) {
					zombies.splice(i, 1);
					break;
				}
			}
		}
	};
	self.teleport = function () {
		if (self.hasTeleported) return;
		self.hasTeleported = true;
		// Flash effect before teleporting
		LK.effects.flashObject(self, 0xffff00, 300);
		// Teleport to the first column (leftmost position behind plants)
		var newX = gridStartX + gridWidth / 2;
		var newY = gridStartY + self.gridY * gridHeight + gridHeight / 2;
		// Animate teleportation with tween
		tween(self, {
			alpha: 0,
			scaleX: 0.5,
			scaleY: 0.5
		}, {
			duration: 500,
			easing: tween.easeIn,
			onFinish: function onFinish() {
				// Move to new position
				self.x = newX;
				self.y = newY;
				// Animate appearing at new location
				tween(self, {
					alpha: 1,
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 500,
					easing: tween.easeOut
				});
				// Flash effect when appearing
				LK.effects.flashObject(self, 0x00ff00, 300);
			}
		});
	};
	return self;
});
var JesterZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with jester zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('jesterZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.8;
	self.health = 120;
	self.maxHealth = 120;
	self.damage = 50;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	self.isJester = true; // Flag to identify this zombie type
	// Override takeDamage to be immune to peas
	self.takeDamage = function (damage, source) {
		// Only take damage from non-pea sources
		if (source !== 'pea' && source !== 'frozenpea') {
			self.health -= damage;
			LK.effects.flashObject(self, 0xff0000, 200);
			LK.getSound('zombie_hit').play();
			if (self.health <= 0) {
				self.destroy();
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i] === self) {
						zombies.splice(i, 1);
						break;
					}
				}
				zombiesKilled++;
			}
		}
	};
	return self;
});
var JackInBoxZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with jack in box zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('jackInBoxZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.7;
	self.health = 80;
	self.maxHealth = 80;
	self.damage = 60;
	self.hasExploded = false;
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Flash the jack in box zombie white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from zombies array
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i] === self) {
						zombies.splice(i, 1);
						break;
					}
				}
				// Destroy the jack in box zombie
				self.destroy();
			}
		});
		// Eliminate plants in a 250 pixel radius
		var explosionRadius = 250;
		for (var i = plants.length - 1; i >= 0; i--) {
			var plant = plants[i];
			var distance = Math.sqrt(Math.pow(plant.x - self.x, 2) + Math.pow(plant.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Flash plant red before destroying
				LK.effects.flashObject(plant, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plant.gridX + ',' + plant.gridY;
				delete plantGrid[gridKey];
				plant.destroy();
				plants.splice(i, 1);
			}
		}
	};
	self.update = function () {
		// Check if there's a plant to explode on
		var plantToExplode = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
				plantToExplode = plant;
				break;
			}
		}
		if (plantToExplode && !self.hasExploded) {
			self.explode();
		} else {
			self.x -= self.speed;
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var Gargantuar = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with gargantuar asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('gargantuar', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 0.2; // Very slow
	self.health = 400; // Very resistant
	self.maxHealth = 400;
	self.damage = 200; // High damage to eliminate plants instantly
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 30; // Fast elimination
	self.hasSpawnedFastZombie = false;
	self.isResistantToExplosion = true; // Flag for cherry popper resistance
	self.update = function () {
		// Check if there's a plant to eliminate
		var plantToEliminate = null;
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 120) {
				plantToEliminate = plant;
				break;
			}
		}
		if (plantToEliminate) {
			self.attackTimer++;
			if (self.attackTimer >= self.attackDelay) {
				// Instantly eliminate the plant
				LK.effects.flashObject(plantToEliminate, 0xff0000, 200);
				// Remove from plant grid
				var gridKey = plantToEliminate.gridX + ',' + plantToEliminate.gridY;
				delete plantGrid[gridKey];
				plantToEliminate.destroy();
				for (var j = 0; j < plants.length; j++) {
					if (plants[j] === plantToEliminate) {
						plants.splice(j, 1);
						break;
					}
				}
				self.attackTimer = 0;
			}
		} else {
			self.x -= self.speed;
			self.attackTimer = 0;
		}
		// Spawn FastZombie when at half health
		if (self.health <= self.maxHealth / 2 && !self.hasSpawnedFastZombie) {
			self.hasSpawnedFastZombie = true;
			var fastZombie = new FastZombie();
			// Spawn 3 squares further away (3 * gridWidth = 3 * 320 = 960 pixels)
			fastZombie.x = self.x + 960;
			fastZombie.y = self.y;
			fastZombie.gridY = self.gridY;
			zombies.push(fastZombie);
			game.addChild(fastZombie);
			// Visual effect for spawning
			LK.effects.flashObject(self, 0xffff00, 500);
		}
		// Check if reached house
		if (self.x < 150) {
			LK.showGameOver();
		}
	};
	return self;
});
var FastZombie = BasicZombie.expand(function () {
	var self = BasicZombie.call(this);
	// Replace the graphics with fast zombie asset
	self.removeChild(self.children[0]);
	var graphics = self.attachAsset('fastZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 1.2;
	self.health = 60;
	self.maxHealth = 60;
	self.damage = 40;
	self.gridY = 0;
	self.attackTimer = 0;
	self.attackDelay = 60;
	return self;
});
var CherryPopper = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('cherrypopper', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 150;
	self.gridX = 0;
	self.gridY = 0;
	self.hasExploded = false;
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Flash the cherry popper white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === self) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from plant grid
				var gridKey = self.gridX + ',' + self.gridY;
				delete plantGrid[gridKey];
				// Destroy the cherry popper
				self.destroy();
			}
		});
		// Eliminate zombies in a 300 pixel radius
		var explosionRadius = 300;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Special handling for Gargantuar
				if (zombie.constructor === Gargantuar) {
					// Flash zombie red
					LK.effects.flashObject(zombie, 0xff0000, 200);
					// If at full health or more than half, reduce to half
					if (zombie.health > zombie.maxHealth / 2) {
						zombie.health = zombie.maxHealth / 2;
						// Visual effect for being damaged but not destroyed
						tween(zombie, {
							tint: 0xff4444
						}, {
							duration: 500,
							easing: tween.easeOut
						});
					} else {
						// Second explosion - eliminate Gargantuar
						zombie.destroy();
						zombies.splice(i, 1);
						zombiesKilled++;
					}
				} else {
					// Normal zombies - eliminate immediately
					LK.effects.flashObject(zombie, 0xff0000, 200);
					zombie.destroy();
					zombies.splice(i, 1);
					zombiesKilled++;
				}
			}
		}
	};
	// Auto-explode when planted (immediately after placement)
	self.update = function () {
		if (!self.hasExploded) {
			self.explode();
		}
	};
	return self;
});
var Chomper = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('chomper', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 150;
	self.health = 100;
	self.maxHealth = 100;
	self.gridX = 0;
	self.gridY = 0;
	self.eatCooldown = 0;
	self.maxEatCooldown = 900; // 15 seconds at 60fps
	self.isOnCooldown = false;
	self.digestionTimer = 0;
	self.maxDigestionTime = 180; // 3 seconds to digest
	self.isDigesting = false;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle digestion timer
		if (self.isDigesting) {
			self.digestionTimer++;
			if (self.digestionTimer >= self.maxDigestionTime) {
				self.isDigesting = false;
				self.digestionTimer = 0;
				// Reset color after digesting
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			}
			return; // Don't eat while digesting
		}
		// Handle cooldown
		if (self.isOnCooldown) {
			self.eatCooldown--;
			if (self.eatCooldown <= 0) {
				self.isOnCooldown = false;
				// Reset color when cooldown ends
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			} else {
				// Ensure black color is maintained during cooldown
				if (graphics.tint !== 0x000000) {
					tween(graphics, {
						tint: 0x000000
					}, {
						duration: 100,
						easing: tween.easeOut
					});
				}
			}
			return; // Don't eat while on cooldown
		}
		// Look for the nearest zombie in adjacent squares (two square range)
		var nearestZombie = null;
		var nearestDistance = Infinity;
		var nearestIndex = -1;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			// Check if zombie is in same lane and within two grid square range
			var gridDistance = Math.abs(zombie.x - self.x) / gridWidth;
			if (zombie.gridY === self.gridY && gridDistance <= 2.2) {
				var distance = Math.abs(zombie.x - self.x);
				if (distance < nearestDistance) {
					nearestDistance = distance;
					nearestZombie = zombie;
					nearestIndex = i;
				}
			}
		}
		// Eat the nearest zombie if found
		if (nearestZombie) {
			self.eatZombie(nearestZombie, nearestIndex);
		}
	};
	self.eatZombie = function (zombie, zombieIndex) {
		// Check if zombie is a Gargantuar - cannot be eaten
		if (zombie.constructor === Gargantuar) {
			// Flash red to show chomper can't eat this zombie
			LK.effects.flashObject(self, 0xff0000, 300);
			return; // Exit without eating
		}
		// Flash white to show eating action
		LK.effects.flashObject(self, 0xffffff, 300);
		// Remove zombie immediately
		zombie.destroy();
		zombies.splice(zombieIndex, 1);
		zombiesKilled++;
		// Start digestion period
		self.isDigesting = true;
		self.digestionTimer = 0;
		// Visual feedback for digesting (green tint)
		tween(graphics, {
			tint: 0x44ff44
		}, {
			duration: 300,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Start cooldown after digestion
				self.isOnCooldown = true;
				self.eatCooldown = self.maxEatCooldown;
				// Visual feedback for cooldown (black tint)
				tween(graphics, {
					tint: 0x000000
				}, {
					duration: 300,
					easing: tween.easeOut
				});
			}
		});
	};
	return self;
});
var FrozenPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('frozenpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.damage = 15;
	self.gridY = 0;
	self.slowDuration = 300; // 5 seconds at 60fps
	self.slowFactor = 0.3; // Reduce speed to 30%
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected frozen pea going back towards plants
					var reflectedFrozenPea = new ReflectedFrozenPea();
					reflectedFrozenPea.x = zombie.x - 50;
					reflectedFrozenPea.y = zombie.y;
					reflectedFrozenPea.gridY = zombie.gridY;
					reflectedfrozenpeas.push(reflectedFrozenPea);
					game.addChild(reflectedFrozenPea);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'frozenpea');
					// Apply slow effect only if not a Zomboni or NewspaperZombie
					if (zombie.constructor !== Zomboni && zombie.constructor !== NewspaperZombie) {
						if (!zombie.originalSpeed) {
							zombie.originalSpeed = zombie.speed;
						}
						zombie.speed = zombie.originalSpeed * self.slowFactor;
						zombie.slowTimer = self.slowDuration;
						// Visual effect for slowed zombie
						tween(zombie, {
							tint: 0x87ceeb
						}, {
							duration: 300,
							easing: tween.easeOut
						});
					}
				}
				self.destroy();
				for (var j = 0; j < frozenpeas.length; j++) {
					if (frozenpeas[j] === self) {
						frozenpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < frozenpeas.length; k++) {
				if (frozenpeas[k] === self) {
					frozenpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Pea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected pea going back towards plants
					var reflectedPea = new ReflectedPea();
					reflectedPea.x = zombie.x - 50;
					reflectedPea.y = zombie.y;
					reflectedPea.gridY = zombie.gridY;
					reflectedpeas.push(reflectedPea);
					game.addChild(reflectedPea);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'pea');
				}
				self.destroy();
				for (var j = 0; j < peas.length; j++) {
					if (peas[j] === self) {
						peas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < peas.length; k++) {
				if (peas[k] === self) {
					peas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Peashooter = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('peashooter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 100;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var pea = new Pea();
		pea.x = self.x + 60;
		pea.y = self.y;
		pea.gridY = self.gridY;
		peas.push(pea);
		game.addChild(pea);
		LK.getSound('shoot').play();
	};
	return self;
});
var Potatomine = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('potatomine', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 25;
	self.health = 100;
	self.maxHealth = 100;
	self.gridX = 0;
	self.gridY = 0;
	self.chargeTimer = 0;
	self.maxChargeTime = 900; // 15 seconds at 60fps
	self.isCharged = false;
	self.hasExploded = false;
	// Start with black color (charging state)
	graphics.tint = 0x000000;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle charging timer
		if (!self.isCharged && !self.hasExploded) {
			self.chargeTimer++;
			if (self.chargeTimer >= self.maxChargeTime) {
				self.isCharged = true;
				// Change to normal color when charged
				tween(graphics, {
					tint: 0xffffff
				}, {
					duration: 500,
					easing: tween.easeOut
				});
			}
			return; // Don't explode while charging
		}
		// Check for zombies touching this potatomine
		if (self.isCharged && !self.hasExploded) {
			for (var i = 0; i < zombies.length; i++) {
				var zombie = zombies[i];
				if (zombie.gridY === self.gridY && self.intersects(zombie)) {
					self.explode();
					break;
				}
			}
		}
	};
	self.explode = function () {
		if (self.hasExploded) return;
		self.hasExploded = true;
		// Flash white before exploding
		LK.effects.flashObject(self, 0xffffff, 200);
		// Scale up effect for explosion
		tween(graphics, {
			scaleX: 3,
			scaleY: 3,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === self) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from plant grid
				var gridKey = self.gridX + ',' + self.gridY;
				delete plantGrid[gridKey];
				// Destroy the potatomine
				self.destroy();
			}
		});
		// Eliminate zombies in a 200 pixel radius
		var explosionRadius = 200;
		for (var i = zombies.length - 1; i >= 0; i--) {
			var zombie = zombies[i];
			var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
			if (distance <= explosionRadius) {
				// Special handling for Gargantuar and NewspaperZombie
				if (zombie.constructor === Gargantuar || zombie.constructor === NewspaperZombie) {
					// Flash zombie red
					LK.effects.flashObject(zombie, 0xff0000, 200);
					// Reduce to half health
					zombie.health = zombie.maxHealth / 2;
					// Visual effect for being damaged but not destroyed
					tween(zombie, {
						tint: 0xff4444
					}, {
						duration: 500,
						easing: tween.easeOut
					});
					// Check if zombie should be eliminated after damage
					if (zombie.health <= 0) {
						zombie.destroy();
						zombies.splice(i, 1);
						zombiesKilled++;
					}
				} else {
					// Normal zombies - eliminate immediately
					LK.effects.flashObject(zombie, 0xff0000, 200);
					zombie.destroy();
					zombies.splice(i, 1);
					zombiesKilled++;
				}
			}
		}
	};
	return self;
});
var Puffshroom = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('puffshroom', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 0;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 120; // 2 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.detectionRange = 3; // 3 tiles
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie within 3 tiles in this lane
			var hasZombieInRange = false;
			for (var i = 0; i < zombies.length; i++) {
				var zombie = zombies[i];
				if (zombie.gridY === self.gridY && zombie.x > self.x) {
					var distance = Math.abs(zombie.x - self.x);
					var tileDistance = distance / gridWidth;
					if (tileDistance <= self.detectionRange) {
						hasZombieInRange = true;
						break;
					}
				}
			}
			if (hasZombieInRange) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var spore = new Spore();
		spore.x = self.x + 40;
		spore.y = self.y;
		spore.gridY = self.gridY;
		spores.push(spore);
		game.addChild(spore);
		LK.getSound('shoot').play();
	};
	return self;
});
var ReflectedFrozenPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('frozenpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint dark red to show it's reflected
	graphics.tint = 0xaa2222;
	self.speed = -8; // Negative speed to go backwards
	self.damage = 20; // Slightly more damage than regular frozen peas
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedfrozenpeas.length; j++) {
					if (reflectedfrozenpeas[j] === self) {
						reflectedfrozenpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedfrozenpeas.length; k++) {
				if (reflectedfrozenpeas[k] === self) {
					reflectedfrozenpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var ReflectedPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('pea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint red to show it's reflected
	graphics.tint = 0xff4444;
	self.speed = -8; // Negative speed to go backwards
	self.damage = 20; // Slightly more damage than regular peas
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedpeas.length; j++) {
					if (reflectedpeas[j] === self) {
						reflectedpeas.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedpeas.length; k++) {
				if (reflectedpeas[k] === self) {
					reflectedpeas.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var ReflectedSpore = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('spore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Tint dark brown to show it's reflected
	graphics.tint = 0x654321;
	self.speed = -6;
	self.damage = 15;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with plants
		for (var i = 0; i < plants.length; i++) {
			var plant = plants[i];
			if (plant.gridY === self.gridY && self.intersects(plant)) {
				if (plant.takeDamage) {
					plant.takeDamage(self.damage);
				}
				self.destroy();
				for (var j = 0; j < reflectedspores.length; j++) {
					if (reflectedspores[j] === self) {
						reflectedspores.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen (left side)
		if (self.x < -100) {
			self.destroy();
			for (var k = 0; k < reflectedspores.length; k++) {
				if (reflectedspores[k] === self) {
					reflectedspores.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Repeater = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('repeater', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 200;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.secondShotTimer = 0;
	self.secondShotDelay = 15; // 0.25 seconds delay between shots
	self.waitingForSecondShot = false;
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		// Handle second shot timing
		if (self.waitingForSecondShot) {
			self.secondShotTimer++;
			if (self.secondShotTimer >= self.secondShotDelay) {
				self.shoot(); // Fire second pea
				self.waitingForSecondShot = false;
				self.secondShotTimer = 0;
			}
		} else {
			self.shootTimer++;
			if (self.shootTimer >= self.shootDelay) {
				// Check if there's a zombie in this lane
				var hasZombieInLane = false;
				for (var i = 0; i < zombies.length; i++) {
					if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
						hasZombieInLane = true;
						break;
					}
				}
				if (hasZombieInLane) {
					self.shoot(); // Fire first pea
					self.waitingForSecondShot = true; // Queue second shot
					self.shootTimer = 0;
				}
			}
		}
	};
	self.shoot = function () {
		var pea = new Pea();
		pea.x = self.x + 60;
		pea.y = self.y;
		pea.gridY = self.gridY;
		peas.push(pea);
		game.addChild(pea);
		LK.getSound('shoot').play();
	};
	return self;
});
var Snowshooter = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('snowshooter', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 175;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		var frozenpea = new FrozenPea();
		frozenpea.x = self.x + 60;
		frozenpea.y = self.y;
		frozenpea.gridY = self.gridY;
		frozenpeas.push(frozenpea);
		game.addChild(frozenpea);
		LK.getSound('shoot').play();
	};
	return self;
});
var SplitPea = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('splitpea', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 125;
	self.health = 100;
	self.maxHealth = 100;
	self.shootTimer = 0;
	self.shootDelay = 90; // 1.5 seconds at 60fps 
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback 
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.shootTimer++;
		if (self.shootTimer >= self.shootDelay) {
			// Check if there's a zombie in this lane (both front and back) 
			var hasZombieInLane = false;
			for (var i = 0; i < zombies.length; i++) {
				if (zombies[i].gridY === self.gridY) {
					hasZombieInLane = true;
					break;
				}
			}
			if (hasZombieInLane) {
				self.shoot();
				self.shootTimer = 0;
			}
		}
	};
	self.shoot = function () {
		// Shoot one pea forward 
		var forwardPea = new Pea();
		forwardPea.x = self.x + 60;
		forwardPea.y = self.y;
		forwardPea.gridY = self.gridY;
		peas.push(forwardPea);
		game.addChild(forwardPea);
		// Shoot two peas backward 
		var backwardPea1 = new BackwardPea();
		backwardPea1.x = self.x - 60;
		backwardPea1.y = self.y - 20;
		backwardPea1.gridY = self.gridY;
		backwardpeas.push(backwardPea1);
		game.addChild(backwardPea1);
		var backwardPea2 = new BackwardPea();
		backwardPea2.x = self.x - 60;
		backwardPea2.y = self.y + 20;
		backwardPea2.gridY = self.gridY;
		backwardpeas.push(backwardPea2);
		game.addChild(backwardPea2);
		LK.getSound('shoot').play();
	};
	return self;
});
var Spore = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('spore', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 6;
	self.damage = 10;
	self.gridY = 0;
	self.update = function () {
		self.x += self.speed;
		// Check collision with zombies
		for (var i = 0; i < zombies.length; i++) {
			var zombie = zombies[i];
			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
				// Check if it's a JesterZombie
				if (zombie.isJester) {
					// Create reflected spore going back towards plants
					var reflectedSpore = new ReflectedSpore();
					reflectedSpore.x = zombie.x - 50;
					reflectedSpore.y = zombie.y;
					reflectedSpore.gridY = zombie.gridY;
					reflectedspores.push(reflectedSpore);
					game.addChild(reflectedSpore);
					// Flash jester zombie to show deflection
					LK.effects.flashObject(zombie, 0xffff00, 200);
				} else {
					zombie.takeDamage(self.damage, 'spore');
				}
				self.destroy();
				for (var j = 0; j < spores.length; j++) {
					if (spores[j] === self) {
						spores.splice(j, 1);
						break;
					}
				}
				return;
			}
		}
		// Remove if off screen
		if (self.x > 2200) {
			self.destroy();
			for (var k = 0; k < spores.length; k++) {
				if (spores[k] === self) {
					spores.splice(k, 1);
					break;
				}
			}
		}
	};
	return self;
});
var Sun = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('sun', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.value = 25;
	self.lifeTimer = 0;
	self.maxLife = 600; // 10 seconds
	self.update = function () {
		self.lifeTimer++;
		if (self.lifeTimer > self.maxLife) {
			self.destroy();
			for (var i = 0; i < suns.length; i++) {
				if (suns[i] === self) {
					suns.splice(i, 1);
					break;
				}
			}
		}
	};
	self.down = function (x, y, obj) {
		sunPoints += self.value;
		updateSunDisplay();
		self.destroy();
		for (var i = 0; i < suns.length; i++) {
			if (suns[i] === self) {
				suns.splice(i, 1);
				break;
			}
		}
		LK.getSound('collect').play();
	};
	return self;
});
var Sunflower = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('sunflower', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 50;
	self.health = 100;
	self.maxHealth = 100;
	self.sunTimer = 0;
	self.sunDelay = 600; // 10 seconds at 60fps
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	self.update = function () {
		self.sunTimer++;
		if (self.sunTimer >= self.sunDelay) {
			self.produceSun();
			self.sunTimer = 0;
		}
	};
	self.produceSun = function () {
		var sun = new Sun();
		sun.x = self.x + (Math.random() - 0.5) * 50;
		sun.y = self.y + (Math.random() - 0.5) * 50;
		suns.push(sun);
		game.addChild(sun);
	};
	return self;
});
var WallNut = Container.expand(function () {
	var self = Container.call(this);
	var graphics = self.attachAsset('wallnut', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.cost = 50;
	self.health = 300;
	self.maxHealth = 300;
	self.gridX = 0;
	self.gridY = 0;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			self.destroy();
			for (var i = 0; i < plants.length; i++) {
				if (plants[i] === self) {
					plants.splice(i, 1);
					break;
				}
			}
			var gridKey = self.gridX + ',' + self.gridY;
			delete plantGrid[gridKey];
		} else {
			// Visual damage feedback
			var damageRatio = self.health / self.maxHealth;
			graphics.alpha = 0.3 + damageRatio * 0.7;
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x8BC34A
});
/**** 
* Game Code
****/ 
// Sounds
// Zombies
// Projectiles and collectibles
// Plants
// Game grid and UI elements
// Game variables
var sunPoints = 150;
var currentWave = 1;
var maxWaves = 20;
var waveTimer = 0;
var waveDelay = 1800; // 30 seconds
var zombieSpawnTimer = 0;
var zombieSpawnDelay = 240; // 4 seconds
var zombiesPerWave = 5;
var zombiesSpawned = 0;
var zombiesKilled = 0;
var totalZombiesToKill = 0;
var waveStarted = false;
var zombieSpawnQueue = [];
// Game arrays
var plants = [];
var zombies = [];
var peas = [];
var frozenpeas = [];
var reflectedpeas = [];
var reflectedfrozenpeas = [];
var backwardpeas = [];
var spores = [];
var reflectedspores = [];
var suns = [];
var plantGrid = {}; // Track occupied grid positions
// Grid settings
var gridStartX = 400;
var gridStartY = 400;
var gridWidth = 320;
var gridHeight = 227;
var gridCols = 5;
var gridRows = 5;
// Selected plant type
var selectedPlantType = null;
// Plant selector management
var currentSelectorPage = 1;
var maxSelectorPages = 2;
// Create lawn grid
for (var row = 0; row < gridRows; row++) {
	for (var col = 0; col < gridCols; col++) {
		var tile = game.addChild(LK.getAsset('grass', {
			x: gridStartX + col * gridWidth,
			y: gridStartY + row * gridHeight,
			anchorX: 0,
			anchorY: 0
		}));
	}
}
// Create paths (zombie lanes)
for (var lane = 0; lane < gridRows; lane++) {
	var pathTile = game.addChild(LK.getAsset('path', {
		x: gridStartX + gridCols * gridWidth,
		y: gridStartY + lane * gridHeight,
		anchorX: 0,
		anchorY: 0
	}));
}
// Create house
var house = game.addChild(LK.getAsset('house', {
	x: 50,
	y: gridStartY + gridRows * gridHeight / 2 - 200,
	anchorX: 0,
	anchorY: 0
}));
// UI Setup
var sunDisplay = new Text2(sunPoints.toString(), {
	size: 80,
	fill: 0xFFD700,
	stroke: 0x000000,
	strokeThickness: 3
});
sunDisplay.anchor.set(0, 0);
LK.gui.topLeft.addChild(sunDisplay);
sunDisplay.x = 120;
sunDisplay.y = 20;
var waveDisplay = new Text2('Wave: ' + currentWave + '/' + maxWaves, {
	size: 60,
	fill: 0x000000
});
waveDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(waveDisplay);
waveDisplay.y = 20;
// Plant selection buttons - repositioned for new order
var peashooterBtn = LK.getAsset('peashooter', {
	x: 250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(peashooterBtn);
var sunflowerBtn = LK.getAsset('sunflower', {
	x: 450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(sunflowerBtn);
var cherrypopperBtn = LK.getAsset('cherrypopper', {
	x: 650,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(cherrypopperBtn);
var wallnutBtn = LK.getAsset('wallnut', {
	x: 850,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(wallnutBtn);
var potatomineBtn = LK.getAsset('potatomine', {
	x: 1050,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(potatomineBtn);
var snowshooterBtn = LK.getAsset('snowshooter', {
	x: 1250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(snowshooterBtn);
var chomperBtn = LK.getAsset('chomper', {
	x: 1450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(chomperBtn);
var repeaterBtn = LK.getAsset('repeater', {
	x: 1650,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(repeaterBtn);
var splitpeaBtn = LK.getAsset('splitpea', {
	x: 250,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(splitpeaBtn);
var puffshroomBtn = LK.getAsset('puffshroom', {
	x: 450,
	y: 2500,
	scaleX: 0.8,
	scaleY: 0.8,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(puffshroomBtn);
var shovelBtn = LK.getAsset('shovel', {
	x: 1900,
	y: 150,
	scaleX: 1.5,
	scaleY: 1.5,
	anchorX: 0.5,
	anchorY: 0.5
});
game.addChild(shovelBtn);
// Cost display texts - updated positions to match new layout
var peaCostTxt = new Text2('100', {
	size: 70,
	fill: 0x000000
});
peaCostTxt.anchor.set(0.5, 0);
game.addChild(peaCostTxt);
peaCostTxt.x = 250;
peaCostTxt.y = 2580;
var sunCostTxt = new Text2('50', {
	size: 70,
	fill: 0x000000
});
sunCostTxt.anchor.set(0.5, 0);
game.addChild(sunCostTxt);
sunCostTxt.x = 450;
sunCostTxt.y = 2580;
var cherryCostTxt = new Text2('150', {
	size: 70,
	fill: 0x000000
});
cherryCostTxt.anchor.set(0.5, 0);
game.addChild(cherryCostTxt);
cherryCostTxt.x = 650;
cherryCostTxt.y = 2580;
var wallCostTxt = new Text2('50', {
	size: 70,
	fill: 0x000000
});
wallCostTxt.anchor.set(0.5, 0);
game.addChild(wallCostTxt);
wallCostTxt.x = 850;
wallCostTxt.y = 2580;
var potatomineCosTxt = new Text2('25', {
	size: 70,
	fill: 0x000000
});
potatomineCosTxt.anchor.set(0.5, 0);
game.addChild(potatomineCosTxt);
potatomineCosTxt.x = 1050;
potatomineCosTxt.y = 2580;
var snowCostTxt = new Text2('175', {
	size: 70,
	fill: 0x000000
});
snowCostTxt.anchor.set(0.5, 0);
game.addChild(snowCostTxt);
snowCostTxt.x = 1250;
snowCostTxt.y = 2580;
var chomperCostTxt = new Text2('150', {
	size: 70,
	fill: 0x000000
});
chomperCostTxt.anchor.set(0.5, 0);
game.addChild(chomperCostTxt);
chomperCostTxt.x = 1450;
chomperCostTxt.y = 2580;
var repeaterCostTxt = new Text2('200', {
	size: 70,
	fill: 0x000000
});
repeaterCostTxt.anchor.set(0.5, 0);
game.addChild(repeaterCostTxt);
repeaterCostTxt.x = 1650;
repeaterCostTxt.y = 2580;
var splitpeaCostTxt = new Text2('125', {
	size: 70,
	fill: 0x000000
});
splitpeaCostTxt.anchor.set(0.5, 0);
game.addChild(splitpeaCostTxt);
splitpeaCostTxt.x = 250;
splitpeaCostTxt.y = 2580;
var puffshroomCostTxt = new Text2('0', {
	size: 70,
	fill: 0x000000
});
puffshroomCostTxt.anchor.set(0.5, 0);
game.addChild(puffshroomCostTxt);
puffshroomCostTxt.x = 450;
puffshroomCostTxt.y = 2580;
var shovelCostTxt = new Text2('Free', {
	size: 70,
	fill: 0x000000
});
shovelCostTxt.anchor.set(0.5, 0);
game.addChild(shovelCostTxt);
shovelCostTxt.x = 1900;
shovelCostTxt.y = 230;
// Add left arrow for plant selector
var leftArrow = new Text2('<', {
	size: 120,
	fill: 0x000000
});
leftArrow.anchor.set(0.5, 0.5);
game.addChild(leftArrow);
leftArrow.x = 50;
leftArrow.y = 2500;
// Add right arrow for plant selector
var rightArrow = new Text2('>', {
	size: 120,
	fill: 0x000000
});
rightArrow.anchor.set(0.5, 0.5);
game.addChild(rightArrow);
rightArrow.x = 2000;
rightArrow.y = 2500;
// Calculate total zombies for victory condition
for (var w = 1; w <= maxWaves; w++) {
	totalZombiesToKill += zombiesPerWave + Math.floor(w / 2);
}
function updateSunDisplay() {
	sunDisplay.setText(sunPoints.toString());
}
function updatePlantSelector() {
	// Hide all plants first
	peashooterBtn.visible = false;
	sunflowerBtn.visible = false;
	wallnutBtn.visible = false;
	snowshooterBtn.visible = false;
	repeaterBtn.visible = false;
	cherrypopperBtn.visible = false;
	splitpeaBtn.visible = false;
	chomperBtn.visible = false;
	potatomineBtn.visible = false;
	puffshroomBtn.visible = false;
	// Hide all cost texts
	peaCostTxt.visible = false;
	sunCostTxt.visible = false;
	wallCostTxt.visible = false;
	snowCostTxt.visible = false;
	repeaterCostTxt.visible = false;
	cherryCostTxt.visible = false;
	splitpeaCostTxt.visible = false;
	chomperCostTxt.visible = false;
	potatomineCosTxt.visible = false;
	puffshroomCostTxt.visible = false;
	if (currentSelectorPage === 1) {
		// First page - show: Peashooter, Sunflower, Cherrypopper, Wallnut, Potatomine, Snowshooter, Chomper, and Repeater
		peashooterBtn.visible = true;
		sunflowerBtn.visible = true;
		cherrypopperBtn.visible = true;
		wallnutBtn.visible = true;
		potatomineBtn.visible = true;
		snowshooterBtn.visible = true;
		chomperBtn.visible = true;
		repeaterBtn.visible = true;
		// Show corresponding cost texts
		peaCostTxt.visible = true;
		sunCostTxt.visible = true;
		cherryCostTxt.visible = true;
		wallCostTxt.visible = true;
		potatomineCosTxt.visible = true;
		snowCostTxt.visible = true;
		chomperCostTxt.visible = true;
		repeaterCostTxt.visible = true;
	} else if (currentSelectorPage === 2) {
		// Second page - show splitpea and puffshroom (only from wave 11)
		splitpeaBtn.visible = true;
		splitpeaCostTxt.visible = true;
		if (currentWave >= 11) {
			puffshroomBtn.visible = true;
			puffshroomCostTxt.visible = true;
		}
	}
}
function getGridPosition(x, y) {
	var col = Math.floor((x - gridStartX) / gridWidth);
	var row = Math.floor((y - gridStartY) / gridHeight);
	if (col >= 0 && col < gridCols && row >= 0 && row < gridRows) {
		return {
			col: col,
			row: row,
			x: gridStartX + col * gridWidth + gridWidth / 2,
			y: gridStartY + row * gridHeight + gridHeight / 2
		};
	}
	return null;
}
function spawnZombie() {
	var lane = Math.floor(Math.random() * gridRows);
	var zombieType = Math.random();
	var zombie;
	// Higher spawn rates for special zombies from wave 15 onwards
	if (currentWave >= 15) {
		if (zombieType < 0.25) {
			zombie = new Gargantuar();
		} else if (zombieType < 0.50) {
			zombie = new Zomboni();
		} else if (zombieType < 0.65) {
			zombie = new JesterZombie();
		} else if (zombieType < 0.75) {
			zombie = new TankZombie();
		} else if (zombieType < 0.80) {
			zombie = new JackInBoxZombie();
		} else if (zombieType < 0.86) {
			zombie = new MinerZombie();
		} else if (zombieType < 0.92) {
			zombie = new FastZombie();
		} else if (zombieType < 0.98) {
			zombie = new NewspaperZombie();
		} else {
			zombie = new BasicZombie();
		}
	} else {
		// Original spawn rates for waves before 15
		if (currentWave > 8 && zombieType < 0.05) {
			zombie = new Gargantuar();
		} else if (currentWave > 6 && zombieType < 0.15) {
			zombie = new Zomboni();
		} else if (currentWave > 5 && zombieType < 0.25) {
			zombie = new TankZombie();
		} else if (currentWave > 4 && zombieType < 0.35) {
			zombie = new JesterZombie();
		} else if (currentWave > 2 && zombieType < 0.45) {
			zombie = new JackInBoxZombie();
		} else if (currentWave > 3 && zombieType < 0.60) {
			zombie = new MinerZombie();
		} else if (currentWave > 3 && zombieType < 0.75) {
			zombie = new FastZombie();
		} else if (currentWave > 1 && zombieType < 0.90) {
			zombie = new NewspaperZombie();
		} else {
			zombie = new BasicZombie();
		}
	}
	zombie.x = gridStartX + gridCols * gridWidth + 100;
	zombie.y = gridStartY + lane * gridHeight + gridHeight / 2;
	zombie.gridY = lane;
	// Add spawn delay animation - zombie starts invisible and fades in
	zombie.alpha = 0;
	zombie.scaleX = 0.5;
	zombie.scaleY = 0.5;
	// Animate zombie spawning in
	tween(zombie, {
		alpha: 1,
		scaleX: 1,
		scaleY: 1
	}, {
		duration: 800,
		easing: tween.easeOut
	});
	zombies.push(zombie);
	game.addChild(zombie);
	zombiesSpawned++;
}
function startNextWave() {
	if (currentWave <= maxWaves) {
		zombiesPerWave = 5 + Math.floor(currentWave / 2);
		zombiesSpawned = 0;
		waveStarted = false;
		zombieSpawnQueue = [];
		waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
		// Change background color to dark blue from wave 11
		if (currentWave >= 11) {
			game.setBackgroundColor(0x191970); // Dark blue
		}
		// Flash screen red when wave increases
		LK.effects.flashScreen(0xff0000, 1000);
		// Add delay before wave actually starts spawning zombies
		// For wave 1, add 10 second delay. For other waves, 2 second delay
		var waveStartDelay = currentWave === 1 ? 10000 : 2000;
		LK.setTimeout(function () {
			waveStarted = true;
			// Pre-queue zombie spawn times with delays
			// Use faster spawn delay from wave 5 onwards, and even faster from wave 11
			var currentSpawnDelay;
			if (currentWave >= 11) {
				currentSpawnDelay = 80; // Even faster from wave 11 (1.33 seconds)
			} else if (currentWave >= 5) {
				currentSpawnDelay = 120; // Faster from wave 5 (2 seconds)
			} else {
				currentSpawnDelay = zombieSpawnDelay; // Normal speed (4 seconds)
			}
			for (var i = 0; i < zombiesPerWave; i++) {
				zombieSpawnQueue.push({
					spawnTime: LK.ticks + i * currentSpawnDelay + Math.random() * 60,
					// Add some randomness (reduced for faster waves)
					spawned: false
				});
			}
		}, waveStartDelay);
	}
}
// Generate sun periodically
var sunGenerationTimer = 0;
var sunGenerationDelay = 480; // 8 seconds
// Event handlers
peashooterBtn.down = function () {
	if (sunPoints >= 100) {
		selectedPlantType = 'peashooter';
		LK.effects.flashObject(peashooterBtn, 0x00ff00, 300);
	}
};
sunflowerBtn.down = function () {
	if (sunPoints >= 50) {
		selectedPlantType = 'sunflower';
		LK.effects.flashObject(sunflowerBtn, 0x00ff00, 300);
	}
};
wallnutBtn.down = function () {
	if (sunPoints >= 50) {
		selectedPlantType = 'wallnut';
		LK.effects.flashObject(wallnutBtn, 0x00ff00, 300);
	}
};
snowshooterBtn.down = function () {
	if (sunPoints >= 175) {
		selectedPlantType = 'snowshooter';
		LK.effects.flashObject(snowshooterBtn, 0x00ff00, 300);
	}
};
repeaterBtn.down = function () {
	if (sunPoints >= 200) {
		selectedPlantType = 'repeater';
		LK.effects.flashObject(repeaterBtn, 0x00ff00, 300);
	}
};
cherrypopperBtn.down = function () {
	if (sunPoints >= 150) {
		selectedPlantType = 'cherrypopper';
		LK.effects.flashObject(cherrypopperBtn, 0x00ff00, 300);
	}
};
splitpeaBtn.down = function () {
	if (sunPoints >= 125) {
		selectedPlantType = 'splitpea';
		LK.effects.flashObject(splitpeaBtn, 0x00ff00, 300);
	}
};
chomperBtn.down = function () {
	if (sunPoints >= 150) {
		selectedPlantType = 'chomper';
		LK.effects.flashObject(chomperBtn, 0x00ff00, 300);
	}
};
potatomineBtn.down = function () {
	if (sunPoints >= 25) {
		selectedPlantType = 'potatomine';
		LK.effects.flashObject(potatomineBtn, 0x00ff00, 300);
	}
};
puffshroomBtn.down = function () {
	if (currentWave >= 11) {
		selectedPlantType = 'puffshroom';
		LK.effects.flashObject(puffshroomBtn, 0x00ff00, 300);
	}
};
shovelBtn.down = function () {
	selectedPlantType = 'shovel';
	LK.effects.flashObject(shovelBtn, 0x00ff00, 300);
};
leftArrow.down = function () {
	if (currentSelectorPage > 1) {
		currentSelectorPage--;
		updatePlantSelector();
		LK.effects.flashObject(leftArrow, 0x00ff00, 200);
	} else {
		// Flash gray if can't go back further
		LK.effects.flashObject(leftArrow, 0x888888, 200);
	}
};
rightArrow.down = function () {
	if (currentSelectorPage < maxSelectorPages) {
		currentSelectorPage++;
		updatePlantSelector();
		LK.effects.flashObject(rightArrow, 0x00ff00, 200);
	} else {
		// Flash gray if can't go forward further
		LK.effects.flashObject(rightArrow, 0x888888, 200);
	}
};
game.down = function (x, y, obj) {
	var gridPos = getGridPosition(x, y);
	if (gridPos && selectedPlantType) {
		var gridKey = gridPos.col + ',' + gridPos.row;
		// Handle shovel - remove existing plant
		if (selectedPlantType === 'shovel') {
			if (plantGrid[gridKey]) {
				var plantToRemove = plantGrid[gridKey];
				// Remove from plants array
				for (var i = 0; i < plants.length; i++) {
					if (plants[i] === plantToRemove) {
						plants.splice(i, 1);
						break;
					}
				}
				// Remove from grid
				delete plantGrid[gridKey];
				// Destroy the plant
				plantToRemove.destroy();
				selectedPlantType = null;
			}
			return;
		}
		// Check if position is already occupied
		if (plantGrid[gridKey]) {
			return;
		}
		var plant = null;
		var cost = 0;
		if (selectedPlantType === 'peashooter' && sunPoints >= 100) {
			plant = new Peashooter();
			cost = 100;
		} else if (selectedPlantType === 'sunflower' && sunPoints >= 50) {
			plant = new Sunflower();
			cost = 50;
		} else if (selectedPlantType === 'wallnut' && sunPoints >= 50) {
			plant = new WallNut();
			cost = 50;
		} else if (selectedPlantType === 'snowshooter' && sunPoints >= 175) {
			plant = new Snowshooter();
			cost = 175;
		} else if (selectedPlantType === 'repeater' && sunPoints >= 200) {
			plant = new Repeater();
			cost = 200;
		} else if (selectedPlantType === 'cherrypopper' && sunPoints >= 150) {
			plant = new CherryPopper();
			cost = 150;
		} else if (selectedPlantType === 'splitpea' && sunPoints >= 125) {
			plant = new SplitPea();
			cost = 125;
		} else if (selectedPlantType === 'chomper' && sunPoints >= 150) {
			plant = new Chomper();
			cost = 150;
		} else if (selectedPlantType === 'potatomine' && sunPoints >= 25) {
			plant = new Potatomine();
			cost = 25;
		} else if (selectedPlantType === 'puffshroom' && currentWave >= 11) {
			plant = new Puffshroom();
			cost = 0;
		}
		if (plant) {
			plant.x = gridPos.x;
			plant.y = gridPos.y;
			plant.gridX = gridPos.col;
			plant.gridY = gridPos.row;
			plants.push(plant);
			game.addChild(plant);
			plantGrid[gridKey] = plant;
			sunPoints -= cost;
			updateSunDisplay();
			selectedPlantType = null;
			LK.getSound('plant').play();
		}
	}
};
game.update = function () {
	// Generate sun periodically
	sunGenerationTimer++;
	if (sunGenerationTimer >= sunGenerationDelay) {
		var sun = new Sun();
		sun.x = 200 + Math.random() * 1600;
		sun.y = -100; // Start above screen
		sun.targetY = 200 + Math.random() * 1000; // Final position
		sun.isFalling = true; // Mark as falling sun
		// Animate falling from top to bottom
		tween(sun, {
			y: sun.targetY
		}, {
			duration: 2000,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				sun.isFalling = false;
			}
		});
		suns.push(sun);
		game.addChild(sun);
		sunGenerationTimer = 0;
	}
	// Wave management
	if (currentWave <= maxWaves) {
		waveTimer++;
		// Spawn zombies for current wave using queue system
		if (waveStarted && zombiesSpawned < zombiesPerWave) {
			for (var i = 0; i < zombieSpawnQueue.length; i++) {
				var queueItem = zombieSpawnQueue[i];
				if (!queueItem.spawned && LK.ticks >= queueItem.spawnTime) {
					spawnZombie();
					queueItem.spawned = true;
					break; // Only spawn one zombie per frame
				}
			}
		}
		// Start next wave
		if (zombiesSpawned >= zombiesPerWave && zombies.length === 0) {
			currentWave++;
			if (currentWave <= maxWaves) {
				startNextWave();
				waveTimer = 0;
			}
		}
	}
	// Check victory condition
	if (currentWave > maxWaves && zombies.length === 0) {
		LK.showYouWin();
	}
	// Handle slow effects on zombies
	for (var z = 0; z < zombies.length; z++) {
		var zombie = zombies[z];
		if (zombie.slowTimer) {
			zombie.slowTimer--;
			if (zombie.slowTimer <= 0) {
				// Restore original speed
				if (zombie.originalSpeed) {
					zombie.speed = zombie.originalSpeed;
				}
				// Remove slow tint
				tween(zombie, {
					tint: 0xffffff
				}, {
					duration: 300,
					easing: tween.easeOut
				});
				zombie.slowTimer = null;
			}
		}
	}
	// Update button availability
	peashooterBtn.alpha = sunPoints >= 100 ? 1.0 : 0.5;
	sunflowerBtn.alpha = sunPoints >= 50 ? 1.0 : 0.5;
	wallnutBtn.alpha = sunPoints >= 50 ? 1.0 : 0.5;
	snowshooterBtn.alpha = sunPoints >= 175 ? 1.0 : 0.5;
	repeaterBtn.alpha = sunPoints >= 200 ? 1.0 : 0.5;
	cherrypopperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
	splitpeaBtn.alpha = sunPoints >= 125 ? 1.0 : 0.5;
	chomperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
	potatomineBtn.alpha = sunPoints >= 25 ? 1.0 : 0.5;
	puffshroomBtn.alpha = currentWave >= 11 ? 1.0 : 0.5;
	shovelBtn.alpha = 1.0; // Shovel is always available
	// Update arrow button availability
	updateArrowButtons();
};
// Initialize plant selector
updatePlantSelector();
// Update arrow button availability in main update loop
function updateArrowButtons() {
	leftArrow.alpha = currentSelectorPage > 1 ? 1.0 : 0.5;
	rightArrow.alpha = currentSelectorPage < maxSelectorPages ? 1.0 : 0.5;
}
// Start first wave
startNextWave(); ===================================================================
--- original.js
+++ change.js
@@ -1048,8 +1048,74 @@
 		}
 	};
 	return self;
 });
+var Puffshroom = Container.expand(function () {
+	var self = Container.call(this);
+	var graphics = self.attachAsset('puffshroom', {
+		anchorX: 0.5,
+		anchorY: 0.5
+	});
+	self.cost = 0;
+	self.health = 100;
+	self.maxHealth = 100;
+	self.shootTimer = 0;
+	self.shootDelay = 120; // 2 seconds at 60fps
+	self.gridX = 0;
+	self.gridY = 0;
+	self.detectionRange = 3; // 3 tiles
+	self.takeDamage = function (damage) {
+		self.health -= damage;
+		LK.effects.flashObject(self, 0xff0000, 200);
+		if (self.health <= 0) {
+			self.destroy();
+			for (var i = 0; i < plants.length; i++) {
+				if (plants[i] === self) {
+					plants.splice(i, 1);
+					break;
+				}
+			}
+			var gridKey = self.gridX + ',' + self.gridY;
+			delete plantGrid[gridKey];
+		} else {
+			// Visual damage feedback
+			var damageRatio = self.health / self.maxHealth;
+			graphics.alpha = 0.3 + damageRatio * 0.7;
+		}
+	};
+	self.update = function () {
+		self.shootTimer++;
+		if (self.shootTimer >= self.shootDelay) {
+			// Check if there's a zombie within 3 tiles in this lane
+			var hasZombieInRange = false;
+			for (var i = 0; i < zombies.length; i++) {
+				var zombie = zombies[i];
+				if (zombie.gridY === self.gridY && zombie.x > self.x) {
+					var distance = Math.abs(zombie.x - self.x);
+					var tileDistance = distance / gridWidth;
+					if (tileDistance <= self.detectionRange) {
+						hasZombieInRange = true;
+						break;
+					}
+				}
+			}
+			if (hasZombieInRange) {
+				self.shoot();
+				self.shootTimer = 0;
+			}
+		}
+	};
+	self.shoot = function () {
+		var spore = new Spore();
+		spore.x = self.x + 40;
+		spore.y = self.y;
+		spore.gridY = self.gridY;
+		spores.push(spore);
+		game.addChild(spore);
+		LK.getSound('shoot').play();
+	};
+	return self;
+});
 var ReflectedFrozenPea = Container.expand(function () {
 	var self = Container.call(this);
 	var graphics = self.attachAsset('frozenpea', {
 		anchorX: 0.5,
@@ -1134,8 +1200,51 @@
 		}
 	};
 	return self;
 });
+var ReflectedSpore = Container.expand(function () {
+	var self = Container.call(this);
+	var graphics = self.attachAsset('spore', {
+		anchorX: 0.5,
+		anchorY: 0.5
+	});
+	// Tint dark brown to show it's reflected
+	graphics.tint = 0x654321;
+	self.speed = -6;
+	self.damage = 15;
+	self.gridY = 0;
+	self.update = function () {
+		self.x += self.speed;
+		// Check collision with plants
+		for (var i = 0; i < plants.length; i++) {
+			var plant = plants[i];
+			if (plant.gridY === self.gridY && self.intersects(plant)) {
+				if (plant.takeDamage) {
+					plant.takeDamage(self.damage);
+				}
+				self.destroy();
+				for (var j = 0; j < reflectedspores.length; j++) {
+					if (reflectedspores[j] === self) {
+						reflectedspores.splice(j, 1);
+						break;
+					}
+				}
+				return;
+			}
+		}
+		// Remove if off screen (left side)
+		if (self.x < -100) {
+			self.destroy();
+			for (var k = 0; k < reflectedspores.length; k++) {
+				if (reflectedspores[k] === self) {
+					reflectedspores.splice(k, 1);
+					break;
+				}
+			}
+		}
+	};
+	return self;
+});
 var Repeater = Container.expand(function () {
 	var self = Container.call(this);
 	var graphics = self.attachAsset('repeater', {
 		anchorX: 0.5,
@@ -1342,8 +1451,60 @@
 		LK.getSound('shoot').play();
 	};
 	return self;
 });
+var Spore = Container.expand(function () {
+	var self = Container.call(this);
+	var graphics = self.attachAsset('spore', {
+		anchorX: 0.5,
+		anchorY: 0.5
+	});
+	self.speed = 6;
+	self.damage = 10;
+	self.gridY = 0;
+	self.update = function () {
+		self.x += self.speed;
+		// Check collision with zombies
+		for (var i = 0; i < zombies.length; i++) {
+			var zombie = zombies[i];
+			if (zombie.gridY === self.gridY && self.intersects(zombie)) {
+				// Check if it's a JesterZombie
+				if (zombie.isJester) {
+					// Create reflected spore going back towards plants
+					var reflectedSpore = new ReflectedSpore();
+					reflectedSpore.x = zombie.x - 50;
+					reflectedSpore.y = zombie.y;
+					reflectedSpore.gridY = zombie.gridY;
+					reflectedspores.push(reflectedSpore);
+					game.addChild(reflectedSpore);
+					// Flash jester zombie to show deflection
+					LK.effects.flashObject(zombie, 0xffff00, 200);
+				} else {
+					zombie.takeDamage(self.damage, 'spore');
+				}
+				self.destroy();
+				for (var j = 0; j < spores.length; j++) {
+					if (spores[j] === self) {
+						spores.splice(j, 1);
+						break;
+					}
+				}
+				return;
+			}
+		}
+		// Remove if off screen
+		if (self.x > 2200) {
+			self.destroy();
+			for (var k = 0; k < spores.length; k++) {
+				if (spores[k] === self) {
+					spores.splice(k, 1);
+					break;
+				}
+			}
+		}
+	};
+	return self;
+});
 var Sun = Container.expand(function () {
 	var self = Container.call(this);
 	var graphics = self.attachAsset('sun', {
 		anchorX: 0.5,
@@ -1494,8 +1655,10 @@
 var frozenpeas = [];
 var reflectedpeas = [];
 var reflectedfrozenpeas = [];
 var backwardpeas = [];
+var spores = [];
+var reflectedspores = [];
 var suns = [];
 var plantGrid = {}; // Track occupied grid positions
 // Grid settings
 var gridStartX = 400;
@@ -1635,8 +1798,17 @@
 	anchorX: 0.5,
 	anchorY: 0.5
 });
 game.addChild(splitpeaBtn);
+var puffshroomBtn = LK.getAsset('puffshroom', {
+	x: 450,
+	y: 2500,
+	scaleX: 0.8,
+	scaleY: 0.8,
+	anchorX: 0.5,
+	anchorY: 0.5
+});
+game.addChild(puffshroomBtn);
 var shovelBtn = LK.getAsset('shovel', {
 	x: 1900,
 	y: 150,
 	scaleX: 1.5,
@@ -1717,8 +1889,16 @@
 splitpeaCostTxt.anchor.set(0.5, 0);
 game.addChild(splitpeaCostTxt);
 splitpeaCostTxt.x = 250;
 splitpeaCostTxt.y = 2580;
+var puffshroomCostTxt = new Text2('0', {
+	size: 70,
+	fill: 0x000000
+});
+puffshroomCostTxt.anchor.set(0.5, 0);
+game.addChild(puffshroomCostTxt);
+puffshroomCostTxt.x = 450;
+puffshroomCostTxt.y = 2580;
 var shovelCostTxt = new Text2('Free', {
 	size: 70,
 	fill: 0x000000
 });
@@ -1761,8 +1941,9 @@
 	cherrypopperBtn.visible = false;
 	splitpeaBtn.visible = false;
 	chomperBtn.visible = false;
 	potatomineBtn.visible = false;
+	puffshroomBtn.visible = false;
 	// Hide all cost texts
 	peaCostTxt.visible = false;
 	sunCostTxt.visible = false;
 	wallCostTxt.visible = false;
@@ -1771,8 +1952,9 @@
 	cherryCostTxt.visible = false;
 	splitpeaCostTxt.visible = false;
 	chomperCostTxt.visible = false;
 	potatomineCosTxt.visible = false;
+	puffshroomCostTxt.visible = false;
 	if (currentSelectorPage === 1) {
 		// First page - show: Peashooter, Sunflower, Cherrypopper, Wallnut, Potatomine, Snowshooter, Chomper, and Repeater
 		peashooterBtn.visible = true;
 		sunflowerBtn.visible = true;
@@ -1791,11 +1973,15 @@
 		snowCostTxt.visible = true;
 		chomperCostTxt.visible = true;
 		repeaterCostTxt.visible = true;
 	} else if (currentSelectorPage === 2) {
-		// Second page - show splitpea
+		// Second page - show splitpea and puffshroom (only from wave 11)
 		splitpeaBtn.visible = true;
 		splitpeaCostTxt.visible = true;
+		if (currentWave >= 11) {
+			puffshroomBtn.visible = true;
+			puffshroomCostTxt.visible = true;
+		}
 	}
 }
 function getGridPosition(x, y) {
 	var col = Math.floor((x - gridStartX) / gridWidth);
@@ -1972,8 +2158,14 @@
 		selectedPlantType = 'potatomine';
 		LK.effects.flashObject(potatomineBtn, 0x00ff00, 300);
 	}
 };
+puffshroomBtn.down = function () {
+	if (currentWave >= 11) {
+		selectedPlantType = 'puffshroom';
+		LK.effects.flashObject(puffshroomBtn, 0x00ff00, 300);
+	}
+};
 shovelBtn.down = function () {
 	selectedPlantType = 'shovel';
 	LK.effects.flashObject(shovelBtn, 0x00ff00, 300);
 };
@@ -2052,8 +2244,11 @@
 			cost = 150;
 		} else if (selectedPlantType === 'potatomine' && sunPoints >= 25) {
 			plant = new Potatomine();
 			cost = 25;
+		} else if (selectedPlantType === 'puffshroom' && currentWave >= 11) {
+			plant = new Puffshroom();
+			cost = 0;
 		}
 		if (plant) {
 			plant.x = gridPos.x;
 			plant.y = gridPos.y;
@@ -2149,8 +2344,9 @@
 	cherrypopperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
 	splitpeaBtn.alpha = sunPoints >= 125 ? 1.0 : 0.5;
 	chomperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
 	potatomineBtn.alpha = sunPoints >= 25 ? 1.0 : 0.5;
+	puffshroomBtn.alpha = currentWave >= 11 ? 1.0 : 0.5;
 	shovelBtn.alpha = 1.0; // Shovel is always available
 	// Update arrow button availability
 	updateArrowButtons();
 };