User prompt
When you click on the ITEMBOX, the main character's health will decrease by 50 and will always be 1 less until you click on x, as if the enemy has dealt damage.
User prompt
When you click on the ITEMBOX, the main character's health will decrease by 1 and will remain 1 less until you click on x, as if the enemy has dealt damage.
User prompt
İTEMBOX A TIKLAYINCA , ana karakterin canı 1 düşsün ve x e tıklayana kadar hep 1 eksik kalsın
User prompt
İTEMBOX A TIKLAYINCA ekranın ortasındaki 1000 px x 1000 px alan harici yerleri black simsiyah yap 1000 px x 1000 px alan açık kalacak siyah black yerlere tıklanamaz ve bu siyah her şerin üzerinde onun üzerine hiç bir şey çıkamaz butonların da üstünü kapatsın ve tıklanamaz yapsın , tıklanabilir olan her şeyin üzerini kapatsın ve tıklanamaz yapsın
User prompt
oyuna eklenen assetlerin de üzerinde olacak bu siyahlık
User prompt
İTEMBOX A TIKLAYINCA ekranın ortasındaki 1000 px x 1000 px alan harici yerleri black simsiyah yap 1000 px x 1000 px alan açık kalacak siyah black yerlere tıklanamaz ve bu siyah her şerin üzerinde onun üzerine hiç bir şey çıkamaz
User prompt
İTEMBOX A TIKLAYINCA ekranın ortasındaki 1000 px x 1000 px alanının dışındaki yerler kararsın ve kararan yerlere tıklanamasın
User prompt
İTEMBOX A TIKLAYINCA açılan pencerenin ,sağ üst kısmına x ekle, sadece x e tıklayınca kapansın bu pencere
User prompt
İTEMBOX A TIKLAYINCA açılan pencerenin sağ üst kısmına x ekle ve ona tıklayınca kapansın bu pencere
User prompt
WHEN CLICKING ON ITEMBOX, PASSIVE ALL ASSETS AND MAKE THEM UNCLICKABLE AND MAKE THEM A LITTLE TRANSPARENT, deactivate spawnBtn and workBtn and MAKE THEM TRANSPARENT
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'interactive')' in or related to this line: 'passiveState[obj._passiveId].interactive = obj.interactive;' Line Number: 461
User prompt
WHEN YOU CLICK ON ITEMBOX, MAKE ALL ASSETS PASSIVE AND UNCLICKABLE AND MAKE THEM SLIGHTLY TRANSPARENT
User prompt
Please fix the bug: 'SecurityError: Failed to read a named property 'alpha' from 'Window': Blocked a frame with origin "null" from accessing a cross-origin frame.' in or related to this line: 'return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;' Line Number: 150
User prompt
İTEMBOX A TIKLAYINCA İSMİNDE bTN GEÇEN TÜM ASSETLER HAFİF ŞEFFAFLAŞIP PASİFLEŞSİN TIKLANAMAZ OLSUN ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
İTEMBOX A TIKLAYINCA AÇILAN PENCERE AÇIK İKEN DİĞER TÜM BUTONLAR PASİFLEŞSİN ANA KARAKTERİN CANI AZKEN PASİFLEŞTİĞİ GİBİ ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
TIKLAYINCA DÜŞMAN ÇAĞIRAN BUTON VE WORK İŞLEVİ YAPAN BUTON DA DAHİL PASİFLEŞSİN ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
İTEMBOX A TIKLAYINCA AÇILAN PENCERE AÇIK İKEN HİÇ BİR BUTONA TIKLANAMASIN VE ONLARI TIKLANAMAZ HALLERİNDEKİ HAFİF ŞEFFAF ŞEKLİNE DÖNÜŞTÜR ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
İTEMBOX A TIKLAYINCA AÇILAN PENCERE AÇIKKEN PENCERENİN DIŞINDA KALAN HER ŞEY TIKLANAMAZ OLSUN
User prompt
İTEMBOX A TIKLAYINCA AÇILAN PENCERENİN BOYUTU 1000 PX X 1000 PX OLSUN VE SİYAY %30 ŞEFFAF OLSUN
User prompt
İTEMBOX A TIKLAYINCA EKRANIN ORTASINDA 500 PX X 500 PX BİR PENCERE AÇSIN RENGİ KOYU KAHVERENGİ OLSUN VE %40 ŞEFFAF OLSUN
User prompt
İTEMBOX A TIKLAYINCA DİĞER BUTONLAR GİBİ HAFİF KÜÇÜLÜP BÜYÜSÜN
User prompt
I AM TELLING THE FEATURES OF THE SHIELD-1 ITEM NOW, IF EQUIPPED, IT ADDS +100 TO THE HEALTH VALUE OF THE CHARACTER. SINCE THIS HEALTH VALUE IS EXTRA, IT IS AUTOMATICALLY RESTORED WHEN THE ENEMY DIES, AND IT ADDS -2 TO MY ATTACK SPEED VALUE. THIS ITEM'S PURCHASE VALUE IS 50 GOLD, SELL VALUE IS 15 GOLD, PROCESS THIS DATA, LATER WE WILL ADD THE PART WE CAN BUY AND SELL
User prompt
SHIELD-1 IS AN ITEM AND WHAT DID WE SAY? WE SAID THAT THE ITEMS SHOULD BE DRAWN TO THE ITEMBAG, WHAT I SAID IS SHIELD-1 FALLS, IT WILL BE DRAWN FROM THE ENEMY TO THE POSITION WHERE THE ITEMBAG IS AND WILL BE COLLECTED
User prompt
DROP ITEMS DRAW itemBag to A
User prompt
itemBag | Height | 200 px | CHANGE TO
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGfx = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 1; self.x = 600; self.y = 2732 / 2; self.isAlive = true; // Animate enemy in self.spawnAnim = function () { self.scaleX = 0.5; self.scaleY = 0.5; tween(self, { scaleX: 1, scaleY: 1 }, { duration: 180, easing: tween.bounceOut }); }; // Animate enemy defeat self.defeatAnim = function (onFinish) { tween(self, { alpha: 0, scaleX: 1.3, scaleY: 1.3 }, { duration: 180, easing: tween.easeIn, onFinish: onFinish }); }; return self; }); // Gold class var Gold = Container.expand(function () { var self = Container.call(this); var goldGfx = self.attachAsset('gold', { anchorX: 0.5, anchorY: 0.5 }); self.x = 600; self.y = 2732 / 2; // Animate gold drop self.dropAnim = function (targetX, targetY, onFinish) { tween(self, { y: targetY }, { duration: 350, easing: tween.bounceOut, onFinish: onFinish }); }; // Animate gold collect self.collectAnim = function (targetX, targetY, onFinish) { tween(self, { x: targetX, y: targetY, scaleX: 0.3, scaleY: 0.3, alpha: 0 }, { duration: 320, easing: tween.cubicIn, onFinish: onFinish }); }; return self; }); // Hero class var Hero = Container.expand(function () { var self = Container.call(this); var heroGfx = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.level = 1; self.x = 200; self.y = 2732 / 2; // For upgrade animation self.flashUpgrade = function () { tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.easeIn }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222a36 }); /**** * Game Code ****/ // Upgrade Button: orange box // Spawn Enemy Button: green box // Gold: yellow ellipse // Enemy: blue ellipse // Hero: red box, left side // --- Background Image --- var backgroundImg = LK.getAsset('backgraund', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); game.addChild(backgroundImg); // --- Global State --- var hero = new Hero(); game.addChild(hero); var currentEnemy = null; var golds = []; var goldAmount = 0; var heroLevel = 1; // --- Inventory and Items --- var inventory = []; var equippedItems = { "shield-1": false }; // Shield-1 item data var itemData = { "shield-1": { name: "Shield-1", type: "shield", bonusHp: 100, // +100 extra HP atkSpdPenalty: 2, // -2 attack speed buyPrice: 50, sellPrice: 15 } }; // --- GoldBag effect state --- var heroIsImmortal = false; var heroOneShotEnemies = false; // Auto-fight timer handles var heroAutoAttackTimer = null; var enemyAutoAttackTimer = null; // --- GUI Elements --- // Gold display (top right) var goldTxt = new Text2('0', { size: 70, fill: 0xFFE066, glow: { color: 0xffffff, distance: 10, strength: 2 } }); goldTxt.anchor.set(1, 0); // right, top LK.gui.topRight.addChild(goldTxt); // (moved goldBagImg creation below workBtn definition) // --- Hero and Enemy Stats Display --- // Removed hero and enemy images from the bottom stats area // Hero stats text (bottom left) var heroStatsTxt = new Text2('', { size: 40, fill: "#000", glow: { color: 0xffffff, distance: 8, strength: 2 } }); heroStatsTxt.anchor.set(0, 1); heroStatsTxt.x = 30; heroStatsTxt.y = LK.gui.bottom.height - 30; LK.gui.bottomLeft.addChild(heroStatsTxt); // Enemy stats text (bottom right, moved slightly to the right) var enemyStatsTxt = new Text2('', { size: 40, fill: "#000", glow: { color: 0xffffff, distance: 8, strength: 2 } }); enemyStatsTxt.anchor.set(1, 1); // Move enemy stats slightly to the right (less offset from right edge) enemyStatsTxt.x = LK.gui.bottomRight.width - 130; enemyStatsTxt.y = LK.gui.bottom.height - 30; LK.gui.bottomRight.addChild(enemyStatsTxt); // Upgrade button (top center) var upgradeBtn = LK.getAsset('upgradeBtn', { anchorX: 0.5, anchorY: 0.5 }); // Work button (to the right of upgradeBtn) var workBtn = LK.getAsset('workBtn', { anchorX: 0.5, anchorY: 0.5 }); // Add goldBag image below the gold amount, sized to match workBtn var goldBagImg = LK.getAsset('goldBag', { anchorX: 1, anchorY: 0, x: goldTxt.x + 40, //{1F} // Move 40px more to the right y: goldTxt.y + goldTxt.height + 10, // 10px gap below gold text width: workBtn.width, height: workBtn.height }); LK.gui.topRight.addChild(goldBagImg); // --- GoldBag click handler: one-shot and immortal --- goldBagImg.down = function (x, y, obj) { heroIsImmortal = true; heroOneShotEnemies = true; // Optional: flash hero for feedback tween(hero, { scaleX: 1.3, scaleY: 1.3, tint: 0xFFD700 }, { duration: 200, easing: tween.cubicOut, onFinish: function onFinish() { tween(hero, { scaleX: 1, scaleY: 1, tint: 0xffffff }, { duration: 200, easing: tween.cubicIn }); } }); }; // --- Work Button State --- var workBtnActive = true; var workBtnTimer = null; var workBtnCountdownTxt = null; var workBtnTimeLeft = 0; var workBtnDuration = 0; // Helper to enable/disable spawnBtn function setSpawnBtnEnabled(enabled) { if (typeof spawnBtn !== "undefined" && spawnBtn) { if (enabled) { spawnBtn.alpha = 1; spawnBtn.interactive = true; spawnBtn.buttonMode = true; } else { spawnBtn.alpha = 0.5; spawnBtn.interactive = false; spawnBtn.buttonMode = false; } } } setSpawnBtnEnabled(true); // Helper to show/hide workBtn countdown text function showWorkBtnCountdown(timeLeft) { if (!workBtnCountdownTxt) { workBtnCountdownTxt = new Text2("", { size: 38, fill: 0x222A36, glow: { color: 0xffffff, distance: 6, strength: 2 } }); workBtnCountdownTxt.anchor.set(0.5, 0); workBtnCountdownTxt.x = workBtn.x; workBtnCountdownTxt.y = workBtn.y + workBtn.height / 2 + 8; LK.gui.top.addChild(workBtnCountdownTxt); } workBtnCountdownTxt.visible = true; workBtnCountdownTxt.setText(timeLeft > 0 ? timeLeft.toFixed(1) + "s" : ""); } function hideWorkBtnCountdown() { if (workBtnCountdownTxt) { workBtnCountdownTxt.visible = false; } } // Place upgradeBtn at top center, but not in the top left 100x100 area // Use LK.gui.top (centered horizontally, below top edge) upgradeBtn.x = LK.gui.top.width / 2; upgradeBtn.y = 100 + upgradeBtn.height / 2; // Place workBtn to the right of upgradeBtn, with a small gap workBtn.x = upgradeBtn.x + upgradeBtn.width / 2 + workBtn.width / 2 + 30; workBtn.y = upgradeBtn.y; // Add gold required text under the upgrade button var upgradeCostTxt = new Text2("", { size: 40, fill: 0x222A36, glow: { color: 0xffffff, distance: 8, strength: 2 } }); upgradeCostTxt.anchor.set(0.5, 0); upgradeCostTxt.x = upgradeBtn.x; upgradeCostTxt.y = upgradeBtn.y + upgradeBtn.height / 2 + 10; LK.gui.top.addChild(upgradeCostTxt); LK.gui.top.addChild(upgradeBtn); LK.gui.top.addChild(workBtn); // Spawn enemy button (bottom center) var spawnBtn = LK.getAsset('spawnBtn', { anchorX: 0.5, anchorY: 0.5 }); // Place spawnBtn at bottom center, above the very bottom edge spawnBtn.x = LK.gui.bottom.width / 2; spawnBtn.y = LK.gui.bottom.height - 100 - spawnBtn.height / 2; // Add "find enemy!" text above the spawn button var findEnemyTxt = new Text2("find enemy!", { size: 45, fill: 0x222A36, glow: { color: 0xffffff, distance: 8, strength: 2 } }); findEnemyTxt.anchor.set(0.5, 1); findEnemyTxt.x = spawnBtn.x; findEnemyTxt.y = spawnBtn.y - spawnBtn.height / 2 - 20; LK.gui.bottom.addChild(findEnemyTxt); LK.gui.bottom.addChild(spawnBtn); // Add itemBag image, 10x size, on the left diagonal of spawnBtn so they do not overlap // Set itemBag to width 300px, height 250px, anchor (0.3, 0.20) // Place on the left diagonal of spawnBtn, with a gap so they do not overlap var itemBagWidth = 300; var itemBagHeight = 200; var itemBagAnchorX = 0.3; var itemBagAnchorY = 0.20; var diagonalGap = 40; var diagonalOffset = (spawnBtn.width * (1 - itemBagAnchorX) + itemBagWidth * itemBagAnchorX + diagonalGap) / Math.sqrt(2); var itemBagImg = LK.getAsset('itemBag', { anchorX: itemBagAnchorX, anchorY: itemBagAnchorY, x: spawnBtn.x - diagonalOffset, y: spawnBtn.y - diagonalOffset, width: itemBagWidth, height: itemBagHeight }); LK.gui.bottom.addChild(itemBagImg); // --- Item drop logic on itemBag tap --- itemBagImg.down = function (x, y, obj) { // Animate shrink and grow like other buttons tween.stop(itemBagImg, { scaleX: true, scaleY: true }); tween(itemBagImg, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(itemBagImg, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut, onFinish: function onFinish() { // --- Show 1000x1000 black, 30% transparent window in center --- // Remove previous if exists if (typeof itemBagWindow !== "undefined" && itemBagWindow && itemBagWindow.parent) { itemBagWindow.parent.removeChild(itemBagWindow); itemBagWindow = null; } if (typeof itemBagOverlay !== "undefined" && itemBagOverlay && itemBagOverlay.parent) { itemBagOverlay.parent.removeChild(itemBagOverlay); itemBagOverlay = null; } // Create overlay: fullscreen black, 100% opaque, blocks all input including all GUI/buttons itemBagOverlay = new Container(); var overlayAlpha = 1; var gameW = 2048, gameH = 2732; var winWidth = 1000, winHeight = 1000; var leftW = (gameW - winWidth) / 2; var topH = (gameH - winHeight) / 2; // Top var overlayTop = LK.getAsset('centerCircle', { width: gameW, height: topH, color: 0x000000, shape: 'box', anchorX: 0, anchorY: 0, x: 0, y: 0 }); overlayTop.alpha = overlayAlpha; itemBagOverlay.addChild(overlayTop); // Bottom var overlayBottom = LK.getAsset('centerCircle', { width: gameW, height: topH, color: 0x000000, shape: 'box', anchorX: 0, anchorY: 0, x: 0, y: gameH - topH }); overlayBottom.alpha = overlayAlpha; itemBagOverlay.addChild(overlayBottom); // Left var overlayLeft = LK.getAsset('centerCircle', { width: leftW, height: winHeight, color: 0x000000, shape: 'box', anchorX: 0, anchorY: 0, x: 0, y: topH }); overlayLeft.alpha = overlayAlpha; itemBagOverlay.addChild(overlayLeft); // Right var overlayRight = LK.getAsset('centerCircle', { width: leftW, height: winHeight, color: 0x000000, shape: 'box', anchorX: 0, anchorY: 0, x: gameW - leftW, y: topH }); overlayRight.alpha = overlayAlpha; itemBagOverlay.addChild(overlayRight); // Block all input on overlay, including all GUI/buttons itemBagOverlay.interactive = true; itemBagOverlay.down = function () {/* block all input */}; itemBagOverlay.up = function () {/* block all input */}; itemBagOverlay.move = function () {/* block all input */}; // Add overlay to game (ensure it's above everything else, including GUI/buttons) game.addChild(itemBagOverlay); // Always bring overlay to top after adding if (game.children && game.children.length > 1) { game.setChildIndex(itemBagOverlay, game.children.length - 1); } // Create window container itemBagWindow = new Container(); // Use a box shape for the window background var winWidth = 1000; var winHeight = 1000; var winColor = 0x000000; // black var winAlpha = 0.3; var winBg = LK.getAsset('centerCircle', { width: winWidth, height: winHeight, color: winColor, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); winBg.alpha = winAlpha; itemBagWindow.addChild(winBg); // Add X close button to top right of window var closeBtnSize = 90; var closeBtn = LK.getAsset('centerCircle', { width: closeBtnSize, height: closeBtnSize, color: 0x222222, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: winWidth / 2 - closeBtnSize / 2 - 20, y: -winHeight / 2 + closeBtnSize / 2 + 20 }); closeBtn.alpha = 0.7; itemBagWindow.addChild(closeBtn); // Add X text on top of closeBtn var closeBtnTxt = new Text2("X", { size: 60, fill: "#fff" }); closeBtnTxt.anchor.set(0.5, 0.5); closeBtnTxt.x = closeBtn.x; closeBtnTxt.y = closeBtn.y; itemBagWindow.addChild(closeBtnTxt); // Close logic for X button closeBtn.down = function () { if (itemBagWindow && itemBagWindow.parent) { itemBagWindow.parent.removeChild(itemBagWindow); itemBagWindow = null; } if (typeof itemBagOverlay !== "undefined" && itemBagOverlay && itemBagOverlay.parent) { itemBagOverlay.parent.removeChild(itemBagOverlay); itemBagOverlay = null; } }; // Center in game area itemBagWindow.x = 2048 / 2; itemBagWindow.y = 2732 / 2; // Add to game game.addChild(itemBagWindow); // Always bring overlay and window to top after adding if (game.children && game.children.length > 1) { game.setChildIndex(itemBagOverlay, game.children.length - 1); game.setChildIndex(itemBagWindow, game.children.length - 1); } // (Removed: close window on tap anywhere on window. Now only X closes the window) // --- (Keep original drop animation for demo) --- var dropX = itemBagImg.x; var dropY = 0 - itemBagHeight; // Start above screen var item = LK.getAsset('gold', { anchorX: 0.5, anchorY: 0.5, x: dropX, y: dropY, width: 150, height: 102 }); game.addChild(item); // Animate drop to itemBag tween(item, { x: itemBagImg.x, y: itemBagImg.y }, { duration: 600, easing: tween.bounceOut, onFinish: function onFinish() { // Optionally: fade out and destroy after reaching itemBag tween(item, { alpha: 0 }, { duration: 250, onFinish: function onFinish() { item.destroy(); } }); } }); } }); } }); }; // --- Helper Functions --- function updateGoldDisplay() { goldTxt.setText(goldAmount); } function updateUpgradeDisplay() { // Show gold required to upgrade under the upgrade button if (typeof upgradeCostTxt !== "undefined") { var nextUpgradeCost = heroLevel * 5; upgradeCostTxt.setText("Gold required: " + nextUpgradeCost); } } // Update hero stats display function updateHeroStatsDisplay() { var stats = getStatsForLevel(heroLevel, "hero"); var hpDisplay = typeof hero.currentHp === "number" ? Math.max(0, Math.round(hero.currentHp)) + " / " + stats.hp : stats.hp; heroStatsTxt.setText("Hero\n" + "Level: " + heroLevel + "\n" + "Health: " + hpDisplay + "\n" + "Attack: " + stats.atk + "\n" + "Atk Spd: " + stats.atkSpd); } // Update enemy stats display function updateEnemyStatsDisplay() { if (currentEnemy && currentEnemy.isAlive) { var enemyLevel = currentEnemy.level || heroLevel; var stats = getStatsForLevel(enemyLevel, "enemy"); var hpDisplay = typeof currentEnemy.hp === "number" ? Math.max(0, Math.round(currentEnemy.hp)) + " / " + stats.hp : stats.hp; enemyStatsTxt.setText("Enemy\n" + "Level: " + enemyLevel + "\n" + "Health: " + hpDisplay + "\n" + "Attack: " + currentEnemy.attack + "\n" + "Atk Spd: " + currentEnemy.attackSpeed); } else { enemyStatsTxt.setText("Enemy\n-"); } } // --- Game Logic --- // Spawn enemy logic // Enemy stat table for levels 1-10 (fixed stats) var enemyStatsByLevel = [ // Level 1 { hp: 60, atk: 10, atkSpd: 2 }, // Level 2 { hp: 95, atk: 14, atkSpd: 3 }, // Level 3 { hp: 130, atk: 18, atkSpd: 4 }, // Level 4 { hp: 170, atk: 23, atkSpd: 4 }, // Level 5 { hp: 215, atk: 27, atkSpd: 5 }, // Level 6 { hp: 265, atk: 32, atkSpd: 6 }, // Level 7 { hp: 320, atk: 38, atkSpd: 6 }, // Level 8 { hp: 380, atk: 45, atkSpd: 7 }, // Level 9 { hp: 445, atk: 53, atkSpd: 8 }, // Level 10 { hp: 515, atk: 62, atkSpd: 9 }]; // --- Stat scaling logic for hero and enemy after level 10 --- // Store hero stat growth per level (compounded) and enemy stat growth per level (linear from level 10 base) var heroStatGrowth = { hp: [enemyStatsByLevel[9].hp], atk: [enemyStatsByLevel[9].atk], atkSpd: [enemyStatsByLevel[9].atkSpd] }; var enemyStatGrowth = { hp: [enemyStatsByLevel[9].hp], atk: [enemyStatsByLevel[9].atk], atkSpd: [enemyStatsByLevel[9].atkSpd] }; // Store enemy stat percent increases per level (for linear scaling) var enemyStatPercents = { hp: [], atk: [], atkSpd: [] }; // Store hero stat percent increases per level (for compounded scaling) var heroStatPercents = { hp: [], atk: [], atkSpd: [] }; // Helper to get random percent between 5% and 20% function randomPercent() { return 0.05 + Math.random() * 0.15; } // Precompute stat growth up to a reasonable max level (e.g. 100) function ensureStatGrowthUpTo(level) { var maxComputed = heroStatGrowth.hp.length + 9; // since index 0 is level 10 for (var lvl = maxComputed + 1; lvl <= level; lvl++) { // HERO: compounded var prevHeroHp = heroStatGrowth.hp[heroStatGrowth.hp.length - 1]; var prevHeroAtk = heroStatGrowth.atk[heroStatGrowth.atk.length - 1]; var prevHeroAtkSpd = heroStatGrowth.atkSpd[heroStatGrowth.atkSpd.length - 1]; var heroHpPct = randomPercent(); var heroAtkPct = randomPercent(); // After level 15, hero attack speed no longer increases var heroAtkSpdPct = lvl > 15 ? 0 : randomPercent(); heroStatPercents.hp.push(heroHpPct); heroStatPercents.atk.push(heroAtkPct); heroStatPercents.atkSpd.push(heroAtkSpdPct); heroStatGrowth.hp.push(Math.round(prevHeroHp * (1 + heroHpPct))); heroStatGrowth.atk.push(Math.round(prevHeroAtk * (1 + heroAtkPct))); heroStatGrowth.atkSpd.push(Math.round(prevHeroAtkSpd * (1 + heroAtkSpdPct))); // ENEMY: linear from level 10 base var baseHp = enemyStatsByLevel[9].hp; var baseAtk = enemyStatsByLevel[9].atk; var baseAtkSpd = enemyStatsByLevel[9].atkSpd; var enemyHpPct = randomPercent(); var enemyAtkPct = randomPercent(); // After level 15, enemy attack speed no longer increases var enemyAtkSpdPct = lvl > 15 ? 0 : randomPercent(); enemyStatPercents.hp.push(enemyHpPct); enemyStatPercents.atk.push(enemyAtkPct); enemyStatPercents.atkSpd.push(enemyAtkSpdPct); // For linear, sum all previous percent increases var totalHpPct = 0; var totalAtkPct = 0; var totalAtkSpdPct = 0; for (var i = 0; i < enemyStatPercents.hp.length; i++) totalHpPct += enemyStatPercents.hp[i]; for (var i = 0; i < enemyStatPercents.atk.length; i++) totalAtkPct += enemyStatPercents.atk[i]; for (var i = 0; i < enemyStatPercents.atkSpd.length; i++) totalAtkSpdPct += enemyStatPercents.atkSpd[i]; // After level 20, enemy health increases by an additional 50% per level var extraHpMultiplier = 1; if (lvl > 20) { // For each level above 20, multiply by 1.5 for each extra level extraHpMultiplier = Math.pow(1.5, lvl - 20); } enemyStatGrowth.hp.push(Math.round(baseHp * (1 + totalHpPct) * extraHpMultiplier)); enemyStatGrowth.atk.push(Math.round(baseAtk * (1 + totalAtkPct))); enemyStatGrowth.atkSpd.push(Math.round(baseAtkSpd * (1 + totalAtkSpdPct))); } } // Returns stats for a given level and type ('hero' or 'enemy') function getStatsForLevel(level, type) { if (level <= 10) { var idx = Math.max(0, Math.min(enemyStatsByLevel.length - 1, level - 1)); var stats = enemyStatsByLevel[idx]; return { hp: stats.hp, atk: stats.atk, atkSpd: stats.atkSpd }; } ensureStatGrowthUpTo(level); var idx = level - 10; if (type === "hero") { // Base stats var baseHp = heroStatGrowth.hp[idx]; var baseAtk = heroStatGrowth.atk[idx]; var baseAtkSpd = heroStatGrowth.atkSpd[idx]; // Apply shield-1 effects if equipped if (equippedItems && equippedItems["shield-1"]) { baseHp += itemData["shield-1"].bonusHp; baseAtkSpd = Math.max(1, baseAtkSpd - itemData["shield-1"].atkSpdPenalty); } return { hp: baseHp, atk: baseAtk, atkSpd: baseAtkSpd }; } else { return { hp: enemyStatGrowth.hp[idx], atk: enemyStatGrowth.atk[idx], atkSpd: enemyStatGrowth.atkSpd[idx] }; } } // For backward compatibility, keep getEnemyStatsForLevel for hero stats (used in refill, etc) function getEnemyStatsForLevel(level) { return getStatsForLevel(level, "hero"); } function spawnEnemy() { if (currentEnemy && currentEnemy.isAlive) return; // Only one at a time if (hero.healthRefilling) return; // Don't allow spawn while refilling var enemy = new Enemy(); // Place enemy on the far right, vertically aligned with hero enemy.x = 2048 - 200; // 200px from the right edge, matching hero's 200px from left enemy.y = hero.y; // Determine enemy level: always one of heroLevel-1, heroLevel, heroLevel+1, or heroLevel+2 var possibleLevels = [Math.max(1, heroLevel - 1), heroLevel, heroLevel + 1, heroLevel + 2]; // Remove duplicates and clamp to at least 1 var uniqueLevels = []; for (var i = 0; i < possibleLevels.length; i++) { var lvl = Math.max(1, possibleLevels[i]); if (uniqueLevels.indexOf(lvl) === -1) uniqueLevels.push(lvl); } // Randomly pick one var enemyLevel = uniqueLevels[Math.floor(Math.random() * uniqueLevels.length)]; // Clamp enemyLevel to valid range for stats table enemyLevel = Math.max(1, Math.min(enemyStatsByLevel.length + heroStatGrowth.hp.length, enemyLevel)); // Get stats for this level (enemy uses linear scaling after level 10) var stats = getStatsForLevel(enemyLevel, "enemy"); enemy.hp = stats.hp; enemy.attack = stats.atk; enemy.attackSpeed = stats.atkSpd; enemy.isAlive = true; enemy.spawnAnim(); game.addChild(enemy); currentEnemy = enemy; // Store the enemy's level for display currentEnemy.level = enemyLevel; updateEnemyStatsDisplay(); // --- Start auto-fight timers --- if (typeof heroAutoAttackTimer !== "undefined" && heroAutoAttackTimer) { LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; } if (typeof enemyAutoAttackTimer !== "undefined" && enemyAutoAttackTimer) { LK.clearInterval(enemyAutoAttackTimer); enemyAutoAttackTimer = null; } // Get hero stats for this level (hero uses compounded scaling after level 10) var heroStats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = heroStats.hp; hero.attack = heroStats.atk; hero.attackSpeed = heroStats.atkSpd; // Hero attacks enemy heroAutoAttackTimer = LK.setInterval(function () { if (!currentEnemy || !currentEnemy.isAlive) { LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; return; } // If one-shot mode, instantly defeat enemy if (heroOneShotEnemies) { currentEnemy.hp = 0; } else { currentEnemy.hp -= hero.attack; } // Flash enemy if (currentEnemy) { tween(currentEnemy, { tint: 0xffffff }, { duration: 60, onFinish: function onFinish() { if (currentEnemy) { tween(currentEnemy, { tint: 0x2a6bde }, { duration: 60 }); } } }); } updateEnemyStatsDisplay(); if (currentEnemy.hp <= 0) { defeatEnemy(); LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; LK.clearInterval(enemyAutoAttackTimer); enemyAutoAttackTimer = null; } }, 1000 / hero.attackSpeed); // Enemy attacks hero enemyAutoAttackTimer = LK.setInterval(function () { if (!currentEnemy || !currentEnemy.isAlive) { LK.clearInterval(enemyAutoAttackTimer); enemyAutoAttackTimer = null; return; } if (typeof hero.currentHp !== "number") { // Defensive: ensure hero.currentHp is set var hStats = getEnemyStatsForLevel(heroLevel); hero.currentHp = hStats.hp; } if (!heroIsImmortal) { hero.currentHp -= currentEnemy.attack; // Flash hero tween(hero, { tint: 0xffffff }, { duration: 60, onFinish: function onFinish() { tween(hero, { tint: 0xd83318 }, { duration: 60 }); } }); updateHeroStatsDisplay(); if (hero.currentHp <= 0) { // Hero defeated, stop fighting hero.currentHp = 0; updateHeroStatsDisplay(); // Optionally, you can add defeat logic here (e.g. show game over) LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; LK.clearInterval(enemyAutoAttackTimer); enemyAutoAttackTimer = null; // Start health refill (handled in update loop) hero.healthRefilling = false; // Will be set to true in update loop } } else { // If immortal, keep HP at max and flash gold var stats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = stats.hp; updateHeroStatsDisplay(); tween(hero, { tint: 0xFFD700 }, { duration: 60, onFinish: function onFinish() { tween(hero, { tint: 0xffffff }, { duration: 60 }); } }); } }, 1000 / currentEnemy.attackSpeed); } // Defeat enemy logic function defeatEnemy() { if (!currentEnemy || !currentEnemy.isAlive) return; currentEnemy.isAlive = false; // Stop auto-fight timers if (typeof heroAutoAttackTimer !== "undefined" && heroAutoAttackTimer) { LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; } if (typeof enemyAutoAttackTimer !== "undefined" && enemyAutoAttackTimer) { LK.clearInterval(enemyAutoAttackTimer); enemyAutoAttackTimer = null; } currentEnemy.defeatAnim(function () { if (currentEnemy) { // --- Shield-1 drop logic --- // Only drop for enemy levels 1-10 if (typeof currentEnemy.level !== "undefined" && currentEnemy.level >= 1 && currentEnemy.level <= 10) { // 5% per level, capped at 50% for level 10 var shieldDropChance = currentEnemy.level * 0.05; if (Math.random() < shieldDropChance) { // Drop shield-1 at enemy's position var shieldAsset = LK.getAsset('shield-1', { anchorX: 0.5, anchorY: 0.5, x: currentEnemy.x, y: currentEnemy.y }); game.addChild(shieldAsset); // Animate drop: move to itemBag position and shrink/fade out // Get itemBag position in game coordinates var itemBagGlobal = LK.gui.bottom.toGlobal({ x: itemBagImg.x, y: itemBagImg.y }); var itemBagGamePos = game.toLocal(itemBagGlobal); tween(shieldAsset, { x: itemBagGamePos.x, y: itemBagGamePos.y, scaleX: 0.3, scaleY: 0.3, alpha: 0.2 }, { duration: 700, easing: tween.cubicIn, onFinish: function onFinish() { shieldAsset.destroy(); // Add to inventory and auto-equip if not already equipped if (!equippedItems["shield-1"]) { inventory.push("shield-1"); equippedItems["shield-1"] = true; // Restore hero HP to new max if in battle or after refill var stats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = stats.hp; updateHeroStatsDisplay(); } } }); } } currentEnemy.destroy(); currentEnemy = null; updateEnemyStatsDisplay(); // If shield-1 is equipped, restore hero HP to new max after enemy defeat if (equippedItems["shield-1"]) { var stats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = stats.hp; updateHeroStatsDisplay(); } } // --- spawnBtn rotation logic on enemy defeat --- // If hero HP is full, rotate 45deg right, else 90deg left var heroStats = getStatsForLevel(heroLevel, "hero"); if (typeof hero.currentHp === "number" && hero.currentHp >= heroStats.hp) { // Full health: rotate 45deg right spawnBtnRotationQueue.push({ angle: Math.PI / 4 }); } else { // Not full: rotate 90deg left spawnBtnRotationQueue.push({ angle: -Math.PI / 2, onFinish: function onFinish() { // After 90deg left, if hero HP is still not full and no enemy, resume right rotation if ((!currentEnemy || !currentEnemy.isAlive) && typeof hero.currentHp === "number" && hero.currentHp < getStatsForLevel(heroLevel, "hero").hp) { if (!spawnBtn._rotatingWhileNotFull) { spawnBtn._rotatingWhileNotFull = true; // Start continuous right rotation (1 full spin per 1.2s) var _rotateRightLoop = function rotateRightLoop() { if (!spawnBtn._rotatingWhileNotFull) return; var startRot = spawnBtn.rotation; var endRot = startRot + Math.PI * 2; tween(spawnBtn, { rotation: endRot }, { duration: 1200, easing: tween.linear, onFinish: function onFinish() { if (spawnBtn._rotatingWhileNotFull && (!currentEnemy || !currentEnemy.isAlive)) { _rotateRightLoop(); } } }); }; tween.stop(spawnBtn, { rotation: true }); _rotateRightLoop(); } } } }); } processSpawnBtnRotationQueue(); // Start hero health refill after any battle (at same refill speed as on defeat) // If hero died (currentHp <= 0), double the refill duration if (typeof hero.currentHp === "number" && hero.currentHp < getStatsForLevel(heroLevel, "hero").hp && !hero.healthRefilling) { hero.healthRefilling = true; hero.refillStartTime = Date.now(); var stats = getStatsForLevel(heroLevel, "hero"); hero.refillFromHp = hero.currentHp; hero.refillToHp = stats.hp; // Set refill duration to 1/5th speed (5x slower), or 1/10th (10x slower) if hero died var baseDuration = 1000; // original duration if (hero.currentHp <= 0) { hero.refillDuration = baseDuration * 10; // 10x slower if died } else { hero.refillDuration = baseDuration * 5; // 5x slower otherwise } } }); // --- Gold drop amount table per level --- var goldDropByLevel = [{ min: 1, max: 5 }, // Level 1 { min: 3, max: 8 }, // Level 2 { min: 5, max: 12 }, // Level 3 { min: 8, max: 16 }, // Level 4 { min: 12, max: 20 }, // Level 5 { min: 15, max: 25 }, // Level 6 { min: 20, max: 32 }, // Level 7 { min: 25, max: 40 }, // Level 8 { min: 30, max: 48 }, // Level 9 { min: 35, max: 60 } // Level 10 ]; // Determine gold drop amount for this level var goldDropStats = goldDropByLevel[Math.max(0, Math.min(heroLevel - 1, goldDropByLevel.length - 1))]; var goldDropAmount = Math.floor(Math.random() * (goldDropStats.max - goldDropStats.min + 1)) + goldDropStats.min; // Drop gold at the far right (where enemy was) // Animate and auto-collect gold after enemy defeat // Calculate the gold display position in game coordinates (top right, where goldTxt is) var goldDisplayGlobal = LK.gui.topRight.toGlobal({ x: goldTxt.x, y: goldTxt.y }); var goldDisplayGamePos = game.toLocal(goldDisplayGlobal); for (var i = 0; i < goldDropAmount; i++) { var gold = new Gold(); gold.x = 2048 - 200; gold.y = hero.y; gold.scaleX = 1; gold.scaleY = 1; gold.alpha = 1; game.addChild(gold); golds.push(gold); // Drop to random y near enemy var dropY = gold.y + (Math.random() * 120 - 60); (function (goldObj, idx) { goldObj.dropAnim(goldObj.x, dropY, function () { // Stagger collection for nice effect LK.setTimeout(function () { // Animate to gold display and collect goldObj.collectAnim(goldDisplayGamePos.x, goldDisplayGamePos.y, function () { goldAmount += 1; updateGoldDisplay(); goldObj.destroy(); }); }, 80 * idx); }); })(gold, i); } // --- Shield-1 drop logic --- // Only drop for enemy levels 1-10 if (typeof enemyLevel !== "undefined" && enemyLevel >= 1 && enemyLevel <= 10) { // 5% per level, capped at 50% for level 10 var shieldDropChance = enemyLevel * 0.05; if (Math.random() < shieldDropChance) { // Drop shield-1 at enemy's position var shieldAsset = LK.getAsset('shield-1', { anchorX: 0.5, anchorY: 0.5, x: 2048 - 200, y: hero.y }); game.addChild(shieldAsset); // Animate drop (fall down a bit, then fade out) var dropTargetY = shieldAsset.y + 180 + (Math.random() * 40 - 20); tween(shieldAsset, { y: dropTargetY }, { duration: 400, easing: tween.bounceOut, onFinish: function onFinish() { // After a short delay, fade out and destroy LK.setTimeout(function () { tween(shieldAsset, { alpha: 0 }, { duration: 350, onFinish: function onFinish() { shieldAsset.destroy(); } }); }, 900); } }); } } } // --- Shield-1 drop logic --- // Only drop for enemy levels 1-10 if (typeof enemyLevel !== "undefined" && enemyLevel >= 1 && enemyLevel <= 10) { // 5% per level, capped at 50% for level 10 var shieldDropChance = enemyLevel * 0.05; if (Math.random() < shieldDropChance) { // Drop shield-1 at enemy's position var shieldAsset = LK.getAsset('shield-1', { anchorX: 0.5, anchorY: 0.5, x: 2048 - 200, y: hero.y }); game.addChild(shieldAsset); // Animate drop (fall down a bit, then fade out) var dropTargetY = shieldAsset.y + 180 + (Math.random() * 40 - 20); tween(shieldAsset, { y: dropTargetY }, { duration: 400, easing: tween.bounceOut, onFinish: function onFinish() { // After a short delay, fade out and destroy LK.setTimeout(function () { tween(shieldAsset, { alpha: 0 }, { duration: 350, onFinish: function onFinish() { shieldAsset.destroy(); } }); }, 900); } }); } } // Collect gold logic function collectGold(gold) { // Animate to gold display var guiGoldPos = LK.gui.topRight.toLocal(gold.toGlobal({ x: 0, y: 0 })); goldAmount += 1; updateGoldDisplay(); gold.collectAnim(guiGoldPos.x, guiGoldPos.y, function () { gold.destroy(); }); } // Upgrade logic function upgradeHero() { var upgradeCost = heroLevel * 5; if (goldAmount < upgradeCost) { // Flash gold text red tween(goldTxt, { tint: 0xff4444 }, { duration: 120, onFinish: function onFinish() { tween(goldTxt, { tint: 0xFFE066 }, { duration: 120 }); } }); return; } goldAmount -= upgradeCost; heroLevel += 1; hero.level = heroLevel; // Refill hero health to full on level up var stats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = stats.hp; hero.healthRefilling = false; updateGoldDisplay(); updateUpgradeDisplay(); updateHeroStatsDisplay(); updateEnemyStatsDisplay(); hero.flashUpgrade(); } // --- Event Handlers --- // Spawn button tap // --- spawnBtn rotation queue state --- var spawnBtnRotationQueue = []; var spawnBtnIsRotating = false; function processSpawnBtnRotationQueue() { if (spawnBtnIsRotating || spawnBtnRotationQueue.length === 0) return; spawnBtnIsRotating = true; var next = spawnBtnRotationQueue.shift(); var targetRotation = spawnBtn.rotation + next.angle; tween(spawnBtn, { rotation: targetRotation }, { duration: 180, easing: tween.cubicInOut, onFinish: function onFinish() { spawnBtn.rotation = targetRotation; spawnBtnIsRotating = false; if (typeof next.onFinish === "function") next.onFinish(); // Process next in queue processSpawnBtnRotationQueue(); } }); } spawnBtn.down = function (x, y, obj) { // Animate shrink tween.stop(spawnBtn, { scaleX: true, scaleY: true }); tween(spawnBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(spawnBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut, onFinish: function onFinish() { // After animation, trigger action // Queue 45deg right rotation spawnBtnRotationQueue.push({ angle: Math.PI / 4 }); processSpawnBtnRotationQueue(); spawnEnemy(); } }); } }); }; // Enemy tap (defeat) function onEnemyDown(x, y, obj) { if (!currentEnemy || !currentEnemy.isAlive) return; currentEnemy.hp -= 1; // Flash enemy tween(currentEnemy, { tint: 0xffffff }, { duration: 60, onFinish: function onFinish() { tween(currentEnemy, { tint: 0x2a6bde }, { duration: 60 }); } }); if (currentEnemy.hp <= 0) { defeatEnemy(); } } // Gold tap (collect) function onGoldDown(x, y, obj) { for (var i = golds.length - 1; i >= 0; i--) { var gold = golds[i]; if (gold && gold.containsPoint && gold.containsPoint({ x: x, y: y })) { collectGold(gold); golds.splice(i, 1); break; } } } // Upgrade button tap upgradeBtn.down = function (x, y, obj) { // Animate shrink tween.stop(upgradeBtn, { scaleX: true, scaleY: true }); tween(upgradeBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(upgradeBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut, onFinish: function onFinish() { // After animation, trigger action upgradeHero(); } }); } }); }; // Work button tap workBtn.down = function (x, y, obj) { if (!workBtnActive) return; // Prevent workBtn press if hero HP is not full if (typeof hero.currentHp === "number" && hero.currentHp < getStatsForLevel(heroLevel, "hero").hp) return; // Animate shrink tween.stop(workBtn, { scaleX: true, scaleY: true }); tween(workBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(workBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut, onFinish: function onFinish() { // After animation, trigger action // Calculate duration: let duration = Math.max(10000, ((level ** 1.2) * 60000) / (attackSpeed * attack)); var stats = getStatsForLevel(heroLevel, "hero"); var denominator = stats.atkSpd * stats.atk; var duration = 10; // Defensive minimum in seconds if (Number.isFinite(denominator) && denominator > 0) { duration = Math.max(10000, Math.pow(heroLevel, 1.2) * 60000 / denominator) / 1000; // ms to seconds } // Multiply duration by heroLevel (time level) duration = duration * heroLevel; workBtnActive = false; workBtnDuration = duration; workBtnTimeLeft = duration; setSpawnBtnEnabled(false); showWorkBtnCountdown(workBtnTimeLeft); // Start timer to update countdown if (workBtnTimer) { LK.clearInterval(workBtnTimer); workBtnTimer = null; } // Start rotation tween for workBtn at 20% of previous speed tween.stop(workBtn, { rotation: true }); workBtn.rotation = 0; // Calculate totalRotations for 20% speed (i.e., 1/5th the previous speed, so 1/5th the number of spins) var baseTotalRotations = 2 + Math.floor(workBtnDuration); var slowTotalRotations = Math.max(1, Math.round(baseTotalRotations * 0.2)); // at least 1 full spin tween(workBtn, { rotation: Math.PI * 2 * slowTotalRotations }, { duration: workBtnDuration * 1000, easing: tween.linear, onFinish: function onFinish() { workBtn.rotation = 0; // reset rotation to 0 for next use } }); workBtnTimer = LK.setInterval(function () { workBtnTimeLeft -= 0.1; if (workBtnTimeLeft < 0) workBtnTimeLeft = 0; showWorkBtnCountdown(workBtnTimeLeft); if (workBtnTimeLeft <= 0) { // Timer done LK.clearInterval(workBtnTimer); workBtnTimer = null; workBtnActive = true; setSpawnBtnEnabled(true); hideWorkBtnCountdown(); // Stop rotation tween and reset rotation tween.stop(workBtn, { rotation: true }); workBtn.rotation = 0; // Drop gold: (main character's level * attack speed + attack / 2) / random(1-5) var stats = getStatsForLevel(heroLevel, "hero"); var divisor = Math.floor(Math.random() * 5) + 1; var goldVal = heroLevel * stats.atkSpd + stats.atk / 2; var goldDrop = Math.max(1, Math.floor(goldVal / divisor)); // Calculate gold display position in game coordinates (top right, where goldTxt is) var goldDisplayGlobal = LK.gui.topRight.toGlobal({ x: goldTxt.x, y: goldTxt.y }); var goldDisplayGamePos = game.toLocal(goldDisplayGlobal); // Spawn gold under hero and animate to gold display for (var i = 0; i < goldDrop; i++) { var gold = new Gold(); gold.x = hero.x; gold.y = hero.y + hero.height / 2 + 60 + (Math.random() * 40 - 20); gold.scaleX = 1; gold.scaleY = 1; gold.alpha = 1; game.addChild(gold); golds.push(gold); // Animate to gold display (function (goldObj, idx) { // Retreat: move down a bit, then animate to gold display var retreatY = goldObj.y + 80 + (Math.random() * 30 - 15); goldObj.dropAnim(goldObj.x, retreatY, function () { LK.setTimeout(function () { goldObj.collectAnim(goldDisplayGamePos.x, goldDisplayGamePos.y, function () { goldAmount += 1; updateGoldDisplay(); goldObj.destroy(); }); }, 80 * idx); }); })(gold, i); } } }, 100); } }); } }); }; // --- Attach event handlers to game --- game.down = function (x, y, obj) { // If overlay is active, block all input except for the itemBag window and its X button if (typeof itemBagOverlay !== "undefined" && itemBagOverlay && itemBagOverlay.parent) { // Do nothing, block input return; } // Check if tap is on enemy if (currentEnemy && currentEnemy.isAlive && currentEnemy.containsPoint && currentEnemy.containsPoint({ x: x, y: y })) { onEnemyDown(x, y, obj); return; } // Check if tap is on any gold for (var i = golds.length - 1; i >= 0; i--) { var gold = golds[i]; if (gold && gold.containsPoint && gold.containsPoint({ x: x, y: y })) { collectGold(gold); golds.splice(i, 1); return; } } // (Buttons handled by their own .down) }; // --- Game update loop --- game.update = function () { // Remove golds that are invisible for (var i = golds.length - 1; i >= 0; i--) { var gold = golds[i]; if (gold.alpha <= 0.01) { gold.destroy(); golds.splice(i, 1); } } // --- Hero health refill logic --- if (typeof hero.healthRefilling === "undefined") hero.healthRefilling = false; if (typeof hero.refillStartTime === "undefined") hero.refillStartTime = 0; if (typeof hero.refillDuration === "undefined") hero.refillDuration = 5000; // Default, will be set below if (typeof hero.refillFromHp === "undefined") hero.refillFromHp = 0; if (typeof hero.refillToHp === "undefined") hero.refillToHp = 0; if (typeof hero.currentHp === "number" && hero.currentHp <= 0 && !hero.healthRefilling) { // Start refill hero.healthRefilling = true; hero.refillStartTime = Date.now(); var stats = getStatsForLevel(heroLevel, "hero"); hero.refillFromHp = 0; hero.refillToHp = stats.hp; // Set refill duration to 1/5th speed (5x slower) hero.refillDuration = 5000; // fallback var baseDuration = 1000; // original duration if (hero.currentHp <= 0) { hero.refillDuration = baseDuration * 10; // 10x slower if died } else { hero.refillDuration = baseDuration * 5; // 5x slower otherwise } // Destroy enemy immediately (so a new one can only be summoned after refill) if (currentEnemy && currentEnemy.isAlive) { currentEnemy.isAlive = false; currentEnemy.defeatAnim(function () { if (currentEnemy) { currentEnemy.destroy(); currentEnemy = null; updateEnemyStatsDisplay(); } }); } } if (hero.healthRefilling) { var now = Date.now(); var elapsed = now - hero.refillStartTime; var t = Math.min(1, elapsed / hero.refillDuration); var stats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = Math.round(hero.refillFromHp + (hero.refillToHp - hero.refillFromHp) * t); if (t >= 1) { hero.currentHp = stats.hp; hero.healthRefilling = false; } } // Prevent spawnBtn and workBtn from being pressed unless hero HP is full if (typeof hero.currentHp === "number" && hero.currentHp < getStatsForLevel(heroLevel, "hero").hp) { setSpawnBtnEnabled(false); // Disable workBtn and make it semi-transparent workBtn.alpha = 0.5; workBtn.interactive = false; workBtn.buttonMode = false; // --- Rotate spawnBtn to the right while hero HP is not full, but only if NO enemy is alive --- if (!spawnBtn._rotatingWhileNotFull && (!currentEnemy || !currentEnemy.isAlive)) { var _rotateRightLoop = function rotateRightLoop() { if (!spawnBtn._rotatingWhileNotFull) return; var startRot = spawnBtn.rotation; var endRot = startRot + Math.PI * 2; tween(spawnBtn, { rotation: endRot }, { duration: 1200, easing: tween.linear, onFinish: function onFinish() { // Continue loop if still not full and still no enemy if (spawnBtn._rotatingWhileNotFull && (!currentEnemy || !currentEnemy.isAlive)) { _rotateRightLoop(); } } }); }; tween.stop(spawnBtn, { rotation: true }); // Start continuous right rotation (1 full spin per 1.2s) spawnBtn._rotatingWhileNotFull = true; _rotateRightLoop(); } } else if (!hero.healthRefilling && workBtnActive) { setSpawnBtnEnabled(true); // Enable workBtn and restore full opacity workBtn.alpha = 1; workBtn.interactive = true; workBtn.buttonMode = true; // If hero HP is full, remove all effects and restore color tween.stop(hero, { tint: true, alpha: true, scaleX: true, scaleY: true }); hero.tint = 0xffffff; hero.alpha = 1; hero.scaleX = 1; hero.scaleY = 1; // --- Stop spawnBtn rotation and reset to original position, with 45deg right spin if HP just became full and no enemy is alive --- if (spawnBtn._rotatingWhileNotFull) { spawnBtn._rotatingWhileNotFull = false; tween.stop(spawnBtn, { rotation: true }); // If hero HP just became full and no enemy is alive, rotate 45deg right and then reset to 0 if ((!currentEnemy || !currentEnemy.isAlive) && typeof hero.currentHp === "number" && hero.currentHp === getStatsForLevel(heroLevel, "hero").hp) { // Animate 45deg right, then reset to 0 tween(spawnBtn, { rotation: spawnBtn.rotation + Math.PI / 4 }, { duration: 180, easing: tween.cubicOut, onFinish: function onFinish() { tween(spawnBtn, { rotation: 0 }, { duration: 200, easing: tween.cubicOut }); } }); } else { // Animate back to original rotation (0) tween(spawnBtn, { rotation: 0 }, { duration: 200, easing: tween.cubicOut }); } } } // Keep hero slightly lower than vertical center hero.y = 2732 / 2 + 200; // Keep enemy vertically centered and at far right if alive if (currentEnemy && currentEnemy.isAlive) { currentEnemy.x = 2048 - 200; currentEnemy.y = hero.y + 100; // Move enemy a little lower } updateHeroStatsDisplay(); updateEnemyStatsDisplay(); // Keep workBtnCountdownTxt positioned under workBtn if visible if (workBtnCountdownTxt && workBtnCountdownTxt.visible) { workBtnCountdownTxt.x = workBtn.x; workBtnCountdownTxt.y = workBtn.y + workBtn.height / 2 + 8; } }; // --- Initial UI state --- updateGoldDisplay(); updateUpgradeDisplay(); updateHeroStatsDisplay(); updateEnemyStatsDisplay();
===================================================================
--- original.js
+++ change.js
@@ -397,18 +397,15 @@
if (typeof itemBagOverlay !== "undefined" && itemBagOverlay && itemBagOverlay.parent) {
itemBagOverlay.parent.removeChild(itemBagOverlay);
itemBagOverlay = null;
}
- // Create overlay: fullscreen black, 100% opaque, blocks all input except the window
+ // Create overlay: fullscreen black, 100% opaque, blocks all input including all GUI/buttons
itemBagOverlay = new Container();
- // Four rectangles: top, left, right, bottom (all black, alpha 1)
var overlayAlpha = 1;
var gameW = 2048,
gameH = 2732;
var winWidth = 1000,
winHeight = 1000;
- var winX = gameW / 2,
- winY = gameH / 2;
var leftW = (gameW - winWidth) / 2;
var topH = (gameH - winHeight) / 2;
// Top
var overlayTop = LK.getAsset('centerCircle', {
@@ -461,12 +458,14 @@
y: topH
});
overlayRight.alpha = overlayAlpha;
itemBagOverlay.addChild(overlayRight);
- // Block all input on overlay
+ // Block all input on overlay, including all GUI/buttons
itemBagOverlay.interactive = true;
itemBagOverlay.down = function () {/* block all input */};
- // Add overlay to game (ensure it's above everything else)
+ itemBagOverlay.up = function () {/* block all input */};
+ itemBagOverlay.move = function () {/* block all input */};
+ // Add overlay to game (ensure it's above everything else, including GUI/buttons)
game.addChild(itemBagOverlay);
// Always bring overlay to top after adding
if (game.children && game.children.length > 1) {
game.setChildIndex(itemBagOverlay, game.children.length - 1);