Code edit (4 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'x')' in or related to this line: 'if (self.x < player.x) {' Line Number: 425
User prompt
Çözülmesi gereken büyük bir problem (sorun) var. Öncelikle bu sorun üzerine iyice düşün ve kafanı yor. Şu anda 2. dalgada gelen bossZombie'nin zombieRebirth özelliği var, arasıra etrafında zombi yaratıyor fakat 10. dalgada gelen (ve sonraki her 10 dalgada gelen) bossZombie'nin neden zombieRebirth özelliği çalışmıyor? 10. dalgada ve sonraki her 10 dalgada gelen bossZombie'lerin sadece yakın ve uzak dövüş modları var, zombieRebirth özellikleri çalışmıyor! Kodu iyice analiz edip sorunun kaynağını tespit et ve kodu düzelt lütfen. Teşekkürler.
User prompt
Şu anda 2. dalgada gelen bossZombie'nin zombieRebirth özelliği var, arasıra etrafında zombi yaratıyor fakat 10. dalgada gelen (ve sonraki her 10 dalgada gelen) bossZombie'nin neden zombieRebirth özelliği çalışmıyor? 10. dalgada ve sonraki her 10 dalgada gelen bossZombie'lerin sadece yakın ve uzak dövüş modları var, zombieRebirth özellikleri çalışmıyor! Kodu iyice analiz edip sorunun kaynağını tespit et ve kodu düzelt lütfen. Teşekkürler.
User prompt
2. dalgada bossZombie gelsin.
User prompt
Kodu düzelt o halde, optimizasyona başla.
User prompt
Kanama (bleeding) buff'unu oyundan kaldır.
User prompt
Ayrıca istiyorum ki 4 kart seçim kısmında 4. kartımın rengi de 1. 2. 3. kart gibi olsun yani farklı olmasın. Şu anda 4. kartta bir renk değişikliği oluyor.
User prompt
Ama şu anda ben tam yeni dalga gelirken seviye atlayıp 4 kart seçimini açtığım zaman o 3 2 1 yazısının da durması ve diğer dalganın spawn'ı için geçen kalan sürenin de durması gerekiyor. Ben kartımı seçtikten sonra devam etmeli.
User prompt
Hani bir dalga bittikten sonra diğer dalgaya geçerken 3 saniyelik bir bekleme süresi var ya, bu bekleme süresindeyken hiçbir silahımın saldırmasını istemiyorum yani bu bekleme süresindeyken görselleri ve sesleri anında durmalı, dalga başladığı zaman tekrar başlamalı. Ayrıca bir dalga bittikten sonra diğer dalga başlayana kadar Dalga (Wave) yazısının altında "3", "2", "1" diye kırmızı renkli bir geri sayım olmalı ve bu geri sayımdan sonra diğer dalga gelmeli. Bu arada ilk dalgayı direkt spawn etme, ben 9 kart seçiminde silahımı seçtikten sonra spawn et, şu anda ben daha kartımı seçmeden zombi spawn oluyor, bunu istemiyorum.
User prompt
Sen bu problemi çözemedin bir türlü. En iyisi grit wound buff'unu oyundan kaldır direkt.
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'call')' in or related to this line: 'Enemy.prototype.update.call(self);' Line Number: 852
User prompt
Ama şu anda derin yara aldığım zaman normal zombi türü hasar alabiliyor evet ama mesela rangedZombie türü hasar almıyor. Diğer zombi türleri de hasar almıyor olabilir. Bunu neden düzeltmedin? Bu sorunları çözmen şart!
User prompt
Şu anda derin yara buff'unu aldığım zaman bu tüm zombi türlerinde çalışmıyor, sadece normal zombide çalışıyor, düzgün de çalışmıyor. Bu buff'u alınca karakterimin hasar verdiği düşmanlar (tüm zombi türleri sayılır) 4 saniye boyunca her 0.5 saniyede bir azami canlarının %2 kadarı hasar almalı, bu yüzde her yükseltişte +1.5 artmalı (%2, %3.5, %5, %6.5, %8 olarak). Ayrıca şu anda derin yara buff'umda çok büyük bir bug var, karakterim bu buff'u alınca can yenilenmesi olmayan düşmanlara vurduğunda vurduğu düşmanlar sonsuz can yenilenmesi alıyor ve ölümsüz oluyorlar. Bunları düzeltmen lazım. Derin yara buff'u, karakterimin hasar verdiği düşmanın (tüm zombi türleri sayılır) 4 saniyeliğine can yenilenmesi oranını azaltması gerekiyor, ilk önce %10 ve sonraki yükseltislerde yüzdesi +15 artacak şekilde (%10, %25,%40,%55,%70) olarak. Kendi özelliği olarak can yenilenmesi olmayan zombi türleri sadece şifacı zombinin potuyla can yenileyebilir, kendi özelliği ile can yenilenmesi olan zombi türleri (bossZombie mesela) hem şifacı zombinin potuyla hem de kendi özelliği ile can yenileyebiliyor. Kodumu iyice incele ve istediğim şekilde düzelt.
User prompt
Bir dalga bitince diğerine geçerken 3 saniyelik falan bir bekleme süresi vardı ya bu bekleme süresini kaldırabilir miyiz? Bekleme süresi olmasın istiyorum artık. Bir dalga bittikten sonra direkt diğer dalga başlamalı.
Code edit (3 edits merged)
Please save this source code
User prompt
Şu anda dil seçeneklerinden Türkçe'yi seçince "Open Beta" yazısı "Açık Beta" olarak değişmiyor. Bunu düzelt.
Code edit (1 edits merged)
Please save this source code
User prompt
Şu anda öldükten sonra bazen ala oyun ekranındaki sesleri (özellikle silahların saldırı seslerini) duymaya devam ediyorum. Bunu düzeltir misin? (Özellikle mesela ölüm ekranında kılıç savurma sesini falan duyuyorum sürekli.). Ayrıca ana menü ekranındaki "Instagram: ugurcanyardim_" yazısının biraz sağında Türkçe'de "Açık Beta", İngilizce'de "Open Beta" yazsın.
Code edit (1 edits merged)
Please save this source code
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Bomb = Container.expand(function () {
	var self = Container.call(this);
	self.active = true;
	var bombGraphics = self.attachAsset('bomb', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 60,
		height: 60,
		tint: 0xff0000
	});
	self.update = function () {
		if (!player || !self.active) {
			return;
		}
		var dx = player.x - self.x;
		var dy = player.y - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist < 80) {
			self.active = false;
			// --- FULL SCREEN PURE WHITE FLASH EFFECT (3s fade out) ---
			var whiteFlash = new Container();
			var whiteRect = whiteFlash.attachAsset('hpBarRect', {
				anchorX: 0,
				anchorY: 0,
				x: 0,
				y: 0,
				width: 2048,
				height: 2732,
				color: 0xffffff,
				// ensure pure white
				tint: 0xffffff,
				// ensure pure white
				alpha: 1
			});
			whiteFlash.x = 0;
			whiteFlash.y = 0;
			whiteFlash.zIndex = 9999; // Defensive: ensure on top
			game.addChild(whiteFlash);
			tween(whiteRect, {
				alpha: 0
			}, {
				duration: 3000,
				easing: tween.linear,
				onFinish: function onFinish() {
					if (whiteFlash.parent) {
						whiteFlash.destroy();
					}
				}
			});
			// --- Play bombBoomSound once, always ---
			if (LK.getSound && LK.getSound('bombBoomSound')) {
				var snd = LK.getSound('bombBoomSound');
				if (typeof snd.stop === "function") {
					snd.stop();
				} // Defensive: stop if already playing
				snd.play();
			}
			// Deal 20 damage to all non-boss enemies on screen
			for (var i = enemies.length - 1; i >= 0; i--) {
				var enemy = enemies[i];
				var screenDx = Math.abs(enemy.x - player.x);
				var screenDy = Math.abs(enemy.y - player.y);
				if (screenDx < 1024 && screenDy < 1366) {
					// Deal 20 damage, drop exp and remove if dead
					if (enemy.takeDamage(20)) {
						dropExpOrb(enemy.x, enemy.y);
						enemy.destroy();
						enemies.splice(i, 1);
					}
				}
			}
			// Remove old red flash
			// LK.effects.flashScreen(0xff0000, 300);
			if (self.parent) {
				self.destroy();
			}
			return true;
		}
	};
	return self;
});
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	self.damage;
	self.speed;
	self.dirX = 0;
	self.dirY = 0;
	self.piercing = 1;
	self.hitEnemies = [];
	var bulletGraphics = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		// Seviye seçim ekranı açıkken hiçbir şey yapma
		if (skillSelectionActive) {
			return;
		}
		// Hareket
		this.x += this.dirX * this.speed;
		this.y += this.dirY * this.speed;
		// Kameranın (görünen alanın) dışına çıktıysa sil
		var camMinX = camera.x;
		var camMaxX = camera.x + 2048;
		var camMinY = camera.y;
		var camMaxY = camera.y + 2732;
		if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
			this.destroy();
			var bi = bullets.indexOf(this);
			if (bi >= 0) {
				bullets.splice(bi, 1);
			}
			return;
		}
		// “Menzil” filtresi: bu top silahının menzili WEAPONS.ball.range
		var maxRange = WEAPONS.ball.range * (player.weapons && player.weapons.ball ? player.weapons.ball.rngMul : 1);
		// (Eğer o envanterde yoksa rngMul=1 varsaydık)
		// Düşmana çarpma kontrolü & menzil filtresi
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			if (this.intersects(e) && isWithinRange(e, maxRange)) {
				damageEnemy(e, this.damage);
				this.destroy();
				var bi2 = bullets.indexOf(this);
				if (bi2 >= 0) {
					bullets.splice(bi2, 1);
				}
				return;
			}
		}
	};
	return self;
});
// ChickenLeg pickup class
var ChickenLeg = Container.expand(function () {
	var self = Container.call(this);
	self.active = true;
	var chickenLegGraphics = self.attachAsset('chickenLeg', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 60,
		height: 60
	});
	self.update = function () {
		if (!player || !self.active) {
			return;
		}
		var dx = player.x - self.x;
		var dy = player.y - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist < 80) {
			self.active = false;
			// Heal player for 30% of max HP, but not above max HP
			var healAmount = Math.floor(player.maxHp * 0.3);
			var oldHp = player.hp;
			player.hp = Math.min(player.hp + healAmount, player.maxHp);
			var actualHealed = player.hp - oldHp;
			if (actualHealed > 0) {
				LK.effects.flashObject(player, 0x00ff00, 300);
				// Show green HP gain text with black border
				var healText = new Text2('+' + actualHealed.toFixed(1), {
					size: 48,
					fill: 0x00ff00,
					stroke: 0x000000,
					strokeThickness: 4
				});
				healText.anchor.set(0.5);
				healText.x = player.x;
				healText.y = player.y - (player.height ? player.height / 2 : 60);
				healText.alpha = 1;
				gameContainer.addChild(healText);
				tween(healText, {
					y: healText.y - 60,
					alpha: 0
				}, {
					duration: 500,
					easing: tween.linear,
					onFinish: function onFinish() {
						if (healText.parent) {
							healText.destroy();
						}
					}
				});
			}
			LK.getSound('pickup').play();
			if (self.parent) {
				self.destroy();
			}
			return true;
		}
	};
	return self;
});
// Enemy base class
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	self.hp = 9999;
	self.maxHp = 9999;
	self.damage = 1;
	self.speed = 0;
	self.expValue = 1;
	self.type = 'normal';
	self.critChance = 0.25;
	// Enemy does not attach a graphic directly; subclasses should do this
	self.takeDamage = function (amount) {
		self.hp -= amount;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.hp <= 0) {
			// Defensive: On death, clear all regen/debuff state to prevent immortal bug
			self.enemyRegen = 0;
			self.lastEnemyRegenTime = 0;
			// self.bleedBuff = 0;
			// self.bleedBuffTime = undefined;
			// self.bleedTicks = 0;
			self.slowBuff = 0;
			self.slowBuffTime = undefined;
			self.stunBuff = 0;
			self.stunBuffTime = undefined;
			return true; // Enemy died
		}
		return false; // Enemy still alive
	};
	self.update = function () {
		// Kart seçim ekranı aktifken düşman hareket etmesin ve saldırmasın
		if (!player || skillSelectionActive) {
			return;
		}
		// Subclasses should implement facing logic if needed
		// Debuff: Stun
		if (self.stunBuff && self.stunBuffTime !== undefined) {
			var stunDuration = Math.floor(self.stunBuff * 60); // seconds to frames
			if (gameTime - self.stunBuffTime < stunDuration) {
				// Stunned: do not move or attack
				return;
			} else {
				self.stunBuff = 0;
				self.stunBuffTime = undefined;
			}
		}
		// 1) Oyuncuya olan vektörü bul
		var dx = player.x - self.x;
		var dy = player.y - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		// Debuff: Slow
		var speedMul = 1;
		if (self.slowBuff && self.slowBuffTime !== undefined) {
			var slowDuration = 120; // 2 seconds
			if (gameTime - self.slowBuffTime < slowDuration) {
				speedMul = Math.max(0, 1 - self.slowBuff / 100);
			} else {
				self.slowBuff = 0;
				self.slowBuffTime = undefined;
			}
		}
		// 2) Eğer düşman, oyuncuya 150 pikselden yakınsa hareket etme
		if (dist > 150) {
			// 3) Aksi halde 50px uzaktan hareket et
			self.x += dx / dist * self.speed * speedMul;
			self.y += dy / dist * self.speed * speedMul;
		}
		// Bleeding+ logic removed
		// --- Enemy HP regen after wave 5, scaling with wave ---
		// Only apply normal regen if enemy has regen
		if (self.enemyRegen && self.enemyRegen > 0) {
			if (!self.lastEnemyRegenTime) {
				self.lastEnemyRegenTime = 0;
			}
			if (gameTime - self.lastEnemyRegenTime >= 300) {
				// every 5s
				var regenAmount = self.maxHp * (self.enemyRegen / 100);
				var oldHp = self.hp;
				self.hp = Math.min(self.hp + regenAmount, self.maxHp);
				var actualHealed = self.hp - oldHp;
				if (actualHealed > 0) {
					// Show green HP gain text with black border
					var healText = new Text2('+' + actualHealed.toFixed(1), {
						size: 48,
						fill: 0x00ff00,
						stroke: 0x000000,
						strokeThickness: 4
					});
					healText.anchor.set(0.5);
					healText.x = self.x;
					healText.y = self.y - (self.height ? self.height / 2 : 60);
					healText.alpha = 1;
					gameContainer.addChild(healText);
					tween(healText, {
						y: healText.y - 60,
						alpha: 0
					}, {
						duration: 500,
						easing: tween.linear,
						onFinish: function onFinish() {
							if (healText.parent) {
								healText.destroy();
							}
						}
					});
				}
				self.lastEnemyRegenTime = gameTime;
			}
		}
		// Burada asla destroy() yok; sadece hareketi sınırlıyoruz
	};
	// Defensive: On destroy, clear all regen/debuff state to prevent immortal bug
	var origDestroy = self.destroy;
	self.destroy = function () {
		self.enemyRegen = 0;
		self.lastEnemyRegenTime = 0;
		// self.bleedBuff = 0;
		// self.bleedBuffTime = undefined;
		// self.bleedTicks = 0;
		self.slowBuff = 0;
		self.slowBuffTime = undefined;
		self.stunBuff = 0;
		self.stunBuffTime = undefined;
		if (typeof origDestroy === "function") {
			origDestroy.call(self);
		}
	};
	return self;
});
// Tank Zombie subclass
var TankZombie = Enemy.expand(function () {
	var self = Enemy.call(this);
	var tankGraphics = self.attachAsset('tankZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHp = 80;
	self.hp = 80;
	self.damage = 20;
	self.speed = 0.8;
	self.attackRange = 200;
	self.attackCooldown = 180; // 3 saniye (60fps)
	self.attackTimer = 0;
	self.type = 'tankZombie';
	self.update = function (origUpdate) {
		return function () {
			// Kart seçim ekranı aktifken tank zombi hareket etmesin ve saldırmasın
			if (skillSelectionActive) {
				return;
			}
			if (typeof player !== "undefined" && player && typeof player.x === "number") {
				if (self.x < player.x) {
					tankGraphics.scaleX = 1;
				} else if (self.x > player.x) {
					tankGraphics.scaleX = -1;
				}
			}
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			if (dist > self.attackRange) {
				var speedMul = 1;
				if (self.slowBuff && self.slowBuffTime !== undefined) {
					var slowDuration = 120;
					if (gameTime - self.slowBuffTime < slowDuration) {
						speedMul = Math.max(0, 1 - self.slowBuff / 100);
					}
				}
				self.x += dx / dist * self.speed * speedMul;
				self.y += dy / dist * self.speed * speedMul;
				self.attackTimer = 0;
			} else {
				self.attackTimer++;
				if (self.attackTimer >= self.attackCooldown) {
					self.attackTimer = 0;
					var atk = gameContainer.addChild(new Container());
					atk.attachAsset('tankZombieAttack', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					atk.x = self.x + dx / dist * 70;
					atk.y = self.y + dy / dist * 70;
					atk.life = 6; // 6 frame = 0.1 saniye
					atk.hasHit = false; // Hasar verildi mi, onu izlemek için
					atk.update = function () {
						this.life--;
						// 2) Eğer henüz hasar vermediysen, o anda intersection kontrol et:
						if (!this.hasHit && this.intersects(player)) {
							player.takeDamage(self.damage);
							this.hasHit = true;
							// NOT: Burada destroy() çağırmıyoruz, sadece hasHit flag'ini true yapıyoruz.
						}
						// 3) Süre (life) dolduğunda nesneyi sil:
						if (this.life <= 0) {
							if (this.parent) {
								this.destroy();
							}
						}
					};
				}
			}
			// Always call Enemy.update to ensure debuff/bleed/regen logic runs for all zombie types
			if (typeof self.__proto__.update === "function" && self.__proto__ !== null && self.__proto__ !== self) {
				self.__proto__.update.call(self);
			}
			// Then call original subclass update for movement/attack logic
			origUpdate.call(self);
		};
	}(self.update);
	// Defensive: On destroy, clear all regen/debuff state to prevent immortal bug
	var origDestroy = self.destroy;
	self.destroy = function () {
		self.gritWound = 0;
		self.lastGritWoundTime = undefined;
		self.enemyRegen = 0;
		self.lastEnemyRegenTime = 0;
		// self.bleedBuff = 0;
		// self.bleedBuffTime = undefined;
		// self.bleedTicks = 0;
		self.slowBuff = 0;
		self.slowBuffTime = undefined;
		self.stunBuff = 0;
		self.stunBuffTime = undefined;
		if (typeof origDestroy === "function") {
			origDestroy.call(self);
		}
	};
	return self;
});
// Ranged Zombie subclass
var RangedZombie = Enemy.expand(function () {
	var self = Enemy.call(this);
	var rangedGraphics = self.attachAsset('rangedZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHp = 12;
	self.hp = 12;
	self.damage = 16;
	self.speed = 1.2;
	self.attackRange = 900;
	self.attackCooldown = 300; // 5 saniye (60fps)
	self.attackTimer = 0;
	self.type = 'rangedZombie';
	self.update = function (origUpdate) {
		return function () {
			// Kart seçim ekranı aktifken menzilli zombi hareket etmesin ve saldırmasın
			if (skillSelectionActive) {
				return;
			}
			// Flip to face player
			if (self.x < player.x) {
				rangedGraphics.scaleX = 1;
			} else if (self.x > player.x) {
				rangedGraphics.scaleX = -1;
			}
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			// Hareket ve saldırı state'i: menzile girince hareketi bırakıp saldırıya geç, çıkınca tekrar hareket et
			if (typeof self.isAttacking === "undefined") {
				self.isAttacking = false;
			}
			if (dist > self.attackRange) {
				// === MENZİL DIŞI: sadece hareket et ve origUpdate’i çağır ===
				var speedMul = 1;
				if (self.slowBuff && self.slowBuffTime !== undefined) {
					var slowDuration = 120;
					if (gameTime - self.slowBuffTime < slowDuration) {
						speedMul = Math.max(0, 1 - self.slowBuff / 100);
					}
				}
				self.x += dx / dist * self.speed * speedMul;
				self.y += dy / dist * self.speed * speedMul;
				self.attackTimer = 0;
				self.isAttacking = false;
				// YALNIZCA BURADA Enemy.update’in (origUpdate’in) hareket+debuff kısımlarını çalıştırıyoruz
				// Always call Enemy.update to ensure debuff/bleed/regen logic runs for all zombie types
				if (typeof self.__proto__.update === "function" && self.__proto__ !== null && self.__proto__ !== self) {
					self.__proto__.update.call(self);
				}
				origUpdate.call(self);
			} else {
				// === MENZİL İÇİ: hareket etmeyi tamamen bırak, sadece saldırı yap ===
				self.isAttacking = true;
				self.attackTimer++;
				if (self.attackTimer >= self.attackCooldown) {
					self.attackTimer = 0;
					// Fire saliva projectile towards player
					var saliva = gameContainer.addChild(new Container());
					saliva.attachAsset('rangedZombieSaliva', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					saliva.x = self.x;
					saliva.y = self.y;
					var dirX = dx / dist;
					var dirY = dy / dist;
					saliva.speed = 18;
					saliva._rotationAngle = 0;
					saliva._salivaAsset = saliva.children && saliva.children.length > 0 ? saliva.children[0] : null;
					saliva.update = function () {
						if (skillSelectionActive) {
							return;
						}
						this.x += dirX * this.speed;
						this.y += dirY * this.speed;
						// Rotate saliva asset (spin as it moves)
						if (this._salivaAsset) {
							this._rotationAngle = (this._rotationAngle || 0) + 0.3;
							this._salivaAsset.rotation = this._rotationAngle;
						}
						// --- Player center hit circle (radius 60) ---
						if (player && typeof player.x === "number" && typeof player.y === "number") {
							var dx = this.x - player.x;
							var dy = this.y - player.y;
							var dist = Math.sqrt(dx * dx + dy * dy);
							if (dist <= 60) {
								player.takeDamage(self.damage);
								// --- Damage Reflection for rangedZombieSaliva ---
								if (player.buffs && player.buffs.damageReflection > 0) {
									// Reflect damage to this RangedZombie
									var reflectDmg = Math.ceil(self.damage * player.buffs.damageReflection / 100);
									if (reflectDmg > 0 && typeof self.takeDamage === "function") {
										self.takeDamage(reflectDmg);
										// Show reflection damage text
										var dmgText = new Text2(reflectDmg.toFixed(1), {
											size: 48,
											fill: 0xffffff,
											stroke: 0x000000,
											strokeThickness: 4
										});
										dmgText.anchor.set(0.5);
										dmgText.x = self.x;
										dmgText.y = self.y - (self.height ? self.height / 2 : 60);
										dmgText.alpha = 1;
										gameContainer.addChild(dmgText);
										tween(dmgText, {
											y: dmgText.y - 60,
											alpha: 0
										}, {
											duration: 500,
											easing: tween.linear,
											onFinish: function onFinish() {
												if (dmgText.parent) {
													dmgText.destroy();
												}
											}
										});
									}
								}
								if (this.parent) {
									this.destroy();
								}
								return;
							}
						}
						// Remove if out of camera
						var camMinX = camera.x;
						var camMaxX = camera.x + 2048;
						var camMinY = camera.y;
						var camMaxY = camera.y + 2732;
						if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
							if (this.parent) {
								this.destroy();
							}
						}
					};
				}
				// Burada origUpdate çağrılmıyor → Enemy.update’in “hareket et” kısmı pasif kalacak
			}
			// Always call Enemy.update to ensure debuff/bleed/regen logic runs for all zombie types
			if (typeof self.__proto__.update === "function" && self.__proto__ !== null && self.__proto__ !== self) {
				self.__proto__.update.call(self);
			}
		};
	}(self.update);
	// Defensive: On destroy, clear all regen/debuff state to prevent immortal bug
	var origDestroy = self.destroy;
	self.destroy = function () {
		self.gritWound = 0;
		self.lastGritWoundTime = undefined;
		self.enemyRegen = 0;
		self.lastEnemyRegenTime = 0;
		// self.bleedBuff = 0;
		// self.bleedBuffTime = undefined;
		// self.bleedTicks = 0;
		self.slowBuff = 0;
		self.slowBuffTime = undefined;
		self.stunBuff = 0;
		self.stunBuffTime = undefined;
		if (typeof origDestroy === "function") {
			origDestroy.call(self);
		}
	};
	return self;
});
// Normal Zombie subclass (renamed from Zombie)
var NormalZombie = Enemy.expand(function () {
	var self = Enemy.call(this);
	var zombieGraphics = self.attachAsset('normalZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHp = 16;
	self.hp = 16;
	self.damage = 8;
	self.speed = 1.0;
	self.attackRange = 150;
	self.attackCooldown = 90; // 1.5 saniye (60fps)
	self.attackTimer = 0;
	self.type = 'normalZombie';
	self.update = function (origUpdate) {
		return function () {
			// Kart seçim ekranı aktifken normal zombi hareket etmesin ve saldırmasın
			if (skillSelectionActive) {
				return;
			}
			// Flip to face player
			if (self.x < player.x) {
				zombieGraphics.scaleX = 1;
			} else if (self.x > player.x) {
				zombieGraphics.scaleX = -1;
			}
			// Move or attack
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			if (dist > self.attackRange) {
				// Move towards player
				var speedMul = 1;
				if (self.slowBuff && self.slowBuffTime !== undefined) {
					var slowDuration = 120;
					if (gameTime - self.slowBuffTime < slowDuration) {
						speedMul = Math.max(0, 1 - self.slowBuff / 100);
					}
				}
				self.x += dx / dist * self.speed * speedMul;
				self.y += dy / dist * self.speed * speedMul;
				self.attackTimer = 0;
			} else {
				// Attack every 1.5s
				self.attackTimer++;
				if (self.attackTimer >= self.attackCooldown) {
					self.attackTimer = 0;
					// Attack: spawn attack asset towards player
					var atk = gameContainer.addChild(new Container());
					atk.attachAsset('normalZombieAttack', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					atk.x = self.x + dx / dist * 60;
					atk.y = self.y + dy / dist * 60;
					atk.life = 6; // 6 frame = 0.1 saniye
					atk.hasHit = false; // Hasar verildi mi, onu izlemek için
					atk.update = function () {
						// 1) Önce remaining life’ı azalt:
						this.life--;
						// 2) Eğer henüz hasar vermediysen, o anda intersection kontrol et:
						if (!this.hasHit && this.intersects(player)) {
							player.takeDamage(self.damage);
							this.hasHit = true;
							// NOT: Burada destroy() çağırmıyoruz, sadece hasHit flag’ini true yapıyoruz.
						}
						// 3) Süre (life) dolduğunda nesneyi sil:
						if (this.life <= 0) {
							if (this.parent) {
								this.destroy();
							}
						}
					};
				}
			}
			// Always call Enemy.update to ensure debuff/bleed/regen logic runs for all zombie types
			if (typeof self.__proto__.update === "function" && self.__proto__ !== null && self.__proto__ !== self) {
				self.__proto__.update.call(self);
			}
			origUpdate.call(self);
		};
	}(self.update);
	// Defensive: On destroy, clear all regen/debuff state to prevent immortal bug
	var origDestroy = self.destroy;
	self.destroy = function () {
		self.gritWound = 0;
		self.lastGritWoundTime = undefined;
		self.enemyRegen = 0;
		self.lastEnemyRegenTime = 0;
		// self.bleedBuff = 0;
		// self.bleedBuffTime = undefined;
		// self.bleedTicks = 0;
		self.slowBuff = 0;
		self.slowBuffTime = undefined;
		self.stunBuff = 0;
		self.stunBuffTime = undefined;
		if (typeof origDestroy === "function") {
			origDestroy.call(self);
		}
	};
	return self;
});
// --- Healer Zombie Class ---
var HealerZombie = Enemy.expand(function () {
	var self = Enemy.call(this);
	var healerGraphics = self.attachAsset('healerZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHp = 24;
	self.hp = 24;
	self.damage = 0;
	self.speed = 1.4;
	self.attackRange = 850; // Saldırı menzili 850 olarak ayarlandı
	self.attackCooldown = 360; // 6 saniye
	self.attackTimer = 0;
	self.type = 'healerZombie';
	self._isAttacking = false;
	self.update = function (origUpdate) {
		return function () {
			if (skillSelectionActive) {
				return;
			}
			// Flip to face player
			if (self.x < player.x) {
				healerGraphics.scaleX = 1;
			} else if (self.x > player.x) {
				healerGraphics.scaleX = -1;
			}
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			// HealerZombie hareketi: oyuncuya 850'den fazla yaklaşamaz, menzile girince durur, çıkarsa tekrar yürür
			if (typeof self._lastPlayerInRange === "undefined") {
				self._lastPlayerInRange = false;
			}
			var playerInRange = dist <= self.attackRange;
			if (!playerInRange) {
				// Saldırı menziline girene kadar oyuncuya doğru yürü, ama 850'den fazla yaklaşma
				var speedMul = 1;
				if (self.slowBuff && self.slowBuffTime !== undefined) {
					var slowDuration = 120;
					if (gameTime - self.slowBuffTime < slowDuration) {
						speedMul = Math.max(0, 1 - self.slowBuff / 100);
					}
				}
				// Sadece 850'den fazla uzaktaysa yaklaş
				if (dist > self.attackRange) {
					self.x += dx / dist * self.speed * speedMul;
					self.y += dy / dist * self.speed * speedMul;
				}
				self.attackTimer = 0;
				self._isAttacking = false;
				// Don't call origUpdate here - we handle movement ourselves
			} else {
				// Saldırı menziline girdiyse dur ve iyileştirme potu fırlat
				self._isAttacking = true;
				// Don't move at all when in attack range
				self.attackTimer++;
				if (self.attackTimer >= self.attackCooldown) {
					self.attackTimer = 0;
					// Hedef: en kalabalık zombi grubu (bosslara öncelik)
					var target = null;
					var maxCount = 0;
					// Önce bosslara bak
					for (var i = 0; i < enemies.length; i++) {
						var e = enemies[i];
						if (!e || !e.type) {
							continue;
						}
						if (e.type === 'bossZombie') {
							var count = 0;
							for (var j = 0; j < enemies.length; j++) {
								var e2 = enemies[j];
								if (!e2) {
									continue;
								}
								var ddx = e2.x - e.x;
								var ddy = e2.y - e.y;
								if (Math.sqrt(ddx * ddx + ddy * ddy) <= 300) {
									count++;
								}
							}
							if (count > maxCount) {
								maxCount = count;
								target = e;
							}
						}
					}
					// Eğer boss yoksa, en kalabalık zombi grubunu bul
					if (!target) {
						for (var i = 0; i < enemies.length; i++) {
							var e = enemies[i];
							if (!e) {
								continue;
							}
							var count = 0;
							for (var j = 0; j < enemies.length; j++) {
								var e2 = enemies[j];
								if (!e2) {
									continue;
								}
								var ddx = e2.x - e.x;
								var ddy = e2.y - e.y;
								if (Math.sqrt(ddx * ddx + ddy * ddy) <= 300) {
									count++;
								}
							}
							if (count > maxCount) {
								maxCount = count;
								target = e;
							}
						}
					}
					// Hedef yoksa kendine at
					if (!target) {
						target = self;
					}
					// Potu fırlat
					var pot = new HealerZombiePot();
					pot.x = self.x;
					pot.y = self.y;
					pot.targetX = target.x;
					pot.targetY = target.y;
					gameContainer.addChild(pot);
				}
			}
			// Son frame'de oyuncu menzilde miydi, kaydet
			self._lastPlayerInRange = playerInRange;
			// Only call origUpdate when not in attack range to handle debuffs
			if (!playerInRange) {
				if (typeof self.__proto__.update === "function" && self.__proto__ !== null && self.__proto__ !== self) {
					self.__proto__.update.call(self);
				}
				origUpdate.call(self);
			}
			// Always call Enemy.update to ensure debuff/bleed/regen logic runs for all zombie types
			if (playerInRange) {
				if (typeof self.__proto__.update === "function" && self.__proto__ !== null && self.__proto__ !== self) {
					self.__proto__.update.call(self);
				}
			}
		};
	}(self.update);
	// Defensive: On destroy, clear all regen/debuff state to prevent immortal bug
	var origDestroy = self.destroy;
	self.destroy = function () {
		self.gritWound = 0;
		self.lastGritWoundTime = undefined;
		self.enemyRegen = 0;
		self.lastEnemyRegenTime = 0;
		// self.bleedBuff = 0;
		// self.bleedBuffTime = undefined;
		// self.bleedTicks = 0;
		self.slowBuff = 0;
		self.slowBuffTime = undefined;
		self.stunBuff = 0;
		self.stunBuffTime = undefined;
		if (typeof origDestroy === "function") {
			origDestroy.call(self);
		}
	};
	return self;
});
// Fast Zombie subclass
var FastZombie = Enemy.expand(function () {
	var self = Enemy.call(this);
	var fastGraphics = self.attachAsset('fastZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHp = 8;
	self.hp = 8;
	self.damage = 10;
	self.speed = 2.0;
	self.attackRange = 100;
	self.attackCooldown = 30; // 0.5 saniye (60fps)
	self.attackTimer = 0;
	self.type = 'fastZombie';
	self.update = function (origUpdate) {
		return function () {
			// Kart seçim ekranı aktifken hızlı zombi hareket etmesin ve saldırmasın
			if (skillSelectionActive) {
				return;
			}
			if (self.x < player.x) {
				fastGraphics.scaleX = 1;
			} else if (self.x > player.x) {
				fastGraphics.scaleX = -1;
			}
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			if (dist > self.attackRange) {
				var speedMul = 1;
				if (self.slowBuff && self.slowBuffTime !== undefined) {
					var slowDuration = 120;
					if (gameTime - self.slowBuffTime < slowDuration) {
						speedMul = Math.max(0, 1 - self.slowBuff / 100);
					}
				}
				self.x += dx / dist * self.speed * speedMul;
				self.y += dy / dist * self.speed * speedMul;
				self.attackTimer = 0;
			} else {
				self.attackTimer++;
				if (self.attackTimer >= self.attackCooldown) {
					self.attackTimer = 0;
					var atk = gameContainer.addChild(new Container());
					atk.attachAsset('fastZombieAttack', {
						anchorX: 0.5,
						anchorY: 0.5
					});
					atk.x = self.x + dx / dist * 50;
					atk.y = self.y + dy / dist * 50;
					atk.life = 6; // 6 frame = 0.1 saniye
					atk.hasHit = false; // Hasar verildi mi, onu izlemek için
					atk.update = function () {
						this.life--;
						// 2) Eğer henüz hasar vermediysen, o anda intersection kontrol et:
						if (!this.hasHit && this.intersects(player)) {
							player.takeDamage(self.damage);
							this.hasHit = true;
							// NOT: Burada destroy() çağırmıyoruz, sadece hasHit flag’ini true yapıyoruz.
						}
						// 3) Süre (life) dolduğunda nesneyi sil:
						if (this.life <= 0) {
							if (this.parent) {
								this.destroy();
							}
						}
					};
				}
			}
			// Always call Enemy.update to ensure debuff/bleed/regen logic runs for all zombie types
			if (typeof self.__proto__.update === "function" && self.__proto__ !== null && self.__proto__ !== self) {
				self.__proto__.update.call(self);
			}
			origUpdate.call(self);
		};
	}(self.update);
	// Defensive: On destroy, clear all regen/debuff state to prevent immortal bug
	var origDestroy = self.destroy;
	self.destroy = function () {
		self.gritWound = 0;
		self.lastGritWoundTime = undefined;
		self.enemyRegen = 0;
		self.lastEnemyRegenTime = 0;
		// self.bleedBuff = 0;
		// self.bleedBuffTime = undefined;
		// self.bleedTicks = 0;
		self.slowBuff = 0;
		self.slowBuffTime = undefined;
		self.stunBuff = 0;
		self.stunBuffTime = undefined;
		if (typeof origDestroy === "function") {
			origDestroy.call(self);
		}
	};
	return self;
});
// Boss Zombie subclass
var BossZombie = Enemy.expand(function () {
	var self = Enemy.call(this);
	var bossGraphics = self.attachAsset('bossZombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.maxHp = 400;
	self.hp = 400;
	self.type = 'bossZombie';
	self.mode = 'melee'; // 'melee' or 'ranged'
	self.modeTimer = 0;
	self.modeSwitchDelay = 0;
	self.attackTimer = 0;
	self.attackCooldownMelee = 180; // 3s
	self.attackCooldownRanged = 24; // 0.4s
	self.attackRangeMelee = 250;
	self.attackRangeRanged = 1000;
	self.damageMelee = 40;
	self.damageRanged = 5;
	self.speed = 0;
	self.speedMelee = 1.2;
	self.speedRanged = 1.8;
	self.modeDurationMelee = 720; // 12s
	self.modeDurationRanged = 240; // 4s
	self.modeSwitchPause = 60; // 1s
	self.lastWarningTime = 0;
	self.warningCountdown = 0;
	self.warningActive = false;
	self.warningText = null;
	self.update = function (origUpdate) {
		return function () {
			// --- Boss zombie her 5 saniyede bir max HP'sinin %4'ü kadar can yenilesin ---
			if (typeof self._lastBossRegenTime === "undefined") {
				self._lastBossRegenTime = 0;
			}
			if (gameTime - self._lastBossRegenTime >= 300) {
				// 5s = 300 frame
				var regenAmount = self.maxHp * 0.04;
				var oldHp = self.hp;
				self.hp = Math.min(self.hp + regenAmount, self.maxHp);
				var actualHealed = self.hp - oldHp;
				if (actualHealed > 0) {
					// Show green HP gain text with black border
					var healText = new Text2('+' + actualHealed.toFixed(1), {
						size: 48,
						fill: 0x00ff00,
						stroke: 0x000000,
						strokeThickness: 4
					});
					healText.anchor.set(0.5);
					healText.x = self.x;
					healText.y = self.y - (self.height ? self.height / 2 : 60);
					healText.alpha = 1;
					gameContainer.addChild(healText);
					tween(healText, {
						y: healText.y - 60,
						alpha: 0
					}, {
						duration: 500,
						easing: tween.linear,
						onFinish: function onFinish() {
							if (healText.parent) {
								healText.destroy();
							}
						}
					});
				}
				self._lastBossRegenTime = gameTime;
			}
			// Kart seçim ekranı aktifken boss hareket etmesin ve saldırmasın
			if (skillSelectionActive) {
				return;
			}
			// Flip to face player
			if (self.x < player.x) {
				bossGraphics.scaleX = 1;
			} else if (self.x > player.x) {
				bossGraphics.scaleX = -1;
			}
			// Mode switching logic
			if (self.modeSwitchDelay > 0) {
				self.modeSwitchDelay--;
				// During pause, boss cannot move, but can attack if already in attack range
				// Defensive: do not move, but allow attack animation/effects if in range
				// For melee mode
				var dx = player.x - self.x;
				var dy = player.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (self.mode === 'melee' && dist <= self.attackRangeMelee) {
					self.attackTimer++;
					self.isAttacking = true;
					if (self.attackTimer >= self.attackCooldownMelee) {
						self.attackTimer = 0;
						var atk = gameContainer.addChild(new Container());
						atk.attachAsset('bossZombieAttack1', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						atk.x = self.x + dx / dist * 90;
						atk.y = self.y + dy / dist * 90;
						atk.life = 6;
						atk.hasHit = false;
						atk.update = function () {
							this.life--;
							if (!this.hasHit) {
								// Yakın dövüş saldırısı: doğrudan player.intersects ile kontrol et
								if (player && typeof player.x === "number" && typeof player.y === "number") {
									if (this.intersects(player)) {
										player.takeDamage(self.damageMelee);
										this.hasHit = true;
									}
								}
							}
							if (this.life <= 0) {
								if (this.parent) {
									this.destroy();
								}
							}
						};
					}
				} else if (self.mode === 'ranged' && dist <= self.attackRangeRanged) {
					self.attackTimer++;
					self.isAttacking = true;
					if (self.attackTimer % self.attackCooldownRanged === 0) {
						var bone = gameContainer.addChild(new Container());
						bone.attachAsset('bossZombieAttack2', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						bone.x = self.x;
						bone.y = self.y;
						var dirX = dx / dist;
						var dirY = dy / dist;
						bone.speed = 28;
						bone._rotationAngle = 0;
						bone._boneAsset = bone.children && bone.children.length > 0 ? bone.children[0] : null;
						bone.update = function () {
							if (skillSelectionActive) {
								return;
							}
							this.x += dirX * bone.speed;
							this.y += dirY * bone.speed;
							// Rotate bone asset (spin as it moves)
							if (this._boneAsset) {
								this._rotationAngle = (this._rotationAngle || 0) + 0.3;
								this._boneAsset.rotation = this._rotationAngle;
							}
							if (player && typeof player.x === "number" && typeof player.y === "number") {
								var dx2 = this.x - player.x;
								var dy2 = this.y - player.y;
								var dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
								if (dist2 <= 60) {
									player.takeDamage(self.damageRanged);
									// --- Damage Reflection for bossZombieAttack2 (ranged mode) ---
									if (player.buffs && player.buffs.damageReflection > 0) {
										// Reflect damage to this BossZombie
										var reflectDmg = Math.ceil(self.damageRanged * player.buffs.damageReflection / 100);
										if (reflectDmg > 0 && typeof self.takeDamage === "function") {
											self.takeDamage(reflectDmg);
											// Show reflection damage text
											var dmgText = new Text2(reflectDmg.toFixed(1), {
												size: 48,
												fill: 0xffffff,
												stroke: 0x000000,
												strokeThickness: 4
											});
											dmgText.anchor.set(0.5);
											dmgText.x = self.x;
											dmgText.y = self.y - (self.height ? self.height / 2 : 60);
											dmgText.alpha = 1;
											gameContainer.addChild(dmgText);
											tween(dmgText, {
												y: dmgText.y - 60,
												alpha: 0
											}, {
												duration: 500,
												easing: tween.linear,
												onFinish: function onFinish() {
													if (dmgText.parent) {
														dmgText.destroy();
													}
												}
											});
										}
									}
									if (this.parent) {
										this.destroy();
									}
								}
							}
							var camMinX = camera.x;
							var camMaxX = camera.x + 2048;
							var camMinY = camera.y;
							var camMaxY = camera.y + 2732;
							if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
								if (this.parent) {
									this.destroy();
								}
							}
						};
					}
				} else {
					self.isAttacking = false;
					self.attackTimer = 0;
				}
				// Do not move during pause
				return;
			}
			self.modeTimer++;
			if (self.mode === 'melee' && self.modeTimer >= self.modeDurationMelee) {
				// --- Only teleport boss away from player if within 800 range ---
				var dxTeleport = self.x - player.x;
				var dyTeleport = self.y - player.y;
				var distTeleport = Math.sqrt(dxTeleport * dxTeleport + dyTeleport * dyTeleport);
				// Only teleport if boss is within 800 units of player
				if (distTeleport <= 800 && distTeleport > 0) {
					// Move boss 800 units away from player, in the direction away from player
					self.x = player.x + dxTeleport / distTeleport * 800;
					self.y = player.y + dyTeleport / distTeleport * 800;
					self.mode = 'ranged';
					self.modeTimer = 0;
					self.modeSwitchDelay = 120; // 2 seconds pause when switching to ranged
					self.isAttacking = false; // Defensive: reset attack state
				} else {
					// If not close enough, keep walking towards player (do not switch to ranged mode yet)
					// Just reset modeTimer so boss keeps trying until close enough
					self.modeTimer = self.modeDurationMelee; // keep at threshold, so check again next frame
				}
			} else if (self.mode === 'ranged' && self.modeTimer >= self.modeDurationRanged) {
				self.mode = 'melee';
				self.modeTimer = 0;
				self.modeSwitchDelay = self.modeSwitchPause;
				self.isAttacking = false; // Defensive: reset attack state
			}
			var dx = player.x - self.x;
			var dy = player.y - self.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			// Boss warning if player is too far
			var bossDist = Math.sqrt((self.x - player.x) * (self.x - player.x) + (self.y - player.y) * (self.y - player.y));
			if (bossDist > 2000) {
				if (!self.warningActive) {
					self.warningActive = true;
					self.warningCountdown = 5;
					self.lastWarningTime = gameTime;
					if (!self.warningText) {
						self.warningText = new Text2(t("bossWarning") + "5", {
							size: 80,
							fill: 0xff0000
						});
						self.warningText.anchor.set(0.5, 0);
						self.warningText.y = 300;
						LK.gui.top.addChild(self.warningText);
					}
				} else {
					if (gameTime - self.lastWarningTime >= 60) {
						self.warningCountdown--;
						self.lastWarningTime = gameTime;
						if (self.warningText) {
							self.warningText.setText(t("bossWarning") + self.warningCountdown);
						}
					}
					if (self.warningCountdown <= 0) {
						if (self.warningText && self.warningText.parent) {
							self.warningText.destroy();
						}
						LK.showGameOver();
						return;
					}
				}
			} else if (self.warningActive) {
				self.warningActive = false;
				if (self.warningText && self.warningText.parent) {
					self.warningText.destroy();
				}
				self.warningText = null;
			}
			// Movement and attack logic
			if (self.mode === 'melee') {
				// Melee mode: slow, short range, high damage
				if (typeof self.isAttacking === "undefined") {
					self.isAttacking = false;
				}
				// Boss zombi yakın dövüşçü modunda saldırı menziline girdiğinde hareket etmeye devam etsin ve saldırı yapabilsin
				var speedMul = 1;
				if (self.slowBuff && self.slowBuffTime !== undefined) {
					var slowDuration = 120;
					if (gameTime - self.slowBuffTime < slowDuration) {
						speedMul = Math.max(0, 1 - self.slowBuff / 100);
					}
				}
				// Sadece saldırı menziline kadar hareket etsin, daha fazla yaklaşmasın
				if (dist > self.attackRangeMelee) {
					self.x += dx / dist * self.speedMelee * speedMul;
					self.y += dy / dist * self.speedMelee * speedMul;
				}
				// Saldırı menziline girildiyse saldırı yapabilsin
				if (dist <= self.attackRangeMelee) {
					self.attackTimer++;
					self.isAttacking = true;
					if (self.attackTimer >= self.attackCooldownMelee) {
						self.attackTimer = 0;
						var atk = gameContainer.addChild(new Container());
						atk.attachAsset('bossZombieAttack1', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						atk.x = self.x + dx / dist * 90;
						atk.y = self.y + dy / dist * 90;
						atk.life = 6; // 6 frame = 0.1 saniye
						atk.hasHit = false; // Hasar verildi mi, onu izlemek için
						atk.update = function () {
							this.life--;
							// Her frame'de intersection kontrolü yap, böylece animasyon karaktere her zaman hasar verebilir
							if (!this.hasHit && player && typeof player.x === "number" && typeof player.y === "number") {
								if (this.intersects(player)) {
									player.takeDamage(self.damageMelee);
									this.hasHit = true;
								}
							}
							if (this.life <= 0) {
								if (this.parent) {
									this.destroy();
								}
							}
						};
					}
				} else {
					self.attackTimer = 0;
					self.isAttacking = false;
				}
			} else if (self.mode === 'ranged') {
				// Ranged mode: normal speed, long range, low damage, fires bones
				if (typeof self.isAttacking === "undefined") {
					self.isAttacking = false;
				}
				if (dist > self.attackRangeRanged) {
					var speedMul = 1;
					if (self.slowBuff && self.slowBuffTime !== undefined) {
						var slowDuration = 120;
						if (gameTime - self.slowBuffTime < slowDuration) {
							speedMul = Math.max(0, 1 - self.slowBuff / 100);
						}
					}
					// Only move if not attacking
					if (!self.isAttacking) {
						self.x += dx / dist * self.speedRanged * speedMul;
						self.y += dy / dist * self.speedRanged * speedMul;
					}
					self.attackTimer = 0;
					self.isAttacking = false;
				} else {
					self.attackTimer++;
					self.isAttacking = true;
					if (self.attackTimer % self.attackCooldownRanged === 0) {
						// Fire bone projectile
						var bone = gameContainer.addChild(new Container());
						bone.attachAsset('bossZombieAttack2', {
							anchorX: 0.5,
							anchorY: 0.5
						});
						bone.x = self.x;
						bone.y = self.y;
						var dirX = dx / dist;
						var dirY = dy / dist;
						bone.speed = 28;
						bone._rotationAngle = 0;
						bone._boneAsset = bone.children && bone.children.length > 0 ? bone.children[0] : null;
						bone.update = function () {
							if (skillSelectionActive) {
								return;
							}
							this.x += dirX * bone.speed;
							this.y += dirY * bone.speed;
							// Rotate bone asset
							if (this._boneAsset) {
								this._rotationAngle = (this._rotationAngle || 0) + 0.3;
								this._boneAsset.rotation = this._rotationAngle;
							}
							// --- Use circular hitbox for player (radius 60) ---
							if (player && typeof player.x === "number" && typeof player.y === "number") {
								var dx = this.x - player.x;
								var dy = this.y - player.y;
								var dist = Math.sqrt(dx * dx + dy * dy);
								if (dist <= 60) {
									player.takeDamage(self.damageRanged);
									// --- Damage Reflection for bossZombieAttack2 (ranged mode, second instance) ---
									if (player.buffs && player.buffs.damageReflection > 0) {
										var reflectDmg = Math.ceil(self.damageRanged * player.buffs.damageReflection / 100);
										if (reflectDmg > 0 && typeof self.takeDamage === "function") {
											self.takeDamage(reflectDmg);
											// Show reflection damage text
											var dmgText = new Text2(reflectDmg.toFixed(1), {
												size: 48,
												fill: 0xffffff,
												stroke: 0x000000,
												strokeThickness: 4
											});
											dmgText.anchor.set(0.5);
											dmgText.x = self.x;
											dmgText.y = self.y - (self.height ? self.height / 2 : 60);
											dmgText.alpha = 1;
											gameContainer.addChild(dmgText);
											tween(dmgText, {
												y: dmgText.y - 60,
												alpha: 0
											}, {
												duration: 500,
												easing: tween.linear,
												onFinish: function onFinish() {
													if (dmgText.parent) {
														dmgText.destroy();
													}
												}
											});
										}
									}
									if (this.parent) {
										this.destroy();
									}
								}
							}
							var camMinX = camera.x;
							var camMaxX = camera.x + 2048;
							var camMinY = camera.y;
							var camMaxY = camera.y + 2732;
							if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
								if (this.parent) {
									this.destroy();
								}
							}
						};
					}
				}
			}
			// Always call Enemy.update to ensure debuff/bleed/regen logic runs for all zombie types
			if (typeof self.__proto__.update === "function" && self.__proto__ !== null && self.__proto__ !== self) {
				self.__proto__.update.call(self);
			}
			origUpdate.call(self);
		};
	}(self.update);
	// Defensive: On destroy, clear all regen/debuff state to prevent immortal bug
	var origDestroy = self.destroy;
	self.destroy = function () {
		self.gritWound = 0;
		self.lastGritWoundTime = undefined;
		self.enemyRegen = 0;
		self.lastEnemyRegenTime = 0;
		// self.bleedBuff = 0;
		// self.bleedBuffTime = undefined;
		// self.bleedTicks = 0;
		self.slowBuff = 0;
		self.slowBuffTime = undefined;
		self.stunBuff = 0;
		self.stunBuffTime = undefined;
		if (typeof origDestroy === "function") {
			origDestroy.call(self);
		}
	};
	return self;
});
var ExpOrb = Container.expand(function () {
	var self = Container.call(this);
	// 1) spawnTime kaydet
	self.spawnTime = gameTime;
	self.value = 1; // Each orb always gives 1 EXP
	self.magnetSpeed = 0;
	var orbGraphics = self.attachAsset('expOrb', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		// ORB YAŞI (frame cinsinden)
		var age = gameTime - self.spawnTime;
		// 2) Eğer 20 saniye geçmişse (1200 frame), orb’u yok et ve listeden çıkar
		if (age >= 1200) {
			// yok et
			if (self.parent) {
				self.destroy();
			}
			var idx = expOrbs.indexOf(self);
			if (idx >= 0) {
				expOrbs.splice(idx, 1);
			}
			return;
		}
		// 3) Son 5 saniyede (age >= 900), yanıp sönme uygulaması
		if (age >= 900) {
			// kalan süre
			var remaining = 1200 - age; // 300’den 0’a kadar azalır
			// blink periyodu: remaining / 50’ye bağlı (en hızlı 1 frame’lik periyot)
			var blinkInterval = Math.ceil(remaining / 50);
			if (blinkInterval < 1) {
				blinkInterval = 1;
			}
			// yaşa göre çift/tek periyoda bölerek görünürlüğü değiştir
			var phase = Math.floor(age / blinkInterval);
			self.visible = phase % 2 === 0;
		} else {
			// son 5 saniye değilse görünür olsun
			self.visible = true;
		}
		// 4) Normal manyetik çekim hareketi
		if (!player || self.magnetSpeed === 0) {
			return;
		}
		var dx = player.x - self.x;
		var dy = player.y - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist > 0) {
			self.x += dx / dist * self.magnetSpeed;
			self.y += dy / dist * self.magnetSpeed;
		}
	};
	return self;
});
// --- Healer Zombie Pot Projectile Class ---
var HealerZombiePot = Container.expand(function () {
	var self = Container.call(this);
	self.targetX = 0;
	self.targetY = 0;
	self.speed = 22;
	self.attachAsset('healerZombiePot', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.7,
		scaleY: 0.7
	});
	self.x = 0;
	self.y = 0;
	self._arrived = false;
	self._rotationAngle = 0;
	self._potAsset = self.children && self.children.length > 0 ? self.children[0] : null;
	self.update = function () {
		if (self._arrived) {
			return;
		}
		var dx = self.targetX - self.x;
		var dy = self.targetY - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist <= self.speed) {
			self.x = self.targetX;
			self.y = self.targetY;
			self._arrived = true;
			// Patlama efekti: iyileştirme alanı oluştur
			var area = new HealerZombiePotArea();
			area.x = self.x;
			area.y = self.y;
			gameContainer.addChild(area);
			if (self.parent) {
				self.destroy();
			}
			return;
		}
		self.x += dx / dist * self.speed;
		self.y += dy / dist * self.speed;
		// Rotate pot asset
		if (self._potAsset) {
			self._rotationAngle = (self._rotationAngle || 0) + 0.3;
			self._potAsset.rotation = self._rotationAngle;
		}
	};
	return self;
});
// --- Healer Zombie Pot Area Class ---
var HealerZombiePotArea = Container.expand(function () {
	var self = Container.call(this);
	self.radius = 300;
	self.life = 240; // 4 saniye (60fps)
	self.healInterval = 30; // 0.5 saniyede bir
	self._lastHealTick = 0;
	self._healedZombies = {}; // {enemyId: lastHealFrame}
	self.attachAsset('healerZombiePotArea', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: self.radius / 100,
		scaleY: self.radius / 100,
		alpha: 0.2
	});
	self.x = 0;
	self.y = 0;
	self.update = function () {
		self.life--;
		if (self.life < 0) {
			if (self.parent) {
				self.destroy();
			}
			return;
		}
		// Her 0.5 saniyede bir (ve ilk frame'de) iyileştir
		if (self.life % self.healInterval === 0 || self.life === 239) {
			for (var i = 0; i < enemies.length; i++) {
				var e = enemies[i];
				if (!e || typeof e.hp !== "number" || typeof e.maxHp !== "number") {
					continue;
				}
				var dx = e.x - self.x;
				var dy = e.y - self.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist <= self.radius) {
					// Sadece bosslara öncelik verilecekse, bosslar da dahil
					// HealerZombiePotArea healing is never affected by Grit Wound+ (always heals full amount)
					var healAmount = e.maxHp * 0.08;
					var oldHp = e.hp;
					e.hp = Math.min(e.hp + healAmount, e.maxHp);
					var actualHealed = e.hp - oldHp;
					if (actualHealed > 0) {
						var healText = new Text2('+' + actualHealed.toFixed(1), {
							size: 36,
							fill: 0x00ffcc,
							stroke: 0x000000,
							strokeThickness: 3
						});
						healText.anchor.set(0.5);
						healText.x = e.x;
						healText.y = e.y - (e.height ? e.height / 2 : 60);
						healText.alpha = 1;
						gameContainer.addChild(healText);
						tween(healText, {
							y: healText.y - 40,
							alpha: 0
						}, {
							duration: 400,
							easing: tween.linear,
							onFinish: function onFinish() {
								if (healText.parent) {
									healText.destroy();
								}
							}
						});
					}
				}
			}
		}
	};
	return self;
});
var Joystick = Container.expand(function () {
	var self = Container.call(this);
	self.active = false;
	self.dirX = 0;
	self.dirY = 0;
	var base = self.attachAsset('joystickBase', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	base.alpha = 0.5;
	var knob = self.attachAsset('joystickKnob', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	knob.alpha = 0.7;
	// Manuel knob merkez offset'i (ör: knob assetinin görsel merkezi ile gerçek merkez arasındaki fark)
	// Bu değerleri elle ayarlayabilirsin. Örneğin, knob görselinin merkezi 10px sağda ve 5px yukarıda ise:
	self.knobCenterOffsetX = 0; // Buraya elle düzeltmek istediğin değeri gir
	self.knobCenterOffsetY = 0; // Buraya elle düzeltmek istediğin değeri gir
	self.setKnobPosition = function (x, y) {
		// x, y: joystick base'in merkezine göre offset (dokunulan nokta - joystick merkezi)
		// Knob'un merkezi joystick base'in merkeziyle tam hizalı olmalı
		// Hareket yönü, knob merkezinden dokunulan pozisyona doğru olmalı
		// dx, dy: knob'un merkezinden dokunulan noktaya vektör
		// Manuel offset uygula
		var dx = x - self.knobCenterOffsetX;
		var dy = y - self.knobCenterOffsetY;
		var dist = Math.sqrt(dx * dx + dy * dy);
		var maxDist = 60;
		if (dist > maxDist) {
			dx = dx / dist * maxDist;
			dy = dy / dist * maxDist;
		}
		knob.x = dx;
		knob.y = dy;
		// Defensive: avoid division by zero
		if (maxDist === 0) {
			self.dirX = 0;
			self.dirY = 0;
		} else {
			// Hareket yönü: knob'un merkezinden dokunulan noktaya doğru normalize edilmiş vektör
			self.dirX = dx / maxDist;
			self.dirY = dy / maxDist;
		}
	};
	self.reset = function () {
		knob.x = 0;
		knob.y = 0;
		self.dirX = 0;
		self.dirY = 0;
		self.active = false;
		// Defensive: always make knob visible and on top
		knob.visible = true;
		if (knob.parent && typeof knob.parent.setChildIndex === "function") {
			knob.parent.setChildIndex(knob, knob.parent.children.length - 1);
		}
	};
	return self;
});
var Magnet = Container.expand(function () {
	var self = Container.call(this);
	self.active = true;
	var magnetGraphics = self.attachAsset('magnet', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 60,
		height: 60,
		tint: 0x0099ff
	});
	self.update = function () {
		if (!player || !self.active) {
			return;
		}
		var dx = player.x - self.x;
		var dy = player.y - self.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist < 80) {
			self.active = false;
			// Magnetize all exp orbs on screen
			for (var i = 0; i < expOrbs.length; i++) {
				var orb = expOrbs[i];
				var orbDx = Math.abs(orb.x - player.x);
				var orbDy = Math.abs(orb.y - player.y);
				if (orbDx < 1024 && orbDy < 1366) {
					orb.magnetSpeed = 20;
				}
			}
			if (self.parent) {
				self.destroy();
			}
			return true;
		}
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	self.level = 1;
	self.exp = 0;
	self.expToNext = 10;
	self.hp = 100;
	self.maxHp = 100;
	self.damage = 10.0;
	self.fireRate = 30;
	self.bulletSpeed = 15;
	self.moveSpeed = 5;
	self.pickupRange = 100;
	self.lastFire = 0;
	self.critChance = 0.25; // Oyuncu başlangıçta %25 kritik vuruş şansı
	/* ===== BUFFS ===== */
	self.buffs = {
		damageReduction: 0,
		// percent, e.g. 10 means 10%
		moveSpeed: 0,
		// percent, e.g. 20 means 20%
		hpRegen: 0,
		// percent per 5s
		damageReflection: 0,
		// percent
		// gritWound removed
		enemySlow: 0,
		// percent
		enemyStun: 0,
		// seconds
		// bleeding removed
		critChance: 0 // Critical Hit Chance+ buff, percent (15 means +15%)
	};
	self.lastRegenTime = 0;
	/* ===== WEAPON INVENTORY ===== */
	self.weapons = {}; // key → instance
	var playerGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.takeDamage = function (amount) {
		// Damage Reduction+
		var finalAmount = amount;
		if (self.buffs.damageReduction > 0) {
			finalAmount = Math.ceil(amount * (1 - self.buffs.damageReduction / 100));
		}
		self.hp -= finalAmount;
		LK.effects.flashObject(self, 0xff0000, 300);
		LK.getSound('damageTaken').play();
		// Damage Reflection+
		if (self.buffs.damageReflection > 0 && enemies.length > 0) {
			// Reflect to all enemies in contact (all types, not just normal zombies)
			for (var i = 0; i < enemies.length; i++) {
				var e = enemies[i];
				var dx = e.x - self.x;
				var dy = e.y - self.y;
				var distSq = dx * dx + dy * dy;
				if (distSq <= 22500) {
					// same as contact check
					var reflectDmg = Math.ceil(finalAmount * self.buffs.damageReflection / 100);
					if (reflectDmg > 0) {
						damageEnemy(e, reflectDmg);
						// Show damage text for reflection
						var dmgText = new Text2(reflectDmg.toFixed(1), {
							size: 48,
							fill: 0xffffff,
							stroke: 0x000000,
							strokeThickness: 4
						});
						dmgText.anchor.set(0.5);
						dmgText.x = e.x;
						dmgText.y = e.y - (e.height ? e.height / 2 : 60);
						dmgText.alpha = 1;
						gameContainer.addChild(dmgText);
						tween(dmgText, {
							y: dmgText.y - 60,
							alpha: 0
						}, {
							duration: 500,
							easing: tween.linear,
							onFinish: function onFinish() {
								if (dmgText.parent) {
									dmgText.destroy();
								}
							}
						});
					}
					// Do not break; reflect to all enemies in contact
				}
			}
		}
		if (self.hp <= 0) {
			// Show death screen and block game update
			showDeathScreen();
			return;
		}
	};
	self.gainExp = function (amount) {
		// Add exp orbs
		self.exp += amount;
		// Level up if exp orbs >= current level
		while (self.exp >= self.level) {
			self.exp -= self.level;
			self.levelUp();
		}
	};
	self.update = function () {
		// Kart seçim ekranı aktifken karakter hareket etmesin ve saldırmasın
		if (skillSelectionActive) {
			return;
		}
		// Flip player graphic based on movement direction
		if (self.lastX === undefined) {
			self.lastX = self.x;
		}
		if (self.x > self.lastX) {
			playerGraphics.scaleX = 1;
		} else if (self.x < self.lastX) {
			playerGraphics.scaleX = -1;
		}
		self.lastX = self.x;
		// Movement Speed+
		if (self.buffs.moveSpeed > 0) {
			self.moveSpeed = 5 * (1 + self.buffs.moveSpeed / 100);
		} else {
			self.moveSpeed = 5;
		}
		// HP Regeneration+ (now heals every 1s for 1% per level, up to 5%)
		if (self.buffs.hpRegen > 0 && gameTime - (self.lastRegenTime || 0) >= 60) {
			// Clamp to max 5
			var regenLevel = Math.min(self.buffs.hpRegen, 5);
			var regenAmount = self.maxHp * (regenLevel / 100); // 1% per level, up to 5%
			if (regenAmount > 0 && self.hp < self.maxHp) {
				var oldHp = self.hp;
				self.hp = Math.min(self.hp + regenAmount, self.maxHp);
				var actualHealed = self.hp - oldHp;
				if (actualHealed > 0) {
					LK.effects.flashObject(self, 0x00ff00, 200);
					// Show green HP gain text with black border
					var healText = new Text2('+' + actualHealed.toFixed(1), {
						size: 48,
						fill: 0x00ff00,
						stroke: 0x000000,
						strokeThickness: 4
					});
					healText.anchor.set(0.5);
					healText.x = self.x;
					healText.y = self.y - (self.height ? self.height / 2 : 60);
					healText.alpha = 1;
					gameContainer.addChild(healText);
					tween(healText, {
						y: healText.y - 60,
						alpha: 0
					}, {
						duration: 500,
						easing: tween.linear,
						onFinish: function onFinish() {
							if (healText.parent) {
								healText.destroy();
							}
						}
					});
				}
			}
			self.lastRegenTime = gameTime;
		}
		// Block all weapon/projectile firing during wave break (3s) after wave clear
		if (!window._waveBreakActive) {
			for (var k in self.weapons) {
				var inst = self.weapons[k],
					meta = WEAPONS[k];
				if (--inst.cdCnt <= 0) {
					fireWeapon(k, inst, meta);
					// inst.cd muhtemelen kesirsiz olmayabilir; istersen Math.floor ile yuvarla:
					inst.cdCnt = Math.floor(inst.cd);
				}
			}
		}
	};
	self.levelUp = function () {
		self.level++;
		// self.exp is now handled in gainExp, do not reset here
		self.expToNext = self.level * 15;
		// self.maxHp += 10; // Artık seviye atlayınca max HP artmıyor
		// Do NOT restore full health on level up
		// self.hp = self.maxHp;
		// Increase movement speed by 4% per level up
		self.moveSpeed *= 1.04;
		LK.getSound('levelup').play();
		showSkillSelection();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x111111
});
/**** 
* Game Code
****/ 
// --- SOUND/MUSIC BLOCKER: Only allow introSpeech while red overlay is visible ---
/* ==== UNIVERSAL HELPERS ==== */
(function () {
	// Patch LK.getSound and LK.playMusic to block all except introSpeech/mainMenuMusic when window._blockAllSounds is true
	var origGetSound = LK.getSound;
	var origPlayMusic = LK.playMusic;
	// Track if introSpeech is currently playing
	window._introSpeechPlaying = false;
	LK.getSound = function (key) {
		var sound = origGetSound.call(LK, key);
		if (!sound) {
			return sound;
		}
		// Patch .play() to block all except introSpeech if _blockAllSounds is set or introSpeech is playing
		var origPlay = sound.play;
		sound.play = function () {
			// Block all sounds except introSpeech if _blockAllSounds or introSpeech is playing
			if ((window._blockAllSounds || window._introSpeechPlaying) && key !== 'introSpeech') {
				return;
			}
			// If introSpeech is about to play, set flag and set up end event
			if (key === 'introSpeech') {
				// Only set if not already playing
				if (!window._introSpeechPlaying) {
					window._introSpeechPlaying = true;
					// Try to listen for 'ended' event to clear the flag
					if (typeof sound.once === "function") {
						sound.once('ended', function () {
							window._introSpeechPlaying = false;
						});
					} else {
						// Fallback: clear after 10s (length of introSpeech)
						LK.setTimeout(function () {
							window._introSpeechPlaying = false;
						}, 10000);
					}
				}
			}
			return origPlay.apply(sound, arguments);
		};
		return sound;
	};
	LK.playMusic = function (key, opts) {
		// Block all music except mainMenuMusic if _blockAllSounds, or block all music if introSpeech is playing
		// Also block mainMenuMusic if red overlay is visible (mainMenuRedBlocker exists and is visible)
		if (window._blockAllSounds && key !== 'mainMenuMusic' || window._introSpeechPlaying || key === 'mainMenuMusic' && typeof mainMenuRedBlocker !== "undefined" && mainMenuRedBlocker && mainMenuRedBlocker.visible) {
			return;
		}
		return origPlayMusic.apply(LK, arguments);
	};
})();
// This is normal for large files or slow connections and cannot be fixed in code.
// Note: If music starts late, it may be due to the time required to load the music asset on first play. 
// --- MENU & LANGUAGE STATE ---
var GAME_STATE = {
	MAIN_MENU: 0,
	PLAYING: 1,
	DEATH: 2
};
var gameState = GAME_STATE.MAIN_MENU;
var currentLanguage = "en"; // "en" or "tr"
var mainMenuContainer = null;
var languageMenuContainer = null;
var deathScreenContainer = null;
// --- TEXTS ---
var TEXTS = {
	en: {
		start: "Start Game",
		languages: "Languages",
		returnMainMenu: "Return to Main Menu",
		death: "You Died!",
		lang_tr: "Türkçe",
		lang_en: "English",
		hp: "HP",
		wave: "Wave",
		level: "Level",
		exp: "EXP",
		expShort: "EXP",
		weaponSelect: "Select Your Weapon",
		unlock: "Unlock",
		noOption: "No Option",
		buffs: {
			damageReduction: "Damage Reduction+",
			moveSpeed: "Movement Speed Increase+",
			hpRegen: "HP Regeneration+",
			damageReflection: "Damage Reflection+",
			// gritWound: "Grit Wound+", (removed)
			enemySlow: "Enemy Slow+",
			enemyStun: "Enemy Stun+",
			// bleeding: "Bleeding+", (removed)
			critChance: "Critical Hit Chance+",
			maxHpPlus: "Maximum HP+",
			magnetPlus: "Magnet+"
		},
		buffDescs: {
			damageReduction: "Take 10% less damage per level.",
			moveSpeed: "Move 20% faster per level.",
			hpRegen: "Regenerate 1% max HP every 5s per level.",
			damageReflection: "Reflect 5% damage per level.",
			// gritWwound: "Reduce enemy regen by 10% per level.", (removed)
			enemySlow: "Slow enemies by 10% per level.",
			enemyStun: "Stun enemies for 0.1s per level.",
			// bleeding: "Bleed: 4s, 0.5s tick, 5% max HP per tick per level.", (removed)
			critChance: "Increase critical hit chance by 15% per level.",
			maxHpPlus: "Increase max HP by 25 per level.",
			magnetPlus: "Nearby EXP orbs (150 radius, +150 per level) are quickly pulled to you."
		},
		upgrade: "Upgrade",
		desc_damage: "Increases weapon damage by 20%.",
		desc_atkspd: "Increases weapon attack speed by 10%.",
		desc_range: "Increases weapon range and size by 10%.",
		bossWarning: "You are too far from the Boss! ",
		expGain: "+",
		wavePrefix: "Wave",
		levelPrefix: "Level",
		expPrefix: "EXP",
		hpPrefix: "HP"
	},
	tr: {
		start: "Oyuna Başla",
		languages: "Diller",
		returnMainMenu: "Ana Menüye Dön",
		death: "Öldün!",
		lang_tr: "Türkçe",
		lang_en: "English",
		hp: "Can",
		wave: "Dalga",
		level: "Seviye",
		exp: "EXP",
		expShort: "EXP",
		weaponSelect: "Silahını Seç",
		unlock: "Aç",
		noOption: "Seçenek Yok",
		buffs: {
			damageReduction: "Hasar Azaltma+",
			moveSpeed: "Hareket Hızı Artışı+",
			hpRegen: "Can Yenileme+",
			damageReflection: "Hasar Yansıtma+",
			// gritWound: "Derin Yara+", (removed)
			enemySlow: "Düşman Yavaşlatma+",
			enemyStun: "Düşman Sersemletme+",
			// bleeding: "Kanama+", (removed)
			critChance: "Kritik Vuruş Şansı+",
			maxHpPlus: "Maksimum Can+",
			magnetPlus: "Mıknatıs+"
		},
		buffDescs: {
			damageReduction: "Her yükseltilişte %10 daha az hasar alırsın.",
			moveSpeed: "Her yükseltilişte %20 daha hızlı hareket edersin.",
			hpRegen: "Her yükseltilişte 5 saniyede bir maksimum canının %1'i kadar yenilenirsin.",
			damageReflection: "Her yükseltilişte %5 hasarı yansıtırsın.",
			// gritWound: "Her yükseltilişte düşman yenilenmesini %10 azaltır.", (removed)
			enemySlow: "Her yükseltilişte düşmanları %10 yavaşlatır.",
			enemyStun: "Her yükseltilişte düşmanları 0.1s sersemletir.",
			// bleeding: "Her yükseltilişte 4s boyunca, 0.5s arayla, her tikte maksimum canın %5'i kadar kanama.", (removed)
			critChance: "Her yükseltilişte kritik vuruş şansını %15 artırır.",
			maxHpPlus: "Her yükseltilişte maksimum canı 25 artırır.",
			magnetPlus: "Yakındaki EXP küreleri (150 yarıçap, yükseltiliş başına +150) hızlıca sana çekilir."
		},
		upgrade: "Yükselt",
		desc_damage: "Silah hasarını %20 artırır.",
		desc_atkspd: "Silah saldırı hızını %10 artırır.",
		desc_range: "Silah menzilini ve boyutunu %10 artırır.",
		bossWarning: "Boss'tan çok uzaktasın! ",
		expGain: "+",
		wavePrefix: "Dalga",
		levelPrefix: "Seviye",
		expPrefix: "EXP",
		hpPrefix: "Can"
	}
};
// --- Language helper ---
function t(key) {
	if (TEXTS[currentLanguage] && TEXTS[currentLanguage][key]) {
		return TEXTS[currentLanguage][key];
	}
	// fallback
	return TEXTS["en"][key] || key;
}
// --- Menu helpers ---
function showMainMenu() {
	gameState = GAME_STATE.MAIN_MENU;
	// 1) Tüm UI ve sesleri kapat
	setGameUIVisible(false);
	LK.stopMusic();
	window._mainMenuMusicPlaying = false;
	if (typeof LK.stopAllSounds === "function") {
		LK.stopAllSounds();
	}
	// 2) Önceki overlay'leri temizle
	if (mainMenuContainer) {
		mainMenuContainer.destroy();
	}
	if (languageMenuContainer) {
		languageMenuContainer.destroy();
	}
	if (deathScreenContainer) {
		deathScreenContainer.destroy();
	}
	if (typeof currentMusic === "undefined") {
		currentMusic = null;
	}
	// Menü kurma işini bir yardımcıya alıyoruz:
	function buildMenu() {
		// Container’ı oluştur ya da görünür yap
		if (!mainMenuContainer) {
			mainMenuContainer = game.addChild(new Container());
		}
		mainMenuContainer.visible = true;
		// Always (re)create Instagram text below Languages button
		if (mainMenuContainer._instagramText && mainMenuContainer._instagramText.parent) {
			mainMenuContainer._instagramText.destroy();
			mainMenuContainer._instagramText = null;
		}
		// We'll add the Instagram text after the Languages button is created, so just skip here.
		// Müzik izin verildiyse başlat
		if (!window._mainMenuMusicPlaying) {
			LK.playMusic('mainMenuMusic', {
				loop: true
			});
			window._mainMenuMusicPlaying = true;
		}
		currentMusic = "mainMenuMusic";
		// — Arka plan —
		var bg = mainMenuContainer.attachAsset('mainMenuBackground', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 1024,
			y: 1366
		});
		// — Start Button —
		var startBtn = mainMenuContainer.addChild(new Container());
		startBtn.attachAsset('startButton', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		startBtn.x = 1024;
		startBtn.y = 1200;
		var startTxt = new Text2(t("start"), {
			size: 72,
			fill: 0xffffff
		});
		startTxt.anchor.set(0.5);
		startBtn.addChild(startTxt);
		startBtn.interactive = true;
		startBtn.down = function () {
			mainMenuContainer.destroy();
			mainMenuContainer = null;
			startGame();
		};
		// — Languages Button —
		var langBtn = mainMenuContainer.addChild(new Container());
		langBtn.attachAsset('languagesButton', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		langBtn.x = 1024;
		langBtn.y = 1600;
		var langTxt = new Text2(t("languages"), {
			size: 72,
			fill: 0xffffff
		});
		langTxt.anchor.set(0.5);
		langBtn.addChild(langTxt);
		langBtn.interactive = true;
		langBtn.down = function () {
			// Butonları gizle
			startBtn.visible = langBtn.visible = false;
			startBtn.interactive = langBtn.interactive = false;
			showLanguageMenu(function () {
				// Tekrar aç
				startBtn.visible = langBtn.visible = true;
				startBtn.interactive = langBtn.interactive = true;
				startTxt.setText(t("start"));
				langTxt.setText(t("languages"));
			});
		};
		// Add Instagram text below Languages button
		if (mainMenuContainer._instagramText && mainMenuContainer._instagramText.parent) {
			mainMenuContainer._instagramText.destroy();
			mainMenuContainer._instagramText = null;
		}
		var instaText = new Text2("Instagram: ugurcanyardim_", {
			size: 66,
			fill: 0xff6666,
			align: "center",
			wordWrap: false
		});
		instaText.anchor.set(0.5, 0);
		instaText.x = langBtn.x - 586;
		instaText.y = langBtn.y + 1040;
		mainMenuContainer.addChild(instaText);
		mainMenuContainer._instagramText = instaText;
		// Add "Açık Beta" (TR) or "Open Beta" (EN) to the right of Instagram text
		var betaLabel = currentLanguage === "tr" ? "Açık Beta" : "Open Beta";
		var betaText = new Text2(betaLabel, {
			size: 66,
			fill: 0xffe066,
			align: "left",
			wordWrap: false
		});
		betaText.anchor.set(0, 0); // left-top
		// Place it to the right of instaText, with a small gap
		betaText.x = instaText.x + 1274;
		betaText.y = instaText.y;
		mainMenuContainer.addChild(betaText);
		mainMenuContainer._betaText = betaText;
	}
	// İlk açılış mı, yoksa menüye dönme mi?
	if (!window._hasShownRedOverlay) {
		var finish = function finish() {
			if (done) {
				return;
			}
			done = true;
			window._blockAllSounds = false;
			if (redOverlay.parent) {
				redOverlay.destroy();
			}
			buildMenu();
		};
		window._hasShownRedOverlay = true;
		// 3) Kırmızı loading overlay
		var redOverlay = game.addChild(new Container());
		redOverlay.attachAsset('hpBarRect', {
			anchorX: 0,
			anchorY: 0,
			x: 0,
			y: 0,
			width: 2048,
			height: 2732,
			color: 0xff0000,
			tint: 0xff0000,
			alpha: 1
		});
		redOverlay.interactive = true;
		redOverlay.down = redOverlay.move = redOverlay.up = function () {};
		// Add myLogo above Loading... text
		var logoAsset = LK.getAsset('myLogo', {
			anchorX: 0.5,
			anchorY: 0.5,
			x: 1024,
			y: 950
		});
		redOverlay.addChild(logoAsset);
		var loadingText = new Text2("Loading...", {
			size: 100,
			fill: 0xffffff
		});
		loadingText.anchor.set(0.5);
		loadingText.x = 1024;
		loadingText.y = 1200;
		redOverlay.addChild(loadingText);
		// Subtitle for best experience, word-wrapped and centered, does not overflow
		var loadingSubTxt = new Text2("For the best gaming experience, please wait until the game's graphic and audio resources are fully loaded.", {
			size: 36,
			fill: 0xffffff,
			wordWrap: true,
			wordWrapWidth: 1800,
			align: "center"
		});
		loadingSubTxt.anchor.set(0.5, 0);
		loadingSubTxt.x = 1024;
		loadingSubTxt.y = 1300;
		redOverlay.addChild(loadingSubTxt);
		var spinner = new Container();
		var spinGfx = spinner.attachAsset('chickenLeg', {
			anchorX: 0.5,
			anchorY: 0.5,
			width: 120,
			height: 120
		});
		spinner.x = 1024;
		spinner.y = 1450;
		spinner.update = function () {
			spinGfx.rotation += 0.2;
		};
		redOverlay.addChild(spinner);
		redOverlay.update = function () {
			spinner.update();
		};
		// Tüm diğer sesleri bloke et
		window._blockAllSounds = true;
		LK.stopMusic();
		if (typeof LK.stopAllSounds === "function") {
			LK.stopAllSounds();
		}
		// 4) introSpeech’i çal ve sonlanınca ya da 10s sonra menüyü kur
		var done = false;
		var intro = LK.getSound('introSpeech');
		var redOverlayTimeout = LK.setTimeout(finish, 10000); // Always remove after 10s
		if (intro && typeof intro.play === "function") {
			intro.play();
			if (typeof intro.once === "function") {
				intro.once('ended', function () {
					LK.clearTimeout(redOverlayTimeout); // Remove timeout if introSpeech ends first
					finish();
				});
			} else {
				// Fallback: 10 saniye sonra (timeout already set)
			}
		} else {
			// Eğer introSpeech yoksa hemen
			LK.clearTimeout(redOverlayTimeout);
			finish();
		}
	} else {
		// İlk açılış değil: anında menüyü göster
		buildMenu();
	}
}
function showLanguageMenu(onClose) {
	if (languageMenuContainer) {
		languageMenuContainer.destroy();
	}
	languageMenuContainer = game.addChild(new Container());
	languageMenuContainer.x = 1024;
	languageMenuContainer.y = 1366;
	// Türkçe button
	var trBtn = languageMenuContainer.addChild(new Container());
	trBtn.attachAsset('langButton', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	trBtn.x = 0;
	trBtn.y = -120;
	var trTxt = new Text2(t("lang_tr"), {
		size: 56,
		fill: 0x222222
	});
	trTxt.anchor.set(0.5);
	trBtn.addChild(trTxt);
	trBtn.down = function () {
		currentLanguage = "tr";
		languageMenuContainer.destroy();
		languageMenuContainer = null;
		window._mainMenuMusicPlaying = false; // Defensive: always reset flag on language menu
		// Do not stop or restart music here; showMainMenu will handle music logic
		// Do not stop or restart music here; let showMainMenu handle music logic
		// Instead of showMainMenu, just refresh mainMenuContainer text and language
		if (mainMenuContainer) {
			// Update start and language button texts
			for (var i = 0; i < mainMenuContainer.children.length; i++) {
				var ch = mainMenuContainer.children[i];
				if (ch && ch.children && ch.children.length > 0) {
					var txt = ch.children[0];
					if (txt && txt.setText) {
						if (ch === mainMenuContainer.children[0]) {
							txt.setText(t("start"));
						} else if (ch === mainMenuContainer.children[1]) {
							txt.setText(t("languages"));
						}
					}
				}
			}
			// Update beta label text if present
			if (mainMenuContainer._betaText) {
				mainMenuContainer._betaText.setText("Açık Beta");
			}
		}
		if (typeof onClose === "function") {
			onClose();
		}
	};
	// English button
	var enBtn = languageMenuContainer.addChild(new Container());
	enBtn.attachAsset('langButton', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	enBtn.x = 0;
	enBtn.y = 120;
	var enTxt = new Text2(t("lang_en"), {
		size: 56,
		fill: 0x222222
	});
	enTxt.anchor.set(0.5);
	enBtn.addChild(enTxt);
	enBtn.down = function () {
		currentLanguage = "en";
		languageMenuContainer.destroy();
		languageMenuContainer = null;
		window._mainMenuMusicPlaying = false; // Defensive: always reset flag on language menu
		// Do not stop or restart music here; let showMainMenu handle music logic
		// Instead of showMainMenu, just refresh mainMenuContainer text and language
		if (mainMenuContainer) {
			// Update start and language button texts
			for (var i = 0; i < mainMenuContainer.children.length; i++) {
				var ch = mainMenuContainer.children[i];
				if (ch && ch.children && ch.children.length > 0) {
					var txt = ch.children[0];
					if (txt && txt.setText) {
						if (ch === mainMenuContainer.children[0]) {
							txt.setText(t("start"));
						} else if (ch === mainMenuContainer.children[1]) {
							txt.setText(t("languages"));
						}
					}
				}
			}
			// Update beta label text if present
			if (mainMenuContainer._betaText) {
				mainMenuContainer._betaText.setText("Open Beta");
			}
		}
		if (typeof onClose === "function") {
			onClose();
		}
	};
}
function showDeathScreen() {
	gameState = GAME_STATE.DEATH;
	// Hide all game UI and stop all game sounds/music
	setGameUIVisible(false);
	LK.stopMusic();
	window._mainMenuMusicPlaying = false;
	if (typeof LK.stopAllSounds === "function") {
		LK.stopAllSounds();
	}
	// Play death sound when death screen is shown
	if (LK.getSound && LK.getSound('death')) {
		// Defensive: stop all weapon/attack sounds before playing death sound
		var weaponSounds = ['swordSoundEffect', 'bumerangSoundEffect', 'ballSoundEffect', 'rocketSoundEffect', 'brickSoundEffect', 'lightningSoundEffect', 'molotovSoundEffect', 'molotovBoom', 'rocketBoom', 'hit'];
		for (var i = 0; i < weaponSounds.length; i++) {
			var s = LK.getSound(weaponSounds[i]);
			if (s && typeof s.stop === "function") {
				s.stop();
			}
		}
		LK.getSound('death').play();
	}
	// Remove overlays if any
	if (mainMenuContainer) {
		mainMenuContainer.destroy();
	}
	if (languageMenuContainer) {
		languageMenuContainer.destroy();
	}
	if (deathScreenContainer) {
		deathScreenContainer.destroy();
	}
	// Destroy all enemies and clear enemy array
	if (typeof enemies !== "undefined" && enemies.length > 0) {
		for (var i = enemies.length - 1; i >= 0; i--) {
			if (enemies[i] && typeof enemies[i].destroy === "function") {
				enemies[i].destroy();
			}
			enemies.splice(i, 1);
		}
	}
	// Music is now handled in game.update based on gameState
	if (typeof currentMusic === "undefined") {
		currentMusic = null;
	}
	deathScreenContainer = game.addChild(new Container());
	// Background
	var bg = deathScreenContainer.attachAsset('deathBackground', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 1024,
		y: 1366
	});
	// Death text
	var deathTxt = new Text2(t("death"), {
		size: 120,
		fill: 0xffffff
	});
	deathTxt.anchor.set(0.5);
	deathTxt.x = 1024;
	deathTxt.y = 1100;
	deathScreenContainer.addChild(deathTxt);
	// Return Main Menu Button
	var retBtn = deathScreenContainer.addChild(new Container());
	retBtn.attachAsset('returnMainMenu', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	retBtn.x = 1024;
	retBtn.y = 1450;
	var retTxt = new Text2(t("returnMainMenu"), {
		size: 60,
		fill: 0xffffff
	});
	retTxt.anchor.set(0.5);
	retBtn.addChild(retTxt);
	retBtn.down = function () {
		// Reset everything and go to main menu
		deathScreenContainer.destroy();
		deathScreenContainer = null;
		resetGameToMainMenu();
	};
	// Show highest wave and elapsed time below the button
	var waveStr, timeStr;
	if (currentLanguage === "tr") {
		waveStr = "Ulaşılan En Yüksek Dalga: " + waveNumber;
	} else {
		waveStr = "Highest Wave Reached: " + waveNumber;
	}
	var elapsedSeconds = Math.floor(gameTime / 60);
	var minutes = Math.floor(elapsedSeconds / 60);
	var seconds = elapsedSeconds % 60;
	var timeFormatted = (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
	if (currentLanguage === "tr") {
		timeStr = "Geçen Süre: " + timeFormatted;
	} else {
		timeStr = "Elapsed Time: " + timeFormatted;
	}
	var waveTextDeath = new Text2(waveStr, {
		size: 60,
		fill: 0x00ffff,
		wordWrap: true,
		wordWrapWidth: 1800,
		align: "center"
	});
	waveTextDeath.anchor.set(0.5, 0);
	waveTextDeath.x = 1024;
	waveTextDeath.y = retBtn.y + 220;
	deathScreenContainer.addChild(waveTextDeath);
	var timeTextDeath = new Text2(timeStr, {
		size: 54,
		fill: 0x00ffff,
		wordWrap: true,
		wordWrapWidth: 1800,
		align: "center"
	});
	timeTextDeath.anchor.set(0.5, 0);
	timeTextDeath.x = 1024;
	timeTextDeath.y = waveTextDeath.y + 80;
	deathScreenContainer.addChild(timeTextDeath);
}
// --- Game start/reset helpers ---
function startGame() {
	gameState = GAME_STATE.PLAYING;
	// Show all game UI and resume game sounds/music
	setGameUIVisible(true);
	LK.stopMusic();
	window._mainMenuMusicPlaying = false;
	if (typeof LK.stopAllSounds === "function") {
		LK.stopAllSounds();
	}
	if (typeof currentMusic === "undefined") {
		currentMusic = null;
	}
	// Music is now handled in game.update based on gameState
	// Reset all game variables and containers
	resetGameWorld();
	// Defensive: joystick and knob always visible and on top
	if (typeof joystick !== "undefined" && joystick) {
		joystick.visible = true;
		if (joystick.parent && typeof joystick.parent.setChildIndex === "function") {
			joystick.parent.setChildIndex(joystick, joystick.parent.children.length - 1);
		}
		if (joystick.children && joystick.children.length > 1) {
			var knob = joystick.children[1];
			knob.visible = true;
			if (knob.parent && typeof knob.parent.setChildIndex === "function") {
				knob.parent.setChildIndex(knob, knob.parent.children.length - 1);
			}
		}
	}
}
function resetGameToMainMenu() {
	// Destroy all overlays and containers
	setGameUIVisible(false);
	LK.stopMusic();
	window._mainMenuMusicPlaying = false;
	if (typeof LK.stopAllSounds === "function") {
		LK.stopAllSounds();
	}
	// Music is now handled in game.update based on gameState
	// Destroy all overlays if exist
	if (mainMenuContainer && mainMenuContainer.destroy) {
		mainMenuContainer.destroy();
	}
	if (languageMenuContainer && languageMenuContainer.destroy) {
		languageMenuContainer.destroy();
	}
	if (deathScreenContainer && deathScreenContainer.destroy) {
		deathScreenContainer.destroy();
	}
	mainMenuContainer = null;
	languageMenuContainer = null;
	deathScreenContainer = null;
	// Destroy all game world objects and arrays
	if (typeof enemies !== "undefined" && enemies.length > 0) {
		for (var i = enemies.length - 1; i >= 0; i--) {
			if (enemies[i] && typeof enemies[i].destroy === "function") {
				enemies[i].destroy();
			}
			enemies.splice(i, 1);
		}
	}
	if (typeof bullets !== "undefined" && bullets.length > 0) {
		for (var i = bullets.length - 1; i >= 0; i--) {
			if (bullets[i] && typeof bullets[i].destroy === "function") {
				bullets[i].destroy();
			}
			bullets.splice(i, 1);
		}
	}
	if (typeof expOrbs !== "undefined" && expOrbs.length > 0) {
		for (var i = expOrbs.length - 1; i >= 0; i--) {
			if (expOrbs[i] && typeof expOrbs[i].destroy === "function") {
				expOrbs[i].destroy();
			}
			expOrbs.splice(i, 1);
		}
	}
	if (typeof pickups !== "undefined" && pickups.length > 0) {
		for (var i = pickups.length - 1; i >= 0; i--) {
			if (pickups[i] && typeof pickups[i].destroy === "function") {
				pickups[i].destroy();
			}
			pickups.splice(i, 1);
		}
	}
	if (typeof shurikenObjs !== "undefined" && shurikenObjs.length > 0) {
		for (var i = shurikenObjs.length - 1; i >= 0; i--) {
			if (shurikenObjs[i] && typeof shurikenObjs[i].destroy === "function") {
				shurikenObjs[i].destroy();
			}
			shurikenObjs.splice(i, 1);
		}
	}
	if (typeof backgroundTiles !== "undefined" && backgroundTiles.length > 0) {
		for (var i = backgroundTiles.length - 1; i >= 0; i--) {
			if (backgroundTiles[i] && typeof backgroundTiles[i].destroy === "function") {
				backgroundTiles[i].destroy();
			}
			backgroundTiles.splice(i, 1);
		}
	}
	// Remove all children from gameContainer
	if (typeof gameContainer !== "undefined" && gameContainer && gameContainer.children) {
		for (var i = gameContainer.children.length - 1; i >= 0; i--) {
			var ch = gameContainer.children[i];
			if (ch && ch.destroy) {
				ch.destroy();
			}
		}
		gameContainer.children = [];
	}
	// Remove overlays
	if (typeof weaponSelectionOverlay !== "undefined" && weaponSelectionOverlay && weaponSelectionOverlay.destroy) {
		weaponSelectionOverlay.destroy();
		weaponSelectionOverlay = null;
	}
	if (typeof ov !== "undefined" && ov && ov.destroy) {
		ov.destroy();
	}
	window._mainMenuMusicPlaying = false; // Defensive: always reset flag on overlays
	// Remove joystick from GUI
	if (typeof joystick !== "undefined" && joystick && joystick.parent && joystick.parent.removeChild) {
		joystick.parent.removeChild(joystick);
	}
	joystick = null;
	// Reset all global variables to initial state
	enemies = [];
	bullets = [];
	expOrbs = [];
	pickups = [];
	shurikenObjs = [];
	backgroundTiles = [];
	player = undefined;
	gameTime = 0;
	waveNumber = 1;
	nextWaveTimeout = null;
	skillSelectionActive = false;
	weaponSelectionActive = false;
	weaponSelectionOverlay = null;
	auraField = null;
	lastPickupSpawn = 0;
	camera = {
		x: 0,
		y: 0
	};
	selectedSkills = [];
	// UI elements
	timerText = null;
	waveText = null;
	levelText = null;
	hpText = null;
	// Clear boss rebirth event
	if (typeof bossRebirthEventTimer !== "undefined" && bossRebirthEventTimer) {
		LK.clearInterval(bossRebirthEventTimer);
		bossRebirthEventTimer = null;
	}
	bossRebirthEvent = null;
	// Remove any global buff counters
	if (typeof window.magnetPlusBuffCount !== "undefined") {
		window.magnetPlusBuffCount = undefined;
	}
	// Reset game state to main menu
	gameState = GAME_STATE.MAIN_MENU;
	currentMusic = null;
	// Show main menu
	showMainMenu();
}
// --- Reset game world (player, enemies, etc) ---
function resetGameWorld() {
	// Remove all children from gameContainer (or create if not exists)
	if (!gameContainer) {
		gameContainer = game.addChild(new Container());
	} else if (gameContainer.children) {
		for (var i = gameContainer.children.length - 1; i >= 0; i--) {
			var ch = gameContainer.children[i];
			if (ch && ch.destroy) {
				ch.destroy();
			}
		}
		gameContainer.children = [];
	}
	// Reset arrays and variables
	enemies = [];
	bullets = [];
	expOrbs = [];
	pickups = [];
	shurikenObjs = [];
	auraField = null;
	waveNumber = 1;
	gameTime = 0;
	nextWaveTimeout = null;
	skillSelectionActive = false;
	weaponSelectionActive = true;
	// Remove overlays
	if (weaponSelectionOverlay) {
		weaponSelectionOverlay.destroy();
		weaponSelectionOverlay = null;
	}
	window._mainMenuMusicPlaying = false; // Defensive: always reset flag on world reset
	// Clear boss rebirth event
	if (typeof bossRebirthEventTimer !== "undefined" && bossRebirthEventTimer) {
		LK.clearInterval(bossRebirthEventTimer);
		bossRebirthEventTimer = null;
	}
	bossRebirthEvent = null;
	// Remove background tiles
	if (backgroundTiles && backgroundTiles.length) {
		for (var i = 0; i < backgroundTiles.length; i++) {
			if (backgroundTiles[i] && backgroundTiles[i].destroy) {
				backgroundTiles[i].destroy();
			}
		}
		backgroundTiles = [];
	}
	// Recreate background tiles
	for (var i = 0; i < bgTilesX; i++) {
		for (var j = 0; j < bgTilesY; j++) {
			var tile = LK.getAsset('seamlessBackGround', {
				anchorX: 0,
				anchorY: 0
			});
			tile.x = i * bgTileWidth;
			tile.y = j * bgTileHeight;
			gameContainer.addChild(tile);
			backgroundTiles.push(tile);
		}
	}
	// Create player
	player = gameContainer.addChild(new Player());
	player.x = 1024;
	player.y = 1366;
	// Health bar for player
	player.hpBar = new Container();
	player.hpBarBg = LK.getAsset('hpBarRect', {
		anchorX: 0,
		anchorY: 0.5
	});
	player.hpBarBg.alpha = 0.3;
	player.hpBarFg = LK.getAsset('hpBarRectFg', {
		anchorX: -0.02,
		anchorY: 0.5
	});
	player.hpBar.addChild(player.hpBarBg);
	player.hpBar.addChild(player.hpBarFg);
	player.hpBar.y = -140;
	player.hpBar.x = -110;
	player.addChild(player.hpBar);
	// Create joystick if not exists
	if (!joystick) {
		joystick = new Joystick();
		joystick.x = 0;
		joystick.y = -300;
		LK.gui.bottom.addChild(joystick);
	} else {
		joystick.reset();
		// Yeniden başlatıldığında da ortala
		joystick.x = 1024; // Ekranın tam ortası X
		joystick.y = 1366; // Ekranın tam ortası Y
	}
	// Her zaman joystick'i görünür yap ve öne getir
	joystick.visible = true;
	if (joystick.parent && typeof joystick.parent.setChildIndex === "function") {
		joystick.parent.setChildIndex(joystick, joystick.parent.children.length - 1);
	}
	// UI: create if not exists, else reset text
	if (!timerText) {
		timerText = new Text2('00:00', {
			size: 80,
			fill: 0xFFFFFF
		});
		timerText.anchor.set(0.5, 0);
		LK.gui.top.addChild(timerText);
	}
	timerText.setText('00:00');
	if (!waveText) {
		waveText = new Text2(t("wavePrefix") + " 1", {
			size: 80,
			fill: 0x00FFFF
		});
		waveText.anchor.set(0.5, 0);
		waveText.y = 100;
		LK.gui.top.addChild(waveText);
	}
	waveText.setText(t("wavePrefix") + " 1");
	if (!levelText) {
		levelText = new Text2(t("levelPrefix") + " 1", {
			size: 60,
			fill: 0xFFFF00
		});
		levelText.anchor.set(0, 0);
		levelText.y = 10;
		// Move a bit more left to avoid overflow at high levels
		levelText.x = 160;
		LK.gui.top.addChild(levelText);
	}
	levelText.setText(t("levelPrefix") + " 1");
	if (!hpText) {
		hpText = new Text2(t("hpPrefix") + ": 100/100", {
			size: 60,
			fill: 0xFF0000
		});
		hpText.anchor.set(1, 0);
		hpText.y = 10;
		hpText.x = -200;
		LK.gui.top.addChild(hpText);
	}
	hpText.setText(t("hpPrefix") + ": 100/100");
	// Remove skill overlays
	if (typeof ov !== "undefined" && ov && ov.destroy) {
		ov.destroy();
	}
	window._mainMenuMusicPlaying = false; // Defensive: always reset flag on overlays (world reset)
	// Weapon selection overlay
	weaponSelectionActive = true;
	weaponSelectionOverlay = game.addChild(new Container());
	weaponSelectionOverlay.x = 1024;
	weaponSelectionOverlay.y = 1366;
	// Add overlay title below wave text
	var weaponSelTitleStr = "";
	if (currentLanguage === "tr") {
		weaponSelTitleStr = "Başlangıç Silahınızı Seçin";
	} else {
		weaponSelTitleStr = "Choose Your Starting Weapon";
	}
	var weaponSelTitle = new Text2(weaponSelTitleStr, {
		size: 64,
		fill: 0xffffff,
		wordWrap: true,
		wordWrapWidth: 900
	});
	weaponSelTitle.anchor.set(0.5, 0);
	// Place below waveText (which is at y=100), so e.g. y=200
	weaponSelTitle.y = 200;
	LK.gui.top.addChild(weaponSelTitle);
	// Remove the title when overlay is destroyed
	weaponSelectionOverlay._titleText = weaponSelTitle;
	weaponSelectionOverlay.destroy = function (origDestroy) {
		return function () {
			if (this._titleText && this._titleText.parent) {
				this._titleText.destroy();
			}
			if (typeof origDestroy === "function") {
				origDestroy.call(this);
			}
		};
	}(weaponSelectionOverlay.destroy);
	// Cards
	var allWeaponKeys = Object.keys(WEAPONS);
	for (var i = 0; i < allWeaponKeys.length; i++) {
		(function (idx) {
			var key = allWeaponKeys[idx];
			var card = weaponSelectionOverlay.addChild(new Container());
			card.attachAsset('skillCard', {
				anchorX: 0.5,
				anchorY: 0.5
			});
			var col = idx % 3;
			var row = Math.floor(idx / 3);
			// Increase horizontal spacing to 440 and move cards lower by 120px
			card.x = (col - 1) * 440;
			card.y = (row - 1) * 700 + 120;
			// Localize weapon name for selection overlay
			var trWeaponNames = {
				sword: "Kılıç",
				boomerang: "Bumerang",
				ball: "Top",
				rocket: "Roket",
				brick: "Tuğla",
				lightning: "Yıldırım",
				aura: "Aura",
				molotov: "Molotof",
				shuriken: "Ninja Yıldızı"
			};
			var weaponLabel = currentLanguage === "tr" && trWeaponNames[key] ? trWeaponNames[key] : key.charAt(0).toUpperCase() + key.slice(1);
			var txt = new Text2(weaponLabel, {
				size: 48,
				fill: 0xffffff
			});
			txt.anchor.set(0.5);
			card.addChild(txt);
			card.down = function () {
				player.weapons = {};
				addWeapon(key);
				weaponSelectionActive = false;
				weaponSelectionOverlay.destroy();
				skillSelectionActive = false;
				spawnWave();
			};
		})(i);
	}
	skillSelectionActive = true;
}
// --- New zombie attack/projectile assets ---
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);
}
function isWithinRange(e, maxRange) {
	var dx = e.x - player.x;
	var dy = e.y - player.y;
	return dx * dx + dy * dy <= maxRange * maxRange;
}
function addWeapon(key) {
	//  <-- artık global
	if (player && Object.keys(player.weapons).length >= 6) {
		return; // Zaten 6 silah varsa yeni eklemeye izin verme
	}
	var m = WEAPONS[key];
	var target = player ? player : {
		weapons: {}
	}; // sınıf kurulumunda da çalışsın
	target.weapons[key] = {
		cd: m.cd,
		cdCnt: m.cd,
		dmgMul: 1,
		rngMul: 1,
		amount: 1,
		upgrade: 0,
		enchTaken: []
	};
}
function rand(min, max) {
	return min + Math.random() * (max - min);
}
function distSq(a, b) {
	var dx = a.x - b.x,
		dy = a.y - b.y;
	return dx * dx + dy * dy;
}
function unitDir(from, to) {
	var dx = to.x - from.x,
		dy = to.y - from.y,
		d = Math.sqrt(dx * dx + dy * dy);
	return {
		dx: dx / d,
		dy: dy / d,
		len: d
	};
}
/* ==== WEAPON META TABLE ==== */
var WEAPONS = {
	sword: {
		cd: 120,
		dmg: 10,
		range: 200,
		type: 'melee',
		ench: ["Sword Damage+", "Sword Attack Speed+", "Sword Range+"],
		up: ["Sword +1", "Sword +2", "Sword +3"]
	},
	boomerang: {
		cd: 240,
		dmg: 6,
		range: 600,
		type: 'boomerang',
		ench: ["Boomerang Damage+", "Boomerang Attack Speed+", "Boomerang Range+"],
		up: ["Boomerang +1", "Boomerang +2", "Boomerang +3"]
	},
	ball: {
		cd: 240,
		dmg: 6,
		range: 600,
		type: 'ball',
		ench: ["Ball Damage+", "Ball Attack Speed+", "Ball Range+"],
		up: ["Ball +1", "Ball +2", "Ball +3"]
	},
	rocket: {
		cd: 480,
		dmg: 16,
		range: 900,
		type: 'rocket',
		ench: ["Rocket Damage+", "Rocket Attack Speed+", "Rocket Range+"],
		up: ["Rocket +1", "Rocket +2", "Rocket +3"]
	},
	brick: {
		cd: 240,
		dmg: 6,
		range: 500,
		type: 'brick',
		ench: ["Brick Damage+", "Brick Attack Speed+", "Brick Range+"],
		up: ["Back 75°", "Front 45°", "Back 45°"]
	},
	lightning: {
		cd: 180,
		dmg: 10,
		range: 1000,
		type: 'lightning',
		ench: ["Lightning Damage+", "Lightning Attack Speed+", "Lightning Range+"],
		up: ["Lightning +1", "Lightning +2", "Lightning +3"]
	},
	aura: {
		cd: 60,
		dmg: 3,
		range: 250,
		type: 'aura',
		ench: ["Aura Damage+", "Aura Attack Speed+", "Aura Range+"],
		up: ["Slow 25%", "Slow 50%", "Slow 75%"]
	},
	molotov: {
		cd: 180,
		dmg: 9,
		range: 600,
		type: 'molotov',
		ench: ["Molotov Damage+", "Molotov Attack Speed+", "Molotov Range+"],
		up: ["Molotov +1", "Molotov +2", "Molotov +3"]
	},
	shuriken: {
		cd: 180,
		dmg: 6,
		range: 300,
		type: 'shuriken',
		ench: ["Shuriken Damage+", "Shuriken Attack Speed+", "Shuriken Range+"],
		up: ["Shuriken +1", "Shuriken +2", "Shuriken +3"]
	}
};
var player;
var enemies = [];
var bullets = [];
var expOrbs = [];
var joystick;
var gameTime = 0;
var waveNumber = 1;
var selectedSkills = [];
var camera = {
	x: 0,
	y: 0
};
var gameContainer;
var skillSelectionActive = false;
var pickups = [];
var lastPickupSpawn = 0;
// --- Game world variables (do not initialize world here, only declare) ---
var gameContainer;
var bgTileAsset = LK.getAsset('seamlessBackGround', {
	anchorX: 0,
	anchorY: 0
});
var bgTileWidth = bgTileAsset.width;
var bgTileHeight = bgTileAsset.height;
var bgTilesX = Math.ceil(2048 / bgTileWidth) + 2; // +2 for safe margin
var bgTilesY = Math.ceil(2732 / bgTileHeight) + 2;
var backgroundTiles = [];
var player;
var weaponSelectionActive = false;
var weaponSelectionOverlay = null;
var joystick = null;
var timerText = null;
var waveText = null;
var levelText = null;
var hpText = null;
// --- Boss Rebirth Event State ---
var bossRebirthEvent = null;
var bossRebirthEventTimer = null;
// Helper to show/hide all game UI elements
function setGameUIVisible(visible) {
	if (timerText) {
		timerText.visible = visible;
	}
	if (waveText) {
		waveText.visible = visible;
	}
	if (levelText) {
		levelText.visible = visible;
	}
	if (hpText) {
		hpText.visible = visible;
	}
	// Hide joystick as well if not playing
	if (joystick) {
		joystick.visible = visible;
	}
	if (!visible) {
		window._mainMenuMusicPlaying = false;
	}
}
// Spawn functions
function spawnEnemy(type, x, y) {
	var enemy;
	if (type === 'normal' || type === 'normalZombie') {
		enemy = new NormalZombie();
	} else if (type === 'rangedZombie') {
		enemy = new RangedZombie();
	} else if (type === 'fastZombie') {
		enemy = new FastZombie();
	} else if (type === 'tankZombie') {
		enemy = new TankZombie();
	} else if (type === 'bossZombie') {
		enemy = new BossZombie();
	} else if (type === 'healerZombie') {
		enemy = new HealerZombie();
	} else {
		enemy = new NormalZombie();
	}
	// --- 11. dalgadan itibaren tüm zombilere %5 max HP ve %5 saldırı gücü artışı ---
	if (waveNumber >= 11) {
		var hpMul = Math.pow(1.10, waveNumber - 10);
		var dmgMul = Math.pow(1.10, waveNumber - 10);
		enemy.maxHp *= hpMul;
		enemy.hp = enemy.maxHp;
		if (typeof enemy.damage === "number") {
			enemy.damage *= dmgMul;
		}
		if (typeof enemy.damageMelee === "number") {
			enemy.damageMelee *= dmgMul;
		}
		if (typeof enemy.damageRanged === "number") {
			enemy.damageRanged *= dmgMul;
		}
	}
	enemy.x = x;
	enemy.y = y;
	// --- Düşman can yenileme: 5. dalgadan sonra, her 5 dalgada +1% artar ---
	if (waveNumber > 5) {
		var regenPercent = 5 + Math.floor((waveNumber - 6) / 5) + 0;
		enemy.enemyRegen = regenPercent;
	} else {
		enemy.enemyRegen = 0;
	}
	enemies.push(enemy);
	gameContainer.addChild(enemy);
	// --- Health bar for enemy ---
	enemy.hpBar = new Container();
	enemy.hpBarBg = LK.getAsset('enemyHpBarRect', {
		anchorX: 0.0,
		anchorY: 0.5
	});
	enemy.hpBarBg.alpha = 0.3;
	enemy.hpBarFg = LK.getAsset('enemyHpBarRectFg', {
		anchorX: -0.04,
		anchorY: 0.5
	});
	enemy.hpBar.addChild(enemy.hpBarBg);
	enemy.hpBar.addChild(enemy.hpBarFg);
	enemy.hpBar.y = -110;
	enemy.hpBar.x = -80;
	enemy.addChild(enemy.hpBar);
}
function spawnWave() {
	var spawnRadius = 1500;
	var spawnList = [];
	// Eski dalga sistemi: her dalgada normal, ranged, fast, tank ve boss (her 10. dalgada) zombi
	var normalCount = 5 + (waveNumber - 1);
	var rangedCount = waveNumber >= 3 ? waveNumber - 2 : 0;
	var fastCount = waveNumber >= 6 ? waveNumber - 5 : 0;
	var tankCount = waveNumber >= 9 ? waveNumber - 8 : 0;
	var bossCount = waveNumber % 10 === 0 ? Math.floor(waveNumber / 10) : 0;
	// --- HealerZombie: Artık ilk dalgada veya dalga ile gelmiyor, boss eventinde spawnlanacak ---
	for (var i = 0; i < normalCount; i++) {
		var angle = Math.random() * Math.PI * 2;
		var x = player.x + Math.cos(angle) * spawnRadius;
		var y = player.y + Math.sin(angle) * spawnRadius;
		spawnList.push({
			type: 'normalZombie',
			x: x,
			y: y
		});
	}
	// --- HealerZombie spawn ---
	for (var i = 0; i < rangedCount; i++) {
		var angle = Math.random() * Math.PI * 2;
		var x = player.x + Math.cos(angle) * spawnRadius;
		var y = player.y + Math.sin(angle) * spawnRadius;
		spawnList.push({
			type: 'rangedZombie',
			x: x,
			y: y
		});
	}
	for (var i = 0; i < fastCount; i++) {
		var angle = Math.random() * Math.PI * 2;
		var x = player.x + Math.cos(angle) * spawnRadius;
		var y = player.y + Math.sin(angle) * spawnRadius;
		spawnList.push({
			type: 'fastZombie',
			x: x,
			y: y
		});
	}
	for (var i = 0; i < tankCount; i++) {
		var angle = Math.random() * Math.PI * 2;
		var x = player.x + Math.cos(angle) * spawnRadius;
		var y = player.y + Math.sin(angle) * spawnRadius;
		spawnList.push({
			type: 'tankZombie',
			x: x,
			y: y
		});
	}
	for (var i = 0; i < bossCount; i++) {
		var angle = Math.random() * Math.PI * 2;
		var x = player.x + Math.cos(angle) * spawnRadius;
		var y = player.y + Math.sin(angle) * spawnRadius;
		spawnList.push({
			type: 'bossZombie',
			x: x,
			y: y
		});
	}
	// Shuffle spawnList for random order
	for (var i = spawnList.length - 1; i > 0; i--) {
		var j = Math.floor(Math.random() * (i + 1));
		var temp = spawnList[i];
		spawnList[i] = spawnList[j];
		spawnList[j] = temp;
	}
	// Staggered spawn with 0.1s (6 frames) delay between each
	var spawnIdx = 0;
	function spawnNextEnemy() {
		if (spawnIdx < spawnList.length) {
			var info = spawnList[spawnIdx];
			spawnEnemy(info.type, info.x, info.y);
			spawnIdx++;
			if (spawnIdx < spawnList.length) {
				LK.setTimeout(spawnNextEnemy, 100); // 0.1s = 100ms
			}
		}
	}
	spawnNextEnemy();
	// --- BossZombie Rebirth Event Logic ---
	// 1) Önce varsa eski timer’ı temizle
	if (bossRebirthEventTimer) {
		LK.clearInterval(bossRebirthEventTimer);
		bossRebirthEventTimer = null;
	}
	// 2) Bu dalgada bir boss var mı?
	var hasBoss = spawnList.some(function (s) {
		return s.type === 'bossZombie';
	});
	if (hasBoss) {
		// a) Rebirth spawn fonksiyonu (aynı kalacak)
		var spawnRebirthZombies = function spawnRebirthZombies() {
			if (skillSelectionActive) return;
			// Sahnedeki tüm boss’ları bul
			var bosses = enemies.filter(function (e) {
				return e.type === 'bossZombie';
			});
			if (!bosses.length) return;
			bosses.forEach(function (boss) {
				var spawnTypes = ['tankZombie', 'rangedZombie', 'rangedZombie', 'healerZombie'];
				spawnTypes.forEach(function (type) {
					var angle = Math.random() * Math.PI * 2;
					var radius = Math.random() * 300;
					var x = boss.x + Math.cos(angle) * radius;
					var y = boss.y + Math.sin(angle) * radius;
					// Görsel efekt
					var fx = new Container();
					var asset = fx.attachAsset('zombieRebirth', {
						anchorX: 0.5,
						anchorY: 0.5,
						alpha: 0
					});
					fx.x = x;
					fx.y = y;
					gameContainer.addChild(fx);
					tween(asset, {
						alpha: 1
					}, {
						duration: 4000,
						easing: tween.linear,
						onFinish: function onFinish() {
							if (fx.parent) fx.destroy();
							spawnEnemy(type, x, y);
						}
					});
				});
			});
		};
		// b) Boss sahneye çıkana kadar yarım saniyede bir kontrol et
		var lookForBossTimer = LK.setInterval(function () {
			var onStage = enemies.some(function (e) {
				return e.type === 'bossZombie';
			});
			if (onStage) {
				LK.clearInterval(lookForBossTimer);
				// hemen bir kere
				spawnRebirthZombies();
				// ardından her 16 saniyede bir
				bossRebirthEventTimer = LK.setInterval(function () {
					if (enemies.some(function (e) {
						return e.type === 'bossZombie';
					})) {
						spawnRebirthZombies();
					} else {
						LK.clearInterval(bossRebirthEventTimer);
						bossRebirthEventTimer = null;
					}
				}, 16000);
			}
		}, 500);
	}
}
function dropExpOrb(x, y) {
	var orb = new ExpOrb();
	orb.x = x;
	orb.y = y;
	// orb.value is always 1 in ExpOrb class
	expOrbs.push(orb);
	gameContainer.addChild(orb);
}
/* =============================================================== */ 
/*  NINE-WEAPON FIRE / PROJECTILES                                 */
/* =============================================================== */ 
function nearestEnemy() {
	var best = null,
		bestD = 1e9;
	for (var i = 0; i < enemies.length; i++) {
		var d = distSq(player, enemies[i]);
		if (d < bestD) {
			best = enemies[i];
			bestD = d;
		}
	}
	return best;
}
function damageEnemy(e, dmg, attacker) {
	// attacker: optional, can be player or enemy
	// Play hit sound on every hit
	LK.getSound('hit').play();
	// Determine crit chance and crit type
	var critChance = 0.25; // default
	var critType = null; // null, "low", "high"
	var isPlayerAttack = false;
	if (attacker === undefined) {
		attacker = player;
	}
	if (attacker === player) {
		isPlayerAttack = true;
		critChance = player.critChance !== undefined ? player.critChance : 0.25;
	} else if (attacker && attacker.type === 'normal') {
		critChance = attacker.critChance !== undefined ? attacker.critChance : 0.25;
	}
	var critRoll = Math.random();
	var critValue = 1;
	if (critRoll < critChance) {
		// Crit! Now decide low or high
		if (Math.random() < 0.5) {
			critType = "low";
			critValue = 1.2;
		} else {
			critType = "high";
			critValue = 1.4;
		}
	}
	var finalDmg = dmg * critValue;
	// Apply debuffs if player has buffs
	if (player && player.buffs) {
		// (Grit Wound/Deep Wound+ logic removed)
		// Enemy Slow+
		if (player.buffs.enemySlow > 0) {
			e.slowBuff = player.buffs.enemySlow;
			e.slowBuffTime = gameTime;
		}
		// Enemy Stun+
		if (player.buffs.enemyStun > 0) {
			e.stunBuff = player.buffs.enemyStun;
			e.stunBuffTime = gameTime;
		}
		// Bleeding+ buff removed
	}
	// Hasar yazısı göster
	if (typeof finalDmg === "number") {
		var fillColor = 0xffffff;
		var strokeColor = 0x000000;
		if (isPlayerAttack) {
			if (critType === "low") {
				fillColor = 0xffe066; // sarı
			} else if (critType === "high") {
				fillColor = 0xff3333; // kırmızı
			} else {
				fillColor = 0xffffff; // beyaz
			}
		} else {
			// Enemy attack, use default
			fillColor = 0xff3333;
		}
		var dmgText = new Text2(finalDmg.toFixed(1), {
			size: 48,
			fill: fillColor,
			stroke: strokeColor,
			strokeThickness: 4
		});
		dmgText.anchor.set(0.5);
		dmgText.x = e.x;
		dmgText.y = e.y - (e.height ? e.height / 2 : 60);
		dmgText.alpha = 1;
		gameContainer.addChild(dmgText);
		// Yavaşça yukarı çıkıp kaybolsun
		tween(dmgText, {
			y: dmgText.y - 60,
			alpha: 0
		}, {
			duration: 500,
			easing: tween.linear,
			onFinish: function onFinish() {
				if (dmgText.parent) {
					dmgText.destroy();
				}
			}
		});
	}
	if (e.takeDamage(finalDmg)) {
		// Play death sound (if you have a death sound asset, e.g. 'death')
		if (LK.getSound('death')) {
			LK.getSound('death').play();
		}
		// Ölünce exp orb düşür:
		dropExpOrb(e.x, e.y);
		// Sonra düşmanı kaldır ve yok et:
		var idx = enemies.indexOf(e);
		enemies.splice(idx, 1);
		e.destroy();
	}
}
/* ---- sword (melee slash) ---- */
function swingSword(inst) {
	// Kılıç ateşlendiğinde sesi çal
	if (LK.getSound && LK.getSound('swordSoundEffect')) {
		LK.getSound('swordSoundEffect').play();
	}
	var sorted = enemies.slice().sort(function (a, b) {
		return distSq(player, a) - distSq(player, b);
	});
	if (sorted.length === 0) {
		return;
	}
	for (var n = 0; n < inst.amount; n++) {
		var idx = n < sorted.length ? n : 0;
		var target = sorted[idx];
		var dir = unitDir(player, target);
		var arc = gameContainer.addChild(new Container());
		arc.x = player.x;
		arc.y = player.y;
		arc.attachAsset('swordHit', {
			anchorX: 0,
			anchorY: 0.5,
			rotation: Math.atan2(dir.dy, dir.dx),
			scaleX: inst.rngMul,
			scaleY: inst.rngMul
		});
		arc.life = 10;
		arc.dmg = WEAPONS.sword.dmg * inst.dmgMul;
		arc.hitList = [];
		arc.update = function () {
			if (--this.life <= 0) {
				if (this.parent) {
					this.destroy();
				}
				return;
			}
			var maxRange = WEAPONS.sword.range * inst.rngMul;
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				// hem arc.intersects hem oyuncudan menzil kontrolü
				if (this.hitList.indexOf(e) === -1 && this.intersects(e) && isWithinRange(e, maxRange)) {
					this.hitList.push(e);
					damageEnemy(e, this.dmg);
				}
			}
		};
	}
}
/* ---- boomerang ---- */
function fireBoomerang(inst) {
	// Bumerang ateşlendiğinde sesi çal
	if (LK.getSound && LK.getSound('bumerangSoundEffect')) {
		LK.getSound('bumerangSoundEffect').play();
	}
	var target = nearestEnemy();
	if (!target) {
		return;
	}
	var dir = unitDir(player, target);
	var maxRange = WEAPONS.boomerang.range * inst.rngMul;
	for (var n = 0; n < inst.amount; n++) {
		var p = new Container();
		var boomerangAsset = p.attachAsset('boomerang', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: inst.rngMul,
			scaleY: inst.rngMul
		});
		p._rotationAngle = 0;
		p._boomerangAsset = boomerangAsset;
		p.x = player.x;
		p.y = player.y;
		p._startX = player.x;
		p._startY = player.y;
		p._dirX = dir.dx;
		p._dirY = dir.dy;
		p._phase = "out"; // "out" = gidiş, "back" = dönüş
		p._distance = 0;
		p._maxRange = maxRange;
		p._speed = 18;
		p.dmg = WEAPONS.boomerang.dmg * inst.dmgMul;
		p.hitEnemies = [];
		p.update = function () {
			if (skillSelectionActive) {
				return;
			}
			// Boomerang assetini döndür
			if (this._boomerangAsset) {
				this._rotationAngle = (this._rotationAngle || 0) + 0.3;
				this._boomerangAsset.rotation = this._rotationAngle;
			}
			// Hareket
			if (this._phase === "out") {
				this.x += this._dirX * this._speed;
				this.y += this._dirY * this._speed;
				this._distance += this._speed;
				if (this._distance >= this._maxRange) {
					this._phase = "back";
				}
			} else if (this._phase === "back") {
				// Dönüşte, oyuncuya doğru hareket et
				var dx = player.x - this.x;
				var dy = player.y - this.y;
				var d = Math.sqrt(dx * dx + dy * dy);
				if (d < this._speed) {
					// Oyuncuya ulaştıysa yok et
					if (this.parent) {
						this.destroy();
					}
					var idx4 = bullets.indexOf(this);
					if (idx4 >= 0) {
						bullets.splice(idx4, 1);
					}
					return;
				}
				this.x += dx / d * this._speed;
				this.y += dy / d * this._speed;
			}
			// Düşmanlara çarpma kontrolü, menzil bakmaksızın, yok olmadan biçip geçmeli
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				if (this.hitEnemies.indexOf(e) === -1 && this.intersects(e)) {
					damageEnemy(e, this.dmg);
					this.hitEnemies.push(e);
				}
				// Eğer boomerang artık düşmanla temas etmiyorsa, tekrar vurabilmesi için hitEnemies'den çıkar
				if (this.hitEnemies.indexOf(e) !== -1 && !this.intersects(e)) {
					this.hitEnemies.splice(this.hitEnemies.indexOf(e), 1);
				}
			}
			// Kameranın (görünen alanın) dışına çıktıysa sil (fail-safe)
			var camMinX = camera.x;
			var camMaxX = camera.x + 2048;
			var camMinY = camera.y;
			var camMaxY = camera.y + 2732;
			if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
				if (this.parent) {
					this.destroy();
				}
				var idx = bullets.indexOf(this);
				if (idx >= 0) {
					bullets.splice(idx, 1);
				}
				return;
			}
		};
		bullets.push(p);
		gameContainer.addChild(p);
	}
}
/* ---- top (rebound ball) ---- */
function fireBall(inst) {
	var maxRange = WEAPONS.ball.range * (player.weapons && player.weapons.ball ? player.weapons.ball.rngMul : 1);
	var target = null;
	for (var i = 0; i < enemies.length; i++) {
		if (isWithinRange(enemies[i], maxRange)) {
			target = enemies[i];
			break;
		}
	}
	// Eğer menzilde hiç düşman yoksa top fırlatma
	if (!target) {
		return;
	}
	// Top ateşlendiğinde sesi çal (yalnızca gerçekten top fırlatılıyorsa)
	if (LK.getSound && LK.getSound('ballSoundEffect')) {
		LK.getSound('ballSoundEffect').play();
	}
	var dir = unitDir(player, target);
	for (var n = 0; n < inst.amount; n++) {
		var p = new Container();
		// Attach the 'ball' asset, scale by range multiplier
		var ballGraphics = p.attachAsset('ball', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: inst.rngMul,
			scaleY: inst.rngMul
		});
		p._rotationAngle = 0;
		p._ballAsset = ballGraphics;
		p.x = player.x;
		p.y = player.y;
		p.dirX = dir.dx;
		p.dirY = dir.dy;
		p.damage = WEAPONS.ball.dmg * inst.dmgMul;
		p.speed = 14;
		p.bounced = false;
		p.hitEnemies = [];
		p.update = function () {
			// Seviye seçim ekranı açıkken hiçbir şey yapma
			if (skillSelectionActive) {
				return;
			}
			// Hareket
			this.x += this.dirX * this.speed;
			this.y += this.dirY * this.speed;
			// Rotate ball asset
			if (this._ballAsset) {
				this._rotationAngle = (this._rotationAngle || 0) + 0.3;
				this._ballAsset.rotation = this._rotationAngle;
			}
			// Kamera (görünen alan) sınırlarını belirle
			var camMinX = camera.x;
			var camMaxX = camera.x + 2048;
			var camMinY = camera.y;
			var camMaxY = camera.y + 2732;
			// Kameranın dışına çıktıysa yok et
			if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
				if (this.parent) {
					this.destroy();
				}
				var bi = bullets.indexOf(this);
				if (bi >= 0) {
					bullets.splice(bi, 1);
				}
				return;
			}
			// Düşmana çarpma kontrolü (menzilsiz, ekranda nerde olursa olsun vurmalı ve sekmeli)
			for (var i = enemies.length - 1; i >= 0; i--) {
				var e = enemies[i];
				if (this.hitEnemies.indexOf(e) === -1 && this.intersects(e)) {
					damageEnemy(e, this.damage);
					this.hitEnemies.push(e);
					// Sadece ilk çarpmada sekmeli
					if (!this.bounced) {
						this.dirX = -this.dirX;
						this.dirY = -this.dirY;
						this.bounced = true;
					}
				}
				// Eğer ball artık düşmanla temas etmiyorsa, tekrar vurabilmesi için hitEnemies'den çıkar
				if (this.hitEnemies.indexOf(e) !== -1 && !this.intersects(e)) {
					this.hitEnemies.splice(this.hitEnemies.indexOf(e), 1);
				}
			}
		};
		bullets.push(p);
		gameContainer.addChild(p);
	}
}
/* ---- rocket ---- */
function fireRocket(inst) {
	// Roket ateşlendiğinde sesi çal
	if (LK.getSound && LK.getSound('rocketSoundEffect')) {
		LK.getSound('rocketSoundEffect').play();
	}
	var target = nearestEnemy();
	if (!target) {
		return;
	}
	var dir = unitDir(player, target);
	// Bu silahın menzili:
	var maxRange = WEAPONS.rocket.range * inst.rngMul;
	for (var n = 0; n < inst.amount; n++) {
		var p = gameContainer.addChild(new Container());
		p.attachAsset('rocket', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: inst.rngMul,
			scaleY: inst.rngMul
		});
		p.x = player.x;
		p.y = player.y;
		p.speed = 10;
		p.dmg = WEAPONS.rocket.dmg * inst.dmgMul;
		// Track target enemy at fire time
		p._targetEnemy = target;
		p._exploded = false;
		p.update = function () {
			if (skillSelectionActive) {
				return;
			}
			// Defensive: if target enemy is dead, just fly straight
			var targetEnemy = this._targetEnemy;
			if (!this._exploded && targetEnemy && enemies.indexOf(targetEnemy) !== -1) {
				// Home in on target enemy's center
				var dx = targetEnemy.x - this.x;
				var dy = targetEnemy.y - this.y;
				var dist = Math.sqrt(dx * dx + dy * dy);
				if (dist > 0) {
					this.x += dx / dist * this.speed;
					this.y += dy / dist * this.speed;
				}
				// Check if reached center (use <= speed for precision)
				if (dist <= this.speed) {
					this.x = targetEnemy.x;
					this.y = targetEnemy.y;
					this._exploded = true;
					LK.getSound('rocketBoom').play();
					// a) Dairesel patlama efekti: rocketBoom asseti kullanılmalı
					var explosion = gameContainer.addChild(new Container());
					var gfx = LK.getAsset('rocketBoom', {
						anchorX: 0.5,
						anchorY: 0.5,
						// Restore original scale (no 2x)
						scaleX: inst.rngMul * (80 / 70),
						scaleY: inst.rngMul * (80 / 70),
						alpha: 0.6
					});
					explosion.addChild(gfx);
					explosion.x = this.x;
					explosion.y = this.y;
					explosion.life = 30;
					explosion.update = function () {
						if (--this.life <= 0) {
							this.destroy();
						} else {
							this.children[0].alpha = this.life / 30 * 0.6;
						}
					};
					// b) AoE hasar: sadece menzil içindekileri vur
					for (var k = enemies.length - 1; k >= 0; k--) {
						var e2 = enemies[k];
						// Restore original AoE radius (radius^2 = 16000)
						if (distSq(this, e2) < 16000) {
							// Rocket patlaması hasar versin
							damageEnemy(e2, this.dmg);
						}
					}
					// c) Bu roketi sil
					if (this.parent) {
						this.destroy();
					}
					var bi = bullets.indexOf(this);
					if (bi >= 0) {
						bullets.splice(bi, 1);
					}
					return;
				}
			} else if (!this._exploded) {
				// If target is gone, fly straight in last direction
				if (typeof this.dirX === "undefined" || typeof this.dirY === "undefined") {
					// Set direction to original target
					var origDir = unitDir({
						x: player.x,
						y: player.y
					}, {
						x: this.x,
						y: this.y
					});
					this.dirX = origDir.dx;
					this.dirY = origDir.dy;
				}
				this.x += this.dirX * this.speed;
				this.y += this.dirY * this.speed;
			}
			// 3) Kameranın (görünen alanın) dışına çıkarsa sil
			var camMinX = camera.x;
			var camMaxX = camera.x + 2048;
			var camMinY = camera.y;
			var camMaxY = camera.y + 2732;
			if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
				if (this.parent) {
					this.destroy();
				}
				var bi2 = bullets.indexOf(this);
				if (bi2 >= 0) {
					bullets.splice(bi2, 1);
				}
				return;
			}
		};
		bullets.push(p);
	}
}
/* ---- brick ---- */
function throwBrick(inst, angDeg) {
	// Tuğla ateşlendiğinde sesi çal
	if (LK.getSound && LK.getSound('brickSoundEffect')) {
		LK.getSound('brickSoundEffect').play();
	}
	var rad = angDeg * Math.PI / 180;
	var p = gameContainer.addChild(new Container());
	var brickAsset = p.attachAsset('brick', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: inst.rngMul,
		scaleY: inst.rngMul
	});
	p._rotationAngle = 0;
	p._brickAsset = brickAsset;
	p.x = player.x;
	p.y = player.y;
	// Brick should be thrown upwards at 75 degrees (not downwards)
	p.vx = Math.cos(rad) * 14;
	p.vy = -Math.abs(Math.sin(rad) * 14); // always upwards
	p.g = 0.3;
	p.dmg = WEAPONS.brick.dmg * inst.dmgMul;
	// Bu silahın menzili:
	var maxRange = WEAPONS.brick.range * inst.rngMul;
	p._hitEnemies = [];
	p.update = function () {
		if (skillSelectionActive) {
			return;
		}
		// 1) Yerçekimi ve hareket
		this.vy += this.g;
		this.x += this.vx;
		this.y += this.vy;
		// Rotate brick asset
		if (this._brickAsset) {
			this._rotationAngle = (this._rotationAngle || 0) + 0.3;
			this._brickAsset.rotation = this._rotationAngle;
		}
		// 2) Düşmana çarpma kontrolü, brick yok olmasın, her düşmana bir kez vurabilsin, menzil bakmaksızın ekrandan çıkana kadar vurmalı
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			if (this._hitEnemies.indexOf(e) === -1 && this.intersects(e)) {
				damageEnemy(e, this.dmg);
				this._hitEnemies.push(e);
			}
			// Eğer brick artık düşmanla temas etmiyorsa, tekrar vurabilmesi için _hitEnemies'den çıkar
			if (this._hitEnemies.indexOf(e) !== -1 && !this.intersects(e)) {
				this._hitEnemies.splice(this._hitEnemies.indexOf(e), 1);
			}
		}
		// 3) Kameranın (görünen alanın) dışına çıkarsa yok et
		var camMinX = camera.x;
		var camMaxX = camera.x + 2048;
		var camMinY = camera.y;
		var camMaxY = camera.y + 2732;
		if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
			if (this.parent) {
				this.destroy();
			}
			return;
		}
	};
}
/* ---- lightning ---- */
function castLightning(inst) {
	// Yıldırım ateşlendiğinde sesi çal
	if (LK.getSound && LK.getSound('lightningSoundEffect')) {
		LK.getSound('lightningSoundEffect').play();
	}
	// 1) Menzildeki düşmanları filtrele
	var maxRange = WEAPONS.lightning.range * inst.rngMul;
	var candidates = enemies.filter(function (e) {
		var dx = e.x - player.x;
		var dy = e.y - player.y;
		return dx * dx + dy * dy <= maxRange * maxRange;
	});
	if (candidates.length === 0) {
		return;
	}
	// 2) Rastgele birini seç
	var victim = candidates[Math.floor(Math.random() * candidates.length)];
	// 3) Efekti ekle
	var l = gameContainer.addChild(new Container());
	l.attachAsset('lightning', {
		anchorX: 0.5,
		anchorY: 1,
		scaleX: inst.rngMul,
		scaleY: inst.rngMul
	});
	l.x = victim.x;
	l.y = victim.y;
	l.life = 15;
	l.update = function () {
		if (skillSelectionActive) {
			return;
		}
		if (--this.life === 14) {
			damageEnemy(victim, WEAPONS.lightning.dmg * inst.dmgMul);
		}
		if (this.life <= 0) {
			if (this.parent) {
				this.destroy();
			}
		}
	};
}
/* ---- aura ---- */
var auraField = null;
function ensureAura(inst) {
	// 1) Sadece ilk defa oluşturulacak:
	if (!auraField) {
		auraField = player.addChild(new Container());
		auraField.attachAsset('auraField', {
			anchorX: 0.5,
			anchorY: 0.5,
			alpha: 0.3,
			scaleX: inst.rngMul,
			scaleY: inst.rngMul
		});
		// Oyuncunun tam ortası (yerel koordinat):
		auraField.x = 0;
		auraField.y = 0;
	}
	// Her frame aura görselini güncelle (range buff alınırsa anında büyüsün/küçülsün)
	if (auraField && auraField.children && auraField.children.length > 0) {
		auraField.children[0].scaleX = inst.rngMul;
		auraField.children[0].scaleY = inst.rngMul;
		// Rotate aura asset
		if (typeof auraField._rotationAngle === "undefined") {
			auraField._rotationAngle = 0;
		}
		auraField._rotationAngle += 0.3; // 10 kat daha hızlı döndür
		auraField.children[0].rotation = auraField._rotationAngle;
	}
	// 2) Hasar uygulama kısmı (oyuncudan r uzaklıktaysa vur):
	var r = WEAPONS.aura.range * inst.rngMul;
	for (var i = enemies.length - 1; i >= 0; i--) {
		var e = enemies[i];
		var dx = e.x - player.x;
		var dy = e.y - player.y;
		if (dx * dx + dy * dy < r * r) {
			damageEnemy(e, WEAPONS.aura.dmg * inst.dmgMul);
		}
	}
}
/* ---- molotov ---- */
function throwMolotov(inst) {
	// Molotov ateşlendiğinde sesi çal
	if (LK.getSound && LK.getSound('molotovSoundEffect')) {
		LK.getSound('molotovSoundEffect').play();
	}
	// Find nearest enemy
	var target = nearestEnemy();
	if (!target) {
		return;
	}
	var dir = unitDir(player, target);
	var p = gameContainer.addChild(new Container());
	var molotovAsset = p.attachAsset('molotov', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: inst.rngMul,
		scaleY: inst.rngMul
	});
	p._rotationAngle = 0;
	p._molotovAsset = molotovAsset;
	p.x = player.x;
	p.y = player.y;
	p.dirX = dir.dx;
	p.dirY = dir.dy;
	p.speed = 16;
	p.life = 120; // Give enough life to reach enemy
	p._targetEnemy = target;
	p.update = function () {
		if (skillSelectionActive) {
			return;
		}
		this.x += this.dirX * this.speed;
		this.y += this.dirY * this.speed;
		// Rotate molotov asset
		if (this._molotovAsset) {
			this._rotationAngle = (this._rotationAngle || 0) + 0.3;
			this._molotovAsset.rotation = this._rotationAngle;
		}
		// Check for collision with target enemy
		if (this._targetEnemy && this.intersects(this._targetEnemy)) {
			// Explode at enemy position
			spawnFlame(this._targetEnemy.x, this._targetEnemy.y, inst);
			if (this.parent) {
				this.destroy();
			}
			return;
		}
		// If life runs out, just destroy (fail-safe)
		if (--this.life <= 0) {
			if (this.parent) {
				this.destroy();
			}
		}
	};
	bullets.push(p);
}
/* ---- molotov flame ---- */
function spawnFlame(x, y, inst) {
	// Molotov patladığında sesi çal (sadece bir kere, flame yaratılırken)
	if (LK.getSound && LK.getSound('molotovBoom')) {
		LK.getSound('molotovBoom').play();
	}
	// 1) Alev container’ını oluşturup ekrana ekliyoruz:
	var f = gameContainer.addChild(new Container());
	f.attachAsset('molotovFlame', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.4,
		scaleX: inst.rngMul,
		scaleY: inst.rngMul
	});
	f.x = x;
	f.y = y;
	// 2) “Kaçıncı frame’deyiz?” ve “her düşmana kaç kez vuruldu?” bilgisini tutacak:
	f._flameTick = 0; // Şu anda kaçıncı güncellemede olduğumuz
	f._hitInfo = {}; // { [enemyId]: { enteredFrame, tickCount } }
	// 3) Alev ömrü: 61 frame (≈1 saniye + 1 frame). Böylece 0–60. frame’lerde
	//    update() çalışır; 60 frame sonundaki üçüncü hasar da tetiklenir.
	f.life = 61;
	// 4)  Her vuruş için 3 hasar verecek (WEAPONS.molotov.dmg = 9 ise /3 → 3).
	//     inst.dmgMul varsa onunla da çarpalım.
	var singleHit = WEAPONS.molotov.dmg / 3 * inst.dmgMul;
	// 5) Alevin etki yarıçapı (radius) ve bunun karesini hesaplıyoruz:
	var radius = 70 * inst.rngMul;
	var radiusSq = radius * radius;
	f.update = function () {
		if (skillSelectionActive) {
			return; // Kart seçimi açıkken hiçbir şey yapma
		}
		this._flameTick++;
		// 6) Her düşman için: eğer bu frame’de alev yarıçapı içindeyse,
		//    “enteredFrame” atamasını yap, ardından 0/30/60 frame kontrollerini yap.
		for (var i = enemies.length - 1; i >= 0; i--) {
			var e = enemies[i];
			var dx = e.x - f.x;
			var dy = e.y - f.y;
			var distSq = dx * dx + dy * dy;
			if (distSq <= radiusSq) {
				// Düşman ilk kez alevin içine giriyorsa benzersiz bir ID atayalım:
				if (typeof e._molotovFlameId === "undefined") {
					e._molotovFlameId = Math.random().toString(36).substr(2, 9) + "_" + Math.floor(Math.random() * 1e6);
				}
				var id = e._molotovFlameId;
				// Eğer bu ID henüz kayıtlı değilse, “enteredFrame” ve “tickCount=0” set et:
				if (!this._hitInfo[id]) {
					this._hitInfo[id] = {
						enteredFrame: this._flameTick,
						tickCount: 0
					};
					// İlk temas anında bir kere **3 hasar** vur:
					damageEnemy(e, singleHit);
					this._hitInfo[id].tickCount = 1;
				}
				var info = this._hitInfo[id];
				var framesSinceEnter = this._flameTick - info.enteredFrame;
				// 7) Eğer bir kez vuruldu (tickCount == 1) ve 30 frame geçtiyse → ikinci 3 hasar:
				if (info.tickCount === 1 && framesSinceEnter >= 30) {
					damageEnemy(e, singleHit);
					info.tickCount = 2;
				}
				// 8) Eğer iki kez vuruldu (tickCount == 2) ve 60 frame geçtiyse → üçüncü 3 hasar:
				else if (info.tickCount === 2 && framesSinceEnter >= 60) {
					damageEnemy(e, singleHit);
					info.tickCount = 3;
				}
				// 9) Üç vuruş da tamamlandıysa bu düşmanla ilgili kaydı silebiliriz:
				if (info.tickCount >= 3) {
					delete this._hitInfo[id];
				}
			}
			// “else” bloğunda hiç silme veya sıfırlama yapmıyoruz,
			// böylece düşman kısa süre sonra çıksa bile sayaç devam eder.
		}
		// 10) Ömür bitti mi? Bittiğinde kendini yok et:
		this.life--;
		if (this.life <= 0) {
			if (this.parent) {
				this.destroy();
			}
			return;
		}
		// 11) Fail-safe: Alev ekran dışına çıktıysa sil:
		var camMinX = camera.x;
		var camMaxX = camera.x + 2048;
		var camMinY = camera.y;
		var camMaxY = camera.y + 2732;
		if (this.x < camMinX || this.x > camMaxX || this.y < camMinY || this.y > camMaxY) {
			if (this.parent) {
				this.destroy();
			}
			return;
		}
	};
}
/* ---- shuriken ring ---- */
var shurikenObjs = [];
// Shuriken now always visible, orbits player, speed = attack speed, range+ increases both orbit radius and asset size
var _maintainShurikens = function maintainShurikens(inst) {
	// Always create shurikens if not present or if amount changed
	if (shurikenObjs.length !== inst.amount) {
		shurikenObjs.forEach(function (s) {
			if (s.parent) {
				s.destroy();
			}
		});
		shurikenObjs = [];
		var n = inst.amount;
		var r = WEAPONS.shuriken.range * inst.rngMul;
		var sizeMul = inst.rngMul; // Range+ increases both orbit and asset size
		for (var i = 0; i < n; i++) {
			var s = gameContainer.addChild(new Container());
			s.attachAsset('shuriken', {
				anchorX: 0.5,
				anchorY: 0.5,
				scaleX: sizeMul,
				scaleY: sizeMul
			});
			s.angle = i / n * Math.PI * 2;
			s.hitEnemies = [];
			s.update = function () {
				if (skillSelectionActive) {
					return;
				}
				var curR = WEAPONS.shuriken.range * inst.rngMul;
				var curSizeMul = inst.rngMul;
				// Orbit around player, speed = attack speed (cd)
				var baseCd = WEAPONS.shuriken.cd;
				var curCd = inst.cd || baseCd;
				// Higher attack speed = lower cd = faster orbit
				var speed = 0.15 * (baseCd / curCd);
				this.angle += speed;
				this.x = player.x + Math.cos(this.angle) * curR;
				this.y = player.y + Math.sin(this.angle) * curR;
				// Update asset size if range+ changes
				if (this.children && this.children.length > 0) {
					this.children[0].scaleX = curSizeMul;
					this.children[0].scaleY = curSizeMul;
					if (typeof this._rotationAngle === "undefined") {
						this._rotationAngle = 0;
					}
					this._rotationAngle += 0.4;
					this.children[0].rotation = this._rotationAngle;
				}
				// Damage enemies if intersecting and within range
				for (var k = enemies.length - 1; k >= 0; k--) {
					var e = enemies[k];
					if (this.hitEnemies.indexOf(e) === -1 && this.intersects(e) && isWithinRange(e, curR)) {
						damageEnemy(e, WEAPONS.shuriken.dmg * inst.dmgMul);
						this.hitEnemies.push(e);
					}
					// Reset hitEnemies if not intersecting anymore (so shuriken can hit again on next contact)
					if (this.hitEnemies.indexOf(e) !== -1 && (!this.intersects(e) || !isWithinRange(e, curR))) {
						this.hitEnemies.splice(this.hitEnemies.indexOf(e), 1);
					}
				}
			};
			shurikenObjs.push(s);
		}
	}
	// Always update shuriken positions even if already created
	for (var i = 0; i < shurikenObjs.length; i++) {
		if (typeof shurikenObjs[i].update === "function") {
			shurikenObjs[i].update();
		}
	}
};
/* ---- ana fireWeapon anahtarı ---- */
function fireWeapon(key, inst, meta) {
	// Block all weapon/projectile firing and aura/shuriken during wave break
	if (window._waveBreakActive) {
		return;
	}
	switch (meta.type) {
		case 'melee':
			swingSword(inst);
			break;
		case 'boomerang':
			{
				// Only fire boomerang if there is an enemy in range
				var maxRange = WEAPONS.boomerang.range * inst.rngMul;
				var hasEnemy = false;
				for (var i = 0; i < enemies.length; i++) {
					var dx = enemies[i].x - player.x;
					var dy = enemies[i].y - player.y;
					if (dx * dx + dy * dy <= maxRange * maxRange) {
						hasEnemy = true;
						break;
					}
				}
				if (hasEnemy && player.weapons && player.weapons.boomerang) {
					fireBoomerang(inst);
				}
			}
			break;
		case 'ball':
			{
				// fireBall already checks for enemy in range and does not play sound if not
				fireBall(inst);
			}
			break;
		case 'rocket':
			{
				// Only fire rocket if there is an enemy in range
				var maxRange = WEAPONS.rocket.range * inst.rngMul;
				var hasEnemy = false;
				for (var i = 0; i < enemies.length; i++) {
					var dx = enemies[i].x - player.x;
					var dy = enemies[i].y - player.y;
					if (dx * dx + dy * dy <= maxRange * maxRange) {
						hasEnemy = true;
						break;
					}
				}
				if (hasEnemy) {
					fireRocket(inst);
				}
			}
			break;
		case 'brick':
			{
				// Only fire brick if there is an enemy in range
				var maxRange = WEAPONS.brick.range * inst.rngMul;
				var hasEnemy = false;
				for (var i = 0; i < enemies.length; i++) {
					var dx = enemies[i].x - player.x;
					var dy = enemies[i].y - player.y;
					if (dx * dx + dy * dy <= maxRange * maxRange) {
						hasEnemy = true;
						break;
					}
				}
				if (hasEnemy) {
					// Brick en yakındaki düşman ekranın sağında mı solunda mı ona göre fırlatılmalı
					var nearest = nearestEnemy();
					var throwRight = true;
					if (nearest) {
						if (nearest.x < player.x) {
							throwRight = false;
						} else {
							throwRight = true;
						}
					} else {
						throwRight = true;
					}
					if (throwRight) {
						throwBrick(inst, 75);
						if (inst.upgrade > 0) {
							throwBrick(inst, 105);
						}
						if (inst.upgrade > 1) {
							throwBrick(inst, 45);
						}
						if (inst.upgrade > 2) {
							throwBrick(inst, 135);
						}
					} else {
						throwBrick(inst, 255);
						if (inst.upgrade > 0) {
							throwBrick(inst, 225);
						}
						if (inst.upgrade > 1) {
							throwBrick(inst, 285);
						}
						if (inst.upgrade > 2) {
							throwBrick(inst, 195);
						}
					}
				}
			}
			break;
		case 'lightning':
			{
				// Only fire lightning if there is an enemy in range
				var maxRange = WEAPONS.lightning.range * inst.rngMul;
				var hasEnemy = false;
				for (var i = 0; i < enemies.length; i++) {
					var dx = enemies[i].x - player.x;
					var dy = enemies[i].y - player.y;
					if (dx * dx + dy * dy <= maxRange * maxRange) {
						hasEnemy = true;
						break;
					}
				}
				if (hasEnemy) {
					for (var n = 0; n < inst.amount; n++) {
						castLightning(inst);
					}
				}
			}
			break;
		case 'aura':
			if (!window._waveBreakActive) {
				ensureAura(inst);
			}
			break;
		case 'molotov':
			{
				// Only fire molotov if there is an enemy in range
				var maxRange = WEAPONS.molotov.range * inst.rngMul;
				var hasEnemy = false;
				for (var i = 0; i < enemies.length; i++) {
					var dx = enemies[i].x - player.x;
					var dy = enemies[i].y - player.y;
					if (dx * dx + dy * dy <= maxRange * maxRange) {
						hasEnemy = true;
						break;
					}
				}
				if (hasEnemy) {
					for (var n = 0; n < inst.amount; n++) {
						throwMolotov(inst);
					}
				}
			}
			break;
		case 'shuriken':
			if (!window._waveBreakActive) {
				_maintainShurikens(inst);
			}
			break;
	}
}
function showSkillSelection() {
	skillSelectionActive = true;
	// 1) Yeni bir Overlay (seçim ekranı) oluşturuyoruz
	var ov = game.addChild(new Container());
	ov.x = 1024;
	ov.y = 1366;
	// Add title text for skill selection
	var titleTextStr = "";
	if (weaponSelectionActive) {
		// Weapon selection overlay (game start)
		if (currentLanguage === "tr") {
			titleTextStr = "Başlangıç Silahınızı Seçin";
		} else {
			titleTextStr = "Choose Your Starting Weapon";
		}
	} else {
		// Power-up selection overlay (level up)
		if (currentLanguage === "tr") {
			titleTextStr = "Güçlendirmenizi Seçin";
		} else {
			titleTextStr = "Choose Your Power-Up";
		}
	}
	var titleTxt = new Text2(titleTextStr, {
		size: currentLanguage === "tr" && titleTextStr === "Güçlendirmenizi Seç" ? 54 : 64,
		fill: 0xffffff,
		wordWrap: true,
		wordWrapWidth: 700
	});
	titleTxt.anchor.set(0.5, 0);
	titleTxt.y = -420;
	ov.addChild(titleTxt);
	var choices = [];
	// 2) Eğer oyuncu seviyesi 5'in katı ise (5,10,15,...)
	if (player.level % 5 === 0) {
		var ownedCount = Object.keys(player.weapons).length;
		//  2.a) Hâlâ < 6 silah sahibi ise: yeni silah açma seçenekleri
		if (ownedCount < 6) {
			// Kilidi açılmamış silahlar havuzunu al
			var pool = Object.keys(WEAPONS).filter(function (key) {
				return !player.weapons[key];
			});
			// Havuzdan rastgele 3 silah göster, her biri benzersiz
			while (choices.length < 3 && pool.length > 0) {
				var rnd = Math.floor(Math.random() * pool.length);
				choices.push(pool.splice(rnd, 1)[0]);
			}
		} else {
			//  2.b) Zaten 6 silah sahibi ise: önce silahların upgrade durumlarını kontrol et
			var upgradePool = [];
			Object.keys(player.weapons).forEach(function (key) {
				var inst = player.weapons[key];
				if (inst.upgrade < 3) {
					// Eğer bu silah hâlâ < 3 aşama güçlendirilmişse,
					// “bu silahın bir sonraki upgrade aşaması” havuza eklenir.
					upgradePool.push({
						w: key
					});
				}
			});
			if (upgradePool.length > 0) {
				//  2.b.i) En az bir silah yükseltmesi kalmış demektir:
				// Rastgele en fazla 3 tane “silah güçlendirme” seçeneği göster, her biri benzersiz
				while (choices.length < 3 && upgradePool.length > 0) {
					var rnd2 = Math.floor(Math.random() * upgradePool.length);
					choices.push({
						w: upgradePool[rnd2].w,
						type: "upgrade"
					});
					upgradePool.splice(rnd2, 1);
				}
			} else {
				//  2.b.ii) Tüm 6 silah zaten upgrade === 3 ise:
				// Bu aşamadan sonra artık sadece efsun kartı göster.
				// Her kart benzersiz olmalı (hem silah hem efsun kombinasyonu)
				var ownedKeys2 = Object.keys(player.weapons);
				var usedPairs = [];
				var attempts = 0;
				while (choices.length < 3 && attempts < 20) {
					var randomKey2 = ownedKeys2[Math.floor(Math.random() * ownedKeys2.length)];
					var enchList = WEAPONS[randomKey2].ench;
					var rnd3 = enchList[Math.floor(Math.random() * enchList.length)];
					var pairKey = randomKey2 + "|" + rnd3;
					if (usedPairs.indexOf(pairKey) === -1) {
						choices.push({
							w: randomKey2,
							e: rnd3
						});
						usedPairs.push(pairKey);
					}
					attempts++;
				}
			}
		}
	} else {
		// 3) Seviye 5'in katı değilse: doğrudan efsun kartları göster
		// Her kart benzersiz olmalı (hem silah hem efsun kombinasyonu)
		var ownedKeys = Object.keys(player.weapons);
		var usedPairs2 = [];
		var attempts2 = 0;
		while (choices.length < 3 && attempts2 < 20) {
			var randomKey = ownedKeys[Math.floor(Math.random() * ownedKeys.length)];
			var enchList = WEAPONS[randomKey].ench;
			var rnd4 = enchList[Math.floor(Math.random() * enchList.length)];
			var pairKey2 = randomKey + "|" + rnd4;
			if (usedPairs2.indexOf(pairKey2) === -1) {
				choices.push({
					w: randomKey,
					e: rnd4
				});
				usedPairs2.push(pairKey2);
			}
			attempts2++;
		}
	}
	// 4) choices dizisini “3 adet kart” olarak UI’da çizelim
	// --- BUFF havuzu ---
	// --- Buff/efsun/buff limit tracking ---
	if (!player.buffCounts) {
		player.buffCounts = {};
	}
	if (!player.efsunCounts) {
		player.efsunCounts = {};
	}
	// --- BUFF havuzu ---
	var buffPool = [{
		key: "damageReduction",
		label: "Damage Reduction+",
		desc: "Take 10% less damage per level"
	}, {
		key: "moveSpeed",
		label: "Movement Speed Increase+",
		desc: "Move 20% faster per level"
	}, {
		key: "hpRegen",
		label: "HP Regeneration+",
		desc: "Regenerate 1% max HP every 5s per level"
	}, {
		key: "damageReflection",
		label: "Damage Reflection+",
		desc: "Reflect 5% damage per level"
	}, {
		// Grit Wound+ removed
		key: "enemySlow",
		label: "Enemy Slow+",
		desc: "Slow enemies by 10% per level"
	}, {
		key: "enemyStun",
		label: "Enemy Stun+",
		desc: "Stun enemies for 0.1s per level"
		// }, {
		// key: "bleeding",
		// label: "Bleeding+",
		// desc: "Bleed: 4s, 0.5s tick, 5% max HP per tick per level"
	}, {
		key: "critChance",
		label: "Critical Hit Chance+",
		desc: "Increase critical hit chance by 15% per level"
	}, {
		key: "maxHpPlus",
		label: "Maximum HP+",
		desc: "Increase max HP by 25 per level"
	}, {
		key: "magnetPlus",
		label: "Magnet+",
		desc: "Nearby EXP orbs (150 radius, +150 per level) are quickly pulled to you."
	}];
	// Remove buffs that have been taken 5 times
	buffPool = buffPool.filter(function (buff) {
		var k = buff.key;
		return (player.buffCounts[k] || 0) < 5;
	});
	// Remove efsun options that have been taken 5 times
	choices = choices.filter(function (c) {
		if (_typeof(c) === "object" && c.e) {
			var key = c.w + "|" + c.e;
			return (player.efsunCounts[key] || 0) < 5;
		}
		return true;
	});
	// Remove upgrade options that have been taken 5 times (for upgrades, max 3, but defensive)
	choices = choices.filter(function (c) {
		if (_typeof(c) === "object" && c.type === "upgrade") {
			var wkey = c.w;
			return player.weapons[wkey] && player.weapons[wkey].upgrade < 3;
		}
		return true;
	});
	// Remove weapon unlocks if already owned (defensive, should not happen)
	choices = choices.filter(function (c) {
		if (typeof c === "string") {
			return !player.weapons[c];
		}
		return true;
	});
	// Always show 4 options if possible, otherwise 3, 2, or 1 if pool is exhausted
	var availableBuffs = buffPool.slice();
	var availableChoices = choices.slice(0); // copy
	// Remove duplicate buffs/efsun/upgrades in availableChoices
	var seenBuffs = {};
	var seenEfsuns = {};
	var seenUpgrades = {};
	availableChoices = availableChoices.filter(function (c) {
		if (c && c.type === "buff") {
			if (seenBuffs[c.buff.key]) {
				return false;
			}
			seenBuffs[c.buff.key] = true;
		}
		if (c && c.e) {
			var key = c.w + "|" + c.e;
			if (seenEfsuns[key]) {
				return false;
			}
			seenEfsuns[key] = true;
		}
		if (c && c.type === "upgrade") {
			if (seenUpgrades[c.w]) {
				return false;
			}
			seenUpgrades[c.w] = true;
		}
		return true;
	});
	// Now, fill up to 4 options: prefer efsun/upgrade/unlock, but always add a buff if possible
	var finalChoices = [];
	for (var i = 0; i < availableChoices.length && finalChoices.length < 4; i++) {
		finalChoices.push(availableChoices[i]);
	}
	while (finalChoices.length < 4 && availableBuffs.length > 0) {
		// Pick a random buff not already in finalChoices
		var buffIdx = Math.floor(Math.random() * availableBuffs.length);
		var buffChoice = availableBuffs.splice(buffIdx, 1)[0];
		if (!finalChoices.some(function (c) {
			return c && c.type === "buff" && c.buff && c.buff.key === buffChoice.key;
		})) {
			finalChoices.push({
				type: "buff",
				buff: buffChoice
			});
		}
	}
	// If after all, less than 4, that's all we can show
	choices = finalChoices;
	// If there are no more available cards (all buffs/efsun/upgrades maxed), on next level up, heal player to full
	if (choices.length === 0) {
		// Show a single card that says "Azami canın %100'ü kadar yenilendi!" or "Fully healed!" depending on language
		var healLabel = currentLanguage === "tr" ? "Azami canın %100'ü kadar yenilendi!" : "Fully healed!";
		var card = ov.addChild(new Container());
		card.attachAsset('skillCard', {
			anchorX: 0.5,
			anchorY: 0.5,
			tint: 0x00ff00
		});
		card.x = 0;
		card.y = 0;
		var txt = new Text2(healLabel, {
			size: 40,
			fill: 0xffffff
		});
		txt.anchor.set(0.5);
		card.addChild(txt);
		card.down = function () {
			player.hp = player.maxHp;
			ov.destroy();
			skillSelectionActive = false;
			levelText.setText('Level ' + player.level);
		};
		return;
	}
	choices.forEach(function (c, idx) {
		var card = ov.addChild(new Container());
		// Tüm kartlar aynı renk (standart skillCard, tint yok)
		card.attachAsset('skillCard', {
			anchorX: 0.5,
			anchorY: 0.5
		});
		// Kartlar arası mesafeyi azalt (ör: 440px), dikey mesafeyi azalt (ör: 0)
		card.x = (idx - 1.5) * 440;
		card.y = 0;
		var label,
			fn,
			desc = "";
		if (typeof c === "string") {
			// c, yeni kilidi açılacak silahın anahtarı (ör. "boomerang")
			var key = c;
			var own = !!player.weapons[key];
			if (!own) {
				// Hâlâ envanterde yoksa “Unlock <silah adı>”
				label = t("unlock") + " " + key.charAt(0).toUpperCase() + key.slice(1);
				fn = function fn() {
					addWeapon(key);
				};
			} else if (player.weapons[key].upgrade < 3) {
				// Silah zaten varsa ve upgrade < 3 ise:
				label = WEAPONS[key].up && WEAPONS[key].up[player.weapons[key].upgrade] ? WEAPONS[key].up[player.weapons[key].upgrade] : t("upgrade");
				fn = function fn() {
					player.weapons[key].upgrade++;
					player.weapons[key].amount++;
				};
			} else {
				// Eğer upgrade === 3’e ulaşmışsa:
				label = t("noOption");
				fn = function fn() {};
			}
		} else if (c.type === "upgrade") {
			// c = { w: "sword", type:"upgrade" }
			var wkey = c.w;
			label = WEAPONS[wkey].up && WEAPONS[wkey].up[player.weapons[wkey].upgrade] ? WEAPONS[wkey].up[player.weapons[wkey].upgrade] : t("upgrade");
			fn = function fn() {
				player.weapons[wkey].upgrade++;
				player.weapons[wkey].amount++;
			};
		} else if (c.type === "buff") {
			label = t("buffs")[c.buff.key] || c.buff.label;
			desc = t("buffDescs")[c.buff.key] || c.buff.desc;
			fn = function fn() {
				// Buff mantığı
				var k = c.buff.key;
				if (!player.buffCounts[k]) {
					player.buffCounts[k] = 0;
				}
				if (player.buffCounts[k] >= 5) {
					return;
				} // Defensive: do not allow more than 5
				switch (k) {
					case "damageReduction":
						player.buffs.damageReduction += 10;
						break;
					case "moveSpeed":
						player.buffs.moveSpeed += 20;
						break;
					case "hpRegen":
						player.buffs.hpRegen += 1;
						break;
					case "damageReflection":
						player.buffs.damageReflection += 5;
						break;
					// case "gritWound": (removed)
					case "enemySlow":
						player.buffs.enemySlow += 10;
						break;
					case "enemyStun":
						player.buffs.enemyStun += 0.1;
						break;
					// case "bleeding": (removed)
					case "critChance":
						player.buffs.critChance += 15;
						player.critChance = 0.25 + player.buffs.critChance / 100;
						if (player.critChance > 1) {
							player.critChance = 1;
						}
						break;
					case "maxHpPlus":
						player.maxHp += 25;
						break;
					case "magnetPlus":
						// Magnet+ buff: increase magnet+ level, only affects EXP orb attraction
						if (!player.buffs.magnetPlus) {
							player.buffs.magnetPlus = 1;
						} else {
							player.buffs.magnetPlus++;
						}
						// No longer affects spawn rates of pickups
						break;
				}
				player.buffCounts[k]++;
			};
		} else {
			// c = { w: "<silahAnahtarı>", e: "<SilahName> Damage+" veya "<SilahName> Attack Speed+" vb. }
			var w2 = c.w;
			var efsun = c.e;
			label = efsun;
			// Efsun açıklaması
			if (efsun.endsWith(" Damage+")) {
				desc = t("desc_damage");
			} else if (efsun.endsWith(" Attack Speed+")) {
				desc = t("desc_atkspd");
			} else if (efsun.endsWith(" Range+")) {
				desc = t("desc_range");
			} else {
				desc = "";
			}
			fn = function fn() {
				var key = w2 + "|" + efsun;
				if (!player.efsunCounts[key]) {
					player.efsunCounts[key] = 0;
				}
				if (player.efsunCounts[key] >= 5) {
					return;
				} // Defensive: do not allow more than 5
				var inst = player.weapons[w2];
				// Efsun metni "<SilahName> Damage+" ile bitiyorsa hasar çarpanını %20 artır (artık sabit):
				if (efsun.endsWith(" Damage+")) {
					if (!inst._baseDmgMul) {
						inst._baseDmgMul = 1;
					}
					if (!inst.dmgMul) {
						inst.dmgMul = 1;
					}
					inst.dmgMul = inst._baseDmgMul + 0.2 * (player.efsunCounts[key] + 1);
				}
				// Efsun metni "<SilahName> Attack Speed+" ile bitiyorsa cd süresini %20 azalt (artık sabit):
				if (efsun.endsWith(" Attack Speed+")) {
					var meta = WEAPONS[w2];
					if (meta && typeof meta.cd === "number") {
						if (!inst._baseCd) {
							inst._baseCd = meta.cd;
						}
						if (!inst._atkSpdMul) {
							inst._atkSpdMul = 1;
						}
						inst._atkSpdMul = 1 - 0.1 * (player.efsunCounts[key] + 1);
						if (inst._atkSpdMul < 0.1) {
							inst._atkSpdMul = 0.1;
						} // min %90 hızlanma sınırı
						inst.cd = inst._baseCd * inst._atkSpdMul;
					} else {
						inst.cd = inst.cd || meta.cd || 1;
						inst.cd = inst.cd * (1 - 0.1 * (player.efsunCounts[key] + 1));
						if (inst.cd < 1) {
							inst.cd = 1;
						}
					}
					// cdCnt’yi de yeni cd’ye çekiyoruz
					if (typeof inst.cdCnt === "number") {
						if (inst.cdCnt > inst.cd) {
							inst.cdCnt = inst.cd;
						}
					} else {
						inst.cdCnt = Math.floor(inst.cd);
					}
				}
				// Efsun metni "<SilahName> Range+" ile bitiyorsa hem menzil hem boyut çarpanını %20 artır (artık sabit):
				if (efsun.endsWith(" Range+")) {
					if (!inst._baseRngMul) {
						inst._baseRngMul = 1;
					}
					if (!inst._baseSizeMul) {
						inst._baseSizeMul = 1;
					}
					inst.rngMul = inst._baseRngMul + 0.1 * (player.efsunCounts[key] + 1);
					inst.sizeMul = inst._baseSizeMul + 0.1 * (player.efsunCounts[key] + 1);
				}
				// "Size+" efsunu artık yok, hiçbir şey yapma
				player.efsunCounts[key]++;
			};
		}
		// --- Weapon and efsun name localization ---
		function localizeWeaponName(key) {
			// Turkish weapon names
			var trNames = {
				sword: "Kılıç",
				boomerang: "Bumerang",
				ball: "Top",
				rocket: "Roket",
				brick: "Tuğla",
				lightning: "Yıldırım",
				aura: "Aura",
				molotov: "Molotof",
				shuriken: "Ninja Yıldızı"
			};
			if (currentLanguage === "tr" && trNames[key]) {
				return trNames[key];
			}
			// Default: Capitalize first letter
			return key.charAt(0).toUpperCase() + key.slice(1);
		}
		function localizeEfsunName(efsun, wkey) {
			// efsun: e.g. "Boomerang Damage+", "Boomerang Range+", "Boomerang Attack Speed+"
			// wkey: e.g. "boomerang"
			var trNames = {
				sword: "Kılıç",
				boomerang: "Bumerang",
				ball: "Top",
				rocket: "Roket",
				brick: "Tuğla",
				lightning: "Yıldırım",
				aura: "Aura",
				molotov: "Molotof",
				shuriken: "Ninja Yıldızı"
			};
			if (currentLanguage === "tr") {
				var base = wkey && trNames[wkey] ? trNames[wkey] : wkey.charAt(0).toUpperCase() + wkey.slice(1);
				if (efsun.endsWith(" Damage+")) {
					return base + " Hasar+";
				}
				if (efsun.endsWith(" Range+")) {
					return base + " Menzil+";
				}
				if (efsun.endsWith(" Attack Speed+")) {
					return base + " Saldırı Hızı+";
				}
				// fallback
				return efsun;
			}
			return efsun;
		}
		var txtLabel = label;
		if (typeof c === "string") {
			// Weapon selection overlay: localize weapon name
			txtLabel = localizeWeaponName(c);
		} else if (c && c.type === "upgrade") {
			// Upgrade overlay: localize weapon name in upgrade label
			var wkey = c.w;
			if (WEAPONS[wkey] && WEAPONS[wkey].up && player.weapons[wkey]) {
				var upLabel = WEAPONS[wkey].up[player.weapons[wkey].upgrade];
				if (currentLanguage === "tr") {
					// Try to localize upgrade label for Turkish
					// For +1, +2, +3 upgrades, just append to Turkish weapon name
					if (upLabel && upLabel.match(/^\w+ \+(\d)$/)) {
						var base = localizeWeaponName(wkey);
						var num = upLabel.match(/\+(\d)/)[1];
						txtLabel = base + " +" + num;
					} else {
						txtLabel = upLabel;
					}
				} else {
					txtLabel = upLabel;
				}
			}
		} else if (c && !c.type && c.e && c.w) {
			// Efsun card: localize efsun name
			txtLabel = localizeEfsunName(c.e, c.w);
		}
		var txt = new Text2(txtLabel, {
			size: 32,
			fill: 0xffffff,
			wordWrap: true,
			wordWrapWidth: 340,
			align: "center"
		});
		txt.anchor.set(0.5);
		card.addChild(txt);
		if (desc) {
			// Card width is 400, so max text width should be less (e.g. 340)
			var descTxt = new Text2(desc, {
				size: 28,
				fill: 0xcccccc,
				wordWrap: true,
				wordWrapWidth: 340,
				align: "center"
			});
			descTxt.anchor.set(0.5, 0);
			descTxt.y = 60;
			card.addChild(descTxt);
		}
		card.down = function () {
			fn();
			ov.destroy();
			skillSelectionActive = false;
			levelText.setText('Level ' + player.level);
		};
	});
}
// Input handling
// Joystick ve knob ekranın tam ortasında başlasın (refA kaldırıldı, joystick'in kendi merkezi kullanılacak)
game.down = function (x, y, obj) {
	// Menü / death ekranı kontrolleri aynı kaldıysa atlayın...
	if (gameState !== GAME_STATE.PLAYING || skillSelectionActive) {
		return;
	}
	// 1) Joystick’in pozisyonu bu manuel girildi:
	var centerX = 1024;
	var centerY = 2290;
	// 2) Dokunma ile poz farkı → joystick sapması
	var dx = x - centerX;
	var dy = y - centerY;
	// 3) Joystick’i aktif edip knob’u çekin
	joystick.active = true;
	joystick.setKnobPosition(dx, dy);
};
game.move = function (x, y, obj) {
	if (gameState !== GAME_STATE.PLAYING || !joystick.active || skillSelectionActive) {
		return;
	}
	// Ekranın ortasını aynı sabit olarak kullan
	var centerX = 1024;
	var centerY = 2290;
	var dx = x - centerX;
	var dy = y - centerY;
	// Knob’u güncelle
	joystick.setKnobPosition(dx, dy);
};
game.up = function (x, y, obj) {
	if (gameState !== GAME_STATE.PLAYING) {
		return;
	}
	joystick.reset();
};
// --- LOADING SCREEN & ASSET PRELOAD ---
// Show a loading screen before main menu, preload all assets, then show main menu
var loadingContainer = null;
function showLoadingScreen() {
	if (loadingContainer) {
		loadingContainer.destroy();
	}
	loadingContainer = game.addChild(new Container());
	// Simple black background
	var bg = loadingContainer.attachAsset('mainMenuBackground', {
		anchorX: 0.5,
		anchorY: 0.5,
		x: 1024,
		y: 1366
	});
	// Loading text
	var loadingTxt = new Text2("Loading...", {
		size: 80,
		fill: 0xffffff
	});
	loadingTxt.anchor.set(0.5, 0.5);
	loadingTxt.x = 1024;
	loadingTxt.y = 1366;
	loadingContainer.addChild(loadingTxt);
	// Subtitle for best experience
	var loadingSubTxt = new Text2("For the best gaming experience, please wait until the game's graphic and audio resources are fully loaded.", {
		size: 36,
		fill: 0xffffff,
		wordWrap: true,
		wordWrapWidth: 1800,
		align: "center"
	});
	loadingSubTxt.anchor.set(0.5, 0);
	loadingSubTxt.x = 1024;
	loadingSubTxt.y = 1460;
	loadingContainer.addChild(loadingSubTxt);
	// Optional: add a simple spinner effect
	var spinner = new Container();
	var spinnerAsset = spinner.attachAsset('chickenLeg', {
		anchorX: 0.5,
		anchorY: 0.5,
		width: 120,
		height: 120
	});
	spinner.x = 1024;
	spinner.y = 1566;
	loadingContainer.addChild(spinner);
	spinner.update = function () {
		if (spinnerAsset) {
			spinnerAsset.rotation += 0.2;
		}
	};
	loadingContainer.update = function () {
		if (spinner && spinner.update) {
			spinner.update();
		}
	};
}
// Preload all assets (images, sounds, music) before showing main menu
function preloadAllAssets(onComplete) {
	// List of all asset keys to preload
	var assetKeys = [
	// Images
	'mainMenuBackground', 'startButton', 'languagesButton', 'langButton', 'returnMainMenu', 'deathBackground', 'player', 'hpBarRect', 'hpBarRectFg', 'enemyHpBarRect', 'enemyHpBarRectFg', 'seamlessBackGround', 'zombie', 'normalZombie', 'normalZombieAttack', 'rangedZombie', 'rangedZombieSaliva', 'fastZombie', 'fastZombieAttack', 'tankZombie', 'tankZombieAttack', 'bossZombie', 'bossZombieAttack1', 'bossZombieAttack2', 'auraField', 'ball', 'bomb', 'boomerang', 'brick', 'lightning', 'magnet', 'molotov', 'molotovFlame', 'rocket', 'rocketBoom', 'shuriken', 'skillCard', 'chickenLeg',
	// Sounds
	'damageTaken', 'death', 'hit', 'levelup', 'pickup', 'rocketBoom',
	// Music
	'backGroundMusic', 'deathScreenMusic', 'mainMenuMusic'];
	var loadedCount = 0;
	var totalCount = assetKeys.length;
	function assetLoaded() {
		loadedCount++;
		// Optionally update loading text
		if (loadingContainer && loadingContainer.children && loadingContainer.children.length > 1) {
			var txt = loadingContainer.children[1];
			if (txt && txt.setText) {
				txt.setText("Loading... " + loadedCount + "/" + totalCount);
			}
		}
		if (loadedCount >= totalCount) {
			if (typeof onComplete === "function") {
				onComplete();
			}
		}
	}
	// Defensive: if LK.getAsset returns synchronously, call assetLoaded immediately
	for (var i = 0; i < assetKeys.length; i++) {
		(function (key) {
			var asset = LK.getAsset(key, {
				anchorX: 0.5,
				anchorY: 0.5
			});
			// If asset is already loaded, call assetLoaded immediately
			if (asset && (asset.texture || asset.width)) {
				assetLoaded();
			} else if (asset && typeof asset.once === "function") {
				// Listen for 'loaded' event if available
				asset.once('loaded', assetLoaded);
			} else {
				// Fallback: call assetLoaded after short delay
				LK.setTimeout(assetLoaded, 10);
			}
		})(assetKeys[i]);
	}
}
// At game start, show loading screen, preload all assets, then show main menu
showLoadingScreen();
preloadAllAssets(function () {
	if (loadingContainer) {
		loadingContainer.destroy();
		loadingContainer = null;
	}
	showMainMenu();
});
// Game update
game.update = function () {
	// Block all game logic, UI, and sounds if not in PLAYING state
	if (gameState !== GAME_STATE.PLAYING) {
		setGameUIVisible(false);
		handleNonPlayingState();
		return;
	}
	setGameUIVisible(true);
	ensurePlayingMusic();
	if (skillSelectionActive) {
		return;
	}
	gameTime++;
	updateTimerUI();
	updatePlayerUI();
	updateWaveUI();
	updatePlayerMovement();
	player.update();
	updatePlayerHealthBar();
	updateEnemyHealthBars();
	updateCamera();
	updateBackgroundTiles();
	handleWaveBreakLogic();
	updateEnemies();
	updateExpOrbs();
	spawnPickupsIfNeeded();
	updatePickups();
};
function handleNonPlayingState() {
	// Defensive: stop all music and sounds if not already stopped
	// Play correct music for each state
	if (gameState === GAME_STATE.MAIN_MENU) {
		// Music is handled in showMainMenu/red overlay logic, do not play here to avoid double playback
	} else if (gameState === GAME_STATE.DEATH) {
		if (currentMusic !== "deathScreenMusic") {
			LK.stopMusic();
			window._mainMenuMusicPlaying = false;
			LK.playMusic('deathScreenMusic', {
				loop: false
			});
			currentMusic = "deathScreenMusic";
		}
	} else {
		LK.stopMusic();
		window._mainMenuMusicPlaying = false;
		currentMusic = null;
	}
	if (typeof LK.stopAllSounds === "function") {
		LK.stopAllSounds();
	}
	window._mainMenuMusicPlaying = false; // Defensive: always reset flag when stopping music
}
function ensurePlayingMusic() {
	// Ensure correct music is playing in PLAYING state
	if (currentMusic !== "backGroundMusic") {
		LK.stopMusic();
		LK.playMusic('backGroundMusic', {
			loop: true
		});
		currentMusic = "backGroundMusic";
	}
}
function updateTimerUI() {
	// Update timer → geçen süreyi göster
	var elapsedSeconds = Math.floor(gameTime / 60);
	var minutes = Math.floor(elapsedSeconds / 60);
	var seconds = elapsedSeconds % 60;
	timerText.setText((minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds));
}
function updatePlayerUI() {
	hpText.setText(t("hpPrefix") + ": " + player.hp.toFixed(1) + '/' + player.maxHp.toFixed(1));
	levelText.setText(t("levelPrefix") + " " + player.level + "  " + t("expPrefix") + ": " + player.exp + "/" + player.level);
}
function updateWaveUI() {
	waveText.setText(t("wavePrefix") + " " + waveNumber);
}
function updatePlayerMovement() {
	if (joystick.active) {
		player.x += joystick.dirX * player.moveSpeed;
		player.y += joystick.dirY * player.moveSpeed;
	}
}
function updatePlayerHealthBar() {
	if (player.hpBar && player.hpBarFg) {
		var hpRatio = Math.max(0, Math.min(1, player.hp / player.maxHp));
		player.hpBarFg.width = 212 * hpRatio;
		player.hpBarFg.x = 0;
		if (hpRatio > 0.8) {
			player.hpBarFg.tint = 0x00ff44; // green
			player.hpBarFg.alpha = 1;
		} else if (hpRatio > 0.5) {
			player.hpBarFg.tint = 0xffe066; // yellow
			player.hpBarFg.alpha = 1;
		} else if (hpRatio > 0.2) {
			player.hpBarFg.tint = 0xff9900; // orange
			player.hpBarFg.alpha = 1;
		} else {
			player.hpBarFg.tint = 0xff0000; // pure red for critical
			if (gameTime % 12 < 6) {
				player.hpBarFg.alpha = 1;
			} else {
				player.hpBarFg.alpha = 0.3;
			}
		}
	}
}
function updateEnemyHealthBars() {
	for (var i = 0; i < enemies.length; i++) {
		var enemy = enemies[i];
		if (enemy.hpBar && enemy.hpBarFg) {
			var ehpRatio = Math.max(0, Math.min(1, enemy.hp / enemy.maxHp));
			enemy.hpBarFg.width = 152 * ehpRatio;
			enemy.hpBarFg.x = 0;
			enemy.hpBarFg.tint = 0xff4444;
			enemy.hpBarFg.alpha = 1;
		}
	}
}
function updateCamera() {
	camera.x = player.x - 1024;
	camera.y = player.y - 1366;
	gameContainer.x = -camera.x;
	gameContainer.y = -camera.y;
}
function updateBackgroundTiles() {
	if (backgroundTiles && backgroundTiles.length) {
		var startX = Math.floor(camera.x / bgTileWidth) * bgTileWidth;
		var startY = Math.floor(camera.y / bgTileHeight) * bgTileHeight;
		var idx = 0;
		for (var i = 0; i < bgTilesX; i++) {
			for (var j = 0; j < bgTilesY; j++) {
				var tile = backgroundTiles[idx++];
				tile.x = startX + i * bgTileWidth;
				tile.y = startY + j * bgTileHeight;
			}
		}
	}
}
function handleWaveBreakLogic() {
	if (typeof nextWaveTimeout === "undefined") {
		nextWaveTimeout = null;
	}
	if (typeof waveBreakCountdown === "undefined") {
		waveBreakCountdown = null;
	}
	if (typeof waveBreakCountdownText === "undefined") {
		waveBreakCountdownText = null;
	}
	// --- Wave break logic: block all weapon/projectile firing, stop all weapon sounds, show countdown under Wave text ---
	if (enemies.length === 0 && !nextWaveTimeout) {
		// Stop all weapon/projectile sounds instantly
		var weaponSounds = ['swordSoundEffect', 'bumerangSoundEffect', 'ballSoundEffect', 'rocketSoundEffect', 'brickSoundEffect', 'lightningSoundEffect', 'molotovSoundEffect', 'molotovBoom', 'rocketBoom', 'hit'];
		for (var i = 0; i < weaponSounds.length; i++) {
			var s = LK.getSound(weaponSounds[i]);
			if (s && typeof s.stop === "function") {
				s.stop();
			}
		}
		window._waveBreakActive = true;
		if (!waveBreakCountdownText) {
			waveBreakCountdownText = new Text2("3", {
				size: 120,
				fill: 0xff2222,
				stroke: 0x000000,
				strokeThickness: 6
			});
			waveBreakCountdownText.anchor.set(0.5, 0);
			waveBreakCountdownText.y = 220;
			LK.gui.top.addChild(waveBreakCountdownText);
		}
		waveBreakCountdown = 3;
		waveBreakCountdownText.setText("3");
		if (typeof window._waveBreakCountdownPaused === "undefined") {
			window._waveBreakCountdownPaused = false;
		}
		if (typeof window._waveBreakCountdownRemaining === "undefined") {
			window._waveBreakCountdownRemaining = 3;
		}
		if (typeof window._waveBreakCountdownStartTime === "undefined") {
			window._waveBreakCountdownStartTime = Date.now();
		}
		var _countdownTick = function countdownTick() {
			if (skillSelectionActive) {
				window._waveBreakCountdownPaused = true;
				if (typeof window._waveBreakCountdownRemaining === "undefined") {
					window._waveBreakCountdownRemaining = waveBreakCountdown;
				} else {
					window._waveBreakCountdownRemaining = waveBreakCountdown;
				}
				return;
			} else {
				window._waveBreakCountdownPaused = false;
			}
			if (waveBreakCountdownText) {
				waveBreakCountdown--;
				window._waveBreakCountdownRemaining = waveBreakCountdown;
				if (waveBreakCountdown > 0) {
					waveBreakCountdownText.setText(waveBreakCountdown.toString());
					nextWaveTimeout = LK.setTimeout(_countdownTick, 1000);
				} else {
					if (waveBreakCountdownText.parent) {
						waveBreakCountdownText.destroy();
					}
					waveBreakCountdownText = null;
					waveBreakCountdown = null;
					window._waveBreakCountdownRemaining = null;
					window._waveBreakCountdownStartTime = null;
					window._waveBreakActive = false;
					waveNumber++;
					spawnWave();
					nextWaveTimeout = null;
				}
			}
		};
		if (!window._waveBreakCountdownPaused) {
			nextWaveTimeout = LK.setTimeout(_countdownTick, 1000);
		}
	}
	// --- Resume countdown after skill selection closes ---
	if (typeof window._waveBreakCountdownPaused !== "undefined" && window._waveBreakCountdownPaused && !skillSelectionActive && typeof window._waveBreakCountdownRemaining === "number" && window._waveBreakCountdownRemaining > 0) {
		waveBreakCountdown = window._waveBreakCountdownRemaining;
		if (waveBreakCountdownText) {
			waveBreakCountdownText.setText(waveBreakCountdown.toString());
		}
		window._waveBreakCountdownPaused = false;
		var _countdownTick = function countdownTick() {
			if (skillSelectionActive) {
				window._waveBreakCountdownPaused = true;
				window._waveBreakCountdownRemaining = waveBreakCountdown;
				return;
			} else {
				window._waveBreakCountdownPaused = false;
			}
			if (waveBreakCountdownText) {
				waveBreakCountdown--;
				window._waveBreakCountdownRemaining = waveBreakCountdown;
				if (waveBreakCountdown > 0) {
					waveBreakCountdownText.setText(waveBreakCountdown.toString());
					nextWaveTimeout = LK.setTimeout(_countdownTick, 1000);
				} else {
					if (waveBreakCountdownText.parent) {
						waveBreakCountdownText.destroy();
					}
					waveBreakCountdownText = null;
					waveBreakCountdown = null;
					window._waveBreakCountdownRemaining = null;
					window._waveBreakCountdownStartTime = null;
					window._waveBreakCountdownPaused = false;
					window._waveBreakActive = false;
					waveNumber++;
					spawnWave();
					nextWaveTimeout = null;
				}
			}
		};
		nextWaveTimeout = LK.setTimeout(_countdownTick, 1000);
	}
	if (enemies.length > 0 && nextWaveTimeout) {
		LK.clearTimeout(nextWaveTimeout);
		nextWaveTimeout = null;
		if (waveBreakCountdownText && waveBreakCountdownText.parent) {
			waveBreakCountdownText.destroy();
		}
		waveBreakCountdownText = null;
		waveBreakCountdown = null;
		window._waveBreakActive = false;
	}
}
function updateEnemies() {
	for (var i = 0; i < enemies.length; i++) {
		enemies[i].update();
	}
}
function updateExpOrbs() {
	for (var i = expOrbs.length - 1; i >= 0; i--) {
		var orb = expOrbs[i];
		var dx = orb.x - player.x;
		var dy = orb.y - player.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (player.buffs && player.buffs.magnetPlus && player.buffs.magnetPlus > 0) {
			var levels = player.buffs.magnetPlus;
			var magnetRadius = 300 + (levels - 1) * 150;
			if (dist <= magnetRadius) {
				if (orb.magnetSpeed < 12) {
					orb.magnetSpeed = 12;
				}
			}
		}
		if (dist < player.pickupRange) {
			orb.magnetSpeed = 10;
		}
		if (dist <= 30) {
			player.gainExp(orb.value);
			orb.destroy();
			expOrbs.splice(i, 1);
			LK.getSound('pickup').play();
		}
	}
}
function spawnPickupsIfNeeded() {
	if (gameTime - lastPickupSpawn > 1200) {
		var baseChance = 0.25;
		var bombMagnetWeight = 0.45;
		var magnetWeight = 0.45;
		var chickenWeight = 0.25;
		var totalWeight = bombMagnetWeight + magnetWeight + chickenWeight;
		var bombMagnetProb = bombMagnetWeight / totalWeight;
		var magnetProb = magnetWeight / totalWeight;
		var chickenProb = chickenWeight / totalWeight;
		if (Math.random() < baseChance) {
			lastPickupSpawn = gameTime;
			var pickup;
			var angle = Math.random() * Math.PI * 2;
			var distance = 300 + Math.random() * 500;
			var pickupX = player.x + Math.cos(angle) * distance;
			var pickupY = player.y + Math.sin(angle) * distance;
			var randVal = Math.random();
			if (randVal < bombMagnetProb) {
				pickup = new Bomb();
			} else if (randVal < bombMagnetProb + magnetProb) {
				pickup = new Magnet();
			} else {
				pickup = new ChickenLeg();
			}
			pickup.x = pickupX;
			pickup.y = pickupY;
			pickups.push(pickup);
			gameContainer.addChild(pickup);
		}
	}
}
function updatePickups() {
	for (var i = pickups.length - 1; i >= 0; i--) {
		var pickup = pickups[i];
		if (!pickup.active) {
			pickups.splice(i, 1);
		}
	}
}
// Initial spawn
// spawnWave();//{jb} // Delay first wave spawn until after weapon selection
// Music is now handled in game.update based on gameState
// (First wave is now only spawned after weapon selection card pick, see resetGameWorld and weaponSelectionOverlay.card.down)
// Tank Zombie asset (bigger, armored)
// Fast Zombie asset (slimmer, agile)
// Poison Zombie asset (greenish, toxic)
// Boss Zombie asset (huge, menacing) ===================================================================
--- original.js
+++ change.js
@@ -1894,10 +1894,10 @@
 
 /**** 
 * Game Code
 ****/ 
-/* ==== UNIVERSAL HELPERS ==== */
 // --- SOUND/MUSIC BLOCKER: Only allow introSpeech while red overlay is visible ---
+/* ==== UNIVERSAL HELPERS ==== */
 (function () {
 	// Patch LK.getSound and LK.playMusic to block all except introSpeech/mainMenuMusic when window._blockAllSounds is true
 	var origGetSound = LK.getSound;
 	var origPlayMusic = LK.playMusic;
@@ -3173,9 +3173,9 @@
 	var normalCount = 5 + (waveNumber - 1);
 	var rangedCount = waveNumber >= 3 ? waveNumber - 2 : 0;
 	var fastCount = waveNumber >= 6 ? waveNumber - 5 : 0;
 	var tankCount = waveNumber >= 9 ? waveNumber - 8 : 0;
-	var bossCount = waveNumber === 2 ? 1 : waveNumber % 10 === 0 ? Math.floor(waveNumber / 10) : 0;
+	var bossCount = waveNumber % 10 === 0 ? Math.floor(waveNumber / 10) : 0;
 	// --- HealerZombie: Artık ilk dalgada veya dalga ile gelmiyor, boss eventinde spawnlanacak ---
 	for (var i = 0; i < normalCount; i++) {
 		var angle = Math.random() * Math.PI * 2;
 		var x = player.x + Math.cos(angle) * spawnRadius;
@@ -3247,118 +3247,78 @@
 		}
 	}
 	spawnNextEnemy();
 	// --- BossZombie Rebirth Event Logic ---
-	// Always clear previous event/timer to avoid stuck state
-	if (bossRebirthEvent) {
-		bossRebirthEvent = null;
-	}
-	if (typeof bossRebirthEventTimer !== "undefined" && bossRebirthEventTimer) {
+	// 1) Önce varsa eski timer’ı temizle
+	if (bossRebirthEventTimer) {
 		LK.clearInterval(bossRebirthEventTimer);
 		bossRebirthEventTimer = null;
 	}
-	// Check if boss exists in spawnList
-	var hasBoss = false;
-	for (var i = 0; i < spawnList.length; i++) {
-		if (spawnList[i].type === 'bossZombie') {
-			hasBoss = true;
-			break;
-		}
-	}
+	// 2) Bu dalgada bir boss var mı?
+	var hasBoss = spawnList.some(function (s) {
+		return s.type === 'bossZombie';
+	});
 	if (hasBoss) {
-		// Function to spawn rebirth zombies
+		// a) Rebirth spawn fonksiyonu (aynı kalacak)
 		var spawnRebirthZombies = function spawnRebirthZombies() {
-			// Stop if skill selection (card) screen is active
-			if (skillSelectionActive) {
-				return;
-			}
-			// Find all living boss zombies (support multiple bosses)
-			var bosses = [];
-			for (var i = 0; i < enemies.length; i++) {
-				if (enemies[i] && enemies[i].type === 'bossZombie') {
-					bosses.push(enemies[i]);
-				}
-			}
-			if (!bosses.length) {
-				return;
-			}
-			// For each boss, spawn rebirth zombies around it
-			for (var b = 0; b < bosses.length; b++) {
-				var boss = bosses[b];
-				// Spawn 1 tank, 2 ranged, 1 healer at random positions within 300 radius of boss
+			if (skillSelectionActive) return;
+			// Sahnedeki tüm boss’ları bul
+			var bosses = enemies.filter(function (e) {
+				return e.type === 'bossZombie';
+			});
+			if (!bosses.length) return;
+			bosses.forEach(function (boss) {
 				var spawnTypes = ['tankZombie', 'rangedZombie', 'rangedZombie', 'healerZombie'];
-				var rebirthPositions = [];
-				for (var j = 0; j < spawnTypes.length; j++) {
+				spawnTypes.forEach(function (type) {
 					var angle = Math.random() * Math.PI * 2;
-					var radius = Math.random() * 300; // 0-300 px from boss
-					var rx = boss.x + Math.cos(angle) * radius;
-					var ry = boss.y + Math.sin(angle) * radius;
-					rebirthPositions.push({
-						x: rx,
-						y: ry,
-						type: spawnTypes[j]
+					var radius = Math.random() * 300;
+					var x = boss.x + Math.cos(angle) * radius;
+					var y = boss.y + Math.sin(angle) * radius;
+					// Görsel efekt
+					var fx = new Container();
+					var asset = fx.attachAsset('zombieRebirth', {
+						anchorX: 0.5,
+						anchorY: 0.5,
+						alpha: 0
 					});
-				}
-				// Show zombieRebirth asset at each position, fade in over 4s, then spawn zombie
-				for (var k = 0; k < rebirthPositions.length; k++) {
-					(function (pos) {
-						var rebirthFx = new Container();
-						var asset = rebirthFx.attachAsset('zombieRebirth', {
-							anchorX: 0.5,
-							anchorY: 0.5,
-							alpha: 0
-						});
-						rebirthFx.x = pos.x;
-						rebirthFx.y = pos.y;
-						gameContainer.addChild(rebirthFx);
-						// Animate alpha from 0 to 1 over 4s
-						tween(asset, {
-							alpha: 1
-						}, {
-							duration: 4000,
-							easing: tween.linear,
-							onFinish: function onFinish() {
-								if (rebirthFx.parent) {
-									rebirthFx.destroy();
-								}
-								spawnEnemy(pos.type, pos.x, pos.y);
-							}
-						});
-					})(rebirthPositions[k]);
-				}
-			}
+					fx.x = x;
+					fx.y = y;
+					gameContainer.addChild(fx);
+					tween(asset, {
+						alpha: 1
+					}, {
+						duration: 4000,
+						easing: tween.linear,
+						onFinish: function onFinish() {
+							if (fx.parent) fx.destroy();
+							spawnEnemy(type, x, y);
+						}
+					});
+				});
+			});
 		};
-		// Wait for boss to spawn, then trigger immediately and set interval
-		LK.setTimeout(function () {
-			var bosses = [];
-			for (var i = 0; i < enemies.length; i++) {
-				if (enemies[i] && enemies[i].type === 'bossZombie') {
-					bosses.push(enemies[i]);
-				}
-			}
-			if (bosses.length > 0) {
-				bossRebirthEvent = bosses.slice(); // store array of bosses
-				// Spawn immediately when boss appears
+		// b) Boss sahneye çıkana kadar yarım saniyede bir kontrol et
+		var lookForBossTimer = LK.setInterval(function () {
+			var onStage = enemies.some(function (e) {
+				return e.type === 'bossZombie';
+			});
+			if (onStage) {
+				LK.clearInterval(lookForBossTimer);
+				// hemen bir kere
 				spawnRebirthZombies();
-				// Then every 16s
+				// ardından her 16 saniyede bir
 				bossRebirthEventTimer = LK.setInterval(function () {
-					// If all bosses are dead or missing, stop event
-					var livingBosses = [];
-					for (var i = 0; i < enemies.length; i++) {
-						if (enemies[i] && enemies[i].type === 'bossZombie') {
-							livingBosses.push(enemies[i]);
-						}
-					}
-					if (!livingBosses.length) {
+					if (enemies.some(function (e) {
+						return e.type === 'bossZombie';
+					})) {
+						spawnRebirthZombies();
+					} else {
 						LK.clearInterval(bossRebirthEventTimer);
 						bossRebirthEventTimer = null;
-						bossRebirthEvent = null;
-						return;
 					}
-					spawnRebirthZombies();
-				}, 16000); // every 16s
+				}, 16000);
 			}
-		}, 1000); // Wait 1s for boss to spawn
+		}, 500);
 	}
 }
 function dropExpOrb(x, y) {
 	var orb = new ExpOrb();
 Survivor.io style 2D sword swing effect made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows. It should only have a slash effect, no swords. The slash effect should also be in the shape of a half moon.
 Survivor.io style 2D round soccer ball made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
 A 2D Survivor.io style lightning strike from a cloud in the sky to the ground, made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
 A red and blue Survivor.io style 2D U-shaped (with N and S) magnet made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
 Survivor.io style 2D shuriken made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
 Survivor.io style 2D brick made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
 Survivor.io style 2D missile rocket made by HABBY PTE. LTD.
 A 2D green radiating circular aura in the Survivor.io style made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
 A 2D bomb in the style of Survivor.io, made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
 A 2D circular burning effect in Survivor.io style made by HABBY PTE. LTD. (not only the surroundings but also the inside burns) In-Game asset. 2d. High contrast. No shadows
 A 2D molotov in the Survivor.io style made by HABBY PTE. LTD.. In-Game asset. 2d. High contrast. No shadows
 Survivor.io style 2D greenish exp sphere made by HABBY PTE. LTD. No exp written on it. In-Game asset. 2d. High contrast. No shadows
 Survivor.io style 2D half-moon orange boomerang made by HABBY PTE. LTD. In-Game asset. 2d. High contrast. No shadows
 Survivor.io style 2D 1 chicken leg.. In-Game asset. 2d. High contrast. No shadows
 2D survivor.io game style atomic boom effect front view. No text written on it.
 
 2D. Ranged zombie. attacks with poisonous saliva. In-Game asset. 2d. High contrast. No shadows
 2D. Child (small) zombie. He has a small saw in his hand.. In-Game asset. 2d. High contrast. No shadows
 2D. Fat zombie. His hands are too big.. In-Game asset. 2d. High contrast. No shadows
 Poisonous green circular saliva. 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
 Small green claw slash effect. 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
 Giant boss angry reddish zombie. 2D.. In-Game asset. 2d. High contrast. No shadows
 Small saw slash effect. 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
 Big red fist slash effect. 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
 Kanlı kemik 2D. Top View.. In-Game asset. 2d. High contrast. No shadows
 2D character that looks like a prophet and holds a holy book in his hand.. In-Game asset. 2d. High contrast. No shadows
 A background image (wallpaper) representing an old prophet-like man with white hair and beard, wearing a priest's robe (hooded) and holding a holy book (christianity, cross) in his hand, fighting against zombies.. In-Game asset. 2d. High contrast. No shadows
 Zombie flesh and bone themed 2D cardboard hollow (without text) horizontal rectangular button.. In-Game asset. 2d. High contrast. No shadows
 2D. Healer zombie. Like a female zombie in a healer costume.. In-Game asset. 2d. High contrast. No shadows
 2D. Brain illustrated healing potion.. In-Game asset. 2d. High contrast. No shadows
 A healing blood pool with circular zombie brain and bone particles. Green + (healing) symbols on top. 2D.. In-Game asset. 2d. High contrast. No shadows
 2D. Survivor.io game style skill card. No text written on it. No symbols on it. Just the blank card. Green.. In-Game asset. 2d. High contrast. No shadows
 2D. Cartoon. The rise of the zombie ghost spirit from the ground.. In-Game asset. 2d. High contrast. No shadows
levelup
Sound effect
hit
Sound effect
rocketBoom
Sound effect
pickup
Sound effect
backGroundMusic
Music
death
Sound effect
damageTaken
Sound effect
mainMenuMusic
Music
deathScreenMusic
Music
swordSoundEffect
Sound effect
bumerangSoundEffect
Sound effect
brickSoundEffect
Sound effect
lightningSoundEffect
Sound effect
ballSoundEffect
Sound effect
rocketSoundEffect
Sound effect
auraSoundEffect
Sound effect
molotovSoundEffect
Sound effect
molotovBoom
Sound effect
introSpeech
Sound effect
bombBoomSound
Sound effect