User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.playerInventory = storageInventory;' Line Number: 663 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.playerInventory = storageInventory;' Line Number: 657 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.playerInventory = playerInventory;' Line Number: 643 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'down')' in or related to this line: 'petCloseBtn.down = function () {' Line Number: 3690
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'down')' in or related to this line: 'inventoryCloseBtn.down = function () {' Line Number: 3671
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'inventoryContainer.addChild(inventoryCloseBtn);' Line Number: 3678
User prompt
Implement an offline progress system: when the player returns, calculate gold, XP, and waves cleared while away. Use formulas like DPS * time * wave multiplier to simulate progress. Add a visual summary on return. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'down')' in or related to this line: 'inventoryCloseBtn.down = function () {' Line Number: 3488
User prompt
Please fix the bug: 'inventoryBtn is not defined' in or related to this line: 'inventoryBtn.down = function () {' Line Number: 3472
User prompt
Please fix the bug: 'inventoryBtn is not defined' in or related to this line: 'inventoryBtn.down = function () {' Line Number: 3472
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'down')' in or related to this line: 'inventoryBtn.down = function () {' Line Number: 3463
User prompt
Introduce a pet or companion system. Pets follow the player and offer passive bonuses or attacks. Examples: "Fire Spirit: shoots fireballs", "Fairy: heals player over time", "Goblin: collects gold automatically". Pets can level up or evolve. ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
Extend the equipment system. Each equipment drop has a type (e.g., Sword, Wand, Bow), a rarity (Common, Rare, Epic, Legendary), and possible bonus effects (e.g., +crit chance, +burn damage). Equipment should visually change the hero (e.g., glowing sword, icy staff). Add an equipment inventory menu with stats and upgrade options. ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Add three difficulty modes: Easy, Normal, Nightmare. In Nightmare mode, enemies have +50% health and damage, but drop +50% more gold and XP. Let players choose mode at the beginning, and display it in the UI. ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Add a biome system that changes the background and enemy types every 10 waves. Example biomes: Forest, Cave, Volcano, Ice. Each biome should have themed enemies and visual effects (e.g., fog in forest, lava cracks in volcano). Adjust music and environment accordingly. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Introduce unique boss enemies that spawn every 5 or 10 waves. Bosses have special mechanics like jumping, poisoning, summoning minions, or charging at the player. Make them visually distinct and drop better loot or exclusive relics. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add a prestige system: when the player reaches a certain wave, allow them to reset progress in exchange for permanent global buffs (e.g., "+5% gold income", "+10 mana capacity"). Keep track of the number of prestiges and make rewards scalable. ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Add a daily reward system that gives gold or bonuses for logging in. Also implement an achievement system with tasks like "Reach wave 10", "Kill 500 enemies", "Collect 100 equipment". Display progress visually and reward players with gold, items, or permanent buffs. ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
Introduce a relic system: permanent passive items that drop randomly from enemies or can be purchased in the shop. Each relic gives a unique bonus, e.g., "Vampire Tooth: heals 5% of damage dealt", "Clockwork: +10% attack speed", "Golden Feather: +20% gold pickup range". Stackable and collectible. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
skill tree daha anlaşılır az olsun. okunaklı olsun.
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'offense')' in or related to this line: 'var skill = skillTreeData[branch][skillKey];' Line Number: 850
User prompt
Add a skill tree system where the player can unlock passive abilities using earned points. Divide skills into branches: Offense (e.g., "+15% damage", "Critical Hit chance"), Defense (e.g., "+25 HP", "Auto Heal"), and Utility (e.g., "+20% gold gain", "+10% mana regen"). Make each upgrade tiered and visually represented in a tree-like menu. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
sağ üstte oyunu hızlandırma butonu olsun 1x 2x 3x olarak
User prompt
düşen manaları da toplasın karakter altınlar gibi
User prompt
ekranın sağ tarafına Aktif skiller ekleyelim. örneğin ekranki tüm düşmanlara yıldırım şoku veren bir skill. 30 saniyede bir aktif olabilsin. kendine koruma kalkanı yapsın 1 dakikada bir 10 saniyeliğine. Tüm düşmanları donduran skill olsun 30 saniyede bir aktif olabilsin. bunlar mana harcasın. mana barımız olsun. düşmanlardan mana potu düşsün. her öldürüdğümüz düşman 1 nama puanı versin. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.damage = 10; self.lifetime = 120; // frames self.update = function () { self.x += self.velocityX * gameSpeed; self.y += self.velocityY * gameSpeed; self.lifetime -= gameSpeed; // Check collision with enemies for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (self.intersects(enemy)) { var finalDamage = self.damage * (skillBonuses.damageMultiplier + skillBonuses.relicDamage); // Apply critical hit if (Math.random() < skillBonuses.critChance) { finalDamage *= 2; LK.effects.flashObject(enemy, 0xffff00, 200); } enemy.takeDamage(finalDamage); // Vampire healing from relics if (skillBonuses.vampireHealing > 0) { var healAmount = finalDamage * skillBonuses.vampireHealing; hero.health = Math.min(hero.maxHealth, hero.health + healAmount); } self.destroy(); var index = bullets.indexOf(self); if (index > -1) { bullets.splice(index, 1); } return; } } // Remove if lifetime expired or off screen if (self.lifetime <= 0 || self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) { self.destroy(); var index = bullets.indexOf(self); if (index > -1) { bullets.splice(index, 1); } } }; return self; }); var Enemy = Container.expand(function (type) { var self = Container.call(this); type = type || 'enemy1'; self.type = type; // Set different assets and colors based on type var assetName = 'enemy1'; var enemyColor = 0xff6b6b; if (type === 'enemy1') { assetName = 'enemy1'; enemyColor = 0xff6b6b; } else if (type === 'enemy2') { assetName = 'enemy2'; enemyColor = 0xff9f43; } else if (type === 'enemy3') { assetName = 'enemy3'; enemyColor = 0x8b5cf6; } else if (type === 'enemy4') { assetName = 'enemy4'; enemyColor = 0xf59e0b; } else if (type === 'enemy5') { assetName = 'enemy5'; enemyColor = 0x10b981; } else if (type === 'enemy6') { assetName = 'enemy1'; enemyColor = 0xef4444; } else if (type === 'enemy7') { assetName = 'enemy1'; enemyColor = 0x06b6d4; } var enemyGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); enemyGraphics.tint = enemyColor; // Set stats based on type if (type === 'enemy1') { // Basic enemy self.health = 10; self.maxHealth = 10; self.damage = 5; self.speed = 1; self.goldReward = 5; } else if (type === 'enemy2') { // Fast enemy self.health = 8; self.maxHealth = 8; self.damage = 4; self.speed = 2.5; self.goldReward = 8; } else if (type === 'enemy3') { // Tank enemy self.health = 40; self.maxHealth = 40; self.damage = 8; self.speed = 0.7; self.goldReward = 15; } else if (type === 'enemy4') { // Boss enemy self.health = 100; self.maxHealth = 100; self.damage = 15; self.speed = 1.2; self.goldReward = 50; enemyGraphics.scaleX = 1.5; enemyGraphics.scaleY = 1.5; } else if (type === 'enemy5') { // Archer enemy self.health = 15; self.maxHealth = 15; self.damage = 6; self.speed = 0.8; self.goldReward = 12; self.range = 300; self.shootTimer = 0; self.shootCooldown = 90; } else if (type === 'enemy6') { // Exploder enemy self.health = 8; self.maxHealth = 8; self.damage = 20; self.speed = 1.8; self.goldReward = 10; self.explodeRadius = 120; } else if (type === 'enemy7') { // Healer enemy self.health = 25; self.maxHealth = 25; self.damage = 2; self.speed = 0.9; self.goldReward = 18; self.healRange = 150; self.healAmount = 3; self.healCooldown = 120; self.healTimer = 0; } self.update = function () { // Handle frozen state if (self.frozenTimer > 0) { self.frozenTimer -= gameSpeed; if (self.frozenTimer <= 0) { self.speed = self.originalSpeed; tween(self, { tint: 0xffffff }, { duration: 200 }); } return; } // Move towards hero var dx = hero.x - self.x; var dy = hero.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Special behavior for archer enemies (enemy5) if (self.type === 'enemy5') { self.shootTimer -= gameSpeed; // Keep distance and shoot if (distance > self.range) { self.x += dx / distance * self.speed * gameSpeed; self.y += dy / distance * self.speed * gameSpeed; } // Shoot at hero when in range if (distance <= self.range && self.shootTimer <= 0) { var enemyBullet = new EnemyBullet(); enemyBullet.x = self.x; enemyBullet.y = self.y; enemyBullet.velocityX = dx / distance * 4; enemyBullet.velocityY = dy / distance * 4; enemyBullet.damage = self.damage; enemyBullets.push(enemyBullet); game.addChild(enemyBullet); self.shootTimer = self.shootCooldown; } } else if (self.type === 'enemy7') { // Healer behavior - heal nearby enemies self.healTimer -= gameSpeed; if (self.healTimer <= 0) { for (var i = 0; i < enemies.length; i++) { var ally = enemies[i]; if (ally !== self) { var healDx = ally.x - self.x; var healDy = ally.y - self.y; var healDistance = Math.sqrt(healDx * healDx + healDy * healDy); if (healDistance <= self.healRange && ally.health < ally.maxHealth) { ally.health = Math.min(ally.maxHealth, ally.health + self.healAmount); // Visual effect for healing LK.effects.flashObject(ally, 0x00ff00, 300); self.healTimer = self.healCooldown; break; } } } } // Move towards hero normally if (distance > 0) { self.x += dx / distance * self.speed * gameSpeed; self.y += dy / distance * self.speed * gameSpeed; } } else if (self.type === 'enemy6') { // Exploder behavior - explode when close to hero if (distance <= self.explodeRadius) { // Explode and damage hero hero.takeDamage(self.damage); // Visual explosion effect LK.effects.flashScreen(0xff4444, 500); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } return; } // Move towards hero faster if (distance > 0) { self.x += dx / distance * self.speed * gameSpeed; self.y += dy / distance * self.speed * gameSpeed; } } else { // Normal movement for other enemy types if (distance > 0) { self.x += dx / distance * self.speed * gameSpeed; self.y += dy / distance * self.speed * gameSpeed; } } // Check collision with hero (except for archer and exploder) if (distance < 50 && self.type !== 'enemy5' && self.type !== 'enemy6') { hero.takeDamage(self.damage); self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } } }; self.takeDamage = function (damage) { self.health -= damage; if (self.health <= 0) { self.die(); } }; self.die = function () { // Drop gold var gold = new Gold(); gold.x = self.x; gold.y = self.y; gold.value = self.goldReward; goldItems.push(gold); game.addChild(gold); // Drop health potion (10% chance) if (Math.random() < 0.1) { var healthPotion = new HealthPotion(); healthPotion.x = self.x; healthPotion.y = self.y; healthPotions.push(healthPotion); game.addChild(healthPotion); } // Drop mana potion (15% chance) if (Math.random() < 0.15) { var manaPotion = new ManaPotion(); manaPotion.x = self.x; manaPotion.y = self.y; manaPotions.push(manaPotion); game.addChild(manaPotion); } // Give 1 mana point per kill playerMana = Math.min(maxMana, playerMana + 1); // Give skill points based on enemy type var pointsToGive = 1; if (self.type === 'enemy4') pointsToGive = 5; // Boss else if (self.type === 'enemy3') pointsToGive = 3; // Tank else if (self.type === 'enemy7') pointsToGive = 2; // Healer skillPoints += pointsToGive; // Drop equipment (15% chance for boss, 8% for tank, 5% for others) var equipmentChance = 0.05; if (self.type === 'enemy4') { equipmentChance = 0.15; } else if (self.type === 'enemy3') { equipmentChance = 0.08; } if (Math.random() < equipmentChance) { var equipment = new Equipment(); equipment.x = self.x; equipment.y = self.y; equipmentItems.push(equipment); game.addChild(equipment); } // Drop relics (rare chance) var relicChance = 0.03; if (self.type === 'enemy4') { relicChance = 0.15; // Boss } else if (self.type === 'enemy3') { relicChance = 0.08; // Tank } else if (self.type === 'enemy7') { relicChance = 0.05; // Healer } if (Math.random() < relicChance) { var relicTypes = ['vampireTooth', 'clockwork', 'goldenFeather', 'crystalCore', 'ironShield', 'luckyCharm']; var randomType = relicTypes[Math.floor(Math.random() * relicTypes.length)]; var relic = new Relic(randomType); relic.x = self.x; relic.y = self.y; relicItems.push(relic); game.addChild(relic); } self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } LK.getSound('enemyHit').play(); }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); bulletGraphics.tint = 0xff4444; // Red tint for enemy bullets self.velocityX = 0; self.velocityY = 0; self.damage = 5; self.lifetime = 120; self.update = function () { self.x += self.velocityX * gameSpeed; self.y += self.velocityY * gameSpeed; self.lifetime -= gameSpeed; // Check collision with hero var dx = hero.x - self.x; var dy = hero.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 40) { hero.takeDamage(self.damage); self.destroy(); var index = enemyBullets.indexOf(self); if (index > -1) { enemyBullets.splice(index, 1); } return; } // Remove if lifetime expired or off screen if (self.lifetime <= 0 || self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) { self.destroy(); var index = enemyBullets.indexOf(self); if (index > -1) { enemyBullets.splice(index, 1); } } }; return self; }); var Equipment = Container.expand(function () { var self = Container.call(this); var equipmentGraphics = self.attachAsset('equipment', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'sword'; self.level = 0; self.magnetRange = 20000; self.magnetSpeed = 3; self.update = function () { // Magnetic pull towards hero var dx = hero.x - self.x; var dy = hero.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.magnetRange * skillBonuses.magnetMultiplier) { self.x += dx / distance * self.magnetSpeed * gameSpeed; self.y += dy / distance * self.magnetSpeed * gameSpeed; } // Automatic collection when close if (distance < 60) { playerEquipment.push(self.type); self.destroy(); var index = equipmentItems.indexOf(self); if (index > -1) { equipmentItems.splice(index, 1); } LK.getSound('pickup').play(); } }; return self; }); var Gold = Container.expand(function () { var self = Container.call(this); var goldGraphics = self.attachAsset('goldCoin', { anchorX: 0.5, anchorY: 0.5 }); self.value = 5; self.magnetRange = 2500; self.magnetSpeed = 4; self.update = function () { // Magnetic pull towards hero var dx = hero.x - self.x; var dy = hero.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.magnetRange * (skillBonuses.magnetMultiplier + skillBonuses.relicGoldRange)) { self.x += dx / distance * self.magnetSpeed * gameSpeed; self.y += dy / distance * self.magnetSpeed * gameSpeed; } // Automatic collection when close if (distance < 60) { playerGold += Math.floor(self.value * (skillBonuses.goldMultiplier + skillBonuses.relicGoldGain)); goldText.setText('Gold: ' + playerGold); self.destroy(); var index = goldItems.indexOf(self); if (index > -1) { goldItems.splice(index, 1); } LK.getSound('pickup').play(); } }; return self; }); var HealthPotion = Container.expand(function () { var self = Container.call(this); var potionGraphics = self.attachAsset('healthPotion', { anchorX: 0.5, anchorY: 0.5 }); self.healAmount = 20; self.magnetRange = 2000; self.magnetSpeed = 4; self.update = function () { // Magnetic pull towards hero var dx = hero.x - self.x; var dy = hero.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.magnetRange * skillBonuses.magnetMultiplier) { self.x += dx / distance * self.magnetSpeed * gameSpeed; self.y += dy / distance * self.magnetSpeed * gameSpeed; } // Automatic collection when close if (distance < 60) { hero.health = Math.min(hero.maxHealth, hero.health + self.healAmount); self.destroy(); var index = healthPotions.indexOf(self); if (index > -1) { healthPotions.splice(index, 1); } LK.getSound('pickup').play(); } }; return self; }); var Hero = Container.expand(function () { var self = Container.call(this); var heroGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); var rangeCircle = self.attachAsset('rangeCircle', { anchorX: 0.5, anchorY: 0.5 }); rangeCircle.alpha = 0.1; rangeCircle.scaleX = 0.5; rangeCircle.scaleY = 0.5; self.rangeCircle = rangeCircle; var shieldEffect = self.attachAsset('shieldEffect', { anchorX: 0.5, anchorY: 0.5 }); shieldEffect.alpha = 0; self.shieldEffect = shieldEffect; self.health = 100; self.maxHealth = 100; self.damage = 40; self.attackSpeed = 60; // frames between shots self.range = 1000; self.shootTimer = 0; self.target = null; self.update = function () { self.shootTimer -= gameSpeed; // Apply health regeneration if (skillBonuses.healthRegen > 0 && LK.ticks % 60 === 0) { self.health = Math.min(self.maxHealth, self.health + skillBonuses.healthRegen); } // Update range circle scale var scale = self.range / 1200; self.rangeCircle.scaleX = scale * 0.5; self.rangeCircle.scaleY = scale * 0.5; // Find nearest enemy in range var nearestEnemy = null; var nearestDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= self.range && distance < nearestDistance) { nearestDistance = distance; nearestEnemy = enemy; } } self.target = nearestEnemy; // Shoot at target if (self.target && self.shootTimer <= 0) { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Calculate rotation angle and smoothly rotate hero towards target var targetAngle = Math.atan2(dy, dx); tween(heroGraphics, { rotation: targetAngle }, { duration: 100, easing: tween.easeOut }); bullet.velocityX = dx / distance * 8; bullet.velocityY = dy / distance * 8; bullet.damage = self.damage; bullets.push(bullet); game.addChild(bullet); self.shootTimer = self.attackSpeed / (skillBonuses.attackSpeedMultiplier + skillBonuses.relicAttackSpeed); LK.getSound('shoot').play(); } }; self.takeDamage = function (damage) { if (shieldActive) { // Shield blocks damage return; } var finalDamage = damage * (1 - (skillBonuses.damageReduction + skillBonuses.relicArmor)); self.health -= finalDamage; if (self.health <= 0) { LK.showGameOver(); } }; return self; }); var ManaPotion = Container.expand(function () { var self = Container.call(this); var potionGraphics = self.attachAsset('manaPotion', { anchorX: 0.5, anchorY: 0.5 }); self.manaAmount = 20; self.magnetRange = 2000; self.magnetSpeed = 4; self.update = function () { // Magnetic pull towards hero var dx = hero.x - self.x; var dy = hero.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.magnetRange * skillBonuses.magnetMultiplier) { self.x += dx / distance * self.magnetSpeed * gameSpeed; self.y += dy / distance * self.magnetSpeed * gameSpeed; } // Automatic collection when close if (distance < 60) { playerMana = Math.min(maxMana, playerMana + self.manaAmount); self.destroy(); var index = manaPotions.indexOf(self); if (index > -1) { manaPotions.splice(index, 1); } LK.getSound('pickup').play(); } }; // Lightning skill button handler lightningBtn.down = function () { if (playerMana >= lightningManaCost && lightningCooldown <= 0) { playerMana -= lightningManaCost; lightningCooldown = lightningMaxCooldown; // Damage all enemies on screen for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; enemy.takeDamage(60); // Lightning effect tween(enemy, { tint: 0xffff00 }, { duration: 100, onFinish: function onFinish() { tween(enemy, { tint: 0xffffff }, { duration: 100 }); } }); } LK.getSound('lightning').play(); LK.effects.flashScreen(0xffff00, 200); } }; // Freeze skill button handler freezeBtn.down = function () { if (playerMana >= freezeManaCost && freezeCooldown <= 0) { playerMana -= freezeManaCost; freezeCooldown = freezeMaxCooldown; // Freeze all enemies for 5 seconds for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; enemy.originalSpeed = enemy.speed; enemy.speed = 0; enemy.frozenTimer = 300; // 5 seconds tween(enemy, { tint: 0x00ffff }, { duration: 200 }); } LK.getSound('freeze').play(); LK.effects.flashScreen(0x00ffff, 300); } }; // Shield skill button handler shieldBtn.down = function () { if (playerMana >= shieldManaCost && shieldCooldown <= 0) { playerMana -= shieldManaCost; shieldCooldown = shieldMaxCooldown; shieldActive = true; shieldDuration = shieldMaxDuration; // Show shield effect hero.shieldEffect.alpha = 0.6; tween(hero.shieldEffect, { scaleX: 1.2, scaleY: 1.2 }, { duration: 300 }); LK.getSound('shield').play(); } }; return self; }); var Relic = Container.expand(function (relicType) { var self = Container.call(this); var relicGraphics = self.attachAsset('relic', { anchorX: 0.5, anchorY: 0.5 }); self.relicType = relicType || 'vampireTooth'; self.magnetRange = 1500; self.magnetSpeed = 3; // Set relic properties and colors based on type if (relicType === 'vampireTooth') { relicGraphics.tint = 0x8B0000; self.name = 'Vampire Tooth'; self.description = 'Heal 5% of damage dealt'; self.bonus = 0.05; } else if (relicType === 'clockwork') { relicGraphics.tint = 0xFFD700; self.name = 'Clockwork'; self.description = '+10% attack speed'; self.bonus = 0.10; } else if (relicType === 'goldenFeather') { relicGraphics.tint = 0xFFA500; self.name = 'Golden Feather'; self.description = '+20% gold pickup range'; self.bonus = 0.20; } else if (relicType === 'crystalCore') { relicGraphics.tint = 0x4169E1; self.name = 'Crystal Core'; self.description = '+15% damage'; self.bonus = 0.15; } else if (relicType === 'ironShield') { relicGraphics.tint = 0x708090; self.name = 'Iron Shield'; self.description = '+10% damage reduction'; self.bonus = 0.10; } else if (relicType === 'luckyCharm') { relicGraphics.tint = 0x32CD32; self.name = 'Lucky Charm'; self.description = '+25% gold gain'; self.bonus = 0.25; } self.update = function () { // Magnetic pull towards hero var dx = hero.x - self.x; var dy = hero.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < self.magnetRange) { self.x += dx / distance * self.magnetSpeed * gameSpeed; self.y += dy / distance * self.magnetSpeed * gameSpeed; } // Automatic collection when close if (distance < 60) { playerRelics.push(self); applyRelicBonus(self); self.destroy(); var index = relicItems.indexOf(self); if (index > -1) { relicItems.splice(index, 1); } LK.getSound('pickup').play(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0d1117 }); /**** * Game Code ****/ // Game variables LK.getSound('metin2likethat').play(); var hero; var enemies = []; var bullets = []; var enemyBullets = []; var goldItems = []; var equipmentItems = []; var healthPotions = []; var playerGold = 0; var playerEquipment = []; var playerRelics = []; var relicItems = []; var waveNumber = 1; var enemySpawnTimer = 0; var enemiesPerWave = 3; // UI Elements var goldText = new Text2('Gold: 0', { size: 40, fill: '#FFD700' }); goldText.anchor.set(0, 0); goldText.x = 120; goldText.y = 50; LK.gui.topLeft.addChild(goldText); var waveText = new Text2('Wave: 1', { size: 40, fill: '#FFFFFF' }); waveText.anchor.set(0.5, 0); waveText.x = 0; waveText.y = 50; LK.gui.top.addChild(waveText); var healthText = new Text2('Health: 100', { size: 40, fill: '#FF0000' }); healthText.anchor.set(1, 0); healthText.x = 0; healthText.y = 50; LK.gui.topRight.addChild(healthText); // Speed button var speedBtn = new Text2('Speed: 1x', { size: 35, fill: '#00FF00' }); speedBtn.anchor.set(1, 0); speedBtn.x = 0; speedBtn.y = 100; LK.gui.topRight.addChild(speedBtn); // Upgrade buttons var damageUpgradeBtn = new Text2('Damage +10 (Cost: 50)', { size: 35, fill: '#FFFFFF' }); damageUpgradeBtn.anchor.set(0.5, 1); damageUpgradeBtn.x = 0; damageUpgradeBtn.y = -200; LK.gui.bottom.addChild(damageUpgradeBtn); var speedUpgradeBtn = new Text2('Speed +10 (Cost: 75)', { size: 35, fill: '#FFFFFF' }); speedUpgradeBtn.anchor.set(0.5, 1); speedUpgradeBtn.x = 0; speedUpgradeBtn.y = -150; LK.gui.bottom.addChild(speedUpgradeBtn); var rangeUpgradeBtn = new Text2('Range +50 (Cost: 100)', { size: 35, fill: '#FFFFFF' }); rangeUpgradeBtn.anchor.set(0.5, 1); rangeUpgradeBtn.x = 0; rangeUpgradeBtn.y = -100; LK.gui.bottom.addChild(rangeUpgradeBtn); var healthUpgradeBtn = new Text2('Health +25 (Cost: 60)', { size: 35, fill: '#FFFFFF' }); healthUpgradeBtn.anchor.set(0.5, 1); healthUpgradeBtn.x = 0; healthUpgradeBtn.y = -50; LK.gui.bottom.addChild(healthUpgradeBtn); var equipmentUpgradeBtn = new Text2('Upgrade Equipment (Cost: 200)', { size: 35, fill: '#FFFFFF' }); equipmentUpgradeBtn.anchor.set(0.5, 1); equipmentUpgradeBtn.x = 0; equipmentUpgradeBtn.y = 0; LK.gui.bottom.addChild(equipmentUpgradeBtn); var equipmentLevelText = new Text2('Equipment Level: 0', { size: 30, fill: '#8a2be2' }); equipmentLevelText.anchor.set(0, 0); equipmentLevelText.x = 120; equipmentLevelText.y = 100; LK.gui.topLeft.addChild(equipmentLevelText); var relicCountText = new Text2('Relics: 0', { size: 30, fill: '#ff6b6b' }); relicCountText.anchor.set(0, 0); relicCountText.x = 120; relicCountText.y = 220; LK.gui.topLeft.addChild(relicCountText); // Skill points display var skillPointsText = new Text2('Skill Points: 0', { size: 30, fill: '#ffd700' }); skillPointsText.anchor.set(0, 0); skillPointsText.x = 120; skillPointsText.y = 180; LK.gui.topLeft.addChild(skillPointsText); // Skill tree button var skillTreeBtn = new Text2('Skill Tree', { size: 35, fill: '#ff6b6b' }); skillTreeBtn.anchor.set(0.5, 0); skillTreeBtn.x = 0; skillTreeBtn.y = 150; LK.gui.top.addChild(skillTreeBtn); // Skill tree UI containers (initially hidden) var skillTreeContainer = new Container(); skillTreeContainer.visible = false; LK.gui.center.addChild(skillTreeContainer); // Background for skill tree var skillTreeBg = LK.getAsset('rangeCircle', { width: 1800, height: 1400, anchorX: 0.5, anchorY: 0.5, color: 0x000000 }); skillTreeBg.alpha = 0.8; skillTreeContainer.addChild(skillTreeBg); // Close button var closeBtn = new Text2('X', { size: 60, fill: '#ff0000' }); closeBtn.anchor.set(0.5, 0.5); closeBtn.x = 850; closeBtn.y = -650; skillTreeContainer.addChild(closeBtn); // Branch titles var offenseTitle = new Text2('ATTACK', { size: 50, fill: '#ff4444' }); offenseTitle.anchor.set(0.5, 0.5); offenseTitle.x = -500; offenseTitle.y = -450; skillTreeContainer.addChild(offenseTitle); var defenseTitle = new Text2('DEFENSE', { size: 50, fill: '#44ff44' }); defenseTitle.anchor.set(0.5, 0.5); defenseTitle.x = 0; defenseTitle.y = -450; skillTreeContainer.addChild(defenseTitle); var utilityTitle = new Text2('SUPPORT', { size: 50, fill: '#4444ff' }); utilityTitle.anchor.set(0.5, 0.5); utilityTitle.x = 500; utilityTitle.y = -450; skillTreeContainer.addChild(utilityTitle); var manaText = new Text2('Mana: 100/100', { size: 35, fill: '#4a90e2' }); manaText.anchor.set(0, 0); manaText.x = 120; manaText.y = 140; LK.gui.topLeft.addChild(manaText); // Initialize hero at center hero = new Hero(); hero.x = 1024; hero.y = 1366; game.addChild(hero); // Skill tree system var skillPoints = 0; var showSkillTree = false; var skillTreeData = { offense: { damage: { unlocked: false, cost: 2, name: "Power", desc: "+50% damage" }, crit: { unlocked: false, cost: 3, name: "Critical", desc: "25% crit chance" }, speed: { unlocked: false, cost: 2, name: "Speed", desc: "+50% attack speed" } }, defense: { health: { unlocked: false, cost: 2, name: "Vitality", desc: "+100 HP" }, regen: { unlocked: false, cost: 3, name: "Regeneration", desc: "Heal 3 HP/sec" }, armor: { unlocked: false, cost: 2, name: "Armor", desc: "-30% damage taken" } }, utility: { gold: { unlocked: false, cost: 2, name: "Wealth", desc: "+100% gold gain" }, mana: { unlocked: false, cost: 3, name: "Mana Flow", desc: "+50% mana regen" }, magnet: { unlocked: false, cost: 2, name: "Magnet", desc: "+200% pickup range" } } }; // Skill bonuses var skillBonuses = { damageMultiplier: 1.0, critChance: 0.0, attackSpeedMultiplier: 1.0, healthBonus: 0, healthRegen: 0, damageReduction: 0.0, goldMultiplier: 1.0, manaRegen: 0.0, magnetMultiplier: 1.0, vampireHealing: 0.0, relicAttackSpeed: 0.0, relicGoldRange: 0.0, relicDamage: 0.0, relicArmor: 0.0, relicGoldGain: 0.0 }; // Create skill tree nodes var skillNodes = {}; function createSkillNode(branch, skillKey, x, y) { var skill = skillTreeData[branch][skillKey]; var node = new Container(); // Node background var bg = LK.getAsset('rangeCircle', { width: 160, height: 160, anchorX: 0.5, anchorY: 0.5, color: skill.unlocked ? 0x00ff00 : 0x666666 }); bg.alpha = 0.8; node.addChild(bg); // Node text var text = new Text2(skill.name, { size: 24, fill: skill.unlocked ? '#ffffff' : '#aaaaaa' }); text.anchor.set(0.5, 0.5); text.y = -15; node.addChild(text); // Cost text var costText = new Text2(skill.cost + ' pts', { size: 18, fill: '#ffff00' }); costText.anchor.set(0.5, 0.5); costText.y = 15; node.addChild(costText); node.x = x; node.y = y; node.skillKey = skillKey; node.branch = branch; // Click handler node.down = function () { if (!skill.unlocked && skillPoints >= skill.cost) { // Check requirements if (skill.requires && !skillTreeData[branch][skill.requires].unlocked) { return; } // Unlock skill skill.unlocked = true; skillPoints -= skill.cost; applySkillBonus(branch, skillKey); updateSkillTreeUI(); LK.getSound('upgrade').play(); } }; skillTreeContainer.addChild(node); skillNodes[branch + '_' + skillKey] = node; } // Create all skill nodes // Offense branch createSkillNode('offense', 'damage', -500, -300); createSkillNode('offense', 'crit', -500, -100); createSkillNode('offense', 'speed', -500, 100); // Defense branch createSkillNode('defense', 'health', 0, -300); createSkillNode('defense', 'regen', 0, -100); createSkillNode('defense', 'armor', 0, 100); // Utility branch createSkillNode('utility', 'gold', 500, -300); createSkillNode('utility', 'mana', 500, -100); createSkillNode('utility', 'magnet', 500, 100); function updateSkillTreeUI() { skillPointsText.setText('Skill Points: ' + skillPoints); // Update all nodes for (var branch in skillTreeData) { for (var skillKey in skillTreeData[branch]) { var skill = skillTreeData[branch][skillKey]; var node = skillNodes[branch + '_' + skillKey]; if (node) { var bg = node.children[0]; var text = node.children[1]; bg.tint = skill.unlocked ? 0x00ff00 : 0x666666; text.tint = skill.unlocked ? 0xffffff : 0xaaaaaa; // Check if can unlock var canUnlock = !skill.unlocked && skillPoints >= skill.cost; if (skill.requires && !skillTreeData[branch][skill.requires].unlocked) { canUnlock = false; } if (canUnlock) { bg.tint = 0xffff00; } } } } } function applySkillBonus(branch, skillKey) { var skill = skillTreeData[branch][skillKey]; // Apply bonuses based on skill if (skillKey === 'damage') { skillBonuses.damageMultiplier += 0.50; } else if (skillKey === 'crit') { skillBonuses.critChance += 0.25; } else if (skillKey === 'speed') { skillBonuses.attackSpeedMultiplier += 0.50; } else if (skillKey === 'health') { skillBonuses.healthBonus += 100; hero.maxHealth += 100; hero.health = Math.min(hero.health + 100, hero.maxHealth); } else if (skillKey === 'regen') { skillBonuses.healthRegen += 3; } else if (skillKey === 'armor') { skillBonuses.damageReduction += 0.30; } else if (skillKey === 'gold') { skillBonuses.goldMultiplier += 1.00; } else if (skillKey === 'mana') { skillBonuses.manaRegen += 0.50; } else if (skillKey === 'magnet') { skillBonuses.magnetMultiplier += 2.00; } } function applyRelicBonus(relic) { if (relic.relicType === 'vampireTooth') { skillBonuses.vampireHealing += relic.bonus; } else if (relic.relicType === 'clockwork') { skillBonuses.relicAttackSpeed += relic.bonus; } else if (relic.relicType === 'goldenFeather') { skillBonuses.relicGoldRange += relic.bonus; } else if (relic.relicType === 'crystalCore') { skillBonuses.relicDamage += relic.bonus; } else if (relic.relicType === 'ironShield') { skillBonuses.relicArmor += relic.bonus; } else if (relic.relicType === 'luckyCharm') { skillBonuses.relicGoldGain += relic.bonus; } } // Button handlers skillTreeBtn.down = function () { showSkillTree = !showSkillTree; skillTreeContainer.visible = showSkillTree; updateSkillTreeUI(); }; closeBtn.down = function () { showSkillTree = false; skillTreeContainer.visible = false; }; // Active skill buttons on right side var lightningBtn = new Text2('Lightning\n(40 mana)', { size: 28, fill: '#ffff00' }); lightningBtn.anchor.set(1, 0.5); lightningBtn.x = -20; lightningBtn.y = -200; LK.gui.right.addChild(lightningBtn); var freezeBtn = new Text2('Freeze\n(30 mana)', { size: 28, fill: '#00ffff' }); freezeBtn.anchor.set(1, 0.5); freezeBtn.x = -20; freezeBtn.y = -50; LK.gui.right.addChild(freezeBtn); var shieldBtn = new Text2('Shield\n(50 mana)', { size: 28, fill: '#00ff00' }); shieldBtn.anchor.set(1, 0.5); shieldBtn.x = -20; shieldBtn.y = 100; LK.gui.right.addChild(shieldBtn); // Upgrade costs var damageCost = 50; var speedCost = 75; var rangeCost = 100; var healthCost = 60; var equipmentCost = 200; var equipmentLevel = 0; // Mana system var playerMana = 100; var maxMana = 100; var manaPotions = []; // Active skills var lightningCooldown = 0; var lightningMaxCooldown = 1800; // 30 seconds at 60fps var freezeCooldown = 0; var freezeMaxCooldown = 1800; // 30 seconds at 60fps var shieldCooldown = 0; var shieldMaxCooldown = 3600; // 60 seconds at 60fps var shieldActive = false; var shieldDuration = 0; var shieldMaxDuration = 600; // 10 seconds at 60fps // Skill costs var lightningManaCost = 40; var freezeManaCost = 30; var shieldManaCost = 50; // Game speed system var gameSpeed = 1; // 1x, 2x, 3x multiplier var speedLevels = [1, 2, 3]; var currentSpeedIndex = 0; // Upgrade button handlers damageUpgradeBtn.down = function () { if (playerGold >= damageCost) { playerGold -= damageCost; hero.damage += 10; damageCost = Math.floor(damageCost * 1.5); goldText.setText('Gold: ' + playerGold); damageUpgradeBtn.setText('Damage +10 (Cost: ' + damageCost + ')'); LK.getSound('upgrade').play(); } }; speedUpgradeBtn.down = function () { if (playerGold >= speedCost) { playerGold -= speedCost; hero.attackSpeed = Math.max(10, hero.attackSpeed - 5); speedCost = Math.floor(speedCost * 1.5); goldText.setText('Gold: ' + playerGold); speedUpgradeBtn.setText('Speed +10 (Cost: ' + speedCost + ')'); LK.getSound('upgrade').play(); } }; rangeUpgradeBtn.down = function () { if (playerGold >= rangeCost) { playerGold -= rangeCost; hero.range += 50; rangeCost = Math.floor(rangeCost * 1.5); goldText.setText('Gold: ' + playerGold); rangeUpgradeBtn.setText('Range +50 (Cost: ' + rangeCost + ')'); LK.getSound('upgrade').play(); } }; healthUpgradeBtn.down = function () { if (playerGold >= healthCost) { playerGold -= healthCost; hero.maxHealth += 25; hero.health = Math.min(hero.health + 25, hero.maxHealth); healthCost = Math.floor(healthCost * 1.4); goldText.setText('Gold: ' + playerGold); healthUpgradeBtn.setText('Health +25 (Cost: ' + healthCost + ')'); LK.getSound('upgrade').play(); } }; equipmentUpgradeBtn.down = function () { if (playerGold >= equipmentCost && playerEquipment.length > 0) { playerGold -= equipmentCost; equipmentLevel++; hero.damage += 15; hero.attackSpeed = Math.max(8, hero.attackSpeed - 3); equipmentCost = Math.floor(equipmentCost * 1.6); goldText.setText('Gold: ' + playerGold); equipmentUpgradeBtn.setText('Upgrade Equipment (Cost: ' + equipmentCost + ')'); equipmentLevelText.setText('Equipment Level: ' + equipmentLevel); LK.getSound('upgrade').play(); } }; // Speed button handler speedBtn.down = function () { currentSpeedIndex = (currentSpeedIndex + 1) % speedLevels.length; gameSpeed = speedLevels[currentSpeedIndex]; speedBtn.setText('Speed: ' + gameSpeed + 'x'); LK.getSound('pickup').play(); }; function spawnEnemy() { // Determine enemy type based on wave and random chance var enemyType = 'enemy1'; var rand = Math.random(); if (waveNumber >= 10 && rand < 0.05) { enemyType = 'enemy4'; // Boss } else if (waveNumber >= 8 && rand < 0.08) { enemyType = 'enemy7'; // Healer } else if (waveNumber >= 6 && rand < 0.12) { enemyType = 'enemy6'; // Exploder } else if (waveNumber >= 4 && rand < 0.15) { enemyType = 'enemy5'; // Archer } else if (waveNumber >= 5 && rand < 0.2) { enemyType = 'enemy3'; // Tank } else if (waveNumber >= 3 && rand < 0.3) { enemyType = 'enemy2'; // Fast } var enemy = new Enemy(enemyType); // Random spawn position at screen edges var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top enemy.x = Math.random() * 2048; enemy.y = -50; break; case 1: // Right enemy.x = 2098; enemy.y = Math.random() * 2732; break; case 2: // Bottom enemy.x = Math.random() * 2048; enemy.y = 2782; break; case 3: // Left enemy.x = -50; enemy.y = Math.random() * 2732; break; } // Scale enemy stats with wave number based on type var healthMultiplier = 1 + (waveNumber - 1) * 0.3; var speedMultiplier = 1 + (waveNumber - 1) * 0.15; var goldMultiplier = 1 + (waveNumber - 1) * 0.4; enemy.health = Math.floor(enemy.health * healthMultiplier); enemy.maxHealth = enemy.health; enemy.speed = enemy.speed * speedMultiplier; enemy.goldReward = Math.floor(enemy.goldReward * goldMultiplier); enemies.push(enemy); game.addChild(enemy); } game.update = function () { // Update health display healthText.setText('Health: ' + hero.health); // Update mana display manaText.setText('Mana: ' + playerMana + '/' + maxMana); // Mana regeneration if (skillBonuses.manaRegen > 0 && LK.ticks % 60 === 0) { var manaToRegen = Math.floor(maxMana * skillBonuses.manaRegen); playerMana = Math.min(maxMana, playerMana + manaToRegen); } // Update skill cooldowns if (lightningCooldown > 0) { lightningCooldown -= gameSpeed; var cooldownText = Math.ceil(lightningCooldown / 60) + 's'; lightningBtn.setText('Lightning\n(' + cooldownText + ')'); lightningBtn.tint = 0x666666; } else { lightningBtn.setText('Lightning\n(40 mana)'); lightningBtn.tint = 0xffff00; } if (freezeCooldown > 0) { freezeCooldown -= gameSpeed; var cooldownText = Math.ceil(freezeCooldown / 60) + 's'; freezeBtn.setText('Freeze\n(' + cooldownText + ')'); freezeBtn.tint = 0x666666; } else { freezeBtn.setText('Freeze\n(30 mana)'); freezeBtn.tint = 0x00ffff; } if (shieldCooldown > 0) { shieldCooldown -= gameSpeed; var cooldownText = Math.ceil(shieldCooldown / 60) + 's'; shieldBtn.setText('Shield\n(' + cooldownText + ')'); shieldBtn.tint = 0x666666; } else { shieldBtn.setText('Shield\n(50 mana)'); shieldBtn.tint = 0x00ff00; } // Update shield duration if (shieldActive) { shieldDuration -= gameSpeed; if (shieldDuration <= 0) { shieldActive = false; hero.shieldEffect.alpha = 0; tween(hero.shieldEffect, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } } // Enemy spawning enemySpawnTimer += gameSpeed; var spawnRate = Math.max(30, 120 - waveNumber * 5); if (enemySpawnTimer >= spawnRate) { if (enemies.length < enemiesPerWave + Math.floor(waveNumber / 2)) { spawnEnemy(); enemySpawnTimer = 0; } } // Check for wave completion if (LK.ticks % 1800 === 0) { // Every 30 seconds waveNumber++; enemiesPerWave = Math.min(15, 3 + Math.floor(waveNumber / 2)); waveText.setText('Wave: ' + waveNumber); } // Update all game objects for (var i = bullets.length - 1; i >= 0; i--) { if (bullets[i].update) { bullets[i].update(); } } for (var i = enemyBullets.length - 1; i >= 0; i--) { if (enemyBullets[i].update) { enemyBullets[i].update(); } } for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].update) { enemies[i].update(); } } for (var i = goldItems.length - 1; i >= 0; i--) { if (goldItems[i].update) { goldItems[i].update(); } } for (var i = equipmentItems.length - 1; i >= 0; i--) { if (equipmentItems[i].update) { equipmentItems[i].update(); } } for (var i = healthPotions.length - 1; i >= 0; i--) { if (healthPotions[i].update) { healthPotions[i].update(); } } for (var i = manaPotions.length - 1; i >= 0; i--) { if (manaPotions[i].update) { manaPotions[i].update(); } } for (var i = relicItems.length - 1; i >= 0; i--) { if (relicItems[i].update) { relicItems[i].update(); } } // Update relic count display relicCountText.setText('Relics: ' + playerRelics.length); };
===================================================================
--- original.js
+++ change.js
@@ -24,15 +24,20 @@
// Check collision with enemies
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (self.intersects(enemy)) {
- var finalDamage = self.damage * skillBonuses.damageMultiplier;
+ var finalDamage = self.damage * (skillBonuses.damageMultiplier + skillBonuses.relicDamage);
// Apply critical hit
if (Math.random() < skillBonuses.critChance) {
finalDamage *= 2;
LK.effects.flashObject(enemy, 0xffff00, 200);
}
enemy.takeDamage(finalDamage);
+ // Vampire healing from relics
+ if (skillBonuses.vampireHealing > 0) {
+ var healAmount = finalDamage * skillBonuses.vampireHealing;
+ hero.health = Math.min(hero.maxHealth, hero.health + healAmount);
+ }
self.destroy();
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
@@ -296,8 +301,26 @@
equipment.y = self.y;
equipmentItems.push(equipment);
game.addChild(equipment);
}
+ // Drop relics (rare chance)
+ var relicChance = 0.03;
+ if (self.type === 'enemy4') {
+ relicChance = 0.15; // Boss
+ } else if (self.type === 'enemy3') {
+ relicChance = 0.08; // Tank
+ } else if (self.type === 'enemy7') {
+ relicChance = 0.05; // Healer
+ }
+ if (Math.random() < relicChance) {
+ var relicTypes = ['vampireTooth', 'clockwork', 'goldenFeather', 'crystalCore', 'ironShield', 'luckyCharm'];
+ var randomType = relicTypes[Math.floor(Math.random() * relicTypes.length)];
+ var relic = new Relic(randomType);
+ relic.x = self.x;
+ relic.y = self.y;
+ relicItems.push(relic);
+ game.addChild(relic);
+ }
self.destroy();
var index = enemies.indexOf(self);
if (index > -1) {
enemies.splice(index, 1);
@@ -390,15 +413,15 @@
// Magnetic pull towards hero
var dx = hero.x - self.x;
var dy = hero.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
- if (distance < self.magnetRange * skillBonuses.magnetMultiplier) {
+ if (distance < self.magnetRange * (skillBonuses.magnetMultiplier + skillBonuses.relicGoldRange)) {
self.x += dx / distance * self.magnetSpeed * gameSpeed;
self.y += dy / distance * self.magnetSpeed * gameSpeed;
}
// Automatic collection when close
if (distance < 60) {
- playerGold += Math.floor(self.value * skillBonuses.goldMultiplier);
+ playerGold += Math.floor(self.value * (skillBonuses.goldMultiplier + skillBonuses.relicGoldGain));
goldText.setText('Gold: ' + playerGold);
self.destroy();
var index = goldItems.indexOf(self);
if (index > -1) {
@@ -511,18 +534,18 @@
bullet.velocityY = dy / distance * 8;
bullet.damage = self.damage;
bullets.push(bullet);
game.addChild(bullet);
- self.shootTimer = self.attackSpeed / skillBonuses.attackSpeedMultiplier;
+ self.shootTimer = self.attackSpeed / (skillBonuses.attackSpeedMultiplier + skillBonuses.relicAttackSpeed);
LK.getSound('shoot').play();
}
};
self.takeDamage = function (damage) {
if (shieldActive) {
// Shield blocks damage
return;
}
- var finalDamage = damage * (1 - skillBonuses.damageReduction);
+ var finalDamage = damage * (1 - (skillBonuses.damageReduction + skillBonuses.relicArmor));
self.health -= finalDamage;
if (self.health <= 0) {
LK.showGameOver();
}
@@ -625,8 +648,72 @@
}
};
return self;
});
+var Relic = Container.expand(function (relicType) {
+ var self = Container.call(this);
+ var relicGraphics = self.attachAsset('relic', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.relicType = relicType || 'vampireTooth';
+ self.magnetRange = 1500;
+ self.magnetSpeed = 3;
+ // Set relic properties and colors based on type
+ if (relicType === 'vampireTooth') {
+ relicGraphics.tint = 0x8B0000;
+ self.name = 'Vampire Tooth';
+ self.description = 'Heal 5% of damage dealt';
+ self.bonus = 0.05;
+ } else if (relicType === 'clockwork') {
+ relicGraphics.tint = 0xFFD700;
+ self.name = 'Clockwork';
+ self.description = '+10% attack speed';
+ self.bonus = 0.10;
+ } else if (relicType === 'goldenFeather') {
+ relicGraphics.tint = 0xFFA500;
+ self.name = 'Golden Feather';
+ self.description = '+20% gold pickup range';
+ self.bonus = 0.20;
+ } else if (relicType === 'crystalCore') {
+ relicGraphics.tint = 0x4169E1;
+ self.name = 'Crystal Core';
+ self.description = '+15% damage';
+ self.bonus = 0.15;
+ } else if (relicType === 'ironShield') {
+ relicGraphics.tint = 0x708090;
+ self.name = 'Iron Shield';
+ self.description = '+10% damage reduction';
+ self.bonus = 0.10;
+ } else if (relicType === 'luckyCharm') {
+ relicGraphics.tint = 0x32CD32;
+ self.name = 'Lucky Charm';
+ self.description = '+25% gold gain';
+ self.bonus = 0.25;
+ }
+ self.update = function () {
+ // Magnetic pull towards hero
+ var dx = hero.x - self.x;
+ var dy = hero.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < self.magnetRange) {
+ self.x += dx / distance * self.magnetSpeed * gameSpeed;
+ self.y += dy / distance * self.magnetSpeed * gameSpeed;
+ }
+ // Automatic collection when close
+ if (distance < 60) {
+ playerRelics.push(self);
+ applyRelicBonus(self);
+ self.destroy();
+ var index = relicItems.indexOf(self);
+ if (index > -1) {
+ relicItems.splice(index, 1);
+ }
+ LK.getSound('pickup').play();
+ }
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -647,8 +734,10 @@
var equipmentItems = [];
var healthPotions = [];
var playerGold = 0;
var playerEquipment = [];
+var playerRelics = [];
+var relicItems = [];
var waveNumber = 1;
var enemySpawnTimer = 0;
var enemiesPerWave = 3;
// UI Elements
@@ -733,8 +822,16 @@
equipmentLevelText.anchor.set(0, 0);
equipmentLevelText.x = 120;
equipmentLevelText.y = 100;
LK.gui.topLeft.addChild(equipmentLevelText);
+var relicCountText = new Text2('Relics: 0', {
+ size: 30,
+ fill: '#ff6b6b'
+});
+relicCountText.anchor.set(0, 0);
+relicCountText.x = 120;
+relicCountText.y = 220;
+LK.gui.topLeft.addChild(relicCountText);
// Skill points display
var skillPointsText = new Text2('Skill Points: 0', {
size: 30,
fill: '#ffd700'
@@ -887,9 +984,15 @@
healthRegen: 0,
damageReduction: 0.0,
goldMultiplier: 1.0,
manaRegen: 0.0,
- magnetMultiplier: 1.0
+ magnetMultiplier: 1.0,
+ vampireHealing: 0.0,
+ relicAttackSpeed: 0.0,
+ relicGoldRange: 0.0,
+ relicDamage: 0.0,
+ relicArmor: 0.0,
+ relicGoldGain: 0.0
};
// Create skill tree nodes
var skillNodes = {};
function createSkillNode(branch, skillKey, x, y) {
@@ -1004,8 +1107,23 @@
} else if (skillKey === 'magnet') {
skillBonuses.magnetMultiplier += 2.00;
}
}
+function applyRelicBonus(relic) {
+ if (relic.relicType === 'vampireTooth') {
+ skillBonuses.vampireHealing += relic.bonus;
+ } else if (relic.relicType === 'clockwork') {
+ skillBonuses.relicAttackSpeed += relic.bonus;
+ } else if (relic.relicType === 'goldenFeather') {
+ skillBonuses.relicGoldRange += relic.bonus;
+ } else if (relic.relicType === 'crystalCore') {
+ skillBonuses.relicDamage += relic.bonus;
+ } else if (relic.relicType === 'ironShield') {
+ skillBonuses.relicArmor += relic.bonus;
+ } else if (relic.relicType === 'luckyCharm') {
+ skillBonuses.relicGoldGain += relic.bonus;
+ }
+}
// Button handlers
skillTreeBtn.down = function () {
showSkillTree = !showSkillTree;
skillTreeContainer.visible = showSkillTree;
@@ -1287,5 +1405,12 @@
if (manaPotions[i].update) {
manaPotions[i].update();
}
}
+ for (var i = relicItems.length - 1; i >= 0; i--) {
+ if (relicItems[i].update) {
+ relicItems[i].update();
+ }
+ }
+ // Update relic count display
+ relicCountText.setText('Relics: ' + playerRelics.length);
};
\ No newline at end of file