/****
* 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);