User prompt
Sadece korsan ve Npc sistemi olsun. NPC'ler ile korsan gemileri bazen aralarında savaşsınlar.
User prompt
Bunların ara ara spawn olma sıklığını 3 katına çıkart.
User prompt
Bütün etkinlik, görev ve özel binalar oyundan kaldır veya sil.
User prompt
Bütün oyun alanını, oyun ekranına sığacak şekilde boyutlandır.
User prompt
Gemi oyun ekranının dışına çıkmasın. Kamerayı ona göre hafif konumlandır.
User prompt
Oyun haritasını 10000 kat büyüt
User prompt
Oyun haritasını 100 kat büyüt ve kamerayı gemi takibini bırakmayacak şekilde ayarla.
User prompt
Oyun haritasını 10 kat büyüt.
User prompt
Sonsuz oyun olmasından kaynaklı bu sorun sanırım. Oyun haritasını sınırlandırma yapsan düzelir mi. Bir dene..
User prompt
Aynı şeyler devam ediyor.
User prompt
Özetle bahsettiğin konuların tamamını elden geç. Gerekirse kod düzenle, yaz, sil. Ama şu sorunu çöz.
User prompt
Ekranda oluşan şeylerin, yazıların ve bütün etkinlik, görev gibi şeylerin yenilenme sürecini oluştur. Ekranda çıkar çıkmaz buga giriyor. Ekranda kalıyor.
User prompt
Bu tür etkinlik, görev ve özel binaların, kendilerine özel resim dosyasını oluştur.
User prompt
Bu tür şeyler ekranda benimle birlikte gitmesin. Çıktıkları yerde dolaşsınlar. Bug oluyor gibi. Ekranda sadece görselleri var. Kendileri yok.
User prompt
Herhangi bir etkinlik, özel bina veya görev olduğun, kalan mesafe üzerinde küçük şekilde anlık olarak göstersin.
User prompt
Bütün etkinlikler ve bu son konuştuğumuz görev çeşitleri, oyunda spawn oluyor ama donuyor öylece kalıyor. Ne gidebiliyorum ne gelebiliyorum. Mesafe çok yakın olmasına rağmen.
User prompt
Bütün bu mesafeyi az biraz uzat. Oyun başlayınca dibimde çıkıyor ve herhangi bir etkileşim veya sistemsel değişim olmuyor.
User prompt
Oyunda bulunan bütün kara delik, solucan ve istasyon vb. Ayrıca bütün etkinlikler 400-500px mesafelerde rastgele olmasını sağla.
User prompt
Bunu çözmek için yakında oluşacak şekilde kodları değiştir.
User prompt
Mesafesi bu kadar uzak bir etkinlik veya görev olmasın. Mesafesi sadece spawn mesafesi kadar uzaklıkta olan görev ve etkinlikler olsun. Bu konuda kod üzerinde değişiklik yap.
User prompt
Mini Map yazısını ve butonunu tamamen ekrandan gizle.
User prompt
Bütün etkinlikler, oyun ekranının köşesinde spawn olsun. Ekran dışında spawn olmasın.
User prompt
KILL yazısını tamamen sil çıkmasın.
User prompt
Exp ve rep yazılarını tamamen sil çıkmasın.
User prompt
Game time 2 saniye geçmesine rağmen, rep ve exp yazıları gitmiyor.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Asteroid = Container.expand(function () { var self = Container.call(this); var asteroidGraphics = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5, tint: 0x8B4513, scaleX: 2, scaleY: 2 }); self.health = 50; self.resources = Math.floor(Math.random() * 10) + 5; self.vx = (Math.random() - 0.5) * 0.5; self.vy = (Math.random() - 0.5) * 0.5; self.rotationSpeed = (Math.random() - 0.5) * 0.02; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xffffff, 100); }; self.update = function () { self.x += self.vx; self.y += self.vy; self.rotation += self.rotationSpeed; }; return self; }); // Black Hole Hazard Class var BlackHole = Container.expand(function () { var self = Container.call(this); var bhGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 8, tint: 0x222222 }); self.radius = 200; self.pullStrength = 0.7 + Math.random() * 0.5; self.damageRadius = 120; self.update = function () { // Animate black hole bhGraphics.rotation += 0.03; // Pull ship if in range var dx = ship.x - self.x; var dy = ship.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.radius) { var pull = (self.radius - dist) / self.radius * self.pullStrength; ship.x -= dx / dist * pull; ship.y -= dy / dist * pull; // Camera follows ship, so move all objects accordingly for (var i = 0; i < stars.length; i++) { stars[i].x -= dx / dist * pull; stars[i].y -= dy / dist * pull; } for (var i = 0; i < npcs.length; i++) { npcs[i].x -= dx / dist * pull; npcs[i].y -= dy / dist * pull; } for (var i = 0; i < pirates.length; i++) { pirates[i].x -= dx / dist * pull; pirates[i].y -= dy / dist * pull; } for (var i = 0; i < coins.length; i++) { coins[i].x -= dx / dist * pull; coins[i].y -= dy / dist * pull; } for (var i = 0; i < resources.length; i++) { resources[i].x -= dx / dist * pull; resources[i].y -= dy / dist * pull; } for (var i = 0; i < bullets.length; i++) { bullets[i].x -= dx / dist * pull; bullets[i].y -= dy / dist * pull; } for (var i = 0; i < enemyBullets.length; i++) { enemyBullets[i].x -= dx / dist * pull; enemyBullets[i].y -= dy / dist * pull; } for (var i = 0; i < asteroids.length; i++) { asteroids[i].x -= dx / dist * pull; asteroids[i].y -= dy / dist * pull; } for (var i = 0; i < upgradeStations.length; i++) { upgradeStations[i].x -= dx / dist * pull; upgradeStations[i].y -= dy / dist * pull; } for (var i = 0; i < boostParticles.length; i++) { boostParticles[i].x -= dx / dist * pull; boostParticles[i].y -= dy / dist * pull; } for (var i = 0; i < explosions.length; i++) { explosions[i].x -= dx / dist * pull; explosions[i].y -= dy / dist * pull; } } // Damage ship if too close if (dist < self.damageRadius) { if (!self.lastDamaged || LK.ticks - self.lastDamaged > 30) { ship.takeDamage(10); self.lastDamaged = LK.ticks; LK.effects.flashObject(ship, 0x000000, 200); } } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.damage = 10; self.directionX = 0; self.directionY = -1; self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.value = Math.floor(Math.random() * 10) + 5; self.update = function () { self.rotation += 0.05; }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 5; self.directionX = 0; self.directionY = 0; self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; }; return self; }); // HealthBar class for displaying health above entities var HealthBar = Container.expand(function () { var self = Container.call(this); // width, height, color, maxValue, getValueFn self._width = 60; self._height = 10; self._color = 0x00ff00; self._maxValue = 100; self._getValueFn = null; self._getMaxFn = null; self._bg = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: self._width / 40, scaleY: self._height / 40, tint: 0x222222 }); self._bar = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: (self._width - 4) / 40, scaleY: (self._height - 4) / 40, tint: self._color }); self._bar.x = 0; self._bar.y = 0; self.set = function (opts) { self._maxValue = opts.maxValue || 100; self._getValueFn = opts.getValueFn; self._getMaxFn = opts.getMaxFn; self._color = opts.color || 0x00ff00; self._bar.tint = self._color; if (opts.width) { self._width = opts.width; self._bg.scaleX = self._width / 40; self._bar.scaleX = (self._width - 4) / 40; } if (opts.height) { self._height = opts.height; self._bg.scaleY = self._height / 40; self._bar.scaleY = (self._height - 4) / 40; } }; self.update = function () { var value = self._getValueFn ? self._getValueFn() : self._maxValue; var maxValue = self._getMaxFn ? self._getMaxFn() : self._maxValue; var ratio = Math.max(0, Math.min(1, value / maxValue)); // Color: green > yellow > red if (ratio > 0.6) { self._bar.tint = 0x00ff00; } else if (ratio > 0.3) { self._bar.tint = 0xffff00; } else { self._bar.tint = 0xff0000; } self._bar.scaleX = (self._width - 4) * ratio / 40; }; return self; }); var NPC = Container.expand(function () { var self = Container.call(this); var npcGraphics = self.attachAsset('npc', { anchorX: 0.5, anchorY: 0.5 }); self.isAI = true; // AI-driven self.baseY = 0; self.moveSpeed = 1 + Math.random() * 2; self.moveAngle = Math.random() * Math.PI * 2; self.wanderTimer = 0; self.lastAIAction = 0; self.targetX = null; self.targetY = null; self.rpgName = "NPC-" + Math.floor(Math.random() * 10000); // Only floating AI logic, no quests/events/trade // Add dummy interact method to prevent TypeError self.interact = function () { // No interaction for basic NPCs, return empty string return ""; }; self.update = function () { // Pause logic: If pauseUntil is set and not expired, skip movement if (self.pauseUntil && LK.ticks < self.pauseUntil) { // Still paused, only float animation self.y += Math.sin(LK.ticks * 0.05) * 0.5; return; } // AI: Sometimes move toward a random point, sometimes wander self.wanderTimer++; if (self.wanderTimer > 120 + Math.random() * 120) { if (Math.random() < 0.5) { // Pick a random point to move toward (simulate AI goal seeking) self.targetX = self.x + (Math.random() - 0.5) * 800; self.targetY = self.y + (Math.random() - 0.5) * 800; } else { self.targetX = null; self.targetY = null; } self.moveAngle = Math.random() * Math.PI * 2; self.wanderTimer = 0; } // Move toward target if set, else wander if (self.targetX !== null && self.targetY !== null) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { self.x += dx / dist * self.moveSpeed; self.y += dy / dist * self.moveSpeed; self.moveAngle = Math.atan2(dy, dx); } else { self.targetX = null; self.targetY = null; } } else { self.x += Math.cos(self.moveAngle) * self.moveSpeed; self.y += Math.sin(self.moveAngle) * self.moveSpeed; } // Float animation on top of movement self.y += Math.sin(LK.ticks * 0.05) * 0.5; }; return self; }); var Pirate = Container.expand(function () { var self = Container.call(this); var pirateGraphics = self.attachAsset('pirate', { anchorX: 0.5, anchorY: 0.5 }); // --- Pirate Level & Scaling --- self.level = typeof waveNumber !== "undefined" ? 1 + waveNumber : 1; self.health = 30 + (self.level - 1) * 10; self.speed = 2 + Math.floor((self.level - 1) / 10) * 0.2; // Slight speed up every 10 waves self.fireRate = 60 - Math.min((self.level - 1) * 2, 30); // Faster fire at higher levels self.lastFire = 0; self.loot = Math.floor(Math.random() * 30) + 10 + (self.level - 1) * 2; self.moveAngle = Math.random() * Math.PI * 2; self.patrolTimer = 0; self.aggroRange = 600; // Korsan saldırı ve savunma gücü seviyeye göre orantılı artar self.damage = 5 + Math.floor((self.level - 1) * 1.5); // Saldırı gücü daha hızlı artar self.defense = 2 + Math.floor((self.level - 1) * 1.2); // Savunma gücü de seviyeye göre artar // --- Level Text --- self._levelText = new Text2("Lv." + self.level, { size: 22, fill: 0xcccccc, align: "center" }); self._levelText.anchor.set(0.5, 0); self._levelText.x = 0; self._levelText.y = 40; // Under the pirate sprite self.addChild(self._levelText); // Level text only, defense text removed self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xffffff, 100); }; self.update = function () { // Update level text position in case of movement if (self._levelText) { self._levelText.x = 0; self._levelText.y = pirateGraphics.height / 2 + 4; self._levelText.setText("Lv." + self.level); } // Defense text removed // Movement AI self.patrolTimer++; if (self.patrolTimer > 180) { self.moveAngle = Math.random() * Math.PI * 2; self.patrolTimer = 0; } // Patrol movement if (self._squadTargetNPC && self._squadTargetNPC.questType === 'defend' && self._squadTargetNPC.questActive) { // Korsan, NPC'yi hedefle var target = self._squadTargetNPC; // Eğer defend quest'te yardım kabul edildiyse, oyuncuya da saldırabilir if (target._defendHelpAccepted === true && Math.random() < 0.5) { // %50 ihtimalle oyuncuya saldır target = Math.random() < 0.5 ? self._squadTargetNPC : ship; } var dx = target.x - self.x; var dy = target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; self.moveAngle = Math.atan2(dy, dx); } // Ateş et if (LK.ticks - self.lastFire > self.fireRate) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; var angle = Math.atan2(target.y - self.y, target.x - self.x); bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullet.rotation = angle + Math.PI / 2; enemyBullets.push(bullet); if (game && game.addChild) game.addChild(bullet); self.lastFire = LK.ticks; } } else { self.x += Math.cos(self.moveAngle) * self.speed * 0.5; self.y += Math.sin(self.moveAngle) * self.speed * 0.5; } }; return self; }); // Pirate Base Class var PirateBase = Container.expand(function () { var self = Container.call(this); var baseGraphics = self.attachAsset('pirate', { anchorX: 0.5, anchorY: 0.5, tint: 0x990000, scaleX: 3, scaleY: 3 }); self.health = 300; self.maxHealth = 300; self.attackPower = 10; self.defensePower = 10; self.spawnRadius = 350; self.pirates = []; self.lastPirateSpawn = 0; self.maxPirates = 10; self._destroyed = false; // Health bar self._healthBar = new HealthBar(); self._healthBar.set({ maxValue: function maxValue() { return self.maxHealth; }, getValueFn: function getValueFn() { return self.health; }, getMaxFn: function getMaxFn() { return self.maxHealth; }, width: 120, height: 16, color: 0xff0000 }); self._healthBar.y = -120; self.addChild(self._healthBar); self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 120); if (self.health <= 0 && !self._destroyed) { self.health = 0; self._destroyed = true; // Remove all pirates around base for (var i = 0; i < self.pirates.length; i++) { if (self.pirates[i] && !self.pirates[i]._destroyed) { self.pirates[i].destroy(); } } // Explosion effect createExplosion(self.x, self.y); // Floating label var label = new Text2("Korsan Üssü Yok Edildi!", { size: 48, fill: 0xffcc00, align: "center" }); label.anchor.set(0.5, 0.5); label.x = self.x; label.y = self.y - 180; if (game && game.addChild) game.addChild(label); self._destroyed = true; self.destroy(); } }; self.update = function () { // Health bar update if (self._healthBar && self._healthBar.update) self._healthBar.update(); // Remove dead pirates from list for (var i = self.pirates.length - 1; i >= 0; i--) { if (!self.pirates[i] || self.pirates[i]._destroyed) { self.pirates.splice(i, 1); } } // Spawn pirates if less than max if (!self._destroyed && self.pirates.length < self.maxPirates && LK.ticks - self.lastPirateSpawn > 90) { var pirate = new Pirate(); var angle = Math.random() * Math.PI * 2; pirate.x = self.x + Math.cos(angle) * (self.spawnRadius + Math.random() * 60); pirate.y = self.y + Math.sin(angle) * (self.spawnRadius + Math.random() * 60); pirate.health = 30 + self.attackPower * 2; pirate.damage = 5 + self.attackPower; pirate.rpgName = "BaseKorsan-" + Math.floor(Math.random() * 10000); pirate._baseRef = self; // Add health bar to pirate pirate._healthBar = new HealthBar(); pirate._healthBar.set({ maxValue: function maxValue() { return pirate.health > 0 ? pirate.health : 0; }, getValueFn: function getValueFn() { return pirate.health > 0 ? pirate.health : 0; }, getMaxFn: function getMaxFn() { return 30 + self.attackPower * 2; }, width: 60, height: 10 }); pirate._healthBar.y = -60; pirate.addChild(pirate._healthBar); pirates.push(pirate); self.pirates.push(pirate); if (game && game.addChild) game.addChild(pirate); self.lastPirateSpawn = LK.ticks; } // Base defense: shoot at player if close var distToShip = Math.sqrt(Math.pow(ship.x - self.x, 2) + Math.pow(ship.y - self.y, 2)); if (!self._destroyed && distToShip < self.spawnRadius + 80 && LK.ticks % 30 === 0) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; var angle = Math.atan2(ship.y - self.y, ship.x - self.x); bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullet.rotation = angle + Math.PI / 2; bullet.damage = 10 + self.attackPower; enemyBullets.push(bullet); if (game && game.addChild) game.addChild(bullet); } }; return self; }); var Resource = Container.expand(function () { var self = Container.call(this); var resourceGraphics = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5 }); self.type = Math.random() < 0.5 ? 'metal' : 'energy'; self.amount = Math.floor(Math.random() * 5) + 1; self.update = function () { self.rotation += 0.03; }; return self; }); var Ship = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('ship', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.shield = 50; self.maxShield = 50; self.shieldRegenDelay = 0; self.speed = 5; self.fireRate = 10; self.damage = 10; self.lastFire = 0; self.boostSpeed = 0; self.boostCooldown = 0; self.takeDamage = function (amount) { // Shield absorbs damage first if (self.shield > 0) { var shieldDamage = Math.min(amount, self.shield); self.shield -= shieldDamage; amount -= shieldDamage; LK.effects.flashObject(self, 0x0088ff, 100); self.shieldRegenDelay = 180; // 3 seconds delay before shield regen } if (amount > 0) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 200); } if (self.health <= 0) { self.health = 0; LK.showGameOver(); } }; self.update = function () { // Shield regeneration if (self.shieldRegenDelay > 0) { self.shieldRegenDelay--; } else if (self.shield < self.maxShield) { self.shield = Math.min(self.shield + 0.1, self.maxShield); } // Boost cooldown if (self.boostCooldown > 0) { self.boostCooldown--; } if (self.boostSpeed > 0) { self.boostSpeed -= 0.2; } }; return self; }); var Star = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); self.speed = Math.random() * 2 + 0.5; starGraphics.alpha = Math.random() * 0.8 + 0.2; self.vx = (Math.random() - 0.5) * 0.5; self.vy = (Math.random() - 0.5) * 0.5; self.update = function () { // Slow floating movement self.x += self.vx; self.y += self.vy; }; return self; }); // Trade Station Class var TradeStation = Container.expand(function () { var self = Container.call(this); var tradeGraphics = self.attachAsset('npc', { anchorX: 0.5, anchorY: 0.5, tint: 0x00ff99, scaleX: 2, scaleY: 2 }); self.type = 'trade'; self.rotationSpeed = 0.01; self.offerType = Math.random() < 0.5 ? 'buy' : 'sell'; // buy: station buys from player, sell: station sells to player self.resourceType = Math.random() < 0.5 ? 'metal' : 'energy'; self.amount = Math.floor(Math.random() * 10) + 5; self.price = Math.floor(Math.random() * 30) + 10; self.specialOffer = Math.random() < 0.2; // 20% chance for special upgrade offer self.specialUpgrade = null; if (self.specialOffer) { var upgrades = [{ name: 'maxHealth', label: 'Max Health +30', cost: 200 }, { name: 'maxShield', label: 'Max Shield +20', cost: 180 }, { name: 'damage', label: 'Damage +5', cost: 150 }, { name: 'speed', label: 'Speed +1', cost: 120 }]; self.specialUpgrade = upgrades[Math.floor(Math.random() * upgrades.length)]; } self.update = function () { self.rotation += self.rotationSpeed; // Pulse effect var scale = 2 + Math.sin(LK.ticks * 0.05) * 0.1; tradeGraphics.scaleX = scale; tradeGraphics.scaleY = scale; }; return self; }); var UpgradeStation = Container.expand(function () { var self = Container.call(this); var stationGraphics = self.attachAsset('pirate', { anchorX: 0.5, anchorY: 0.5, tint: 0x00ffff, scaleX: 1.5, scaleY: 1.5 }); self.type = 'upgrade'; self.upgrades = [{ name: 'health', cost: 100, metalCost: 10 }, { name: 'shield', cost: 150, metalCost: 15 }, { name: 'damage', cost: 200, energyCost: 20 }, { name: 'speed', cost: 120, energyCost: 10 }]; self.currentUpgrade = 0; self.rotationSpeed = 0.01; self.update = function () { self.rotation += self.rotationSpeed; // Pulse effect var scale = 1.5 + Math.sin(LK.ticks * 0.05) * 0.1; stationGraphics.scaleX = scale; stationGraphics.scaleY = scale; }; return self; }); // Wormhole Teleporter Class var Wormhole = Container.expand(function () { var self = Container.call(this); var whGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, scaleX: 5, scaleY: 5, tint: 0x00ffff }); self.radius = 120; self.cooldown = 0; self.update = function () { whGraphics.rotation += 0.07; // Teleport ship if close and not on cooldown var dx = ship.x - self.x; var dy = ship.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.radius && self.cooldown <= 0) { // Teleport ship to a random far location var tx = ship.x + (Math.random() - 0.5) * 4000; var ty = ship.y + (Math.random() - 0.5) * 4000; var dx2 = tx - ship.x; var dy2 = ty - ship.y; ship.x = tx; ship.y = ty; // Move all objects to keep camera effect for (var i = 0; i < stars.length; i++) { stars[i].x -= dx2; stars[i].y -= dy2; } for (var i = 0; i < npcs.length; i++) { npcs[i].x -= dx2; npcs[i].y -= dy2; } for (var i = 0; i < pirates.length; i++) { pirates[i].x -= dx2; pirates[i].y -= dy2; } for (var i = 0; i < coins.length; i++) { coins[i].x -= dx2; coins[i].y -= dy2; } for (var i = 0; i < resources.length; i++) { resources[i].x -= dx2; resources[i].y -= dy2; } for (var i = 0; i < bullets.length; i++) { bullets[i].x -= dx2; bullets[i].y -= dy2; } for (var i = 0; i < enemyBullets.length; i++) { enemyBullets[i].x -= dx2; enemyBullets[i].y -= dy2; } for (var i = 0; i < asteroids.length; i++) { asteroids[i].x -= dx2; asteroids[i].y -= dy2; } for (var i = 0; i < upgradeStations.length; i++) { upgradeStations[i].x -= dx2; upgradeStations[i].y -= dy2; } for (var i = 0; i < boostParticles.length; i++) { boostParticles[i].x -= dx2; boostParticles[i].y -= dy2; } for (var i = 0; i < explosions.length; i++) { explosions[i].x -= dx2; explosions[i].y -= dy2; } for (var i = 0; i < blackHoles.length; i++) { blackHoles[i].x -= dx2; blackHoles[i].y -= dy2; } for (var i = 0; i < wormholes.length; i++) { if (wormholes[i] !== self) { wormholes[i].x -= dx2; wormholes[i].y -= dy2; } } self.cooldown = 180; LK.effects.flashScreen(0x00ffff, 500); } if (self.cooldown > 0) self.cooldown--; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000033 }); /**** * Game Code ****/ // Game variables var ship; var joystickBase; var joystickHandle; var isDragging = false; var bullets = []; var enemyBullets = []; var npcs = []; var pirates = []; var coins = []; var resources = []; var stars = []; var asteroids = []; var upgradeStations = []; var boostParticles = []; var explosions = []; var blackHoles = []; var wormholes = []; var tradeStations = []; var pirateBases = []; // NEW: array for pirate bases var tradeText = new Text2('', { size: 40, fill: 0x00ff99 }); // Helper: spawn a pirate base at a random edge, with pirates around it function spawnPirateBase() { var base = new PirateBase(); // Spawn within 700-900px of the ship, random angle var angle = Math.random() * Math.PI * 2; var dist = 700 + Math.random() * 200; // 700-900px base.x = ship.x + Math.cos(angle) * dist; base.y = ship.y + Math.sin(angle) * dist; pirateBases.push(base); game.addChild(base); // Spawn initial pirates around base for (var i = 0; i < 10; i++) { var pirate = new Pirate(); var angle = Math.PI * 2 * (i / 10); pirate.x = base.x + Math.cos(angle) * (base.spawnRadius + Math.random() * 60); pirate.y = base.y + Math.sin(angle) * (base.spawnRadius + Math.random() * 60); // Level range: wave 1 => 1-3, wave 2 => 3-5, wave 3 => 5-7, etc. var minLevel = 1 + waveNumber * 2; var maxLevel = minLevel + 2; pirate.level = minLevel + Math.floor(Math.random() * (maxLevel - minLevel + 1)); pirate.health = 30 + (pirate.level - 1) * 10 + base.attackPower * 2; pirate.damage = 5 + Math.floor((pirate.level - 1) * 1.5) + base.attackPower; pirate.defense = 2 + Math.floor((pirate.level - 1) * 1.2) + base.defensePower; pirate.rpgName = "BaseKorsan-" + Math.floor(Math.random() * 10000); pirate._baseRef = base; // Add health bar to pirate pirate._healthBar = new HealthBar(); pirate._healthBar.set({ maxValue: function maxValue() { return pirate.health > 0 ? pirate.health : 0; }, getValueFn: function getValueFn() { return pirate.health > 0 ? pirate.health : 0; }, getMaxFn: function getMaxFn() { return 30 + base.attackPower * 2; }, width: 60, height: 10 }); pirate._healthBar.y = -60; pirate.addChild(pirate._healthBar); pirates.push(pirate); base.pirates.push(pirate); game.addChild(pirate); } } tradeText.anchor.set(0.5, 0); tradeText.y = 180; LK.gui.top.addChild(tradeText); var camera = { x: 0, y: 0 }; // --- Reputation system --- var playerGoodRep = storage.playerGoodRep || 0; var playerBadRep = storage.playerBadRep || 0; // --- Helper for multi-pirate attack quest --- function spawnPirateSquad(centerX, centerY, count, targetNPC) { var squad = []; for (var i = 0; i < count; i++) { var pirate = new Pirate(); var angle = Math.PI * 2 * (i / count); pirate.x = centerX + Math.cos(angle) * 200 + (Math.random() - 0.5) * 60; pirate.y = centerY + Math.sin(angle) * 200 + (Math.random() - 0.5) * 60; // Level range: wave 1 => 1-3, wave 2 => 3-5, wave 3 => 5-7, etc. var minLevel = 1 + waveNumber * 2; var maxLevel = minLevel + 2; pirate.level = minLevel + Math.floor(Math.random() * (maxLevel - minLevel + 1)); pirate.health = 30 + (pirate.level - 1) * 10; pirate.damage = 5 + Math.floor((pirate.level - 1) * 1.5); pirate.defense = 2 + Math.floor((pirate.level - 1) * 1.2); pirate.rpgName = "Korsan-" + Math.floor(Math.random() * 10000); pirate._squadTargetNPC = targetNPC; pirates.push(pirate); game.addChild(pirate); squad.push(pirate); } return squad; } // Trade station tap detection (RPG/ticaret) for (var i = 0; i < tradeStations.length; i++) { var ts = tradeStations[i]; var dist = Math.sqrt(Math.pow(ts.x - ship.x, 2) + Math.pow(ts.y - ship.y, 2)); if (dist < 180) { game._lastTradeStationTap = LK.ticks; break; } } var waveNumber = 0; var enemiesKilled = 0; var totalDistance = 0; // Player stats var playerCoins = storage.coins || 0; var playerMetal = storage.metal || 0; var playerEnergy = storage.energy || 0; var questsCompleted = storage.questsCompleted || 0; // UI Elements // Calculate the unified font size (30% smaller than expText, then %10 büyüt) var unifiedFontSize = Math.round(38 * 0.7 * 1.1); var coinText = new Text2('Coins: ' + playerCoins, { size: unifiedFontSize, fill: 0xFFFF00 }); coinText.anchor.set(0, 0); coinText.x = 120; coinText.y = 20; LK.gui.topLeft.addChild(coinText); // --- GAME TIME LABEL --- // Track game start time in ticks var gameStartTick = LK.ticks; var gameTimeText = new Text2('Game Time: 0:00', { size: unifiedFontSize, fill: 0xcccccc }); gameTimeText.anchor.set(0, 0); gameTimeText.x = coinText.x + coinText.width + 40; gameTimeText.y = coinText.y; LK.gui.topLeft.addChild(gameTimeText); var resourceText = new Text2('Metal: ' + playerMetal + ' Energy: ' + playerEnergy, { size: unifiedFontSize, fill: 0xFFFFFF }); resourceText.anchor.set(0, 0); resourceText.x = 120; resourceText.y = 80; LK.gui.topLeft.addChild(resourceText); var healthText = new Text2('Health: 100/100', { size: unifiedFontSize, fill: 0x00FF00 }); healthText.anchor.set(0.5, 0); healthText._isHealthBar = true; // Mark for tap detection LK.gui.top.addChild(healthText); var shieldText = new Text2('Shield: 50/50', { size: unifiedFontSize, fill: 0x0088FF }); shieldText.anchor.set(0.5, 0); shieldText.y = 60; LK.gui.top.addChild(shieldText); var boostText = new Text2('BOOST READY', { size: unifiedFontSize, fill: 0x00FFFF }); boostText.anchor.set(0.5, 0); boostText.y = 110; LK.gui.top.addChild(boostText); var waveText = new Text2('Wave: 1', { size: unifiedFontSize, fill: 0xFFFFFF }); waveText.anchor.set(1, 0); waveText.x = -20; waveText.y = 20; LK.gui.topRight.addChild(waveText); // --- RESET BUTTON (bottom right) --- var resetBtn = new Text2('Reset', { size: 44, fill: 0xff4444, font: "'Heath', Impact, 'Arial Black', Tahoma", // Heath-like font align: "center" }); resetBtn.anchor.set(1, 1); // bottom right resetBtn.x = -40; resetBtn.y = -40; LK.gui.bottomRight.addChild(resetBtn); // Touch/click handler for reset button resetBtn._isResetBtn = true; game._resetBtn = resetBtn; // Mini Map button removed // --- MINI MAP OVERLAY (hidden by default) --- window._miniMapVisible = false; window._miniMapElements = []; window._miniMapContainer = null; // Level/EXP system var playerLevel = storage.playerLevel || 1; var playerEXP = storage.playerEXP || 0; var expToNext = function expToNext(lv) { return 100 + (lv - 1) * 50; }; var expText = new Text2('Level: ' + playerLevel + ' EXP: ' + playerEXP + '/' + expToNext(playerLevel), { size: unifiedFontSize, fill: 0x00ffcc }); expText.anchor.set(1, 0); expText.x = -20; expText.y = 80; LK.gui.topRight.addChild(expText); // Move coordinateText to the left of waveText, decrease its size by 30%, and update its position and size in real time var coordinateText = new Text2('X: 0 Y: 0', { size: unifiedFontSize, // 30% smaller than Level text fill: 0xcccccc }); coordinateText.anchor.set(1, 0.5); // right center of the text // Position coordinateText to the left of waveText coordinateText.x = waveText.x - waveText.width - 30; coordinateText.y = waveText.y + waveText.height / 2; LK.gui.topRight.addChild(coordinateText); // Create joystick joystickBase = game.addChild(LK.getAsset('joystickBase', { anchorX: 0.5, anchorY: 0.5, x: 300, y: 2432 })); joystickBase.alpha = 0.5; joystickHandle = game.addChild(LK.getAsset('joystickHandle', { anchorX: 0.5, anchorY: 0.5, x: 300, y: 2432 })); joystickHandle.alpha = 0.7; // Create ship ship = game.addChild(new Ship()); ship.x = 1024; ship.y = 1366; // Add health bar to ship ship._healthBar = new HealthBar(); ship._healthBar.set({ maxValue: function maxValue() { return ship.maxHealth; }, getValueFn: function getValueFn() { return ship.health; }, getMaxFn: function getMaxFn() { return ship.maxHealth; }, width: 80, height: 12 }); ship._healthBar.y = -70; ship.addChild(ship._healthBar); // Start background music LK.playMusic('bgmusic'); // Initialize star field for (var i = 0; i < 50; i++) { spawnStar(); } // Helper functions function spawnStar() { var star = new Star(); // Spawn from edges of visible area var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top star.x = ship.x + (Math.random() - 0.5) * 2500; star.y = ship.y - 1500; break; case 1: // Right star.x = ship.x + 1500; star.y = ship.y + (Math.random() - 0.5) * 2500; break; case 2: // Bottom star.x = ship.x + (Math.random() - 0.5) * 2500; star.y = ship.y + 1500; break; case 3: // Left star.x = ship.x - 1500; star.y = ship.y + (Math.random() - 0.5) * 2500; break; } stars.push(star); game.addChild(star); } function spawnNPC() { var npc = new NPC(); // Spawn from edges of visible area var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top npc.x = ship.x + (Math.random() - 0.5) * 2000; npc.y = ship.y - 1500; break; case 1: // Right npc.x = ship.x + 1500; npc.y = ship.y + (Math.random() - 0.5) * 2000; break; case 2: // Bottom npc.x = ship.x + (Math.random() - 0.5) * 2000; npc.y = ship.y + 1500; break; case 3: // Left npc.x = ship.x - 1500; npc.y = ship.y + (Math.random() - 0.5) * 2000; break; } npc.baseY = npc.y; // Add health bar to NPC (for defend/hunt/escort/delivery/explore) npc._healthBar = new HealthBar(); npc._healthBar.set({ maxValue: function maxValue() { return npc.health !== undefined ? npc.health : 100; }, getValueFn: function getValueFn() { return npc.health !== undefined ? npc.health : 100; }, getMaxFn: function getMaxFn() { return 100; }, width: 60, height: 10 }); npc._healthBar.y = -60; npc.addChild(npc._healthBar); npcs.push(npc); game.addChild(npc); } function spawnPirate() { var pirate = new Pirate(); // Spawn from edges of visible area var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top pirate.x = ship.x + (Math.random() - 0.5) * 1800; pirate.y = ship.y - 1400; break; case 1: // Right pirate.x = ship.x + 1400; pirate.y = ship.y + (Math.random() - 0.5) * 1800; break; case 2: // Bottom pirate.x = ship.x + (Math.random() - 0.5) * 1800; pirate.y = ship.y + 1400; break; case 3: // Left pirate.x = ship.x - 1400; pirate.y = ship.y + (Math.random() - 0.5) * 1800; break; } // Set pirate level and scale stats based on wave // Level range: wave 1 => 1-3, wave 2 => 3-5, wave 3 => 5-7, etc. var minLevel = 1 + waveNumber * 2; var maxLevel = minLevel + 2; pirate.level = minLevel + Math.floor(Math.random() * (maxLevel - minLevel + 1)); pirate.health = 30 + (pirate.level - 1) * 10; pirate.damage = 5 + Math.floor((pirate.level - 1) * 1.5); pirate.defense = 2 + Math.floor((pirate.level - 1) * 1.2); // Add health bar to pirate pirate._healthBar = new HealthBar(); pirate._healthBar.set({ maxValue: function maxValue() { return pirate.health > 0 ? pirate.health : 0; }, getValueFn: function getValueFn() { return pirate.health > 0 ? pirate.health : 0; }, getMaxFn: function getMaxFn() { return 30 + waveNumber * 10; }, width: 60, height: 10 }); pirate._healthBar.y = -60; pirate.addChild(pirate._healthBar); pirates.push(pirate); game.addChild(pirate); } function spawnAsteroid() { var asteroid = new Asteroid(); var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: asteroid.x = ship.x + (Math.random() - 0.5) * 2200; asteroid.y = ship.y - 1600; break; case 1: asteroid.x = ship.x + 1600; asteroid.y = ship.y + (Math.random() - 0.5) * 2200; break; case 2: asteroid.x = ship.x + (Math.random() - 0.5) * 2200; asteroid.y = ship.y + 1600; break; case 3: asteroid.x = ship.x - 1600; asteroid.y = ship.y + (Math.random() - 0.5) * 2200; break; } // Add health bar to asteroid asteroid._healthBar = new HealthBar(); asteroid._healthBar.set({ maxValue: function maxValue() { return asteroid.health; }, getValueFn: function getValueFn() { return asteroid.health; }, getMaxFn: function getMaxFn() { return 50; }, width: 50, height: 8 }); asteroid._healthBar.y = -50; asteroid.addChild(asteroid._healthBar); asteroids.push(asteroid); game.addChild(asteroid); } function spawnUpgradeStation() { var station = new UpgradeStation(); // Spawn within 700-900px of the ship, random angle var angle = Math.random() * Math.PI * 2; var dist = 700 + Math.random() * 200; // 700-900px station.x = ship.x + Math.cos(angle) * dist; station.y = ship.y + Math.sin(angle) * dist; upgradeStations.push(station); game.addChild(station); } function spawnTradeStation() { var ts = new TradeStation(); // Spawn within 700-900px of the ship, random angle var angle = Math.random() * Math.PI * 2; var dist = 700 + Math.random() * 200; // 700-900px ts.x = ship.x + Math.cos(angle) * dist; ts.y = ship.y + Math.sin(angle) * dist; tradeStations.push(ts); game.addChild(ts); } function createExplosion(x, y) { for (var i = 0; i < 8; i++) { var particle = LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5, x: x, y: y }); particle.vx = (Math.random() - 0.5) * 10; particle.vy = (Math.random() - 0.5) * 10; particle.life = 30; explosions.push(particle); game.addChild(particle); } } function spawnBlackHole() { var bh = new BlackHole(); // Spawn within 700-900px of the ship, random angle var angle = Math.random() * Math.PI * 2; var dist = 700 + Math.random() * 200; // 700-900px bh.x = ship.x + Math.cos(angle) * dist; bh.y = ship.y + Math.sin(angle) * dist; blackHoles.push(bh); game.addChild(bh); } function spawnWormhole() { var wh = new Wormhole(); // Spawn within 700-900px of the ship, random angle var angle = Math.random() * Math.PI * 2; var dist = 700 + Math.random() * 200; // 700-900px wh.x = ship.x + Math.cos(angle) * dist; wh.y = ship.y + Math.sin(angle) * dist; wormholes.push(wh); game.addChild(wh); } function createBoostParticle() { var particle = LK.getAsset('boostParticle', { anchorX: 0.5, anchorY: 0.5, x: ship.x - Math.cos(ship.rotation - Math.PI / 2) * 50, y: ship.y - Math.sin(ship.rotation - Math.PI / 2) * 50 }); particle.vx = -Math.cos(ship.rotation - Math.PI / 2) * 5 + (Math.random() - 0.5) * 2; particle.vy = -Math.sin(ship.rotation - Math.PI / 2) * 5 + (Math.random() - 0.5) * 2; particle.life = 20; boostParticles.push(particle); game.addChild(particle); } function updateUI() { coinText.setText('Coins: ' + playerCoins); resourceText.setText('Metal: ' + playerMetal + ' Energy: ' + playerEnergy); healthText.setText('Health: ' + ship.health + '/' + ship.maxHealth); shieldText.setText('Shield: ' + Math.floor(ship.shield) + '/' + ship.maxShield); waveText.setText('Wave: ' + (waveNumber + 1)); expText.setText('Level: ' + playerLevel + ' EXP: ' + playerEXP + '/' + expToNext(playerLevel)); // Show rep in GUI if (!window.repText) { window.repText = new Text2('Rep: +' + playerGoodRep + ' / -' + playerBadRep, { size: unifiedFontSize, fill: 0xffffff }); window.repText.anchor.set(1, 0); window.repText.x = -20; window.repText.y = 140; LK.gui.topRight.addChild(window.repText); } window.repText.setText('Rep: +' + playerGoodRep + ' / -' + playerBadRep); // Update health text color if (ship.health > 60) { healthText.fill = 0x00ff00; } else if (ship.health > 30) { healthText.fill = 0xffff00; } else { healthText.fill = 0xff0000; } // Update shield text color if (ship.shield > 30) { shieldText.fill = 0x0088ff; } else if (ship.shield > 10) { shieldText.fill = 0xffff00; } else { shieldText.fill = 0xff0000; } // Update boost text if (ship.boostCooldown <= 0) { boostText.setText('BOOST READY'); boostText.fill = 0x00ffff; } else { boostText.setText('BOOST: ' + Math.ceil(ship.boostCooldown / 60) + 's'); boostText.fill = 0x888888; } storage.playerLevel = playerLevel; storage.playerEXP = playerEXP; } function saveProgress() { storage.coins = playerCoins; storage.metal = playerMetal; storage.energy = playerEnergy; storage.questsCompleted = questsCompleted; storage.playerGoodRep = playerGoodRep; storage.playerBadRep = playerBadRep; } // Event handlers game.down = function (x, y, obj) { // --- RESET BUTTON HANDLER --- if (game._resetBtn && game._resetBtn.parent) { // Convert GUI coordinates for bottomRight // LK.gui.bottomRight is anchored at (1,1) so x,y are negative from bottom right var btn = game._resetBtn; var bx = btn.x, by = btn.y; // Button is about 180x80 px, but let's use a safe area // Since anchor is (1,1), bottom right, and x/y are negative from bottom right // So, for a tap, check if x is within 200px of right edge and y within 100px of bottom // LK.gui.bottomRight: x=0,y=0 is bottom right, so x,y negative if (x > 2048 - 200 && y > 2732 - 100) { // Clear all persistent storage storage.coins = 0; storage.metal = 0; storage.energy = 0; storage.questsCompleted = 0; storage.playerLevel = 1; storage.playerEXP = 0; storage.playerGoodRep = 0; storage.playerBadRep = 0; // Optionally clear any other custom progress keys // Show a quick feedback btn.setText("Reset!"); btn.fill = 0x00ff99; // Reload game (reset all progress) LK.showGameOver(); return; } } // Mini Map button tap handler removed if (window.repairPanel && window.repairBtn && window.repairBtn.parent) { // Check tap on repair button var btn = window.repairBtn; var bx = btn.x, by = btn.y; if (x > bx - 90 && x < bx + 90 && y > by - 40 && y < by + 40) { // Try to repair var costCoins = btn._repairCostCoins, costMetal = btn._repairCostMetal, costEnergy = btn._repairCostEnergy; if (playerCoins >= costCoins && playerMetal >= costMetal && playerEnergy >= costEnergy) { playerCoins -= costCoins; playerMetal -= costMetal; playerEnergy -= costEnergy; ship.health = ship.maxHealth; updateUI(); saveProgress(); // Show feedback btn.setText("Tamir Edildi!"); btn.fill = 0x00ffcc; // Remove panel after short delay var expire = LK.ticks + 40; var origUpdate = game.update; game.update = function () { if (LK.ticks > expire) { if (window.repairPanel && window.repairPanel.parent) window.repairPanel.parent.removeChild(window.repairPanel); if (window.repairText && window.repairText.parent) window.repairText.parent.removeChild(window.repairText); if (window.repairBtn && window.repairBtn.parent) window.repairBtn.parent.removeChild(window.repairBtn); if (window.cancelRepairBtn && window.cancelRepairBtn.parent) window.cancelRepairBtn.parent.removeChild(window.cancelRepairBtn); window.repairPanel = null; window.repairText = null; window.repairBtn = null; window.cancelRepairBtn = null; game.update = origUpdate; } if (origUpdate) origUpdate.apply(game, arguments); }; } else { // Not enough resources btn.setText("Yetersiz kaynak!"); btn.fill = 0xff4444; } return; } // Check tap on cancel button var cbtn = window.cancelRepairBtn; var cbx = cbtn.x, cby = cbtn.y; if (x > cbx - 90 && x < cbx + 90 && y > cby - 40 && y < cby + 40) { if (window.repairPanel.parent) window.repairPanel.parent.removeChild(window.repairPanel); if (window.repairText && window.repairText.parent) window.repairText.parent.removeChild(window.repairText); if (window.repairBtn && window.repairBtn.parent) window.repairBtn.parent.removeChild(window.repairBtn); if (window.cancelRepairBtn && window.cancelRepairBtn.parent) window.cancelRepairBtn.parent.removeChild(window.cancelRepairBtn); window.repairPanel = null; window.repairText = null; window.repairBtn = null; window.cancelRepairBtn = null; return; } } // --- Health bar tap to show repair panel --- if (healthText && healthText.parent && healthText._isHealthBar && ship.health < ship.maxHealth && ship.health > 0) { // Get healthText bounds in screen coordinates // healthText is anchored at (0.5, 0), at top center // Let's estimate its bounds var hx = healthText.x, hy = healthText.y; var hw = healthText.width || 300; var hh = healthText.height || 60; // Accept generous tap area if (x > hx - hw / 2 && x < hx + hw / 2 && y > hy && y < hy + hh) { window._showRepairPanel = true; return; } } // --- SHIP TAP: Show upgrade/can-buy-health panel --- if (ship && ship.parent) { // Ship is at (ship.x, ship.y), size is 80x100 (see asset) var sx = ship.x, sy = ship.y; var sw = 80, sh = 100; // Accept generous tap area if (x > sx - sw / 2 && x < sx + sw / 2 && y > sy - sh / 2 && y < sy + sh / 2) { // Only show if not already shown if (!window.shipUpgradePanel) { // Panel background // --- DYNAMIC PANEL SIZE BASED ON CONTENT --- var upgBtnFont = unifiedFontSize; var upgBtnWidth = 340; var upgBtnHeight = 90; var colSpacing = 80; var colXOffset = upgBtnWidth / 2 + colSpacing / 2; var upgBtnSpacingY = 140; var numUpgradeRows = 4; // 3 upgrade rows + 1 buy health row var panelContentHeight = 100 + numUpgradeRows * upgBtnSpacingY + 2 * upgBtnHeight; // title + upgrades + buy health + speed + some margin var panelContentWidth = upgBtnWidth * 2 + colSpacing + 80; // two columns + spacing + margin // Add extra for speed upgrade and close button panelContentHeight += upgBtnSpacingY + 60; // speed upgrade + close btn margin // Clamp min/max var panelWidth = Math.max(700, Math.round(panelContentWidth)); var panelHeight = Math.max(340, Math.round(panelContentHeight)); var panel = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, x: sx, y: sy - 220, scaleX: panelWidth / 40, // asset is 40px wide scaleY: panelHeight / 40, // asset is 40px tall tint: 0x224488 }); // Title var titleFont = Math.round(62 * 1.1); var title = new Text2("Yükseltmeler & Can Satın Al", { size: titleFont, fill: 0xffffff, align: "center" }); title.anchor.set(0.5, 0.5); title.x = sx; title.y = sy - 220 - panelHeight / 2 + 100; // Upgrade buttons, dikeyde aralıklı ve panelin içine sığacak şekilde var upgBtnY = title.y + 110; var upgBtnSpacingY = 140; // Paneldeki yazı ve butonların font boyutunu, Wave font boyutu ile aynı yap var upgBtnFont = unifiedFontSize; var upgBtnWidth = 340; var upgBtnHeight = 90; var colSpacing = 80; var colXOffset = upgBtnWidth / 2 + colSpacing / 2; // Normal upgrades var upg1 = new Text2("Max Can +20\n(100 coin, 10 metal)", { size: upgBtnFont, fill: 0x00ff99, align: "center" }); upg1.anchor.set(0.5, 0.5); upg1.x = sx - colXOffset; upg1.y = upgBtnY; upg1._isShipUpgradeBtn = true; upg1._upgradeType = "maxHealth"; upg1._upgradeCost = { coins: 100, metal: 10, energy: 0 }; var upg1x2 = new Text2("Max Can +20\n(200 coin, 20 metal)", { size: upgBtnFont, fill: 0x00cc99, align: "center" }); upg1x2.anchor.set(0.5, 0.5); upg1x2.x = sx + colXOffset; upg1x2.y = upgBtnY; upg1x2._isShipUpgradeBtn = true; upg1x2._upgradeType = "maxHealth"; upg1x2._upgradeCost = { coins: 200, metal: 20, energy: 0 }; upg1x2._isDoubleCost = true; var upg2 = new Text2("Max Kalkan +10\n(120 coin, 12 metal)", { size: upgBtnFont, fill: 0x00ccff, align: "center" }); upg2.anchor.set(0.5, 0.5); upg2.x = sx - colXOffset; upg2.y = upgBtnY + upgBtnSpacingY; upg2._isShipUpgradeBtn = true; upg2._upgradeType = "maxShield"; upg2._upgradeCost = { coins: 120, metal: 12, energy: 0 }; var upg2x2 = new Text2("Max Kalkan +10\n(240 coin, 24 metal)", { size: upgBtnFont, fill: 0x00aaff, align: "center" }); upg2x2.anchor.set(0.5, 0.5); upg2x2.x = sx + colXOffset; upg2x2.y = upgBtnY + upgBtnSpacingY; upg2x2._isShipUpgradeBtn = true; upg2x2._upgradeType = "maxShield"; upg2x2._upgradeCost = { coins: 240, metal: 24, energy: 0 }; upg2x2._isDoubleCost = true; var upg3 = new Text2("Hasar +5\n(150 coin, 15 enerji)", { size: upgBtnFont, fill: 0xffcc00, align: "center" }); upg3.anchor.set(0.5, 0.5); upg3.x = sx - colXOffset; upg3.y = upgBtnY + upgBtnSpacingY * 2; upg3._isShipUpgradeBtn = true; upg3._upgradeType = "damage"; upg3._upgradeCost = { coins: 150, metal: 0, energy: 15 }; var upg3x2 = new Text2("Hasar +5\n(300 coin, 30 enerji)", { size: upgBtnFont, fill: 0xff9900, align: "center" }); upg3x2.anchor.set(0.5, 0.5); upg3x2.x = sx + colXOffset; upg3x2.y = upgBtnY + upgBtnSpacingY * 2; upg3x2._isShipUpgradeBtn = true; upg3x2._upgradeType = "damage"; upg3x2._upgradeCost = { coins: 300, metal: 0, energy: 30 }; upg3x2._isDoubleCost = true; // Buy health button (if not full) var canBuyHealth = ship.health < ship.maxHealth; var buyHealthBtnFont = unifiedFontSize; // Proportional cost scaling for buy health button var healthToRestore = ship.maxHealth - ship.health; var baseFullRepairHealth = 60; var baseCoinCost = 90; var baseMetalCost = 6; var baseEnergyCost = 6; var buyHealthCostCoins = Math.max(30, Math.round(baseCoinCost * (healthToRestore / baseFullRepairHealth))); var buyHealthCostMetal = Math.max(2, Math.round(baseMetalCost * (healthToRestore / baseFullRepairHealth))); var buyHealthCostEnergy = Math.max(2, Math.round(baseEnergyCost * (healthToRestore / baseFullRepairHealth))); var buyHealthBtn = new Text2("Canı Doldur (" + buyHealthCostCoins + " coin, " + buyHealthCostMetal + " metal, " + buyHealthCostEnergy + " enerji)", { size: buyHealthBtnFont, fill: canBuyHealth ? 0x00ffcc : 0x888888, align: "center" }); buyHealthBtn.anchor.set(0.5, 0.5); buyHealthBtn.x = sx; buyHealthBtn.y = upgBtnY + upgBtnSpacingY * 3 + 30; buyHealthBtn._isShipBuyHealthBtn = true; buyHealthBtn._repairCostCoins = buyHealthCostCoins; buyHealthBtn._repairCostMetal = buyHealthCostMetal; buyHealthBtn._repairCostEnergy = buyHealthCostEnergy; // Speed upgrade button (bottom of panel) var speedUpgLevel = window.shipSpeedUpgradeLevel || 0; var speedUpgFont = unifiedFontSize; var speedUpgCost = 120 + speedUpgLevel * 60; var speedUpgBtn = new Text2("Hız +" + Math.round((speedUpgLevel + 1) * 10) + "%\n(" + speedUpgCost + " coin)", { size: speedUpgFont, fill: 0x00ffff, align: "center" }); speedUpgBtn.anchor.set(0.5, 0.5); speedUpgBtn.x = sx; speedUpgBtn.y = buyHealthBtn.y + upgBtnSpacingY; speedUpgBtn._isShipSpeedUpgradeBtn = true; speedUpgBtn._speedUpgradeLevel = speedUpgLevel; speedUpgBtn._speedUpgradeCost = speedUpgCost; // Close button var closeBtnFont = unifiedFontSize; var closeBtn = new Text2("Kapat", { size: closeBtnFont, fill: 0xff4444, align: "center" }); closeBtn.anchor.set(0.5, 0.5); // Move close button above the panel title, with extra margin closeBtn.x = sx; closeBtn.y = title.y - 90; closeBtn._isShipUpgradeCloseBtn = true; // Add to game game.addChild(panel); game.addChild(title); game.addChild(upg1); game.addChild(upg1x2); game.addChild(upg2); game.addChild(upg2x2); game.addChild(upg3); game.addChild(upg3x2); game.addChild(buyHealthBtn); game.addChild(speedUpgBtn); game.addChild(closeBtn); // Store refs for tap logic/cleanup window.shipUpgradePanel = panel; window.shipUpgradeTitle = title; window.shipUpgradeBtn1 = upg1; window.shipUpgradeBtn1x2 = upg1x2; window.shipUpgradeBtn2 = upg2; window.shipUpgradeBtn2x2 = upg2x2; window.shipUpgradeBtn3 = upg3; window.shipUpgradeBtn3x2 = upg3x2; window.shipBuyHealthBtn = buyHealthBtn; window.shipSpeedUpgradeBtn = speedUpgBtn; window.shipUpgradeCloseBtn = closeBtn; } return; } } if (Math.sqrt(Math.pow(x - joystickBase.x, 2) + Math.pow(y - joystickBase.y, 2)) < 100) { isDragging = true; joystickHandle.x = x; joystickHandle.y = y; } else if (y < 300 && ship.boostCooldown <= 0) { ship.boostSpeed = 10; ship.boostCooldown = 300; // 5 seconds cooldown if (LK.getSound('boost')) { LK.getSound('boost').play(); } } else { // --- SHIP UPGRADE PANEL BUTTONS --- if (window.shipUpgradePanel) { // Upgrade buttons var btns = [window.shipUpgradeBtn1, window.shipUpgradeBtn1x2, window.shipUpgradeBtn2, window.shipUpgradeBtn2x2, window.shipUpgradeBtn3, window.shipUpgradeBtn3x2]; for (var i = 0; i < btns.length; i++) { var btn = btns[i]; if (!btn) continue; var bx = btn.x, by = btn.y; if (x > bx - 120 && x < bx + 120 && y > by - 50 && y < by + 50) { // Try to buy upgrade var upg = btn._upgradeType; var cost = btn._upgradeCost; var isDouble = !!btn._isDoubleCost; if (upg === "maxHealth" && playerCoins >= cost.coins && playerMetal >= cost.metal) { ship.maxHealth += 20; ship.health = ship.maxHealth; playerCoins -= cost.coins; playerMetal -= cost.metal; LK.effects.flashObject(ship, isDouble ? 0x00cc99 : 0x00ff99, 400); btn.setText("Alındı!"); btn.fill = 0x00ffcc; updateUI(); saveProgress(); } else if (upg === "maxShield" && playerCoins >= cost.coins && playerMetal >= cost.metal) { ship.maxShield += 10; ship.shield = ship.maxShield; playerCoins -= cost.coins; playerMetal -= cost.metal; LK.effects.flashObject(ship, isDouble ? 0x00aaff : 0x00ccff, 400); btn.setText("Alındı!"); btn.fill = 0x00ffcc; updateUI(); saveProgress(); } else if (upg === "damage" && playerCoins >= cost.coins && playerEnergy >= cost.energy) { ship.damage += 5; playerCoins -= cost.coins; playerEnergy -= cost.energy; LK.effects.flashObject(ship, isDouble ? 0xff9900 : 0xffcc00, 400); btn.setText("Alındı!"); btn.fill = 0x00ffcc; updateUI(); saveProgress(); } else { btn.setText("Yetersiz kaynak!"); btn.fill = 0xff4444; } return; } } // Buy health button var bhb = window.shipBuyHealthBtn; if (bhb) { var bx = bhb.x, by = bhb.y; if (x > bx - 180 && x < bx + 180 && y > by - 50 && y < by + 50) { if (ship.health < ship.maxHealth) { var costCoins = bhb._repairCostCoins, costMetal = bhb._repairCostMetal, costEnergy = bhb._repairCostEnergy; if (playerCoins >= costCoins && playerMetal >= costMetal && playerEnergy >= costEnergy) { playerCoins -= costCoins; playerMetal -= costMetal; playerEnergy -= costEnergy; ship.health = ship.maxHealth; updateUI(); saveProgress(); bhb.setText("Can Dolduruldu!"); bhb.fill = 0x00ffcc; } else { bhb.setText("Yetersiz kaynak!"); bhb.fill = 0xff4444; } } else { bhb.setText("Can zaten tam!"); bhb.fill = 0x888888; } return; } } // Speed upgrade button var sub = window.shipSpeedUpgradeBtn; if (sub) { var bx = sub.x, by = sub.y; if (x > bx - 180 && x < bx + 180 && y > by - 50 && y < by + 50) { var level = window.shipSpeedUpgradeLevel || 0; var cost = 120 + level * 60; if (playerCoins >= cost) { playerCoins -= cost; level++; window.shipSpeedUpgradeLevel = level; // Each level increases speed by 10% (multiplicative) ship.speed = Math.round(ship.speed * Math.pow(1.1, 1) * 100) / 100; sub.setText("Alındı! +" + level * 10 + "%"); sub.fill = 0x00ffcc; LK.effects.flashObject(ship, 0x00ffff, 400); updateUI(); saveProgress(); } else { sub.setText("Yetersiz coin!"); sub.fill = 0xff4444; } return; } } // Close button var cb = window.shipUpgradeCloseBtn; if (cb) { var bx = cb.x, by = cb.y; if (x > bx - 120 && x < bx + 120 && y > by - 50 && y < by + 50) { // Remove all panel elements if (window.shipUpgradePanel && window.shipUpgradePanel.parent) window.shipUpgradePanel.parent.removeChild(window.shipUpgradePanel); if (window.shipUpgradeTitle && window.shipUpgradeTitle.parent) window.shipUpgradeTitle.parent.removeChild(window.shipUpgradeTitle); if (window.shipUpgradeBtn1 && window.shipUpgradeBtn1.parent) window.shipUpgradeBtn1.parent.removeChild(window.shipUpgradeBtn1); if (window.shipUpgradeBtn1x2 && window.shipUpgradeBtn1x2.parent) window.shipUpgradeBtn1x2.parent.removeChild(window.shipUpgradeBtn1x2); if (window.shipUpgradeBtn2 && window.shipUpgradeBtn2.parent) window.shipUpgradeBtn2.parent.removeChild(window.shipUpgradeBtn2); if (window.shipUpgradeBtn2x2 && window.shipUpgradeBtn2x2.parent) window.shipUpgradeBtn2x2.parent.removeChild(window.shipUpgradeBtn2x2); if (window.shipUpgradeBtn3 && window.shipUpgradeBtn3.parent) window.shipUpgradeBtn3.parent.removeChild(window.shipUpgradeBtn3); if (window.shipUpgradeBtn3x2 && window.shipUpgradeBtn3x2.parent) window.shipUpgradeBtn3x2.parent.removeChild(window.shipUpgradeBtn3x2); if (window.shipBuyHealthBtn && window.shipBuyHealthBtn.parent) window.shipBuyHealthBtn.parent.removeChild(window.shipBuyHealthBtn); if (window.shipSpeedUpgradeBtn && window.shipSpeedUpgradeBtn.parent) window.shipSpeedUpgradeBtn.parent.removeChild(window.shipSpeedUpgradeBtn); if (window.shipUpgradeCloseBtn && window.shipUpgradeCloseBtn.parent) window.shipUpgradeCloseBtn.parent.removeChild(window.shipUpgradeCloseBtn); // Hide all upgrade panel texts window.shipUpgradePanel = null; window.shipUpgradeTitle = null; window.shipUpgradeBtn1 = null; window.shipUpgradeBtn1x2 = null; window.shipUpgradeBtn2 = null; window.shipUpgradeBtn2x2 = null; window.shipUpgradeBtn3 = null; window.shipUpgradeBtn3x2 = null; window.shipBuyHealthBtn = null; window.shipSpeedUpgradeBtn = null; window.shipUpgradeCloseBtn = null; return; } } } // --- Handle Accept/Reject quest button taps --- if (game._questDecisionAcceptBtn && game._questDecisionAcceptBtn.parent) { var btn = game._questDecisionAcceptBtn; var bx = btn.x, by = btn.y; // Button is about 180x80 px if (x > bx - 90 && x < bx + 90 && y > by - 40 && y < by + 40) { // Accept quest var npc = btn._questNPC; if (npc) { // Defend quest özel: yardım kabul edildi if (npc.questType === 'defend') { npc._defendHelpAccepted = true; // Show floating label for accepted var acceptLabel = new Text2("Yardım kabul edildi!", { size: 36, fill: 0x00ff99, align: "center" }); acceptLabel.anchor.set(0.5, 0.5); acceptLabel.x = npc.x; acceptLabel.y = npc.y + 110; game.addChild(acceptLabel); npc._npcInteractionLabel = acceptLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc.pauseUntil = LK.ticks + 120; npc._npcText && npc._npcText.parent && npc._npcText.parent.removeChild(npc._npcText); npc._npcText = new Text2(npc.rpgName + ": Teşekkürler! Beni korsanlardan koru!", { size: 32, fill: 0x00ffcc, align: "center" }); npc._npcText.anchor.set(0.5, 1); npc._npcText.x = npc.x; npc._npcText.y = npc.y - 70; game.addChild(npc._npcText); } else { // Mark quest as accepted (progress 1 means started) npc.questProgress = 1; // Show NPC response var acceptLabel = new Text2("Görev kabul edildi!", { size: 36, fill: 0x00ff99, align: "center" }); acceptLabel.anchor.set(0.5, 0.5); acceptLabel.x = npc.x; acceptLabel.y = npc.y + 110; game.addChild(acceptLabel); npc._npcInteractionLabel = acceptLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc.pauseUntil = LK.ticks + 120; npc._npcText && npc._npcText.parent && npc._npcText.parent.removeChild(npc._npcText); npc._npcText = new Text2(npc.rpgName + ": Harika! Görev başladı.", { size: 32, fill: 0x00ffcc, align: "center" }); npc._npcText.anchor.set(0.5, 1); npc._npcText.x = npc.x; npc._npcText.y = npc.y - 70; game.addChild(npc._npcText); } // Remove quest panel if (npc._questDecisionPanel && npc._questDecisionPanel.parent) npc._questDecisionPanel.parent.removeChild(npc._questDecisionPanel); if (npc._questDecisionText && npc._questDecisionText.parent) npc._questDecisionText.parent.removeChild(npc._questDecisionText); if (npc._questDecisionAcceptBtn && npc._questDecisionAcceptBtn.parent) npc._questDecisionAcceptBtn.parent.removeChild(npc._questDecisionAcceptBtn); if (npc._questDecisionRejectBtn && npc._questDecisionRejectBtn.parent) npc._questDecisionRejectBtn.parent.removeChild(npc._questDecisionRejectBtn); npc._questDecisionPanel = null; npc._questDecisionText = null; npc._questDecisionAcceptBtn = null; npc._questDecisionRejectBtn = null; game._questDecisionPanel = null; game._questDecisionAcceptBtn = null; game._questDecisionRejectBtn = null; game._questDecisionText = null; game._questDecisionNPC = null; } return; } } if (game._questDecisionRejectBtn && game._questDecisionRejectBtn.parent) { var btn = game._questDecisionRejectBtn; var bx = btn.x, by = btn.y; if (x > bx - 90 && x < bx + 90 && y > by - 40 && y < by + 40) { // Reject quest var npc = btn._questNPC; if (npc) { if (npc.questType === 'defend') { npc._defendHelpAccepted = false; // Show floating label for rejected var rejectLabel = new Text2("Yardım edilmedi.", { size: 36, fill: 0xff4444, align: "center" }); rejectLabel.anchor.set(0.5, 0.5); rejectLabel.x = npc.x; rejectLabel.y = npc.y + 110; game.addChild(rejectLabel); npc._npcInteractionLabel = rejectLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc.pauseUntil = LK.ticks + 120; npc._npcText && npc._npcText.parent && npc._npcText.parent.removeChild(npc._npcText); npc._npcText = new Text2(npc.rpgName + ": Anlaşıldı, kendi başıma savaşacağım!", { size: 32, fill: 0x00ffcc, align: "center" }); npc._npcText.anchor.set(0.5, 1); npc._npcText.x = npc.x; npc._npcText.y = npc.y - 70; game.addChild(npc._npcText); } else { // Mark quest as inactive npc.questActive = false; // Show floating label for rejected var rejectLabel = new Text2("Görev reddedildi.", { size: 36, fill: 0xff4444, align: "center" }); rejectLabel.anchor.set(0.5, 0.5); rejectLabel.x = npc.x; rejectLabel.y = npc.y + 110; game.addChild(rejectLabel); npc._npcInteractionLabel = rejectLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc.pauseUntil = LK.ticks + 120; npc._npcText && npc._npcText.parent && npc._npcText.parent.removeChild(npc._npcText); npc._npcText = new Text2(npc.rpgName + ": Belki başka zaman!", { size: 32, fill: 0x00ffcc, align: "center" }); npc._npcText.anchor.set(0.5, 1); npc._npcText.x = npc.x; npc._npcText.y = npc.y - 70; game.addChild(npc._npcText); } // Remove quest panel if (npc._questDecisionPanel && npc._questDecisionPanel.parent) npc._questDecisionPanel.parent.removeChild(npc._questDecisionPanel); if (npc._questDecisionText && npc._questDecisionText.parent) npc._questDecisionText.parent.removeChild(npc._questDecisionText); if (npc._questDecisionAcceptBtn && npc._questDecisionAcceptBtn.parent) npc._questDecisionAcceptBtn.parent.removeChild(npc._questDecisionAcceptBtn); if (npc._questDecisionRejectBtn && npc._questDecisionRejectBtn.parent) npc._questDecisionRejectBtn.parent.removeChild(npc._questDecisionRejectBtn); npc._questDecisionPanel = null; npc._questDecisionText = null; npc._questDecisionAcceptBtn = null; npc._questDecisionRejectBtn = null; game._questDecisionPanel = null; game._questDecisionAcceptBtn = null; game._questDecisionRejectBtn = null; game._questDecisionText = null; game._questDecisionNPC = null; } return; } } // Check for NPC tap (RPG/adventure/trade) for (var i = 0; i < npcs.length; i++) { var npc = npcs[i]; var dist = Math.sqrt(Math.pow(npc.x - ship.x, 2) + Math.pow(npc.y - ship.y, 2)); if (dist < 180) { game._lastNPCTap = LK.ticks; break; } } // --- Distress event tap detection --- if (window.distressEvent && window.distressEvent.helpBtn && window.distressEvent.ignoreBtn) { game._lastDistressTapTick = LK.ticks; game._lastDistressTapX = x; game._lastDistressTapY = y; } } }; game.move = function (x, y, obj) { if (isDragging) { var dx = x - joystickBase.x; var dy = y - joystickBase.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 100) { dx = dx / distance * 100; dy = dy / distance * 100; } joystickHandle.x = joystickBase.x + dx; joystickHandle.y = joystickBase.y + dy; } }; game.up = function (x, y, obj) { isDragging = false; joystickHandle.x = joystickBase.x; joystickHandle.y = joystickBase.y; }; // Main game loop game.update = function () { // Ship movement var shipDX = 0; var shipDY = 0; if (isDragging) { var dx = joystickHandle.x - joystickBase.x; var dy = joystickHandle.y - joystickBase.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 10) { var effectiveSpeed = ship.speed + ship.boostSpeed; shipDX = dx / 100 * effectiveSpeed; shipDY = dy / 100 * effectiveSpeed; ship.rotation = Math.atan2(dy, dx) + Math.PI / 2; // Create boost particles when boosting if (ship.boostSpeed > 0 && LK.ticks % 2 === 0) { createBoostParticle(); } } } // Track total distance traveled totalDistance += Math.sqrt(shipDX * shipDX + shipDY * shipDY); // Update camera to follow ship movement camera.x += shipDX; camera.y += shipDY; // Move all world objects opposite to ship movement to create camera effect for (var i = 0; i < stars.length; i++) { stars[i].x -= shipDX; stars[i].y -= shipDY; } for (var i = 0; i < npcs.length; i++) { npcs[i].x -= shipDX; npcs[i].y -= shipDY; } for (var i = 0; i < pirates.length; i++) { pirates[i].x -= shipDX; pirates[i].y -= shipDY; } for (var i = 0; i < coins.length; i++) { coins[i].x -= shipDX; coins[i].y -= shipDY; } for (var i = 0; i < resources.length; i++) { resources[i].x -= shipDX; resources[i].y -= shipDY; } for (var i = 0; i < bullets.length; i++) { bullets[i].x -= shipDX; bullets[i].y -= shipDY; } for (var i = 0; i < enemyBullets.length; i++) { enemyBullets[i].x -= shipDX; enemyBullets[i].y -= shipDY; } for (var i = 0; i < asteroids.length; i++) { asteroids[i].x -= shipDX; asteroids[i].y -= shipDY; } for (var i = 0; i < upgradeStations.length; i++) { upgradeStations[i].x -= shipDX; upgradeStations[i].y -= shipDY; } for (var i = 0; i < boostParticles.length; i++) { boostParticles[i].x -= shipDX; boostParticles[i].y -= shipDY; } for (var i = 0; i < explosions.length; i++) { explosions[i].x -= shipDX; explosions[i].y -= shipDY; } // (Removed camera-follow for event and quest objects so they stay at their spawn location) // Auto fire at very close pirates or asteroids // Saldırı mesafesi %10 arttırıldı (200 -> 220) var ATTACK_RANGE = 220; if (LK.ticks - ship.lastFire > ship.fireRate && (pirates.length > 0 || asteroids.length > 0)) { // Find nearest pirate or asteroid within 220 pixels var nearestTarget = null; var nearestDistance = Infinity; var isPirate = false; // Check pirates for (var i = 0; i < pirates.length; i++) { var dist = Math.sqrt(Math.pow(pirates[i].x - ship.x, 2) + Math.pow(pirates[i].y - ship.y, 2)); if (dist < ATTACK_RANGE && dist < nearestDistance) { nearestDistance = dist; nearestTarget = pirates[i]; isPirate = true; } } // Check asteroids for (var i = 0; i < asteroids.length; i++) { var dist = Math.sqrt(Math.pow(asteroids[i].x - ship.x, 2) + Math.pow(asteroids[i].y - ship.y, 2)); if (dist < ATTACK_RANGE && dist < nearestDistance) { nearestDistance = dist; nearestTarget = asteroids[i]; isPirate = false; } } if (nearestTarget) { var bullet = new Bullet(); bullet.x = ship.x; bullet.y = ship.y; var angle = Math.atan2(nearestTarget.y - ship.y, nearestTarget.x - ship.x); bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullet.rotation = angle + Math.PI / 2; bullets.push(bullet); game.addChild(bullet); ship.lastFire = LK.ticks; LK.getSound('shoot').play(); } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check collision with pirates for (var j = pirates.length - 1; j >= 0; j--) { if (bullet.intersects(pirates[j])) { pirates[j].takeDamage(bullet.damage); var killedByPlayer = !bullet._npcBullet; var killedByNPC = !!bullet._npcBullet; if (pirates[j].health <= 0) { enemiesKilled++; createExplosion(pirates[j].x, pirates[j].y); // Drop loot var coin = new Coin(); coin.x = pirates[j].x; coin.y = pirates[j].y; coin.value = coin.value * (1 + Math.floor(waveNumber / 3)); coins.push(coin); game.addChild(coin); if (Math.random() < 0.3) { var resource = new Resource(); resource.x = pirates[j].x + (Math.random() - 0.5) * 50; resource.y = pirates[j].y + (Math.random() - 0.5) * 50; resources.push(resource); game.addChild(resource); } // Remove KILL label after 2 seconds if present if (pirates[j]._killLabel) { // If not already expiring, set expire tick if (!pirates[j]._killLabel._expireTick) { pirates[j]._killLabel._expireTick = LK.ticks + 120; } } // Remove KILL label if expired if (pirates[j]._killLabel && pirates[j]._killLabel._expireTick && LK.ticks > pirates[j]._killLabel._expireTick) { if (pirates[j]._killLabel.parent) pirates[j]._killLabel.parent.removeChild(pirates[j]._killLabel); pirates[j]._killLabel = null; } if (killedByPlayer) { // Oyuncu öldürdü: +rep ve exp playerGoodRep += 1; var pirateExp = 3 + Math.floor(Math.random() * 3); playerEXP += pirateExp; // Rep/exp etiketi gösterme, tamamen kaldırıldı } else if (killedByNPC) { // NPC öldürdü: yoluna devam etsin, rep/exp yok // Kısa bir etiket göster (isteğe bağlı) var npcLabel = new Text2("NPC KILL", { size: 28, fill: 0xccccff, align: "center" }); npcLabel.anchor.set(0.5, 0.5); npcLabel.x = pirates[j].x; npcLabel.y = pirates[j].y - 80; game.addChild(npcLabel); (function (lbl) { var expire = LK.ticks + 40; var origUpdate = game.update; game.update = function () { if (LK.ticks > expire && lbl.parent) { lbl.parent.removeChild(lbl); game.update = origUpdate; } if (origUpdate) origUpdate.apply(game, arguments); }; })(npcLabel); } // Level up if enough EXP while (playerEXP >= expToNext(playerLevel)) { playerEXP -= expToNext(playerLevel); playerLevel++; LK.effects.flashObject(ship, 0x00ffcc, 800); } // Update UI after EXP gain updateUI(); pirates[j].destroy(); pirates.splice(j, 1); // Check for wave completion if (enemiesKilled >= 10 + waveNumber * 5) { waveNumber++; enemiesKilled = 0; // Spawn upgrade station every 3 waves if (waveNumber % 3 === 0) { spawnUpgradeStation(); } } } bullet.destroy(); bullets.splice(i, 1); LK.getSound('hit').play(); break; } } // Check collision with asteroids for (var j = asteroids.length - 1; j >= 0; j--) { if (bullet.intersects(asteroids[j])) { asteroids[j].takeDamage(bullet.damage); if (asteroids[j].health <= 0) { // Drop multiple resources for (var k = 0; k < asteroids[j].resources; k++) { var resource = new Resource(); resource.x = asteroids[j].x + (Math.random() - 0.5) * 100; resource.y = asteroids[j].y + (Math.random() - 0.5) * 100; resource.amount = Math.floor(Math.random() * 3) + 1; resources.push(resource); game.addChild(resource); } createExplosion(asteroids[j].x, asteroids[j].y); asteroids[j].destroy(); asteroids.splice(j, 1); } bullet.destroy(); bullets.splice(i, 1); LK.getSound('hit').play(); break; } } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); enemyBullets.splice(i, 1); continue; } if (bullet.intersects(ship)) { ship.takeDamage(bullet.damage); updateUI(); bullet.destroy(); enemyBullets.splice(i, 1); LK.getSound('hit').play(); } } // Update pirates for (var i = 0; i < pirates.length; i++) { var pirate = pirates[i]; if (pirate._healthBar && pirate._healthBar.update) pirate._healthBar.update(); // Rep/exp label logic removed: no rep/exp label is created or cleaned up // --- Show "KILL" label above quest target pirate for hunt quests --- // (KILL etiketi tamamen kaldırıldı) // Update pirate AI var dist = Math.sqrt(Math.pow(ship.x - pirate.x, 2) + Math.pow(ship.y - pirate.y, 2)); // Eğer bir NPC'nin hunt görevi varsa ve bu korsan hedefse, birlikte saldırı efekti var huntedByNPC = false; for (var n = 0; n < npcs.length; n++) { var npc = npcs[n]; if (npc.questType === 'hunt' && npc.questActive && npc.questTarget === pirate && !pirate._destroyed) { huntedByNPC = true; // NPC'nin saldırı animasyonu için efekt if (!pirate._lastHuntFlash || LK.ticks - pirate._lastHuntFlash > 30) { LK.effects.flashObject(pirate, 0xffcccc, 100); pirate._lastHuntFlash = LK.ticks; } // Eğer oyuncu da yakınsa, korsan hem NPC'ye hem oyuncuya saldırabilir var distToNPC = Math.sqrt(Math.pow(npc.x - pirate.x, 2) + Math.pow(npc.y - pirate.y, 2)); if (distToNPC < 200 && dist < 200) { // Rastgele oyuncuya veya NPC'ye saldır var target = Math.random() < 0.5 ? ship : npc; var angle = Math.atan2(target.y - pirate.y, target.x - pirate.x); pirate.x += Math.cos(angle) * pirate.speed; pirate.y += Math.sin(angle) * pirate.speed; pirate.rotation = angle + Math.PI / 2; // Pirate shooting if (LK.ticks - pirate.lastFire > pirate.fireRate) { var bullet = new EnemyBullet(); bullet.x = pirate.x; bullet.y = pirate.y; bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); enemyBullets.push(bullet); game.addChild(bullet); pirate.lastFire = LK.ticks; } continue; } } } // Only chase and attack when very close (within 220 pixels) // Saldırı mesafesi %10 arttırıldı (200 -> 220) if (!huntedByNPC && dist < 220) { // Chase ship when very close var angle = Math.atan2(ship.y - pirate.y, ship.x - pirate.x); pirate.x += Math.cos(angle) * pirate.speed; pirate.y += Math.sin(angle) * pirate.speed; pirate.rotation = angle + Math.PI / 2; // Pirate shooting when very close if (LK.ticks - pirate.lastFire > pirate.fireRate) { var bullet = new EnemyBullet(); bullet.x = pirate.x; bullet.y = pirate.y; bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); enemyBullets.push(bullet); game.addChild(bullet); pirate.lastFire = LK.ticks; } } if (dist > 2000) { pirate.destroy(); pirates.splice(i, 1); i--; } } // Update NPCs for (var i = npcs.length - 1; i >= 0; i--) { var npc = npcs[i]; if (npc._healthBar && npc._healthBar.update) npc._healthBar.update(); // Remove NPCs that are too far away var dist = Math.sqrt(Math.pow(npc.x - ship.x, 2) + Math.pow(npc.y - ship.y, 2)); if (dist > 2500) { npc.destroy(); npcs.splice(i, 1); continue; } // Remove any floating text if player is not close if (npc._npcText && npc._npcText.parent) { npc._npcText.parent.removeChild(npc._npcText); npc._npcText = null; } // --- NPC AI: Attack pirates sometimes --- // Only if there are pirates and not already targeting one if (!npc._aiTargetPirate || npc._aiTargetPirate._destroyed) { // %20 ihtimalle yeni hedef seçsin if (pirates.length > 0 && Math.random() < 0.20) { // En yakın korsanı bul var minDist = Infinity; var targetPirate = null; for (var j = 0; j < pirates.length; j++) { var p = pirates[j]; if (p._destroyed) continue; var d = Math.sqrt(Math.pow(p.x - npc.x, 2) + Math.pow(p.y - npc.y, 2)); if (d < minDist) { minDist = d; targetPirate = p; } } if (targetPirate && minDist < 800) { npc._aiTargetPirate = targetPirate; npc._aiAttackTimer = 0; } } } // Saldırıya geçtiyse, hedefe yaklaş ve ateş et if (npc._aiTargetPirate && !npc._aiTargetPirate._destroyed) { var tp = npc._aiTargetPirate; var dx = tp.x - npc.x; var dy = tp.y - npc.y; var d = Math.sqrt(dx * dx + dy * dy); // Yaklaş if (d > 120) { npc.x += dx / d * npc.moveSpeed * 1.2; npc.y += dy / d * npc.moveSpeed * 1.2; } // Ateş et (her 30 tickte bir) npc._aiAttackTimer = (npc._aiAttackTimer || 0) + 1; if (d < 300 && npc._aiAttackTimer > 30) { // NPC'nin mermisi: Bullet ile aynı, ama _npcBullet=true var bullet = new Bullet(); bullet.x = npc.x; bullet.y = npc.y; var angle = Math.atan2(tp.y - npc.y, tp.x - npc.x); bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullet.rotation = angle + Math.PI / 2; bullet._npcBullet = true; bullets.push(bullet); game.addChild(bullet); npc._aiAttackTimer = 0; } // KILL etiketi gösterme ve kaldırma kodu tamamen kaldırıldı if (tp.health <= 0 || tp._destroyed) { npc._aiTargetPirate = null; } } else { npc._aiTargetPirate = null; } } // Update asteroids for (var i = asteroids.length - 1; i >= 0; i--) { var asteroid = asteroids[i]; if (asteroid._healthBar && asteroid._healthBar.update) asteroid._healthBar.update(); var dist = Math.sqrt(Math.pow(asteroid.x - ship.x, 2) + Math.pow(asteroid.y - ship.y, 2)); if (dist > 2500) { asteroid.destroy(); asteroids.splice(i, 1); } } // --- Space Debris Field Event --- // Every 18000 ticks, 10% chance, only one at a time if (!window.debrisField && LK.ticks % 18000 === 0 && Math.random() < 0.1) { // Spawn debris field within 700-900px of the ship var angle = Math.random() * Math.PI * 2; var dist = 700 + Math.random() * 200; // 700-900px var cx = ship.x + Math.cos(angle) * dist; var cy = ship.y + Math.sin(angle) * dist; var debris = []; for (var i = 0; i < 15; i++) { var a = new Asteroid(); var aAngle = Math.random() * Math.PI * 2; var radius = 200 + Math.random() * 200; a.x = cx + Math.cos(aAngle) * radius; a.y = cy + Math.sin(aAngle) * radius; a.health = 10 + Math.floor(Math.random() * 20); a.resources = 1 + Math.floor(Math.random() * 3); asteroids.push(a); game.addChild(a); debris.push(a); } var debrisLabel = new Text2("Enkaz Alanı", { size: 36, fill: 0xcccccc, align: "center" }); debrisLabel.anchor.set(0.5, 0); debrisLabel.x = cx; debrisLabel.y = cy + 250; game.addChild(debrisLabel); window.debrisField = { debris: debris, label: debrisLabel, x: cx, y: cy }; } // Remove debris field if all asteroids gone or too far if (window.debrisField) { var allGone = true; for (var i = 0; i < window.debrisField.debris.length; i++) { if (asteroids.indexOf(window.debrisField.debris[i]) !== -1) { allGone = false; break; } } var dist = Math.sqrt(Math.pow(window.debrisField.x - ship.x, 2) + Math.pow(window.debrisField.y - ship.y, 2)); if (allGone || dist > 4000) { if (window.debrisField.label && window.debrisField.label.parent) window.debrisField.label.parent.removeChild(window.debrisField.label); window.debrisField = null; } else { // Keep label above field if (window.debrisField.label) { window.debrisField.label.x = window.debrisField.x; window.debrisField.label.y = window.debrisField.y + 250; } } } // Update upgrade stations for (var i = upgradeStations.length - 1; i >= 0; i--) { var station = upgradeStations[i]; var dist = Math.sqrt(Math.pow(station.x - ship.x, 2) + Math.pow(station.y - ship.y, 2)); if (dist < 100 && playerCoins >= 100) { // Apply random upgrade var upgrade = station.upgrades[Math.floor(Math.random() * station.upgrades.length)]; if (upgrade.name === 'health' && playerMetal >= (upgrade.metalCost || 0)) { ship.maxHealth += 20; ship.health = ship.maxHealth; playerCoins -= upgrade.cost; playerMetal -= upgrade.metalCost || 0; } else if (upgrade.name === 'shield' && playerMetal >= (upgrade.metalCost || 0)) { ship.maxShield += 10; ship.shield = ship.maxShield; playerCoins -= upgrade.cost; playerMetal -= upgrade.metalCost || 0; } else if (upgrade.name === 'damage' && playerEnergy >= (upgrade.energyCost || 0)) { ship.damage += 5; playerCoins -= upgrade.cost; playerEnergy -= upgrade.energyCost || 0; } else if (upgrade.name === 'speed' && playerEnergy >= (upgrade.energyCost || 0)) { ship.speed += 1; playerCoins -= upgrade.cost; playerEnergy -= upgrade.energyCost || 0; } if (LK.getSound('upgrade')) { LK.getSound('upgrade').play(); } updateUI(); saveProgress(); station.destroy(); upgradeStations.splice(i, 1); } if (dist > 3000) { station.destroy(); upgradeStations.splice(i, 1); } } // Update boost particles for (var i = boostParticles.length - 1; i >= 0; i--) { var particle = boostParticles[i]; particle.x += particle.vx; particle.y += particle.vy; particle.life--; particle.alpha = particle.life / 20; if (particle.life <= 0) { particle.destroy(); boostParticles.splice(i, 1); } } // Update explosion particles for (var i = explosions.length - 1; i >= 0; i--) { var particle = explosions[i]; particle.x += particle.vx; particle.y += particle.vy; particle.vx *= 0.9; particle.vy *= 0.9; particle.life--; particle.alpha = particle.life / 30; particle.scaleX = particle.scaleY = 1 + (30 - particle.life) / 10; if (particle.life <= 0) { particle.destroy(); explosions.splice(i, 1); } } // Collect items for (var i = coins.length - 1; i >= 0; i--) { if (coins[i].intersects(ship)) { playerCoins += coins[i].value; coins[i].destroy(); coins.splice(i, 1); LK.getSound('collect').play(); updateUI(); saveProgress(); } } for (var i = resources.length - 1; i >= 0; i--) { if (resources[i].intersects(ship)) { if (resources[i].type === 'metal') { playerMetal += resources[i].amount; } else { playerEnergy += resources[i].amount; } resources[i].destroy(); resources.splice(i, 1); LK.getSound('collect').play(); updateUI(); saveProgress(); } } // Update stars for (var i = stars.length - 1; i >= 0; i--) { var dist = Math.sqrt(Math.pow(stars[i].x - ship.x, 2) + Math.pow(stars[i].y - ship.y, 2)); if (dist > 2000) { stars[i].destroy(); stars.splice(i, 1); } } // Update pirate bases for (var i = pirateBases.length - 1; i >= 0; i--) { var base = pirateBases[i]; if (base.update) base.update(); var dist = Math.sqrt(Math.pow(base.x - ship.x, 2) + Math.pow(base.y - ship.y, 2)); // Remove base if too far or destroyed if (dist > 3500 || base._destroyed) { if (base._healthBar && base._healthBar.parent) base._healthBar.parent.removeChild(base._healthBar); base.destroy(); pirateBases.splice(i, 1); } } // Update black holes for (var i = blackHoles.length - 1; i >= 0; i--) { var bh = blackHoles[i]; if (bh.update) bh.update(); var dist = Math.sqrt(Math.pow(bh.x - ship.x, 2) + Math.pow(bh.y - ship.y, 2)); if (dist > 3000) { bh.destroy(); blackHoles.splice(i, 1); } } // Update wormholes for (var i = wormholes.length - 1; i >= 0; i--) { var wh = wormholes[i]; if (wh.update) wh.update(); var dist = Math.sqrt(Math.pow(wh.x - ship.x, 2) + Math.pow(wh.y - ship.y, 2)); if (dist > 3000) { wh.destroy(); wormholes.splice(i, 1); } } // Update trade stations (RPG/ticaret) var tradeActive = false; for (var i = tradeStations.length - 1; i >= 0; i--) { var ts = tradeStations[i]; if (ts.update) ts.update(); var dist = Math.sqrt(Math.pow(ts.x - ship.x, 2) + Math.pow(ts.y - ship.y, 2)); if (dist < 180) { tradeActive = true; // Show trade offer if (ts.specialOffer && ts.specialUpgrade) { tradeText.setText('Special: ' + ts.specialUpgrade.label + ' for ' + ts.specialUpgrade.cost + ' coins\n(Tap to buy)'); // Buy special upgrade on tap if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) { if (playerCoins >= ts.specialUpgrade.cost) { playerCoins -= ts.specialUpgrade.cost; if (ts.specialUpgrade.name === 'maxHealth') { ship.maxHealth += 30; ship.health = ship.maxHealth; } else if (ts.specialUpgrade.name === 'maxShield') { ship.maxShield += 20; ship.shield = ship.maxShield; } else if (ts.specialUpgrade.name === 'damage') { ship.damage += 5; } else if (ts.specialUpgrade.name === 'speed') { ship.speed += 1; } LK.effects.flashObject(ship, 0x00ff99, 400); updateUI(); saveProgress(); ts.destroy(); tradeStations.splice(i, 1); tradeText.setText('Upgrade purchased!'); game._lastTradeStation = null; break; } else { tradeText.setText('Not enough coins!'); } } } else if (ts.offerType === 'buy') { tradeText.setText('Trade: Sell ' + ts.amount + ' ' + ts.resourceType + ' for ' + ts.price + ' coins\n(Tap to sell)'); // Sell resource on tap if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) { if (ts.resourceType === 'metal' && playerMetal >= ts.amount) { playerMetal -= ts.amount; playerCoins += ts.price; LK.effects.flashObject(ship, 0x00ff99, 200); updateUI(); saveProgress(); ts.destroy(); tradeStations.splice(i, 1); tradeText.setText('Sold!'); game._lastTradeStation = null; break; } else if (ts.resourceType === 'energy' && playerEnergy >= ts.amount) { playerEnergy -= ts.amount; playerCoins += ts.price; LK.effects.flashObject(ship, 0x00ff99, 200); updateUI(); saveProgress(); ts.destroy(); tradeStations.splice(i, 1); tradeText.setText('Sold!'); game._lastTradeStation = null; break; } else { tradeText.setText('Not enough ' + ts.resourceType + '!'); } } } else if (ts.offerType === 'sell') { tradeText.setText('Trade: Buy ' + ts.amount + ' ' + ts.resourceType + ' for ' + ts.price + ' coins\n(Tap to buy)'); // Buy resource on tap if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) { if (playerCoins >= ts.price) { playerCoins -= ts.price; if (ts.resourceType === 'metal') { playerMetal += ts.amount; } else { playerEnergy += ts.amount; } LK.effects.flashObject(ship, 0x00ff99, 200); updateUI(); saveProgress(); ts.destroy(); tradeStations.splice(i, 1); tradeText.setText('Purchased!'); game._lastTradeStation = null; break; } else { tradeText.setText('Not enough coins!'); } } } game._lastTradeStation = ts; } if (dist > 2500) { ts.destroy(); tradeStations.splice(i, 1); } } if (!tradeActive) { tradeText.setText(''); game._lastTradeStation = null; } // Spawn entities (reduced by 70%) if (LK.ticks % 100 === 0) { if (Math.random() < 0.5) { // 50% chance spawnStar(); } } // --- Anomaly Events: Space Storm, Nebula, Time Warp --- // Only one anomaly at a time, random chance every 9000 ticks if (!window.activeAnomaly && LK.ticks % 9000 === 0 && Math.random() < 0.33) { var anomalyType = Math.random(); if (anomalyType < 0.34) { // Space Storm: disables boost and slows ship for 20 seconds window.activeAnomaly = "storm"; window.anomalyExpire = LK.ticks + 1200; ship.speed = Math.max(2, ship.speed - 2); ship.boostCooldown = 9999; var anomalyFontSize = Math.round(unifiedFontSize * 1.1); var stormLabel = new Text2("UZAY FIRTINASI! Hız ve boost devre dışı!", { size: anomalyFontSize, fill: 0x00ffff, align: "center" }); stormLabel.anchor.set(0.5, 0.5); stormLabel.x = ship.x; stormLabel.y = ship.y - 200; game.addChild(stormLabel); window.anomalyLabel = stormLabel; } else if (anomalyType < 0.67) { // Nebula: disables auto-fire and reduces vision (star alpha) window.activeAnomaly = "nebula"; window.anomalyExpire = LK.ticks + 1200; window._oldStarAlpha = []; for (var i = 0; i < stars.length; i++) { window._oldStarAlpha[i] = stars[i].children[0].alpha; stars[i].children[0].alpha = 0.1; } window._oldAutoFire = ship.autoFireDisabled; ship.autoFireDisabled = true; var nebulaLabel = new Text2("NEBULA! Otomatik ateş ve görüş kısıtlı!", { size: anomalyFontSize, fill: 0xcc99ff, align: "center" }); nebulaLabel.anchor.set(0.5, 0.5); nebulaLabel.x = ship.x; nebulaLabel.y = ship.y - 200; game.addChild(nebulaLabel); window.anomalyLabel = nebulaLabel; } else { // Time Warp: all pirates/asteroids move double speed, player gets double EXP window.activeAnomaly = "timewarp"; window.anomalyExpire = LK.ticks + 1200; for (var i = 0; i < pirates.length; i++) pirates[i].speed *= 2; for (var i = 0; i < asteroids.length; i++) asteroids[i].vx *= 2, asteroids[i].vy *= 2; window._expMultiplier = 2; var warpLabel = new Text2("ZAMAN YAMULMASI! Düşmanlar hızlı, EXP x2!", { size: anomalyFontSize, fill: 0xffcc00, align: "center" }); warpLabel.anchor.set(0.5, 0.5); warpLabel.x = ship.x; warpLabel.y = ship.y - 200; game.addChild(warpLabel); window.anomalyLabel = warpLabel; } } // Anomaly expire logic if (window.activeAnomaly && LK.ticks > window.anomalyExpire) { if (window.activeAnomaly === "storm") { ship.speed = Math.min(ship.speed + 2, 10); ship.boostCooldown = 0; } else if (window.activeAnomaly === "nebula") { for (var i = 0; i < stars.length; i++) { if (window._oldStarAlpha && window._oldStarAlpha[i] !== undefined) stars[i].children[0].alpha = window._oldStarAlpha[i]; } ship.autoFireDisabled = window._oldAutoFire || false; } else if (window.activeAnomaly === "timewarp") { for (var i = 0; i < pirates.length; i++) pirates[i].speed /= 2; for (var i = 0; i < asteroids.length; i++) asteroids[i].vx /= 2, asteroids[i].vy /= 2; window._expMultiplier = 1; } if (window.anomalyLabel && window.anomalyLabel.parent) window.anomalyLabel.parent.removeChild(window.anomalyLabel); window.activeAnomaly = null; window.anomalyExpire = null; window.anomalyLabel = null; } // Spawn black holes occasionally if (LK.ticks % 3600 === 0 && Math.random() < 0.6) { spawnBlackHole(); } // Spawn wormholes occasionally if (LK.ticks % 4200 === 0 && Math.random() < 0.6) { spawnWormhole(); } // Spawn trade stations occasionally (RPG/ticaret) if (LK.ticks % 4800 === 0 && Math.random() < 0.6) { spawnTradeStation(); } // Spawn pirate bases occasionally if (LK.ticks % 6000 === 0 && Math.random() < 0.5 && pirateBases.length < 3) { spawnPirateBase(); } if (LK.ticks % 900 === 0) { var spawnRoll = Math.random(); if (spawnRoll < 0.15) { // 15% chance (pirates reduced by 85%) spawnPirate(); } else if (spawnRoll < 0.31) { // 16% chance (NPCs increased by 10%) spawnNPC(); } else if (spawnRoll < 0.33) { // 2% chance // Spawn multiple entities occasionally spawnPirate(); spawnNPC(); } } // Spawn asteroids (reduced by 70%) if (LK.ticks % 1500 === 0) { if (Math.random() < 0.5) { // 50% chance spawnAsteroid(); } } // --- Derelict Ship Event --- // Every 12000 ticks, 20% chance, only one at a time if (!window.derelictShip && LK.ticks % 12000 === 0 && Math.random() < 0.2) { // Spawn derelict ship at a moderate distance (within 700-900px), not at screen corners var angle = Math.random() * Math.PI * 2; var dist = 700 + Math.random() * 200; // 700-900px away var dx = Math.cos(angle) * dist; var dy = Math.sin(angle) * dist; var derelict = LK.getAsset('ship', { anchorX: 0.5, anchorY: 0.5, x: ship.x + dx, y: ship.y + dy, tint: 0x888888, scaleX: 1.2, scaleY: 1.2, alpha: 0.7 }); derelict._isDerelict = true; derelict._loot = { coins: 50 + Math.floor(Math.random() * 100), metal: 5 + Math.floor(Math.random() * 10), energy: 5 + Math.floor(Math.random() * 10) }; derelict._label = new Text2("Terkedilmiş Gemi", { size: 32, fill: 0xcccccc, align: "center" }); derelict._label.anchor.set(0.5, 0); derelict._label.x = derelict.x; derelict._label.y = derelict.y + 70; game.addChild(derelict); game.addChild(derelict._label); window.derelictShip = derelict; } // Derelict ship interaction if (window.derelictShip) { var d = window.derelictShip; var dist = Math.sqrt(Math.pow(d.x - ship.x, 2) + Math.pow(d.y - ship.y, 2)); if (dist < 120) { // Collect loot playerCoins += d._loot.coins; playerMetal += d._loot.metal; playerEnergy += d._loot.energy; var lootLabel = new Text2("Gemi yağmalandı!\n+" + d._loot.coins + " coin, +" + d._loot.metal + " metal, +" + d._loot.energy + " enerji", { size: 36, fill: 0x00ffcc, align: "center" }); lootLabel.anchor.set(0.5, 0.5); lootLabel.x = d.x; lootLabel.y = d.y - 80; game.addChild(lootLabel); if (d.parent) d.parent.removeChild(d); if (d._label && d._label.parent) d._label.parent.removeChild(d._label); window.derelictShip = null; updateUI(); saveProgress(); // Remove loot label after 2 seconds (function (lbl) { var expire = LK.ticks + 120; var removeLootLabel = function removeLootLabel() { if (LK.ticks > expire && lbl.parent) { lbl.parent.removeChild(lbl); game.update = origUpdate; } }; var origUpdate = game.update; game.update = function () { removeLootLabel(); if (origUpdate) origUpdate.apply(game, arguments); }; })(lootLabel); } else if (dist > 3000) { if (d.parent) d.parent.removeChild(d); if (d._label && d._label.parent) d._label.parent.removeChild(d._label); window.derelictShip = null; } else { // Keep label above derelict if (d._label) { d._label.x = d.x; d._label.y = d.y + 70; } } } // Wave-based pirate spawning if (LK.ticks % (180 - Math.min(waveNumber * 10, 100)) === 0) { var piratesInWave = 1 + Math.floor(waveNumber / 2); for (var j = 0; j < piratesInWave; j++) { spawnPirate(); } } // --- Distress Signal Event --- // Every 15000 ticks, 15% chance, only one at a time if (!window.distressEvent && LK.ticks % 15000 === 0 && Math.random() < 0.15) { // Spawn distress event at a moderate distance (within 700-900px), not at screen corners var angle = Math.random() * Math.PI * 2; var dist = 700 + Math.random() * 200; // 700-900px away var sx = ship.x + Math.cos(angle) * dist; var sy = ship.y + Math.sin(angle) * dist; var signal = LK.getAsset('star', { anchorX: 0.5, anchorY: 0.5, x: sx, y: sy, tint: 0xff00ff, scaleX: 4, scaleY: 4, alpha: 0.8 }); var label = new Text2("İmdat Sinyali", { size: 36, fill: 0xff00ff, align: "center" }); label.anchor.set(0.5, 0); label.x = sx; label.y = sy + 70; game.addChild(signal); game.addChild(label); window.distressEvent = { signal: signal, label: label, x: sx, y: sy, state: "waiting" }; } // Distress event logic if (window.distressEvent) { var e = window.distressEvent; var dist = Math.sqrt(Math.pow(e.x - ship.x, 2) + Math.pow(e.y - ship.y, 2)); if (e.state === "waiting" && dist < 120) { // Show choice: rescue or ignore (ambush possibility) if (!e.panel) { // --- DYNAMIC DISTRESS PANEL SIZE BASED ON TEXT --- var distressTextStr = "İmdat sinyali! Yardım et veya uzaklaş?"; var distressPanelFontSize = 38; var distressPanelWidth = Math.max(700, distressTextStr.length * distressPanelFontSize * 0.32); var distressPanelHeight = 220 + distressPanelFontSize * 1.5; // title + buttons var panel = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, x: e.x, y: e.y - 180, scaleX: distressPanelWidth / 40, scaleY: distressPanelHeight / 40, tint: 0x222244 }); var text = new Text2("İmdat sinyali! Yardım et veya uzaklaş?", { size: 38, fill: 0xffffff, align: "center" }); text.anchor.set(0.5, 0.5); text.x = e.x; text.y = e.y - 200; var helpBtn = new Text2("Yardım Et", { size: 44, fill: 0x00ff99, align: "center" }); helpBtn.anchor.set(0.5, 0.5); helpBtn.x = e.x - 100; helpBtn.y = e.y - 120; var ignoreBtn = new Text2("Uzaklaş", { size: 44, fill: 0xff4444, align: "center" }); ignoreBtn.anchor.set(0.5, 0.5); ignoreBtn.x = e.x + 100; ignoreBtn.y = e.y - 120; game.addChild(panel); game.addChild(text); game.addChild(helpBtn); game.addChild(ignoreBtn); e.panel = panel; e.text = text; e.helpBtn = helpBtn; e.ignoreBtn = ignoreBtn; helpBtn._isDistressHelp = true; ignoreBtn._isDistressIgnore = true; helpBtn._distressEvent = e; ignoreBtn._distressEvent = e; } // Tap logic for help/ignore if (game._lastDistressTap !== e && game._lastDistressTapTick !== undefined && game._lastDistressTapTick + 30 > LK.ticks) { var tapX = game._lastDistressTapX, tapY = game._lastDistressTapY; if (tapX > e.helpBtn.x - 90 && tapX < e.helpBtn.x + 90 && tapY > e.helpBtn.y - 40 && tapY < e.helpBtn.y + 40) { // Help: 70% chance for reward, 30% ambush if (Math.random() < 0.7) { var reward = 100 + Math.floor(Math.random() * 100); playerCoins += reward; var msg = new Text2("Kurtarılan gemi! Ödül: " + reward + " coin", { size: 36, fill: 0x00ffcc, align: "center" }); msg.anchor.set(0.5, 0.5); msg.x = e.x; msg.y = e.y - 80; game.addChild(msg); updateUI(); saveProgress(); } else { // Ambush: spawn 3 pirates for (var i = 0; i < 3; i++) { var pirate = new Pirate(); pirate.x = e.x + (Math.random() - 0.5) * 100; pirate.y = e.y + (Math.random() - 0.5) * 100; pirates.push(pirate); game.addChild(pirate); } var msg = new Text2("Pusu! Korsanlar saldırıyor!", { size: 36, fill: 0xff4444, align: "center" }); msg.anchor.set(0.5, 0.5); msg.x = e.x; msg.y = e.y - 80; game.addChild(msg); } // Clean up if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal); if (e.label && e.label.parent) e.label.parent.removeChild(e.label); if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel); if (e.text && e.text.parent) e.text.parent.removeChild(e.text); if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn); if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn); window.distressEvent = null; } else if (tapX > e.ignoreBtn.x - 90 && tapX < e.ignoreBtn.x + 90 && tapY > e.ignoreBtn.y - 40 && tapY < e.ignoreBtn.y + 40) { // Ignore: nothing happens, clean up if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal); if (e.label && e.label.parent) e.label.parent.removeChild(e.label); if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel); if (e.text && e.text.parent) e.text.parent.removeChild(e.text); if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn); if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn); window.distressEvent = null; } game._lastDistressTap = e; } } else if (dist > 3000) { if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal); if (e.label && e.label.parent) e.label.parent.removeChild(e.label); if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel); if (e.text && e.text.parent) e.text.parent.removeChild(e.text); if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn); if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn); window.distressEvent = null; } else { // Keep label above signal if (e.label) { e.label.x = e.x; e.label.y = e.y + 70; } } } // Boss wave every 5 waves if (waveNumber > 0 && waveNumber % 5 === 0 && pirates.length === 0) { var bossPirate = new Pirate(); bossPirate.x = ship.x + 1000; bossPirate.y = ship.y; // Level range: wave 1 => 1-3, wave 2 => 3-5, wave 3 => 5-7, etc. var minLevel = 1 + waveNumber * 2; var maxLevel = minLevel + 2; bossPirate.level = minLevel + Math.floor(Math.random() * (maxLevel - minLevel + 1)); bossPirate.health = 200 + (bossPirate.level - 1) * 20; bossPirate.damage = 10 + Math.floor(bossPirate.level * 1.5); bossPirate.defense = 2 + Math.floor(bossPirate.level * 1.2); bossPirate.loot = 200 + bossPirate.level * 50; bossPirate.speed = 3; var bossGraphics = bossPirate.children[0]; bossGraphics.tint = 0xff00ff; bossGraphics.scaleX = 2; bossGraphics.scaleY = 2; pirates.push(bossPirate); game.addChild(bossPirate); } // Update score LK.setScore(playerCoins + questsCompleted * 100 + enemiesKilled * 10 + Math.floor(totalDistance / 100)); if (ship._healthBar && ship._healthBar.update) ship._healthBar.update(); updateUI(); // --- AUTO-REPAIR PANEL WHEN HEALTH IS LOW OR HEALTH BAR TAPPED --- // Show repair panel if health < 100% and not dead, and not already shown if (!window.repairPanel && ship.health < ship.maxHealth && ship.health > 0 && window._showRepairPanel) { // Calculate how much health will be restored var healthToRestore = ship.maxHealth - ship.health; // Proportional cost scaling // Base costs for full repair: 90 coins, 6 metal, 6 energy (for 60 health missing) // Scale linearly with health to restore, but clamp minimums var baseFullRepairHealth = 60; var baseCoinCost = 90; var baseMetalCost = 6; var baseEnergyCost = 6; var repairCostCoins = Math.max(30, Math.round(baseCoinCost * (healthToRestore / baseFullRepairHealth))); var repairCostMetal = Math.max(2, Math.round(baseMetalCost * (healthToRestore / baseFullRepairHealth))); var repairCostEnergy = Math.max(2, Math.round(baseEnergyCost * (healthToRestore / baseFullRepairHealth))); // Panel background // --- DYNAMIC REPAIR PANEL SIZE BASED ON TEXT --- var repairTextStr = "Gemi hasarlı! Tamir: " + repairCostCoins + " coin, " + repairCostMetal + " metal, " + repairCostEnergy + " enerji"; var repairPanelFontSize = 38; var repairPanelWidth = Math.max(700, repairTextStr.length * repairPanelFontSize * 0.32); var repairPanelHeight = 180 + repairPanelFontSize * 1.5; // text + buttons var panel = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, x: ship.x, y: ship.y - 220, scaleX: repairPanelWidth / 40, scaleY: repairPanelHeight / 40, tint: 0x224444 }); // Repair text var repairText = new Text2("Gemi hasarlı! Tamir: " + repairCostCoins + " coin, " + repairCostMetal + " metal, " + repairCostEnergy + " enerji", { size: 38, fill: 0xffffff, align: "center" }); repairText.anchor.set(0.5, 0.5); repairText.x = ship.x; repairText.y = ship.y - 240; // Repair button var repairBtn = new Text2("Tamir Et", { size: 44, fill: 0x00ff99, align: "center" }); repairBtn.anchor.set(0.5, 0.5); repairBtn.x = ship.x - 100; repairBtn.y = ship.y - 160; // Cancel button var cancelBtn = new Text2("Kapat", { size: 44, fill: 0xff4444, align: "center" }); cancelBtn.anchor.set(0.5, 0.5); cancelBtn.x = ship.x + 100; cancelBtn.y = ship.y - 160; // Add to game game.addChild(panel); game.addChild(repairText); game.addChild(repairBtn); game.addChild(cancelBtn); // Store references for tap logic and cleanup window.repairPanel = panel; window.repairText = repairText; window.repairBtn = repairBtn; window.cancelRepairBtn = cancelBtn; repairBtn._isRepairBtn = true; cancelBtn._isCancelRepairBtn = true; repairBtn._repairCostCoins = repairCostCoins; repairBtn._repairCostMetal = repairCostMetal; repairBtn._repairCostEnergy = repairCostEnergy; window._showRepairPanel = false; // Reset flag } else if (window.repairPanel && ship.health >= ship.maxHealth * 0.7) { // Remove repair panel if health is restored if (window.repairPanel.parent) window.repairPanel.parent.removeChild(window.repairPanel); if (window.repairText && window.repairText.parent) window.repairText.parent.removeChild(window.repairText); if (window.repairBtn && window.repairBtn.parent) window.repairBtn.parent.removeChild(window.repairBtn); if (window.cancelRepairBtn && window.cancelRepairBtn.parent) window.cancelRepairBtn.parent.removeChild(window.cancelRepairBtn); window.repairPanel = null; window.repairText = null; window.repairBtn = null; window.cancelRepairBtn = null; window._showRepairPanel = false; } // If health < 50% and not dead, auto-show repair panel (legacy behavior) if (!window.repairPanel && ship.health < ship.maxHealth * 0.5 && ship.health > 0) { window._showRepairPanel = true; } // --- GAME TIME UPDATE --- // Calculate elapsed time in seconds var elapsedTicks = LK.ticks - gameStartTick; var elapsedSeconds = Math.floor(elapsedTicks / 60); var minutes = Math.floor(elapsedSeconds / 60); var seconds = elapsedSeconds % 60; if (typeof gameTimeText !== "undefined") { // Format as mm:ss var timeStr = "Game Time: " + minutes + ":" + (seconds < 10 ? "0" : "") + seconds; gameTimeText.setText(timeStr); // Always keep gameTimeText to the right of coinText gameTimeText.x = coinText.x + coinText.width + 40; gameTimeText.y = coinText.y; } // --- Synchronize LK.ticks with real game time --- // This ensures all time-based systems use real elapsed time, not just frame count LK.ticks = gameStartTick + Math.floor((Date.now() - (window._gameStartRealTime || (window._gameStartRealTime = Date.now()))) / (1000 / 60)); // Update coordinateText with current ship coordinates (rounded) in real time to the left of waveText if (typeof coordinateText !== "undefined" && ship && typeof waveText !== "undefined") { // Show the actual current coordinates of the ship coordinateText.setText('X: ' + Math.round(ship.x) + ' Y: ' + Math.round(ship.y)); // Always keep coordinateText to the left of waveText, and keep size 30% smaller than expText coordinateText.size = Math.round(expText.size * 0.7); coordinateText.x = waveText.x - waveText.width - 30; coordinateText.y = waveText.y + waveText.height / 2; } // --- QUEST TARGET ARROW INDICATOR --- // Only one arrow at a time, create if needed if (!window.questArrow) { // Use a yellow triangle as arrow var arrow = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 1.2, tint: 0xffff00, alpha: 0.85 }); arrow.visible = false; window.questArrow = arrow; game.addChild(arrow); } var showArrow = false; var arrowX = 0, arrowY = 0, arrowRot = 0; var questTarget = null; var minDist = Infinity; // Find the nearest active coordinate-based quest target for (var i = 0; i < npcs.length; i++) { var npc = npcs[i]; if (!npc.questActive || !npc.questTarget) continue; // Only for coordinate-based quests if (npc.questType === 'explore' || npc.questType === 'delivery' || npc.questType === 'escort' || npc.questType === 'hunt') { // For hunt, questTarget can be a pirate, otherwise it's {x, y} var tx, ty; if (npc.questType === 'hunt' && npc.questTarget && npc.questTarget.x !== undefined && npc.questTarget.y !== undefined && !npc.questTarget._destroyed) { tx = npc.questTarget.x; ty = npc.questTarget.y; } else if (npc.questTarget.x !== undefined && npc.questTarget.y !== undefined) { tx = npc.questTarget.x; ty = npc.questTarget.y; } if (typeof tx === "number" && typeof ty === "number") { var dist = Math.sqrt(Math.pow(tx - ship.x, 2) + Math.pow(ty - ship.y, 2)); if (dist > 120 && dist < minDist) { // Only show if not already at target minDist = dist; questTarget = { x: tx, y: ty }; } } } } // --- Derelict ship arrow logic --- if (!questTarget && window.derelictShip && window.derelictShip.x !== undefined && window.derelictShip.y !== undefined) { var d = window.derelictShip; var dist = Math.sqrt(Math.pow(d.x - ship.x, 2) + Math.pow(d.y - ship.y, 2)); if (dist > 120 && dist < 3000) { questTarget = { x: d.x, y: d.y }; } } if (questTarget) { // Project questTarget to screen edge var dx = questTarget.x - ship.x; var dy = questTarget.y - ship.y; var angle = Math.atan2(dy, dx); // Screen center in game coordinates var screenW = 2048, screenH = 2732; var margin = 90; // keep arrow inside screen var cx = screenW / 2, cy = screenH / 2; // Find intersection with screen edge var ex = cx + Math.cos(angle) * (Math.min(cx, cy) - margin); var ey = cy + Math.sin(angle) * (Math.min(cx, cy) - margin); // Clamp to screen bounds ex = Math.max(margin, Math.min(screenW - margin, ex)); ey = Math.max(margin, Math.min(screenH - margin, ey)); // Don't show if target is on screen (within 40% of screen from center) if (Math.abs(dx) > screenW * 0.2 || Math.abs(dy) > screenH * 0.2) { showArrow = true; arrowX = ex; arrowY = ey; arrowRot = angle + Math.PI / 2; } } if (window.questArrow) { window.questArrow.visible = showArrow; if (showArrow) { window.questArrow.x = arrowX; window.questArrow.y = arrowY; window.questArrow.rotation = arrowRot; window.questArrow.alpha = 0.85 + Math.sin(LK.ticks * 0.1) * 0.15; window.questArrow.scaleX = 2.5 + Math.sin(LK.ticks * 0.07) * 0.2; window.questArrow.scaleY = 1.2 + Math.cos(LK.ticks * 0.09) * 0.1; window.questArrow.zIndex = 9999; } } // --- Remaining Distance Label for Quest/Event Target and All Special Events --- // Only one label at a time, create if needed if (!window.questDistanceLabel) { var questDistanceLabel = new Text2('', { size: Math.round(unifiedFontSize * 0.9), fill: 0xffffff, align: "center" }); questDistanceLabel.anchor.set(0.5, 0.5); questDistanceLabel.visible = false; window.questDistanceLabel = questDistanceLabel; game.addChild(questDistanceLabel); } // Gather all event/building/quest targets to show distance for var eventTargets = []; // 1. Active quest target (from arrow logic) if (questTarget) { eventTargets.push({ x: questTarget.x, y: questTarget.y, label: null, // Will be set below type: "quest" }); } // 2. Derelict ship if (window.derelictShip && window.derelictShip.x !== undefined && window.derelictShip.y !== undefined) { eventTargets.push({ x: window.derelictShip.x, y: window.derelictShip.y, label: "Gemi", type: "derelict" }); } // 3. Distress event if (window.distressEvent && window.distressEvent.x !== undefined && window.distressEvent.y !== undefined) { eventTargets.push({ x: window.distressEvent.x, y: window.distressEvent.y, label: "İmdat", type: "distress" }); } // 4. Upgrade stations for (var i = 0; i < upgradeStations.length; i++) { eventTargets.push({ x: upgradeStations[i].x, y: upgradeStations[i].y, label: "Yükseltme", type: "upgrade" }); } // 5. Trade stations for (var i = 0; i < tradeStations.length; i++) { eventTargets.push({ x: tradeStations[i].x, y: tradeStations[i].y, label: "Ticaret", type: "trade" }); } // 6. Black holes for (var i = 0; i < blackHoles.length; i++) { eventTargets.push({ x: blackHoles[i].x, y: blackHoles[i].y, label: "Kara Delik", type: "blackhole" }); } // 7. Wormholes for (var i = 0; i < wormholes.length; i++) { eventTargets.push({ x: wormholes[i].x, y: wormholes[i].y, label: "Solucan Deliği", type: "wormhole" }); } // 8. Pirate bases for (var i = 0; i < pirateBases.length; i++) { eventTargets.push({ x: pirateBases[i].x, y: pirateBases[i].y, label: "Korsan Üssü", type: "piratebase" }); } // 9. Debris field if (window.debrisField && window.debrisField.x !== undefined && window.debrisField.y !== undefined) { eventTargets.push({ x: window.debrisField.x, y: window.debrisField.y, label: "Enkaz", type: "debris" }); } // Find the closest event/building/quest target that is off-screen (not in center area) var minDist = Infinity; var bestTarget = null; var screenW = 2048, screenH = 2732; var margin = 90; var cx = screenW / 2, cy = screenH / 2; for (var i = 0; i < eventTargets.length; i++) { var tx = eventTargets[i].x, ty = eventTargets[i].y; var dx = tx - ship.x, dy = ty - ship.y; var dist = Math.sqrt(dx * dx + dy * dy); // Only show if not already at target and not on screen (center 40%) if (dist > 120 && (Math.abs(dx) > screenW * 0.2 || Math.abs(dy) > screenH * 0.2)) { if (dist < minDist) { minDist = dist; bestTarget = eventTargets[i]; bestTarget._dx = dx; bestTarget._dy = dy; bestTarget._dist = dist; } } } // Show label if found var showDistanceLabel = false; var labelX = 0, labelY = 0, labelText = ''; if (bestTarget) { // Project to screen edge var angle = Math.atan2(bestTarget._dy, bestTarget._dx); var ex = cx + Math.cos(angle) * (Math.min(cx, cy) - margin); var ey = cy + Math.sin(angle) * (Math.min(cx, cy) - margin); // Clamp to screen bounds ex = Math.max(margin, Math.min(screenW - margin, ex)); ey = Math.max(margin, Math.min(screenH - margin, ey)); // Place label near the arrow, but offset further outwards var labelOffset = 70; labelX = ex + Math.cos(angle) * labelOffset; labelY = ey + Math.sin(angle) * labelOffset; // Show in km if >1000, else in px if (bestTarget._dist >= 1000) { labelText = (bestTarget.label ? bestTarget.label + ": " : "") + Math.round(bestTarget._dist / 10) / 100 + "k px"; } else { labelText = (bestTarget.label ? bestTarget.label + ": " : "") + Math.round(bestTarget._dist) + " px"; } // For quest, try to show quest type if (bestTarget.type === "quest") { for (var i = 0; i < npcs.length; i++) { var npc = npcs[i]; if (npc.questActive && npc.questTarget && (npc.questType === 'explore' || npc.questType === 'delivery' || npc.questType === 'escort') && npc.questTarget.x === bestTarget.x && npc.questTarget.y === bestTarget.y) { if (npc.questType === 'explore') labelText = "Keşif: " + labelText;else if (npc.questType === 'delivery') labelText = "Teslimat: " + labelText;else if (npc.questType === 'escort') labelText = "Eşlik: " + labelText; break; } if (npc.questActive && npc.questType === 'hunt' && npc.questTarget && npc.questTarget.x === bestTarget.x && npc.questTarget.y === bestTarget.y) { labelText = "Av: " + labelText; break; } } } showDistanceLabel = true; } if (window.questDistanceLabel) { window.questDistanceLabel.visible = showDistanceLabel; if (showDistanceLabel) { window.questDistanceLabel.x = labelX; window.questDistanceLabel.y = labelY; window.questDistanceLabel.setText(labelText); window.questDistanceLabel.alpha = 0.9 + Math.sin(LK.ticks * 0.1) * 0.1; window.questDistanceLabel.size = Math.round(unifiedFontSize * 0.9); window.questDistanceLabel.zIndex = 9999; } } };
===================================================================
--- original.js
+++ change.js
@@ -2067,61 +2067,9 @@
for (var i = 0; i < explosions.length; i++) {
explosions[i].x -= shipDX;
explosions[i].y -= shipDY;
}
- // Move all event and station objects with the camera so they are reachable
- if (window.derelictShip) {
- window.derelictShip.x -= shipDX;
- window.derelictShip.y -= shipDY;
- if (window.derelictShip._label) {
- window.derelictShip._label.x -= shipDX;
- window.derelictShip._label.y -= shipDY;
- }
- }
- if (window.debrisField) {
- window.debrisField.x -= shipDX;
- window.debrisField.y -= shipDY;
- if (window.debrisField.label) {
- window.debrisField.label.x -= shipDX;
- window.debrisField.label.y -= shipDY;
- }
- if (window.debrisField.debris) {
- for (var i = 0; i < window.debrisField.debris.length; i++) {
- if (window.debrisField.debris[i]) {
- window.debrisField.debris[i].x -= shipDX;
- window.debrisField.debris[i].y -= shipDY;
- }
- }
- }
- }
- if (window.distressEvent) {
- window.distressEvent.x -= shipDX;
- window.distressEvent.y -= shipDY;
- if (window.distressEvent.signal) {
- window.distressEvent.signal.x -= shipDX;
- window.distressEvent.signal.y -= shipDY;
- }
- if (window.distressEvent.label) {
- window.distressEvent.label.x -= shipDX;
- window.distressEvent.label.y -= shipDY;
- }
- if (window.distressEvent.panel) {
- window.distressEvent.panel.x -= shipDX;
- window.distressEvent.panel.y -= shipDY;
- }
- if (window.distressEvent.text) {
- window.distressEvent.text.x -= shipDX;
- window.distressEvent.text.y -= shipDY;
- }
- if (window.distressEvent.helpBtn) {
- window.distressEvent.helpBtn.x -= shipDX;
- window.distressEvent.helpBtn.y -= shipDY;
- }
- if (window.distressEvent.ignoreBtn) {
- window.distressEvent.ignoreBtn.x -= shipDX;
- window.distressEvent.ignoreBtn.y -= shipDY;
- }
- }
+ // (Removed camera-follow for event and quest objects so they stay at their spawn location)
// Auto fire at very close pirates or asteroids
// Saldırı mesafesi %10 arttırıldı (200 -> 220)
var ATTACK_RANGE = 220;
if (LK.ticks - ship.lastFire > ship.fireRate && (pirates.length > 0 || asteroids.length > 0)) {
Uzay temalı global Cevher ticareti, gerçekçi, Altında "Trade" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı global Cevher ticareti, uzay istasyonu, gerçekçi, Altında "Space Stations" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı global Cevher deposu, uzay kargosu, gerçekçi, Altında "Storage" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı Gemi Geliştirme, Tamirci İstasyonu, gerçekçi, Altında "Upgrade" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı global Achievements, gerçekçi, Altında "Achievements" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı, içi altın dolu kapağı açık kasa, gerçekçi, In-Game asset. High contrast. No shadows
Uzay temalı Spaceship Crew, gerçekçi, Altında "crew" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı altın coin, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı asteroid, üzerinde cevherler bulunsun, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows