User prompt
Add new weapons in encyclopedia
User prompt
Bow gets reworked so that its arrows deal less damage and don't pierce through enemies anymore, but you get 100% more XP than any other weapon
User prompt
Arrows get reworked so that they explode after they disappear ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Arrows should have a bigger lifespan
User prompt
Add new weapons: Toy Bow (Bart is now armed with a bow! It shoots rubber arrows that can pierce through up to 3 enemies), Pot-a-Bomb (Bart holds a pot! The pot deals area damage and has a chance to split into 4 pottery sherds on all diagnoals) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make buttons for equipping weapons and sub weapons A LOT BIGGER
User prompt
I can't equip snowball II anymore: fox that
User prompt
Homing Sound Waves should be faster but smaller and should have a slightly bigger lifespan ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sound waves should be much bigger and faster and should have a longer lifespan and should have a glowing effect ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sound waves should have the same logic as regular projectiles like bowling balls
User prompt
Make Sound waves a lot faster but make homing sound wave only slightly faster
User prompt
Drummer's sound waves always stop moving even if their life span isn't over: fix that by making them always move
User prompt
Drummer's sound waves always stop moving even if their life span isn't over: fix that by making them always move
User prompt
Drummer's sound waves now never stop moving and have an infinite life span until they go off screen
User prompt
Add new Attacks to Concert: Noisy Drumming: Drummer shoots 10 sound waves really fast every 10 seconds; Rising Rockstars: Summon a Drummer Mutant, Vocal Mutant and Rocker Mutant every 15 seconds; Stereo Sounds: Vocal, Drummer and Rocker all shoot a homing soundwave that instakills Bart every 60 seconds
User prompt
Add new Attacks to Concert: Noisy Drumming: Drummer shoots 10 sound waves really fast every 10 seconds; Rising Rockstars: Summon a Drummer Mutant, Vocal Mutant and Rocker Mutant every 15 seconds; Stereo Sounds: Vocal, Drummer and Rocker all shoot a homing soundwave that instakills Bart every 60 seconds
User prompt
Add a boss selection for Boss Rush
User prompt
Add new Giant Mutant: Concert! The concert is a 25750 HP Giant Mutant that cannot move and is at the top of the screen. It has a concert asset and a Drummer on the left, Vocal in the center and Rocker in the right assets on top of it. Here are it's abilities: Ecsessive Drumming: The Drummer on top of the Concert shoots 3 soundwaves at Bart every 3.75 seconds in a spread that deal slightly more damage than the regular ones; Rock fans: During the fight, Regular Mutants spawn like normal, but there is no wave system in this one, so it's always Regular Mutants; Swear-fest: The vocal in the Concert will swear excessively every 10 seconds, making everything deal 15% more damage permanently up to 90%; Rock Music: The Rocker in the concert makes all mutants on screen faster every 5 seconds
User prompt
Add new Giant Mutant: Concert! The concert is a 25750 HP Giant Mutant that cannot move and is at the top of the screen. It has a concert asset and a Drummer on the left, Vocal in the center and Rocker in the right assets on top of it. Here are it's abilities: Ecsessive Drumming: The Drummer on top of the Concert shoots 3 soundwaves at Bart every 3.75 seconds in a spread that deal slightly more damage than the regular ones; Rock fans: During the fight, Regular Mutants spawn like normal, but there is no wave system in this one, so it's always Regular Mutants; Swear-fest: The vocal in the Concert will swear excessively every 10 seconds, making everything deal 15% more damage permanently up to 90%; Rock Music: The Rocker in the concert makes all mutants on screen faster every 5 seconds ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Boss rush now has an entry fee of 50 coins
User prompt
Reduce Mutant Leader Health to 20000 health
User prompt
Giant Mutants (and ONLY Giant Mutants) should automatically give you 350 coins
User prompt
Enemies should never give you 100 coins
User prompt
Enemies should never drop 100 gold
User prompt
Buff Mutant Leader by making him have 35000 HP, Always Instakill Bart and have a new ability: Rage! When at 50% health, he is faster and summons enemies every 4.5 seconds
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var AlienMeal = Container.expand(function () { var self = Container.call(this); var mealGraphics = self.attachAsset('alien_meal', { anchorX: 0.5, anchorY: 0.5 }); self.invincibilityDuration = 600; // 10 seconds at 60fps self.checkRadius = 80; self.lifetime = 600; // 10 seconds self.consumed = false; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } // Pulsing effect to show it's active mealGraphics.alpha = 0.7 + Math.sin(LK.ticks * 0.2) * 0.3; // Check for non-cook mutants touching the meal if (!self.consumed) { for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Skip cook mutants - they can't consume their own meals if (enemy instanceof CookMutant) continue; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.checkRadius) { // Give invincibility to this enemy enemy.invincible = true; enemy.invincibilityTimer = self.invincibilityDuration; // Visual effect for invincibility gain LK.effects.flashObject(enemy, 0x00FFFF, 500); tween(enemy, { tint: 0x00FFFF }, { duration: 200, easing: tween.easeOut }); tween(enemy, { tint: 0xFFFFFF }, { duration: 200, easing: tween.easeIn }); // Mark meal as consumed self.consumed = true; self.shouldDestroy = true; return; } } } }; return self; }); var Bart = Container.expand(function () { var self = Container.call(this); var bartGraphics = self.attachAsset('bart_slingshot', { anchorX: 0.5, anchorY: 0.5 }); self.bartGraphics = bartGraphics; self.currentWeapon = 'slingshot'; self.updateWeaponVisual = function (weaponId) { if (self.currentWeapon === weaponId) return; self.currentWeapon = weaponId; var oldGraphics = self.bartGraphics; var newGraphics = self.attachAsset('bart_' + weaponId, { anchorX: 0.5, anchorY: 0.5 }); newGraphics.x = oldGraphics.x; newGraphics.y = oldGraphics.y; newGraphics.rotation = oldGraphics.rotation; newGraphics.alpha = oldGraphics.alpha; newGraphics.scaleX = oldGraphics.scaleX; newGraphics.scaleY = oldGraphics.scaleY; self.removeChild(oldGraphics); self.bartGraphics = newGraphics; }; self.maxHealth = 100; self.health = self.maxHealth; self.level = 1; self.xp = 0; self.xpToNext = 100; self.damage = 10; self.fireRate = 30; self.fireTimer = 0; self.coins = 0; self.takeDamage = function (damage) { self.health -= damage; LK.getSound('hut').play(); LK.effects.flashObject(self, 0xFF0000, 500); if (healthBarFill) { healthBarFill.scaleX = Math.max(0, self.health / self.maxHealth); } if (self.health <= 0) { try { storage.coins = self.coins; } catch (e) { console.log('Could not save coins on game over:', e); } LK.showGameOver(); } }; self.gainXP = function (amount) { self.xp += amount; while (self.xp >= self.xpToNext) { self.xp -= self.xpToNext; self.level++; self.xpToNext = self.level * 100; self.maxHealth += 20; self.health = self.maxHealth; if (healthBarFill) { healthBarFill.scaleX = 1; } self.damage += 5; self.fireRate = Math.max(10, self.fireRate - 2); LK.getSound('levelup').play(); LK.effects.flashScreen(0xFFFF00, 300); } }; self.update = function () { self.fireTimer--; }; return self; }); var Boss = Container.expand(function () { var self = Container.call(this); var bossGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 500; self.health = self.maxHealth; self.speed = 1; self.xpValue = 100; self.coinChance = 1; self.powerupChance = 0.5; self.invincible = true; self.invincibilityTimer = 180; // 3 seconds at 60fps var healthBarBg = self.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, y: -100 }); self.healthBarFill = self.attachAsset('healthbar_fill', { anchorX: 0, anchorY: 0.5, x: -100, y: -100 }); self.takeDamage = function (damage) { if (self.invincible) return; // No damage during invincibility self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); self.healthBarFill.scaleX = Math.max(0, self.health / self.maxHealth); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; bossGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; // Flashing effect if (self.invincibilityTimer <= 0) { self.invincible = false; bossGraphics.alpha = 1; // Reset to full opacity } } if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } }; return self; }); var BowlingBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('bowling_ball', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 15; self.targetX = 0; self.targetY = 0; self.directionSet = false; self.velocityX = 0; self.velocityY = 0; self.lifetime = 180; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } if (!self.directionSet) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.velocityX = dx / dist * self.speed; self.velocityY = dy / dist * self.speed; } self.directionSet = true; } self.x += self.velocityX; self.y += self.velocityY; self.rotation += 0.2; }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 10; self.speed = 15; self.target = null; self.lifetime = 60; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } if (self.target && !self.target.destroyed) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } else { self.y -= self.speed; } }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.value = 5; self.lifetime = 300; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; } self.rotation += 0.05; }; return self; }); var Concert = Container.expand(function () { var self = Container.call(this); var concertGraphics = self.attachAsset('concert', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 25750; self.health = self.maxHealth; self.speed = 0; // Cannot move self.xpValue = 2000; self.coinChance = 1; self.powerupChance = 1; self.isInstantKillBoss = true; // Damage multiplier from swearing self.damageMultiplier = 1.0; self.maxDamageMultiplier = 1.9; // Up to 90% more damage // Timers for abilities self.drummingTimer = 225; // 3.75 seconds self.swearTimer = 600; // 10 seconds self.rockMusicTimer = 300; // 5 seconds // Performer sprites on top of concert self.drummer = self.attachAsset('drummer', { anchorX: 0.5, anchorY: 1, x: -200, y: -150 }); self.vocal = self.attachAsset('vocal', { anchorX: 0.5, anchorY: 1, x: 0, y: -150 }); self.rocker = self.attachAsset('rocker', { anchorX: 0.5, anchorY: 1, x: 200, y: -150 }); // Health bar var healthBarBg = self.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, y: -350, scaleX: 2 }); self.healthBarFill = self.attachAsset('healthbar_fill', { anchorX: 0, anchorY: 0.5, x: -200, y: -350, scaleX: 2 }); self.takeDamage = function (damage) { // Apply damage multiplier from swearing var actualDamage = damage * self.damageMultiplier; self.health -= actualDamage; LK.effects.flashObject(self, 0xFFFFFF, 200); self.healthBarFill.scaleX = Math.max(0, self.health / self.maxHealth) * 2; if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); // Drop massive coins for (var i = 0; i < 30; i++) { spawnItem(self.x + (Math.random() - 0.5) * 400, self.y + (Math.random() - 0.5) * 300, 'coin'); } } }; self.update = function () { // Update timers self.drummingTimer--; self.swearTimer--; self.rockMusicTimer--; if (bart) { // Excessive Drumming: Drummer shoots 3 soundwaves in spread if (self.drummingTimer <= 0) { for (var i = -1; i <= 1; i++) { var soundWave = new SoundWave(); soundWave.x = self.x - 200; // From drummer position soundWave.y = self.y - 150; // Create spread targeting var spreadAngle = i * 0.4; // Spread angle var dx = bart.x - soundWave.x; var dy = bart.y - soundWave.y; var baseAngle = Math.atan2(dy, dx); var newAngle = baseAngle + spreadAngle; var targetDist = Math.sqrt(dx * dx + dy * dy); soundWave.targetX = soundWave.x + Math.cos(newAngle) * targetDist; soundWave.targetY = soundWave.y + Math.sin(newAngle) * targetDist; soundWave.damage = 18; // Slightly more than regular (12) enemyProjectiles.push(soundWave); game.addChild(soundWave); } self.drummingTimer = 225; // Reset timer LK.effects.flashObject(self.drummer, 0xFF00FF, 300); } // Swear-fest: Increase damage permanently up to 90% if (self.swearTimer <= 0) { if (self.damageMultiplier < self.maxDamageMultiplier) { self.damageMultiplier += 0.15; // 15% increase self.damageMultiplier = Math.min(self.damageMultiplier, self.maxDamageMultiplier); LK.effects.flashObject(self.vocal, 0xFF0000, 500); LK.effects.flashScreen(0xFF0000, 300); // Visual effect to show damage increase tween(self.vocal, { scaleX: 1.3, scaleY: 1.3 }, { duration: 300, easing: tween.easeOut }); tween(self.vocal, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeIn }); } self.swearTimer = 600; // Reset timer } // Rock Music: Make all mutants faster if (self.rockMusicTimer <= 0) { for (var i = 0; i < enemies.length; i++) { if (enemies[i] !== self && !enemies[i].rockBoosted) { enemies[i].originalRockSpeed = enemies[i].speed; enemies[i].speed *= 1.5; // 50% faster enemies[i].rockBoosted = true; enemies[i].rockBoostTimer = 300; // 5 seconds LK.effects.flashObject(enemies[i], 0x00FFFF, 500); } } self.rockMusicTimer = 300; // Reset timer LK.effects.flashObject(self.rocker, 0x00FFFF, 500); // Visual effect for rock music tween(self.rocker, { scaleX: 1.4, scaleY: 1.4 }, { duration: 250, easing: tween.easeOut }); tween(self.rocker, { scaleX: 1, scaleY: 1 }, { duration: 250, easing: tween.easeIn }); } } // Pulsing effect for the concert concertGraphics.alpha = 0.9 + Math.sin(LK.ticks * 0.05) * 0.1; }; return self; }); var CookMutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('cook_mutant', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 60; self.health = self.maxHealth; self.speed = 1.5; self.xpValue = 30; self.coinChance = 0.5; self.powerupChance = 0.2; self.cookTimer = 0; self.cookInterval = 240; // 4 seconds self.invincible = true; self.invincibilityTimer = 180; // 3 seconds at 60fps self.takeDamage = function (damage) { if (self.invincible) return; // No damage during invincibility self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; // Flashing effect if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; // Reset to full opacity } } self.cookTimer--; if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } // Cook alien meals when close to other enemies if (self.cookTimer <= 0) { var nearbyEnemies = []; for (var i = 0; i < enemies.length; i++) { if (enemies[i] !== self) { var eDx = enemies[i].x - self.x; var eDy = enemies[i].y - self.y; var eDist = Math.sqrt(eDx * eDx + eDy * eDy); if (eDist < 300) { nearbyEnemies.push(enemies[i]); } } } if (nearbyEnemies.length > 0) { // Create an alien meal var meal = new AlienMeal(); meal.x = self.x + (Math.random() - 0.5) * 100; meal.y = self.y + (Math.random() - 0.5) * 100; alienMeals.push(meal); game.addChild(meal); self.cookTimer = self.cookInterval; LK.effects.flashObject(self, 0x00FF00, 300); } } } }; return self; }); var Dart = Container.expand(function () { var self = Container.call(this); var dartGraphics = self.attachAsset('dart', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 10; self.speed = 20; self.target = null; self.lifetime = 60; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } if (self.target && !self.target.destroyed) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; self.rotation = Math.atan2(dy, dx) + Math.PI / 2; // Point towards target } } else { self.y -= self.speed; } }; return self; }); var DrummerMutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('drummer_mutant', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 150; self.health = self.maxHealth; self.speed = 0.8; self.xpValue = 45; self.coinChance = 0.6; self.powerupChance = 0.3; self.shootTimer = 0; self.shootInterval = 90; // 1.5 seconds base self.invincible = true; self.invincibilityTimer = 180; self.takeDamage = function (damage) { if (self.invincible) return; self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; } } self.shootTimer--; // Check if Vocal is on screen to double attack speed var vocalOnScreen = false; for (var i = 0; i < enemies.length; i++) { if (enemies[i] instanceof VocalMutant && enemies[i] !== self) { vocalOnScreen = true; break; } } var currentInterval = vocalOnScreen ? self.shootInterval / 2 : self.shootInterval; if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } // Shoot sound waves at Bart (infinite range) if (self.shootTimer <= 0) { var soundWave = new SoundWave(); soundWave.x = self.x; soundWave.y = self.y; soundWave.targetX = bart.x; soundWave.targetY = bart.y; enemyProjectiles.push(soundWave); game.addChild(soundWave); self.shootTimer = currentInterval; // Visual effect when shooting LK.effects.flashObject(self, 0xFF00FF, 300); } } }; return self; }); var Encyclopedia = Container.expand(function () { var self = Container.call(this); // Background var bg = self.attachAsset('encyclopedia', { anchorX: 0.5, anchorY: 0.5 }); // Title self.titleText = new Text2('ENCYCLOPEDIA', { size: 80, fill: 0xFFFF00 }); self.titleText.anchor.set(0.5, 0.5); self.titleText.y = -300; self.addChild(self.titleText); // Page content container self.pageContainer = new Container(); self.addChild(self.pageContainer); // Close button var closeButton = self.attachAsset('info_button', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 350 }); var closeText = new Text2('CLOSE', { size: 40, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeText.y = 350; self.addChild(closeText); // Navigation buttons var prevButton = self.attachAsset('info_button', { anchorX: 0.5, anchorY: 0.5, x: -200, y: 280, scaleX: 0.8 }); var prevText = new Text2('< PREV', { size: 35, fill: 0xFFFFFF }); prevText.anchor.set(0.5, 0.5); prevText.x = -200; prevText.y = 280; self.addChild(prevText); var nextButton = self.attachAsset('info_button', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 280, scaleX: 0.8 }); var nextText = new Text2('NEXT >', { size: 35, fill: 0xFFFFFF }); nextText.anchor.set(0.5, 0.5); nextText.x = 200; nextText.y = 280; self.addChild(nextText); // Page indicator self.pageIndicator = new Text2('Page 1/1', { size: 30, fill: 0xAAAAAA }); self.pageIndicator.anchor.set(0.5, 0.5); self.pageIndicator.y = 320; self.addChild(self.pageIndicator); self.currentPage = 0; self.pages = []; // Initialize encyclopedia content self.initializePages = function () { self.pages = [ // Enemies { title: "MUTANT", content: "Basic enemy that moves towards Bart.\nHealth: 30 + (wave × 15)\nSpeed: 2 + (wave × 0.3)\nXP Value: 10 + (wave × 2)\nAppears from: Wave 1" }, { title: "FAST MUTANT", content: "Quick enemy that rushes at Bart.\nHealth: 15 + (wave × 8)\nSpeed: 4 + (wave × 0.4)\nXP Value: 15 + (wave × 2)\nAppears from: Wave 2" }, { title: "SHOOTER MUTANT", content: "Fires bowling balls at Bart.\nHealth: 50 + (wave × 10)\nSpeed: 1.5 + (wave × 0.2)\nXP Value: 25 + (wave × 3)\nAppears from: Wave 7" }, { title: "COOK MUTANT", content: "Creates alien meals that grant invincibility.\nHealth: 60 + (wave × 10)\nSpeed: 1.5 + (wave × 0.2)\nXP Value: 30 + (wave × 4)\nAppears from: Wave 6" }, { title: "POET MUTANT", content: "Summons other mutants to help!\nHealth: 80 + (wave × 12)\nSpeed: 1 + (wave × 0.15)\nXP Value: 40 + (wave × 5)\nAppears from: Wave 8" }, { title: "SAMURAI MUTANT", content: "Has a spinning katana that reflects projectiles.\nHealth: 100 + (wave × 15)\nSpeed: 1.2 + (wave × 0.2)\nXP Value: 50 + (wave × 6)\nAppears from: Wave 8" }, { title: "DRUMMER MUTANT", content: "High HP, shoots sound waves. Attack speed doubles if Vocal is present.\nHealth: 150 + (wave × 20)\nSpeed: 0.8 + (wave × 0.1)\nXP Value: 45 + (wave × 5)\nAppears from: Wave 13" }, { title: "VOCAL MUTANT", content: "Fast with low HP. Damage doubles if Rocker is present.\nHealth: 40 + (wave × 10)\nSpeed: 5 + (wave × 0.5)\nXP Value: 35 + (wave × 4)\nAppears from: Wave 13" }, { title: "ROCKER MUTANT", content: "Boosts ally speed for 5 seconds. Enhanced boost if Drummer is present.\nHealth: 70 + (wave × 15)\nSpeed: 2.5 + (wave × 0.3)\nXP Value: 40 + (wave × 5)\nAppears from: Wave 13" }, { title: "BOSS", content: "Powerful enemy that appears every 5 waves.\nHealth: 500 + ((wave-5) × 200)\nSpeed: 1 + (wave × 0.1)\nXP Value: 100 + (wave × 20)\nAppears: Waves 5, 10, 15, 20..." }, // Weapons { title: "SLINGSHOT", content: "The default weapon.\nDamage: 10\nFire Rate: Medium\nProjectiles: 1\nCost: FREE (Starting weapon)" }, { title: "DART GUN", content: "High damage, slow fire rate.\nDamage: 50\nFire Rate: Slow\nProjectiles: 1\nCost: 100 coins" }, { title: "SCATTERSHOT", content: "Shoots peanuts that split.\nDamage: 15 (5 per split)\nFire Rate: Medium-Slow\nProjectiles: 1→3\nCost: 250 coins" }, { title: "DUCKY TRIPLE", content: "Shoots 3 projectiles in a spread.\nDamage: 25\nFire Rate: Medium\nProjectiles: 3\nCost: 500 coins" }, { title: "SPRAYCAN", content: "Stuns enemies on hit.\nDamage: 8\nFire Rate: Slow\nStun: 1.2 seconds\nCost: 750 coins" }, { title: "KRUSTY'S FLOWER", content: "Water beam with rapid fire.\nDamage: 3\nFire Rate: Very Fast\nProjectiles: 1 (continuous)\nCost: 1000 coins" }, // Subweapons { title: "SANTA'S LITTLE HELPER", content: "Fast ally that bites enemies.\nDamage: 15 per bite\nSpeed: 12\nSight Range: 800 pixels\nCost: 750 coins" }, { title: "KRUSTY BURGER SHOP", content: "Spawns powerups periodically.\nSpawn Rate: Every 15 seconds\nPowerup Types: Damage/Fire Rate\nCost: 1200 coins" }, { title: "SNOWBALL II", content: "Sneaky cat that distracts enemies.\nDistraction Range: 600 pixels\nReduces invincibility by 50%\nSpeed: 8\nCost: 900 coins" }, // Game Features { title: "POWER-UPS", content: "Dropped by enemies randomly.\n• Damage Boost: +5 damage\n• Fire Rate: -5 fire rate delay\nDrop chance varies by enemy type." }, { title: "COINS", content: "Currency for buying weapons.\nValue: 5 coins each\nDropped by defeated enemies.\nCoins are saved between games!" }, { title: "ALIEN MEALS", content: "Created by Cook Mutants.\nGrants 10 seconds invincibility.\nCan be destroyed by shooting.\nOnly non-cook mutants can consume." }, { title: "INVINCIBILITY", content: "Enemy spawn protection:\n• Waves 1-9: 3 seconds\n• Waves 10-14: 1.5 seconds\n• Wave 15+: No invincibility" }, { title: "LEVELING SYSTEM", content: "Gain XP from defeating enemies.\nEach level grants:\n• +20 max health\n• +5 damage\n• -2 fire rate delay\nFull heal on level up!" }, { title: "WAVE PROGRESSION", content: "Infinite waves with scaling difficulty.\nBosses appear every 5 waves.\nEnemies get stronger each wave.\nNew enemy types unlock at higher waves." }]; }; self.showPage = function (pageIndex) { // Clear previous content self.pageContainer.removeChildren(); if (pageIndex >= 0 && pageIndex < self.pages.length) { var page = self.pages[pageIndex]; // Page title var pageTitle = new Text2(page.title, { size: 60, fill: 0x00FFFF }); pageTitle.anchor.set(0.5, 0.5); pageTitle.y = -200; self.pageContainer.addChild(pageTitle); // Page content var lines = page.content.split('\n'); var yOffset = -100; for (var i = 0; i < lines.length; i++) { var contentLine = new Text2(lines[i], { size: 35, fill: 0xFFFFFF }); contentLine.anchor.set(0.5, 0.5); contentLine.y = yOffset; self.pageContainer.addChild(contentLine); yOffset += 45; } self.currentPage = pageIndex; self.pageIndicator.setText('Page ' + (pageIndex + 1) + '/' + self.pages.length); } }; self.nextPage = function () { if (self.currentPage < self.pages.length - 1) { self.showPage(self.currentPage + 1); } }; self.prevPage = function () { if (self.currentPage > 0) { self.showPage(self.currentPage - 1); } }; self.initializePages(); self.showPage(0); return self; }); var FastMutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('fast_mutant', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 15; self.health = self.maxHealth; self.speed = 4; self.xpValue = 15; self.coinChance = 0.2; self.powerupChance = 0.05; self.invincible = true; self.invincibilityTimer = 180; // 3 seconds at 60fps self.takeDamage = function (damage) { if (self.invincible) return; // No damage during invincibility self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; // Flashing effect if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; // Reset to full opacity } } var target = self.distractedBy || bart; if (target) { var dx = target.x - self.x; var dy = target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } if (self.distractedBy && dist < 100) { self.distractedBy = null; } } }; return self; }); var FlowerBeam = Container.expand(function () { var self = Container.call(this); var beamGraphics = self.attachAsset('flower_beam', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 10; self.speed = 25; self.target = null; self.lifetime = 60; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } if (self.target && !self.target.destroyed) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; self.rotation = Math.atan2(dy, dx) + Math.PI / 2; // Point towards target } } else { self.y -= self.speed; } }; return self; }); var KrustyShop = Container.expand(function () { var self = Container.call(this); var shopGraphics = self.attachAsset('krusty_shop', { anchorX: 0.5, anchorY: 0.5 }); self.powerupTimer = 900; // 15 seconds at 60fps self.update = function () { self.powerupTimer--; // Pulse effect when close to spawning powerup if (self.powerupTimer < 60) { shopGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.5) * 0.5; } else { shopGraphics.alpha = 1; } if (self.powerupTimer <= 0) { // Spawn powerup spawnItem(self.x, self.y, 'powerup'); self.powerupTimer = 900; // Reset timer LK.effects.flashObject(self, 0xFFFF00, 500); } // Gentle floating animation self.y += Math.sin(LK.ticks * 0.03) * 0.3; }; return self; }); var LeaderBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('leader_bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 90; self.targetX = 0; self.targetY = 0; self.directionSet = false; self.velocityX = 0; self.velocityY = 0; self.lifetime = 180; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } if (!self.directionSet) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.velocityX = dx / dist * self.speed; self.velocityY = dy / dist * self.speed; } self.directionSet = true; } self.x += self.velocityX; self.y += self.velocityY; self.rotation += 0.15; }; return self; }); var Mutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('mutant', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 30; self.health = self.maxHealth; self.speed = 2; self.xpValue = 10; self.coinChance = 0.3; self.powerupChance = 0.1; self.invincible = true; self.invincibilityTimer = 180; // 3 seconds at 60fps self.stunned = false; self.stunnedTimer = 0; self.takeDamage = function (damage, stunDuration) { if (self.invincible) return; // No damage during invincibility self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (stunDuration && stunDuration > 0) { self.stunned = true; self.stunnedTimer = stunDuration; } if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.stunned) { self.stunnedTimer--; mutantGraphics.tint = 0x00FF00; // Green tint when stunned if (self.stunnedTimer <= 0) { self.stunned = false; mutantGraphics.tint = 0xFFFFFF; } return; // Don't move when stunned } if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; // Flashing effect if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; // Reset to full opacity } } // Check if distracted by Snowball II var target = self.distractedBy || bart; if (target) { var dx = target.x - self.x; var dy = target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } // Reset distraction after getting close if (self.distractedBy && dist < 100) { self.distractedBy = null; } } }; return self; }); var MutantLeader = Container.expand(function () { var self = Container.call(this); var leaderGraphics = self.attachAsset('mutant_leader', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.maxHealth = 20000; self.health = self.maxHealth; self.speed = 3; self.xpValue = 1000; self.coinChance = 1; self.coinValue = 100; // Drops 100 coins self.powerupChance = 1; self.isInstantKillBoss = true; // Special flag to not destroy on contact self.rageMode = false; self.originalSpeed = self.speed; // Timers for abilities self.callForHelpTimer = 600; // 10 seconds self.gunAttackTimer = 300; // 5 seconds self.whistleTimer = 1200; // 20 seconds // Health bar var healthBarBg = self.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, y: -150, scaleX: 1.5 }); self.healthBarFill = self.attachAsset('healthbar_fill', { anchorX: 0, anchorY: 0.5, x: -150, y: -150, scaleX: 1.5 }); self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); self.healthBarFill.scaleX = Math.max(0, self.health / self.maxHealth) * 1.5; if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); // Drop tons of coins for (var i = 0; i < 20; i++) { spawnItem(self.x + (Math.random() - 0.5) * 200, self.y + (Math.random() - 0.5) * 200, 'coin'); } } }; self.update = function () { // Update timers self.callForHelpTimer--; self.gunAttackTimer--; self.whistleTimer--; // Check for rage mode activation at 50% health if (!self.rageMode && self.health <= self.maxHealth / 2) { self.rageMode = true; self.speed = self.originalSpeed * 1.5; // 50% faster LK.effects.flashObject(self, 0xFF0000, 1000); LK.effects.flashScreen(0xFF0000, 500); // Visual effect for rage activation tween(leaderGraphics, { scaleX: 2.5, scaleY: 2.5 }, { duration: 500, easing: tween.easeOut }); tween(leaderGraphics, { scaleX: 1.5, scaleY: 1.5 }, { duration: 500, easing: tween.easeIn }); } if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); // Move towards Bart if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } // Call for help ability - faster in rage mode var helpInterval = self.rageMode ? 270 : 600; // 4.5 seconds in rage, 10 seconds normal if (self.callForHelpTimer <= 0) { // Summon 3 random enemies for (var i = 0; i < 3; i++) { var enemyType = Math.random(); var enemy; if (enemyType < 0.33) { enemy = new Mutant(); } else if (enemyType < 0.66) { enemy = new FastMutant(); } else { enemy = new ShooterMutant(); } // Spawn on opposite side of screen from Bart enemy.x = bart.x < 1024 ? 1800 : 200; enemy.y = Math.random() * 1800 + 400; enemy.invincible = false; enemy.invincibilityTimer = 0; enemies.push(enemy); game.addChild(enemy); } self.callForHelpTimer = helpInterval; LK.effects.flashObject(self, 0x00FF00, 500); // Play call help sound LK.getSound('Callhelp').play(); } // Gun attack ability if (self.gunAttackTimer <= 0) { var bullet = new LeaderBullet(); bullet.x = self.x; bullet.y = self.y; bullet.targetX = bart.x; bullet.targetY = bart.y; bullet.damage = 90; // Insane damage but not instant kill bullet.speed = 12; enemyProjectiles.push(bullet); game.addChild(bullet); self.gunAttackTimer = 300; LK.effects.flashObject(self, 0xFF0000, 300); } // Whistle ability - reduce Bart's attack speed if (self.whistleTimer <= 0) { bart.originalFireRate = bart.fireRate; bart.fireRate = bart.fireRate * 2; // Double fire rate delay (slower) bart.attackSpeedDebuffTimer = 285; // 4.75 seconds self.whistleTimer = 1200; LK.effects.flashScreen(0x0000FF, 500); LK.effects.flashObject(self, 0x0000FF, 1000); // Change Bart to debuffed visual bart.updateWeaponVisual('debuffed'); // Play whistle sound LK.getSound('Whistleblow').play(); // Visual effect on Bart tween(leaderGraphics, { scaleX: 2, scaleY: 2 }, { duration: 300, easing: tween.easeOut }); tween(leaderGraphics, { scaleX: 1.5, scaleY: 1.5 }, { duration: 300, easing: tween.easeIn }); } } }; return self; }); var Peanut = Container.expand(function () { var self = Container.call(this); var peanutGraphics = self.attachAsset('peanut', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 15; self.speed = 12; self.target = null; self.lifetime = 60; self.hasSplit = false; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } if (self.target && !self.target.destroyed) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } else { self.y -= self.speed; } self.rotation += 0.1; }; return self; }); var PoetMutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('poet_mutant', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 80; self.health = self.maxHealth; self.speed = 1; self.xpValue = 40; self.coinChance = 0.6; self.powerupChance = 0.25; self.summonTimer = 0; self.summonInterval = 180; // 3 seconds self.invincible = true; self.invincibilityTimer = 180; // 3 seconds at 60fps self.takeDamage = function (damage) { if (self.invincible) return; // No damage during invincibility self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; // Flashing effect if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; // Reset to full opacity } } self.summonTimer--; if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } // Summon mutants when close to player if (self.summonTimer <= 0 && dist < 800) { // Summon a basic mutant var summonedMutant = new Mutant(); summonedMutant.x = self.x + (Math.random() - 0.5) * 200; summonedMutant.y = self.y + (Math.random() - 0.5) * 200; summonedMutant.maxHealth = 20 + wave * 8; summonedMutant.health = summonedMutant.maxHealth; summonedMutant.speed = 2 + wave * 0.2; enemies.push(summonedMutant); game.addChild(summonedMutant); self.summonTimer = self.summonInterval; LK.effects.flashObject(self, 0xFF00FF, 300); } } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.type = Math.random() < 0.5 ? 'damage' : 'firerate'; self.lifetime = 300; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; } self.rotation += 0.03; self.y += Math.sin(LK.ticks * 0.05) * 0.5; }; return self; }); var RockerMutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('rocker_mutant', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 70; self.health = self.maxHealth; self.speed = 2.5; self.xpValue = 40; self.coinChance = 0.5; self.powerupChance = 0.2; self.boostTimer = 0; self.boostInterval = 300; // 5 seconds self.invincible = true; self.invincibilityTimer = 180; self.takeDamage = function (damage) { if (self.invincible) return; self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; } } self.boostTimer--; // Check if Drummer is on screen for enhanced boost var drummerOnScreen = false; for (var i = 0; i < enemies.length; i++) { if (enemies[i] instanceof DrummerMutant && enemies[i] !== self) { drummerOnScreen = true; break; } } // Apply speed boost to all allies if (self.boostTimer <= 0) { var boostAmount = drummerOnScreen ? 1.5 : 1; // Extra boost if drummer present for (var i = 0; i < enemies.length; i++) { if (enemies[i] !== self && !enemies[i].speedBoosted) { enemies[i].originalSpeed = enemies[i].speed; enemies[i].speed += boostAmount; enemies[i].speedBoosted = true; enemies[i].speedBoostTimer = 300; // 5 seconds // Visual effect for boosted enemies LK.effects.flashObject(enemies[i], 0x00FF00, 500); } } self.boostTimer = self.boostInterval; // Visual effect when boosting LK.effects.flashObject(self, 0x00FF00, 1000); mutantGraphics.tint = 0x00FF00; tween(mutantGraphics, { tint: 0xFFFFFF }, { duration: 500, easing: tween.easeOut }); } if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } }; return self; }); var SamuraiMutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('samurai_mutant', { anchorX: 0.5, anchorY: 0.5 }); // Create katana - much bigger self.katana = self.attachAsset('katana', { anchorX: 0.5, anchorY: 0.5, x: 300, y: 0, scaleX: 2.5, scaleY: 2.5 }); self.maxHealth = 100; self.health = self.maxHealth; self.speed = 1.2; self.xpValue = 50; self.coinChance = 0.7; self.powerupChance = 0.3; self.invincible = true; self.invincibilityTimer = 180; // 3 seconds at 60fps self.katanaAngle = 0; self.katanaRadius = 300; // Much farther from mutant self.reflectRadius = 350; // Increased to match farther katana self.takeDamage = function (damage) { if (self.invincible) return; // No damage during invincibility self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; // Flashing effect if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; // Reset to full opacity } } // Rotate katana around the mutant - much faster self.katanaAngle += 0.3; // Much faster rotation speed self.katana.x = Math.cos(self.katanaAngle) * self.katanaRadius; self.katana.y = Math.sin(self.katanaAngle) * self.katanaRadius; self.katana.rotation = self.katanaAngle + Math.PI / 2; // Orient katana tangentially // Move towards Bart if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } }; return self; }); var SantaHelper = Container.expand(function () { var self = Container.call(this); var helperGraphics = self.attachAsset('santa_helper', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 12; self.damage = 15; self.target = null; self.attackCooldown = 0; self.findTarget = function () { var closestEnemy = null; var closestDist = Infinity; for (var i = 0; i < enemies.length; i++) { var dx = enemies[i].x - self.x; var dy = enemies[i].y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < closestDist && dist < 800) { closestDist = dist; closestEnemy = enemies[i]; } } return closestEnemy; }; self.update = function () { self.attackCooldown--; // Find new target if current target is destroyed if (!self.target || self.target.shouldDestroy || self.target.destroyed) { self.target = self.findTarget(); } if (self.target) { // Move towards target aggressively var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } // Attack if close enough if (dist < 60 && self.attackCooldown <= 0) { self.target.takeDamage(self.damage); self.attackCooldown = 20; // Attack every 0.33 seconds LK.effects.flashObject(self, 0xFF0000, 200); // Bite animation effect tween(helperGraphics, { scaleX: 1.3, scaleY: 1.3 }, { duration: 100, easing: tween.easeOut }); tween(helperGraphics, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeIn }); } } else { // Follow Bart if no enemies if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 80) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } } }; return self; }); var ShooterMutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('shooter_mutant', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 50; self.health = self.maxHealth; self.speed = 1.5; self.xpValue = 25; self.coinChance = 0.4; self.powerupChance = 0.15; self.shootTimer = 0; self.shootInterval = 120; self.invincible = true; self.invincibilityTimer = 180; // 3 seconds at 60fps self.takeDamage = function (damage) { if (self.invincible) return; // No damage during invincibility self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; // Flashing effect if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; // Reset to full opacity } } self.shootTimer--; if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } if (self.shootTimer <= 0 && dist < 2567) { var bowlingBall = new BowlingBall(); bowlingBall.x = self.x; bowlingBall.y = self.y; bowlingBall.targetX = bart.x; bowlingBall.targetY = bart.y; enemyProjectiles.push(bowlingBall); game.addChild(bowlingBall); self.shootTimer = self.shootInterval; } } }; return self; }); var SmallNut = Container.expand(function () { var self = Container.call(this); var nutGraphics = self.attachAsset('small_nut', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 5; self.speed = 10; self.velocityX = 0; self.velocityY = 0; self.lifetime = 40; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } self.x += self.velocityX; self.y += self.velocityY; self.rotation += 0.2; }; return self; }); var SnowballCat = Container.expand(function () { var self = Container.call(this); var catGraphics = self.attachAsset('snowball_cat', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.distractionRadius = 600; self.runDirection = 1; self.runTimer = 0; self.invincibilityReduction = 0.5; // Reduces invincibility time by 50% self.velocityX = (Math.random() - 0.5) * self.speed * 2; // Random X velocity self.velocityY = (Math.random() - 0.5) * self.speed * 2; // Random Y velocity self.directionChangeTimer = 0; self.update = function () { // Change direction randomly every 1-3 seconds self.directionChangeTimer++; if (self.directionChangeTimer > 60 + Math.random() * 120) { self.velocityX = (Math.random() - 0.5) * self.speed * 2; self.velocityY = (Math.random() - 0.5) * self.speed * 2; self.directionChangeTimer = 0; } // Move in current direction self.x += self.velocityX; self.y += self.velocityY; // Bounce off edges with some randomness if (self.x < 50) { self.x = 50; self.velocityX = Math.abs(self.velocityX) * (0.8 + Math.random() * 0.4); self.velocityY = (Math.random() - 0.5) * self.speed; } else if (self.x > 1998) { self.x = 1998; self.velocityX = -Math.abs(self.velocityX) * (0.8 + Math.random() * 0.4); self.velocityY = (Math.random() - 0.5) * self.speed; } if (self.y < 50) { self.y = 50; self.velocityY = Math.abs(self.velocityY) * (0.8 + Math.random() * 0.4); self.velocityX = (Math.random() - 0.5) * self.speed; } else if (self.y > 2682) { self.y = 2682; self.velocityY = -Math.abs(self.velocityY) * (0.8 + Math.random() * 0.4); self.velocityX = (Math.random() - 0.5) * self.speed; } // Check for nearby enemies to distract for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = self.x - enemy.x; var dy = self.y - enemy.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.distractionRadius) { // Make enemy follow the cat instead of Bart enemy.distractedBy = self; // Reduce invincibility time if enemy is invincible if (enemy.invincible && enemy.invincibilityTimer > 0) { enemy.invincibilityTimer = Math.floor(enemy.invincibilityTimer * self.invincibilityReduction); } } } // Animated running effect with rotation based on movement direction var catGraphics = self.children[0]; catGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.3) * 0.1; catGraphics.rotation = Math.atan2(self.velocityY, self.velocityX) * 0.2; // Face movement direction }; return self; }); var SoundWave = Container.expand(function () { var self = Container.call(this); var waveGraphics = self.attachAsset('sound_wave', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.damage = 12; self.targetX = 0; self.targetY = 0; self.directionSet = false; self.velocityX = 0; self.velocityY = 0; self.lifetime = 120; self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } if (!self.directionSet) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.velocityX = dx / dist * self.speed; self.velocityY = dy / dist * self.speed; } self.directionSet = true; // Start growing the sound wave over time tween(waveGraphics, { scaleX: 3, scaleY: 3 }, { duration: self.lifetime * 16.67, // Convert frames to milliseconds easing: tween.easeOut }); // Increase speed over time tween(self, { speed: self.speed * 2.5 }, { duration: self.lifetime * 16.67, easing: tween.easeOut }); } // Update velocity with new speed if (self.directionSet) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.velocityX = dx / dist * self.speed; self.velocityY = dy / dist * self.speed; } } self.x += self.velocityX; self.y += self.velocityY; // Pulsing effect waveGraphics.alpha = 0.6 + Math.sin(LK.ticks * 0.2) * 0.4; }; return self; }); var Spray = Container.expand(function () { var self = Container.call(this); var sprayGraphics = self.attachAsset('spray', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 8; self.speed = 15; self.target = null; self.lifetime = 45; self.stunDuration = 72; // 1.2 seconds at 60fps self.update = function () { self.lifetime--; if (self.lifetime <= 0) { self.shouldDestroy = true; return; } if (self.target && !self.target.destroyed) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; self.rotation = Math.atan2(dy, dx); } } else { self.y -= self.speed; } sprayGraphics.alpha = 0.7 + Math.sin(LK.ticks * 0.3) * 0.3; }; return self; }); var VocalMutant = Container.expand(function () { var self = Container.call(this); var mutantGraphics = self.attachAsset('vocal_mutant', { anchorX: 0.5, anchorY: 0.5 }); self.maxHealth = 40; self.health = self.maxHealth; self.speed = 5; self.xpValue = 35; self.coinChance = 0.4; self.powerupChance = 0.15; self.baseDamage = 15; // Base damage when swearing at Bart self.invincible = true; self.invincibilityTimer = 180; self.takeDamage = function (damage) { if (self.invincible) return; self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.shouldDestroy = true; LK.getSound('hit').play(); } }; self.getDamage = function () { // Check if Rocker is on screen to double damage var rockerOnScreen = false; for (var i = 0; i < enemies.length; i++) { if (enemies[i] instanceof RockerMutant && enemies[i] !== self) { rockerOnScreen = true; break; } } return rockerOnScreen ? self.baseDamage * 2 : self.baseDamage; }; self.update = function () { if (self.invincible) { self.invincibilityTimer--; mutantGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.3) * 0.3; if (self.invincibilityTimer <= 0) { self.invincible = false; mutantGraphics.alpha = 1; } } if (bart) { var dx = bart.x - self.x; var dy = bart.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000080 }); /**** * Game Code ****/ var bart; var enemies = []; var bullets = []; var items = []; var enemyProjectiles = []; var alienMeals = []; var wave = 1; var enemiesKilled = 0; var spawnTimer = 0; var dragTarget = null; var gameStarted = false; var titleScreen; var startButton; var titleText; var shopScreen; var shopButton; var selectedWeapon = 'slingshot'; var unlockedWeapons = ['slingshot']; var weaponPrices = { dartgun: 100, scattershot: 250, ducky: 500, spraycan: 750, flower: 1000 }; var isGiantMutantRush = false; var giantMutantRushButton; var mutantLeaderSpawned = false; var weaponStats = { slingshot: { damage: 10, fireRate: 30, projectileCount: 1 }, dartgun: { damage: 50, fireRate: 60, projectileCount: 1 }, scattershot: { damage: 15, fireRate: 40, projectileCount: 1 }, ducky: { damage: 25, fireRate: 45, projectileCount: 3 }, spraycan: { damage: 8, fireRate: 50, projectileCount: 1 }, flower: { damage: 3, fireRate: 6, projectileCount: 1 } }; var selectedSubweapon = null; var unlockedSubweapons = []; var subweaponPrices = { santa_helper: 750, krusty_shop: 1200, snowball_cat: 900 }; var activeSubweapon = null; var encyclopediaScreen; // Create title screen titleScreen = new Container(); game.addChild(titleScreen); // Title text titleText = new Text2('BART vs MUTANTS', { size: 120, fill: 0xFFFF00 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 800; titleScreen.addChild(titleText); // Start button background startButton = titleScreen.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1400, scaleX: 2, scaleY: 3 }); // Start button text var startText = new Text2('START', { size: 80, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); startText.x = 1024; startText.y = 1400; titleScreen.addChild(startText); // Instructions text var instructionsText = new Text2('Drag to move • Auto-shoot enemies', { size: 50, fill: 0xAAAAAA }); instructionsText.anchor.set(0.5, 0.5); instructionsText.x = 1024; instructionsText.y = 1600; titleScreen.addChild(instructionsText); // Title screen coins display var titleCoinsText = new Text2('Coins: 0', { size: 60, fill: 0xFFD700 }); titleCoinsText.anchor.set(1, 0); titleCoinsText.x = 1948; titleCoinsText.y = 100; titleScreen.addChild(titleCoinsText); // Shop button background shopButton = titleScreen.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1800, scaleX: 2, scaleY: 2 }); // Shop button text var shopButtonText = new Text2('KRUSTY BURGER', { size: 60, fill: 0xFFFF00 }); shopButtonText.anchor.set(0.5, 0.5); shopButtonText.x = 1024; shopButtonText.y = 1800; titleScreen.addChild(shopButtonText); // Encyclopedia button background var encyclopediaButton = titleScreen.attachAsset('info_button', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2100, scaleX: 2, scaleY: 2 }); // Encyclopedia button text var encyclopediaButtonText = new Text2('ENCYCLOPEDIA', { size: 60, fill: 0x00FFFF }); encyclopediaButtonText.anchor.set(0.5, 0.5); encyclopediaButtonText.x = 1024; encyclopediaButtonText.y = 2100; titleScreen.addChild(encyclopediaButtonText); // Giant Mutant Rush button background giantMutantRushButton = titleScreen.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2400, scaleX: 2.5, scaleY: 2 }); giantMutantRushButton.tint = 0xFF0000; // Giant Mutant Rush button text var giantRushText = new Text2('GIANT MUTANT RUSH!', { size: 50, fill: 0xFFFF00 }); giantRushText.anchor.set(0.5, 0.5); giantRushText.x = 1024; giantRushText.y = 2400; titleScreen.addChild(giantRushText); // GUI elements (hidden initially) var levelText = new Text2('Level 1', { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0, 0); levelText.x = 150; levelText.visible = false; LK.gui.topLeft.addChild(levelText); var xpBarBg = LK.gui.top.attachAsset('xpbar_bg', { anchorX: 0.5, anchorY: 0, y: 10 }); xpBarBg.visible = false; var xpBarFill = LK.gui.top.attachAsset('xpbar_fill', { anchorX: 0, anchorY: 0, x: -150, y: 10, scaleX: 0 }); xpBarFill.visible = false; var coinText = new Text2('Coins: 0', { size: 50, fill: 0xFFD700 }); coinText.anchor.set(1, 0); coinText.visible = false; LK.gui.topRight.addChild(coinText); var healthBarBg = LK.gui.topLeft.attachAsset('healthbar_bg', { anchorX: 0, anchorY: 0, x: 120, y: 80 }); healthBarBg.visible = false; var healthBarFill = LK.gui.topLeft.attachAsset('healthbar_fill', { anchorX: 0, anchorY: 0, x: 120, y: 80, scaleX: 1 }); healthBarFill.visible = false; var waveText = new Text2('Wave 1', { size: 80, fill: 0xFFFFFF }); waveText.anchor.set(0.5, 0.5); waveText.visible = false; LK.gui.center.addChild(waveText); var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 1); scoreText.visible = false; LK.gui.bottom.addChild(scoreText); // Load saved data var savedCoins = 0; var savedWeapons = null; var savedSelected = null; var savedSubweapons = null; var savedSelectedSubweapon = null; try { savedCoins = storage.coins || 0; savedWeapons = storage.unlockedWeapons; savedSelected = storage.selectedWeapon; savedSubweapons = storage.unlockedSubweapons; savedSelectedSubweapon = storage.selectedSubweapon; } catch (e) { console.log('Storage not available:', e); } if (savedWeapons) { unlockedWeapons = savedWeapons; } if (savedSelected) { selectedWeapon = savedSelected; } if (savedSubweapons) { unlockedSubweapons = savedSubweapons; } if (savedSelectedSubweapon) { selectedSubweapon = savedSelectedSubweapon; } bart = game.addChild(new Bart()); bart.x = 1024; bart.y = 2000; bart.visible = false; bart.coins = savedCoins; // Set initial weapon visual bart.updateWeaponVisual(selectedWeapon); // Update coin display immediately coinText.setText('Coins: ' + bart.coins); // Update title screen coins display titleCoinsText.setText('Coins: ' + bart.coins); // Create shop screen shopScreen = new Container(); shopScreen.visible = false; game.addChild(shopScreen); // Create encyclopedia screen encyclopediaScreen = new Encyclopedia(); encyclopediaScreen.x = 1024; encyclopediaScreen.y = 1366; encyclopediaScreen.visible = false; game.addChild(encyclopediaScreen); // Shop tab system variables var currentTab = 'weapons'; // Shop title var shopTitle = new Text2('KRUSTY BURGER', { size: 100, fill: 0xFFFF00 }); shopTitle.anchor.set(0.5, 0.5); shopTitle.x = 1024; shopTitle.y = 150; shopScreen.addChild(shopTitle); // Weapons tab button var weaponsTabButton = shopScreen.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, x: 750, y: 250, scaleX: 2, scaleY: 1.5 }); weaponsTabButton.tint = 0x00FF00; // Active tab color var weaponsTabText = new Text2('WEAPONS', { size: 50, fill: 0xFFFFFF }); weaponsTabText.anchor.set(0.5, 0.5); weaponsTabText.x = 750; weaponsTabText.y = 250; shopScreen.addChild(weaponsTabText); // Subweapons tab button var subweaponsTabButton = shopScreen.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, x: 1298, y: 250, scaleX: 2, scaleY: 1.5 }); var subweaponsTabText = new Text2('SUBWEAPONS', { size: 50, fill: 0xFFFFFF }); subweaponsTabText.anchor.set(0.5, 0.5); subweaponsTabText.x = 1298; subweaponsTabText.y = 250; shopScreen.addChild(subweaponsTabText); // Back button var backButton = shopScreen.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 200, scaleX: 1.5, scaleY: 1.5 }); var backText = new Text2('BACK', { size: 50, fill: 0xFFFFFF }); backText.anchor.set(0.5, 0.5); backText.x = 200; backText.y = 200; shopScreen.addChild(backText); // Coins display in shop var shopCoinsText = new Text2('Coins: 0', { size: 60, fill: 0xFFD700 }); shopCoinsText.anchor.set(1, 0.5); shopCoinsText.x = 1848; shopCoinsText.y = 200; shopScreen.addChild(shopCoinsText); // Containers for different tab content var weaponsContainer = new Container(); var subweaponsContainer = new Container(); shopScreen.addChild(weaponsContainer); shopScreen.addChild(subweaponsContainer); subweaponsContainer.visible = false; // Start with weapons tab active // Weapon buttons var weaponData = [{ id: 'slingshot', name: 'Slingshot', desc: 'The Default Weapon', y: 400 }, { id: 'dartgun', name: 'Dart Gun', desc: 'High damage, slow fire rate', y: 550 }, { id: 'scattershot', name: 'Scattershot', desc: 'Shoots peanuts that split into 3', y: 700 }, { id: 'ducky', name: 'Ducky Triple', desc: 'Shoots 3 projectiles', y: 850 }, { id: 'spraycan', name: 'Spraycan', desc: 'Medium damage, stuns for 1.2s', y: 1000 }, { id: 'flower', name: "Krusty's Flower", desc: 'Water beam, rapid fire', y: 1150 }]; // Subweapon buttons var subweaponData = [{ id: 'santa_helper', name: "Santa's Little Helper", desc: 'Fast ally that bites enemies', y: 400 }, { id: 'krusty_shop', name: 'Krusty Burger Shop', desc: 'Spawns powerups every 15 seconds', y: 550 }, { id: 'snowball_cat', name: 'Snowball II', desc: 'Distracts enemies & reduces invincibility', y: 700 }]; subweaponData.forEach(function (subweapon) { // Subweapon button background var subweaponBg = subweaponsContainer.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: subweapon.y, scaleX: 4, scaleY: 1.2 }); subweaponBg.subweaponId = subweapon.id; // Subweapon name var subweaponName = new Text2(subweapon.name, { size: 50, fill: 0x00FFFF }); subweaponName.anchor.set(0.5, 0.5); subweaponName.x = 800; subweaponName.y = subweapon.y - 15; subweaponsContainer.addChild(subweaponName); // Subweapon description var subweaponDesc = new Text2(subweapon.desc, { size: 35, fill: 0xAAAAAA }); subweaponDesc.anchor.set(0.5, 0.5); subweaponDesc.x = 800; subweaponDesc.y = subweapon.y + 15; subweaponsContainer.addChild(subweaponDesc); // Price/status text var priceText = new Text2('Cost: ' + subweaponPrices[subweapon.id], { size: 45, fill: 0xFFD700 }); priceText.anchor.set(0.5, 0.5); priceText.x = 1400; priceText.y = subweapon.y; priceText.subweaponId = subweapon.id; subweaponsContainer.addChild(priceText); }); weaponData.forEach(function (weapon) { // Weapon button background var weaponBg = weaponsContainer.attachAsset('healthbar_bg', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: weapon.y, scaleX: 4, scaleY: 1.5 }); weaponBg.weaponId = weapon.id; // Weapon name var weaponName = new Text2(weapon.name, { size: 60, fill: 0xFFFFFF }); weaponName.anchor.set(0.5, 0.5); weaponName.x = 800; weaponName.y = weapon.y - 20; weaponsContainer.addChild(weaponName); // Weapon description var weaponDesc = new Text2(weapon.desc, { size: 40, fill: 0xAAAAAA }); weaponDesc.anchor.set(0.5, 0.5); weaponDesc.x = 800; weaponDesc.y = weapon.y + 20; weaponsContainer.addChild(weaponDesc); // Price/status text var priceText = new Text2(weapon.id === 'slingshot' ? 'OWNED' : 'Cost: ' + weaponPrices[weapon.id], { size: 50, fill: weapon.id === 'slingshot' ? 0x00FF00 : 0xFFD700 }); priceText.anchor.set(0.5, 0.5); priceText.x = 1400; priceText.y = weapon.y; priceText.weaponId = weapon.id; weaponsContainer.addChild(priceText); }); function switchShopTab(tabName) { currentTab = tabName; if (tabName === 'weapons') { weaponsContainer.visible = true; subweaponsContainer.visible = false; weaponsTabButton.tint = 0x00FF00; // Active tab color subweaponsTabButton.tint = 0xFFFFFF; // Inactive tab color } else if (tabName === 'subweapons') { weaponsContainer.visible = false; subweaponsContainer.visible = true; weaponsTabButton.tint = 0xFFFFFF; // Inactive tab color subweaponsTabButton.tint = 0x00FF00; // Active tab color } } function updateShopDisplay() { // Update coins in shop var shopCoinsText = shopScreen.children.find(function (child) { return child instanceof Text2 && child.text && child.text.startsWith('Coins:'); }); if (shopCoinsText) { shopCoinsText.setText('Coins: ' + bart.coins); } // Update title screen coins display titleCoinsText.setText('Coins: ' + bart.coins); // Update weapon status texts weaponsContainer.children.forEach(function (child) { if (child instanceof Text2 && child.weaponId) { if (unlockedWeapons.indexOf(child.weaponId) !== -1) { var newText = selectedWeapon === child.weaponId ? 'EQUIPPED' : 'OWNED'; var newColor = selectedWeapon === child.weaponId ? 0x00FFFF : 0x00FF00; child.setText(newText); // Remove old text and create new one with correct color var parent = child.parent; var x = child.x; var y = child.y; var weaponId = child.weaponId; parent.removeChild(child); var newTextObj = new Text2(newText, { size: 50, fill: newColor }); newTextObj.anchor.set(0.5, 0.5); newTextObj.x = x; newTextObj.y = y; newTextObj.weaponId = weaponId; parent.addChild(newTextObj); } } }); // Update subweapon status texts subweaponsContainer.children.forEach(function (child) { if (child instanceof Text2 && child.subweaponId) { if (unlockedSubweapons.indexOf(child.subweaponId) !== -1) { var newText = selectedSubweapon === child.subweaponId ? 'EQUIPPED' : 'OWNED'; var newColor = selectedSubweapon === child.subweaponId ? 0x00FFFF : 0x00FF00; child.setText(newText); // Remove old text and create new one with correct color var parent = child.parent; var x = child.x; var y = child.y; var subweaponId = child.subweaponId; parent.removeChild(child); var newTextObj = new Text2(newText, { size: 45, fill: newColor }); newTextObj.anchor.set(0.5, 0.5); newTextObj.x = x; newTextObj.y = y; newTextObj.subweaponId = subweaponId; parent.addChild(newTextObj); } } }); } function startGame() { gameStarted = true; // Hide title screen titleScreen.visible = false; // Show game elements bart.visible = true; levelText.visible = true; xpBarBg.visible = true; xpBarFill.visible = true; coinText.visible = true; waveText.visible = true; scoreText.visible = true; healthBarBg.visible = true; healthBarFill.visible = true; // Apply selected weapon stats var stats = weaponStats[selectedWeapon]; bart.damage = stats.damage; bart.fireRate = stats.fireRate; // Update Bart's visual appearance bart.updateWeaponVisual(selectedWeapon); // Giant Mutant Rush mode setup if (isGiantMutantRush) { // Set Bart to level 10 bart.level = 10; bart.xpToNext = 1000; bart.maxHealth = 100 + 9 * 20; // 9 level ups worth of health bart.health = bart.maxHealth; bart.damage = stats.damage + 9 * 5; // 9 level ups worth of damage bart.fireRate = Math.max(10, stats.fireRate - 9 * 2); // 9 level ups worth of fire rate // Update UI levelText.setText('Level ' + bart.level); healthBarFill.scaleX = 1; waveText.setText('GIANT MUTANT RUSH!'); waveText.tint = 0xFF0000; // Randomly choose between Mutant Leader and Concert var giantMutantType = Math.random(); if (giantMutantType < 0.5) { // Spawn the Mutant Leader var leader = new MutantLeader(); leader.x = 1024; leader.y = 400; enemies.push(leader); game.addChild(leader); mutantLeaderSpawned = true; } else { // Spawn the Concert var concert = new Concert(); concert.x = 1024; concert.y = 300; // At the top of the screen enemies.push(concert); game.addChild(concert); mutantLeaderSpawned = true; // Use same flag to prevent regular spawning } } // Spawn active subweapon if (selectedSubweapon) { if (selectedSubweapon === 'santa_helper') { activeSubweapon = new SantaHelper(); activeSubweapon.x = bart.x + 80; activeSubweapon.y = bart.y + 50; game.addChild(activeSubweapon); } else if (selectedSubweapon === 'krusty_shop') { activeSubweapon = new KrustyShop(); activeSubweapon.x = bart.x + 150; activeSubweapon.y = bart.y - 100; game.addChild(activeSubweapon); } else if (selectedSubweapon === 'snowball_cat') { activeSubweapon = new SnowballCat(); activeSubweapon.x = bart.x - 150; activeSubweapon.y = bart.y; game.addChild(activeSubweapon); } } // Show initial wave text waveText.setText('Wave 1'); tween(waveText, { scaleX: 2, scaleY: 2 }, { duration: 500, easing: tween.elasticOut }); tween(waveText, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.elasticIn }); } function spawnEnemy() { var enemy; // Boss waves: 5, 10, 15, 20 if (wave % 5 === 0) { enemy = new Boss(); // Scale boss health and speed based on wave enemy.maxHealth = 500 + (wave - 5) * 200; enemy.health = enemy.maxHealth; enemy.speed = 1 + wave * 0.1; enemy.xpValue = 100 + wave * 20; } else { var mutantType = Math.random(); if (wave >= 8 && mutantType < 0.1) { enemy = new SamuraiMutant(); enemy.speed = 1.2 + wave * 0.2; enemy.maxHealth = 100 + wave * 15; enemy.health = enemy.maxHealth; enemy.xpValue = 50 + wave * 6; } else if (wave >= 13 && mutantType < 0.15) { enemy = new DrummerMutant(); enemy.speed = 0.8 + wave * 0.1; enemy.maxHealth = 150 + wave * 20; enemy.health = enemy.maxHealth; enemy.xpValue = 45 + wave * 5; } else if (wave >= 13 && mutantType < 0.25) { enemy = new VocalMutant(); enemy.speed = 5 + wave * 0.5; enemy.maxHealth = 40 + wave * 10; enemy.health = enemy.maxHealth; enemy.xpValue = 35 + wave * 4; } else if (wave >= 13 && mutantType < 0.35) { enemy = new RockerMutant(); enemy.speed = 2.5 + wave * 0.3; enemy.maxHealth = 70 + wave * 15; enemy.health = enemy.maxHealth; enemy.xpValue = 40 + wave * 5; } else if (wave >= 8 && mutantType < 0.45) { enemy = new PoetMutant(); enemy.speed = 1 + wave * 0.15; enemy.maxHealth = 80 + wave * 12; enemy.health = enemy.maxHealth; enemy.xpValue = 40 + wave * 5; } else if (wave >= 7 && mutantType < 0.55) { enemy = new ShooterMutant(); enemy.speed = 1.5 + wave * 0.2; enemy.maxHealth = 50 + wave * 10; enemy.health = enemy.maxHealth; enemy.xpValue = 25 + wave * 3; } else if (wave >= 6 && mutantType < 0.45) { enemy = new CookMutant(); enemy.speed = 1.5 + wave * 0.2; enemy.maxHealth = 60 + wave * 10; enemy.health = enemy.maxHealth; enemy.xpValue = 30 + wave * 4; } else if (wave >= 2 && mutantType < 0.65) { enemy = new FastMutant(); enemy.speed = 4 + wave * 0.4; enemy.maxHealth = 15 + wave * 8; enemy.health = enemy.maxHealth; enemy.xpValue = 15 + wave * 2; } else { enemy = new Mutant(); // Progressive scaling for mutants across all 20 waves enemy.speed = 2 + wave * 0.3; enemy.maxHealth = 30 + wave * 15; enemy.health = enemy.maxHealth; enemy.xpValue = 10 + wave * 2; } // Adjust invincibility based on wave if (wave >= 15) { // No invincibility at wave 15 onwards enemy.invincible = false; enemy.invincibilityTimer = 0; } else if (wave >= 10) { // Reduced invincibility (1.5 seconds) at wave 10 onwards enemy.invincibilityTimer = 90; // 1.5 seconds at 60fps } else { // Normal invincibility for waves 1-9 (3 seconds) enemy.invincibilityTimer = 180; // 3 seconds at 60fps } // Special mutant variants for higher waves if (wave >= 10) { enemy.speed += 1; enemy.maxHealth += 50; enemy.health = enemy.maxHealth; mutantGraphics = enemy.children[0]; if (mutantGraphics) { mutantGraphics.tint = 0xFF6666; // Red tint for stronger mutants } } if (wave >= 15) { enemy.speed += 1; enemy.maxHealth += 100; enemy.health = enemy.maxHealth; mutantGraphics = enemy.children[0]; if (mutantGraphics) { mutantGraphics.tint = 0xFF0000; // Dark red tint for elite mutants } } } enemy.x = Math.random() * 1848 + 100; enemy.y = -100; enemies.push(enemy); game.addChild(enemy); } function shootBullet() { if (bart.fireTimer > 0 || enemies.length === 0) return; var closestEnemy = null; var closestDist = Infinity; for (var i = 0; i < enemies.length; i++) { var dx = enemies[i].x - bart.x; var dy = enemies[i].y - bart.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < closestDist) { closestDist = dist; closestEnemy = enemies[i]; } } if (closestEnemy && closestDist < 800) { var stats = weaponStats[selectedWeapon]; if (selectedWeapon === 'flower') { // Continuous beam weapon var bullet = new FlowerBeam(); bullet.x = bart.x; bullet.y = bart.y; bullet.target = closestEnemy; bullet.damage = bart.damage; bullet.speed = 25; bullets.push(bullet); game.addChild(bullet); } else if (selectedWeapon === 'dartgun') { // Dart gun projectile var bullet = new Dart(); bullet.x = bart.x; bullet.y = bart.y; bullet.target = closestEnemy; bullet.damage = bart.damage; bullets.push(bullet); game.addChild(bullet); } else if (selectedWeapon === 'scattershot') { // Scattershot peanut var bullet = new Peanut(); bullet.x = bart.x; bullet.y = bart.y; bullet.target = closestEnemy; bullet.damage = bart.damage; bullets.push(bullet); game.addChild(bullet); } else if (selectedWeapon === 'spraycan') { // Spraycan projectile var bullet = new Spray(); bullet.x = bart.x; bullet.y = bart.y; bullet.target = closestEnemy; bullet.damage = bart.damage; bullets.push(bullet); game.addChild(bullet); } else if (selectedWeapon === 'ducky') { // Triple shot with spread for (var i = -1; i <= 1; i++) { var bullet = new Bullet(); bullet.x = bart.x + i * 30; bullet.y = bart.y; // Create spread by offsetting target position var spreadAngle = i * 0.3; // 0.3 radians spread per bullet var targetDx = closestEnemy.x - bart.x; var targetDy = closestEnemy.y - bart.y; var targetDist = Math.sqrt(targetDx * targetDx + targetDy * targetDy); // Apply spread to target direction var currentAngle = Math.atan2(targetDy, targetDx); var newAngle = currentAngle + spreadAngle; // Create a virtual target with spread var virtualTarget = { x: bart.x + Math.cos(newAngle) * targetDist, y: bart.y + Math.sin(newAngle) * targetDist }; bullet.target = virtualTarget; bullet.damage = bart.damage; bullets.push(bullet); game.addChild(bullet); } } else { // Single shot (slingshot) var bullet = new Bullet(); bullet.x = bart.x; bullet.y = bart.y; bullet.target = closestEnemy; bullet.damage = bart.damage; bullets.push(bullet); game.addChild(bullet); } bart.fireTimer = bart.fireRate; LK.getSound('shoot').play(); } } function spawnItem(x, y, type) { var item; if (type === 'coin') { item = new Coin(); } else { item = new PowerUp(); } item.x = x; item.y = y; items.push(item); game.addChild(item); } game.down = function (x, y, obj) { if (!gameStarted) { if (encyclopediaScreen.visible) { // Encyclopedia interactions var localX = x - encyclopediaScreen.x; var localY = y - encyclopediaScreen.y; if (localX > -75 && localX < 75 && localY > 325 && localY < 375) { // Close button encyclopediaScreen.visible = false; titleScreen.visible = true; } else if (localX > -275 && localX < -125 && localY > 255 && localY < 305) { // Previous button encyclopediaScreen.prevPage(); } else if (localX > 125 && localX < 275 && localY > 255 && localY < 305) { // Next button encyclopediaScreen.nextPage(); } } else if (shopScreen.visible) { // Shop interactions if (x > 100 && x < 300 && y > 100 && y < 300) { // Back button shopScreen.visible = false; titleScreen.visible = true; } // Tab buttons if (x > 650 && x < 850 && y > 200 && y < 300) { // Weapons tab switchShopTab('weapons'); } else if (x > 1198 && x < 1398 && y > 200 && y < 300) { // Subweapons tab switchShopTab('subweapons'); } // Subweapon buttons (only when subweapons tab is active) if (currentTab === 'subweapons') { var subweaponY = [400, 550, 700]; var subweaponIds = ['santa_helper', 'krusty_shop', 'snowball_cat']; for (var i = 0; i < subweaponY.length; i++) { if (x > 624 && x < 1424 && y > subweaponY[i] - 48 && y < subweaponY[i] + 48) { var subweaponId = subweaponIds[i]; if (unlockedSubweapons.indexOf(subweaponId) !== -1) { // Already owned - equip it selectedSubweapon = selectedSubweapon === subweaponId ? null : subweaponId; try { storage.selectedSubweapon = selectedSubweapon; } catch (e) { console.log('Could not save selected subweapon:', e); } updateShopDisplay(); } else if (bart.coins >= subweaponPrices[subweaponId]) { // Can afford - buy it bart.coins -= subweaponPrices[subweaponId]; unlockedSubweapons.push(subweaponId); selectedSubweapon = subweaponId; try { storage.coins = bart.coins; storage.unlockedSubweapons = unlockedSubweapons; storage.selectedSubweapon = selectedSubweapon; } catch (e) { console.log('Could not save subweapon purchase:', e); } updateShopDisplay(); } } } } // Weapon buttons (only when weapons tab is active) if (currentTab === 'weapons') { var weaponY = [400, 550, 700, 850, 1000, 1150]; var weaponIds = ['slingshot', 'dartgun', 'scattershot', 'ducky', 'spraycan', 'flower']; for (var i = 0; i < weaponY.length; i++) { if (x > 624 && x < 1424 && y > weaponY[i] - 60 && y < weaponY[i] + 60) { var weaponId = weaponIds[i]; if (unlockedWeapons.indexOf(weaponId) !== -1) { // Already owned - equip it selectedWeapon = weaponId; bart.updateWeaponVisual(selectedWeapon); try { storage.selectedWeapon = selectedWeapon; } catch (e) { console.log('Could not save selected weapon:', e); } updateShopDisplay(); } else if (bart.coins >= weaponPrices[weaponId]) { // Can afford - buy it bart.coins -= weaponPrices[weaponId]; unlockedWeapons.push(weaponId); selectedWeapon = weaponId; bart.updateWeaponVisual(selectedWeapon); try { storage.coins = bart.coins; storage.unlockedWeapons = unlockedWeapons; storage.selectedWeapon = selectedWeapon; } catch (e) { console.log('Could not save weapon purchase:', e); } updateShopDisplay(); } } } } } else { // Title screen if (x > 824 && x < 1224 && y > 1300 && y < 1500) { // Start button startGame(); } else if (x > 824 && x < 1224 && y > 1700 && y < 1900) { // Shop button titleScreen.visible = false; shopScreen.visible = true; updateShopDisplay(); } else if (x > 824 && x < 1224 && y > 2000 && y < 2200) { // Encyclopedia button titleScreen.visible = false; encyclopediaScreen.visible = true; } else if (x > 724 && x < 1324 && y > 2300 && y < 2500) { // Giant Mutant Rush button if (bart.coins >= 50) { bart.coins -= 50; try { storage.coins = bart.coins; } catch (e) { console.log('Could not save coins for Boss rush entry fee:', e); } coinText.setText('Coins: ' + bart.coins); titleCoinsText.setText('Coins: ' + bart.coins); isGiantMutantRush = true; startGame(); } else { // Flash button red to indicate insufficient funds LK.effects.flashObject(giantMutantRushButton, 0xFF0000, 500); } } } } else { dragTarget = bart; } }; game.up = function (x, y, obj) { dragTarget = null; }; game.move = function (x, y, obj) { if (dragTarget) { dragTarget.x = Math.max(60, Math.min(1988, x)); dragTarget.y = Math.max(80, Math.min(2652, y)); } }; game.update = function () { if (!gameStarted) { // Animate title on title screen titleText.y = 800 + Math.sin(LK.ticks * 0.05) * 20; return; } // Handle attack speed debuff if (bart.attackSpeedDebuffTimer && bart.attackSpeedDebuffTimer > 0) { bart.attackSpeedDebuffTimer--; if (bart.attackSpeedDebuffTimer <= 0) { bart.fireRate = bart.originalFireRate; // Restore Bart's normal weapon visual bart.updateWeaponVisual(selectedWeapon); } } shootBullet(); spawnTimer--; if (spawnTimer <= 0) { if (!isGiantMutantRush) { spawnEnemy(); // Dynamic spawn rate that gets faster but never too overwhelming var baseSpawnRate = 120 - wave * 4; if (wave >= 10) baseSpawnRate -= 20; // Faster spawning for waves 10+ if (wave >= 15) baseSpawnRate += 30; // Slower spawning for waves 15+ to reduce difficulty spawnTimer = Math.max(20, baseSpawnRate); } else { // Giant Mutant Rush mode - check if Concert is active var concertActive = false; for (var c = 0; c < enemies.length; c++) { if (enemies[c] instanceof Concert) { concertActive = true; break; } } if (concertActive) { // During Concert fight: spawn regular mutants continuously var mutant = new Mutant(); mutant.maxHealth = 30 + 10 * 5; // Wave 10 equivalent mutant.health = mutant.maxHealth; mutant.speed = 2 + 10 * 0.3; mutant.xpValue = 10 + 10 * 2; mutant.x = Math.random() * 1848 + 100; mutant.y = -100; mutant.invincible = false; // No invincibility during Concert mutant.invincibilityTimer = 0; enemies.push(mutant); game.addChild(mutant); spawnTimer = 90; // Spawn every 1.5 seconds } else { // Regular Giant Mutant Rush mode - no regular spawning spawnTimer = 60; } } } for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.shouldDestroy || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check for reflection by Samurai Mutant's katana var reflected = false; for (var s = 0; s < enemies.length; s++) { if (enemies[s] instanceof SamuraiMutant && !enemies[s].invincible) { var samurai = enemies[s]; var dx = bullet.x - samurai.x; var dy = bullet.y - samurai.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < samurai.reflectRadius) { // Reflect the bullet back towards Bart reflected = true; if (bart) { bullet.target = bart; // Reverse bullet direction var newDx = bart.x - bullet.x; var newDy = bart.y - bullet.y; var newDist = Math.sqrt(newDx * newDx + newDy * newDy); if (newDist > 0) { bullet.velocityX = newDx / newDist * bullet.speed; bullet.velocityY = newDy / newDist * bullet.speed; } } // Visual effect for reflection LK.effects.flashObject(samurai.katana, 0xFFFFFF, 200); LK.getSound('hit').play(); break; } } } if (reflected) continue; for (var j = enemies.length - 1; j >= 0; j--) { if (bullet.intersects(enemies[j])) { // Handle spray stun if (bullet instanceof Spray) { enemies[j].takeDamage(bullet.damage, bullet.stunDuration); } else { enemies[j].takeDamage(bullet.damage); } // Handle peanut splitting if (bullet instanceof Peanut && !bullet.hasSplit) { bullet.hasSplit = true; // Create 3 small nuts for (var k = 0; k < 3; k++) { var nut = new SmallNut(); nut.x = bullet.x; nut.y = bullet.y; // Spread nuts in different directions var angle = (k - 1) * 0.8; // -0.8, 0, 0.8 radians nut.velocityX = Math.sin(angle) * 8; nut.velocityY = Math.cos(angle) * -8; bullets.push(nut); game.addChild(nut); } } bullet.destroy(); bullets.splice(i, 1); break; } } // Check if reflected bullet hits Bart if (bullet.target === bart && bullet.intersects(bart)) { bart.takeDamage(bullet.damage); bullet.destroy(); bullets.splice(i, 1); break; } // Check collision with alien meals for (var j = alienMeals.length - 1; j >= 0; j--) { if (bullet.intersects(alienMeals[j])) { alienMeals[j].destroy(); alienMeals.splice(j, 1); bullet.destroy(); bullets.splice(i, 1); LK.effects.flashObject(bullet, 0xFF0000, 200); break; } } } var bartTookDamage = false; for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.intersects(bart)) { if (enemy instanceof MutantLeader) { // Instant kill for Mutant Leader bart.health = 0; bart.takeDamage(0); // Trigger game over } else { var damage = 10; if (enemy instanceof VocalMutant) { damage = enemy.getDamage(); } bart.takeDamage(damage); enemy.shouldDestroy = true; } bartTookDamage = true; } if (enemy.y > 2832) { enemy.destroy(); enemies.splice(i, 1); } } // Handle speed boost timers for (var i = 0; i < enemies.length; i++) { if (enemies[i].speedBoosted && enemies[i].speedBoostTimer) { enemies[i].speedBoostTimer--; if (enemies[i].speedBoostTimer <= 0) { enemies[i].speed = enemies[i].originalSpeed; enemies[i].speedBoosted = false; } } // Handle rock music boost timers if (enemies[i].rockBoosted && enemies[i].rockBoostTimer) { enemies[i].rockBoostTimer--; if (enemies[i].rockBoostTimer <= 0) { enemies[i].speed = enemies[i].originalRockSpeed; enemies[i].rockBoosted = false; } } } // Only process enemy destruction and XP gain if Bart didn't take damage this frame if (!bartTookDamage) { for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.shouldDestroy) { bart.gainXP(enemy.xpValue); LK.setScore(LK.getScore() + enemy.xpValue); scoreText.setText('Score: ' + LK.getScore()); enemiesKilled++; // Automatic 350 coins for Giant Mutants (MutantLeader and Concert) in Giant Mutant Rush mode if (isGiantMutantRush && (enemy instanceof MutantLeader || enemy instanceof Concert)) { bart.coins += 350; coinText.setText('Coins: ' + bart.coins); try { storage.coins = bart.coins; } catch (e) { console.log('Could not save coins for Giant Mutant:', e); } } if (Math.random() < enemy.coinChance) { if (enemy instanceof MutantLeader) { // Drop tons of coins for Mutant Leader for (var c = 0; c < 20; c++) { spawnItem(enemy.x + (Math.random() - 0.5) * 200, enemy.y + (Math.random() - 0.5) * 200, 'coin'); } } else { spawnItem(enemy.x, enemy.y, 'coin'); } } if (Math.random() < enemy.powerupChance) { spawnItem(enemy.x, enemy.y, 'powerup'); } // Check if this was the Mutant Leader or Concert in Giant Mutant Rush mode if (isGiantMutantRush && (enemy instanceof MutantLeader || enemy instanceof Concert)) { // Victory! try { storage.coins = bart.coins; } catch (e) { console.log('Could not save coins on victory:', e); } LK.showYouWin(); } enemy.destroy(); enemies.splice(i, 1); // Dynamic enemy count per wave - starts at 10, increases every 5 waves var enemiesNeeded = 10 + Math.floor((wave - 1) / 5) * 5; if (enemiesKilled >= enemiesNeeded) { wave++; enemiesKilled = 0; // Infinite waves - no win condition waveText.setText('Wave ' + wave); // Special celebration for milestone waves if (wave % 5 === 0) { LK.effects.flashScreen(0xFFD700, 1000); waveText.tint = 0xFFD700; } else { waveText.tint = 0xFFFFFF; } tween(waveText, { scaleX: 2, scaleY: 2 }, { duration: 500, easing: tween.elasticOut }); tween(waveText, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.elasticIn }); } continue; } } } else { // If Bart took damage, still clean up destroyed enemies but don't give XP for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.shouldDestroy) { enemy.destroy(); enemies.splice(i, 1); } } } for (var i = items.length - 1; i >= 0; i--) { var item = items[i]; if (item.shouldDestroy) { item.destroy(); items.splice(i, 1); continue; } if (item.intersects(bart)) { if (item instanceof Coin) { bart.coins += item.value; coinText.setText('Coins: ' + bart.coins); try { storage.coins = bart.coins; } catch (e) { console.log('Could not save coins:', e); } LK.getSound('pickup').play(); } else if (item instanceof PowerUp) { if (item.type === 'damage') { bart.damage += 5; } else { bart.fireRate = Math.max(5, bart.fireRate - 5); } LK.getSound('powerup_pickup').play(); } item.destroy(); items.splice(i, 1); } } for (var i = enemyProjectiles.length - 1; i >= 0; i--) { var projectile = enemyProjectiles[i]; if (projectile.shouldDestroy || projectile.y < -50 || projectile.y > 2832 || projectile.x < -50 || projectile.x > 2098) { projectile.destroy(); enemyProjectiles.splice(i, 1); continue; } if (projectile.intersects(bart)) { bart.takeDamage(projectile.damage); projectile.destroy(); enemyProjectiles.splice(i, 1); } } for (var i = alienMeals.length - 1; i >= 0; i--) { var meal = alienMeals[i]; if (meal.shouldDestroy) { meal.destroy(); alienMeals.splice(i, 1); } } levelText.setText('Level ' + bart.level); xpBarFill.scaleX = bart.xp / bart.xpToNext; }; LK.playMusic('battle');
===================================================================
--- original.js
+++ change.js
@@ -272,8 +272,164 @@
self.rotation += 0.05;
};
return self;
});
+var Concert = Container.expand(function () {
+ var self = Container.call(this);
+ var concertGraphics = self.attachAsset('concert', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.maxHealth = 25750;
+ self.health = self.maxHealth;
+ self.speed = 0; // Cannot move
+ self.xpValue = 2000;
+ self.coinChance = 1;
+ self.powerupChance = 1;
+ self.isInstantKillBoss = true;
+ // Damage multiplier from swearing
+ self.damageMultiplier = 1.0;
+ self.maxDamageMultiplier = 1.9; // Up to 90% more damage
+ // Timers for abilities
+ self.drummingTimer = 225; // 3.75 seconds
+ self.swearTimer = 600; // 10 seconds
+ self.rockMusicTimer = 300; // 5 seconds
+ // Performer sprites on top of concert
+ self.drummer = self.attachAsset('drummer', {
+ anchorX: 0.5,
+ anchorY: 1,
+ x: -200,
+ y: -150
+ });
+ self.vocal = self.attachAsset('vocal', {
+ anchorX: 0.5,
+ anchorY: 1,
+ x: 0,
+ y: -150
+ });
+ self.rocker = self.attachAsset('rocker', {
+ anchorX: 0.5,
+ anchorY: 1,
+ x: 200,
+ y: -150
+ });
+ // Health bar
+ var healthBarBg = self.attachAsset('healthbar_bg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -350,
+ scaleX: 2
+ });
+ self.healthBarFill = self.attachAsset('healthbar_fill', {
+ anchorX: 0,
+ anchorY: 0.5,
+ x: -200,
+ y: -350,
+ scaleX: 2
+ });
+ self.takeDamage = function (damage) {
+ // Apply damage multiplier from swearing
+ var actualDamage = damage * self.damageMultiplier;
+ self.health -= actualDamage;
+ LK.effects.flashObject(self, 0xFFFFFF, 200);
+ self.healthBarFill.scaleX = Math.max(0, self.health / self.maxHealth) * 2;
+ if (self.health <= 0) {
+ self.shouldDestroy = true;
+ LK.getSound('hit').play();
+ // Drop massive coins
+ for (var i = 0; i < 30; i++) {
+ spawnItem(self.x + (Math.random() - 0.5) * 400, self.y + (Math.random() - 0.5) * 300, 'coin');
+ }
+ }
+ };
+ self.update = function () {
+ // Update timers
+ self.drummingTimer--;
+ self.swearTimer--;
+ self.rockMusicTimer--;
+ if (bart) {
+ // Excessive Drumming: Drummer shoots 3 soundwaves in spread
+ if (self.drummingTimer <= 0) {
+ for (var i = -1; i <= 1; i++) {
+ var soundWave = new SoundWave();
+ soundWave.x = self.x - 200; // From drummer position
+ soundWave.y = self.y - 150;
+ // Create spread targeting
+ var spreadAngle = i * 0.4; // Spread angle
+ var dx = bart.x - soundWave.x;
+ var dy = bart.y - soundWave.y;
+ var baseAngle = Math.atan2(dy, dx);
+ var newAngle = baseAngle + spreadAngle;
+ var targetDist = Math.sqrt(dx * dx + dy * dy);
+ soundWave.targetX = soundWave.x + Math.cos(newAngle) * targetDist;
+ soundWave.targetY = soundWave.y + Math.sin(newAngle) * targetDist;
+ soundWave.damage = 18; // Slightly more than regular (12)
+ enemyProjectiles.push(soundWave);
+ game.addChild(soundWave);
+ }
+ self.drummingTimer = 225; // Reset timer
+ LK.effects.flashObject(self.drummer, 0xFF00FF, 300);
+ }
+ // Swear-fest: Increase damage permanently up to 90%
+ if (self.swearTimer <= 0) {
+ if (self.damageMultiplier < self.maxDamageMultiplier) {
+ self.damageMultiplier += 0.15; // 15% increase
+ self.damageMultiplier = Math.min(self.damageMultiplier, self.maxDamageMultiplier);
+ LK.effects.flashObject(self.vocal, 0xFF0000, 500);
+ LK.effects.flashScreen(0xFF0000, 300);
+ // Visual effect to show damage increase
+ tween(self.vocal, {
+ scaleX: 1.3,
+ scaleY: 1.3
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ tween(self.vocal, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 300,
+ easing: tween.easeIn
+ });
+ }
+ self.swearTimer = 600; // Reset timer
+ }
+ // Rock Music: Make all mutants faster
+ if (self.rockMusicTimer <= 0) {
+ for (var i = 0; i < enemies.length; i++) {
+ if (enemies[i] !== self && !enemies[i].rockBoosted) {
+ enemies[i].originalRockSpeed = enemies[i].speed;
+ enemies[i].speed *= 1.5; // 50% faster
+ enemies[i].rockBoosted = true;
+ enemies[i].rockBoostTimer = 300; // 5 seconds
+ LK.effects.flashObject(enemies[i], 0x00FFFF, 500);
+ }
+ }
+ self.rockMusicTimer = 300; // Reset timer
+ LK.effects.flashObject(self.rocker, 0x00FFFF, 500);
+ // Visual effect for rock music
+ tween(self.rocker, {
+ scaleX: 1.4,
+ scaleY: 1.4
+ }, {
+ duration: 250,
+ easing: tween.easeOut
+ });
+ tween(self.rocker, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 250,
+ easing: tween.easeIn
+ });
+ }
+ }
+ // Pulsing effect for the concert
+ concertGraphics.alpha = 0.9 + Math.sin(LK.ticks * 0.05) * 0.1;
+ };
+ return self;
+});
var CookMutant = Container.expand(function () {
var self = Container.call(this);
var mutantGraphics = self.attachAsset('cook_mutant', {
anchorX: 0.5,
@@ -2242,15 +2398,27 @@
levelText.setText('Level ' + bart.level);
healthBarFill.scaleX = 1;
waveText.setText('GIANT MUTANT RUSH!');
waveText.tint = 0xFF0000;
- // Spawn the Mutant Leader immediately
- var leader = new MutantLeader();
- leader.x = 1024;
- leader.y = 400;
- enemies.push(leader);
- game.addChild(leader);
- mutantLeaderSpawned = true;
+ // Randomly choose between Mutant Leader and Concert
+ var giantMutantType = Math.random();
+ if (giantMutantType < 0.5) {
+ // Spawn the Mutant Leader
+ var leader = new MutantLeader();
+ leader.x = 1024;
+ leader.y = 400;
+ enemies.push(leader);
+ game.addChild(leader);
+ mutantLeaderSpawned = true;
+ } else {
+ // Spawn the Concert
+ var concert = new Concert();
+ concert.x = 1024;
+ concert.y = 300; // At the top of the screen
+ enemies.push(concert);
+ game.addChild(concert);
+ mutantLeaderSpawned = true; // Use same flag to prevent regular spawning
+ }
}
// Spawn active subweapon
if (selectedSubweapon) {
if (selectedSubweapon === 'santa_helper') {
@@ -2665,10 +2833,34 @@
if (wave >= 10) baseSpawnRate -= 20; // Faster spawning for waves 10+
if (wave >= 15) baseSpawnRate += 30; // Slower spawning for waves 15+ to reduce difficulty
spawnTimer = Math.max(20, baseSpawnRate);
} else {
- // Giant Mutant Rush mode - no regular spawning
- spawnTimer = 60;
+ // Giant Mutant Rush mode - check if Concert is active
+ var concertActive = false;
+ for (var c = 0; c < enemies.length; c++) {
+ if (enemies[c] instanceof Concert) {
+ concertActive = true;
+ break;
+ }
+ }
+ if (concertActive) {
+ // During Concert fight: spawn regular mutants continuously
+ var mutant = new Mutant();
+ mutant.maxHealth = 30 + 10 * 5; // Wave 10 equivalent
+ mutant.health = mutant.maxHealth;
+ mutant.speed = 2 + 10 * 0.3;
+ mutant.xpValue = 10 + 10 * 2;
+ mutant.x = Math.random() * 1848 + 100;
+ mutant.y = -100;
+ mutant.invincible = false; // No invincibility during Concert
+ mutant.invincibilityTimer = 0;
+ enemies.push(mutant);
+ game.addChild(mutant);
+ spawnTimer = 90; // Spawn every 1.5 seconds
+ } else {
+ // Regular Giant Mutant Rush mode - no regular spawning
+ spawnTimer = 60;
+ }
}
}
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
@@ -2786,8 +2978,16 @@
enemies[i].speed = enemies[i].originalSpeed;
enemies[i].speedBoosted = false;
}
}
+ // Handle rock music boost timers
+ if (enemies[i].rockBoosted && enemies[i].rockBoostTimer) {
+ enemies[i].rockBoostTimer--;
+ if (enemies[i].rockBoostTimer <= 0) {
+ enemies[i].speed = enemies[i].originalRockSpeed;
+ enemies[i].rockBoosted = false;
+ }
+ }
}
// Only process enemy destruction and XP gain if Bart didn't take damage this frame
if (!bartTookDamage) {
for (var i = enemies.length - 1; i >= 0; i--) {
@@ -2796,10 +2996,10 @@
bart.gainXP(enemy.xpValue);
LK.setScore(LK.getScore() + enemy.xpValue);
scoreText.setText('Score: ' + LK.getScore());
enemiesKilled++;
- // Automatic 350 coins for Giant Mutants (MutantLeader) in Giant Mutant Rush mode
- if (isGiantMutantRush && enemy instanceof MutantLeader) {
+ // Automatic 350 coins for Giant Mutants (MutantLeader and Concert) in Giant Mutant Rush mode
+ if (isGiantMutantRush && (enemy instanceof MutantLeader || enemy instanceof Concert)) {
bart.coins += 350;
coinText.setText('Coins: ' + bart.coins);
try {
storage.coins = bart.coins;
@@ -2819,10 +3019,10 @@
}
if (Math.random() < enemy.powerupChance) {
spawnItem(enemy.x, enemy.y, 'powerup');
}
- // Check if this was the Mutant Leader in Giant Mutant Rush mode
- if (isGiantMutantRush && enemy instanceof MutantLeader) {
+ // Check if this was the Mutant Leader or Concert in Giant Mutant Rush mode
+ if (isGiantMutantRush && (enemy instanceof MutantLeader || enemy instanceof Concert)) {
// Victory!
try {
storage.coins = bart.coins;
} catch (e) {
Bart holding a slingshot. In-Game asset. 2d. High contrast. No shadows
Alien mutant from the Simpsons. In-Game asset. 2d. High contrast. No shadows
Make my character purple
Krusty Burger. In-Game asset. 2d. High contrast. No shadows
Remove Krusty burger
Make my character red
Make my character turquoise and make him hold a bowling ball
Bart holding a plasma gun. In-Game asset. 2d. High contrast. No shadows
Bart holding a shotgun with 2 duck heads instead of barrels and make sure that Bart's body is fully visible In-Game asset. 2d. High contrast. No shadows
Bart in a fighting pose with a flower's head in his shirt. In-Game asset. 2d. High contrast. No shadows
Plasma projectile. In-Game asset. 2d. High contrast. No shadows
Red bowling ball. In-Game asset. 2d. High contrast. No shadows
Santa's Little Helper the Simpsons In-Game asset. 2d. High contrast. No shadows
Make my character have White Classical hair and make him hold a poem
Make my character orange, have a chef's hat and make him hold some Alien Jelly
Alien food: Some green, oozing jelly and some purple shrimp with blue Human eyes all on a plate In-Game asset. 2d. High contrast. No shadows.
Bart holding a light brown slingshot shaped like a peanut. Make him be in a fighting stance In-Game asset. 2d. High contrast. No shadows
Bart holding a purple Spraycan while he is wearing purple shoes and shorts. Show all of his body in a fighting stance In-Game asset. 2d. High contrast. No shadows
Peanut. In-Game asset. 2d. High contrast. No shadows
Chestnut. In-Game asset. 2d. High contrast. No shadows
Add outlines
Make my character dark yellow and have a red samurai helmet
Katana. In-Game asset. 2d. High contrast. No shadows
Make my character have more tentacle based hands and make him have dark black hair with a ponytail (make my character's background white)
Make my character have cute white hair and make him hold a microphone
Make my character pink and make him have rock hair and a rock guitar
Make my character have a brown mustache, hold a gun and have a sergeant's hat
Bart is tired. In-Game asset. 2d. High contrast. No shadows
Bullet. In-Game asset. 2d. High contrast. No shadows
Topdown stageplay design no instruments or crowd, only the base. In-Game asset. 2d. High contrast. No shadows
Bart holding a toy bow and has a quiver full of toy arrows. In-Game asset. 2d. High contrast. No shadows
Bart holding a pot with a plant and is about to throw it. In-Game asset. 2d. High contrast. No shadows
Potted plant. In-Game asset. 2d. High contrast. No shadows
Pottery sherd. In-Game asset. 2d. High contrast. No shadows
Make my character inside an UFO armed with a laser cannon and make him drive it
Itchy's head. In-Game asset. 2d. High contrast. No shadows. Simpsons
Scratchy's head. In-Game asset. 2d. High contrast. No shadows. Simpsons
Itchy and scratchy show!. In-Game asset. 2d. High contrast. No shadows