/**** * 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; }); // Enemy2 class (new enemy type after level 10) var Enemy2 = Container.expand(function () { var self = Container.call(this); var enemyGfx = self.attachAsset('enemy2', { 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; }); // MadenResource class for madenBtn resource spawn/collect logic var MadenResource = Container.expand(function () { var self = Container.call(this); // Resource types and their values var types = [{ id: "hamdemir", value: 5 }, { id: "hamgumus", value: 50 }, { id: "hamaltin", value: 100 }, { id: "hammitril", value: 1000 }]; // Pick type (passed in or random) self.typeIdx = typeof arguments[0] === "number" ? arguments[0] : Math.floor(Math.random() * types.length); self.type = types[self.typeIdx]; // Attach asset var gfx = self.attachAsset(self.type.id, { anchorX: 0.5, anchorY: 0.5 }); // For animation self.scaleX = 0.7; self.scaleY = 0.7; // Animate pop out self.popAnim = function (fromX, fromY, toX, toY, onFinish) { self.x = fromX; self.y = fromY; self.alpha = 0.7; tween(self, { x: toX, y: toY, scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 220, easing: tween.bounceOut, onFinish: onFinish }); }; // Animate collect to itemBag 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 }); }; // Helper: check if point is inside self.containsPoint = function (pt) { var w = gfx.width || 100, h = gfx.height || 100; return pt.x >= self.x - w / 2 && pt.x <= self.x + w / 2 && pt.y >= self.y - h / 2 && pt.y <= self.y + h / 2; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222a36 }); /**** * Game Code ****/ // --- Gold drop amount table per level --- var goldDropByLevel = [ // Level 1 { min: 1, max: 5 }, // Level 2 { min: 3, max: 8 }, // Level 3 { min: 5, max: 12 }, // Level 4 { min: 8, max: 16 }, // Level 5 { min: 12, max: 20 }, // Level 6 { min: 15, max: 25 }, // Level 7 { min: 20, max: 32 }, // Level 8 { min: 25, max: 40 }, // Level 9 { min: 30, max: 48 }, // Level 10 { min: 35, max: 60 }]; // Defensive: If goldDropByLevel is referenced for higher levels, extend with scaled values (function extendGoldDropByLevel() { var last = goldDropByLevel[goldDropByLevel.length - 1]; for (var i = goldDropByLevel.length; i < 100; i++) { // Increase min/max by 10% per level after 10 var prev = goldDropByLevel[i - 1]; goldDropByLevel.push({ min: Math.round(prev.min * 1.1), max: Math.round(prev.max * 1.1) }); } })(); // --- Global State --- // new unique asset for leftBtn // Upgrade Button: orange box // Spawn Enemy Button: green box // Gold: yellow ellipse // Enemy: blue ellipse // Hero: red box, left side // Background images for each location (dummy ids, replace with real asset ids as needed) function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var backgroundImg = null; // Helper to create a scaled background asset (returns a dummy container for now) function getScaledBgAsset(bgId) { // Defensive: If bgId is not a valid asset, return a transparent container var bgAsset; try { bgAsset = LK.getAsset(bgId, { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, width: 2048, height: 2732 }); } catch (e) { bgAsset = new Container(); } return bgAsset; } // --- Set initial background to 'orman' (forest) --- backgroundImg = getScaledBgAsset('bg_orman'); game.addChildAt(backgroundImg, 0); // Add at bottom layer to ensure orman is visible at start // Show spawnBtn only for 'orman' and 'dağ' at game start if (typeof spawnBtn !== "undefined" && spawnBtn) { spawnBtn.visible = true; if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = true; } var hero = new Hero(); game.addChild(hero); var currentEnemy = null; var enemySpawnCount = 0; // Track how many enemies have been spawned var golds = []; var goldAmount = 0; var heroLevel = 1; // --- Inventory and Items --- var inventory = []; // Track equipped item upgrade levels (itemId -> level) var equippedItemUpgradeLevels = {}; var equippedItems = { "shield-1": false, "sword-1": false }; // --- Shield-1 barrier state --- var heroShield1Barrier = 0; // If >0, this is the current shield-1 barrier HP var heroShield1BarrierMax = 0; // Max barrier HP (100 if equipped) // Shield-1 and Sword-1 item data var itemData = { "shield-1": { name: "Shield-1", type: "shield", bonusHp: 250, // +250 extra HP atkSpdPenalty: 2, // -2 attack speed buyPrice: 50, sellPrice: 15 }, "sword-1": { name: "Kılıç-1", type: "sword", bonusAtk: 50, // +50 attack bonusAtkSpd: 1, // +1 attack speed buyPrice: 50, sellPrice: 15 }, "kazma": { name: "Kazma", type: "tool", bonusMine: 1, // future: can be used for mining bonus buyPrice: 250, sellPrice: 75 }, "hamdemir": { name: "Ham Demir", type: "maden", buyPrice: 0, sellPrice: 5 }, "hamgumus": { name: "Ham Gümüş", type: "maden", buyPrice: 0, sellPrice: 50 }, "hamaltin": { name: "Ham Altın", type: "maden", buyPrice: 0, sellPrice: 100 }, "hammitril": { name: "Ham Mitril", type: "maden", buyPrice: 0, sellPrice: 1000 } }; // --- GoldBag effect state --- var heroIsImmortal = false; var heroOneShotEnemies = false; // Auto-fight timer handles var heroAutoAttackTimer = null; var enemyAutoAttackTimer = null; // --- GUI Elements --- // Location display (top center, above upgradeBtn) var locationNames = { "bg_orman": "ORMAN", "bg_sehir": "ŞEHİR", "bg_dag": "DAĞ", "bg_demirci": "DEMİRCİ", "bg_maden": "MADEN", "bg_kale": "KALE", "bg_sahil": "SAHİL" }; var currentLocationId = "bg_orman"; var locationTxt = new Text2(locationNames[currentLocationId], { size: 70, fill: "#fff", glow: { color: 0x2a6bde, distance: 8, strength: 2 } }); locationTxt.anchor.set(0.5, 0); locationTxt.x = LK.gui.top.width / 2; locationTxt.y = 10; LK.gui.top.addChild(locationTxt); // 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: "#fff", glow: { color: 0x000000, distance: 12, strength: 4 }, fontWeight: "bold" }); 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: "#fff", glow: { color: 0x000000, distance: 12, strength: 4 }, fontWeight: "bold" }); 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 }); // New button to the left of upgradeBtn, with its own unique visual var leftBtn = LK.getAsset('leftBtn', { anchorX: 0.5, anchorY: 0.5 }); // Ensure leftBtn is added to the GUI (if not already) if (!leftBtn.parent) { LK.gui.top.addChild(leftBtn); } // Add shrink-grow animation to leftBtn when tapped, and show location list leftBtn.down = function (x, y, obj) { tween.stop(leftBtn, { scaleX: true, scaleY: true }); tween(leftBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(leftBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut, onFinish: function onFinish() { // Show location list after animation if (typeof locationListWindow !== "undefined" && locationListWindow && locationListWindow.parent) { locationListWindow.parent.removeChild(locationListWindow); locationListWindow = null; } // Hide leftBtn while window is open leftBtn.visible = false; // Create window container locationListWindow = new Container(); var winWidth = 700; var winHeight = 900; var winColor = 0x000000; var winAlpha = 0.85; 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; locationListWindow.addChild(winBg); // Add X close button to top right of window var closeBtnSize = 80; var closeBtn = LK.getAsset('centerCircle', { width: closeBtnSize, height: closeBtnSize, color: 0x222222, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: winWidth / 2 - closeBtnSize / 2 - 18, y: -winHeight / 2 + closeBtnSize / 2 + 18 }); closeBtn.alpha = 0.7; locationListWindow.addChild(closeBtn); var closeBtnTxt = new Text2("X", { size: 48, fill: "#fff" }); closeBtnTxt.anchor.set(0.5, 0.5); closeBtnTxt.x = closeBtn.x; closeBtnTxt.y = closeBtn.y; locationListWindow.addChild(closeBtnTxt); // Close logic for X button closeBtn.down = function () { if (locationListWindow && locationListWindow.parent) { locationListWindow.parent.removeChild(locationListWindow); locationListWindow = null; } // Restore leftBtn leftBtn.visible = true; }; // List of locations var locations = ["1. ORMAN", "2. ŞEHİR", "3. DAĞ", "4. DEMİRCİ", "5. MADEN", "6. KALE", "7. SAHİL"]; var btnHeight = 90; var btnWidth = winWidth - 120; var btnGap = 18; var startY = -winHeight / 2 + 120; for (var i = 0; i < locations.length; i++) { (function (idx) { var btnY = startY + idx * (btnHeight + btnGap); var locBtn = LK.getAsset('centerCircle', { width: btnWidth, height: btnHeight, color: 0x2a6bde, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 0, y: btnY }); locBtn.alpha = 0.92; locationListWindow.addChild(locBtn); var locTxt = new Text2(locations[idx], { size: 44, fill: "#fff" }); locTxt.anchor.set(0.5, 0.5); locTxt.x = locBtn.x; locTxt.y = locBtn.y; locationListWindow.addChild(locTxt); // Optionally: add tap handler for each location locBtn.down = function () { // Animate button for feedback tween.stop(locBtn, { scaleX: true, scaleY: true }); tween(locBtn, { scaleX: 0.93, scaleY: 0.93 }, { duration: 80, easing: tween.cubicIn, onFinish: function onFinish() { tween(locBtn, { scaleX: 1, scaleY: 1 }, { duration: 80, easing: tween.cubicOut }); } }); // Handle location selection and change background // Map each location to a unique background asset id var bgMap = ["bg_orman", // 1. ORMAN "bg_sehir", // 2. ŞEHİR "bg_dag", // 3. DAĞ "bg_demirci", // 4. DEMİRCİ "bg_maden", // 5. MADEN "bg_kale", // 6. KALE "bg_sahil" // 7. SAHİL ]; var selectedIdx = idx; var newBgId = bgMap[selectedIdx]; // Update currentLocationId and locationTxt currentLocationId = newBgId; if (locationTxt && locationNames[newBgId]) { locationTxt.setText(locationNames[newBgId]); } // Remove old background image if present if (backgroundImg && backgroundImg.parent) { backgroundImg.parent.removeChild(backgroundImg); backgroundImg.destroy(); } // Create new background image asset, scaled to fit the screen backgroundImg = getScaledBgAsset(newBgId); game.addChildAt(backgroundImg, 0); // Add at bottom layer // Show spawnBtn only for 'orman' and 'dağ', show demirciBtn for 'demirci', hide otherwise if (typeof spawnBtn !== "undefined" && spawnBtn) { if (newBgId === "bg_orman" || newBgId === "bg_dag") { spawnBtn.visible = true; if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = true; if (typeof demirciBtn !== "undefined" && demirciBtn) demirciBtn.visible = false; } else if (newBgId === "bg_demirci") { spawnBtn.visible = false; if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = false; if (typeof demirciBtn === "undefined" || !demirciBtn) { // Create demirciBtn if not already created demirciBtn = LK.getAsset('demirciBtn', { anchorX: 0.5, anchorY: 0.5, x: spawnBtn.x, y: spawnBtn.y }); demirciBtn.down = function (x, y, obj) { // Animate shrink/grow for feedback tween.stop(demirciBtn, { scaleX: true, scaleY: true }); tween(demirciBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(demirciBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut }); } }); // You can add demirci-specific logic here }; LK.gui.bottom.addChild(demirciBtn); } if (typeof demirciBtn !== "undefined" && demirciBtn) demirciBtn.visible = true; } else { spawnBtn.visible = false; if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = false; if (typeof demirciBtn !== "undefined" && demirciBtn) demirciBtn.visible = false; } } // Close the location list window if (locationListWindow && locationListWindow.parent) { locationListWindow.parent.removeChild(locationListWindow); locationListWindow = null; } // Restore leftBtn leftBtn.visible = true; }; })(i); } // Center in game area locationListWindow.x = 2048 / 2; locationListWindow.y = 2732 / 2; game.addChild(locationListWindow); } }); } }); }; // 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) { // Toggle immortal/one-shot state heroIsImmortal = !heroIsImmortal; heroOneShotEnemies = heroIsImmortal; // Optional: flash hero for feedback if (heroIsImmortal) { 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 }); } }); } else { // If disabling, reset hero color/scale tween.stop(hero, { tint: true, scaleX: true, scaleY: true }); hero.tint = 0xffffff; hero.scaleX = 1; hero.scaleY = 1; } }; // --- 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: "#fff", glow: { color: 0x000000, distance: 12, strength: 4 }, fontWeight: "bold" }); 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; // Move leftBtn, upgradeBtn, and workBtn further left as a group, keeping upgradeBtn centered relative to the new group var groupShift = 120; // Amount to shift all three buttons left // Place upgradeBtn at new center upgradeBtn.x = LK.gui.top.width / 2 - groupShift; upgradeBtn.y = 100 + upgradeBtn.height / 2; // Place leftBtn to the left of upgradeBtn, with a small gap leftBtn.x = upgradeBtn.x - upgradeBtn.width / 2 - leftBtn.width / 2 - 30; leftBtn.y = upgradeBtn.y; // 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: "#fff", glow: { color: 0x000000, distance: 12, strength: 4 }, fontWeight: "bold" }); 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(leftBtn); 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; // Maden special button (only visible in maden) var madenBtn = LK.getAsset('madenBtn', { anchorX: 0.5, anchorY: 0.5, x: spawnBtn.x, y: spawnBtn.y }); madenBtn.visible = false; // Kale special button (only visible in kale, no function) var kaleBtn = LK.getAsset('kaleBtn', { anchorX: 0.5, anchorY: 0.5, x: spawnBtn.x, y: spawnBtn.y }); kaleBtn.visible = false; // --- KaleBtn tap: rotate 90deg right, open window, rotate back on close --- var kaleWindow = null; kaleBtn.down = function (x, y, obj) { // Animate shrink/grow for feedback tween.stop(kaleBtn, { scaleX: true, scaleY: true }); tween(kaleBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(kaleBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut, onFinish: function onFinish() { // After shrink/grow, rotate 90deg right tween.stop(kaleBtn, { rotation: true }); tween(kaleBtn, { rotation: kaleBtn.rotation + Math.PI / 2 }, { duration: 180, easing: tween.cubicInOut, onFinish: function onFinish() { // Open window after rotation if (kaleWindow && kaleWindow.parent) { kaleWindow.parent.removeChild(kaleWindow); kaleWindow = null; } kaleBtn.visible = false; // Create window container kaleWindow = new Container(); var winWidth = 800; var winHeight = 600; var winColor = 0x222222; var winAlpha = 0.92; 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; kaleWindow.addChild(winBg); // Add X close button to top right of window var closeBtnSize = 80; var closeBtn = LK.getAsset('centerCircle', { width: closeBtnSize, height: closeBtnSize, color: 0x444444, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: winWidth / 2 - closeBtnSize / 2 - 18, y: -winHeight / 2 + closeBtnSize / 2 + 18 }); closeBtn.alpha = 0.7; kaleWindow.addChild(closeBtn); var closeBtnTxt = new Text2("X", { size: 48, fill: "#fff" }); closeBtnTxt.anchor.set(0.5, 0.5); closeBtnTxt.x = closeBtn.x; closeBtnTxt.y = closeBtn.y; kaleWindow.addChild(closeBtnTxt); // Close logic for X button closeBtn.down = function () { if (kaleWindow && kaleWindow.parent) { kaleWindow.parent.removeChild(kaleWindow); kaleWindow = null; } // Rotate back 90deg left and show kaleBtn tween.stop(kaleBtn, { rotation: true }); tween(kaleBtn, { rotation: kaleBtn.rotation - Math.PI / 2 }, { duration: 180, easing: tween.cubicInOut, onFinish: function onFinish() { kaleBtn.visible = true; } }); }; // Center window in game area kaleWindow.x = 2048 / 2; kaleWindow.y = 2732 / 2; game.addChild(kaleWindow); } }); } }); } }); }; LK.gui.bottom.addChild(kaleBtn); // --- MadenBtn resource spawn/collect logic --- var madenResourceTypes = [{ id: "hamdemir", value: 5 }, { id: "hamgumus", value: 50 }, { id: "hamaltin", value: 100 }, { id: "hammitril", value: 1000 }]; var madenActiveResource = null; var madenResourceTimeout = null; madenBtn.down = function (x, y, obj) { // Check if kazma is in inventory var hasKazma = false; for (var i = 0; i < inventory.length; i++) { if (inventory[i] === "kazma") { hasKazma = true; break; } } if (!hasKazma) { // Animate button for feedback tween.stop(madenBtn, { scaleX: true, scaleY: true }); tween(madenBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(madenBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut }); } }); // Show message: "Kazmaya ihtiyacın var" if (typeof madenBtnMsg === "undefined" || !madenBtnMsg || madenBtnMsg.destroyed) { madenBtnMsg = new Text2("Kazmaya ihtiyacın var", { size: 60, fill: "#fff", glow: { color: 0x000000, distance: 10, strength: 2 } }); madenBtnMsg.anchor.set(0.5, 0.5); madenBtnMsg.x = 2048 / 2; madenBtnMsg.y = 2732 / 2 + 400; game.addChild(madenBtnMsg); } madenBtnMsg.visible = true; madenBtnMsg.alpha = 1; // Fade out after 1.2s tween(madenBtnMsg, { alpha: 0 }, { duration: 1200, onFinish: function onFinish() { if (madenBtnMsg) madenBtnMsg.visible = false; } }); return; } // Animate shrink/grow for feedback tween.stop(madenBtn, { scaleX: true, scaleY: true }); tween(madenBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(madenBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut }); } }); // If resources are already active, ignore further clicks if (madenActiveResource && madenActiveResource.length > 0) return; // --- Custom drop logic: drop up to 4 resources, each with its own probability --- // Probabilities (cumulative for easier logic): // hammitril (1000): 5% // hamaltin (100): 25% // hamgumus (50): 50% // hamdemir (5): 95% // We'll try to drop each, but only if the random roll is within the chance. var centerX = 2048 / 2; var centerY = 2732 / 2; madenActiveResource = []; var madenResourceTimeouts = []; var oldGameDown = game.down; // --- Ava: Reduce drop rates by half, and increase with kazma upgrade level --- // Get kazma upgrade level (0 if not upgraded) var kazmaUpgradeLevel = equippedItemUpgradeLevels && equippedItemUpgradeLevels["kazma"] ? equippedItemUpgradeLevels["kazma"] : 0; // Each upgrade level increases drop rates by 10% of original (not compounded, capped at 100%) var upgradeBonus = kazmaUpgradeLevel * 0.1; // Base drop rates halved var dropTable = [{ typeIdx: 3, chance: Math.min(1, 0.025 + 0.05 * upgradeBonus) // hammitril (1000) }, { typeIdx: 2, chance: Math.min(1, 0.125 + 0.25 * upgradeBonus) // hamaltin (100) }, { typeIdx: 1, chance: Math.min(1, 0.25 + 0.5 * upgradeBonus) // hamgumus (50) }, { typeIdx: 0, chance: Math.min(1, 0.475 + 0.95 * upgradeBonus) // hamdemir (5) } // hamdemir (5) ]; // For each resource type, roll and drop if passed for (var i = 0; i < dropTable.length; i++) { var entry = dropTable[i]; if (Math.random() < entry.chance) { var fromX = centerX; var fromY = centerY; var toX = centerX; var toY = centerY; var resource = new MadenResource(entry.typeIdx); resource.x = fromX; resource.y = fromY; game.addChild(resource); resource.popAnim(fromX, fromY, toX, toY); (function (resource, idx) { var itemBagGlobal = LK.gui.bottom.toGlobal({ x: itemBagImg.x, y: itemBagImg.y }); var itemBagGamePos = game.toLocal(itemBagGlobal); LK.setTimeout(function () { resource.collectAnim(itemBagGamePos.x, itemBagGamePos.y, function () { inventory.push(resource.type.id); resource.destroy(); var idxInArr = madenActiveResource.indexOf(resource); if (idxInArr !== -1) madenActiveResource.splice(idxInArr, 1); if (madenActiveResource.length === 0) { game.down = oldGameDown; } }); }, 250 + Math.floor(Math.random() * 100)); resource._timeoutIdx = idx; madenActiveResource.push(resource); })(resource, i); } } // No tap handler needed, auto-collects }; LK.gui.bottom.addChild(madenBtn); // Demirci button (hidden by default, shown only in demirci) var demirciBtn = LK.getAsset('demirciBtn', { anchorX: 0.5, anchorY: 0.5, x: spawnBtn.x, y: spawnBtn.y }); demirciBtn.visible = false; demirciBtn.down = function (x, y, obj) { // Animate shrink/grow for feedback tween.stop(demirciBtn, { scaleX: true, scaleY: true }); tween(demirciBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { tween(demirciBtn, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.cubicOut }); } }); // --- Show equipped items window with upgrade buttons --- if (typeof equippedItemsWindow !== "undefined" && equippedItemsWindow && equippedItemsWindow.parent) { equippedItemsWindow.parent.removeChild(equippedItemsWindow); equippedItemsWindow = null; } // Hide demirciBtn while window is open demirciBtn.visible = false; // Create window container equippedItemsWindow = new Container(); var winWidth = 900; var winHeight = 700; var winColor = 0x222222; var winAlpha = 0.92; 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; equippedItemsWindow.addChild(winBg); // --- Small single-row window for 'Kazma' under main demirci window --- var kazmaWinWidth = 600; var kazmaWinHeight = 90; var kazmaWinColor = 0x111111; var kazmaWinAlpha = 0.95; var kazmaWinY = winHeight / 2 + kazmaWinHeight / 2 + 18; // just below main window var kazmaWindow = new Container(); var kazmaBg = LK.getAsset('centerCircle', { width: kazmaWinWidth, height: kazmaWinHeight, color: kazmaWinColor, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 0, y: kazmaWinY }); kazmaBg.alpha = kazmaWinAlpha; kazmaWindow.addChild(kazmaBg); // "Kazma" label var kazmaLabel = new Text2("Kazma", { size: 44, fill: "#fff" }); kazmaLabel.anchor.set(0, 0.5); kazmaLabel.x = -kazmaWinWidth / 2 + 30; kazmaLabel.y = kazmaWinY; kazmaWindow.addChild(kazmaLabel); // Price label var kazmaPrice = new Text2("250 altın", { size: 40, fill: 0xFFE066 }); kazmaPrice.anchor.set(0, 0.5); kazmaPrice.x = kazmaLabel.x + 180; kazmaPrice.y = kazmaWinY; kazmaWindow.addChild(kazmaPrice); // "Satın Al" button var satinAlBtnWidth = 180; var satinAlBtnHeight = 70; var satinAlBtn = LK.getAsset('centerCircle', { width: satinAlBtnWidth, height: satinAlBtnHeight, color: 0x2a6bde, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: kazmaWinWidth / 2 - satinAlBtnWidth / 2 - 20, y: kazmaWinY }); satinAlBtn.alpha = 0.92; kazmaWindow.addChild(satinAlBtn); var satinAlTxt = new Text2("Satın Al", { size: 38, fill: "#fff" }); satinAlTxt.anchor.set(0.5, 0.5); satinAlTxt.x = satinAlBtn.x; satinAlTxt.y = satinAlBtn.y; kazmaWindow.addChild(satinAlTxt); // Animate button on tap and handle buy logic for kazma satinAlBtn.down = function () { tween.stop(satinAlBtn, { scaleX: true, scaleY: true }); tween(satinAlBtn, { scaleX: 0.9, scaleY: 0.9 }, { duration: 80, easing: tween.cubicIn, onFinish: function onFinish() { tween(satinAlBtn, { scaleX: 1, scaleY: 1 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { // Buy logic for kazma var kazmaPriceVal = itemData["kazma"] ? itemData["kazma"].buyPrice : 250; // Check if already owned var alreadyOwned = false; for (var i = 0; i < inventory.length; i++) { if (inventory[i] === "kazma") { alreadyOwned = true; break; } } if (alreadyOwned) { // Flash button red if already owned tween(satinAlBtn, { tint: 0xff4444 }, { duration: 120, onFinish: function onFinish() { tween(satinAlBtn, { tint: 0x2a6bde }, { duration: 120 }); } }); return; } if (goldAmount < kazmaPriceVal) { // Flash button red if not enough gold tween(satinAlBtn, { tint: 0xff4444 }, { duration: 120, onFinish: function onFinish() { tween(satinAlBtn, { tint: 0x2a6bde }, { duration: 120 }); } }); return; } // Deduct gold, add kazma to inventory (do NOT auto-equip) goldAmount -= kazmaPriceVal; updateGoldDisplay(); inventory.push("kazma"); // Refresh demirci window to show new inventory state if (equippedItemsWindow && equippedItemsWindow.parent) { equippedItemsWindow.parent.removeChild(equippedItemsWindow); equippedItemsWindow = null; } demirciBtn.down(); } }); } }); }; // Add kazmaWindow to equippedItemsWindow equippedItemsWindow.addChild(kazmaWindow); // Add X close button to bottom center of window var closeBtnSize = 90; var closeBtn = LK.getAsset('centerCircle', { width: closeBtnSize, height: closeBtnSize, color: 0x444444, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 0, y: winHeight / 2 - closeBtnSize / 2 - 20 }); closeBtn.alpha = 0.7; equippedItemsWindow.addChild(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; equippedItemsWindow.addChild(closeBtnTxt); // Close logic for X button closeBtn.down = function () { if (equippedItemsWindow && equippedItemsWindow.parent) { equippedItemsWindow.parent.removeChild(equippedItemsWindow); equippedItemsWindow = null; } // Restore demirciBtn demirciBtn.visible = true; }; // --- List equipped items with upgrade buttons --- var equippedList = []; for (var itemId in equippedItems) { if (equippedItems[itemId]) equippedList.push(itemId); } var itemRowHeight = 180; var itemIconSize = 120; var btnWidth = 220; var btnHeight = 80; var fontSize = 44; var startY = -winHeight / 2 + 120; if (equippedList.length === 0) { var noEqTxt = new Text2("Kuşanılan eşya yok!", { size: 54, fill: "#fff" }); noEqTxt.anchor.set(0.5, 0.5); noEqTxt.x = 0; noEqTxt.y = 0; equippedItemsWindow.addChild(noEqTxt); } else { for (var i = 0; i < equippedList.length; i++) { (function (idx) { var itemId = equippedList[idx]; var data = itemData[itemId]; // Icon var icon = LK.getAsset(itemId, { anchorX: 0.5, anchorY: 0.5, x: -winWidth / 2 + itemIconSize / 2 + 60, y: startY + idx * itemRowHeight + itemIconSize / 2, width: itemIconSize, height: itemIconSize }); equippedItemsWindow.addChild(icon); // Name and stats var labelText = data ? data.name : itemId; var label = new Text2(labelText, { size: fontSize, fill: "#fff" }); label.anchor.set(0, 0.5); label.x = icon.x + itemIconSize / 2 + 30; label.y = icon.y; equippedItemsWindow.addChild(label); // Show upgrade bonus next to item name var upgradeLevel = equippedItemUpgradeLevels[itemId] || 0; var bonusText = ""; if (itemId === "shield-1") { var base = 250; var bonus = Math.round(base * (1 + 0.1 * upgradeLevel)); bonusText = "Bariyer: +" + bonus; } else if (itemId === "sword-1") { var base = itemData["sword-1"].bonusAtk; var bonus = Math.round(base * (1 + 0.1 * upgradeLevel)); bonusText = "Bonus: +" + bonus; } if (bonusText) { var bonusTxt = new Text2(bonusText, { size: 32, fill: 0xFFE066 }); bonusTxt.anchor.set(0, 0.5); bonusTxt.x = label.x; bonusTxt.y = label.y + 44; equippedItemsWindow.addChild(bonusTxt); } // Upgrade button var upgradeBtnEq = LK.getAsset('upgradeBtn', { anchorX: 0.5, anchorY: 0.5, x: label.x + 350, y: icon.y, width: btnWidth, height: btnHeight }); equippedItemsWindow.addChild(upgradeBtnEq); var upgradeTxt = new Text2("Yükselt", { size: fontSize, fill: "#fff" }); upgradeTxt.anchor.set(0.5, 0.5); upgradeTxt.x = upgradeBtnEq.x; upgradeTxt.y = upgradeBtnEq.y; equippedItemsWindow.addChild(upgradeTxt); // Show current upgrade level (if any) if (typeof equippedItemUpgradeLevels === "undefined") window.equippedItemUpgradeLevels = {}; if (typeof equippedItemUpgradeLevels[itemId] === "undefined") equippedItemUpgradeLevels[itemId] = 0; var upgradeLevel = equippedItemUpgradeLevels[itemId]; var levelTxt = new Text2("Seviye: " + (upgradeLevel + 1), { size: 36, fill: 0xFFE066 }); levelTxt.anchor.set(0, 0.5); levelTxt.x = upgradeBtnEq.x + btnWidth / 2 + 30; levelTxt.y = upgradeBtnEq.y; equippedItemsWindow.addChild(levelTxt); // Upgrade logic upgradeBtnEq.down = function () { // Cost: 20 * (upgradeLevel+1) var cost = 20 * (equippedItemUpgradeLevels[itemId] + 1); if (goldAmount < cost) { // Flash gold text red tween(goldTxt, { tint: 0xff4444 }, { duration: 120, onFinish: function onFinish() { tween(goldTxt, { tint: 0xFFE066 }, { duration: 120 }); } }); return; } goldAmount -= cost; equippedItemUpgradeLevels[itemId]++; updateGoldDisplay(); // Optionally: flash upgradeBtnEq tween(upgradeBtnEq, { scaleX: 1.15, scaleY: 1.15 }, { duration: 120, onFinish: function onFinish() { tween(upgradeBtnEq, { scaleX: 1, scaleY: 1 }, { duration: 120 }); } }); // Refresh window to update level text if (equippedItemsWindow && equippedItemsWindow.parent) { equippedItemsWindow.parent.removeChild(equippedItemsWindow); equippedItemsWindow = null; } demirciBtn.down(); }; })(i); } } // Center in game area equippedItemsWindow.x = 2048 / 2; equippedItemsWindow.y = 2732 / 2; game.addChild(equippedItemsWindow); }; LK.gui.bottom.addChild(demirciBtn); // Add "find enemy!" text above the spawn button var findEnemyTxt = new Text2("find enemy!", { size: 45, fill: "#fff", glow: { color: 0x000000, distance: 12, strength: 4 }, fontWeight: "bold" }); 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; } // 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 bottom center 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: 0, 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); // --- Hide spawnBtn, demirciBtn, workBtn, upgradeBtn, leftBtn, and all on-screen texts when X is visible --- spawnBtn.visible = false; if (typeof demirciBtn !== "undefined" && demirciBtn) demirciBtn.visible = false; workBtn.visible = false; upgradeBtn.visible = false; leftBtn.visible = false; findEnemyTxt.visible = false; upgradeCostTxt.visible = false; heroStatsTxt.visible = false; enemyStatsTxt.visible = false; goldTxt.visible = false; goldBagImg.visible = false; if (workBtnCountdownTxt) workBtnCountdownTxt.visible = false; // Close logic for X button closeBtn.down = function () { if (itemBagWindow && itemBagWindow.parent) { itemBagWindow.parent.removeChild(itemBagWindow); itemBagWindow = null; } // Restore all UI elements if (typeof demirciBtn !== "undefined" && demirciBtn && demirciBtn.parent && demirciBtn.visible === false) { // Only show demirciBtn if spawnBtn would be hidden (i.e. in demirci) if (backgroundImg && backgroundImg.assetId === "bg_demirci") { demirciBtn.visible = true; spawnBtn.visible = false; } else { demirciBtn.visible = false; spawnBtn.visible = true; } } else { spawnBtn.visible = true; } workBtn.visible = true; upgradeBtn.visible = true; leftBtn.visible = true; findEnemyTxt.visible = true; upgradeCostTxt.visible = true; heroStatsTxt.visible = true; enemyStatsTxt.visible = true; goldTxt.visible = true; goldBagImg.visible = true; if (workBtnCountdownTxt && workBtnActive === false && workBtnTimeLeft > 0) { workBtnCountdownTxt.visible = true; } }; // Center in game area itemBagWindow.x = 2048 / 2; itemBagWindow.y = 2732 / 2; // Add to game game.addChild(itemBagWindow); // (Removed: close window on tap anywhere on window. Now only X closes the window) // --- Inventory UI inside itemBagWindow --- // Remove any previous inventory UI if (typeof itemBagInventoryUI !== "undefined" && itemBagInventoryUI && itemBagInventoryUI.parent) { itemBagInventoryUI.parent.removeChild(itemBagInventoryUI); itemBagInventoryUI = null; } // --- Tabbed UI for inventory: "Ekipmanlar", "Öğeler", "Kuşandıklarım" --- itemBagInventoryUI = new Container(); var tabBarHeight = 90; var tabBarY = -winHeight / 2 + tabBarHeight / 2 + 10; var tabBarWidth = winWidth - 120; var tabBtnWidth = (tabBarWidth - 20) / 3; var tabBtnHeight = tabBarHeight - 10; var tabFontSize = 38; var tabActiveColor = 0x2a6bde; var tabInactiveColor = 0x444444; var tabTextColor = "#fff"; var tabNames = ["Ekipmanlar", "Öğeler", "Kuşandıklarım"]; var tabSelected = 0; // 0: ekipmanlar, 1: öğeler, 2: kuşandıklarım // Tab buttons var tabBtns = []; for (var t = 0; t < 3; t++) { (function (tabIdx) { var tabBtn = LK.getAsset('centerCircle', { width: tabBtnWidth, height: tabBtnHeight, color: tabIdx === tabSelected ? tabActiveColor : tabInactiveColor, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: -tabBarWidth / 2 + tabBtnWidth / 2 + tabIdx * (tabBtnWidth + 10), y: tabBarY }); tabBtn.alpha = 0.92; itemBagInventoryUI.addChild(tabBtn); var tabTxt = new Text2(tabNames[tabIdx], { size: tabFontSize, fill: tabTextColor }); tabTxt.anchor.set(0.5, 0.5); tabTxt.x = tabBtn.x; tabTxt.y = tabBtn.y; itemBagInventoryUI.addChild(tabTxt); tabBtns.push({ btn: tabBtn, txt: tabTxt }); tabBtn.down = function () { if (tabSelected === tabIdx) return; tabSelected = tabIdx; // Update tab colors for (var k = 0; k < tabBtns.length; k++) { tabBtns[k].btn.color = k === tabSelected ? tabActiveColor : tabInactiveColor; tabBtns[k].btn.alpha = 0.92; tabBtns[k].txt.fill = tabTextColor; } // Remove old list if exists if (typeof itemBagListUI !== "undefined" && itemBagListUI && itemBagListUI.parent) { itemBagListUI.parent.removeChild(itemBagListUI); itemBagListUI = null; } renderItemBagList(); }; })(t); } // --- List UI container (will be replaced on tab switch) --- var itemBagListUI = null; function renderItemBagList() { if (itemBagListUI && itemBagListUI.parent) { itemBagListUI.parent.removeChild(itemBagListUI); itemBagListUI = null; } itemBagListUI = new Container(); var itemListStartY = tabBarY + tabBarHeight / 2 + 20; var itemListStartX = -winWidth / 2 + 60; var itemRowHeight = 140; var itemIconSize = 100; var btnWidth = 160; var btnHeight = 70; var btnGap = 18; var fontSize = 38; // Build a count of each item in inventory, and track equipped index for each type var itemStackMap = {}; // itemId -> array of {idx, equipped} for (var i = 0; i < inventory.length; i++) { var id = inventory[i]; if (!itemStackMap[id]) itemStackMap[id] = []; // If this is equipped and not already marked, mark as equipped var isEquipped = false; if (equippedItems[id]) { // Only one equipped per type, so only one stack can be equipped var alreadyEquipped = false; for (var s = 0; s < itemStackMap[id].length; s++) { if (itemStackMap[id][s].equipped) alreadyEquipped = true; } if (!alreadyEquipped) isEquipped = true; } itemStackMap[id].push({ idx: i, equipped: isEquipped }); } // For each item type, create a stack for equipped and for each group of unequipped var stackRows = []; for (var id in itemStackMap) { var stack = itemStackMap[id]; // Find equipped var equippedIdx = -1; for (var s = 0; s < stack.length; s++) { if (stack[s].equipped) equippedIdx = stack[s].idx; } if (equippedIdx !== -1) { stackRows.push({ itemId: id, count: 1, equipped: true, indices: [equippedIdx] }); } // Now, group unequipped into stacks (could be more than one stack if equipped is in the middle) var unequippedIndices = []; for (var s = 0; s < stack.length; s++) { if (!stack[s].equipped) unequippedIndices.push(stack[s].idx); } if (unequippedIndices.length > 0) { stackRows.push({ itemId: id, count: unequippedIndices.length, equipped: false, indices: unequippedIndices }); } } // Filter stackRows by tab var filteredRows = []; if (tabSelected === 0) { // Ekipmanlar: only equipment (kalkan, kılıç, kazma, etc), regardless of equipped state for (var r = 0; r < stackRows.length; r++) { var id = stackRows[r].itemId; var data = itemData[id]; if (data && (data.type === "shield" || data.type === "sword" || data.type === "tool")) { filteredRows.push(stackRows[r]); } } } else if (tabSelected === 1) { // Öğeler: only non-equipment (ores, etc) for (var r = 0; r < stackRows.length; r++) { var id = stackRows[r].itemId; var data = itemData[id]; if (data && data.type === "maden") { filteredRows.push(stackRows[r]); } } } else if (tabSelected === 2) { // Kuşandıklarım: only equipped items (equipment) for (var r = 0; r < stackRows.length; r++) { var id = stackRows[r].itemId; var data = itemData[id]; if (stackRows[r].equipped && data && (data.type === "shield" || data.type === "sword" || data.type === "tool")) { filteredRows.push(stackRows[r]); } } } if (filteredRows.length === 0) { var noItemTxt = new Text2(tabSelected === 0 ? "Kuşanılan eşya yok!" : "Kuşanılmayan eşya yok!", { size: 48, fill: "#fff" }); noItemTxt.anchor.set(0.5, 0.5); noItemTxt.x = 0; noItemTxt.y = 0; itemBagListUI.addChild(noItemTxt); } else { for (var row = 0; row < filteredRows.length; row++) { (function (rowIdx) { var stack = filteredRows[rowIdx]; var itemId = stack.itemId; var data = itemData[itemId]; var count = stack.count; var isEquipped = stack.equipped; // Icon var icon = LK.getAsset(itemId, { anchorX: 0.5, anchorY: 0.5, x: itemListStartX + itemIconSize / 2, y: itemListStartY + rowIdx * itemRowHeight + itemIconSize / 2, width: itemIconSize, height: itemIconSize }); itemBagListUI.addChild(icon); // Name and stats, show count and equipped var labelText = data ? data.name : itemId; if (count > 1) labelText += " x" + count; if (isEquipped) labelText += " (Kuşanıldı)"; var label = new Text2(labelText, { size: fontSize, fill: "#fff" }); label.anchor.set(0, 0.5); label.x = icon.x + itemIconSize / 2 + 20; label.y = icon.y; itemBagListUI.addChild(label); // Equip/Remove button (only for equipped or first unequipped stack) // Only show for items that are not maden (raw ores) var isMaden = itemId === "hamdemir" || itemId === "hamgumus" || itemId === "hamaltin" || itemId === "hammitril"; var showEquipBtn = !isMaden && (!isEquipped && !equippedItems[itemId] || isEquipped); // Define equipBtn and equipTxt before using them var equipBtn = LK.getAsset('centerCircle', { width: btnWidth, height: btnHeight, color: isEquipped ? 0x8B4513 : 0x2a6bde, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: label.x + btnWidth / 2 + 30, y: icon.y }); equipBtn.alpha = 0.92; itemBagListUI.addChild(equipBtn); var equipTxt = new Text2(isEquipped ? "Çıkart" : "Kuşan", { size: fontSize, fill: "#fff" }); equipTxt.anchor.set(0.5, 0.5); equipTxt.x = equipBtn.x; equipTxt.y = equipBtn.y; itemBagListUI.addChild(equipTxt); equipBtn.visible = showEquipBtn; equipTxt.visible = showEquipBtn; // Equip/Remove logic equipBtn.down = function () { if (isMaden) return; // Do nothing for maden types // --- Ava: Kazma kuşanma/çıkarma ve diğer ekipmanlarla etkileşim --- // Helper: unequip all equipment except the given itemId function unequipAllExcept(itemIdToKeep) { for (var k in equippedItems) { if (k !== itemIdToKeep && equippedItems[k]) { equippedItems[k] = false; if (typeof hero.equippedVisuals !== "undefined" && hero.equippedVisuals[k]) { hero.removeChild(hero.equippedVisuals[k]); hero.equippedVisuals[k].destroy(); hero.equippedVisuals[k] = null; } // Shield-1 barrier reset if shield unequipped if (k === "shield-1") { heroShield1Barrier = 0; heroShield1BarrierMax = 0; } } } } // Helper: re-equip all equipment except kazma function reEquipAllExceptKazma() { for (var k in equippedItems) { if (k !== "kazma" && inventory.indexOf(k) !== -1 && !equippedItems[k]) { equippedItems[k] = true; // Add visual if not present if (typeof hero.equippedVisuals === "undefined") hero.equippedVisuals = {}; if (!hero.equippedVisuals[k]) { var equipVisual; if (k === "shield-1") { equipVisual = LK.getAsset(k, { anchorX: 0.5, anchorY: 0.5, x: 240, y: 0, width: 300, height: 698 }); } else if (k === "sword-1") { equipVisual = LK.getAsset(k, { anchorX: 0.5, anchorY: 0.5, x: -120, y: 320, width: 320, height: 1550 }); equipVisual.rotation = -Math.PI / 3; } else { equipVisual = LK.getAsset(k, { anchorX: 0.5, anchorY: 0.5, x: 90, y: 0, width: 320, height: 320 }); } hero.addChild(equipVisual); hero.equippedVisuals[k] = equipVisual; // Shield-1 barrier logic if (k === "shield-1") { var baseBarrier = 250; var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0; if (shieldUpgradeLevel > 0) { baseBarrier = Math.round(baseBarrier * (1 + 0.1 * shieldUpgradeLevel)); } heroShield1Barrier = baseBarrier; heroShield1BarrierMax = baseBarrier; } } } } } if (!isEquipped) { // --- Equip logic --- // If equipping kazma, unequip all other equipment if (itemId === "kazma") { unequipAllExcept("kazma"); } else { // If kazma is equipped, unequip it before equipping another if (equippedItems["kazma"]) { equippedItems["kazma"] = false; if (typeof hero.equippedVisuals !== "undefined" && hero.equippedVisuals["kazma"]) { hero.removeChild(hero.equippedVisuals["kazma"]); hero.equippedVisuals["kazma"].destroy(); hero.equippedVisuals["kazma"] = null; } } // Unequip all of this type (original logic) for (var k in equippedItems) { if (itemData[k] && itemData[k].type === data.type) { equippedItems[k] = false; if (typeof hero.equippedVisuals !== "undefined" && hero.equippedVisuals[k]) { hero.removeChild(hero.equippedVisuals[k]); hero.equippedVisuals[k].destroy(); hero.equippedVisuals[k] = null; } } } } equippedItems[itemId] = true; // Show item visual on hero (front) if (typeof hero.equippedVisuals === "undefined") hero.equippedVisuals = {}; if (hero.equippedVisuals[itemId]) { hero.removeChild(hero.equippedVisuals[itemId]); hero.equippedVisuals[itemId].destroy(); hero.equippedVisuals[itemId] = null; } var equipVisual; if (itemId === "shield-1") { equipVisual = LK.getAsset(itemId, { anchorX: 0.5, anchorY: 0.5, x: 240, y: 0, width: 300, height: 698 }); } else if (itemId === "sword-1") { equipVisual = LK.getAsset(itemId, { anchorX: 0.5, anchorY: 0.5, x: -120, y: 320, width: 320, height: 1550 }); equipVisual.rotation = -Math.PI / 3; } else if (itemId === "kazma") { try { equipVisual = LK.getAsset('kazma', { anchorX: 0.5, anchorY: 0.5, x: -120, y: 220, width: 640, height: Math.round(1550 / 3 * 2) }); equipVisual.rotation = -Math.PI / 2; } catch (e) { equipVisual = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: -120, y: 220, width: 640, height: Math.round(1550 / 3 * 2), color: 0x888888, shape: "box" }); equipVisual.rotation = -Math.PI / 2; } } else { equipVisual = LK.getAsset(itemId, { anchorX: 0.5, anchorY: 0.5, x: 90, y: 0, width: 320, height: 320 }); } hero.addChild(equipVisual); hero.equippedVisuals[itemId] = equipVisual; // Shield-1 barrier logic if (itemId === "shield-1") { var baseBarrier = 250; var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0; if (shieldUpgradeLevel > 0) { baseBarrier = Math.round(baseBarrier * (1 + 0.1 * shieldUpgradeLevel)); } heroShield1Barrier = baseBarrier; heroShield1BarrierMax = baseBarrier; } updateHeroStatsDisplay(); if (itemBagWindow && itemBagWindow.parent) { itemBagWindow.parent.removeChild(itemBagWindow); itemBagWindow = null; } itemBagImg.down(); } else { // --- Remove (Çıkart) logic --- equippedItems[itemId] = false; if (typeof hero.equippedVisuals !== "undefined" && hero.equippedVisuals[itemId]) { hero.removeChild(hero.equippedVisuals[itemId]); hero.equippedVisuals[itemId].destroy(); hero.equippedVisuals[itemId] = null; } if (itemId === "shield-1") { heroShield1Barrier = 0; heroShield1BarrierMax = 0; } // If kazma is being removed, re-equip all other equipment that is in inventory if (itemId === "kazma") { reEquipAllExceptKazma(); } updateHeroStatsDisplay(); if (itemBagWindow && itemBagWindow.parent) { itemBagWindow.parent.removeChild(itemBagWindow); itemBagWindow = null; } itemBagImg.down(); } }; // Sell button var sellBtn = LK.getAsset('centerCircle', { width: btnWidth, height: btnHeight, color: 0x8B4513, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: equipBtn.x + btnWidth + btnGap, y: icon.y }); sellBtn.alpha = 0.85; itemBagListUI.addChild(sellBtn); var sellTxt = new Text2("Sat (" + (data ? data.sellPrice : 1) + ")", { size: fontSize, fill: "#fff" }); sellTxt.anchor.set(0.5, 0.5); sellTxt.x = sellBtn.x; sellTxt.y = sellBtn.y; itemBagListUI.addChild(sellTxt); // Sell logic sellBtn.down = function () { // If this stack is equipped, and only one exists, prevent selling if (isEquipped && count === 1) { tween(sellBtn, { scaleX: 1.15, scaleY: 1.15, tint: 0xff4444 }, { duration: 120, onFinish: function onFinish() { tween(sellBtn, { scaleX: 1, scaleY: 1, tint: 0x8B4513 }, { duration: 120 }); } }); return; } // Remove one from inventory (from this stack) var removedIdx = -1; for (var j = 0; j < stack.indices.length; j++) { var idx = stack.indices[j]; // If equipped, skip if this is the equipped one if (isEquipped && count === 1) continue; removedIdx = idx; break; } if (removedIdx === -1) { // Defensive: fallback to remove first found for (var j = 0; j < inventory.length; j++) { if (inventory[j] === itemId && (!isEquipped || isEquipped && count > 1)) { removedIdx = j; break; } } } if (removedIdx !== -1) { inventory.splice(removedIdx, 1); } // If equipped and now zero remain, unequip var stillHas = false; for (var j = 0; j < inventory.length; j++) { if (inventory[j] === itemId) stillHas = true; } if (isEquipped && !stillHas) { equippedItems[itemId] = false; var stats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = stats.hp; updateHeroStatsDisplay(); } // Add gold goldAmount += data ? data.sellPrice : 1; updateGoldDisplay(); // Animate gold to gold counter var goldDisplayGlobal = LK.gui.topRight.toGlobal({ x: goldTxt.x, y: goldTxt.y }); var goldDisplayGamePos = game.toLocal(goldDisplayGlobal); var goldAnim = LK.getAsset('gold', { anchorX: 0.5, anchorY: 0.5, x: sellBtn.x + itemBagWindow.x, y: sellBtn.y + itemBagWindow.y, width: 80, height: 54 }); game.addChild(goldAnim); tween(goldAnim, { x: goldDisplayGamePos.x, y: goldDisplayGamePos.y, scaleX: 0.3, scaleY: 0.3, alpha: 0 }, { duration: 420, easing: tween.cubicIn, onFinish: function onFinish() { goldAnim.destroy(); } }); // Refresh inventory UI, but keep the same tab if (itemBagWindow && itemBagWindow.parent) { // Instead of closing and reopening, just re-render the list and keep the tab if (typeof itemBagListUI !== "undefined" && itemBagListUI && itemBagListUI.parent) { itemBagListUI.parent.removeChild(itemBagListUI); itemBagListUI = null; } renderItemBagList(); } }; })(row); } } itemBagListUI.x = 0; itemBagListUI.y = 0; itemBagInventoryUI.addChild(itemBagListUI); } // Initial render renderItemBagList(); itemBagInventoryUI.x = 0; itemBagInventoryUI.y = 0; itemBagWindow.addChild(itemBagInventoryUI); // --- (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; var barrierDisplay = ""; if (equippedItems && equippedItems["shield-1"] && heroShield1Barrier > 0) { barrierDisplay = " +" + heroShield1Barrier; } var atkDisplay = "" + stats.atk; var bonusDisplay = ""; // Will show item upgrade bonuses // Calculate and show shield-1 barrier if equipped if (equippedItems && equippedItems["shield-1"]) { var baseBarrier = 250; var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0; if (shieldUpgradeLevel > 0) { baseBarrier = Math.round(baseBarrier * (1 + 0.1 * shieldUpgradeLevel)); } bonusDisplay += "\nShield-1 Bariyer: +" + baseBarrier; } // Calculate and show sword-1 bonus if equipped if (equippedItems && equippedItems["sword-1"]) { var swordBonus = itemData["sword-1"].bonusAtk; var swordUpgradeLevel = equippedItemUpgradeLevels["sword-1"] || 0; if (swordUpgradeLevel > 0) { swordBonus = Math.round(swordBonus * (1 + 0.1 * swordUpgradeLevel)); } atkDisplay += " +" + swordBonus; bonusDisplay += "\nKılıç-1 Bonus: +" + swordBonus; } heroStatsTxt.setText("Hero\n" + "Level: " + heroLevel + "\n" + "Health: " + hpDisplay + barrierDisplay + "\n" + "Attack: " + atkDisplay + (bonusDisplay ? "\n" + bonusDisplay : "")); } // Update enemy stats display function updateEnemyStatsDisplay() { // DAĞ: multi-enemy stacked stats if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy) && currentEnemy.length > 0) { // Show each enemy's stats, stacked, in order, with level above each enemy var lines = []; for (var i = 0; i < currentEnemy.length; i++) { var e = currentEnemy[i]; if (!e || !e.isAlive) continue; var enemyLevel = e.level || heroLevel; var maxHp = typeof e.maxHp === "number" ? e.maxHp : getStatsForLevel(enemyLevel, "enemy").hp; var hpDisplay = typeof e.hp === "number" ? Math.max(0, Math.round(e.hp)) + " / " + maxHp : maxHp; var atkDisplay = typeof e.attack === "number" ? e.attack : "-"; // Show level above each enemy lines.push("Seviye: " + enemyLevel); lines.push(i + 1 + "- " + hpDisplay + " HP " + atkDisplay + " ATK"); } if (lines.length > 0) { enemyStatsTxt.setText(lines.join("\n")); } else { enemyStatsTxt.setText("Enemy\n-"); } } else if (currentEnemy && currentEnemy.isAlive) { var enemyLevel = currentEnemy.level || heroLevel; // Use enemy.maxHp if available, otherwise fallback to stats.hp var maxHp = typeof currentEnemy.maxHp === "number" ? currentEnemy.maxHp : getStatsForLevel(enemyLevel, "enemy").hp; var hpDisplay = typeof currentEnemy.hp === "number" ? Math.max(0, Math.round(currentEnemy.hp)) + " / " + maxHp : maxHp; enemyStatsTxt.setText("Enemy\n" + "Level: " + enemyLevel + "\n" + "Health: " + hpDisplay + "\n" + "Attack: " + currentEnemy.attack); } 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 }, // Level 2 { hp: 95, atk: 14 }, // Level 3 { hp: 130, atk: 18 }, // Level 4 { hp: 170, atk: 23 }, // Level 5 { hp: 215, atk: 27 }, // Level 6 { hp: 265, atk: 32 }, // Level 7 { hp: 320, atk: 38 }, // Level 8 { hp: 380, atk: 45 }, // Level 9 { hp: 445, atk: 53 }, // Level 10 { hp: 515, atk: 62 }]; // --- 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] }; var enemyStatGrowth = { hp: [enemyStatsByLevel[9].hp], atk: [enemyStatsByLevel[9].atk] }; // Store enemy stat percent increases per level (for linear scaling) var enemyStatPercents = { hp: [], atk: [] }; // Store hero stat percent increases per level (for compounded scaling) var heroStatPercents = { hp: [], atk: [] }; // 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 heroHpPct = randomPercent(); var heroAtkPct = randomPercent(); heroStatPercents.hp.push(heroHpPct); heroStatPercents.atk.push(heroAtkPct); heroStatGrowth.hp.push(Math.round(prevHeroHp * (1 + heroHpPct))); heroStatGrowth.atk.push(Math.round(prevHeroAtk * (1 + heroAtkPct))); // ENEMY: linear from level 10 base var baseHp = enemyStatsByLevel[9].hp; var baseAtk = enemyStatsByLevel[9].atk; var enemyHpPct = randomPercent(); var enemyAtkPct = randomPercent(); enemyStatPercents.hp.push(enemyHpPct); enemyStatPercents.atk.push(enemyAtkPct); // For linear, sum all previous percent increases var totalHpPct = 0; var totalAtkPct = 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]; // 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))); } } // 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]; // Always include equipment HP calculation for hero if (type === "hero") { var baseHp = Math.round(stats.hp * 1.5); // At level 1, make sure hero attack is enough to defeat enemy 1 var baseAtk; if (level === 1) { // Enemy 1 HP: 60, Enemy 1 Atk: 10 // Give hero enough attack to defeat enemy in 6 hits (10 damage per hit) baseAtk = 10; } else { baseAtk = Math.round(stats.atk * 0.6); } // --- Increase stats by 15% for each equipped item --- var equippedCount = 0; if (equippedItems) { for (var k in equippedItems) { if (equippedItems[k]) equippedCount++; } } if (equippedCount > 0) { var multiplier = 1 + 0.15 * equippedCount; baseHp = Math.round(baseHp * multiplier); baseAtk = Math.round(baseAtk * multiplier); } // Apply shield-1 effects if equipped // No longer add shieldBonus to baseHp; shield-1 only gives barrier, not HP bonus // Apply sword-1 effects if equipped if (equippedItems && equippedItems["sword-1"]) { var swordBonus = itemData["sword-1"].bonusAtk; var swordUpgradeLevel = equippedItemUpgradeLevels["sword-1"] || 0; if (swordUpgradeLevel > 0) { swordBonus = Math.round(swordBonus * (1 + 0.1 * swordUpgradeLevel)); } baseAtk += swordBonus; } return { hp: baseHp, atk: baseAtk }; } else { return { hp: Math.round(stats.hp * 1.5), // %50 daha fazla can atk: Math.round(stats.atk * 0.6) // %40 daha az atak }; } } ensureStatGrowthUpTo(level); var idx = level - 10; if (type === "hero") { // Base stats var baseHp = heroStatGrowth.hp[idx]; var baseAtk = heroStatGrowth.atk[idx]; // --- Increase stats by 15% for each equipped item --- var equippedCount = 0; if (equippedItems) { for (var k in equippedItems) { if (equippedItems[k]) equippedCount++; } } if (equippedCount > 0) { var multiplier = 1 + 0.15 * equippedCount; baseHp = Math.round(baseHp * multiplier); baseAtk = Math.round(baseAtk * multiplier); } // Apply shield-1 effects if equipped // No longer add shieldBonus to baseHp; shield-1 only gives barrier, not HP bonus // Apply sword-1 effects if equipped if (equippedItems && equippedItems["sword-1"]) { var swordBonus = itemData["sword-1"].bonusAtk; var swordUpgradeLevel = equippedItemUpgradeLevels["sword-1"] || 0; if (swordUpgradeLevel > 0) { swordBonus = Math.round(swordBonus * (1 + 0.1 * swordUpgradeLevel)); } baseAtk += swordBonus; } return { hp: baseHp, atk: baseAtk }; } else { return { hp: Math.round(enemyStatGrowth.hp[idx] * 1.5), // %50 daha fazla can atk: Math.round(enemyStatGrowth.atk[idx] * 0.6) // %40 daha az atak }; } } // For backward compatibility, keep getEnemyStatsForLevel for hero stats (used in refill, etc) function getEnemyStatsForLevel(level) { return getStatsForLevel(level, "hero"); } function spawnEnemy() { // --- DAĞ: spawn 1-4 random enemies (from 1-20) side by side --- if (currentLocationId === "bg_dag") { // Remove any previous enemies if (Array.isArray(currentEnemy)) { for (var i = 0; i < currentEnemy.length; i++) { if (currentEnemy[i] && currentEnemy[i].parent) { currentEnemy[i].destroy(); } } } else if (currentEnemy && currentEnemy.isAlive && currentEnemy.parent) { currentEnemy.destroy(); } currentEnemy = null; // How many enemies? 1-4 random var enemyCount = Math.floor(Math.random() * 4) + 1; // Pick unique random levels for each enemy (from 1-20) var possibleLevels = []; for (var i = 1; i <= 20; i++) possibleLevels.push(i); // Shuffle for (var i = possibleLevels.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = possibleLevels[i]; possibleLevels[i] = possibleLevels[j]; possibleLevels[j] = temp; } var enemyLevels = possibleLevels.slice(0, enemyCount); // Calculate spacing and position so that all enemies are on the right half, never crossing center, and always visible var enemyWidth = 400; // estimate for safety, actual asset is 1280px but scaled down var rightHalfStart = 2048 / 2; var rightHalfEnd = 2048 - 100; // leave 100px margin on right var availableWidth = rightHalfEnd - rightHalfStart; var spacing = 0; if (enemyCount > 1) { spacing = Math.min(340, (availableWidth - enemyWidth) / (enemyCount - 1)); } else { spacing = 0; } var totalWidth = (enemyCount - 1) * spacing; var startX = rightHalfStart + (availableWidth - totalWidth - enemyWidth) / 2 + enemyWidth / 2; if (startX < rightHalfStart + enemyWidth / 2) startX = rightHalfStart + enemyWidth / 2; if (startX + totalWidth > rightHalfEnd - enemyWidth / 2) startX = rightHalfEnd - totalWidth - enemyWidth / 2; currentEnemy = []; for (var idx = 0; idx < enemyCount; idx++) { var level = enemyLevels[idx]; var isEnemy2 = false; var enemy; if (level > 10) { if (Math.random() < 0.5) { enemy = new Enemy2(); isEnemy2 = true; } else { enemy = new Enemy(); } } else { enemy = new Enemy(); } // Place enemies side by side, vertically aligned with hero enemy.x = startX + idx * spacing; enemy.y = hero.y + 100; // Get stats for this level var stats = getStatsForLevel(level, "enemy"); // Randomize stats ±30% var statRand = Math.random(); var hpMod = 1, atkMod = 1; if (statRand < 0.3) { hpMod = 0.7; atkMod = 0.7; } else if (statRand < 0.6) { hpMod = 1.3; atkMod = 1.3; } enemy.maxHp = Math.round(stats.hp * hpMod); if (isEnemy2) { enemy.hp = Math.round(stats.hp * 0.8 * hpMod); enemy.attack = Math.round(stats.atk * 1.3 * atkMod); } else { enemy.hp = Math.round(stats.hp * hpMod); enemy.attack = Math.round(stats.atk * atkMod); } enemy.isAlive = true; enemy.spawnAnim(); game.addChild(enemy); enemy.level = level; enemy.isEnemy2 = isEnemy2; enemy.isBoss = false; // Attach tap handler for each enemy (function (enemyObj) { enemyObj.down = function (x, y, obj) { if (!enemyObj.isAlive) return; enemyObj.hp -= 1; if (enemyObj.hp < 0) enemyObj.hp = 0; // Flash enemy tween(enemyObj, { tint: 0xffffff }, { duration: 60, onFinish: function onFinish() { tween(enemyObj, { tint: 0x2a6bde }, { duration: 60 }); } }); if (enemyObj.hp <= 0) { enemyObj.isAlive = false; enemyObj.defeatAnim(function () { enemyObj.destroy(); // Remove from currentEnemy array for (var i = 0; i < currentEnemy.length; i++) { if (currentEnemy[i] === enemyObj) { currentEnemy.splice(i, 1); break; } } // Drop gold and items // Gold drop logic (use same as defeatEnemy, but per enemy) // --- DAĞ: Make gold drop proportional to number of enemies defeated --- var goldDropByLevelIdx = Math.max(0, Math.min(level - 1, goldDropByLevel.length - 1)); var goldDropStats = goldDropByLevel[goldDropByLevelIdx]; var goldDropAmount = Math.floor(Math.random() * (goldDropStats.max - goldDropStats.min + 1)) + goldDropStats.min; // If DAĞ and multi-enemy, multiply by total number of enemies spawned in this wave if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy)) { // enemyCount is the number of enemies spawned in this wave // We need to find the total number of enemies that were spawned for this wave. // Since currentEnemy is being spliced, we can track the original count. // Let's use a property on the array to store the original count if not already set. if (typeof currentEnemy._originalCount === "undefined") { // Set on first defeat currentEnemy._originalCount = currentEnemy.length + 1; } goldDropAmount = goldDropAmount * currentEnemy._originalCount; } // Drop gold at enemy position var goldDisplayGlobal = LK.gui.topRight.toGlobal({ x: goldTxt.x, y: goldTxt.y }); var goldDisplayGamePos = game.toLocal(goldDisplayGlobal); for (var g = 0; g < goldDropAmount; g++) { var gold = new Gold(); gold.x = enemyObj.x; gold.y = enemyObj.y; gold.scaleX = 1; gold.scaleY = 1; gold.alpha = 1; game.addChild(gold); golds.push(gold); var dropY = gold.y + (Math.random() * 120 - 60); (function (goldObj, idx) { goldObj.dropAnim(goldObj.x, dropY, function () { LK.setTimeout(function () { goldObj.collectAnim(goldDisplayGamePos.x, goldDisplayGamePos.y, function () { goldAmount += 1; updateGoldDisplay(); goldObj.destroy(); }); }, 80 * idx); }); })(gold, g); } // Shield-1 drop logic (5% per level, capped at 50% for level 10) if (level >= 1 && level <= 10 && !enemyObj.isEnemy2) { var shieldDropChance = level * 0.05; if (Math.random() < shieldDropChance) { var shieldAsset = LK.getAsset('shield-1', { anchorX: 0.5, anchorY: 0.5, x: enemyObj.x, y: enemyObj.y }); game.addChild(shieldAsset); 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(); inventory.push("shield-1"); } }); } } // Sword-1 drop logic (Enemy2, level 10/20 always, else 15%) if (enemyObj.isEnemy2) { var swordDrop = false; if (level === 10 || level === 20) { swordDrop = true; } else if (Math.random() < 0.15) { swordDrop = true; } if (swordDrop) { var swordAsset = LK.getAsset('sword-1', { anchorX: 0.5, anchorY: 0.5, x: enemyObj.x, y: enemyObj.y }); game.addChild(swordAsset); var itemBagGlobalSword = LK.gui.bottom.toGlobal({ x: itemBagImg.x, y: itemBagImg.y }); var itemBagGamePosSword = game.toLocal(itemBagGlobalSword); tween(swordAsset, { x: itemBagGamePosSword.x, y: itemBagGamePosSword.y, scaleX: 0.3, scaleY: 0.3, alpha: 0.2 }, { duration: 700, easing: tween.cubicIn, onFinish: function onFinish() { swordAsset.destroy(); inventory.push("sword-1"); } }); } } }); } }; })(enemy); currentEnemy.push(enemy); } // DAĞ: auto-fight all enemies in array if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy) && currentEnemy.length > 0) { // Defensive: clear any previous 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 var heroStats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = heroStats.hp; hero.attack = heroStats.atk; if (equippedItems && equippedItems["sword-1"]) { hero.attack += itemData["sword-1"].bonusAtk; } // Hero attacks all alive enemies in array, one per second heroAutoAttackTimer = LK.setInterval(function () { // Defensive: skip if no enemies left if (!Array.isArray(currentEnemy) || currentEnemy.length === 0) { LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; if (typeof enemyAutoAttackTimer !== "undefined" && enemyAutoAttackTimer) { LK.clearInterval(enemyAutoAttackTimer); enemyAutoAttackTimer = null; } return; } // Animate hero and equipped items: move slightly right and return var heroAttackMoveX = 32; tween.stop(hero, { x: true }); tween(hero, { x: hero.x + heroAttackMoveX }, { duration: 60, easing: tween.cubicOut, onFinish: function onFinish() { tween(hero, { x: hero.x - heroAttackMoveX }, { duration: 80, easing: tween.cubicIn }); } }); // Animate equipped visuals if any if (_typeof(hero.equippedVisuals) === "object" && hero.equippedVisuals) { for (var k in hero.equippedVisuals) { if (hero.equippedVisuals[k]) { tween.stop(hero.equippedVisuals[k], { x: true }); var eq = hero.equippedVisuals[k]; var origX = typeof eq._origX === "number" ? eq._origX : eq.x; eq._origX = origX; tween(eq, { x: origX + heroAttackMoveX }, { duration: 60, easing: tween.cubicOut, onFinish: function (eq, origX) { return function () { tween(eq, { x: origX }, { duration: 80, easing: tween.cubicIn }); }; }(eq, origX) }); } } } // Attack all alive enemies for (var i = 0; i < currentEnemy.length; i++) { var e = currentEnemy[i]; if (!e || !e.isAlive) continue; // If one-shot mode, instantly defeat if (heroOneShotEnemies) { e.hp = 0; } else { e.hp -= hero.attack; if (e.hp < 0) e.hp = 0; } // Flash enemy tween(e, { tint: 0xffffff }, { duration: 60, onFinish: function (e) { return function () { tween(e, { tint: 0x2a6bde }, { duration: 60 }); }; }(e) }); // If enemy defeated, trigger its defeatAnim and remove from array if (e.hp <= 0 && e.isAlive) { e.isAlive = false; (function (enemyObj) { enemyObj.defeatAnim(function () { if (!Array.isArray(currentEnemy)) return; // Remove from currentEnemy array for (var j = 0; j < currentEnemy.length; j++) { if (currentEnemy[j] === enemyObj) { currentEnemy.splice(j, 1); break; } } // Drop gold and items (same as tap logic) var level = enemyObj.level || heroLevel; var goldDropByLevelIdx = Math.max(0, Math.min(level - 1, goldDropByLevel.length - 1)); var goldDropStats = goldDropByLevel[goldDropByLevelIdx]; var goldDropAmount = Math.floor(Math.random() * (goldDropStats.max - goldDropStats.min + 1)) + goldDropStats.min; // If DAĞ and multi-enemy, multiply by total number of enemies spawned in this wave if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy)) { if (typeof currentEnemy._originalCount === "undefined") { // Set on first defeat currentEnemy._originalCount = currentEnemy.length + 1; } goldDropAmount = goldDropAmount * currentEnemy._originalCount; } var goldDisplayGlobal = LK.gui.topRight.toGlobal({ x: goldTxt.x, y: goldTxt.y }); var goldDisplayGamePos = game.toLocal(goldDisplayGlobal); for (var g = 0; g < goldDropAmount; g++) { var gold = new Gold(); gold.x = enemyObj.x; gold.y = enemyObj.y; gold.scaleX = 1; gold.scaleY = 1; gold.alpha = 1; game.addChild(gold); golds.push(gold); var dropY = gold.y + (Math.random() * 120 - 60); (function (goldObj, idx) { goldObj.dropAnim(goldObj.x, dropY, function () { LK.setTimeout(function () { goldObj.collectAnim(goldDisplayGamePos.x, goldDisplayGamePos.y, function () { goldAmount += 1; updateGoldDisplay(); goldObj.destroy(); }); }, 80 * idx); }); })(gold, g); } // Shield-1 drop logic (5% per level, capped at 50% for level 10) if (level >= 1 && level <= 10 && !enemyObj.isEnemy2) { var shieldDropChance = level * 0.05; if (Math.random() < shieldDropChance) { var shieldAsset = LK.getAsset('shield-1', { anchorX: 0.5, anchorY: 0.5, x: enemyObj.x, y: enemyObj.y }); game.addChild(shieldAsset); 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(); inventory.push("shield-1"); } }); } } // Sword-1 drop logic (Enemy2, level 10/20 always, else 15%) if (enemyObj.isEnemy2) { var swordDrop = false; if (level === 10 || level === 20) { swordDrop = true; } else if (Math.random() < 0.15) { swordDrop = true; } if (swordDrop) { var swordAsset = LK.getAsset('sword-1', { anchorX: 0.5, anchorY: 0.5, x: enemyObj.x, y: enemyObj.y }); game.addChild(swordAsset); var itemBagGlobalSword = LK.gui.bottom.toGlobal({ x: itemBagImg.x, y: itemBagImg.y }); var itemBagGamePosSword = game.toLocal(itemBagGlobalSword); tween(swordAsset, { x: itemBagGamePosSword.x, y: itemBagGamePosSword.y, scaleX: 0.3, scaleY: 0.3, alpha: 0.2 }, { duration: 700, easing: tween.cubicIn, onFinish: function onFinish() { swordAsset.destroy(); inventory.push("sword-1"); } }); } } enemyObj.destroy(); updateEnemyStatsDisplay(); }); })(e); } } updateEnemyStatsDisplay(); // If all enemies are defeated, stop timer if (!Array.isArray(currentEnemy) || currentEnemy.length === 0) { LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; if (typeof enemyAutoAttackTimer !== "undefined" && enemyAutoAttackTimer) { LK.clearInterval(enemyAutoAttackTimer); enemyAutoAttackTimer = null; } } }, 1000); // All enemies attack hero, one per second enemyAutoAttackTimer = LK.setInterval(function () { if (!Array.isArray(currentEnemy) || currentEnemy.length === 0) { LK.clearInterval(enemyAutoAttackTimer); enemyAutoAttackTimer = null; if (typeof heroAutoAttackTimer !== "undefined" && heroAutoAttackTimer) { LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; } return; } if (typeof hero.currentHp !== "number") { var hStats = getEnemyStatsForLevel(heroLevel); hero.currentHp = hStats.hp; } if (!heroIsImmortal) { // Sum all alive enemy attacks var totalDmg = 0; for (var i = 0; i < currentEnemy.length; i++) { var e = currentEnemy[i]; if (e && e.isAlive && typeof e.attack === "number") { totalDmg += e.attack; } } // --- Shield-1 barrier logic: block damage with barrier first --- if (equippedItems && equippedItems["shield-1"] && heroShield1Barrier > 0) { var dmg = totalDmg; if (heroShield1Barrier >= dmg) { heroShield1Barrier -= dmg; dmg = 0; } else { dmg -= heroShield1Barrier; heroShield1Barrier = 0; } if (dmg > 0) { hero.currentHp -= dmg; } } else { hero.currentHp -= totalDmg; } // 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(); 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); updateEnemyStatsDisplay(); return; } updateEnemyStatsDisplay(); return; } // --- DEFAULT: single enemy logic (as before) --- if (currentEnemy && currentEnemy.isAlive) return; // Only one at a time if (hero.healthRefilling) return; // Don't allow spawn while refilling var enemy; var isEnemy2 = false; // --- BOSS LOGIC --- // Increment enemy spawn count enemySpawnCount = (typeof enemySpawnCount === "number" ? enemySpawnCount : 0) + 1; var isBoss = enemySpawnCount % 8 === 0; // 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); } // Orman seçeneğinde benden yüksek seviyede düşman gelme ihtimali %5 olsun var enemyLevel; if (currentLocationId === "bg_orman") { // %5 ihtimalle heroLevel+1 veya heroLevel+2, %95 ihtimalle heroLevel veya heroLevel-1 if (Math.random() < 0.05) { // Yüksek seviye: heroLevel+1 veya heroLevel+2 var highLevels = []; for (var i = 0; i < uniqueLevels.length; i++) { if (uniqueLevels[i] > heroLevel) highLevels.push(uniqueLevels[i]); } if (highLevels.length > 0) { enemyLevel = highLevels[Math.floor(Math.random() * highLevels.length)]; } else { enemyLevel = heroLevel; } } else { // Düşük/aynı seviye: heroLevel veya heroLevel-1 var lowLevels = []; for (var i = 0; i < uniqueLevels.length; i++) { if (uniqueLevels[i] <= heroLevel) lowLevels.push(uniqueLevels[i]); } if (lowLevels.length > 0) { enemyLevel = lowLevels[Math.floor(Math.random() * lowLevels.length)]; } else { enemyLevel = heroLevel; } } } else { // Diğer lokasyonlar: eski random seçimi 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)); // Decide which enemy type to spawn if (enemyLevel > 10) { // After level 10, 50% chance for Enemy2, 50% for Enemy if (Math.random() < 0.5) { enemy = new Enemy2(); isEnemy2 = true; } else { enemy = new Enemy(); } } else { enemy = new Enemy(); } // Place enemy on the far right, vertically aligned with hero if (isEnemy2) { enemy.x = 2048 - 400; // Move Enemy2 200px further left than Enemy } else { enemy.x = 2048 - 200; // 200px from the right edge, matching hero's 200px from left } enemy.y = hero.y; // Get stats for this level (enemy uses linear scaling after level 10) var stats = getStatsForLevel(enemyLevel, "enemy"); // --- RANDOMIZE ENEMY STATS: hp/atk ±30% for 30% --- // 0-0.3: -30% hp/atk, 0.3-0.6: +30% hp/atk, 0.6-1.0: normal var statRand = Math.random(); var hpMod = 1, atkMod = 1; if (statRand < 0.3) { hpMod = 0.7; atkMod = 0.7; } else if (statRand < 0.6) { hpMod = 1.3; atkMod = 1.3; } // Set maxHp for enemy, so it matches the randomized HP value enemy.maxHp = Math.round(stats.hp * hpMod); // --- BOSS STAT MODIFIERS --- if (isBoss) { // HP +100%, Atk +50% enemy.hp = Math.round(stats.hp * 2.0 * hpMod); enemy.attack = Math.round(stats.atk * 1.5 * atkMod); // Make enemy 50% larger enemy.scaleX = (typeof enemy.scaleX === "number" ? enemy.scaleX : 1) * 1.5; enemy.scaleY = (typeof enemy.scaleY === "number" ? enemy.scaleY : 1) * 1.5; // Add BOSS label above enemy var bossLabel = new Text2("BOSS", { size: 90, fill: 0xFF2222, glow: { color: 0xffffff, distance: 10, strength: 2 } }); bossLabel.anchor.set(0.5, 1); bossLabel.x = 0; bossLabel.y = -((enemy.height || 300) / 2) - 30; enemy.addChild(bossLabel); enemy.isBoss = true; } else if (isEnemy2) { // CAN %20 DAHA AZ, ATAK %30 DAHA ÇOK enemy.hp = Math.round(stats.hp * 0.8 * hpMod); enemy.attack = Math.round(stats.atk * 1.3 * atkMod); } else { enemy.hp = Math.round(stats.hp * hpMod); enemy.attack = Math.round(stats.atk * atkMod); } enemy.isAlive = true; enemy.spawnAnim(); game.addChild(enemy); currentEnemy = enemy; // Store the enemy's level for display currentEnemy.level = enemyLevel; currentEnemy.isEnemy2 = isEnemy2; // Track type for possible future use currentEnemy.isBoss = !!isBoss; 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; // Calculate hero attack, always include sword-1 bonus if equipped hero.attack = heroStats.atk; if (equippedItems && equippedItems["sword-1"]) { hero.attack += itemData["sword-1"].bonusAtk; } // Hero attacks enemy (fixed interval, e.g. 1s) heroAutoAttackTimer = LK.setInterval(function () { if (!currentEnemy || !currentEnemy.isAlive) { LK.clearInterval(heroAutoAttackTimer); heroAutoAttackTimer = null; return; } // Animate hero and equipped items: move slightly right and return var heroAttackMoveX = 32; tween.stop(hero, { x: true }); tween(hero, { x: hero.x + heroAttackMoveX }, { duration: 60, easing: tween.cubicOut, onFinish: function onFinish() { tween(hero, { x: hero.x - heroAttackMoveX }, { duration: 80, easing: tween.cubicIn }); } }); // Animate equipped visuals if any if (_typeof(hero.equippedVisuals) === "object" && hero.equippedVisuals) { for (var k in hero.equippedVisuals) { if (hero.equippedVisuals[k]) { tween.stop(hero.equippedVisuals[k], { x: true }); var eq = hero.equippedVisuals[k]; var origX = typeof eq._origX === "number" ? eq._origX : eq.x; eq._origX = origX; tween(eq, { x: origX + heroAttackMoveX }, { duration: 60, easing: tween.cubicOut, onFinish: function (eq, origX) { return function () { tween(eq, { x: origX }, { duration: 80, easing: tween.cubicIn }); }; }(eq, origX) }); } } } // If one-shot mode, instantly defeat enemy if (heroOneShotEnemies) { currentEnemy.hp = 0; } else { currentEnemy.hp -= hero.attack; if (currentEnemy.hp < 0) currentEnemy.hp = 0; } // 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); // Fixed 1s interval // Enemy attacks hero (fixed interval, e.g. 1s) 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) { // --- Shield-1 barrier logic: block damage with barrier first --- if (equippedItems && equippedItems["shield-1"] && heroShield1Barrier > 0) { var dmg = currentEnemy.attack; if (heroShield1Barrier >= dmg) { heroShield1Barrier -= dmg; dmg = 0; } else { dmg -= heroShield1Barrier; heroShield1Barrier = 0; } if (dmg > 0) { hero.currentHp -= dmg; } } else { 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); // Fixed 1s interval } // 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, and only from Enemy (not Enemy2) if (typeof currentEnemy.level !== "undefined" && currentEnemy.level >= 1 && currentEnemy.level <= 10 && !currentEnemy.isEnemy2) { // 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 only (do not auto-equip) inventory.push("shield-1"); } }); } } // --- Sword-1 drop logic: only for Enemy2, and only for level 10 and 20 enemies --- // Now: Drop chance is 100% at level 10/20, and for all other levels, 15% chance per defeat from Enemy2 if (typeof currentEnemy.level !== "undefined" && currentEnemy.isEnemy2) { var swordDrop = false; if (currentEnemy.level === 10 || currentEnemy.level === 20) { swordDrop = true; // Always drop at level 10 and 20 } else { // 15% drop chance for all other levels from Enemy2 if (Math.random() < 0.15) swordDrop = true; } if (swordDrop) { var swordAsset = LK.getAsset('sword-1', { anchorX: 0.5, anchorY: 0.5, x: currentEnemy.x, y: currentEnemy.y }); game.addChild(swordAsset); // Animate drop: move to itemBag position and shrink/fade out var itemBagGlobalSword = LK.gui.bottom.toGlobal({ x: itemBagImg.x, y: itemBagImg.y }); var itemBagGamePosSword = game.toLocal(itemBagGlobalSword); tween(swordAsset, { x: itemBagGamePosSword.x, y: itemBagGamePosSword.y, scaleX: 0.3, scaleY: 0.3, alpha: 0.2 }, { duration: 700, easing: tween.cubicIn, onFinish: function onFinish() { swordAsset.destroy(); // Add to inventory only (do not auto-equip) inventory.push("sword-1"); } }); } } // Track boss defeat for level gating if (typeof heroDefeatedBosses === "undefined") heroDefeatedBosses = []; if (currentEnemy && currentEnemy.isBoss && typeof currentEnemy.level === "number") { // Bosses are at spawn counts 8, 16, 24, ... which correspond to levels 5, 10, 15, ... // So, for level gating, bossIndex = Math.floor((currentEnemy.level) / 5) var bossIndex = Math.floor(currentEnemy.level / 5); heroDefeatedBosses[bossIndex] = true; } currentEnemy.destroy(); currentEnemy = null; updateEnemyStatsDisplay(); // HERO CANINI FULLLE! var stats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = stats.hp; updateHeroStatsDisplay(); // If shield-1 is equipped, restore hero HP to new max after enemy defeat if (equippedItems["shield-1"]) { heroShield1Barrier = 250; heroShield1BarrierMax = 250; 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 = [ // Level 1 { min: 1, max: 5 }, // Level 2 { min: 3, max: 8 }, // Level 3 { min: 5, max: 12 }, // Level 4 { min: 8, max: 16 }, // Level 5 { min: 12, max: 20 }, // Level 6 { min: 15, max: 25 }, // Level 7 { min: 20, max: 32 }, // Level 8 { min: 25, max: 40 }, // Level 9 { min: 30, max: 48 }, // Level 10 { min: 35, max: 60 }]; // Defensive: If goldDropByLevel is referenced for higher levels, extend with scaled values (function extendGoldDropByLevel() { var last = goldDropByLevel[goldDropByLevel.length - 1]; for (var i = goldDropByLevel.length; i < 100; i++) { // Increase min/max by 10% per level after 10 var prev = goldDropByLevel[i - 1]; goldDropByLevel.push({ min: Math.round(prev.min * 1.1), max: Math.round(prev.max * 1.1) }); } })(); // 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; // Boss: drop 50% more gold if (currentEnemy && currentEnemy.isBoss) { goldDropAmount = Math.round(goldDropAmount * 1.5); } // 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; } // --- Boss defeat requirement for every 5th level --- var nextLevel = heroLevel + 1; var mustDefeatBoss = false; if (nextLevel > 5 && (nextLevel - 1) % 5 === 0) { // For 6, 11, 16, ... 501, etc. (i.e. 6 = after 1st boss, 11 = after 2nd boss, ...) var bossIndex = Math.floor((nextLevel - 1) / 5); // 6->1, 11->2, 16->3, ... // Track defeated bosses in an array if (typeof heroDefeatedBosses === "undefined") heroDefeatedBosses = []; if (!heroDefeatedBosses[bossIndex]) { // Block upgrade, flash upgradeBtn red tween(upgradeBtn, { tint: 0xff4444 }, { duration: 120, onFinish: function onFinish() { tween(upgradeBtn, { tint: 0xffffff }, { duration: 120 }); } }); // Optionally show a message (not required) 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; if (currentEnemy.hp < 0) currentEnemy.hp = 0; // 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 duration = Math.max(10, Math.pow(heroLevel, 1.2) * 2); // Simple duration, e.g. 2s per level^1.2 // 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 / 2) / random(1-5) var stats = getStatsForLevel(heroLevel, "hero"); var divisor = Math.floor(Math.random() * 5) + 1; var goldVal = heroLevel + 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) { // 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 () { // Hide spawnBtn if current location is şehir, demirci, maden, kale, or sahil if (currentLocationId === "bg_sehir" || currentLocationId === "bg_demirci" || currentLocationId === "bg_maden" || currentLocationId === "bg_kale" || currentLocationId === "bg_sahil") { if (typeof spawnBtn !== "undefined" && spawnBtn) spawnBtn.visible = false; if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = false; // Always show demirciBtn if in demirci if (currentLocationId === "bg_demirci" && typeof demirciBtn !== "undefined" && demirciBtn) { demirciBtn.visible = true; } // Show madenBtn only in maden if (typeof madenBtn !== "undefined" && madenBtn) { madenBtn.visible = currentLocationId === "bg_maden"; // Check if kazma is in inventory var hasKazma = false; for (var i = 0; i < inventory.length; i++) { if (inventory[i] === "kazma") { hasKazma = true; break; } } if (madenBtn.visible) { // Only allow madenBtn if kazma is EQUIPPED, not just in inventory var kazmaEquipped = !!equippedItems["kazma"]; if (!kazmaEquipped) { madenBtn.alpha = 0.5; madenBtn.interactive = false; madenBtn.buttonMode = false; } else { madenBtn.alpha = 1; madenBtn.interactive = true; madenBtn.buttonMode = true; } } } // Show kaleBtn only in kale if (typeof kaleBtn !== "undefined" && kaleBtn) { kaleBtn.visible = currentLocationId === "bg_kale"; } } else { if (typeof spawnBtn !== "undefined" && spawnBtn) spawnBtn.visible = true; if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = true; // Hide demirciBtn if not in demirci if (typeof demirciBtn !== "undefined" && demirciBtn) { demirciBtn.visible = false; } // Hide madenBtn if not in maden if (typeof madenBtn !== "undefined" && madenBtn) { madenBtn.visible = false; } // Hide kaleBtn if not in kale if (typeof kaleBtn !== "undefined" && kaleBtn) { kaleBtn.visible = false; } } // 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) // --- DAĞ: Remove all enemies and prevent gold drop on hero defeat --- if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy)) { // Remove all DAĞ enemies for (var i = 0; i < currentEnemy.length; i++) { if (currentEnemy[i] && currentEnemy[i].isAlive) { currentEnemy[i].isAlive = false; // Animate defeat, but do not drop gold/items (function (enemyObj) { enemyObj.defeatAnim(function () { if (enemyObj && enemyObj.parent) { enemyObj.destroy(); } }); })(currentEnemy[i]); } } currentEnemy = null; updateEnemyStatsDisplay(); // --- DAĞ: Restore hero shield and health after fight, just like ORMAN --- // Always restore barrier to max after refill, if shield is equipped if (equippedItems && equippedItems["shield-1"]) { var baseBarrier = 250; var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0; if (shieldUpgradeLevel > 0) { baseBarrier = Math.round(baseBarrier * (1 + 0.1 * shieldUpgradeLevel)); } heroShield1Barrier = baseBarrier; heroShield1BarrierMax = baseBarrier; } else { heroShield1Barrier = 0; heroShield1BarrierMax = 0; } // Restore hero health to FULL after DAĞ fight (like ORMAN) var stats = getStatsForLevel(heroLevel, "hero"); hero.currentHp = stats.hp; updateHeroStatsDisplay(); } else 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; // After refill, if shield-1 is equipped, restore barrier to max if (equippedItems && equippedItems["shield-1"]) { heroShield1Barrier = 250; heroShield1BarrierMax = 250; } } } // 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 && typeof workBtnCountdownTxt.destroyed === "boolean" && !workBtnCountdownTxt.destroyed && typeof workBtnCountdownTxt.setText === "function" && typeof workBtnCountdownTxt.x !== "undefined" && typeof workBtnCountdownTxt.y !== "undefined") { // Defensive: Only access .visible if it exists, and never access .setAsset if ((typeof workBtnCountdownTxt.visible === "undefined" || workBtnCountdownTxt.visible) && typeof workBtnCountdownTxt.x !== "undefined" && typeof workBtnCountdownTxt.y !== "undefined") { workBtnCountdownTxt.x = workBtn.x; workBtnCountdownTxt.y = workBtn.y + workBtn.height / 2 + 8; } } }; // --- Initial UI state --- updateGoldDisplay(); updateUpgradeDisplay(); updateHeroStatsDisplay(); updateEnemyStatsDisplay(); // --- Hero HP and Shield Auto-Regeneration Logic --- // Regenerate 25% of max HP per second, and refill shield barrier, if no enemy is present if (typeof heroAutoRegenInterval === "undefined") { var heroAutoRegenInterval = null; } if (heroAutoRegenInterval) { LK.clearInterval(heroAutoRegenInterval); heroAutoRegenInterval = null; } heroAutoRegenInterval = LK.setInterval(function () { // Defensive: Only run if hero exists and not in battle if (!hero || typeof hero.currentHp !== "number") return; // If any enemy is alive, do not regen var enemyAlive = false; if (Array.isArray(currentEnemy)) { for (var i = 0; i < currentEnemy.length; i++) { if (currentEnemy[i] && currentEnemy[i].isAlive) { enemyAlive = true; break; } } } else if (currentEnemy && currentEnemy.isAlive) { enemyAlive = true; } if (enemyAlive) return; // Regen HP if not full var stats = getStatsForLevel(heroLevel, "hero"); var maxHp = stats.hp; if (typeof hero.currentHp !== "number" || hero.currentHp >= maxHp) { hero.currentHp = Math.min(maxHp, hero.currentHp); } else { var regenAmount = Math.ceil(maxHp * 0.25); hero.currentHp = Math.min(maxHp, hero.currentHp + regenAmount); updateHeroStatsDisplay(); } // Regen shield barrier if equipped and not full if (equippedItems && equippedItems["shield-1"]) { var maxBarrier = 250; var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0; if (shieldUpgradeLevel > 0) { maxBarrier = Math.round(maxBarrier * (1 + 0.1 * shieldUpgradeLevel)); } if (typeof heroShield1Barrier !== "number" || heroShield1Barrier >= maxBarrier) { heroShield1Barrier = Math.min(maxBarrier, heroShield1Barrier); heroShield1BarrierMax = maxBarrier; } else { // Refill all missing barrier at once per second heroShield1Barrier = maxBarrier; heroShield1BarrierMax = maxBarrier; updateHeroStatsDisplay(); } } }, 1000);
/****
* 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;
});
// Enemy2 class (new enemy type after level 10)
var Enemy2 = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy2', {
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;
});
// MadenResource class for madenBtn resource spawn/collect logic
var MadenResource = Container.expand(function () {
var self = Container.call(this);
// Resource types and their values
var types = [{
id: "hamdemir",
value: 5
}, {
id: "hamgumus",
value: 50
}, {
id: "hamaltin",
value: 100
}, {
id: "hammitril",
value: 1000
}];
// Pick type (passed in or random)
self.typeIdx = typeof arguments[0] === "number" ? arguments[0] : Math.floor(Math.random() * types.length);
self.type = types[self.typeIdx];
// Attach asset
var gfx = self.attachAsset(self.type.id, {
anchorX: 0.5,
anchorY: 0.5
});
// For animation
self.scaleX = 0.7;
self.scaleY = 0.7;
// Animate pop out
self.popAnim = function (fromX, fromY, toX, toY, onFinish) {
self.x = fromX;
self.y = fromY;
self.alpha = 0.7;
tween(self, {
x: toX,
y: toY,
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 220,
easing: tween.bounceOut,
onFinish: onFinish
});
};
// Animate collect to itemBag
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
});
};
// Helper: check if point is inside
self.containsPoint = function (pt) {
var w = gfx.width || 100,
h = gfx.height || 100;
return pt.x >= self.x - w / 2 && pt.x <= self.x + w / 2 && pt.y >= self.y - h / 2 && pt.y <= self.y + h / 2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222a36
});
/****
* Game Code
****/
// --- Gold drop amount table per level ---
var goldDropByLevel = [
// Level 1
{
min: 1,
max: 5
},
// Level 2
{
min: 3,
max: 8
},
// Level 3
{
min: 5,
max: 12
},
// Level 4
{
min: 8,
max: 16
},
// Level 5
{
min: 12,
max: 20
},
// Level 6
{
min: 15,
max: 25
},
// Level 7
{
min: 20,
max: 32
},
// Level 8
{
min: 25,
max: 40
},
// Level 9
{
min: 30,
max: 48
},
// Level 10
{
min: 35,
max: 60
}];
// Defensive: If goldDropByLevel is referenced for higher levels, extend with scaled values
(function extendGoldDropByLevel() {
var last = goldDropByLevel[goldDropByLevel.length - 1];
for (var i = goldDropByLevel.length; i < 100; i++) {
// Increase min/max by 10% per level after 10
var prev = goldDropByLevel[i - 1];
goldDropByLevel.push({
min: Math.round(prev.min * 1.1),
max: Math.round(prev.max * 1.1)
});
}
})();
// --- Global State ---
// new unique asset for leftBtn
// Upgrade Button: orange box
// Spawn Enemy Button: green box
// Gold: yellow ellipse
// Enemy: blue ellipse
// Hero: red box, left side
// Background images for each location (dummy ids, replace with real asset ids as needed)
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var backgroundImg = null;
// Helper to create a scaled background asset (returns a dummy container for now)
function getScaledBgAsset(bgId) {
// Defensive: If bgId is not a valid asset, return a transparent container
var bgAsset;
try {
bgAsset = LK.getAsset(bgId, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 2048,
height: 2732
});
} catch (e) {
bgAsset = new Container();
}
return bgAsset;
}
// --- Set initial background to 'orman' (forest) ---
backgroundImg = getScaledBgAsset('bg_orman');
game.addChildAt(backgroundImg, 0); // Add at bottom layer to ensure orman is visible at start
// Show spawnBtn only for 'orman' and 'dağ' at game start
if (typeof spawnBtn !== "undefined" && spawnBtn) {
spawnBtn.visible = true;
if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = true;
}
var hero = new Hero();
game.addChild(hero);
var currentEnemy = null;
var enemySpawnCount = 0; // Track how many enemies have been spawned
var golds = [];
var goldAmount = 0;
var heroLevel = 1;
// --- Inventory and Items ---
var inventory = [];
// Track equipped item upgrade levels (itemId -> level)
var equippedItemUpgradeLevels = {};
var equippedItems = {
"shield-1": false,
"sword-1": false
};
// --- Shield-1 barrier state ---
var heroShield1Barrier = 0; // If >0, this is the current shield-1 barrier HP
var heroShield1BarrierMax = 0; // Max barrier HP (100 if equipped)
// Shield-1 and Sword-1 item data
var itemData = {
"shield-1": {
name: "Shield-1",
type: "shield",
bonusHp: 250,
// +250 extra HP
atkSpdPenalty: 2,
// -2 attack speed
buyPrice: 50,
sellPrice: 15
},
"sword-1": {
name: "Kılıç-1",
type: "sword",
bonusAtk: 50,
// +50 attack
bonusAtkSpd: 1,
// +1 attack speed
buyPrice: 50,
sellPrice: 15
},
"kazma": {
name: "Kazma",
type: "tool",
bonusMine: 1,
// future: can be used for mining bonus
buyPrice: 250,
sellPrice: 75
},
"hamdemir": {
name: "Ham Demir",
type: "maden",
buyPrice: 0,
sellPrice: 5
},
"hamgumus": {
name: "Ham Gümüş",
type: "maden",
buyPrice: 0,
sellPrice: 50
},
"hamaltin": {
name: "Ham Altın",
type: "maden",
buyPrice: 0,
sellPrice: 100
},
"hammitril": {
name: "Ham Mitril",
type: "maden",
buyPrice: 0,
sellPrice: 1000
}
};
// --- GoldBag effect state ---
var heroIsImmortal = false;
var heroOneShotEnemies = false;
// Auto-fight timer handles
var heroAutoAttackTimer = null;
var enemyAutoAttackTimer = null;
// --- GUI Elements ---
// Location display (top center, above upgradeBtn)
var locationNames = {
"bg_orman": "ORMAN",
"bg_sehir": "ŞEHİR",
"bg_dag": "DAĞ",
"bg_demirci": "DEMİRCİ",
"bg_maden": "MADEN",
"bg_kale": "KALE",
"bg_sahil": "SAHİL"
};
var currentLocationId = "bg_orman";
var locationTxt = new Text2(locationNames[currentLocationId], {
size: 70,
fill: "#fff",
glow: {
color: 0x2a6bde,
distance: 8,
strength: 2
}
});
locationTxt.anchor.set(0.5, 0);
locationTxt.x = LK.gui.top.width / 2;
locationTxt.y = 10;
LK.gui.top.addChild(locationTxt);
// 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: "#fff",
glow: {
color: 0x000000,
distance: 12,
strength: 4
},
fontWeight: "bold"
});
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: "#fff",
glow: {
color: 0x000000,
distance: 12,
strength: 4
},
fontWeight: "bold"
});
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
});
// New button to the left of upgradeBtn, with its own unique visual
var leftBtn = LK.getAsset('leftBtn', {
anchorX: 0.5,
anchorY: 0.5
});
// Ensure leftBtn is added to the GUI (if not already)
if (!leftBtn.parent) {
LK.gui.top.addChild(leftBtn);
}
// Add shrink-grow animation to leftBtn when tapped, and show location list
leftBtn.down = function (x, y, obj) {
tween.stop(leftBtn, {
scaleX: true,
scaleY: true
});
tween(leftBtn, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.cubicIn,
onFinish: function onFinish() {
tween(leftBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.cubicOut,
onFinish: function onFinish() {
// Show location list after animation
if (typeof locationListWindow !== "undefined" && locationListWindow && locationListWindow.parent) {
locationListWindow.parent.removeChild(locationListWindow);
locationListWindow = null;
}
// Hide leftBtn while window is open
leftBtn.visible = false;
// Create window container
locationListWindow = new Container();
var winWidth = 700;
var winHeight = 900;
var winColor = 0x000000;
var winAlpha = 0.85;
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;
locationListWindow.addChild(winBg);
// Add X close button to top right of window
var closeBtnSize = 80;
var closeBtn = LK.getAsset('centerCircle', {
width: closeBtnSize,
height: closeBtnSize,
color: 0x222222,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: winWidth / 2 - closeBtnSize / 2 - 18,
y: -winHeight / 2 + closeBtnSize / 2 + 18
});
closeBtn.alpha = 0.7;
locationListWindow.addChild(closeBtn);
var closeBtnTxt = new Text2("X", {
size: 48,
fill: "#fff"
});
closeBtnTxt.anchor.set(0.5, 0.5);
closeBtnTxt.x = closeBtn.x;
closeBtnTxt.y = closeBtn.y;
locationListWindow.addChild(closeBtnTxt);
// Close logic for X button
closeBtn.down = function () {
if (locationListWindow && locationListWindow.parent) {
locationListWindow.parent.removeChild(locationListWindow);
locationListWindow = null;
}
// Restore leftBtn
leftBtn.visible = true;
};
// List of locations
var locations = ["1. ORMAN", "2. ŞEHİR", "3. DAĞ", "4. DEMİRCİ", "5. MADEN", "6. KALE", "7. SAHİL"];
var btnHeight = 90;
var btnWidth = winWidth - 120;
var btnGap = 18;
var startY = -winHeight / 2 + 120;
for (var i = 0; i < locations.length; i++) {
(function (idx) {
var btnY = startY + idx * (btnHeight + btnGap);
var locBtn = LK.getAsset('centerCircle', {
width: btnWidth,
height: btnHeight,
color: 0x2a6bde,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: btnY
});
locBtn.alpha = 0.92;
locationListWindow.addChild(locBtn);
var locTxt = new Text2(locations[idx], {
size: 44,
fill: "#fff"
});
locTxt.anchor.set(0.5, 0.5);
locTxt.x = locBtn.x;
locTxt.y = locBtn.y;
locationListWindow.addChild(locTxt);
// Optionally: add tap handler for each location
locBtn.down = function () {
// Animate button for feedback
tween.stop(locBtn, {
scaleX: true,
scaleY: true
});
tween(locBtn, {
scaleX: 0.93,
scaleY: 0.93
}, {
duration: 80,
easing: tween.cubicIn,
onFinish: function onFinish() {
tween(locBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 80,
easing: tween.cubicOut
});
}
});
// Handle location selection and change background
// Map each location to a unique background asset id
var bgMap = ["bg_orman",
// 1. ORMAN
"bg_sehir",
// 2. ŞEHİR
"bg_dag",
// 3. DAĞ
"bg_demirci",
// 4. DEMİRCİ
"bg_maden",
// 5. MADEN
"bg_kale",
// 6. KALE
"bg_sahil" // 7. SAHİL
];
var selectedIdx = idx;
var newBgId = bgMap[selectedIdx];
// Update currentLocationId and locationTxt
currentLocationId = newBgId;
if (locationTxt && locationNames[newBgId]) {
locationTxt.setText(locationNames[newBgId]);
}
// Remove old background image if present
if (backgroundImg && backgroundImg.parent) {
backgroundImg.parent.removeChild(backgroundImg);
backgroundImg.destroy();
}
// Create new background image asset, scaled to fit the screen
backgroundImg = getScaledBgAsset(newBgId);
game.addChildAt(backgroundImg, 0); // Add at bottom layer
// Show spawnBtn only for 'orman' and 'dağ', show demirciBtn for 'demirci', hide otherwise
if (typeof spawnBtn !== "undefined" && spawnBtn) {
if (newBgId === "bg_orman" || newBgId === "bg_dag") {
spawnBtn.visible = true;
if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = true;
if (typeof demirciBtn !== "undefined" && demirciBtn) demirciBtn.visible = false;
} else if (newBgId === "bg_demirci") {
spawnBtn.visible = false;
if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = false;
if (typeof demirciBtn === "undefined" || !demirciBtn) {
// Create demirciBtn if not already created
demirciBtn = LK.getAsset('demirciBtn', {
anchorX: 0.5,
anchorY: 0.5,
x: spawnBtn.x,
y: spawnBtn.y
});
demirciBtn.down = function (x, y, obj) {
// Animate shrink/grow for feedback
tween.stop(demirciBtn, {
scaleX: true,
scaleY: true
});
tween(demirciBtn, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.cubicIn,
onFinish: function onFinish() {
tween(demirciBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.cubicOut
});
}
});
// You can add demirci-specific logic here
};
LK.gui.bottom.addChild(demirciBtn);
}
if (typeof demirciBtn !== "undefined" && demirciBtn) demirciBtn.visible = true;
} else {
spawnBtn.visible = false;
if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = false;
if (typeof demirciBtn !== "undefined" && demirciBtn) demirciBtn.visible = false;
}
}
// Close the location list window
if (locationListWindow && locationListWindow.parent) {
locationListWindow.parent.removeChild(locationListWindow);
locationListWindow = null;
}
// Restore leftBtn
leftBtn.visible = true;
};
})(i);
}
// Center in game area
locationListWindow.x = 2048 / 2;
locationListWindow.y = 2732 / 2;
game.addChild(locationListWindow);
}
});
}
});
};
// 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) {
// Toggle immortal/one-shot state
heroIsImmortal = !heroIsImmortal;
heroOneShotEnemies = heroIsImmortal;
// Optional: flash hero for feedback
if (heroIsImmortal) {
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
});
}
});
} else {
// If disabling, reset hero color/scale
tween.stop(hero, {
tint: true,
scaleX: true,
scaleY: true
});
hero.tint = 0xffffff;
hero.scaleX = 1;
hero.scaleY = 1;
}
};
// --- 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: "#fff",
glow: {
color: 0x000000,
distance: 12,
strength: 4
},
fontWeight: "bold"
});
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;
// Move leftBtn, upgradeBtn, and workBtn further left as a group, keeping upgradeBtn centered relative to the new group
var groupShift = 120; // Amount to shift all three buttons left
// Place upgradeBtn at new center
upgradeBtn.x = LK.gui.top.width / 2 - groupShift;
upgradeBtn.y = 100 + upgradeBtn.height / 2;
// Place leftBtn to the left of upgradeBtn, with a small gap
leftBtn.x = upgradeBtn.x - upgradeBtn.width / 2 - leftBtn.width / 2 - 30;
leftBtn.y = upgradeBtn.y;
// 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: "#fff",
glow: {
color: 0x000000,
distance: 12,
strength: 4
},
fontWeight: "bold"
});
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(leftBtn);
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;
// Maden special button (only visible in maden)
var madenBtn = LK.getAsset('madenBtn', {
anchorX: 0.5,
anchorY: 0.5,
x: spawnBtn.x,
y: spawnBtn.y
});
madenBtn.visible = false;
// Kale special button (only visible in kale, no function)
var kaleBtn = LK.getAsset('kaleBtn', {
anchorX: 0.5,
anchorY: 0.5,
x: spawnBtn.x,
y: spawnBtn.y
});
kaleBtn.visible = false;
// --- KaleBtn tap: rotate 90deg right, open window, rotate back on close ---
var kaleWindow = null;
kaleBtn.down = function (x, y, obj) {
// Animate shrink/grow for feedback
tween.stop(kaleBtn, {
scaleX: true,
scaleY: true
});
tween(kaleBtn, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.cubicIn,
onFinish: function onFinish() {
tween(kaleBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.cubicOut,
onFinish: function onFinish() {
// After shrink/grow, rotate 90deg right
tween.stop(kaleBtn, {
rotation: true
});
tween(kaleBtn, {
rotation: kaleBtn.rotation + Math.PI / 2
}, {
duration: 180,
easing: tween.cubicInOut,
onFinish: function onFinish() {
// Open window after rotation
if (kaleWindow && kaleWindow.parent) {
kaleWindow.parent.removeChild(kaleWindow);
kaleWindow = null;
}
kaleBtn.visible = false;
// Create window container
kaleWindow = new Container();
var winWidth = 800;
var winHeight = 600;
var winColor = 0x222222;
var winAlpha = 0.92;
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;
kaleWindow.addChild(winBg);
// Add X close button to top right of window
var closeBtnSize = 80;
var closeBtn = LK.getAsset('centerCircle', {
width: closeBtnSize,
height: closeBtnSize,
color: 0x444444,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: winWidth / 2 - closeBtnSize / 2 - 18,
y: -winHeight / 2 + closeBtnSize / 2 + 18
});
closeBtn.alpha = 0.7;
kaleWindow.addChild(closeBtn);
var closeBtnTxt = new Text2("X", {
size: 48,
fill: "#fff"
});
closeBtnTxt.anchor.set(0.5, 0.5);
closeBtnTxt.x = closeBtn.x;
closeBtnTxt.y = closeBtn.y;
kaleWindow.addChild(closeBtnTxt);
// Close logic for X button
closeBtn.down = function () {
if (kaleWindow && kaleWindow.parent) {
kaleWindow.parent.removeChild(kaleWindow);
kaleWindow = null;
}
// Rotate back 90deg left and show kaleBtn
tween.stop(kaleBtn, {
rotation: true
});
tween(kaleBtn, {
rotation: kaleBtn.rotation - Math.PI / 2
}, {
duration: 180,
easing: tween.cubicInOut,
onFinish: function onFinish() {
kaleBtn.visible = true;
}
});
};
// Center window in game area
kaleWindow.x = 2048 / 2;
kaleWindow.y = 2732 / 2;
game.addChild(kaleWindow);
}
});
}
});
}
});
};
LK.gui.bottom.addChild(kaleBtn);
// --- MadenBtn resource spawn/collect logic ---
var madenResourceTypes = [{
id: "hamdemir",
value: 5
}, {
id: "hamgumus",
value: 50
}, {
id: "hamaltin",
value: 100
}, {
id: "hammitril",
value: 1000
}];
var madenActiveResource = null;
var madenResourceTimeout = null;
madenBtn.down = function (x, y, obj) {
// Check if kazma is in inventory
var hasKazma = false;
for (var i = 0; i < inventory.length; i++) {
if (inventory[i] === "kazma") {
hasKazma = true;
break;
}
}
if (!hasKazma) {
// Animate button for feedback
tween.stop(madenBtn, {
scaleX: true,
scaleY: true
});
tween(madenBtn, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.cubicIn,
onFinish: function onFinish() {
tween(madenBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.cubicOut
});
}
});
// Show message: "Kazmaya ihtiyacın var"
if (typeof madenBtnMsg === "undefined" || !madenBtnMsg || madenBtnMsg.destroyed) {
madenBtnMsg = new Text2("Kazmaya ihtiyacın var", {
size: 60,
fill: "#fff",
glow: {
color: 0x000000,
distance: 10,
strength: 2
}
});
madenBtnMsg.anchor.set(0.5, 0.5);
madenBtnMsg.x = 2048 / 2;
madenBtnMsg.y = 2732 / 2 + 400;
game.addChild(madenBtnMsg);
}
madenBtnMsg.visible = true;
madenBtnMsg.alpha = 1;
// Fade out after 1.2s
tween(madenBtnMsg, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
if (madenBtnMsg) madenBtnMsg.visible = false;
}
});
return;
}
// Animate shrink/grow for feedback
tween.stop(madenBtn, {
scaleX: true,
scaleY: true
});
tween(madenBtn, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.cubicIn,
onFinish: function onFinish() {
tween(madenBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.cubicOut
});
}
});
// If resources are already active, ignore further clicks
if (madenActiveResource && madenActiveResource.length > 0) return;
// --- Custom drop logic: drop up to 4 resources, each with its own probability ---
// Probabilities (cumulative for easier logic):
// hammitril (1000): 5%
// hamaltin (100): 25%
// hamgumus (50): 50%
// hamdemir (5): 95%
// We'll try to drop each, but only if the random roll is within the chance.
var centerX = 2048 / 2;
var centerY = 2732 / 2;
madenActiveResource = [];
var madenResourceTimeouts = [];
var oldGameDown = game.down;
// --- Ava: Reduce drop rates by half, and increase with kazma upgrade level ---
// Get kazma upgrade level (0 if not upgraded)
var kazmaUpgradeLevel = equippedItemUpgradeLevels && equippedItemUpgradeLevels["kazma"] ? equippedItemUpgradeLevels["kazma"] : 0;
// Each upgrade level increases drop rates by 10% of original (not compounded, capped at 100%)
var upgradeBonus = kazmaUpgradeLevel * 0.1;
// Base drop rates halved
var dropTable = [{
typeIdx: 3,
chance: Math.min(1, 0.025 + 0.05 * upgradeBonus) // hammitril (1000)
}, {
typeIdx: 2,
chance: Math.min(1, 0.125 + 0.25 * upgradeBonus) // hamaltin (100)
}, {
typeIdx: 1,
chance: Math.min(1, 0.25 + 0.5 * upgradeBonus) // hamgumus (50)
}, {
typeIdx: 0,
chance: Math.min(1, 0.475 + 0.95 * upgradeBonus) // hamdemir (5)
} // hamdemir (5)
];
// For each resource type, roll and drop if passed
for (var i = 0; i < dropTable.length; i++) {
var entry = dropTable[i];
if (Math.random() < entry.chance) {
var fromX = centerX;
var fromY = centerY;
var toX = centerX;
var toY = centerY;
var resource = new MadenResource(entry.typeIdx);
resource.x = fromX;
resource.y = fromY;
game.addChild(resource);
resource.popAnim(fromX, fromY, toX, toY);
(function (resource, idx) {
var itemBagGlobal = LK.gui.bottom.toGlobal({
x: itemBagImg.x,
y: itemBagImg.y
});
var itemBagGamePos = game.toLocal(itemBagGlobal);
LK.setTimeout(function () {
resource.collectAnim(itemBagGamePos.x, itemBagGamePos.y, function () {
inventory.push(resource.type.id);
resource.destroy();
var idxInArr = madenActiveResource.indexOf(resource);
if (idxInArr !== -1) madenActiveResource.splice(idxInArr, 1);
if (madenActiveResource.length === 0) {
game.down = oldGameDown;
}
});
}, 250 + Math.floor(Math.random() * 100));
resource._timeoutIdx = idx;
madenActiveResource.push(resource);
})(resource, i);
}
}
// No tap handler needed, auto-collects
};
LK.gui.bottom.addChild(madenBtn);
// Demirci button (hidden by default, shown only in demirci)
var demirciBtn = LK.getAsset('demirciBtn', {
anchorX: 0.5,
anchorY: 0.5,
x: spawnBtn.x,
y: spawnBtn.y
});
demirciBtn.visible = false;
demirciBtn.down = function (x, y, obj) {
// Animate shrink/grow for feedback
tween.stop(demirciBtn, {
scaleX: true,
scaleY: true
});
tween(demirciBtn, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.cubicIn,
onFinish: function onFinish() {
tween(demirciBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.cubicOut
});
}
});
// --- Show equipped items window with upgrade buttons ---
if (typeof equippedItemsWindow !== "undefined" && equippedItemsWindow && equippedItemsWindow.parent) {
equippedItemsWindow.parent.removeChild(equippedItemsWindow);
equippedItemsWindow = null;
}
// Hide demirciBtn while window is open
demirciBtn.visible = false;
// Create window container
equippedItemsWindow = new Container();
var winWidth = 900;
var winHeight = 700;
var winColor = 0x222222;
var winAlpha = 0.92;
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;
equippedItemsWindow.addChild(winBg);
// --- Small single-row window for 'Kazma' under main demirci window ---
var kazmaWinWidth = 600;
var kazmaWinHeight = 90;
var kazmaWinColor = 0x111111;
var kazmaWinAlpha = 0.95;
var kazmaWinY = winHeight / 2 + kazmaWinHeight / 2 + 18; // just below main window
var kazmaWindow = new Container();
var kazmaBg = LK.getAsset('centerCircle', {
width: kazmaWinWidth,
height: kazmaWinHeight,
color: kazmaWinColor,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: kazmaWinY
});
kazmaBg.alpha = kazmaWinAlpha;
kazmaWindow.addChild(kazmaBg);
// "Kazma" label
var kazmaLabel = new Text2("Kazma", {
size: 44,
fill: "#fff"
});
kazmaLabel.anchor.set(0, 0.5);
kazmaLabel.x = -kazmaWinWidth / 2 + 30;
kazmaLabel.y = kazmaWinY;
kazmaWindow.addChild(kazmaLabel);
// Price label
var kazmaPrice = new Text2("250 altın", {
size: 40,
fill: 0xFFE066
});
kazmaPrice.anchor.set(0, 0.5);
kazmaPrice.x = kazmaLabel.x + 180;
kazmaPrice.y = kazmaWinY;
kazmaWindow.addChild(kazmaPrice);
// "Satın Al" button
var satinAlBtnWidth = 180;
var satinAlBtnHeight = 70;
var satinAlBtn = LK.getAsset('centerCircle', {
width: satinAlBtnWidth,
height: satinAlBtnHeight,
color: 0x2a6bde,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: kazmaWinWidth / 2 - satinAlBtnWidth / 2 - 20,
y: kazmaWinY
});
satinAlBtn.alpha = 0.92;
kazmaWindow.addChild(satinAlBtn);
var satinAlTxt = new Text2("Satın Al", {
size: 38,
fill: "#fff"
});
satinAlTxt.anchor.set(0.5, 0.5);
satinAlTxt.x = satinAlBtn.x;
satinAlTxt.y = satinAlBtn.y;
kazmaWindow.addChild(satinAlTxt);
// Animate button on tap and handle buy logic for kazma
satinAlBtn.down = function () {
tween.stop(satinAlBtn, {
scaleX: true,
scaleY: true
});
tween(satinAlBtn, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 80,
easing: tween.cubicIn,
onFinish: function onFinish() {
tween(satinAlBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 80,
easing: tween.cubicOut,
onFinish: function onFinish() {
// Buy logic for kazma
var kazmaPriceVal = itemData["kazma"] ? itemData["kazma"].buyPrice : 250;
// Check if already owned
var alreadyOwned = false;
for (var i = 0; i < inventory.length; i++) {
if (inventory[i] === "kazma") {
alreadyOwned = true;
break;
}
}
if (alreadyOwned) {
// Flash button red if already owned
tween(satinAlBtn, {
tint: 0xff4444
}, {
duration: 120,
onFinish: function onFinish() {
tween(satinAlBtn, {
tint: 0x2a6bde
}, {
duration: 120
});
}
});
return;
}
if (goldAmount < kazmaPriceVal) {
// Flash button red if not enough gold
tween(satinAlBtn, {
tint: 0xff4444
}, {
duration: 120,
onFinish: function onFinish() {
tween(satinAlBtn, {
tint: 0x2a6bde
}, {
duration: 120
});
}
});
return;
}
// Deduct gold, add kazma to inventory (do NOT auto-equip)
goldAmount -= kazmaPriceVal;
updateGoldDisplay();
inventory.push("kazma");
// Refresh demirci window to show new inventory state
if (equippedItemsWindow && equippedItemsWindow.parent) {
equippedItemsWindow.parent.removeChild(equippedItemsWindow);
equippedItemsWindow = null;
}
demirciBtn.down();
}
});
}
});
};
// Add kazmaWindow to equippedItemsWindow
equippedItemsWindow.addChild(kazmaWindow);
// Add X close button to bottom center of window
var closeBtnSize = 90;
var closeBtn = LK.getAsset('centerCircle', {
width: closeBtnSize,
height: closeBtnSize,
color: 0x444444,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: winHeight / 2 - closeBtnSize / 2 - 20
});
closeBtn.alpha = 0.7;
equippedItemsWindow.addChild(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;
equippedItemsWindow.addChild(closeBtnTxt);
// Close logic for X button
closeBtn.down = function () {
if (equippedItemsWindow && equippedItemsWindow.parent) {
equippedItemsWindow.parent.removeChild(equippedItemsWindow);
equippedItemsWindow = null;
}
// Restore demirciBtn
demirciBtn.visible = true;
};
// --- List equipped items with upgrade buttons ---
var equippedList = [];
for (var itemId in equippedItems) {
if (equippedItems[itemId]) equippedList.push(itemId);
}
var itemRowHeight = 180;
var itemIconSize = 120;
var btnWidth = 220;
var btnHeight = 80;
var fontSize = 44;
var startY = -winHeight / 2 + 120;
if (equippedList.length === 0) {
var noEqTxt = new Text2("Kuşanılan eşya yok!", {
size: 54,
fill: "#fff"
});
noEqTxt.anchor.set(0.5, 0.5);
noEqTxt.x = 0;
noEqTxt.y = 0;
equippedItemsWindow.addChild(noEqTxt);
} else {
for (var i = 0; i < equippedList.length; i++) {
(function (idx) {
var itemId = equippedList[idx];
var data = itemData[itemId];
// Icon
var icon = LK.getAsset(itemId, {
anchorX: 0.5,
anchorY: 0.5,
x: -winWidth / 2 + itemIconSize / 2 + 60,
y: startY + idx * itemRowHeight + itemIconSize / 2,
width: itemIconSize,
height: itemIconSize
});
equippedItemsWindow.addChild(icon);
// Name and stats
var labelText = data ? data.name : itemId;
var label = new Text2(labelText, {
size: fontSize,
fill: "#fff"
});
label.anchor.set(0, 0.5);
label.x = icon.x + itemIconSize / 2 + 30;
label.y = icon.y;
equippedItemsWindow.addChild(label);
// Show upgrade bonus next to item name
var upgradeLevel = equippedItemUpgradeLevels[itemId] || 0;
var bonusText = "";
if (itemId === "shield-1") {
var base = 250;
var bonus = Math.round(base * (1 + 0.1 * upgradeLevel));
bonusText = "Bariyer: +" + bonus;
} else if (itemId === "sword-1") {
var base = itemData["sword-1"].bonusAtk;
var bonus = Math.round(base * (1 + 0.1 * upgradeLevel));
bonusText = "Bonus: +" + bonus;
}
if (bonusText) {
var bonusTxt = new Text2(bonusText, {
size: 32,
fill: 0xFFE066
});
bonusTxt.anchor.set(0, 0.5);
bonusTxt.x = label.x;
bonusTxt.y = label.y + 44;
equippedItemsWindow.addChild(bonusTxt);
}
// Upgrade button
var upgradeBtnEq = LK.getAsset('upgradeBtn', {
anchorX: 0.5,
anchorY: 0.5,
x: label.x + 350,
y: icon.y,
width: btnWidth,
height: btnHeight
});
equippedItemsWindow.addChild(upgradeBtnEq);
var upgradeTxt = new Text2("Yükselt", {
size: fontSize,
fill: "#fff"
});
upgradeTxt.anchor.set(0.5, 0.5);
upgradeTxt.x = upgradeBtnEq.x;
upgradeTxt.y = upgradeBtnEq.y;
equippedItemsWindow.addChild(upgradeTxt);
// Show current upgrade level (if any)
if (typeof equippedItemUpgradeLevels === "undefined") window.equippedItemUpgradeLevels = {};
if (typeof equippedItemUpgradeLevels[itemId] === "undefined") equippedItemUpgradeLevels[itemId] = 0;
var upgradeLevel = equippedItemUpgradeLevels[itemId];
var levelTxt = new Text2("Seviye: " + (upgradeLevel + 1), {
size: 36,
fill: 0xFFE066
});
levelTxt.anchor.set(0, 0.5);
levelTxt.x = upgradeBtnEq.x + btnWidth / 2 + 30;
levelTxt.y = upgradeBtnEq.y;
equippedItemsWindow.addChild(levelTxt);
// Upgrade logic
upgradeBtnEq.down = function () {
// Cost: 20 * (upgradeLevel+1)
var cost = 20 * (equippedItemUpgradeLevels[itemId] + 1);
if (goldAmount < cost) {
// Flash gold text red
tween(goldTxt, {
tint: 0xff4444
}, {
duration: 120,
onFinish: function onFinish() {
tween(goldTxt, {
tint: 0xFFE066
}, {
duration: 120
});
}
});
return;
}
goldAmount -= cost;
equippedItemUpgradeLevels[itemId]++;
updateGoldDisplay();
// Optionally: flash upgradeBtnEq
tween(upgradeBtnEq, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 120,
onFinish: function onFinish() {
tween(upgradeBtnEq, {
scaleX: 1,
scaleY: 1
}, {
duration: 120
});
}
});
// Refresh window to update level text
if (equippedItemsWindow && equippedItemsWindow.parent) {
equippedItemsWindow.parent.removeChild(equippedItemsWindow);
equippedItemsWindow = null;
}
demirciBtn.down();
};
})(i);
}
}
// Center in game area
equippedItemsWindow.x = 2048 / 2;
equippedItemsWindow.y = 2732 / 2;
game.addChild(equippedItemsWindow);
};
LK.gui.bottom.addChild(demirciBtn);
// Add "find enemy!" text above the spawn button
var findEnemyTxt = new Text2("find enemy!", {
size: 45,
fill: "#fff",
glow: {
color: 0x000000,
distance: 12,
strength: 4
},
fontWeight: "bold"
});
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;
}
// 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 bottom center 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: 0,
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);
// --- Hide spawnBtn, demirciBtn, workBtn, upgradeBtn, leftBtn, and all on-screen texts when X is visible ---
spawnBtn.visible = false;
if (typeof demirciBtn !== "undefined" && demirciBtn) demirciBtn.visible = false;
workBtn.visible = false;
upgradeBtn.visible = false;
leftBtn.visible = false;
findEnemyTxt.visible = false;
upgradeCostTxt.visible = false;
heroStatsTxt.visible = false;
enemyStatsTxt.visible = false;
goldTxt.visible = false;
goldBagImg.visible = false;
if (workBtnCountdownTxt) workBtnCountdownTxt.visible = false;
// Close logic for X button
closeBtn.down = function () {
if (itemBagWindow && itemBagWindow.parent) {
itemBagWindow.parent.removeChild(itemBagWindow);
itemBagWindow = null;
}
// Restore all UI elements
if (typeof demirciBtn !== "undefined" && demirciBtn && demirciBtn.parent && demirciBtn.visible === false) {
// Only show demirciBtn if spawnBtn would be hidden (i.e. in demirci)
if (backgroundImg && backgroundImg.assetId === "bg_demirci") {
demirciBtn.visible = true;
spawnBtn.visible = false;
} else {
demirciBtn.visible = false;
spawnBtn.visible = true;
}
} else {
spawnBtn.visible = true;
}
workBtn.visible = true;
upgradeBtn.visible = true;
leftBtn.visible = true;
findEnemyTxt.visible = true;
upgradeCostTxt.visible = true;
heroStatsTxt.visible = true;
enemyStatsTxt.visible = true;
goldTxt.visible = true;
goldBagImg.visible = true;
if (workBtnCountdownTxt && workBtnActive === false && workBtnTimeLeft > 0) {
workBtnCountdownTxt.visible = true;
}
};
// Center in game area
itemBagWindow.x = 2048 / 2;
itemBagWindow.y = 2732 / 2;
// Add to game
game.addChild(itemBagWindow);
// (Removed: close window on tap anywhere on window. Now only X closes the window)
// --- Inventory UI inside itemBagWindow ---
// Remove any previous inventory UI
if (typeof itemBagInventoryUI !== "undefined" && itemBagInventoryUI && itemBagInventoryUI.parent) {
itemBagInventoryUI.parent.removeChild(itemBagInventoryUI);
itemBagInventoryUI = null;
}
// --- Tabbed UI for inventory: "Ekipmanlar", "Öğeler", "Kuşandıklarım" ---
itemBagInventoryUI = new Container();
var tabBarHeight = 90;
var tabBarY = -winHeight / 2 + tabBarHeight / 2 + 10;
var tabBarWidth = winWidth - 120;
var tabBtnWidth = (tabBarWidth - 20) / 3;
var tabBtnHeight = tabBarHeight - 10;
var tabFontSize = 38;
var tabActiveColor = 0x2a6bde;
var tabInactiveColor = 0x444444;
var tabTextColor = "#fff";
var tabNames = ["Ekipmanlar", "Öğeler", "Kuşandıklarım"];
var tabSelected = 0; // 0: ekipmanlar, 1: öğeler, 2: kuşandıklarım
// Tab buttons
var tabBtns = [];
for (var t = 0; t < 3; t++) {
(function (tabIdx) {
var tabBtn = LK.getAsset('centerCircle', {
width: tabBtnWidth,
height: tabBtnHeight,
color: tabIdx === tabSelected ? tabActiveColor : tabInactiveColor,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: -tabBarWidth / 2 + tabBtnWidth / 2 + tabIdx * (tabBtnWidth + 10),
y: tabBarY
});
tabBtn.alpha = 0.92;
itemBagInventoryUI.addChild(tabBtn);
var tabTxt = new Text2(tabNames[tabIdx], {
size: tabFontSize,
fill: tabTextColor
});
tabTxt.anchor.set(0.5, 0.5);
tabTxt.x = tabBtn.x;
tabTxt.y = tabBtn.y;
itemBagInventoryUI.addChild(tabTxt);
tabBtns.push({
btn: tabBtn,
txt: tabTxt
});
tabBtn.down = function () {
if (tabSelected === tabIdx) return;
tabSelected = tabIdx;
// Update tab colors
for (var k = 0; k < tabBtns.length; k++) {
tabBtns[k].btn.color = k === tabSelected ? tabActiveColor : tabInactiveColor;
tabBtns[k].btn.alpha = 0.92;
tabBtns[k].txt.fill = tabTextColor;
}
// Remove old list if exists
if (typeof itemBagListUI !== "undefined" && itemBagListUI && itemBagListUI.parent) {
itemBagListUI.parent.removeChild(itemBagListUI);
itemBagListUI = null;
}
renderItemBagList();
};
})(t);
}
// --- List UI container (will be replaced on tab switch) ---
var itemBagListUI = null;
function renderItemBagList() {
if (itemBagListUI && itemBagListUI.parent) {
itemBagListUI.parent.removeChild(itemBagListUI);
itemBagListUI = null;
}
itemBagListUI = new Container();
var itemListStartY = tabBarY + tabBarHeight / 2 + 20;
var itemListStartX = -winWidth / 2 + 60;
var itemRowHeight = 140;
var itemIconSize = 100;
var btnWidth = 160;
var btnHeight = 70;
var btnGap = 18;
var fontSize = 38;
// Build a count of each item in inventory, and track equipped index for each type
var itemStackMap = {}; // itemId -> array of {idx, equipped}
for (var i = 0; i < inventory.length; i++) {
var id = inventory[i];
if (!itemStackMap[id]) itemStackMap[id] = [];
// If this is equipped and not already marked, mark as equipped
var isEquipped = false;
if (equippedItems[id]) {
// Only one equipped per type, so only one stack can be equipped
var alreadyEquipped = false;
for (var s = 0; s < itemStackMap[id].length; s++) {
if (itemStackMap[id][s].equipped) alreadyEquipped = true;
}
if (!alreadyEquipped) isEquipped = true;
}
itemStackMap[id].push({
idx: i,
equipped: isEquipped
});
}
// For each item type, create a stack for equipped and for each group of unequipped
var stackRows = [];
for (var id in itemStackMap) {
var stack = itemStackMap[id];
// Find equipped
var equippedIdx = -1;
for (var s = 0; s < stack.length; s++) {
if (stack[s].equipped) equippedIdx = stack[s].idx;
}
if (equippedIdx !== -1) {
stackRows.push({
itemId: id,
count: 1,
equipped: true,
indices: [equippedIdx]
});
}
// Now, group unequipped into stacks (could be more than one stack if equipped is in the middle)
var unequippedIndices = [];
for (var s = 0; s < stack.length; s++) {
if (!stack[s].equipped) unequippedIndices.push(stack[s].idx);
}
if (unequippedIndices.length > 0) {
stackRows.push({
itemId: id,
count: unequippedIndices.length,
equipped: false,
indices: unequippedIndices
});
}
}
// Filter stackRows by tab
var filteredRows = [];
if (tabSelected === 0) {
// Ekipmanlar: only equipment (kalkan, kılıç, kazma, etc), regardless of equipped state
for (var r = 0; r < stackRows.length; r++) {
var id = stackRows[r].itemId;
var data = itemData[id];
if (data && (data.type === "shield" || data.type === "sword" || data.type === "tool")) {
filteredRows.push(stackRows[r]);
}
}
} else if (tabSelected === 1) {
// Öğeler: only non-equipment (ores, etc)
for (var r = 0; r < stackRows.length; r++) {
var id = stackRows[r].itemId;
var data = itemData[id];
if (data && data.type === "maden") {
filteredRows.push(stackRows[r]);
}
}
} else if (tabSelected === 2) {
// Kuşandıklarım: only equipped items (equipment)
for (var r = 0; r < stackRows.length; r++) {
var id = stackRows[r].itemId;
var data = itemData[id];
if (stackRows[r].equipped && data && (data.type === "shield" || data.type === "sword" || data.type === "tool")) {
filteredRows.push(stackRows[r]);
}
}
}
if (filteredRows.length === 0) {
var noItemTxt = new Text2(tabSelected === 0 ? "Kuşanılan eşya yok!" : "Kuşanılmayan eşya yok!", {
size: 48,
fill: "#fff"
});
noItemTxt.anchor.set(0.5, 0.5);
noItemTxt.x = 0;
noItemTxt.y = 0;
itemBagListUI.addChild(noItemTxt);
} else {
for (var row = 0; row < filteredRows.length; row++) {
(function (rowIdx) {
var stack = filteredRows[rowIdx];
var itemId = stack.itemId;
var data = itemData[itemId];
var count = stack.count;
var isEquipped = stack.equipped;
// Icon
var icon = LK.getAsset(itemId, {
anchorX: 0.5,
anchorY: 0.5,
x: itemListStartX + itemIconSize / 2,
y: itemListStartY + rowIdx * itemRowHeight + itemIconSize / 2,
width: itemIconSize,
height: itemIconSize
});
itemBagListUI.addChild(icon);
// Name and stats, show count and equipped
var labelText = data ? data.name : itemId;
if (count > 1) labelText += " x" + count;
if (isEquipped) labelText += " (Kuşanıldı)";
var label = new Text2(labelText, {
size: fontSize,
fill: "#fff"
});
label.anchor.set(0, 0.5);
label.x = icon.x + itemIconSize / 2 + 20;
label.y = icon.y;
itemBagListUI.addChild(label);
// Equip/Remove button (only for equipped or first unequipped stack)
// Only show for items that are not maden (raw ores)
var isMaden = itemId === "hamdemir" || itemId === "hamgumus" || itemId === "hamaltin" || itemId === "hammitril";
var showEquipBtn = !isMaden && (!isEquipped && !equippedItems[itemId] || isEquipped);
// Define equipBtn and equipTxt before using them
var equipBtn = LK.getAsset('centerCircle', {
width: btnWidth,
height: btnHeight,
color: isEquipped ? 0x8B4513 : 0x2a6bde,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: label.x + btnWidth / 2 + 30,
y: icon.y
});
equipBtn.alpha = 0.92;
itemBagListUI.addChild(equipBtn);
var equipTxt = new Text2(isEquipped ? "Çıkart" : "Kuşan", {
size: fontSize,
fill: "#fff"
});
equipTxt.anchor.set(0.5, 0.5);
equipTxt.x = equipBtn.x;
equipTxt.y = equipBtn.y;
itemBagListUI.addChild(equipTxt);
equipBtn.visible = showEquipBtn;
equipTxt.visible = showEquipBtn;
// Equip/Remove logic
equipBtn.down = function () {
if (isMaden) return; // Do nothing for maden types
// --- Ava: Kazma kuşanma/çıkarma ve diğer ekipmanlarla etkileşim ---
// Helper: unequip all equipment except the given itemId
function unequipAllExcept(itemIdToKeep) {
for (var k in equippedItems) {
if (k !== itemIdToKeep && equippedItems[k]) {
equippedItems[k] = false;
if (typeof hero.equippedVisuals !== "undefined" && hero.equippedVisuals[k]) {
hero.removeChild(hero.equippedVisuals[k]);
hero.equippedVisuals[k].destroy();
hero.equippedVisuals[k] = null;
}
// Shield-1 barrier reset if shield unequipped
if (k === "shield-1") {
heroShield1Barrier = 0;
heroShield1BarrierMax = 0;
}
}
}
}
// Helper: re-equip all equipment except kazma
function reEquipAllExceptKazma() {
for (var k in equippedItems) {
if (k !== "kazma" && inventory.indexOf(k) !== -1 && !equippedItems[k]) {
equippedItems[k] = true;
// Add visual if not present
if (typeof hero.equippedVisuals === "undefined") hero.equippedVisuals = {};
if (!hero.equippedVisuals[k]) {
var equipVisual;
if (k === "shield-1") {
equipVisual = LK.getAsset(k, {
anchorX: 0.5,
anchorY: 0.5,
x: 240,
y: 0,
width: 300,
height: 698
});
} else if (k === "sword-1") {
equipVisual = LK.getAsset(k, {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: 320,
width: 320,
height: 1550
});
equipVisual.rotation = -Math.PI / 3;
} else {
equipVisual = LK.getAsset(k, {
anchorX: 0.5,
anchorY: 0.5,
x: 90,
y: 0,
width: 320,
height: 320
});
}
hero.addChild(equipVisual);
hero.equippedVisuals[k] = equipVisual;
// Shield-1 barrier logic
if (k === "shield-1") {
var baseBarrier = 250;
var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0;
if (shieldUpgradeLevel > 0) {
baseBarrier = Math.round(baseBarrier * (1 + 0.1 * shieldUpgradeLevel));
}
heroShield1Barrier = baseBarrier;
heroShield1BarrierMax = baseBarrier;
}
}
}
}
}
if (!isEquipped) {
// --- Equip logic ---
// If equipping kazma, unequip all other equipment
if (itemId === "kazma") {
unequipAllExcept("kazma");
} else {
// If kazma is equipped, unequip it before equipping another
if (equippedItems["kazma"]) {
equippedItems["kazma"] = false;
if (typeof hero.equippedVisuals !== "undefined" && hero.equippedVisuals["kazma"]) {
hero.removeChild(hero.equippedVisuals["kazma"]);
hero.equippedVisuals["kazma"].destroy();
hero.equippedVisuals["kazma"] = null;
}
}
// Unequip all of this type (original logic)
for (var k in equippedItems) {
if (itemData[k] && itemData[k].type === data.type) {
equippedItems[k] = false;
if (typeof hero.equippedVisuals !== "undefined" && hero.equippedVisuals[k]) {
hero.removeChild(hero.equippedVisuals[k]);
hero.equippedVisuals[k].destroy();
hero.equippedVisuals[k] = null;
}
}
}
}
equippedItems[itemId] = true;
// Show item visual on hero (front)
if (typeof hero.equippedVisuals === "undefined") hero.equippedVisuals = {};
if (hero.equippedVisuals[itemId]) {
hero.removeChild(hero.equippedVisuals[itemId]);
hero.equippedVisuals[itemId].destroy();
hero.equippedVisuals[itemId] = null;
}
var equipVisual;
if (itemId === "shield-1") {
equipVisual = LK.getAsset(itemId, {
anchorX: 0.5,
anchorY: 0.5,
x: 240,
y: 0,
width: 300,
height: 698
});
} else if (itemId === "sword-1") {
equipVisual = LK.getAsset(itemId, {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: 320,
width: 320,
height: 1550
});
equipVisual.rotation = -Math.PI / 3;
} else if (itemId === "kazma") {
try {
equipVisual = LK.getAsset('kazma', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: 220,
width: 640,
height: Math.round(1550 / 3 * 2)
});
equipVisual.rotation = -Math.PI / 2;
} catch (e) {
equipVisual = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: 220,
width: 640,
height: Math.round(1550 / 3 * 2),
color: 0x888888,
shape: "box"
});
equipVisual.rotation = -Math.PI / 2;
}
} else {
equipVisual = LK.getAsset(itemId, {
anchorX: 0.5,
anchorY: 0.5,
x: 90,
y: 0,
width: 320,
height: 320
});
}
hero.addChild(equipVisual);
hero.equippedVisuals[itemId] = equipVisual;
// Shield-1 barrier logic
if (itemId === "shield-1") {
var baseBarrier = 250;
var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0;
if (shieldUpgradeLevel > 0) {
baseBarrier = Math.round(baseBarrier * (1 + 0.1 * shieldUpgradeLevel));
}
heroShield1Barrier = baseBarrier;
heroShield1BarrierMax = baseBarrier;
}
updateHeroStatsDisplay();
if (itemBagWindow && itemBagWindow.parent) {
itemBagWindow.parent.removeChild(itemBagWindow);
itemBagWindow = null;
}
itemBagImg.down();
} else {
// --- Remove (Çıkart) logic ---
equippedItems[itemId] = false;
if (typeof hero.equippedVisuals !== "undefined" && hero.equippedVisuals[itemId]) {
hero.removeChild(hero.equippedVisuals[itemId]);
hero.equippedVisuals[itemId].destroy();
hero.equippedVisuals[itemId] = null;
}
if (itemId === "shield-1") {
heroShield1Barrier = 0;
heroShield1BarrierMax = 0;
}
// If kazma is being removed, re-equip all other equipment that is in inventory
if (itemId === "kazma") {
reEquipAllExceptKazma();
}
updateHeroStatsDisplay();
if (itemBagWindow && itemBagWindow.parent) {
itemBagWindow.parent.removeChild(itemBagWindow);
itemBagWindow = null;
}
itemBagImg.down();
}
};
// Sell button
var sellBtn = LK.getAsset('centerCircle', {
width: btnWidth,
height: btnHeight,
color: 0x8B4513,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: equipBtn.x + btnWidth + btnGap,
y: icon.y
});
sellBtn.alpha = 0.85;
itemBagListUI.addChild(sellBtn);
var sellTxt = new Text2("Sat (" + (data ? data.sellPrice : 1) + ")", {
size: fontSize,
fill: "#fff"
});
sellTxt.anchor.set(0.5, 0.5);
sellTxt.x = sellBtn.x;
sellTxt.y = sellBtn.y;
itemBagListUI.addChild(sellTxt);
// Sell logic
sellBtn.down = function () {
// If this stack is equipped, and only one exists, prevent selling
if (isEquipped && count === 1) {
tween(sellBtn, {
scaleX: 1.15,
scaleY: 1.15,
tint: 0xff4444
}, {
duration: 120,
onFinish: function onFinish() {
tween(sellBtn, {
scaleX: 1,
scaleY: 1,
tint: 0x8B4513
}, {
duration: 120
});
}
});
return;
}
// Remove one from inventory (from this stack)
var removedIdx = -1;
for (var j = 0; j < stack.indices.length; j++) {
var idx = stack.indices[j];
// If equipped, skip if this is the equipped one
if (isEquipped && count === 1) continue;
removedIdx = idx;
break;
}
if (removedIdx === -1) {
// Defensive: fallback to remove first found
for (var j = 0; j < inventory.length; j++) {
if (inventory[j] === itemId && (!isEquipped || isEquipped && count > 1)) {
removedIdx = j;
break;
}
}
}
if (removedIdx !== -1) {
inventory.splice(removedIdx, 1);
}
// If equipped and now zero remain, unequip
var stillHas = false;
for (var j = 0; j < inventory.length; j++) {
if (inventory[j] === itemId) stillHas = true;
}
if (isEquipped && !stillHas) {
equippedItems[itemId] = false;
var stats = getStatsForLevel(heroLevel, "hero");
hero.currentHp = stats.hp;
updateHeroStatsDisplay();
}
// Add gold
goldAmount += data ? data.sellPrice : 1;
updateGoldDisplay();
// Animate gold to gold counter
var goldDisplayGlobal = LK.gui.topRight.toGlobal({
x: goldTxt.x,
y: goldTxt.y
});
var goldDisplayGamePos = game.toLocal(goldDisplayGlobal);
var goldAnim = LK.getAsset('gold', {
anchorX: 0.5,
anchorY: 0.5,
x: sellBtn.x + itemBagWindow.x,
y: sellBtn.y + itemBagWindow.y,
width: 80,
height: 54
});
game.addChild(goldAnim);
tween(goldAnim, {
x: goldDisplayGamePos.x,
y: goldDisplayGamePos.y,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0
}, {
duration: 420,
easing: tween.cubicIn,
onFinish: function onFinish() {
goldAnim.destroy();
}
});
// Refresh inventory UI, but keep the same tab
if (itemBagWindow && itemBagWindow.parent) {
// Instead of closing and reopening, just re-render the list and keep the tab
if (typeof itemBagListUI !== "undefined" && itemBagListUI && itemBagListUI.parent) {
itemBagListUI.parent.removeChild(itemBagListUI);
itemBagListUI = null;
}
renderItemBagList();
}
};
})(row);
}
}
itemBagListUI.x = 0;
itemBagListUI.y = 0;
itemBagInventoryUI.addChild(itemBagListUI);
}
// Initial render
renderItemBagList();
itemBagInventoryUI.x = 0;
itemBagInventoryUI.y = 0;
itemBagWindow.addChild(itemBagInventoryUI);
// --- (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;
var barrierDisplay = "";
if (equippedItems && equippedItems["shield-1"] && heroShield1Barrier > 0) {
barrierDisplay = " +" + heroShield1Barrier;
}
var atkDisplay = "" + stats.atk;
var bonusDisplay = ""; // Will show item upgrade bonuses
// Calculate and show shield-1 barrier if equipped
if (equippedItems && equippedItems["shield-1"]) {
var baseBarrier = 250;
var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0;
if (shieldUpgradeLevel > 0) {
baseBarrier = Math.round(baseBarrier * (1 + 0.1 * shieldUpgradeLevel));
}
bonusDisplay += "\nShield-1 Bariyer: +" + baseBarrier;
}
// Calculate and show sword-1 bonus if equipped
if (equippedItems && equippedItems["sword-1"]) {
var swordBonus = itemData["sword-1"].bonusAtk;
var swordUpgradeLevel = equippedItemUpgradeLevels["sword-1"] || 0;
if (swordUpgradeLevel > 0) {
swordBonus = Math.round(swordBonus * (1 + 0.1 * swordUpgradeLevel));
}
atkDisplay += " +" + swordBonus;
bonusDisplay += "\nKılıç-1 Bonus: +" + swordBonus;
}
heroStatsTxt.setText("Hero\n" + "Level: " + heroLevel + "\n" + "Health: " + hpDisplay + barrierDisplay + "\n" + "Attack: " + atkDisplay + (bonusDisplay ? "\n" + bonusDisplay : ""));
}
// Update enemy stats display
function updateEnemyStatsDisplay() {
// DAĞ: multi-enemy stacked stats
if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy) && currentEnemy.length > 0) {
// Show each enemy's stats, stacked, in order, with level above each enemy
var lines = [];
for (var i = 0; i < currentEnemy.length; i++) {
var e = currentEnemy[i];
if (!e || !e.isAlive) continue;
var enemyLevel = e.level || heroLevel;
var maxHp = typeof e.maxHp === "number" ? e.maxHp : getStatsForLevel(enemyLevel, "enemy").hp;
var hpDisplay = typeof e.hp === "number" ? Math.max(0, Math.round(e.hp)) + " / " + maxHp : maxHp;
var atkDisplay = typeof e.attack === "number" ? e.attack : "-";
// Show level above each enemy
lines.push("Seviye: " + enemyLevel);
lines.push(i + 1 + "- " + hpDisplay + " HP " + atkDisplay + " ATK");
}
if (lines.length > 0) {
enemyStatsTxt.setText(lines.join("\n"));
} else {
enemyStatsTxt.setText("Enemy\n-");
}
} else if (currentEnemy && currentEnemy.isAlive) {
var enemyLevel = currentEnemy.level || heroLevel;
// Use enemy.maxHp if available, otherwise fallback to stats.hp
var maxHp = typeof currentEnemy.maxHp === "number" ? currentEnemy.maxHp : getStatsForLevel(enemyLevel, "enemy").hp;
var hpDisplay = typeof currentEnemy.hp === "number" ? Math.max(0, Math.round(currentEnemy.hp)) + " / " + maxHp : maxHp;
enemyStatsTxt.setText("Enemy\n" + "Level: " + enemyLevel + "\n" + "Health: " + hpDisplay + "\n" + "Attack: " + currentEnemy.attack);
} 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
},
// Level 2
{
hp: 95,
atk: 14
},
// Level 3
{
hp: 130,
atk: 18
},
// Level 4
{
hp: 170,
atk: 23
},
// Level 5
{
hp: 215,
atk: 27
},
// Level 6
{
hp: 265,
atk: 32
},
// Level 7
{
hp: 320,
atk: 38
},
// Level 8
{
hp: 380,
atk: 45
},
// Level 9
{
hp: 445,
atk: 53
},
// Level 10
{
hp: 515,
atk: 62
}];
// --- 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]
};
var enemyStatGrowth = {
hp: [enemyStatsByLevel[9].hp],
atk: [enemyStatsByLevel[9].atk]
};
// Store enemy stat percent increases per level (for linear scaling)
var enemyStatPercents = {
hp: [],
atk: []
};
// Store hero stat percent increases per level (for compounded scaling)
var heroStatPercents = {
hp: [],
atk: []
};
// 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 heroHpPct = randomPercent();
var heroAtkPct = randomPercent();
heroStatPercents.hp.push(heroHpPct);
heroStatPercents.atk.push(heroAtkPct);
heroStatGrowth.hp.push(Math.round(prevHeroHp * (1 + heroHpPct)));
heroStatGrowth.atk.push(Math.round(prevHeroAtk * (1 + heroAtkPct)));
// ENEMY: linear from level 10 base
var baseHp = enemyStatsByLevel[9].hp;
var baseAtk = enemyStatsByLevel[9].atk;
var enemyHpPct = randomPercent();
var enemyAtkPct = randomPercent();
enemyStatPercents.hp.push(enemyHpPct);
enemyStatPercents.atk.push(enemyAtkPct);
// For linear, sum all previous percent increases
var totalHpPct = 0;
var totalAtkPct = 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];
// 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)));
}
}
// 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];
// Always include equipment HP calculation for hero
if (type === "hero") {
var baseHp = Math.round(stats.hp * 1.5);
// At level 1, make sure hero attack is enough to defeat enemy 1
var baseAtk;
if (level === 1) {
// Enemy 1 HP: 60, Enemy 1 Atk: 10
// Give hero enough attack to defeat enemy in 6 hits (10 damage per hit)
baseAtk = 10;
} else {
baseAtk = Math.round(stats.atk * 0.6);
}
// --- Increase stats by 15% for each equipped item ---
var equippedCount = 0;
if (equippedItems) {
for (var k in equippedItems) {
if (equippedItems[k]) equippedCount++;
}
}
if (equippedCount > 0) {
var multiplier = 1 + 0.15 * equippedCount;
baseHp = Math.round(baseHp * multiplier);
baseAtk = Math.round(baseAtk * multiplier);
}
// Apply shield-1 effects if equipped
// No longer add shieldBonus to baseHp; shield-1 only gives barrier, not HP bonus
// Apply sword-1 effects if equipped
if (equippedItems && equippedItems["sword-1"]) {
var swordBonus = itemData["sword-1"].bonusAtk;
var swordUpgradeLevel = equippedItemUpgradeLevels["sword-1"] || 0;
if (swordUpgradeLevel > 0) {
swordBonus = Math.round(swordBonus * (1 + 0.1 * swordUpgradeLevel));
}
baseAtk += swordBonus;
}
return {
hp: baseHp,
atk: baseAtk
};
} else {
return {
hp: Math.round(stats.hp * 1.5),
// %50 daha fazla can
atk: Math.round(stats.atk * 0.6)
// %40 daha az atak
};
}
}
ensureStatGrowthUpTo(level);
var idx = level - 10;
if (type === "hero") {
// Base stats
var baseHp = heroStatGrowth.hp[idx];
var baseAtk = heroStatGrowth.atk[idx];
// --- Increase stats by 15% for each equipped item ---
var equippedCount = 0;
if (equippedItems) {
for (var k in equippedItems) {
if (equippedItems[k]) equippedCount++;
}
}
if (equippedCount > 0) {
var multiplier = 1 + 0.15 * equippedCount;
baseHp = Math.round(baseHp * multiplier);
baseAtk = Math.round(baseAtk * multiplier);
}
// Apply shield-1 effects if equipped
// No longer add shieldBonus to baseHp; shield-1 only gives barrier, not HP bonus
// Apply sword-1 effects if equipped
if (equippedItems && equippedItems["sword-1"]) {
var swordBonus = itemData["sword-1"].bonusAtk;
var swordUpgradeLevel = equippedItemUpgradeLevels["sword-1"] || 0;
if (swordUpgradeLevel > 0) {
swordBonus = Math.round(swordBonus * (1 + 0.1 * swordUpgradeLevel));
}
baseAtk += swordBonus;
}
return {
hp: baseHp,
atk: baseAtk
};
} else {
return {
hp: Math.round(enemyStatGrowth.hp[idx] * 1.5),
// %50 daha fazla can
atk: Math.round(enemyStatGrowth.atk[idx] * 0.6)
// %40 daha az atak
};
}
}
// For backward compatibility, keep getEnemyStatsForLevel for hero stats (used in refill, etc)
function getEnemyStatsForLevel(level) {
return getStatsForLevel(level, "hero");
}
function spawnEnemy() {
// --- DAĞ: spawn 1-4 random enemies (from 1-20) side by side ---
if (currentLocationId === "bg_dag") {
// Remove any previous enemies
if (Array.isArray(currentEnemy)) {
for (var i = 0; i < currentEnemy.length; i++) {
if (currentEnemy[i] && currentEnemy[i].parent) {
currentEnemy[i].destroy();
}
}
} else if (currentEnemy && currentEnemy.isAlive && currentEnemy.parent) {
currentEnemy.destroy();
}
currentEnemy = null;
// How many enemies? 1-4 random
var enemyCount = Math.floor(Math.random() * 4) + 1;
// Pick unique random levels for each enemy (from 1-20)
var possibleLevels = [];
for (var i = 1; i <= 20; i++) possibleLevels.push(i);
// Shuffle
for (var i = possibleLevels.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = possibleLevels[i];
possibleLevels[i] = possibleLevels[j];
possibleLevels[j] = temp;
}
var enemyLevels = possibleLevels.slice(0, enemyCount);
// Calculate spacing and position so that all enemies are on the right half, never crossing center, and always visible
var enemyWidth = 400; // estimate for safety, actual asset is 1280px but scaled down
var rightHalfStart = 2048 / 2;
var rightHalfEnd = 2048 - 100; // leave 100px margin on right
var availableWidth = rightHalfEnd - rightHalfStart;
var spacing = 0;
if (enemyCount > 1) {
spacing = Math.min(340, (availableWidth - enemyWidth) / (enemyCount - 1));
} else {
spacing = 0;
}
var totalWidth = (enemyCount - 1) * spacing;
var startX = rightHalfStart + (availableWidth - totalWidth - enemyWidth) / 2 + enemyWidth / 2;
if (startX < rightHalfStart + enemyWidth / 2) startX = rightHalfStart + enemyWidth / 2;
if (startX + totalWidth > rightHalfEnd - enemyWidth / 2) startX = rightHalfEnd - totalWidth - enemyWidth / 2;
currentEnemy = [];
for (var idx = 0; idx < enemyCount; idx++) {
var level = enemyLevels[idx];
var isEnemy2 = false;
var enemy;
if (level > 10) {
if (Math.random() < 0.5) {
enemy = new Enemy2();
isEnemy2 = true;
} else {
enemy = new Enemy();
}
} else {
enemy = new Enemy();
}
// Place enemies side by side, vertically aligned with hero
enemy.x = startX + idx * spacing;
enemy.y = hero.y + 100;
// Get stats for this level
var stats = getStatsForLevel(level, "enemy");
// Randomize stats ±30%
var statRand = Math.random();
var hpMod = 1,
atkMod = 1;
if (statRand < 0.3) {
hpMod = 0.7;
atkMod = 0.7;
} else if (statRand < 0.6) {
hpMod = 1.3;
atkMod = 1.3;
}
enemy.maxHp = Math.round(stats.hp * hpMod);
if (isEnemy2) {
enemy.hp = Math.round(stats.hp * 0.8 * hpMod);
enemy.attack = Math.round(stats.atk * 1.3 * atkMod);
} else {
enemy.hp = Math.round(stats.hp * hpMod);
enemy.attack = Math.round(stats.atk * atkMod);
}
enemy.isAlive = true;
enemy.spawnAnim();
game.addChild(enemy);
enemy.level = level;
enemy.isEnemy2 = isEnemy2;
enemy.isBoss = false;
// Attach tap handler for each enemy
(function (enemyObj) {
enemyObj.down = function (x, y, obj) {
if (!enemyObj.isAlive) return;
enemyObj.hp -= 1;
if (enemyObj.hp < 0) enemyObj.hp = 0;
// Flash enemy
tween(enemyObj, {
tint: 0xffffff
}, {
duration: 60,
onFinish: function onFinish() {
tween(enemyObj, {
tint: 0x2a6bde
}, {
duration: 60
});
}
});
if (enemyObj.hp <= 0) {
enemyObj.isAlive = false;
enemyObj.defeatAnim(function () {
enemyObj.destroy();
// Remove from currentEnemy array
for (var i = 0; i < currentEnemy.length; i++) {
if (currentEnemy[i] === enemyObj) {
currentEnemy.splice(i, 1);
break;
}
}
// Drop gold and items
// Gold drop logic (use same as defeatEnemy, but per enemy)
// --- DAĞ: Make gold drop proportional to number of enemies defeated ---
var goldDropByLevelIdx = Math.max(0, Math.min(level - 1, goldDropByLevel.length - 1));
var goldDropStats = goldDropByLevel[goldDropByLevelIdx];
var goldDropAmount = Math.floor(Math.random() * (goldDropStats.max - goldDropStats.min + 1)) + goldDropStats.min;
// If DAĞ and multi-enemy, multiply by total number of enemies spawned in this wave
if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy)) {
// enemyCount is the number of enemies spawned in this wave
// We need to find the total number of enemies that were spawned for this wave.
// Since currentEnemy is being spliced, we can track the original count.
// Let's use a property on the array to store the original count if not already set.
if (typeof currentEnemy._originalCount === "undefined") {
// Set on first defeat
currentEnemy._originalCount = currentEnemy.length + 1;
}
goldDropAmount = goldDropAmount * currentEnemy._originalCount;
}
// Drop gold at enemy position
var goldDisplayGlobal = LK.gui.topRight.toGlobal({
x: goldTxt.x,
y: goldTxt.y
});
var goldDisplayGamePos = game.toLocal(goldDisplayGlobal);
for (var g = 0; g < goldDropAmount; g++) {
var gold = new Gold();
gold.x = enemyObj.x;
gold.y = enemyObj.y;
gold.scaleX = 1;
gold.scaleY = 1;
gold.alpha = 1;
game.addChild(gold);
golds.push(gold);
var dropY = gold.y + (Math.random() * 120 - 60);
(function (goldObj, idx) {
goldObj.dropAnim(goldObj.x, dropY, function () {
LK.setTimeout(function () {
goldObj.collectAnim(goldDisplayGamePos.x, goldDisplayGamePos.y, function () {
goldAmount += 1;
updateGoldDisplay();
goldObj.destroy();
});
}, 80 * idx);
});
})(gold, g);
}
// Shield-1 drop logic (5% per level, capped at 50% for level 10)
if (level >= 1 && level <= 10 && !enemyObj.isEnemy2) {
var shieldDropChance = level * 0.05;
if (Math.random() < shieldDropChance) {
var shieldAsset = LK.getAsset('shield-1', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyObj.x,
y: enemyObj.y
});
game.addChild(shieldAsset);
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();
inventory.push("shield-1");
}
});
}
}
// Sword-1 drop logic (Enemy2, level 10/20 always, else 15%)
if (enemyObj.isEnemy2) {
var swordDrop = false;
if (level === 10 || level === 20) {
swordDrop = true;
} else if (Math.random() < 0.15) {
swordDrop = true;
}
if (swordDrop) {
var swordAsset = LK.getAsset('sword-1', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyObj.x,
y: enemyObj.y
});
game.addChild(swordAsset);
var itemBagGlobalSword = LK.gui.bottom.toGlobal({
x: itemBagImg.x,
y: itemBagImg.y
});
var itemBagGamePosSword = game.toLocal(itemBagGlobalSword);
tween(swordAsset, {
x: itemBagGamePosSword.x,
y: itemBagGamePosSword.y,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.2
}, {
duration: 700,
easing: tween.cubicIn,
onFinish: function onFinish() {
swordAsset.destroy();
inventory.push("sword-1");
}
});
}
}
});
}
};
})(enemy);
currentEnemy.push(enemy);
}
// DAĞ: auto-fight all enemies in array
if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy) && currentEnemy.length > 0) {
// Defensive: clear any previous 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
var heroStats = getStatsForLevel(heroLevel, "hero");
hero.currentHp = heroStats.hp;
hero.attack = heroStats.atk;
if (equippedItems && equippedItems["sword-1"]) {
hero.attack += itemData["sword-1"].bonusAtk;
}
// Hero attacks all alive enemies in array, one per second
heroAutoAttackTimer = LK.setInterval(function () {
// Defensive: skip if no enemies left
if (!Array.isArray(currentEnemy) || currentEnemy.length === 0) {
LK.clearInterval(heroAutoAttackTimer);
heroAutoAttackTimer = null;
if (typeof enemyAutoAttackTimer !== "undefined" && enemyAutoAttackTimer) {
LK.clearInterval(enemyAutoAttackTimer);
enemyAutoAttackTimer = null;
}
return;
}
// Animate hero and equipped items: move slightly right and return
var heroAttackMoveX = 32;
tween.stop(hero, {
x: true
});
tween(hero, {
x: hero.x + heroAttackMoveX
}, {
duration: 60,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(hero, {
x: hero.x - heroAttackMoveX
}, {
duration: 80,
easing: tween.cubicIn
});
}
});
// Animate equipped visuals if any
if (_typeof(hero.equippedVisuals) === "object" && hero.equippedVisuals) {
for (var k in hero.equippedVisuals) {
if (hero.equippedVisuals[k]) {
tween.stop(hero.equippedVisuals[k], {
x: true
});
var eq = hero.equippedVisuals[k];
var origX = typeof eq._origX === "number" ? eq._origX : eq.x;
eq._origX = origX;
tween(eq, {
x: origX + heroAttackMoveX
}, {
duration: 60,
easing: tween.cubicOut,
onFinish: function (eq, origX) {
return function () {
tween(eq, {
x: origX
}, {
duration: 80,
easing: tween.cubicIn
});
};
}(eq, origX)
});
}
}
}
// Attack all alive enemies
for (var i = 0; i < currentEnemy.length; i++) {
var e = currentEnemy[i];
if (!e || !e.isAlive) continue;
// If one-shot mode, instantly defeat
if (heroOneShotEnemies) {
e.hp = 0;
} else {
e.hp -= hero.attack;
if (e.hp < 0) e.hp = 0;
}
// Flash enemy
tween(e, {
tint: 0xffffff
}, {
duration: 60,
onFinish: function (e) {
return function () {
tween(e, {
tint: 0x2a6bde
}, {
duration: 60
});
};
}(e)
});
// If enemy defeated, trigger its defeatAnim and remove from array
if (e.hp <= 0 && e.isAlive) {
e.isAlive = false;
(function (enemyObj) {
enemyObj.defeatAnim(function () {
if (!Array.isArray(currentEnemy)) return;
// Remove from currentEnemy array
for (var j = 0; j < currentEnemy.length; j++) {
if (currentEnemy[j] === enemyObj) {
currentEnemy.splice(j, 1);
break;
}
}
// Drop gold and items (same as tap logic)
var level = enemyObj.level || heroLevel;
var goldDropByLevelIdx = Math.max(0, Math.min(level - 1, goldDropByLevel.length - 1));
var goldDropStats = goldDropByLevel[goldDropByLevelIdx];
var goldDropAmount = Math.floor(Math.random() * (goldDropStats.max - goldDropStats.min + 1)) + goldDropStats.min;
// If DAĞ and multi-enemy, multiply by total number of enemies spawned in this wave
if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy)) {
if (typeof currentEnemy._originalCount === "undefined") {
// Set on first defeat
currentEnemy._originalCount = currentEnemy.length + 1;
}
goldDropAmount = goldDropAmount * currentEnemy._originalCount;
}
var goldDisplayGlobal = LK.gui.topRight.toGlobal({
x: goldTxt.x,
y: goldTxt.y
});
var goldDisplayGamePos = game.toLocal(goldDisplayGlobal);
for (var g = 0; g < goldDropAmount; g++) {
var gold = new Gold();
gold.x = enemyObj.x;
gold.y = enemyObj.y;
gold.scaleX = 1;
gold.scaleY = 1;
gold.alpha = 1;
game.addChild(gold);
golds.push(gold);
var dropY = gold.y + (Math.random() * 120 - 60);
(function (goldObj, idx) {
goldObj.dropAnim(goldObj.x, dropY, function () {
LK.setTimeout(function () {
goldObj.collectAnim(goldDisplayGamePos.x, goldDisplayGamePos.y, function () {
goldAmount += 1;
updateGoldDisplay();
goldObj.destroy();
});
}, 80 * idx);
});
})(gold, g);
}
// Shield-1 drop logic (5% per level, capped at 50% for level 10)
if (level >= 1 && level <= 10 && !enemyObj.isEnemy2) {
var shieldDropChance = level * 0.05;
if (Math.random() < shieldDropChance) {
var shieldAsset = LK.getAsset('shield-1', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyObj.x,
y: enemyObj.y
});
game.addChild(shieldAsset);
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();
inventory.push("shield-1");
}
});
}
}
// Sword-1 drop logic (Enemy2, level 10/20 always, else 15%)
if (enemyObj.isEnemy2) {
var swordDrop = false;
if (level === 10 || level === 20) {
swordDrop = true;
} else if (Math.random() < 0.15) {
swordDrop = true;
}
if (swordDrop) {
var swordAsset = LK.getAsset('sword-1', {
anchorX: 0.5,
anchorY: 0.5,
x: enemyObj.x,
y: enemyObj.y
});
game.addChild(swordAsset);
var itemBagGlobalSword = LK.gui.bottom.toGlobal({
x: itemBagImg.x,
y: itemBagImg.y
});
var itemBagGamePosSword = game.toLocal(itemBagGlobalSword);
tween(swordAsset, {
x: itemBagGamePosSword.x,
y: itemBagGamePosSword.y,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.2
}, {
duration: 700,
easing: tween.cubicIn,
onFinish: function onFinish() {
swordAsset.destroy();
inventory.push("sword-1");
}
});
}
}
enemyObj.destroy();
updateEnemyStatsDisplay();
});
})(e);
}
}
updateEnemyStatsDisplay();
// If all enemies are defeated, stop timer
if (!Array.isArray(currentEnemy) || currentEnemy.length === 0) {
LK.clearInterval(heroAutoAttackTimer);
heroAutoAttackTimer = null;
if (typeof enemyAutoAttackTimer !== "undefined" && enemyAutoAttackTimer) {
LK.clearInterval(enemyAutoAttackTimer);
enemyAutoAttackTimer = null;
}
}
}, 1000);
// All enemies attack hero, one per second
enemyAutoAttackTimer = LK.setInterval(function () {
if (!Array.isArray(currentEnemy) || currentEnemy.length === 0) {
LK.clearInterval(enemyAutoAttackTimer);
enemyAutoAttackTimer = null;
if (typeof heroAutoAttackTimer !== "undefined" && heroAutoAttackTimer) {
LK.clearInterval(heroAutoAttackTimer);
heroAutoAttackTimer = null;
}
return;
}
if (typeof hero.currentHp !== "number") {
var hStats = getEnemyStatsForLevel(heroLevel);
hero.currentHp = hStats.hp;
}
if (!heroIsImmortal) {
// Sum all alive enemy attacks
var totalDmg = 0;
for (var i = 0; i < currentEnemy.length; i++) {
var e = currentEnemy[i];
if (e && e.isAlive && typeof e.attack === "number") {
totalDmg += e.attack;
}
}
// --- Shield-1 barrier logic: block damage with barrier first ---
if (equippedItems && equippedItems["shield-1"] && heroShield1Barrier > 0) {
var dmg = totalDmg;
if (heroShield1Barrier >= dmg) {
heroShield1Barrier -= dmg;
dmg = 0;
} else {
dmg -= heroShield1Barrier;
heroShield1Barrier = 0;
}
if (dmg > 0) {
hero.currentHp -= dmg;
}
} else {
hero.currentHp -= totalDmg;
}
// 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();
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);
updateEnemyStatsDisplay();
return;
}
updateEnemyStatsDisplay();
return;
}
// --- DEFAULT: single enemy logic (as before) ---
if (currentEnemy && currentEnemy.isAlive) return; // Only one at a time
if (hero.healthRefilling) return; // Don't allow spawn while refilling
var enemy;
var isEnemy2 = false;
// --- BOSS LOGIC ---
// Increment enemy spawn count
enemySpawnCount = (typeof enemySpawnCount === "number" ? enemySpawnCount : 0) + 1;
var isBoss = enemySpawnCount % 8 === 0;
// 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);
}
// Orman seçeneğinde benden yüksek seviyede düşman gelme ihtimali %5 olsun
var enemyLevel;
if (currentLocationId === "bg_orman") {
// %5 ihtimalle heroLevel+1 veya heroLevel+2, %95 ihtimalle heroLevel veya heroLevel-1
if (Math.random() < 0.05) {
// Yüksek seviye: heroLevel+1 veya heroLevel+2
var highLevels = [];
for (var i = 0; i < uniqueLevels.length; i++) {
if (uniqueLevels[i] > heroLevel) highLevels.push(uniqueLevels[i]);
}
if (highLevels.length > 0) {
enemyLevel = highLevels[Math.floor(Math.random() * highLevels.length)];
} else {
enemyLevel = heroLevel;
}
} else {
// Düşük/aynı seviye: heroLevel veya heroLevel-1
var lowLevels = [];
for (var i = 0; i < uniqueLevels.length; i++) {
if (uniqueLevels[i] <= heroLevel) lowLevels.push(uniqueLevels[i]);
}
if (lowLevels.length > 0) {
enemyLevel = lowLevels[Math.floor(Math.random() * lowLevels.length)];
} else {
enemyLevel = heroLevel;
}
}
} else {
// Diğer lokasyonlar: eski random seçimi
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));
// Decide which enemy type to spawn
if (enemyLevel > 10) {
// After level 10, 50% chance for Enemy2, 50% for Enemy
if (Math.random() < 0.5) {
enemy = new Enemy2();
isEnemy2 = true;
} else {
enemy = new Enemy();
}
} else {
enemy = new Enemy();
}
// Place enemy on the far right, vertically aligned with hero
if (isEnemy2) {
enemy.x = 2048 - 400; // Move Enemy2 200px further left than Enemy
} else {
enemy.x = 2048 - 200; // 200px from the right edge, matching hero's 200px from left
}
enemy.y = hero.y;
// Get stats for this level (enemy uses linear scaling after level 10)
var stats = getStatsForLevel(enemyLevel, "enemy");
// --- RANDOMIZE ENEMY STATS: hp/atk ±30% for 30% ---
// 0-0.3: -30% hp/atk, 0.3-0.6: +30% hp/atk, 0.6-1.0: normal
var statRand = Math.random();
var hpMod = 1,
atkMod = 1;
if (statRand < 0.3) {
hpMod = 0.7;
atkMod = 0.7;
} else if (statRand < 0.6) {
hpMod = 1.3;
atkMod = 1.3;
}
// Set maxHp for enemy, so it matches the randomized HP value
enemy.maxHp = Math.round(stats.hp * hpMod);
// --- BOSS STAT MODIFIERS ---
if (isBoss) {
// HP +100%, Atk +50%
enemy.hp = Math.round(stats.hp * 2.0 * hpMod);
enemy.attack = Math.round(stats.atk * 1.5 * atkMod);
// Make enemy 50% larger
enemy.scaleX = (typeof enemy.scaleX === "number" ? enemy.scaleX : 1) * 1.5;
enemy.scaleY = (typeof enemy.scaleY === "number" ? enemy.scaleY : 1) * 1.5;
// Add BOSS label above enemy
var bossLabel = new Text2("BOSS", {
size: 90,
fill: 0xFF2222,
glow: {
color: 0xffffff,
distance: 10,
strength: 2
}
});
bossLabel.anchor.set(0.5, 1);
bossLabel.x = 0;
bossLabel.y = -((enemy.height || 300) / 2) - 30;
enemy.addChild(bossLabel);
enemy.isBoss = true;
} else if (isEnemy2) {
// CAN %20 DAHA AZ, ATAK %30 DAHA ÇOK
enemy.hp = Math.round(stats.hp * 0.8 * hpMod);
enemy.attack = Math.round(stats.atk * 1.3 * atkMod);
} else {
enemy.hp = Math.round(stats.hp * hpMod);
enemy.attack = Math.round(stats.atk * atkMod);
}
enemy.isAlive = true;
enemy.spawnAnim();
game.addChild(enemy);
currentEnemy = enemy;
// Store the enemy's level for display
currentEnemy.level = enemyLevel;
currentEnemy.isEnemy2 = isEnemy2; // Track type for possible future use
currentEnemy.isBoss = !!isBoss;
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;
// Calculate hero attack, always include sword-1 bonus if equipped
hero.attack = heroStats.atk;
if (equippedItems && equippedItems["sword-1"]) {
hero.attack += itemData["sword-1"].bonusAtk;
}
// Hero attacks enemy (fixed interval, e.g. 1s)
heroAutoAttackTimer = LK.setInterval(function () {
if (!currentEnemy || !currentEnemy.isAlive) {
LK.clearInterval(heroAutoAttackTimer);
heroAutoAttackTimer = null;
return;
}
// Animate hero and equipped items: move slightly right and return
var heroAttackMoveX = 32;
tween.stop(hero, {
x: true
});
tween(hero, {
x: hero.x + heroAttackMoveX
}, {
duration: 60,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(hero, {
x: hero.x - heroAttackMoveX
}, {
duration: 80,
easing: tween.cubicIn
});
}
});
// Animate equipped visuals if any
if (_typeof(hero.equippedVisuals) === "object" && hero.equippedVisuals) {
for (var k in hero.equippedVisuals) {
if (hero.equippedVisuals[k]) {
tween.stop(hero.equippedVisuals[k], {
x: true
});
var eq = hero.equippedVisuals[k];
var origX = typeof eq._origX === "number" ? eq._origX : eq.x;
eq._origX = origX;
tween(eq, {
x: origX + heroAttackMoveX
}, {
duration: 60,
easing: tween.cubicOut,
onFinish: function (eq, origX) {
return function () {
tween(eq, {
x: origX
}, {
duration: 80,
easing: tween.cubicIn
});
};
}(eq, origX)
});
}
}
}
// If one-shot mode, instantly defeat enemy
if (heroOneShotEnemies) {
currentEnemy.hp = 0;
} else {
currentEnemy.hp -= hero.attack;
if (currentEnemy.hp < 0) currentEnemy.hp = 0;
}
// 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); // Fixed 1s interval
// Enemy attacks hero (fixed interval, e.g. 1s)
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) {
// --- Shield-1 barrier logic: block damage with barrier first ---
if (equippedItems && equippedItems["shield-1"] && heroShield1Barrier > 0) {
var dmg = currentEnemy.attack;
if (heroShield1Barrier >= dmg) {
heroShield1Barrier -= dmg;
dmg = 0;
} else {
dmg -= heroShield1Barrier;
heroShield1Barrier = 0;
}
if (dmg > 0) {
hero.currentHp -= dmg;
}
} else {
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); // Fixed 1s interval
}
// 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, and only from Enemy (not Enemy2)
if (typeof currentEnemy.level !== "undefined" && currentEnemy.level >= 1 && currentEnemy.level <= 10 && !currentEnemy.isEnemy2) {
// 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 only (do not auto-equip)
inventory.push("shield-1");
}
});
}
}
// --- Sword-1 drop logic: only for Enemy2, and only for level 10 and 20 enemies ---
// Now: Drop chance is 100% at level 10/20, and for all other levels, 15% chance per defeat from Enemy2
if (typeof currentEnemy.level !== "undefined" && currentEnemy.isEnemy2) {
var swordDrop = false;
if (currentEnemy.level === 10 || currentEnemy.level === 20) {
swordDrop = true; // Always drop at level 10 and 20
} else {
// 15% drop chance for all other levels from Enemy2
if (Math.random() < 0.15) swordDrop = true;
}
if (swordDrop) {
var swordAsset = LK.getAsset('sword-1', {
anchorX: 0.5,
anchorY: 0.5,
x: currentEnemy.x,
y: currentEnemy.y
});
game.addChild(swordAsset);
// Animate drop: move to itemBag position and shrink/fade out
var itemBagGlobalSword = LK.gui.bottom.toGlobal({
x: itemBagImg.x,
y: itemBagImg.y
});
var itemBagGamePosSword = game.toLocal(itemBagGlobalSword);
tween(swordAsset, {
x: itemBagGamePosSword.x,
y: itemBagGamePosSword.y,
scaleX: 0.3,
scaleY: 0.3,
alpha: 0.2
}, {
duration: 700,
easing: tween.cubicIn,
onFinish: function onFinish() {
swordAsset.destroy();
// Add to inventory only (do not auto-equip)
inventory.push("sword-1");
}
});
}
}
// Track boss defeat for level gating
if (typeof heroDefeatedBosses === "undefined") heroDefeatedBosses = [];
if (currentEnemy && currentEnemy.isBoss && typeof currentEnemy.level === "number") {
// Bosses are at spawn counts 8, 16, 24, ... which correspond to levels 5, 10, 15, ...
// So, for level gating, bossIndex = Math.floor((currentEnemy.level) / 5)
var bossIndex = Math.floor(currentEnemy.level / 5);
heroDefeatedBosses[bossIndex] = true;
}
currentEnemy.destroy();
currentEnemy = null;
updateEnemyStatsDisplay();
// HERO CANINI FULLLE!
var stats = getStatsForLevel(heroLevel, "hero");
hero.currentHp = stats.hp;
updateHeroStatsDisplay();
// If shield-1 is equipped, restore hero HP to new max after enemy defeat
if (equippedItems["shield-1"]) {
heroShield1Barrier = 250;
heroShield1BarrierMax = 250;
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 = [
// Level 1
{
min: 1,
max: 5
},
// Level 2
{
min: 3,
max: 8
},
// Level 3
{
min: 5,
max: 12
},
// Level 4
{
min: 8,
max: 16
},
// Level 5
{
min: 12,
max: 20
},
// Level 6
{
min: 15,
max: 25
},
// Level 7
{
min: 20,
max: 32
},
// Level 8
{
min: 25,
max: 40
},
// Level 9
{
min: 30,
max: 48
},
// Level 10
{
min: 35,
max: 60
}];
// Defensive: If goldDropByLevel is referenced for higher levels, extend with scaled values
(function extendGoldDropByLevel() {
var last = goldDropByLevel[goldDropByLevel.length - 1];
for (var i = goldDropByLevel.length; i < 100; i++) {
// Increase min/max by 10% per level after 10
var prev = goldDropByLevel[i - 1];
goldDropByLevel.push({
min: Math.round(prev.min * 1.1),
max: Math.round(prev.max * 1.1)
});
}
})();
// 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;
// Boss: drop 50% more gold
if (currentEnemy && currentEnemy.isBoss) {
goldDropAmount = Math.round(goldDropAmount * 1.5);
}
// 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;
}
// --- Boss defeat requirement for every 5th level ---
var nextLevel = heroLevel + 1;
var mustDefeatBoss = false;
if (nextLevel > 5 && (nextLevel - 1) % 5 === 0) {
// For 6, 11, 16, ... 501, etc. (i.e. 6 = after 1st boss, 11 = after 2nd boss, ...)
var bossIndex = Math.floor((nextLevel - 1) / 5); // 6->1, 11->2, 16->3, ...
// Track defeated bosses in an array
if (typeof heroDefeatedBosses === "undefined") heroDefeatedBosses = [];
if (!heroDefeatedBosses[bossIndex]) {
// Block upgrade, flash upgradeBtn red
tween(upgradeBtn, {
tint: 0xff4444
}, {
duration: 120,
onFinish: function onFinish() {
tween(upgradeBtn, {
tint: 0xffffff
}, {
duration: 120
});
}
});
// Optionally show a message (not required)
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;
if (currentEnemy.hp < 0) currentEnemy.hp = 0;
// 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 duration = Math.max(10, Math.pow(heroLevel, 1.2) * 2); // Simple duration, e.g. 2s per level^1.2
// 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 / 2) / random(1-5)
var stats = getStatsForLevel(heroLevel, "hero");
var divisor = Math.floor(Math.random() * 5) + 1;
var goldVal = heroLevel + 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) {
// 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 () {
// Hide spawnBtn if current location is şehir, demirci, maden, kale, or sahil
if (currentLocationId === "bg_sehir" || currentLocationId === "bg_demirci" || currentLocationId === "bg_maden" || currentLocationId === "bg_kale" || currentLocationId === "bg_sahil") {
if (typeof spawnBtn !== "undefined" && spawnBtn) spawnBtn.visible = false;
if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = false;
// Always show demirciBtn if in demirci
if (currentLocationId === "bg_demirci" && typeof demirciBtn !== "undefined" && demirciBtn) {
demirciBtn.visible = true;
}
// Show madenBtn only in maden
if (typeof madenBtn !== "undefined" && madenBtn) {
madenBtn.visible = currentLocationId === "bg_maden";
// Check if kazma is in inventory
var hasKazma = false;
for (var i = 0; i < inventory.length; i++) {
if (inventory[i] === "kazma") {
hasKazma = true;
break;
}
}
if (madenBtn.visible) {
// Only allow madenBtn if kazma is EQUIPPED, not just in inventory
var kazmaEquipped = !!equippedItems["kazma"];
if (!kazmaEquipped) {
madenBtn.alpha = 0.5;
madenBtn.interactive = false;
madenBtn.buttonMode = false;
} else {
madenBtn.alpha = 1;
madenBtn.interactive = true;
madenBtn.buttonMode = true;
}
}
}
// Show kaleBtn only in kale
if (typeof kaleBtn !== "undefined" && kaleBtn) {
kaleBtn.visible = currentLocationId === "bg_kale";
}
} else {
if (typeof spawnBtn !== "undefined" && spawnBtn) spawnBtn.visible = true;
if (typeof findEnemyTxt !== "undefined" && findEnemyTxt) findEnemyTxt.visible = true;
// Hide demirciBtn if not in demirci
if (typeof demirciBtn !== "undefined" && demirciBtn) {
demirciBtn.visible = false;
}
// Hide madenBtn if not in maden
if (typeof madenBtn !== "undefined" && madenBtn) {
madenBtn.visible = false;
}
// Hide kaleBtn if not in kale
if (typeof kaleBtn !== "undefined" && kaleBtn) {
kaleBtn.visible = false;
}
}
// 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)
// --- DAĞ: Remove all enemies and prevent gold drop on hero defeat ---
if (currentLocationId === "bg_dag" && Array.isArray(currentEnemy)) {
// Remove all DAĞ enemies
for (var i = 0; i < currentEnemy.length; i++) {
if (currentEnemy[i] && currentEnemy[i].isAlive) {
currentEnemy[i].isAlive = false;
// Animate defeat, but do not drop gold/items
(function (enemyObj) {
enemyObj.defeatAnim(function () {
if (enemyObj && enemyObj.parent) {
enemyObj.destroy();
}
});
})(currentEnemy[i]);
}
}
currentEnemy = null;
updateEnemyStatsDisplay();
// --- DAĞ: Restore hero shield and health after fight, just like ORMAN ---
// Always restore barrier to max after refill, if shield is equipped
if (equippedItems && equippedItems["shield-1"]) {
var baseBarrier = 250;
var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0;
if (shieldUpgradeLevel > 0) {
baseBarrier = Math.round(baseBarrier * (1 + 0.1 * shieldUpgradeLevel));
}
heroShield1Barrier = baseBarrier;
heroShield1BarrierMax = baseBarrier;
} else {
heroShield1Barrier = 0;
heroShield1BarrierMax = 0;
}
// Restore hero health to FULL after DAĞ fight (like ORMAN)
var stats = getStatsForLevel(heroLevel, "hero");
hero.currentHp = stats.hp;
updateHeroStatsDisplay();
} else 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;
// After refill, if shield-1 is equipped, restore barrier to max
if (equippedItems && equippedItems["shield-1"]) {
heroShield1Barrier = 250;
heroShield1BarrierMax = 250;
}
}
}
// 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 && typeof workBtnCountdownTxt.destroyed === "boolean" && !workBtnCountdownTxt.destroyed && typeof workBtnCountdownTxt.setText === "function" && typeof workBtnCountdownTxt.x !== "undefined" && typeof workBtnCountdownTxt.y !== "undefined") {
// Defensive: Only access .visible if it exists, and never access .setAsset
if ((typeof workBtnCountdownTxt.visible === "undefined" || workBtnCountdownTxt.visible) && typeof workBtnCountdownTxt.x !== "undefined" && typeof workBtnCountdownTxt.y !== "undefined") {
workBtnCountdownTxt.x = workBtn.x;
workBtnCountdownTxt.y = workBtn.y + workBtn.height / 2 + 8;
}
}
};
// --- Initial UI state ---
updateGoldDisplay();
updateUpgradeDisplay();
updateHeroStatsDisplay();
updateEnemyStatsDisplay();
// --- Hero HP and Shield Auto-Regeneration Logic ---
// Regenerate 25% of max HP per second, and refill shield barrier, if no enemy is present
if (typeof heroAutoRegenInterval === "undefined") {
var heroAutoRegenInterval = null;
}
if (heroAutoRegenInterval) {
LK.clearInterval(heroAutoRegenInterval);
heroAutoRegenInterval = null;
}
heroAutoRegenInterval = LK.setInterval(function () {
// Defensive: Only run if hero exists and not in battle
if (!hero || typeof hero.currentHp !== "number") return;
// If any enemy is alive, do not regen
var enemyAlive = false;
if (Array.isArray(currentEnemy)) {
for (var i = 0; i < currentEnemy.length; i++) {
if (currentEnemy[i] && currentEnemy[i].isAlive) {
enemyAlive = true;
break;
}
}
} else if (currentEnemy && currentEnemy.isAlive) {
enemyAlive = true;
}
if (enemyAlive) return;
// Regen HP if not full
var stats = getStatsForLevel(heroLevel, "hero");
var maxHp = stats.hp;
if (typeof hero.currentHp !== "number" || hero.currentHp >= maxHp) {
hero.currentHp = Math.min(maxHp, hero.currentHp);
} else {
var regenAmount = Math.ceil(maxHp * 0.25);
hero.currentHp = Math.min(maxHp, hero.currentHp + regenAmount);
updateHeroStatsDisplay();
}
// Regen shield barrier if equipped and not full
if (equippedItems && equippedItems["shield-1"]) {
var maxBarrier = 250;
var shieldUpgradeLevel = equippedItemUpgradeLevels["shield-1"] || 0;
if (shieldUpgradeLevel > 0) {
maxBarrier = Math.round(maxBarrier * (1 + 0.1 * shieldUpgradeLevel));
}
if (typeof heroShield1Barrier !== "number" || heroShield1Barrier >= maxBarrier) {
heroShield1Barrier = Math.min(maxBarrier, heroShield1Barrier);
heroShield1BarrierMax = maxBarrier;
} else {
// Refill all missing barrier at once per second
heroShield1Barrier = maxBarrier;
heroShield1BarrierMax = maxBarrier;
updateHeroStatsDisplay();
}
}
}, 1000);