User prompt
Tank sınıfının sinerjisini değiştir yerine tank şampiyonlar 1 can kazansın
User prompt
Tank sınıfı birleşince 2 turda tank kartlar 1 can yenilesin
User prompt
Kolay mod da rakibin kulesinin canı 15 oyuncunun 20 orta mod da ikisininki de 20 zor mod da rakibin kulesi 25 can olsun
User prompt
Bu yazıyı daha aşağı al
User prompt
Gelecek tur kaç mana geleceği sağ tarafta yazsın
User prompt
Her tur 1 mana gelsin 3 turda 1 2 mana gelsin
User prompt
Bütün laneleri birleştir
User prompt
Rakip 2 mana ile başlasın
User prompt
Laneler arasında boşluk olsun
User prompt
Lane 1 lane 2 lane 3 lane 4 arasında eşit boşluklar olsun
User prompt
Her lane arasında aynı boşluk olsun
User prompt
Laneler aralıklı olsun
User prompt
Lane 4 ekle
User prompt
Golem 3 mana yap
User prompt
Michael demiurgos hasarını 2 canını 7 yap
User prompt
Drake karakterinin hasarını 3 canını 4 yap
User prompt
Luciferin pasifindeki iyileşmeyi 1 yap canını 6 yap
User prompt
Lightning karakterinin hasarını 1 canını 5 yap
User prompt
Air karakterinin manasını 1 hasarını 1 canını 3 yap
User prompt
Golem karakterinin manasını 4 hasarını 1 canını 10 yap
User prompt
Water karakterinin hasarını 2 canını 4 yap
User prompt
Fire karakterinin manasını 3 yap hasarı 2 canı 5 olsun
User prompt
Freeze 2 manaya düşür
User prompt
Şifa verdiği canı 2 ye düşür
User prompt
Fireball manasını ve hasarını 2 yap
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Card = Container.expand(function (cardData) { var self = Container.call(this); // Card properties self.cardData = cardData || { name: "Basic Card", cost: 1, attack: 2, health: 2, description: "A basic creature card", passive: null // Passive ability type }; // Damage tracking to prevent duplicate triggers self.damageDealtThisTurn = 0; self.hasTriggeredLifeSteal = false; // Ensure cardData has valid numeric values if (typeof self.cardData.attack !== 'number' || isNaN(self.cardData.attack)) { self.cardData.attack = 2; } if (typeof self.cardData.health !== 'number' || isNaN(self.cardData.health)) { self.cardData.health = 2; } if (typeof self.cardData.cost !== 'number' || isNaN(self.cardData.cost)) { self.cardData.cost = 1; } // Initialize passive abilities based on card name if not already set if (!self.cardData.passive) { switch (self.cardData.name) { case "Fire Imp": self.cardData.passive = "burn"; break; case "Water Spirit": self.cardData.passive = "heal"; break; case "Earth Golem": self.cardData.passive = "taunt"; break; case "Air Wisp": self.cardData.passive = "evasion"; break; case "Lightning Bolt": self.cardData.passive = "shock"; break; case "Lucifer": self.cardData.passive = "lifesteal"; break; case "Shadow Drake": self.cardData.passive = "stealth"; break; case "Michael Demiurgos": self.cardData.passive = "divine_shield"; break; } } self.maxHealth = self.cardData.health; self.currentHealth = self.cardData.health; self.synergyAttackBonus = 0; // Track synergy bonuses self.synergyHealthBonus = 0; self.synergyHealthRegen = 0; // Track health regeneration per turn self.synergyRage = false; // Track rage mechanic for Mage cards self.frozenTurns = 0; // Track frozen state duration self.isPlayable = false; self.isOnBattlefield = false; self.hasAttacked = false; // Create card graphics based on card type var cardAssetName = 'cardBack'; // default var symbolAssetName = null; // Determine assets based on card name switch (self.cardData.name) { case "Fire Imp": cardAssetName = 'fireImpBg'; symbolAssetName = 'fireImpSymbol'; break; case "Water Spirit": cardAssetName = 'waterSpiritBg'; symbolAssetName = 'waterSpiritSymbol'; break; case "Earth Golem": cardAssetName = 'earthGolemBg'; symbolAssetName = 'earthGolemSymbol'; break; case "Air Wisp": cardAssetName = 'airWispBg'; symbolAssetName = 'airWispSymbol'; break; case "Lightning Bolt": cardAssetName = 'lightningBoltBg'; symbolAssetName = 'lightningBoltSymbol'; break; case "Lucifer": cardAssetName = 'walterSpiritBg'; symbolAssetName = 'walterSpiritSymbol'; break; case "Shadow Drake": cardAssetName = 'shadowDrakeBg'; symbolAssetName = 'shadowDrakeSymbol'; break; case "Michael Demiurgos": cardAssetName = 'michaelDemiurgosBg'; symbolAssetName = 'michaelDemiurgosSymbol'; break; } var cardBg = self.attachAsset(cardAssetName, { anchorX: 0.5, anchorY: 0.5 }); // Add symbol if available if (symbolAssetName) { var cardSymbol = self.attachAsset(symbolAssetName, { anchorX: 0.5, anchorY: 0.5 }); cardSymbol.x = 0; cardSymbol.y = -20; // Position symbol in upper middle area } // Add class indicators for cards var classAsset = null; if (self.cardData.name === "Earth Golem" || self.cardData.name === "Lightning Bolt") { classAsset = self.attachAsset('tankClass', { anchorX: 1, anchorY: 0 }); classAsset.x = 80; // Top right corner classAsset.y = -100; } else if (self.cardData.name === "Fire Imp" || self.cardData.name === "Water Spirit") { classAsset = self.attachAsset('mageClass', { anchorX: 1, anchorY: 0 }); classAsset.x = 80; // Top right corner classAsset.y = -100; } else if (self.cardData.name === "Air Wisp" || self.cardData.name === "Shadow Drake") { classAsset = self.attachAsset('rogueClass', { anchorX: 1, anchorY: 0 }); classAsset.x = 80; // Top right corner classAsset.y = -100; } else if (self.cardData.name === "Lucifer" || self.cardData.name === "Michael Demiurgos") { classAsset = self.attachAsset('warriorClass', { anchorX: 1, anchorY: 0 }); classAsset.x = 80; // Top right corner classAsset.y = -100; } // Card text elements - name removed var costText = new Text2(self.cardData.cost.toString(), { size: 32, fill: 0x9B59B6 }); costText.anchor.set(0.5, 0.5); costText.x = -70; costText.y = -100; self.addChild(costText); var attackText = new Text2(self.cardData.attack.toString(), { size: 28, fill: 0xE74C3C }); attackText.anchor.set(0.5, 0.5); attackText.x = -50; attackText.y = 90; self.addChild(attackText); // Store reference to attack text for potential updates self.attackText = attackText; var healthText = new Text2(self.currentHealth.toString(), { size: 28, fill: 0x27AE60 }); healthText.anchor.set(0.5, 0.5); healthText.x = 50; healthText.y = 90; self.addChild(healthText); // Store reference to health text self.healthText = healthText; self.updateHealthDisplay = function () { // Calculate health with synergy bonus (Tank cards don't get health bonus display) var cardClass = getCardClass(self.cardData.name); var healthBonus = cardClass === "Tank" ? 0 : self.synergyHealthBonus || 0; var synergyMaxHealth = self.cardData.health + healthBonus; var adjustedCurrentHealth = self.currentHealth + healthBonus; var displayHealth = isNaN(adjustedCurrentHealth) ? 0 : Math.max(0, adjustedCurrentHealth); // Ensure currentHealth is always a valid number if (isNaN(self.currentHealth)) { self.currentHealth = 0; } if (isNaN(self.maxHealth)) { self.maxHealth = self.cardData.health || 1; } // Update health text display with synergy bonus if (self.healthText) { self.healthText.setText(displayHealth.toString()); // Change color if synergy bonus is active (excluding Tank regen) var cardClass = getCardClass(self.cardData.name); if (healthBonus > 0 && cardClass !== "Tank") { self.healthText.fill = 0x00ff00; // Green for boosted health } else { self.healthText.fill = 0x27AE60; // Normal green } } else if (healthText) { healthText.setText(displayHealth.toString()); } // Update attack text with synergy bonus if (self.attackText && self.cardData.attack !== undefined) { var displayAttack = self.cardData.attack + (self.synergyAttackBonus || 0); self.attackText.setText(displayAttack.toString()); // Change color if synergy bonus is active (but not for Mage rage) var cardClass = getCardClass(self.cardData.name); if (self.synergyAttackBonus > 0) { self.attackText.fill = 0x00ff00; // Green for boosted attack } else if (self.synergyRage && cardClass === "Mage") { self.attackText.fill = 0xFF4444; // Red glow for rage-enabled Mage cards } else { self.attackText.fill = 0xE74C3C; // Normal red } } // Debug log for Lightning Bolt if (self.cardData.name === "Lightning Bolt") { console.log("Lightning Bolt health - current:", self.currentHealth, "max:", self.maxHealth, "display:", displayHealth); } if (self.currentHealth <= 0) { cardBg.alpha = 0.5; } }; self.takeDamage = function (damage, attacker) { // Ensure damage is a valid number but don't reduce it to 0 unnecessarily if (typeof damage !== 'number' || isNaN(damage)) { damage = 0; } if (damage < 0) { damage = 0; } // Check for damage prevention passives var passiveResult = self.triggerPassive("before_damage", { attacker: attacker, damage: damage }); if (passiveResult === -1) { // Damage was negated by passive ability return; } var finalDamage = Math.max(0, damage); self.currentHealth -= finalDamage; // Ensure currentHealth is always a valid number if (isNaN(self.currentHealth)) { self.currentHealth = 0; } self.updateHealthDisplay(); // If card dies, remove it immediately if (self.currentHealth <= 0) { // Check if card is on battlefield before trying to find player var ownerPlayer = null; if (self.isOnBattlefield) { // Safely check which player owns this card for (var i = 0; i < humanPlayer.battlefield.length; i++) { if (humanPlayer.battlefield[i] === self) { ownerPlayer = humanPlayer; break; } } if (!ownerPlayer) { for (var i = 0; i < aiPlayer.battlefield.length; i++) { if (aiPlayer.battlefield[i] === self) { ownerPlayer = aiPlayer; break; } } } } // Trigger death passive before removing if (ownerPlayer) { self.triggerPassive("death", { player: ownerPlayer }); } // Remove from battlefield arrays and add new card to deck var humanIndex = humanPlayer.battlefield.indexOf(self); if (humanIndex >= 0) { humanPlayer.battlefield.splice(humanIndex, 1); // Create a new card with the same data instead of resetting this one var newCard = new Card(self.cardData); newCard.validateStats(); // Ensure stats are correct // Add new card to human player's deck humanPlayer.deck.push(newCard); } var aiIndex = aiPlayer.battlefield.indexOf(self); if (aiIndex >= 0) { aiPlayer.battlefield.splice(aiIndex, 1); // Create a new card with the same data instead of resetting this one var newCard = new Card(self.cardData); newCard.validateStats(); // Ensure stats are correct // Add new card to AI player's deck aiPlayer.deck.push(newCard); } // Clear lane assignment self.laneIndex = undefined; self.isOnBattlefield = false; // Death animation and removal from game animateCardDeath(self); LK.setTimeout(function () { if (game.children.includes(self)) { game.removeChild(self); } // Update battlefield layout after card removal arrangeBattlefield(); }, 600); // Match the death animation duration } // Lucifer passive: heal 1 health when dealing damage to other cards if (attacker && attacker.cardData.name === "Lucifer" && self.isOnBattlefield) { // Heal Lucifer by 1 health (not exceeding max health) var healAmount = 1; attacker.currentHealth = Math.min(attacker.maxHealth, attacker.currentHealth + healAmount); attacker.updateHealthDisplay(); // Create healing visual effect var healText = new Text2("+" + healAmount.toString(), { size: 40, fill: 0x00ff00 }); healText.anchor.set(0.5, 0.5); healText.x = attacker.x + (Math.random() - 0.5) * 60; healText.y = attacker.y - 50; healText.alpha = 1.0; game.addChild(healText); // Animate healing number floating up and fading tween(healText, { y: healText.y - 80, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(healText); } }); // Brief green flash on Lucifer LK.effects.flashObject(attacker, 0x00ff00, 300); } // Vampire passive: heal equal to damage dealt if (attacker && attacker.isOnBattlefield && getCardClass(attacker.cardData.name) === "Vampire") { // Check if vampire synergy is active (2 or more vampire cards) var attackerPlayer = null; // Find which player owns the attacker for (var i = 0; i < humanPlayer.battlefield.length; i++) { if (humanPlayer.battlefield[i] === attacker) { attackerPlayer = humanPlayer; break; } } if (!attackerPlayer) { for (var i = 0; i < aiPlayer.battlefield.length; i++) { if (aiPlayer.battlefield[i] === attacker) { attackerPlayer = aiPlayer; break; } } } if (attackerPlayer) { // Count vampire cards on battlefield var vampireCount = 0; for (var i = 0; i < attackerPlayer.battlefield.length; i++) { if (getCardClass(attackerPlayer.battlefield[i].cardData.name) === "Vampire") { vampireCount++; } } // Vampire synergy triggers with 2 or more vampire cards if (vampireCount >= 2) { var healAmount = finalDamage; // Heal equal to damage dealt var oldHealth = attacker.currentHealth; attacker.currentHealth = Math.min(attacker.maxHealth, attacker.currentHealth + healAmount); // Only show effect if health was actually restored if (attacker.currentHealth > oldHealth) { var actualHeal = attacker.currentHealth - oldHealth; attacker.updateHealthDisplay(); // Create vampire healing visual effect var vampireHealText = new Text2("+" + actualHeal.toString(), { size: 38, fill: 0x8B0000 // Dark red for vampire heal }); vampireHealText.anchor.set(0.5, 0.5); vampireHealText.x = attacker.x + (Math.random() - 0.5) * 60; vampireHealText.y = attacker.y - 60; vampireHealText.alpha = 1.0; game.addChild(vampireHealText); // Animate vampire healing with blood-like effect tween(vampireHealText, { y: vampireHealText.y - 90, alpha: 0, scaleX: 1.4, scaleY: 1.4 }, { duration: 900, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(vampireHealText); } }); // Dark red flash on vampire card LK.effects.flashObject(attacker, 0x8B0000, 400); } } } } // Enhanced damage animation // Screen shake for significant damage if (damage >= 3) { LK.effects.flashScreen(0xff4444, 200); } // Damage number popup animation var damageText = new Text2("-" + damage.toString(), { size: 40, fill: 0xff0000 }); damageText.anchor.set(0.5, 0.5); damageText.x = self.x + (Math.random() - 0.5) * 60; damageText.y = self.y - 50; damageText.alpha = 1.0; game.addChild(damageText); // Animate damage number floating up and fading tween(damageText, { y: damageText.y - 80, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(damageText); } }); // Card damage animation - recoil and flash tween(self, { x: self.x + (Math.random() - 0.5) * 30, y: self.y + (Math.random() - 0.5) * 20, scaleX: 0.9, scaleY: 0.9, tint: 0xff4444 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { x: self.x, y: self.y, scaleX: 1.0, scaleY: 1.0, tint: 0xFFFFFF }, { duration: 300, easing: tween.easeOut }); } }); // Flash red when taking damage LK.effects.flashObject(self, 0xff0000, 500); }; self.canAttack = function () { return self.isOnBattlefield && !self.hasAttacked && self.currentHealth > 0 && (!self.frozenTurns || self.frozenTurns <= 0); }; self.attack = function (target) { if (self.canAttack() && target) { // Check if both cards are in the same lane if (self.laneIndex !== undefined && target.laneIndex !== undefined && self.laneIndex !== target.laneIndex) { return; // Cannot attack cards in different lanes } // Store original position var originalX = self.x; var originalY = self.y; // Calculate target position (move towards target) var targetX = target.x; var targetY = target.y; // Animate attack: move toward target, then back tween(self, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Collision animation - both cards shake and flash on impact var collisionDuration = 150; // Shake the attacking card tween(self, { x: targetX + 20 }, { duration: collisionDuration / 3, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { x: targetX - 20 }, { duration: collisionDuration / 3, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { x: targetX }, { duration: collisionDuration / 3, easing: tween.easeInOut }); } }); } }); // Shake the target card tween(target, { x: target.x - 15 }, { duration: collisionDuration / 3, easing: tween.easeInOut, onFinish: function onFinish() { tween(target, { x: target.x + 15 }, { duration: collisionDuration / 3, easing: tween.easeInOut, onFinish: function onFinish() { tween(target, { x: target.x }, { duration: collisionDuration / 3, easing: tween.easeInOut }); } }); } }); // Flash both cards white for collision effect tween(self, { tint: 0xFFFFFF }, { duration: collisionDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { tint: 0xFFFFFF }, { duration: collisionDuration, easing: tween.easeInOut }); } }); tween(target, { tint: 0xFFFFFF }, { duration: collisionDuration, easing: tween.easeInOut, onFinish: function onFinish() { tween(target, { tint: 0xFFFFFF }, { duration: collisionDuration, easing: tween.easeInOut }); } }); // Use base attack value plus synergy bonus var totalDamage = self.cardData.attack + (self.synergyAttackBonus || 0); // Apply Mage rage mechanic if enabled var isCriticalHit = false; if (self.synergyRage && Math.random() < 0.5) { totalDamage *= 2; // Double damage on rage proc isCriticalHit = true; // Critical hit screen flash LK.effects.flashScreen(0xFFD700, 400); // Show critical hit effect var critText = new Text2("KRİTİK VURUŞ!", { size: 50, fill: 0xFFD700 }); critText.anchor.set(0.5, 0.5); critText.x = self.x + (Math.random() - 0.5) * 60; critText.y = self.y - 80; critText.alpha = 1.0; game.addChild(critText); // Create sparkle effects around the attacking card for (var sparkle = 0; sparkle < 6; sparkle++) { var spark = game.addChild(LK.getAsset('manaOrb', { anchorX: 0.5, anchorY: 0.5, x: self.x + (Math.random() - 0.5) * 120, y: self.y + (Math.random() - 0.5) * 120, scaleX: 0.3, scaleY: 0.3, alpha: 1.0, tint: 0xFFD700 })); // Animate sparkles tween(spark, { scaleX: 0.8, scaleY: 0.8, alpha: 0, x: spark.x + (Math.random() - 0.5) * 200, y: spark.y + (Math.random() - 0.5) * 200 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { if (game.children.includes(spark)) { game.removeChild(spark); } } }); } // Animate critical text with glow effect tween(critText, { y: critText.y - 80, alpha: 0, scaleX: 2.0, scaleY: 2.0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(critText); } }); // Enhanced card flash for critical hit tween(self, { tint: 0xFFD700, scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { tint: 0xFFFFFF, scaleX: 1.0, scaleY: 1.0 }, { duration: 300, easing: tween.easeIn }); } }); } // Ensure we're using a clean integer value if (typeof totalDamage !== 'number' || isNaN(totalDamage)) { totalDamage = self.cardData.attack; } // Debug logging for attacks console.log("Card attacking:", self.cardData.name, "(" + totalDamage + " damage) ->", target.cardData.name, "(" + target.currentHealth + " health)"); // Deal exact damage as written on card target.takeDamage(totalDamage, self); // After collision, animate return to original position LK.setTimeout(function () { tween(self, { x: originalX, y: originalY }, { duration: 300, easing: tween.easeIn }); }, collisionDuration); } }); self.hasAttacked = true; cardBg.alpha = 0.7; LK.getSound('attack').play(); } }; self.resetForNewTurn = function () { self.hasAttacked = false; self.damageDealtThisTurn = 0; self.hasTriggeredLifeSteal = false; // Handle frozen state if (self.frozenTurns > 0) { self.frozenTurns--; if (self.frozenTurns <= 0) { // Return to normal state when freeze ends self.alpha = 1.0; self.tint = 0xFFFFFF; // Remove blue tint } } if (self.currentHealth > 0) { cardBg.alpha = 1.0; } }; // Passive ability system self.triggerPassive = function (trigger, context) { if (!self.hasPassive()) return 0; var passiveType = self.cardData.passive; var effect = 0; switch (passiveType) { case "burn": if (trigger === "end_turn" && self.isOnBattlefield) { // Fire Imp: Burns all enemy cards for 1 damage at end of turn var enemyPlayer = context.player.isHuman ? aiPlayer : humanPlayer; for (var i = 0; i < enemyPlayer.battlefield.length; i++) { var enemyCard = enemyPlayer.battlefield[i]; if (enemyCard.currentHealth > 0) { enemyCard.takeDamage(1, self); // Create burn visual effect var burnEffect = game.addChild(LK.getAsset('burnEffect', { anchorX: 0.5, anchorY: 0.5, x: enemyCard.x + (Math.random() - 0.5) * 40, y: enemyCard.y - 30, alpha: 0.8, tint: 0xff4400 })); tween(burnEffect, { y: burnEffect.y - 60, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(burnEffect); } }); } } effect = 1; } break; case "heal": if (trigger === "turn_start" && self.isOnBattlefield) { // Water Spirit: Heals 1 health at start of turn var oldHealth = self.currentHealth; self.currentHealth = Math.min(self.maxHealth, self.currentHealth + 1); if (self.currentHealth > oldHealth) { self.updateHealthDisplay(); // Create healing visual effect var healText = new Text2("+1", { size: 30, fill: 0x00ff00 }); healText.anchor.set(0.5, 0.5); healText.x = self.x + (Math.random() - 0.5) * 40; healText.y = self.y - 30; healText.alpha = 1.0; game.addChild(healText); tween(healText, { y: healText.y - 60, alpha: 0, scaleX: 1.2, scaleY: 1.2 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(healText); } }); LK.effects.flashObject(self, 0x00ff00, 200); effect = 1; } } break; case "shock": if (trigger === "played") { // Lightning Bolt: Deals 3 damage to all enemies when played var enemyPlayer = context.player.isHuman ? aiPlayer : humanPlayer; for (var i = 0; i < enemyPlayer.battlefield.length; i++) { var enemyCard = enemyPlayer.battlefield[i]; if (enemyCard.currentHealth > 0) { enemyCard.takeDamage(3, self); } } // Screen flash for shock effect LK.effects.flashScreen(0xffff00, 300); effect = 1; } break; case "evasion": if (trigger === "before_damage" && Math.random() < 0.25) { // Air Wisp: 25% chance to dodge attacks var dodgeText = new Text2("DODGE!", { size: 35, fill: 0x00ffff }); dodgeText.anchor.set(0.5, 0.5); dodgeText.x = self.x; dodgeText.y = self.y - 50; dodgeText.alpha = 1.0; game.addChild(dodgeText); tween(dodgeText, { y: dodgeText.y - 80, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(dodgeText); } }); LK.effects.flashObject(self, 0x00ffff, 300); return -1; // Negative return indicates damage should be negated } break; case "divine_shield": if (trigger === "played" && !self.shieldUsed) { // Initialize divine shield when card is played self.shieldUsed = false; self.alpha = 0.9; // Slight transparency to indicate shield } if (trigger === "before_damage" && !self.shieldUsed) { // Michael Demiurgos: Ignores first damage taken self.shieldUsed = true; self.alpha = 1.0; // Return to normal transparency var shieldText = new Text2("DIVINE SHIELD!", { size: 35, fill: 0xffd700 }); shieldText.anchor.set(0.5, 0.5); shieldText.x = self.x; shieldText.y = self.y - 50; shieldText.alpha = 1.0; game.addChild(shieldText); tween(shieldText, { y: shieldText.y - 80, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(shieldText); } }); LK.effects.flashObject(self, 0xffd700, 400); return -1; // Negative return indicates damage should be negated } if (trigger === "before_damage" && self.shieldUsed && turnCounter > 1 && Math.random() < 0.1) { // Michael Demiurgos: 10% chance to avoid damage after first turn var dodgeText = new Text2("DIVINE PROTECTION!", { size: 35, fill: 0xffd700 }); dodgeText.anchor.set(0.5, 0.5); dodgeText.x = self.x; dodgeText.y = self.y - 50; dodgeText.alpha = 1.0; game.addChild(dodgeText); tween(dodgeText, { y: dodgeText.y - 80, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(dodgeText); } }); LK.effects.flashObject(self, 0xffd700, 300); return -1; // Negative return indicates damage should be negated } break; case "stealth": if (trigger === "played") { // Shadow Drake: Cannot be targeted by spells for first turn self.stealthTurns = 1; var stealthText = new Text2("STEALTH", { size: 30, fill: 0x8b008b }); stealthText.anchor.set(0.5, 0.5); stealthText.x = self.x; stealthText.y = self.y - 50; stealthText.alpha = 1.0; game.addChild(stealthText); tween(stealthText, { y: stealthText.y - 60, alpha: 0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(stealthText); } }); self.alpha = 0.7; // Visual indicator of stealth effect = 1; } else if (trigger === "turn_start" && self.stealthTurns > 0) { self.stealthTurns--; if (self.stealthTurns <= 0) { self.alpha = 1.0; // Return to normal visibility } } break; case "taunt": // Earth Golem: Forces enemies to attack this card first // This is handled in AI targeting logic and combat resolution break; } return effect; }; self.hasPassive = function () { return self.cardData.passive !== null && self.cardData.passive !== undefined; }; // Method to validate and fix card stats self.validateStats = function () { // Ensure all stats are valid numbers if (typeof self.cardData.attack !== 'number' || isNaN(self.cardData.attack)) { self.cardData.attack = 1; } if (typeof self.cardData.health !== 'number' || isNaN(self.cardData.health)) { self.cardData.health = 1; } if (typeof self.cardData.cost !== 'number' || isNaN(self.cardData.cost)) { self.cardData.cost = 1; } if (typeof self.currentHealth !== 'number' || isNaN(self.currentHealth)) { self.currentHealth = self.cardData.health; } if (typeof self.maxHealth !== 'number' || isNaN(self.maxHealth)) { self.maxHealth = self.cardData.health; } // Ensure current health doesn't exceed max health if (self.currentHealth > self.maxHealth) { self.currentHealth = self.maxHealth; } // Update display after validation self.updateHealthDisplay(); }; return self; }); var DeckView = Container.expand(function () { var self = Container.call(this); // Dark overlay background var overlay = self.attachAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.9 }); // Title var titleText = new Text2("KART VE BÜYÜ KOLEKSİYONU", { size: 80, fill: 0xf39c12 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 200; self.addChild(titleText); // Cards section title var cardsTitle = new Text2("KARTLAR", { size: 60, fill: 0x3498db }); cardsTitle.anchor.set(0.5, 0.5); cardsTitle.x = 1024; cardsTitle.y = 350; self.addChild(cardsTitle); // Spells section title var spellsTitle = new Text2("BÜYÜLER", { size: 60, fill: 0x9b59b6 }); spellsTitle.anchor.set(0.5, 0.5); spellsTitle.x = 1024; spellsTitle.y = 1800; self.addChild(spellsTitle); // Close button var closeBtn = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2400, scaleX: 0.8, scaleY: 0.8 }); // Create sample cards for display var cardTypes = [{ name: "Fire Imp", cost: 3, attack: 2, health: 5, description: "A small fire creature", passive: "burn" }, { name: "Water Spirit", cost: 2, attack: 2, health: 4, description: "A defensive water creature", passive: "heal" }, { name: "Earth Golem", cost: 3, attack: 1, health: 10, description: "A powerful earth creature", passive: "taunt" }, { name: "Air Wisp", cost: 1, attack: 1, health: 3, description: "A quick air creature", passive: "evasion" }, { name: "Lightning Bolt", cost: 2, attack: 1, health: 5, description: "A shocking creature", passive: "shock" }, { name: "Lucifer", cost: 4, attack: 3, health: 6, description: "A mystical water spirit with high endurance", passive: "lifesteal" }, { name: "Shadow Drake", cost: 3, attack: 3, health: 4, description: "A powerful shadow dragon", passive: "stealth" // Cannot be targeted by spells for first turn }, { name: "Michael Demiurgos", cost: 4, attack: 2, health: 7, description: "An archangel with divine power", passive: "divine_shield" }]; // Display cards in a grid (4 cards per row) self.displayCards = []; for (var i = 0; i < cardTypes.length; i++) { var displayCard = new Card(cardTypes[i]); var row = Math.floor(i / 4); var col = i % 4; var startX = 1024 - 3 * 100; // Center 4 cards displayCard.x = startX + col * 200; displayCard.y = 500 + row * 300; displayCard.scaleX = 0.6; displayCard.scaleY = 0.6; self.addChild(displayCard); self.displayCards.push(displayCard); // Add class logos to cards in deck view var classAsset = null; if (cardTypes[i].name === "Earth Golem" || cardTypes[i].name === "Lightning Bolt") { classAsset = self.attachAsset('tankClass', { anchorX: 1, anchorY: 0 }); classAsset.x = displayCard.x + 48; // Adjusted for scaled card classAsset.y = displayCard.y - 60; classAsset.scaleX = 0.6; classAsset.scaleY = 0.6; } else if (cardTypes[i].name === "Fire Imp" || cardTypes[i].name === "Water Spirit") { classAsset = self.attachAsset('mageClass', { anchorX: 1, anchorY: 0 }); classAsset.x = displayCard.x + 48; // Adjusted for scaled card classAsset.y = displayCard.y - 60; classAsset.scaleX = 0.6; classAsset.scaleY = 0.6; } else if (cardTypes[i].name === "Air Wisp" || cardTypes[i].name === "Shadow Drake") { classAsset = self.attachAsset('rogueClass', { anchorX: 1, anchorY: 0 }); classAsset.x = displayCard.x + 48; // Adjusted for scaled card classAsset.y = displayCard.y - 60; classAsset.scaleX = 0.6; classAsset.scaleY = 0.6; } else if (cardTypes[i].name === "Lucifer" || cardTypes[i].name === "Michael Demiurgos") { classAsset = self.attachAsset('warriorClass', { anchorX: 1, anchorY: 0 }); classAsset.x = displayCard.x + 48; // Adjusted for scaled card classAsset.y = displayCard.y - 60; classAsset.scaleX = 0.6; classAsset.scaleY = 0.6; } } // Create sample spells for display var spellTypes = [{ name: "Fire Ball", cost: 2, damage: 2, target: "enemy", description: "Deals 2 damage to target" }, { name: "Şifa", cost: 2, damage: -2, target: "ally", description: "Heals target for 2 health" }, { name: "Freeze", cost: 2, damage: 0, target: "enemy", description: "Freezes target enemy for 1 turn" }]; // Display spells self.displaySpells = []; for (var i = 0; i < spellTypes.length; i++) { var displaySpell = new Spell(spellTypes[i]); displaySpell.x = 1024 - 100 + i * 200; displaySpell.y = 1950; displaySpell.scaleX = 0.8; displaySpell.scaleY = 0.8; self.addChild(displaySpell); self.displaySpells.push(displaySpell); } self.closeButtonHover = false; self.down = function (x, y, obj) { // If showing zoom, hide it first if (self.isShowingZoom) { self.hideCardZoom(); return; } // Check if close button was clicked if (x >= 824 && x <= 1224 && y >= 2360 && y <= 2440) { // Button press effect tween(closeBtn, { scaleX: 0.75, scaleY: 0.75, tint: 0x2980b9 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(closeBtn, { scaleX: 0.8, scaleY: 0.8, tint: 0x3498db }, { duration: 100, easing: tween.easeOut }); } }); // Close deck view after animation LK.setTimeout(function () { self.closeDeckView(); }, 200); return; } // Check if any card was clicked for zoom preview for (var i = 0; i < self.displayCards.length; i++) { var card = self.displayCards[i]; var cardBounds = { left: card.x - 54, // card.scaleX is 0.6, so bounds are 90*0.6 = 54 right: card.x + 54, top: card.y - 75, // card.scaleY is 0.6, so bounds are 125*0.6 = 75 bottom: card.y + 75 }; if (x >= cardBounds.left && x <= cardBounds.right && y >= cardBounds.top && y <= cardBounds.bottom) { self.showCardZoom(card); return; } } // Check if any spell was clicked for zoom preview for (var i = 0; i < self.displaySpells.length; i++) { var spell = self.displaySpells[i]; var spellBounds = { left: spell.x - 48, // spell.scaleX is 0.8, so bounds are 60*0.8 = 48 right: spell.x + 48, top: spell.y - 48, // spell.scaleY is 0.8, so bounds are 60*0.8 = 48 bottom: spell.y + 48 }; if (x >= spellBounds.left && x <= spellBounds.right && y >= spellBounds.top && y <= spellBounds.bottom) { self.showSpellZoom(spell); return; } } }; self.move = function (x, y, obj) { // Check if mouse is over close button var isOverCloseButton = x >= 824 && x <= 1224 && y >= 2360 && y <= 2440; if (isOverCloseButton && !self.closeButtonHover) { self.closeButtonHover = true; tween(closeBtn, { scaleX: 0.9, scaleY: 0.9, tint: 0x5dade2 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverCloseButton && self.closeButtonHover) { self.closeButtonHover = false; tween(closeBtn, { scaleX: 0.8, scaleY: 0.8, tint: 0x3498db }, { duration: 200, easing: tween.easeOut }); } }; self.closeDeckView = function () { // Fade out deck view tween(self, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { // Remove deck view and return to menu game.removeChild(self); } }); }; // Entrance animation self.alpha = 0; self.scaleX = 0.8; self.scaleY = 0.8; tween(self, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 600, easing: tween.easeOut }); // Card zoom preview variables for deck view self.zoomCard = null; self.zoomBg = null; self.zoomTexts = []; self.isShowingZoom = false; self.showCardZoom = function (card) { if (self.isShowingZoom) { self.hideCardZoom(); } // Create dark overlay self.zoomBg = self.attachAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.95 }); // Create zoomed card self.zoomCard = new Card(card.cardData); self.zoomCard.x = 1024; self.zoomCard.y = 1200; self.zoomCard.scaleX = 3.0; self.zoomCard.scaleY = 3.0; self.addChild(self.zoomCard); // Card name var nameText = new Text2(card.cardData.name, { size: 80, fill: 0xf39c12 }); nameText.anchor.set(0.5, 0.5); nameText.x = 1024; nameText.y = 800; self.addChild(nameText); self.zoomTexts.push(nameText); // Card stats var statsText = new Text2("Mana: " + card.cardData.cost + " | Saldırı: " + card.cardData.attack + " | Can: " + card.cardData.health, { size: 48, fill: 0x3498db }); statsText.anchor.set(0.5, 0.5); statsText.x = 1024; statsText.y = 900; self.addChild(statsText); self.zoomTexts.push(statsText); // Card description var descText = new Text2(card.cardData.description, { size: 40, fill: 0xecf0f1 }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = 1600; self.addChild(descText); self.zoomTexts.push(descText); // Passive abilities var passiveDesc = card.hasPassive() ? getPassiveDescription(card.cardData.passive) : "Yok"; var passiveText = new Text2("Pasif Yetenek: " + passiveDesc, { size: 36, fill: card.hasPassive() ? 0xf39c12 : 0x95a5a6 }); passiveText.anchor.set(0.5, 0.5); passiveText.x = 1024; passiveText.y = 1700; self.addChild(passiveText); self.zoomTexts.push(passiveText); // Close instruction var closeText = new Text2("Kapatmak için herhangi bir yere tıklayın", { size: 32, fill: 0x7f8c8d }); closeText.anchor.set(0.5, 0.5); closeText.x = 1024; closeText.y = 2000; self.addChild(closeText); self.zoomTexts.push(closeText); // Animate zoom in self.zoomCard.alpha = 0; self.zoomCard.scaleX = 1.0; self.zoomCard.scaleY = 1.0; tween(self.zoomCard, { alpha: 1.0, scaleX: 3.0, scaleY: 3.0 }, { duration: 400, easing: tween.easeOut }); for (var i = 0; i < self.zoomTexts.length; i++) { self.zoomTexts[i].alpha = 0; tween(self.zoomTexts[i], { alpha: 1.0 }, { duration: 400, easing: tween.easeOut }); } self.isShowingZoom = true; }; self.showSpellZoom = function (spell) { if (self.isShowingZoom) { self.hideCardZoom(); } // Create dark overlay self.zoomBg = self.attachAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.95 }); // Create zoomed spell self.zoomCard = new Spell(spell.spellData); self.zoomCard.x = 1024; self.zoomCard.y = 1200; self.zoomCard.scaleX = 4.0; self.zoomCard.scaleY = 4.0; self.addChild(self.zoomCard); // Spell name var nameText = new Text2(spell.spellData.name, { size: 80, fill: 0x9b59b6 }); nameText.anchor.set(0.5, 0.5); nameText.x = 1024; nameText.y = 800; self.addChild(nameText); self.zoomTexts.push(nameText); // Spell stats var effectText = spell.spellData.damage >= 0 ? "Hasar: " + spell.spellData.damage : "İyileştirme: " + Math.abs(spell.spellData.damage); var statsText = new Text2("Mana: " + spell.spellData.cost + " | " + effectText + " | Hedef: " + (spell.spellData.target === "enemy" ? "Düşman" : "Müttefik"), { size: 48, fill: 0x3498db }); statsText.anchor.set(0.5, 0.5); statsText.x = 1024; statsText.y = 900; self.addChild(statsText); self.zoomTexts.push(statsText); // Spell description var descText = new Text2(spell.spellData.description, { size: 40, fill: 0xecf0f1 }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = 1600; self.addChild(descText); self.zoomTexts.push(descText); // Close instruction var closeText = new Text2("Kapatmak için herhangi bir yere tıklayın", { size: 32, fill: 0x7f8c8d }); closeText.anchor.set(0.5, 0.5); closeText.x = 1024; closeText.y = 2000; self.addChild(closeText); self.zoomTexts.push(closeText); // Animate zoom in self.zoomCard.alpha = 0; self.zoomCard.scaleX = 1.0; self.zoomCard.scaleY = 1.0; tween(self.zoomCard, { alpha: 1.0, scaleX: 4.0, scaleY: 4.0 }, { duration: 400, easing: tween.easeOut }); for (var i = 0; i < self.zoomTexts.length; i++) { self.zoomTexts[i].alpha = 0; tween(self.zoomTexts[i], { alpha: 1.0 }, { duration: 400, easing: tween.easeOut }); } self.isShowingZoom = true; }; self.hideCardZoom = function () { if (!self.isShowingZoom) return; // Animate zoom out if (self.zoomCard) { tween(self.zoomCard, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { self.removeChild(self.zoomCard); self.zoomCard = null; } }); } // Animate text fade out for (var i = 0; i < self.zoomTexts.length; i++) { var text = self.zoomTexts[i]; tween(text, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { self.removeChild(text); } }); } // Remove background if (self.zoomBg) { tween(self.zoomBg, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { self.removeChild(self.zoomBg); self.zoomBg = null; } }); } self.zoomTexts = []; self.isShowingZoom = false; }; return self; }); var DifficultySelection = Container.expand(function () { var self = Container.call(this); // Dark overlay background var overlay = self.attachAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.9 }); // Title var titleText = new Text2("ZORLUK SEÇİN", { size: 100, fill: 0xf39c12 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; self.addChild(titleText); // Easy button var easyBtn = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1000, tint: 0x27ae60 }); var easyBtnText = new Text2("KOLAY", { size: 56, fill: 0xffffff }); easyBtnText.anchor.set(0.5, 0.5); easyBtnText.x = 1024; easyBtnText.y = 1080; self.addChild(easyBtnText); // Medium button var mediumBtn = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1300, tint: 0xf39c12 }); var mediumBtnText = new Text2("ORTA", { size: 56, fill: 0xffffff }); mediumBtnText.anchor.set(0.5, 0.5); mediumBtnText.x = 1024; mediumBtnText.y = 1380; self.addChild(mediumBtnText); // Hard button var hardBtn = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1600, tint: 0xe74c3c }); var hardBtnText = new Text2("ZOR", { size: 56, fill: 0xffffff }); hardBtnText.anchor.set(0.5, 0.5); hardBtnText.x = 1024; hardBtnText.y = 1680; self.addChild(hardBtnText); // Back button var backBtn = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1850, scaleX: 0.8, scaleY: 0.8, tint: 0x95a5a6 }); // Button hover tracking self.easyButtonHover = false; self.mediumButtonHover = false; self.hardButtonHover = false; self.backButtonHover = false; self.down = function (x, y, obj) { // Check if easy button was clicked if (x >= 824 && x <= 1224 && y >= 940 && y <= 1060) { // Button press effect tween(easyBtn, { scaleX: 0.95, scaleY: 0.95, tint: 0x2ecc71 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(easyBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0x27ae60 }, { duration: 100, easing: tween.easeOut }); } }); // Start game with easy difficulty LK.setTimeout(function () { self.startGameWithDifficulty("easy"); }, 200); } // Check if medium button was clicked else if (x >= 824 && x <= 1224 && y >= 1240 && y <= 1360) { // Button press effect tween(mediumBtn, { scaleX: 0.95, scaleY: 0.95, tint: 0xe67e22 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(mediumBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0xf39c12 }, { duration: 100, easing: tween.easeOut }); } }); // Start game with medium difficulty LK.setTimeout(function () { self.startGameWithDifficulty("medium"); }, 200); } // Check if hard button was clicked else if (x >= 824 && x <= 1224 && y >= 1540 && y <= 1660) { // Button press effect tween(hardBtn, { scaleX: 0.95, scaleY: 0.95, tint: 0xc0392b }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(hardBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0xe74c3c }, { duration: 100, easing: tween.easeOut }); } }); // Start game with hard difficulty LK.setTimeout(function () { self.startGameWithDifficulty("hard"); }, 200); } // Check if back button was clicked else if (x >= 904 && x <= 1144 && y >= 1810 && y <= 1890) { // Button press effect tween(backBtn, { scaleX: 0.75, scaleY: 0.75, tint: 0x7f8c8d }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(backBtn, { scaleX: 0.8, scaleY: 0.8, tint: 0x95a5a6 }, { duration: 100, easing: tween.easeOut }); } }); // Go back to main menu LK.setTimeout(function () { self.goBackToMenu(); }, 200); } }; self.move = function (x, y, obj) { // Check if mouse is over easy button var isOverEasyButton = x >= 824 && x <= 1224 && y >= 940 && y <= 1060; if (isOverEasyButton && !self.easyButtonHover) { self.easyButtonHover = true; tween(easyBtn, { scaleX: 1.1, scaleY: 1.1, tint: 0x2ecc71 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverEasyButton && self.easyButtonHover) { self.easyButtonHover = false; tween(easyBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0x27ae60 }, { duration: 200, easing: tween.easeOut }); } // Check if mouse is over medium button var isOverMediumButton = x >= 824 && x <= 1224 && y >= 1240 && y <= 1360; if (isOverMediumButton && !self.mediumButtonHover) { self.mediumButtonHover = true; tween(mediumBtn, { scaleX: 1.1, scaleY: 1.1, tint: 0xe67e22 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverMediumButton && self.mediumButtonHover) { self.mediumButtonHover = false; tween(mediumBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0xf39c12 }, { duration: 200, easing: tween.easeOut }); } // Check if mouse is over hard button var isOverHardButton = x >= 824 && x <= 1224 && y >= 1540 && y <= 1660; if (isOverHardButton && !self.hardButtonHover) { self.hardButtonHover = true; tween(hardBtn, { scaleX: 1.1, scaleY: 1.1, tint: 0xc0392b }, { duration: 200, easing: tween.easeOut }); } else if (!isOverHardButton && self.hardButtonHover) { self.hardButtonHover = false; tween(hardBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0xe74c3c }, { duration: 200, easing: tween.easeOut }); } // Check if mouse is over back button var isOverBackButton = x >= 904 && x <= 1144 && y >= 1810 && y <= 1890; if (isOverBackButton && !self.backButtonHover) { self.backButtonHover = true; tween(backBtn, { scaleX: 0.9, scaleY: 0.9, tint: 0xbdc3c7 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverBackButton && self.backButtonHover) { self.backButtonHover = false; tween(backBtn, { scaleX: 0.8, scaleY: 0.8, tint: 0x95a5a6 }, { duration: 200, easing: tween.easeOut }); } }; self.startGameWithDifficulty = function (difficulty) { // Store difficulty for later use gameDifficulty = difficulty; // Update player health based on selected difficulty if (gameDifficulty === "easy") { humanPlayer.health = 20; aiPlayer.health = 15; } else if (gameDifficulty === "medium") { humanPlayer.health = 20; aiPlayer.health = 20; } else if (gameDifficulty === "hard") { humanPlayer.health = 20; aiPlayer.health = 25; } // Fade out difficulty selection tween(self, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { // Remove difficulty selection and start game game.removeChild(self); gameState = "playing"; initializeGameplay(); } }); }; self.goBackToMenu = function () { // Fade out difficulty selection tween(self, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { // Remove difficulty selection and return to menu game.removeChild(self); showMainMenu(); } }); }; // Entrance animation self.alpha = 0; self.scaleX = 0.8; self.scaleY = 0.8; tween(self, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 600, easing: tween.easeOut }); return self; }); var MainMenu = Container.expand(function () { var self = Container.call(this); // Menu background var menuBg = self.attachAsset('menuBackground', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.8 }); // Dark overlay for better text visibility var overlay = self.attachAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.6 }); // Game title var titleText = new Text2("Arsenic", { size: 120, fill: 0xf39c12 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 800; self.addChild(titleText); // Subtitle var subtitleText = new Text2("Rakibini Yenmek İçin Kartlarını Kullan", { size: 48, fill: 0xecf0f1 }); subtitleText.anchor.set(0.5, 0.5); subtitleText.x = 1024; subtitleText.y = 950; self.addChild(subtitleText); // Play button var playBtn = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1250 }); // Deck button var deckBtn = self.attachAsset('deckButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1500 }); // Wiki button at bottom var wikiBtn = self.attachAsset('wikiButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2000 }); // Wiki icon removed // Wiki button text removed // Medal display var medalCount = storage.gamesWon || 0; var medalText = new Text2("🏆 Kazanılan Oyunlar: " + medalCount, { size: 48, fill: 0xf39c12 }); medalText.anchor.set(0.5, 0.5); medalText.x = 1024; medalText.y = 1650; self.addChild(medalText); // Instructions var instructionText = new Text2("• Kartları sürükleyerek oynat\n• Büyüleri rakip kartlara hedefle\n• Rakibin canını 0'a düşür", { size: 36, fill: 0xbdc3c7 }); instructionText.anchor.set(0.5, 0.5); instructionText.x = 1024; instructionText.y = 1750; self.addChild(instructionText); // Early Access text var earlyAccessText = new Text2("Early Access", { size: 36, fill: 0xe74c3c }); earlyAccessText.anchor.set(0.5, 0.5); earlyAccessText.x = 1024; earlyAccessText.y = 2150; self.addChild(earlyAccessText); // Waldo credit text var waldoText = new Text2("Waldo tarafından yapıldı", { size: 32, fill: 0x3498db }); waldoText.anchor.set(0.5, 0.5); waldoText.x = 1024; waldoText.y = 2220; self.addChild(waldoText); // Credits var creditsText = new Text2("FRVR Tarafından Yapıldı", { size: 28, fill: 0x95a5a6 }); creditsText.anchor.set(0.5, 0.5); creditsText.x = 1024; creditsText.y = 2280; self.addChild(creditsText); // Button hover effect self.playButtonHover = false; self.deckButtonHover = false; self.wikiButtonHover = false; self.down = function (x, y, obj) { // Check if play button was clicked if (x >= 824 && x <= 1224 && y >= 1190 && y <= 1310) { // Button press effect tween(playBtn, { scaleX: 0.95, scaleY: 0.95, tint: 0x2980b9 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(playBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0x3498db }, { duration: 100, easing: tween.easeOut }); } }); // Start game after animation LK.setTimeout(function () { self.startGame(); }, 200); } // Check if deck button was clicked else if (x >= 824 && x <= 1224 && y >= 1440 && y <= 1560) { // Button press effect tween(deckBtn, { scaleX: 0.95, scaleY: 0.95, tint: 0x2980b9 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(deckBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0x3498db }, { duration: 100, easing: tween.easeOut }); } }); // Show deck view after animation LK.setTimeout(function () { self.showDeckView(); }, 200); } // Check if wiki button was clicked else if (x >= 824 && x <= 1224 && y >= 1960 && y <= 2040) { // Button press effect tween(wikiBtn, { scaleX: 0.95, scaleY: 0.95, tint: 0x2980b9 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(wikiBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0x3498db }, { duration: 100, easing: tween.easeOut }); } }); // Show wiki view after animation LK.setTimeout(function () { self.showWikiView(); }, 200); } // Check if medal was clicked else if (x >= 824 && x <= 1224 && y >= 1610 && y <= 1690) { self.showMedalDetails(); } }; self.move = function (x, y, obj) { var isOverPlayButton = x >= 824 && x <= 1224 && y >= 1190 && y <= 1310; if (isOverPlayButton && !self.playButtonHover) { self.playButtonHover = true; tween(playBtn, { scaleX: 1.1, scaleY: 1.1, tint: 0x5dade2 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverPlayButton && self.playButtonHover) { self.playButtonHover = false; tween(playBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0x3498db }, { duration: 200, easing: tween.easeOut }); } // Check if mouse is over deck button var isOverDeckButton = x >= 824 && x <= 1224 && y >= 1440 && y <= 1560; if (isOverDeckButton && !self.deckButtonHover) { self.deckButtonHover = true; tween(deckBtn, { scaleX: 1.1, scaleY: 1.1, tint: 0x5dade2 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverDeckButton && self.deckButtonHover) { self.deckButtonHover = false; tween(deckBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0x3498db }, { duration: 200, easing: tween.easeOut }); } // Check if mouse is over wiki button var isOverWikiButton = x >= 824 && x <= 1224 && y >= 1960 && y <= 2040; if (isOverWikiButton && !self.wikiButtonHover) { self.wikiButtonHover = true; tween(wikiBtn, { scaleX: 1.1, scaleY: 1.1, tint: 0x5dade2 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverWikiButton && self.wikiButtonHover) { self.wikiButtonHover = false; tween(wikiBtn, { scaleX: 1.0, scaleY: 1.0, tint: 0x3498db }, { duration: 200, easing: tween.easeOut }); } }; self.startGame = function () { // Fade out menu tween(self, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { // Remove menu and show difficulty selection game.removeChild(self); self.showDifficultySelection(); } }); }; // Entrance animation self.alpha = 0; self.scaleX = 0.8; self.scaleY = 0.8; tween(self, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 800, easing: tween.easeOut }); // Title pulse animation tween(titleText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { tween(titleText, { scaleX: 1.0, scaleY: 1.0 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Restart pulse animation self.titlePulse(); } }); } }); self.showDeckView = function () { // Create and show deck view var deckView = new DeckView(); game.addChild(deckView); }; self.showWikiView = function () { // Create and show wiki view var wikiView = new WikiView(); game.addChild(wikiView); }; self.showDifficultySelection = function () { // Create and show difficulty selection var difficultySelection = new DifficultySelection(); game.addChild(difficultySelection); }; self.titlePulse = function () { tween(titleText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { tween(titleText, { scaleX: 1.0, scaleY: 1.0 }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { self.titlePulse(); } }); } }); }; self.showMedalDetails = function () { // Get win counts for each difficulty var easyWins = storage.easyWins || 0; var mediumWins = storage.mediumWins || 0; var hardWins = storage.hardWins || 0; // Create medal details view var medalView = new MedalDetailsView(easyWins, mediumWins, hardWins); game.addChild(medalView); }; return self; }); var MedalDetailsView = Container.expand(function (easyWins, mediumWins, hardWins) { var self = Container.call(this); // Dark overlay background var overlay = self.attachAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.9 }); // Title var titleText = new Text2("MADALYA İSTATİSTİKLERİ", { size: 80, fill: 0xf39c12 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; self.addChild(titleText); // Easy difficulty stats var easyText = new Text2("KOLAY: " + easyWins + " galibiyet", { size: 56, fill: 0x27ae60 }); easyText.anchor.set(0.5, 0.5); easyText.x = 1024; easyText.y = 1000; self.addChild(easyText); // Medium difficulty stats var mediumText = new Text2("ORTA: " + mediumWins + " galibiyet", { size: 56, fill: 0xf39c12 }); mediumText.anchor.set(0.5, 0.5); mediumText.x = 1024; mediumText.y = 1200; self.addChild(mediumText); // Hard difficulty stats var hardText = new Text2("ZOR: " + hardWins + " galibiyet", { size: 56, fill: 0xe74c3c }); hardText.anchor.set(0.5, 0.5); hardText.x = 1024; hardText.y = 1400; self.addChild(hardText); // Total wins var totalWins = easyWins + mediumWins + hardWins; var totalText = new Text2("TOPLAM: " + totalWins + " galibiyet", { size: 64, fill: 0xecf0f1 }); totalText.anchor.set(0.5, 0.5); totalText.x = 1024; totalText.y = 1650; self.addChild(totalText); // Close button var closeBtn = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2000, scaleX: 0.8, scaleY: 0.8 }); var closeBtnText = new Text2("KAPAT", { size: 48, fill: 0xffffff }); closeBtnText.anchor.set(0.5, 0.5); closeBtnText.x = 1024; closeBtnText.y = 2000; self.addChild(closeBtnText); self.closeButtonHover = false; self.down = function (x, y, obj) { // Check if close button was clicked if (x >= 824 && x <= 1224 && y >= 1960 && y <= 2040) { // Button press effect tween(closeBtn, { scaleX: 0.75, scaleY: 0.75, tint: 0x2980b9 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(closeBtn, { scaleX: 0.8, scaleY: 0.8, tint: 0x3498db }, { duration: 100, easing: tween.easeOut }); } }); // Close medal details view after animation LK.setTimeout(function () { self.closeMedalView(); }, 200); } }; self.move = function (x, y, obj) { // Check if mouse is over close button var isOverCloseButton = x >= 824 && x <= 1224 && y >= 1960 && y <= 2040; if (isOverCloseButton && !self.closeButtonHover) { self.closeButtonHover = true; tween(closeBtn, { scaleX: 0.9, scaleY: 0.9, tint: 0x5dade2 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverCloseButton && self.closeButtonHover) { self.closeButtonHover = false; tween(closeBtn, { scaleX: 0.8, scaleY: 0.8, tint: 0x3498db }, { duration: 200, easing: tween.easeOut }); } }; self.closeMedalView = function () { // Fade out medal view tween(self, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { // Remove medal view game.removeChild(self); } }); }; // Entrance animation self.alpha = 0; self.scaleX = 0.8; self.scaleY = 0.8; tween(self, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 600, easing: tween.easeOut }); return self; }); var OpeningScreen = Container.expand(function () { var self = Container.call(this); // Dark background var overlay = self.attachAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.95 }); // "inspired by Waldo" text var inspiredText = new Text2("inspired by Waldo", { size: 80, fill: 0x3498db }); inspiredText.anchor.set(0.5, 0.5); inspiredText.x = 1024; inspiredText.y = 1366; inspiredText.alpha = 0; self.addChild(inspiredText); // Fade in animation self.alpha = 0; tween(self, { alpha: 1.0 }, { duration: 800, easing: tween.easeOut }); // Fade in the text tween(inspiredText, { alpha: 1.0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Hold for 2 seconds, then fade out LK.setTimeout(function () { tween(self, { alpha: 0 }, { duration: 800, easing: tween.easeIn, onFinish: function onFinish() { // Remove opening screen and show main menu game.removeChild(self); showMainMenu(); } }); }, 2000); } }); // Allow clicking to skip self.down = function (x, y, obj) { // Skip opening and go to main menu tween(self, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { game.removeChild(self); showMainMenu(); } }); }; return self; }); var Player = Container.expand(function (isHuman) { var self = Container.call(this); self.isHuman = isHuman || false; // Set health based on difficulty and player type if (gameDifficulty === "easy") { self.health = isHuman ? 20 : 15; // Player: 20, AI: 15 on easy } else if (gameDifficulty === "medium") { self.health = 20; // Both players have 20 health on medium } else if (gameDifficulty === "hard") { self.health = isHuman ? 20 : 25; // Player: 20, AI: 25 on hard } else { self.health = 20; // Default fallback } self.maxMana = 12; self.currentMana = isHuman ? 3 : 0; self.hand = []; self.battlefield = []; self.deck = []; self.spells = []; // Initialize with Fire Ball spell var fireBallSpell = new Spell({ name: "Fire Ball", cost: 2, damage: 2, target: "enemy", description: "Deals 2 damage to target" }); self.spells.push(fireBallSpell); // Add heal spell var healSpell = new Spell({ name: "Şifa", cost: 2, damage: -2, // Negative damage for healing target: "ally", description: "Heals target for 2 health" }); self.spells.push(healSpell); // Add freeze spell var freezeSpell = new Spell({ name: "Freeze", cost: 2, damage: 0, target: "enemy", description: "Freezes target enemy for 1 turn" }); self.spells.push(freezeSpell); // AI player also gets spells if not human if (!isHuman) { var aiFireBallSpell = new Spell({ name: "Fire Ball", cost: 2, damage: 2, target: "enemy", description: "Deals 2 damage to target" }); self.spells.push(aiFireBallSpell); } // Initialize deck with basic cards var cardTypes = [{ name: "Fire Imp", cost: 3, attack: 2, health: 5, description: "A small fire creature" }, { name: "Water Spirit", cost: 2, attack: 2, health: 4, description: "A defensive water creature" }, { name: "Earth Golem", cost: 3, attack: 1, health: 10, description: "A powerful earth creature" }, { name: "Air Wisp", cost: 1, attack: 1, health: 3, description: "A quick air creature" }, { name: "Lightning Bolt", cost: 2, attack: 1, health: 5, description: "A shocking creature" }, { name: "Lucifer", cost: 4, attack: 3, health: 6, description: "A mystical water spirit with high endurance" }, { name: "Shadow Drake", cost: 3, attack: 3, health: 4, description: "A powerful shadow dragon" }, { name: "Michael Demiurgos", cost: 4, attack: 2, health: 7, description: "An archangel with divine power" }]; // Add exactly one of each card type to the deck for (var i = 0; i < cardTypes.length; i++) { var newCard = new Card(cardTypes[i]); newCard.validateStats(); // Ensure stats are correct self.deck.push(newCard); } // Shuffle the deck to randomize card order for (var i = self.deck.length - 1; i > 0; i--) { var randomIndex = Math.floor(Math.random() * (i + 1)); var temp = self.deck[i]; self.deck[i] = self.deck[randomIndex]; self.deck[randomIndex] = temp; } self.drawCard = function () { if (self.deck.length > 0 && self.hand.length < 7) { var card = self.deck.pop(); self.hand.push(card); LK.getSound('cardDraw').play(); return card; } return null; }; self.canPlayCard = function (card) { return card && card.cardData.cost <= self.currentMana; }; self.playCard = function (card) { var handIndex = self.hand.indexOf(card); if (handIndex >= 0 && self.canPlayCard(card) && self.battlefield.length < 3) { self.hand.splice(handIndex, 1); self.battlefield.push(card); self.currentMana -= card.cardData.cost; card.isOnBattlefield = true; LK.getSound('cardPlay').play(); // Trigger played passive card.triggerPassive("played", { player: self }); // Check for class synergy activation var cardClass = getCardClass(card.cardData.name); var sameClassCount = 0; for (var i = 0; i < self.battlefield.length; i++) { if (getCardClass(self.battlefield[i].cardData.name) === cardClass) { sameClassCount++; } } // Show synergy effect if 2 or more cards of same class if (sameClassCount >= 2) { // Create synergy activation text var synergyText = new Text2("SINERJI AKTIF: " + cardClass.toUpperCase(), { size: 40, fill: 0xFFD700 }); synergyText.anchor.set(0.5, 0.5); synergyText.x = 1024; synergyText.y = self.isHuman ? 1300 : 500; synergyText.alpha = 0; game.addChild(synergyText); // Animate synergy text tween(synergyText, { alpha: 1.0, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(synergyText, { alpha: 0, y: synergyText.y - 50 }, { duration: 1000, easing: tween.easeIn, onFinish: function onFinish() { game.removeChild(synergyText); } }); } }); // Flash all cards of same class for (var i = 0; i < self.battlefield.length; i++) { if (getCardClass(self.battlefield[i].cardData.name) === cardClass) { LK.effects.flashObject(self.battlefield[i], 0xFFD700, 800); } } } return true; } return false; }; self.takeDamage = function (damage) { self.health -= damage; if (self.health < 0) self.health = 0; // Tower damage animation animateTowerDamage(!self.isHuman); // Damage number popup for tower var damageText = new Text2("-" + damage.toString(), { size: 60, fill: 0xff0000 }); damageText.anchor.set(0.5, 0.5); damageText.x = 1024 + (Math.random() - 0.5) * 100; damageText.y = self.isHuman ? 1700 : 400; damageText.alpha = 1.0; game.addChild(damageText); // Animate damage number tween(damageText, { y: damageText.y - 120, alpha: 0, scaleX: 2.0, scaleY: 2.0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(damageText); } }); }; self.canCastSpell = function (spell) { return spell && spell.spellData.cost <= self.currentMana; }; self.castSpell = function (spell, target) { if (self.canCastSpell(spell)) { self.currentMana -= spell.spellData.cost; return spell.castSpell(target); } return false; }; self.startTurn = function () { // Base mana gain: 1 per turn, 2 every 3rd turn var manaGain = 1; // Check if this is every 3rd turn (turnCounter is global) if (turnCounter % 3 === 0) { manaGain = 2; // Give 2 mana every 3rd turn instead of 1 } self.currentMana = Math.min(self.maxMana, self.currentMana + manaGain); // Max mana is always 12, no need to increment // Reset battlefield cards and trigger turn start passives for (var i = 0; i < self.battlefield.length; i++) { self.battlefield[i].resetForNewTurn(); // Apply Tank synergy health regeneration var cardClass = getCardClass(self.battlefield[i].cardData.name); if (cardClass === "Tank" && self.battlefield[i].synergyHealthRegen > 0) { var regenAmount = self.battlefield[i].synergyHealthRegen; var oldHealth = self.battlefield[i].currentHealth; self.battlefield[i].currentHealth = Math.min(self.battlefield[i].maxHealth, self.battlefield[i].currentHealth + regenAmount); // Show regeneration effect if health was actually restored if (self.battlefield[i].currentHealth > oldHealth) { var actualRegen = self.battlefield[i].currentHealth - oldHealth; // Create healing visual effect var healText = new Text2("+" + actualRegen.toString(), { size: 30, fill: 0x00ff00 }); healText.anchor.set(0.5, 0.5); healText.x = self.battlefield[i].x + (Math.random() - 0.5) * 40; healText.y = self.battlefield[i].y - 30; healText.alpha = 1.0; game.addChild(healText); // Animate healing number floating up and fading tween(healText, { y: healText.y - 60, alpha: 0, scaleX: 1.2, scaleY: 1.2 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(healText); } }); // Brief green flash on card LK.effects.flashObject(self.battlefield[i], 0x00ff00, 200); } self.battlefield[i].updateHealthDisplay(); } self.battlefield[i].triggerPassive("turn_start", { player: self }); // Handle stealth countdown if (self.battlefield[i].stealthTurns > 0) { self.battlefield[i].stealthTurns--; if (self.battlefield[i].stealthTurns <= 0) { self.battlefield[i].alpha = 1.0; // Return to normal visibility } } } // Draw a card self.drawCard(); }; return self; }); var Spell = Container.expand(function (spellData) { var self = Container.call(this); // Spell properties self.spellData = spellData || { name: "Fire Ball", cost: 2, damage: 2, target: "enemy", // "enemy", "ally", "self" description: "Deals 2 damage to target" }; self.isUsable = false; // Create spell graphics var spellBg = self.attachAsset('spellSlot', { anchorX: 0.5, anchorY: 0.5 }); // Choose appropriate spell icon based on spell name var spellAssetName = 'fireballSpell'; // default if (self.spellData.name === "Şifa") { spellAssetName = 'healSpell'; } else if (self.spellData.name === "Freeze") { spellAssetName = 'freezeSpell'; } var spellIcon = self.attachAsset(spellAssetName, { anchorX: 0.5, anchorY: 0.5 }); // Spell text elements var nameText = new Text2(self.spellData.name, { size: 18, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0); nameText.x = 0; nameText.y = -50; self.addChild(nameText); var costText = new Text2(self.spellData.cost.toString(), { size: 24, fill: 0x9B59B6 }); costText.anchor.set(0.5, 0.5); costText.x = -40; costText.y = -40; self.addChild(costText); var damageText = new Text2(self.spellData.damage.toString(), { size: 20, fill: 0xE74C3C }); damageText.anchor.set(0.5, 0.5); damageText.x = 0; damageText.y = 35; self.addChild(damageText); self.castSpell = function (target) { if (!self.isUsable) return false; // Play appropriate sound based on spell type if (self.spellData.name === "Şifa") { LK.getSound('healSound').play(); } else { LK.getSound('spellCast').play(); } // Animate spell casting var originalScale = self.scaleX; tween(self, { scaleX: 1.3, scaleY: 1.3, tint: 0xffff00 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: originalScale, scaleY: originalScale, tint: 0xFFFFFF }, { duration: 200, easing: tween.easeIn }); } }); // Create spell projectile animation var projectileAsset = self.spellData.name === "Şifa" ? 'healSpell' : 'fireballSpell'; var projectile = game.addChild(LK.getAsset(projectileAsset, { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y })); var targetX = target ? target.x : 1024 + (Math.random() - 0.5) * 200; var targetY = target ? target.y : aiPlayer.battlefield.length > 0 ? 650 : 300; // Animate projectile to target tween(projectile, { x: targetX, y: targetY, scaleX: 1.5, scaleY: 1.5, rotation: Math.PI * 2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Impact effect LK.effects.flashScreen(0xff4444, 300); // Handle damage, healing, and freeze spells if (target && target.takeDamage && target.isOnBattlefield) { if (self.spellData.name === "Freeze") { // Freeze spell target.frozenTurns = 3; // Play freeze sound effect LK.getSound('freezeSound').play(); // Create ice crystal effects around the target for (var crystal = 0; crystal < 8; crystal++) { var iceEffect = game.addChild(LK.getAsset('manaOrb', { anchorX: 0.5, anchorY: 0.5, x: target.x + Math.cos(crystal * Math.PI / 4) * 80, y: target.y + Math.sin(crystal * Math.PI / 4) * 80, scaleX: 0.4, scaleY: 0.4, alpha: 0.9, tint: 0x87CEEB })); // Animate ice crystals converging to target tween(iceEffect, { x: target.x, y: target.y, scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 600 + crystal * 50, easing: tween.easeIn, onFinish: function onFinish() { if (game.children.includes(iceEffect)) { game.removeChild(iceEffect); } } }); } // Create freeze burst effect at target var freezeBurst = game.addChild(LK.getAsset('manaOrb', { anchorX: 0.5, anchorY: 0.5, x: target.x, y: target.y, scaleX: 0.5, scaleY: 0.5, alpha: 1.0, tint: 0x00BFFF })); // Animate freeze burst expanding and fading tween(freezeBurst, { scaleX: 3.0, scaleY: 3.0, alpha: 0 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(freezeBurst); } }); // Apply visual freeze effect to target with blue tint target.alpha = 0.7; // Slightly transparent tween(target, { tint: 0x87CEEB }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Pulsing freeze effect var _freezePulse = function freezePulse() { if (target.frozenTurns > 0) { tween(target, { alpha: 0.5, tint: 0x00BFFF }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(target, { alpha: 0.7, tint: 0x87CEEB }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { if (target.frozenTurns > 0) { _freezePulse(); } } }); } }); } }; _freezePulse(); } }); // Create freeze visual effect text var freezeText = new Text2("DONDU!", { size: 45, fill: 0x00ffff }); freezeText.anchor.set(0.5, 0.5); freezeText.x = target.x + (Math.random() - 0.5) * 60; freezeText.y = target.y - 50; freezeText.alpha = 1.0; game.addChild(freezeText); // Animate freeze text with ice effect tween(freezeText, { y: freezeText.y - 100, alpha: 0, scaleX: 2.0, scaleY: 2.0, rotation: Math.PI * 0.1 }, { duration: 1200, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(freezeText); } }); // Screen flash with icy blue color LK.effects.flashScreen(0x00BFFF, 400); } else if (self.spellData.damage < 0) { // Healing spell var healAmount = Math.abs(self.spellData.damage); target.currentHealth = Math.min(target.maxHealth, target.currentHealth + healAmount); target.updateHealthDisplay(); // Create healing visual effect var healText = new Text2("+" + healAmount.toString(), { size: 40, fill: 0x00ff00 }); healText.anchor.set(0.5, 0.5); healText.x = target.x + (Math.random() - 0.5) * 60; healText.y = target.y - 50; healText.alpha = 1.0; game.addChild(healText); // Animate healing number floating up and fading tween(healText, { y: healText.y - 80, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(healText); } }); // Brief green flash on target LK.effects.flashObject(target, 0x00ff00, 300); } else { // Damage spell target.takeDamage(self.spellData.damage); } } // Remove projectile game.removeChild(projectile); } }); return true; }; return self; }); var WikiView = Container.expand(function () { var self = Container.call(this); // Dark overlay background var overlay = self.attachAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.9 }); // Title var titleText = new Text2("OYUN REHBERİ", { size: 80, fill: 0xf39c12 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 200; self.addChild(titleText); // Game rules section var rulesTitle = new Text2("OYUN KURALLARI", { size: 60, fill: 0x3498db }); rulesTitle.anchor.set(0.5, 0.5); rulesTitle.x = 1024; rulesTitle.y = 350; self.addChild(rulesTitle); // Rules text var rulesText = new Text2("• Her oyuncu 3 lane'de kart oynayabilir\n• Kartları sürükleyerek lane'lere yerleştirin\n• Büyüleri düşman/müttefik kartlara hedefleyin\n• Mana her tur otomatik olarak yenilenir\n• Rakibin canını 0'a düşürün\n• Karakterlerin üstündeki yeşil sayı CAN, kırmızı HASAR, mor MANA", { size: 36, fill: 0xbdc3c7 }); rulesText.anchor.set(0.5, 0.5); rulesText.x = 1024; rulesText.y = 550; self.addChild(rulesText); // Class synergy section var synergyTitle = new Text2("SINIF SİNERJİLERİ", { size: 60, fill: 0x9b59b6 }); synergyTitle.anchor.set(0.5, 0.5); synergyTitle.x = 1024; synergyTitle.y = 800; self.addChild(synergyTitle); // Synergy explanation var synergyText = new Text2("2 veya daha fazla aynı sınıf kartı ile sinerji bonusları:\n\n• TANK: +1 Can Yenileme/Tur\n• MAGE: %50 şans ile 2x hasar\n• ROGUE: +1 Saldırı ve +1 Can\n• WARRIOR: +2 Saldırı", { size: 36, fill: 0xbdc3c7 }); synergyText.anchor.set(0.5, 0.5); synergyText.x = 1024; synergyText.y = 1100; self.addChild(synergyText); // Spell section var spellTitle = new Text2("BÜYÜLER", { size: 60, fill: 0xe74c3c }); spellTitle.anchor.set(0.5, 0.5); spellTitle.x = 1024; spellTitle.y = 1400; self.addChild(spellTitle); // Spell explanation var spellText = new Text2("• Fire Ball: 2 hasar (Düşman kartlara)\n• Şifa: 2 iyileştirme (Müttefik kartlara)\n• Freeze: 2 mana, 3 tur dondurma (Düşman kartlara)", { size: 36, fill: 0xbdc3c7 }); spellText.anchor.set(0.5, 0.5); spellText.x = 1024; spellText.y = 1600; self.addChild(spellText); // Tips section var tipsTitle = new Text2("İPUÇLARI", { size: 60, fill: 0x27ae60 }); tipsTitle.anchor.set(0.5, 0.5); tipsTitle.x = 1024; tipsTitle.y = 1850; self.addChild(tipsTitle); // Tips text var tipsText = new Text2("• Sinerji bonusları için aynı sınıf kartları kullanın\n• Pasif yetenekleri stratejinize dahil edin\n• Büyüleri doğru zamanda kullanın\n• Kartları desteye geri döndürmek için aşağı sürükleyin", { size: 36, fill: 0xbdc3c7 }); tipsText.anchor.set(0.5, 0.5); tipsText.x = 1024; tipsText.y = 2050; self.addChild(tipsText); // Add wiki icon at top var wikiIcon = self.attachAsset('wikiIcon', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 120, scaleX: 1.5, scaleY: 1.5 }); // Add game rules icon var gameRulesIcon = self.attachAsset('gameRulesIcon', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 350, scaleX: 1.2, scaleY: 1.2 }); // Add synergy icon var synergyIcon = self.attachAsset('synergyIcon', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 800, scaleX: 1.2, scaleY: 1.2 }); // Add spell icon var spellIconAsset = self.attachAsset('spellIcon', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 1400, scaleX: 1.2, scaleY: 1.2 }); // Add tips icon var tipsIcon = self.attachAsset('tipsIcon', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 1850, scaleX: 1.2, scaleY: 1.2 }); // Close button var closeBtn = self.attachAsset('wikiButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2400, scaleX: 0.8, scaleY: 0.8 }); var closeBtnText = new Text2("KAPAT", { size: 48, fill: 0xffffff }); closeBtnText.anchor.set(0.5, 0.5); closeBtnText.x = 1024; closeBtnText.y = 2400; self.addChild(closeBtnText); self.closeButtonHover = false; self.down = function (x, y, obj) { // Check if close button was clicked if (x >= 824 && x <= 1224 && y >= 2360 && y <= 2440) { // Button press effect tween(closeBtn, { scaleX: 0.75, scaleY: 0.75, tint: 0x2980b9 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(closeBtn, { scaleX: 0.8, scaleY: 0.8, tint: 0x3498db }, { duration: 100, easing: tween.easeOut }); } }); // Close wiki view after animation LK.setTimeout(function () { self.closeWikiView(); }, 200); } }; self.move = function (x, y, obj) { // Check if mouse is over close button var isOverCloseButton = x >= 824 && x <= 1224 && y >= 2360 && y <= 2440; if (isOverCloseButton && !self.closeButtonHover) { self.closeButtonHover = true; tween(closeBtn, { scaleX: 0.9, scaleY: 0.9, tint: 0x5dade2 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverCloseButton && self.closeButtonHover) { self.closeButtonHover = false; tween(closeBtn, { scaleX: 0.8, scaleY: 0.8, tint: 0x3498db }, { duration: 200, easing: tween.easeOut }); } }; self.closeWikiView = function () { // Fade out wiki view tween(self, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { // Remove wiki view and return to menu game.removeChild(self); } }); }; // Entrance animation self.alpha = 0; self.scaleX = 0.8; self.scaleY = 0.8; tween(self, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 600, easing: tween.easeOut }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ // Game state variables // Fire Imp card assets // Water Spirit card assets // Earth Golem card assets // Air Wisp card assets // Lightning Bolt card assets // Walter Spirit card assets // Generic card back var gameState = "menu"; // "menu", "playing", "gameOver" var gameDifficulty = "easy"; // "easy", "medium", "hard" - will be set by difficulty selection var currentPlayer = 0; // 0 = human, 1 = AI var gamePhase = "playing"; // "playing", "gameOver" var mainMenu = null; var selectedCard = null; var draggedCard = null; var turnCounter = 0; // Track total turns taken var combatPhase = false; // Track if we're in combat phase var cardsLockedIn = false; // Track if cards are locked in for the turn // Create players var humanPlayer = new Player(true); var aiPlayer = new Player(false); // Set AI player's starting mana to 2 aiPlayer.currentMana = 2; var players = [humanPlayer, aiPlayer]; // Create game areas var opponentAreaBg = game.addChild(LK.getAsset('opponentArea', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.3 })); var battlefieldBg = game.addChild(LK.getAsset('battlefield', { anchorX: 0, anchorY: 0, x: 0, y: 400, alpha: 0.8 })); var playerAreaBg = game.addChild(LK.getAsset('playerArea', { anchorX: 0, anchorY: 0, x: 0, y: 1800, alpha: 0.3 })); // Create visible lane graphics var lanePositions = [600, 1024, 1448]; // Left, Center, Right lanes - centered var lanes = []; // Create lanes with borders for visual clarity for (var i = 0; i < 3; i++) { // Lane border (darker background) var laneBorder = game.addChild(LK.getAsset('laneBorder', { anchorX: 0.5, anchorY: 0.5, x: lanePositions[i], y: 985, alpha: 0.8 })); // Lane background (lighter) var lane = game.addChild(LK.getAsset('lane', { anchorX: 0.5, anchorY: 0.5, x: lanePositions[i], y: 985, alpha: 0.7 })); lanes.push({ border: laneBorder, background: lane }); // Add lane number text var laneText = new Text2("Lane " + (i + 1), { size: 24, fill: 0xECF0F1 }); laneText.anchor.set(0.5, 0.5); laneText.x = lanePositions[i]; laneText.y = 1255; laneText.alpha = 0.6; game.addChild(laneText); } // UI Elements var playerHealthText = new Text2("Health: 20", { size: 48, fill: 0xECF0F1 }); playerHealthText.anchor.set(0, 0.5); playerHealthText.x = 50; playerHealthText.y = 1950; game.addChild(playerHealthText); // Synergy indicator display var synergyDisplays = { Tank: null, Mage: null, Rogue: null, Warrior: null }; var synergyIcons = { Tank: null, Mage: null, Rogue: null, Warrior: null }; // Store class feature info var classFeatures = { Tank: { name: "TANK", feature: "Savunma Odaklı", synergy: "+1 Can Yenileme/Tur (Her Tank kartı için)", description: "Tank kartları yüksek can değerleriyle düşman saldırılarını absorbe eder. 2 veya daha fazla Tank kartı aynı anda savaş alanında olduğunda, her Tank kartı sinerji bonusu olarak her tur +1 can yeniler." }, Mage: { name: "MAGE", feature: "Öfkelenme", synergy: "%50 şans ile 2x hasar (Her Mage kartı için)", description: "Mage kartları öfkelenme yetisi ile saldırır. 2 veya daha fazla Mage kartı aynı anda savaş alanında olduğunda, her Mage kartı sinerji bonusu olarak %50 şans ile 2x hasar verir." }, Rogue: { name: "ROGUE", feature: "Hızlı ve Çevik", synergy: "+1 Saldırı ve +1 Can (Her Rogue kartı için)", description: "Rogue kartları hız ve çeviklikle hem saldırı hem savunmada iyidir. 2 veya daha fazla Rogue kartı aynı anda savaş alanında olduğunda, her Rogue kartı sinerji bonusu olarak +1 Saldırı ve +1 Can kazanır." }, Warrior: { name: "WARRIOR", feature: "Savaş Ustası", synergy: "+2 Saldırı (Her Warrior kartı için)", description: "Warrior kartları güçlü saldırılarıyla bilinir. 2 veya daha fazla Warrior kartı aynı anda savaş alanında olduğunda, her Warrior kartı sinerji bonusu olarak +2 Saldırı kazanır." }, Vampire: { name: "VAMPIRE", feature: "Vampirizm", synergy: "Verilen hasar kadar can yenileme (Her Vampire kartı için)", description: "Vampire kartları verdiği hasar kadar can kazanır. 2 veya daha fazla Vampire kartı aynı anda savaş alanında olduğunda, her Vampire kartı hasar verdiğinde verdiği hasar kadar can yeniler." } }; // Class feature display variables var classFeatureDisplay = null; var isShowingClassFeature = false; // Create synergy displays var synergyStartY = 800; var synergySpacing = 200; var classNames = ["Tank", "Mage", "Rogue", "Warrior"]; var classAssets = ["tankClass", "mageClass", "rogueClass", "warriorClass"]; for (var i = 0; i < classNames.length; i++) { var className = classNames[i]; var assetName = classAssets[i]; var yPos = synergyStartY + i * synergySpacing; // Create class icon var icon = game.addChild(LK.getAsset(assetName, { anchorX: 0.5, anchorY: 0.5, x: 100, y: yPos, scaleX: 1.5, scaleY: 1.5, alpha: 0.3 })); synergyIcons[className] = icon; // Create synergy text var synergyText = new Text2("", { size: 36, fill: 0x95a5a6 }); synergyText.anchor.set(0, 0.5); synergyText.x = 150; synergyText.y = yPos; synergyText.alpha = 0.3; game.addChild(synergyText); synergyDisplays[className] = synergyText; } var opponentHealthText = new Text2("Enemy: 15", { size: 48, fill: 0xECF0F1 }); opponentHealthText.anchor.set(0.5, 0.5); opponentHealthText.x = 1024; opponentHealthText.y = 150; game.addChild(opponentHealthText); var manaText = new Text2("Mana: 3/12", { size: 36, fill: 0x9B59B6 }); manaText.anchor.set(0, 0.5); manaText.x = 50; manaText.y = 2000; game.addChild(manaText); var aiManaText = new Text2("Enemy Mana: 3/12", { size: 36, fill: 0x9B59B6 }); aiManaText.anchor.set(0.5, 0.5); aiManaText.x = 1024; aiManaText.y = 200; game.addChild(aiManaText); var nextTurnManaText = new Text2("Next Turn: +1 Mana", { size: 36, fill: 0x9B59B6 }); nextTurnManaText.anchor.set(1, 0.5); nextTurnManaText.x = 1950; nextTurnManaText.y = 2100; game.addChild(nextTurnManaText); var turnText = new Text2("Your Turn", { size: 42, fill: 0xF39C12 }); turnText.anchor.set(0.5, 0.5); turnText.x = 1024; turnText.y = 100; game.addChild(turnText); // End turn button var endTurnBtn = game.addChild(LK.getAsset('endTurnButton', { anchorX: 0.5, anchorY: 0.5, x: 1800, y: 1950 })); var endTurnText = new Text2("End Turn", { size: 28, fill: 0x2C3E50 }); endTurnText.anchor.set(0.5, 0.5); endTurnText.x = 1800; endTurnText.y = 1950; game.addChild(endTurnText); // Main menu button var mainMenuBtn = game.addChild(LK.getAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: 1600, y: 150, scaleX: 0.6, scaleY: 0.6 })); var mainMenuBtnText = new Text2("ANA MENÜ", { size: 20, fill: 0xffffff }); mainMenuBtnText.anchor.set(0.5, 0.5); mainMenuBtnText.x = 1600; mainMenuBtnText.y = 150; game.addChild(mainMenuBtnText); function arrangeSpells() { // Arrange human player spells var spells = humanPlayer.spells; for (var i = 0; i < spells.length; i++) { var spell = spells[i]; if (!game.children.includes(spell)) { game.addChild(spell); } spell.x = 150; spell.y = 2150 + i * 140; spell.isUsable = humanPlayer.canCastSpell(spell) && currentPlayer === 0 && !combatPhase; // Visual feedback for usable spells if (spell.isUsable) { spell.alpha = 1.0; } else { spell.alpha = 0.6; } } // AI spells are hidden from UI - no display for AI spells } function updateUI() { playerHealthText.setText("Health: " + humanPlayer.health); opponentHealthText.setText("Enemy: " + aiPlayer.health); manaText.setText("Mana: " + humanPlayer.currentMana + "/" + humanPlayer.maxMana); aiManaText.setText("Enemy Mana: " + aiPlayer.currentMana + "/" + aiPlayer.maxMana); if (combatPhase) { turnText.setText("Combat Phase"); turnText.fill = "#e67e22"; } else if (currentPlayer === 0) { turnText.setText("Your Turn"); turnText.fill = "#f39c12"; } else { turnText.setText("Enemy Turn"); turnText.fill = "#e74c3c"; } // Update next turn mana display var nextManaGain = 1; if ((turnCounter + 1) % 3 === 0) { nextManaGain = 2; } nextTurnManaText.setText("Gelecek Tur: +" + nextManaGain + " Mana"); } function arrangeHand() { var handCards = humanPlayer.hand; var startX = 1024 - handCards.length * 100; for (var i = 0; i < handCards.length; i++) { var card = handCards[i]; if (!game.children.includes(card)) { game.addChild(card); } card.x = startX + i * 200; card.y = 2300; card.isPlayable = humanPlayer.canPlayCard(card); // Visual feedback for playable cards if (card.isPlayable && currentPlayer === 0) { card.alpha = 1.0; } else { card.alpha = 0.6; } } arrangeSpells(); } function getCardClass(cardName) { // Determine card class based on name if (cardName === "Earth Golem" || cardName === "Lightning Bolt") { return "Tank"; } else if (cardName === "Fire Imp" || cardName === "Water Spirit") { return "Mage"; } else if (cardName === "Air Wisp" || cardName === "Shadow Drake") { return "Rogue"; } else if (cardName === "Lucifer" || cardName === "Michael Demiurgos") { return "Warrior"; } else if (cardName === "Vampire Lord" || cardName === "Blood Drake") { return "Vampire"; } return "None"; } function calculateClassSynergy(player) { // Count cards by class on battlefield var classCounts = { "Tank": 0, "Mage": 0, "Rogue": 0, "Warrior": 0, "Vampire": 0 }; for (var i = 0; i < player.battlefield.length; i++) { var cardClass = getCardClass(player.battlefield[i].cardData.name); if (classCounts[cardClass] !== undefined) { classCounts[cardClass]++; } } // Update synergy display only for human player if (player.isHuman) { for (var className in synergyDisplays) { var count = classCounts[className]; var icon = synergyIcons[className]; var display = synergyDisplays[className]; if (count >= 2) { // Synergy is active icon.alpha = 1.0; icon.tint = 0xFFD700; // Gold color for active display.alpha = 1.0; display.fill = 0xFFD700; // Show synergy bonus text var bonusText = ""; if (className === "Tank") { bonusText = "+" + count + " Can/Tur"; } else if (className === "Mage") { bonusText = "%50 2x hasar"; } else if (className === "Rogue") { bonusText = "+" + count + " Saldırı/Can"; } else if (className === "Warrior") { bonusText = "+" + count * 2 + " Saldırı"; } else if (className === "Vampire") { bonusText = "Vampirizm: Hasar=Can"; } display.setText(className.toUpperCase() + ": " + bonusText); } else if (count === 1) { // One card, not active yet icon.alpha = 0.7; icon.tint = 0xFFFFFF; display.alpha = 0.7; display.fill = 0xbdc3c7; display.setText(className.toUpperCase() + ": 1/2"); } else { // No cards icon.alpha = 0.3; icon.tint = 0xFFFFFF; display.alpha = 0.3; display.fill = 0x95a5a6; display.setText(className.toUpperCase() + ": 0/2"); } } } // Apply synergy bonuses for (var i = 0; i < player.battlefield.length; i++) { var card = player.battlefield[i]; var cardClass = getCardClass(card.cardData.name); var classCount = classCounts[cardClass]; // Reset to base values first card.synergyAttackBonus = 0; card.synergyHealthBonus = 0; card.synergyRage = false; // Reset rage mechanic // Apply synergy bonuses based on class count if (classCount >= 2) { if (cardClass === "Tank") { // Tank synergy: +1 health regeneration per turn per Tank card (no static bonus) card.synergyHealthBonus = 0; // No static health bonus for tanks card.synergyHealthRegen = classCount; // Track regen amount instead } else if (cardClass === "Mage") { // Mage synergy: 50% chance for 2x damage (rage mechanic) card.synergyRage = true; // Enable rage for Mage cards with synergy } else if (cardClass === "Rogue") { // Rogue synergy: +1 attack and +1 health per Rogue card card.synergyAttackBonus = classCount; card.synergyHealthBonus = classCount; } else if (cardClass === "Warrior") { // Warrior synergy: +2 attack per Warrior card card.synergyAttackBonus = classCount * 2; } } } } function arrangeBattlefield() { // Calculate synergies for both players calculateClassSynergy(humanPlayer); calculateClassSynergy(aiPlayer); // Define 3 lane positions var lanePositions = [600, 1024, 1448]; // Left, Center, Right lanes - centered // Player battlefield - maintain lane assignments var playerCards = humanPlayer.battlefield; for (var i = 0; i < playerCards.length; i++) { var card = playerCards[i]; if (!game.children.includes(card)) { game.addChild(card); } // Use the card's assigned lane position instead of array index if (card.laneIndex !== undefined) { card.x = lanePositions[card.laneIndex]; card.y = 1120; } } // AI battlefield - maintain lane assignments var aiCards = aiPlayer.battlefield; for (var i = 0; i < aiCards.length; i++) { var card = aiCards[i]; if (!game.children.includes(card)) { game.addChild(card); } // Use the card's assigned lane position instead of array index if (card.laneIndex !== undefined) { card.x = lanePositions[card.laneIndex]; card.y = 650; } } } function resolveCombat() { // Process lanes sequentially - lane 1, then lane 2, then lane 3 processLaneCombat(0, function () { // Lane 1 complete, process lane 2 processLaneCombat(1, function () { // Lane 2 complete, process lane 3 processLaneCombat(2, function () { // All lanes complete, update battlefield LK.setTimeout(function () { arrangeBattlefield(); updateUI(); }, 500); }); }); }); } function processLaneCombat(laneIndex, onComplete) { var humanCard = null; var aiCard = null; // Find cards in this lane for (var i = 0; i < humanPlayer.battlefield.length; i++) { if (humanPlayer.battlefield[i].laneIndex === laneIndex && humanPlayer.battlefield[i].currentHealth > 0) { humanCard = humanPlayer.battlefield[i]; break; } } for (var i = 0; i < aiPlayer.battlefield.length; i++) { if (aiPlayer.battlefield[i].laneIndex === laneIndex && aiPlayer.battlefield[i].currentHealth > 0) { aiCard = aiPlayer.battlefield[i]; break; } } // Determine combat outcome for this lane if (humanCard && humanCard.currentHealth > 0 && aiCard && aiCard.currentHealth > 0) { // Check if either card has taunt - taunt forces combat var humanDamage = humanCard.cardData.attack + (humanCard.synergyAttackBonus || 0); var aiDamage = aiCard.cardData.attack + (aiCard.synergyAttackBonus || 0); // Check if cards are frozen - frozen cards cannot deal damage if (humanCard.frozenTurns && humanCard.frozenTurns > 0) { humanDamage = 0; // Frozen cards deal no damage } if (aiCard.frozenTurns && aiCard.frozenTurns > 0) { aiDamage = 0; // Frozen cards deal no damage } // Apply Mage rage if applicable (only if not frozen) if (humanCard.synergyRage && Math.random() < 0.5 && humanDamage > 0) { humanDamage *= 2; } if (aiCard.synergyRage && Math.random() < 0.5 && aiDamage > 0) { aiDamage *= 2; } // Ensure we're using the exact attack values animateCardVsCard(humanCard, aiCard, humanDamage, aiDamage, 0); // Wait for combat animation to complete before continuing LK.setTimeout(onComplete, 1200); } else if (humanCard && humanCard.currentHealth > 0 && !aiCard) { // Human card attacks AI tower - check if frozen first if (humanCard.frozenTurns && humanCard.frozenTurns > 0) { // Frozen card cannot attack tower, skip this lane LK.setTimeout(onComplete, 100); } else { // Human card attacks AI tower - use card's actual attack value animateCardToTower(humanCard, "ai", 0, 0); // Wait for tower attack animation to complete before continuing LK.setTimeout(onComplete, 1000); } } else if (aiCard && aiCard.currentHealth > 0 && !humanCard) { // AI card attacks human tower - check if frozen first if (aiCard.frozenTurns && aiCard.frozenTurns > 0) { // Frozen card cannot attack tower, skip this lane LK.setTimeout(onComplete, 100); } else { // AI card attacks human tower - use card's actual attack value animateCardToTower(aiCard, "human", 0, 0); // Wait for tower attack animation to complete before continuing LK.setTimeout(onComplete, 1000); } } else { // No combat in this lane, proceed immediately LK.setTimeout(onComplete, 100); } } function animateCardVsCard(card1, card2, damage1, damage2, delay) { LK.setTimeout(function () { // Store original positions var originalX1 = card1.x; var originalY1 = card1.y; var originalX2 = card2.x; var originalY2 = card2.y; // Calculate midpoint for collision var midX = (card1.x + card2.x) / 2; var midY = (card1.y + card2.y) / 2; // Phase 1: Both cards move toward each other tween(card1, { x: midX, y: midY - 20, scaleX: 1.1, scaleY: 1.1 }, { duration: 300, easing: tween.easeOut }); tween(card2, { x: midX, y: midY + 20, scaleX: 1.1, scaleY: 1.1 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Phase 2: Collision effect - shake and flash LK.getSound('attack').play(); // Shake both cards tween(card1, { x: midX + 15, rotation: 0.1 }, { duration: 60, easing: tween.easeInOut, onFinish: function onFinish() { tween(card1, { x: midX - 15, rotation: -0.1 }, { duration: 60, easing: tween.easeInOut, onFinish: function onFinish() { tween(card1, { x: midX, rotation: 0 }, { duration: 60, easing: tween.easeInOut }); } }); } }); tween(card2, { x: midX - 15, rotation: -0.1 }, { duration: 60, easing: tween.easeInOut, onFinish: function onFinish() { tween(card2, { x: midX + 15, rotation: 0.1 }, { duration: 60, easing: tween.easeInOut, onFinish: function onFinish() { tween(card2, { x: midX, rotation: 0 }, { duration: 60, easing: tween.easeInOut }); } }); } }); // Flash white for collision tween(card1, { tint: 0xFFFFFF }, { duration: 150, easing: tween.easeInOut, onFinish: function onFinish() { tween(card1, { tint: 0xFFFFFF }, { duration: 150, easing: tween.easeInOut }); } }); tween(card2, { tint: 0xFFFFFF }, { duration: 150, easing: tween.easeInOut, onFinish: function onFinish() { tween(card2, { tint: 0xFFFFFF }, { duration: 150, easing: tween.easeInOut }); } }); // Apply damage after collision - use exact damage values passed to function LK.setTimeout(function () { // card1 takes damage2 (from card2), card2 takes damage1 (from card1) card1.takeDamage(damage2, card2); card2.takeDamage(damage1, card1); }, 180); // Phase 3: Return to original positions LK.setTimeout(function () { tween(card1, { x: originalX1, y: originalY1, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeIn }); tween(card2, { x: originalX2, y: originalY2, scaleX: 1.0, scaleY: 1.0 }, { duration: 400, easing: tween.easeIn }); }, 300); } }); }, delay); } function animateCardToTower(card, target, damage, delay) { LK.setTimeout(function () { // Store original position var originalX = card.x; var originalY = card.y; // Determine tower position var towerX = 1024; // Center of screen var towerY = target === "ai" ? 100 : 1800; // AI or human area var targetX = towerX + (Math.random() - 0.5) * 200; // Add some randomness var targetY = towerY + (Math.random() - 0.5) * 100; // Phase 1: Card charges toward tower tween(card, { x: targetX, y: targetY, scaleX: 1.2, scaleY: 1.2, rotation: Math.PI * 0.1 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { // Phase 2: Impact effect LK.getSound('attack').play(); // Use card's actual attack value but check if card is frozen var actualDamage = 0; if (!card.frozenTurns || card.frozenTurns <= 0) { actualDamage = card.cardData.attack; } // Flash the tower area only if damage will be dealt if (actualDamage > 0) { if (target === "ai") { LK.effects.flashObject(opponentAreaBg, 0xff0000, 400); LK.effects.flashScreen(0xff0000, 200); aiPlayer.takeDamage(actualDamage); } else { LK.effects.flashObject(playerAreaBg, 0xff0000, 400); LK.effects.flashScreen(0xff0000, 200); humanPlayer.takeDamage(actualDamage); } } // Shake the card on impact tween(card, { x: targetX + 20, rotation: Math.PI * 0.15 }, { duration: 80, easing: tween.easeInOut, onFinish: function onFinish() { tween(card, { x: targetX - 20, rotation: Math.PI * 0.05 }, { duration: 80, easing: tween.easeInOut, onFinish: function onFinish() { tween(card, { x: targetX, rotation: Math.PI * 0.1 }, { duration: 80, easing: tween.easeInOut }); } }); } }); // Phase 3: Return to original position LK.setTimeout(function () { tween(card, { x: originalX, y: originalY, scaleX: 1.0, scaleY: 1.0, rotation: 0 }, { duration: 500, easing: tween.easeIn }); }, 300); } }); }, delay); } function animateCardDeath(card) { // Death animation - fade out while spinning and shrinking tween(card, { alpha: 0, scaleX: 0.2, scaleY: 0.2, rotation: Math.PI * 2, y: card.y - 100 }, { duration: 600, easing: tween.easeIn }); } function animateTowerDamage(isAI) { // Tower damage animation - screen shake and flash var targetArea = isAI ? opponentAreaBg : playerAreaBg; var healthText = isAI ? opponentHealthText : playerHealthText; // Flash the area red LK.effects.flashObject(targetArea, 0xff0000, 500); // Screen shake effect LK.effects.flashScreen(0xff0000, 300); // Animate health text tween(healthText, { scaleX: 1.3, scaleY: 1.3, tint: 0xff0000 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(healthText, { scaleX: 1.0, scaleY: 1.0, tint: 0xFFFFFF }, { duration: 300, easing: tween.easeIn }); } }); } function checkGameOver() { if (humanPlayer.health <= 0) { gamePhase = "gameOver"; LK.showGameOver(); // Reset game after showing game over LK.setTimeout(function () { resetGame(); }, 3000); return true; } else if (aiPlayer.health <= 0) { gamePhase = "gameOver"; // Increment medal count when player wins var currentMedals = storage.gamesWon || 0; storage.gamesWon = currentMedals + 1; // Track wins by difficulty if (gameDifficulty === "easy") { var easyWins = storage.easyWins || 0; storage.easyWins = easyWins + 1; } else if (gameDifficulty === "medium") { var mediumWins = storage.mediumWins || 0; storage.mediumWins = mediumWins + 1; } else if (gameDifficulty === "hard") { var hardWins = storage.hardWins || 0; storage.hardWins = hardWins + 1; } LK.showYouWin(); // Reset game after showing you win LK.setTimeout(function () { resetGame(); }, 3000); return true; } return false; } function resetGame() { // Reset game state gameState = "menu"; gamePhase = "playing"; currentPlayer = 0; turnCounter = 0; combatPhase = false; // Remove all cards from display before resetting arrays var allCards = humanPlayer.hand.concat(humanPlayer.battlefield).concat(aiPlayer.hand).concat(aiPlayer.battlefield); for (var i = 0; i < allCards.length; i++) { if (game.children.includes(allCards[i])) { game.removeChild(allCards[i]); } } // Remove all spells from display for (var i = 0; i < humanPlayer.spells.length; i++) { if (game.children.includes(humanPlayer.spells[i])) { game.removeChild(humanPlayer.spells[i]); } } for (var i = 0; i < aiPlayer.spells.length; i++) { if (game.children.includes(aiPlayer.spells[i])) { game.removeChild(aiPlayer.spells[i]); } } // Reset players with difficulty-based health if (gameDifficulty === "easy") { humanPlayer.health = 20; aiPlayer.health = 15; } else if (gameDifficulty === "medium") { humanPlayer.health = 20; aiPlayer.health = 20; } else if (gameDifficulty === "hard") { humanPlayer.health = 20; aiPlayer.health = 25; } else { humanPlayer.health = 20; aiPlayer.health = 20; } humanPlayer.currentMana = 3; humanPlayer.maxMana = 12; humanPlayer.hand = []; humanPlayer.battlefield = []; humanPlayer.deck = []; aiPlayer.currentMana = 0; aiPlayer.maxMana = 12; aiPlayer.hand = []; aiPlayer.battlefield = []; aiPlayer.deck = []; // Initialize deck with basic cards var cardTypes = [{ name: "Fire Imp", cost: 3, attack: 2, health: 5, description: "A small fire creature", passive: "burn" // Burns enemy for 1 damage at end of turn }, { name: "Water Spirit", cost: 2, attack: 2, health: 4, description: "A defensive water creature", passive: "heal" // Heals 1 health at start of turn }, { name: "Earth Golem", cost: 3, attack: 1, health: 10, description: "A powerful earth creature", passive: "taunt" // Forces enemies to attack this card first }, { name: "Air Wisp", cost: 1, attack: 1, health: 3, description: "A quick air creature", passive: "evasion" // 25% chance to dodge attacks }, { name: "Lightning Bolt", cost: 2, attack: 1, health: 5, description: "A shocking creature", passive: "shock" // Deals 3 damage to all enemies when played }, { name: "Lucifer", cost: 4, attack: 3, health: 6, description: "A mystical water spirit with high endurance", passive: "lifesteal" // Already implemented: heals when dealing damage }, { name: "Shadow Drake", cost: 3, attack: 3, health: 4, description: "A powerful shadow dragon", passive: "stealth" }, { name: "Michael Demiurgos", cost: 4, attack: 2, health: 7, description: "An archangel with divine power", passive: "divine_shield" // Ignores first damage taken }]; // Recreate decks for both players for (var p = 0; p < 2; p++) { var player = p === 0 ? humanPlayer : aiPlayer; for (var i = 0; i < cardTypes.length; i++) { var newCard = new Card(cardTypes[i]); newCard.validateStats(); player.deck.push(newCard); } // Shuffle deck for (var i = player.deck.length - 1; i > 0; i--) { var randomIndex = Math.floor(Math.random() * (i + 1)); var temp = player.deck[i]; player.deck[i] = player.deck[randomIndex]; player.deck[randomIndex] = temp; } } // Clear any remaining display elements selectedCard = null; draggedCard = null; // Show main menu showMainMenu(); } function endTurn() { // Lock in cards for current turn - no more returns to deck allowed cardsLockedIn = true; // Trigger end turn passives for current player var currentPlayerObj = players[currentPlayer]; for (var i = 0; i < currentPlayerObj.battlefield.length; i++) { currentPlayerObj.battlefield[i].triggerPassive("end_turn", { player: currentPlayerObj }); } // Apply Tank synergy health regeneration after 2 turns for current player if (turnCounter >= 2) { var tankCards = []; for (var i = 0; i < currentPlayerObj.battlefield.length; i++) { if (getCardClass(currentPlayerObj.battlefield[i].cardData.name) === "Tank") { tankCards.push(currentPlayerObj.battlefield[i]); } } // Tank synergy: heal 1 health if 2 or more tank cards present if (tankCards.length >= 2) { for (var i = 0; i < tankCards.length; i++) { var tankCard = tankCards[i]; var oldHealth = tankCard.currentHealth; tankCard.currentHealth = Math.min(tankCard.maxHealth, tankCard.currentHealth + 1); // Show regeneration effect if health was actually restored if (tankCard.currentHealth > oldHealth) { tankCard.updateHealthDisplay(); // Create healing visual effect var healText = new Text2("+1", { size: 30, fill: 0x00ff00 }); healText.anchor.set(0.5, 0.5); healText.x = tankCard.x + (Math.random() - 0.5) * 40; healText.y = tankCard.y - 30; healText.alpha = 1.0; game.addChild(healText); // Animate healing number floating up and fading tween(healText, { y: healText.y - 60, alpha: 0, scaleX: 1.2, scaleY: 1.2 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(healText); } }); // Brief green flash on card LK.effects.flashObject(tankCard, 0x00ff00, 200); } } } } // Switch to next player turnCounter++; currentPlayer = 1 - currentPlayer; // Reset cards locked in flag for new turn cardsLockedIn = false; // New turn system: Each player gets one full turn, then combat // Human starts (currentPlayer 0), then AI (currentPlayer 1), then combat if (turnCounter % 2 === 0) { // After both players have taken a turn, enter combat phase combatPhase = true; turnText.setText("Combat Phase"); turnText.fill = "#e67e22"; // Resolve combat after both players complete their turns LK.setTimeout(function () { resolveCombat(); combatPhase = false; // Start next round with human player currentPlayer = 0; // Always start new round with human player players[currentPlayer].startTurn(); if (!checkGameOver()) { updateUI(); arrangeHand(); arrangeBattlefield(); } }, 1000); } else { // Switch to the other player for their turn players[currentPlayer].startTurn(); if (currentPlayer === 1) { // AI turn LK.setTimeout(function () { performAITurn(); }, 1000); } if (!checkGameOver()) { updateUI(); arrangeHand(); arrangeBattlefield(); } } } function performAITurn() { // Enhanced AI with strategic decision-making and adaptive difficulty console.log("AI Turn - Difficulty:", gameDifficulty, "Health:", aiPlayer.health, "vs", humanPlayer.health); console.log("AI Hand size:", aiPlayer.hand.length, "Battlefield:", aiPlayer.battlefield.length, "Mana:", aiPlayer.currentMana); // Calculate board state and threat assessment var boardState = evaluateBoardState(); var threatLevel = calculateThreatLevel(); var aiStrategy = determineStrategy(boardState, threatLevel); console.log("AI Strategy:", aiStrategy, "Threat Level:", threatLevel); // Always try to play cards first - this is the main issue var playableCards = aiPlayer.hand.filter(function (card) { return aiPlayer.canPlayCard(card); }); console.log("Playable cards:", playableCards.length); // Force AI to play at least one card if possible var cardsPlayed = 0; var maxCardsToPlay = Math.min(3 - aiPlayer.battlefield.length, 2); // Play up to 2 cards per turn while (cardsPlayed < maxCardsToPlay && playableCards.length > 0 && aiPlayer.battlefield.length < 3) { var cardDecision = makeCardDecision(playableCards, boardState, threatLevel, aiStrategy); if (cardDecision.card && cardDecision.lane !== -1) { console.log("AI playing card:", cardDecision.card.cardData.name, "in lane", cardDecision.lane); if (aiPlayer.playCard(cardDecision.card)) { cardDecision.card.laneIndex = cardDecision.lane; cardDecision.card.targetLane = cardDecision.lane; cardsPlayed++; // Remove played card from playable list var cardIndex = playableCards.indexOf(cardDecision.card); if (cardIndex >= 0) { playableCards.splice(cardIndex, 1); } updateUI(); arrangeHand(); arrangeBattlefield(); } else { break; // Failed to play card, stop trying } } else { break; // No valid card decision, stop trying } } // Spell casting after playing cards var usableSpells = aiPlayer.spells.filter(function (spell) { return aiPlayer.canCastSpell(spell); }); if (usableSpells.length > 0) { var spellDecision = makeSpellDecision(usableSpells, boardState, threatLevel); if (spellDecision.spell && spellDecision.target) { console.log("AI casting spell:", spellDecision.spell.spellData.name, "on", spellDecision.target.cardData.name); if (aiPlayer.castSpell(spellDecision.spell, spellDecision.target)) { updateUI(); arrangeHand(); arrangeBattlefield(); } } } // Dynamic turn timing based on complexity and difficulty var turnDelay = calculateTurnDelay(boardState, threatLevel); LK.setTimeout(function () { if (!checkGameOver()) { endTurn(); } }, turnDelay); // AI helper functions for strategic decision making function evaluateBoardState() { var state = { aiCards: aiPlayer.battlefield.length, humanCards: humanPlayer.battlefield.length, aiTotalPower: 0, humanTotalPower: 0, aiSynergies: calculateAISynergies(), humanSynergies: calculateHumanSynergies(), availableLanes: getAvailableLanes(), manaEfficiency: aiPlayer.currentMana / aiPlayer.maxMana }; // Calculate total power on board for (var i = 0; i < aiPlayer.battlefield.length; i++) { var card = aiPlayer.battlefield[i]; state.aiTotalPower += card.cardData.attack + card.currentHealth; } for (var i = 0; i < humanPlayer.battlefield.length; i++) { var card = humanPlayer.battlefield[i]; state.humanTotalPower += card.cardData.attack + card.currentHealth; } return state; } function calculateThreatLevel() { var threat = 0; // Player health threat if (humanPlayer.health <= 15) threat += 30;else if (humanPlayer.health <= 25) threat += 15; // AI health threat if (aiPlayer.health <= 20) threat += 40;else if (aiPlayer.health <= 35) threat += 20; // Board control threat var powerDifference = 0; for (var i = 0; i < humanPlayer.battlefield.length; i++) { powerDifference += humanPlayer.battlefield[i].cardData.attack; } for (var i = 0; i < aiPlayer.battlefield.length; i++) { powerDifference -= aiPlayer.battlefield[i].cardData.attack; } if (powerDifference > 5) threat += 25;else if (powerDifference > 0) threat += 10; return Math.min(100, threat); } function determineStrategy(boardState, threatLevel) { if (threatLevel > 60) return "defensive"; if (aiPlayer.health > humanPlayer.health * 1.5) return "aggressive"; if (boardState.manaEfficiency > 0.8) return "tempo"; if (boardState.aiSynergies.count >= 2) return "synergy"; return "balanced"; } function makeSpellDecision(usableSpells, boardState, threatLevel) { var bestSpell = null; var bestTarget = null; var bestValue = -1; for (var s = 0; s < usableSpells.length; s++) { var spell = usableSpells[s]; var targets = []; if (spell.spellData.target === "enemy") { targets = humanPlayer.battlefield.slice(); } else if (spell.spellData.target === "ally") { targets = aiPlayer.battlefield.slice(); } for (var t = 0; t < targets.length; t++) { var target = targets[t]; var value = evaluateSpellValue(spell, target, boardState, threatLevel); if (value > bestValue) { bestValue = value; bestSpell = spell; bestTarget = target; } } } // Difficulty-based casting probability - made more aggressive var castProbability = 0.7; // Increased base probability if (gameDifficulty === "medium") castProbability = 0.8;else if (gameDifficulty === "hard") castProbability = 0.95;else if (gameDifficulty === "easy") castProbability = 0.6; // Increase probability based on threat level castProbability += threatLevel * 0.005; // Always cast if spell can kill an enemy or has very high value if (bestValue > 80) castProbability = 1.0; if (Math.random() < castProbability && bestSpell && bestTarget) { return { spell: bestSpell, target: bestTarget }; } return { spell: null, target: null }; } function evaluateSpellValue(spell, target, boardState, threatLevel) { var value = 0; if (spell.spellData.target === "enemy") { // Damage spells on enemies if (spell.spellData.name === "Fire Ball") { // Prioritize killing high-value targets if (target.currentHealth <= spell.spellData.damage) { value = 100 + target.cardData.cost * 15 + target.cardData.attack * 10; // Extra value for removing synergy threats var targetClass = getCardClass(target.cardData.name); var humanClassCount = countClassCards(humanPlayer.battlefield, targetClass); if (humanClassCount >= 2) value += 50; // Extra value for removing taunt if (target.cardData.passive === "taunt") value += 30; } else { value = spell.spellData.damage * 5; } } else if (spell.spellData.name === "Freeze") { // Freeze high-attack threats var attackValue = target.cardData.attack + (target.synergyAttackBonus || 0); value = attackValue * 15; // Extra value for freezing synergy engines var targetClass = getCardClass(target.cardData.name); var humanClassCount = countClassCards(humanPlayer.battlefield, targetClass); if (humanClassCount >= 2) value += 40; } } else if (spell.spellData.target === "ally") { // Heal spells on allies if (spell.spellData.name === "Şifa") { var missingHealth = target.maxHealth - target.currentHealth; if (missingHealth > 0) { value = Math.min(missingHealth, Math.abs(spell.spellData.damage)) * 8; value += target.cardData.cost * 5; // Value keeping expensive cards alive // Extra value for healing synergy cards var targetClass = getCardClass(target.cardData.name); var aiClassCount = countClassCards(aiPlayer.battlefield, targetClass); if (aiClassCount >= 2) value += 25; } } } // Adjust value based on difficulty if (gameDifficulty === "easy") value *= 0.7;else if (gameDifficulty === "hard") value *= 1.3; return value; } function makeCardDecision(playableCards, boardState, threatLevel, strategy) { if (playableCards.length === 0) { return { card: null, lane: -1 }; } var bestCard = null; var bestLane = -1; var bestValue = -999; //{DE} // Start with very low value var availableLanes = getAvailableLanes(); // If no lanes available, return null if (availableLanes.length === 0) { return { card: null, lane: -1 }; } for (var c = 0; c < playableCards.length; c++) { var card = playableCards[c]; for (var l = 0; l < availableLanes.length; l++) { var lane = availableLanes[l]; var value = evaluateCardPlacement(card, lane, boardState, threatLevel, strategy); if (value > bestValue) { bestValue = value; bestCard = card; bestLane = lane; } } } // Fallback: if no good placement found, pick first available card and lane if (bestCard === null && playableCards.length > 0 && availableLanes.length > 0) { bestCard = playableCards[0]; bestLane = availableLanes[0]; console.log("AI fallback: playing", bestCard.cardData.name, "in lane", bestLane); } return { card: bestCard, lane: bestLane }; } function evaluateCardPlacement(card, lane, boardState, threatLevel, strategy) { var value = 50; // Start with base positive value to ensure AI plays cards // Base card value var costEfficiency = card.cardData.cost > 0 ? (card.cardData.attack + card.cardData.health / 2) / card.cardData.cost : card.cardData.attack + card.cardData.health; value += costEfficiency * 15; // Synergy bonus evaluation var cardClass = getCardClass(card.cardData.name); var currentClassCount = countClassCards(aiPlayer.battlefield, cardClass); if (currentClassCount >= 1) { // Will create or strengthen synergy var synergyValue = calculateSynergyValue(cardClass, currentClassCount + 1); value += synergyValue; } // Lane-specific evaluation var humanCardInLane = findHumanCardInLane(lane); if (humanCardInLane) { // Can we win this matchup? var ourAttack = card.cardData.attack; var theirHealth = humanCardInLane.currentHealth; var ourHealth = card.cardData.health; var theirAttack = humanCardInLane.cardData.attack; if (ourAttack >= theirHealth && theirAttack < ourHealth) { value += 60; // Great trade } else if (ourAttack >= theirHealth) { value += 30; // We kill them but might die } else if (theirAttack < ourHealth) { value += 20; // We survive their attack } else { value -= 20; // Bad matchup } // Avoid Lucifer conflicts if (card.cardData.name === "Lucifer" && humanCardInLane.cardData.name === "Lucifer") { value -= 200; } } else { // Empty lane - good for pressure value += 25; if (lane === 1) value += 10; // Center lane preference } // Strategy adjustments if (strategy === "aggressive") { value += card.cardData.attack * 10; } else if (strategy === "defensive") { value += card.cardData.health * 8; if (card.cardData.passive === "taunt") value += 40; } else if (strategy === "synergy") { if (currentClassCount >= 1) value += 50; } // Passive ability values if (card.cardData.passive) { value += evaluatePassiveValue(card.cardData.passive, boardState, threatLevel); } // Difficulty scaling if (gameDifficulty === "easy") { value *= 0.6 + Math.random() * 0.4; // Add randomness for easy } else if (gameDifficulty === "hard") { value *= 1.2; // Better evaluation for hard } return value; } function calculateSynergyValue(cardClass, newCount) { if (newCount < 2) return 0; var value = 0; switch (cardClass) { case "Tank": value = newCount * 25; break; // Health regen case "Mage": value = newCount * 35; break; // Rage damage case "Rogue": value = newCount * 30; break; // Attack/health boost case "Warrior": value = newCount * 40; break; // Attack boost case "Vampire": value = newCount * 30; break; // Lifesteal } return value; } function evaluatePassiveValue(passive, boardState, threatLevel) { switch (passive) { case "burn": return 25 + humanPlayer.battlefield.length * 10; case "heal": return 20; case "taunt": return threatLevel > 40 ? 35 : 15; case "evasion": return 20; case "shock": return humanPlayer.battlefield.length * 15; case "lifesteal": return 25; case "stealth": return 15; case "divine_shield": return 30; default: return 0; } } function calculateAISynergies() { var synergies = { count: 0, types: [] }; var classCounts = {}; for (var i = 0; i < aiPlayer.battlefield.length; i++) { var cardClass = getCardClass(aiPlayer.battlefield[i].cardData.name); classCounts[cardClass] = (classCounts[cardClass] || 0) + 1; } for (var cardClass in classCounts) { if (classCounts[cardClass] >= 2) { synergies.count++; synergies.types.push(cardClass); } } return synergies; } function calculateHumanSynergies() { var synergies = { count: 0, types: [] }; var classCounts = {}; for (var i = 0; i < humanPlayer.battlefield.length; i++) { var cardClass = getCardClass(humanPlayer.battlefield[i].cardData.name); classCounts[cardClass] = (classCounts[cardClass] || 0) + 1; } for (var cardClass in classCounts) { if (classCounts[cardClass] >= 2) { synergies.count++; synergies.types.push(cardClass); } } return synergies; } function countClassCards(battlefield, cardClass) { var count = 0; for (var i = 0; i < battlefield.length; i++) { if (getCardClass(battlefield[i].cardData.name) === cardClass) { count++; } } return count; } function getAvailableLanes() { var availableLanes = [0, 1, 2]; for (var i = 0; i < aiPlayer.battlefield.length; i++) { var occupiedLane = aiPlayer.battlefield[i].laneIndex; if (occupiedLane !== undefined) { var laneIdx = availableLanes.indexOf(occupiedLane); if (laneIdx >= 0) availableLanes.splice(laneIdx, 1); } } return availableLanes; } function findHumanCardInLane(lane) { for (var i = 0; i < humanPlayer.battlefield.length; i++) { if (humanPlayer.battlefield[i].laneIndex === lane) { return humanPlayer.battlefield[i]; } } return null; } function calculateTurnDelay(boardState, threatLevel) { var baseDelay = 1500; if (gameDifficulty === "easy") { baseDelay = 2200; // Slower for easy } else if (gameDifficulty === "hard") { baseDelay = 1000; // Faster for hard } // Faster decisions under high threat if (threatLevel > 70) baseDelay *= 0.8; // Add some variation baseDelay += (Math.random() - 0.5) * 400; return Math.max(800, baseDelay); } } // Card zoom preview variables var zoomPreviewCard = null; var zoomPreviewBg = null; var zoomPreviewTimeout = null; var isShowingZoom = false; // Double-tap tracking variables var lastTappedCard = null; var lastTapTime = 0; var doubleTapThreshold = 500; // milliseconds // Button hover tracking var mainMenuButtonHover = false; // Card info display variables var cardInfoDisplay = null; var cardInfoBg = null; var isShowingCardInfo = false; function createZoomPreview(card) { if (isShowingZoom) return; // Create dark background overlay zoomPreviewBg = game.addChild(LK.getAsset('battlefield', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.8, tint: 0x000000 })); zoomPreviewBg.width = 2048; zoomPreviewBg.height = 2732; // Create zoomed card preview zoomPreviewCard = new Card(card.cardData); zoomPreviewCard.x = 1024; zoomPreviewCard.y = 1000; zoomPreviewCard.scaleX = 2.5; zoomPreviewCard.scaleY = 2.5; zoomPreviewCard.alpha = 0; game.addChild(zoomPreviewCard); // Add card name text var nameText = new Text2(card.cardData.name, { size: 60, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.x = 1024; nameText.y = 700; nameText.alpha = 0; game.addChild(nameText); zoomPreviewCard.nameDisplay = nameText; // Add passive description if card has passive if (card.hasPassive()) { var passiveText = new Text2("Passive: " + getPassiveDescription(card.cardData.passive), { size: 36, fill: 0xF39C12 }); passiveText.anchor.set(0.5, 0.5); passiveText.x = 1024; passiveText.y = 1400; passiveText.alpha = 0; game.addChild(passiveText); zoomPreviewCard.passiveDisplay = passiveText; } // Add description text var descText = new Text2(card.cardData.description, { size: 32, fill: 0xECF0F1 }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = card.hasPassive() ? 1500 : 1400; descText.alpha = 0; game.addChild(descText); zoomPreviewCard.descDisplay = descText; // Animate zoom in tween(zoomPreviewBg, { alpha: 0.8 }, { duration: 300, easing: tween.easeOut }); tween(zoomPreviewCard, { alpha: 1.0, scaleX: 2.5, scaleY: 2.5 }, { duration: 400, easing: tween.easeOut }); tween(nameText, { alpha: 1.0 }, { duration: 400, easing: tween.easeOut }); tween(descText, { alpha: 1.0 }, { duration: 400, easing: tween.easeOut }); if (zoomPreviewCard.passiveDisplay) { tween(zoomPreviewCard.passiveDisplay, { alpha: 1.0 }, { duration: 400, easing: tween.easeOut }); } isShowingZoom = true; } function destroyZoomPreview() { if (!isShowingZoom) return; if (zoomPreviewCard) { if (zoomPreviewCard.nameDisplay) { game.removeChild(zoomPreviewCard.nameDisplay); } if (zoomPreviewCard.passiveDisplay) { game.removeChild(zoomPreviewCard.passiveDisplay); } if (zoomPreviewCard.descDisplay) { game.removeChild(zoomPreviewCard.descDisplay); } game.removeChild(zoomPreviewCard); zoomPreviewCard = null; } if (zoomPreviewBg) { game.removeChild(zoomPreviewBg); zoomPreviewBg = null; } isShowingZoom = false; } function getPassiveDescription(passiveType) { switch (passiveType) { case "burn": return "Burns all enemies for 1 damage at end of turn"; case "heal": return "Heals 1 health at start of turn"; case "taunt": return "Forces enemies to attack this card first"; case "evasion": return "25% chance to dodge attacks"; case "shock": return "Deals 3 damage to all enemies when played"; case "lifesteal": return "Heals 1 when dealing damage to other cards"; case "stealth": return "Cannot be targeted by spells for first turn"; case "divine_shield": return "Ignores the first damage taken"; default: return "No passive ability"; } } function createClassFeatureDisplay(className) { if (isShowingClassFeature) { destroyClassFeatureDisplay(); } var classInfo = classFeatures[className]; if (!classInfo) return; // Create dark overlay background var overlay = game.addChild(LK.getAsset('menuOverlay', { anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.85 })); // Class name title var titleText = new Text2(classInfo.name + " SINIFI", { size: 60, fill: 0xf39c12 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 800; game.addChild(titleText); // Class feature var featureText = new Text2("Özellik: " + classInfo.feature, { size: 48, fill: 0x3498db }); featureText.anchor.set(0.5, 0.5); featureText.x = 1024; featureText.y = 900; game.addChild(featureText); // Synergy bonus var synergyText = new Text2("Sinerji Bonusu: " + classInfo.synergy, { size: 44, fill: 0xFFD700 }); synergyText.anchor.set(0.5, 0.5); synergyText.x = 1024; synergyText.y = 1000; game.addChild(synergyText); // Description (split into multiple lines for better readability) var descLines = classInfo.description.split('. '); for (var i = 0; i < descLines.length; i++) { var lineText = new Text2(descLines[i] + (i < descLines.length - 1 ? '.' : ''), { size: 36, fill: 0xecf0f1 }); lineText.anchor.set(0.5, 0.5); lineText.x = 1024; lineText.y = 1150 + i * 60; game.addChild(lineText); } // Close instruction var closeText = new Text2("Kapatmak için herhangi bir yere tıklayın", { size: 32, fill: 0x7f8c8d }); closeText.anchor.set(0.5, 0.5); closeText.x = 1024; closeText.y = 1600; game.addChild(closeText); // Store references for cleanup classFeatureDisplay = { overlay: overlay, titleText: titleText, featureText: featureText, synergyText: synergyText, descLines: [], closeText: closeText }; // Add description lines to cleanup list for (var i = 0; i < descLines.length; i++) { classFeatureDisplay.descLines.push(game.children[game.children.length - 2 - i]); } isShowingClassFeature = true; // Auto-hide after 5 seconds LK.setTimeout(function () { destroyClassFeatureDisplay(); }, 5000); } function destroyClassFeatureDisplay() { if (!isShowingClassFeature || !classFeatureDisplay) return; if (classFeatureDisplay.overlay) { game.removeChild(classFeatureDisplay.overlay); } if (classFeatureDisplay.titleText) { game.removeChild(classFeatureDisplay.titleText); } if (classFeatureDisplay.featureText) { game.removeChild(classFeatureDisplay.featureText); } if (classFeatureDisplay.synergyText) { game.removeChild(classFeatureDisplay.synergyText); } for (var i = 0; i < classFeatureDisplay.descLines.length; i++) { if (classFeatureDisplay.descLines[i]) { game.removeChild(classFeatureDisplay.descLines[i]); } } if (classFeatureDisplay.closeText) { game.removeChild(classFeatureDisplay.closeText); } classFeatureDisplay = null; isShowingClassFeature = false; } function createCardInfoDisplay(card) { if (isShowingCardInfo) { destroyCardInfoDisplay(); } // Create semi-transparent background at bottom cardInfoBg = game.addChild(LK.getAsset('playerArea', { anchorX: 0, anchorY: 0, x: 0, y: 2200, alpha: 0.8, tint: 0x2c3e50 })); // Create card name text var nameText = new Text2(card.cardData.name, { size: 48, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.x = 1024; nameText.y = 2320; game.addChild(nameText); // Create passive text if card has passive var passiveText = null; if (card.hasPassive()) { var passiveDesc = getPassiveDescription(card.cardData.passive); passiveText = new Text2("Pasif: " + passiveDesc, { size: 36, fill: 0xF39C12 }); passiveText.anchor.set(0.5, 0.5); passiveText.x = 1024; passiveText.y = 2380; game.addChild(passiveText); } else { passiveText = new Text2("Pasif: Yok", { size: 36, fill: 0x95A5A6 }); passiveText.anchor.set(0.5, 0.5); passiveText.x = 1024; passiveText.y = 2380; game.addChild(passiveText); } // Store references for cleanup cardInfoDisplay = { background: cardInfoBg, nameText: nameText, passiveText: passiveText }; isShowingCardInfo = true; // Auto-hide after 3 seconds LK.setTimeout(function () { destroyCardInfoDisplay(); }, 3000); } function destroyCardInfoDisplay() { if (!isShowingCardInfo || !cardInfoDisplay) return; if (cardInfoDisplay.background) { game.removeChild(cardInfoDisplay.background); } if (cardInfoDisplay.nameText) { game.removeChild(cardInfoDisplay.nameText); } if (cardInfoDisplay.passiveText) { game.removeChild(cardInfoDisplay.passiveText); } cardInfoDisplay = null; cardInfoBg = null; isShowingCardInfo = false; } // Event handlers game.down = function (x, y, obj) { if (gamePhase !== "playing" || currentPlayer !== 0 || combatPhase) return; // Close zoom preview if showing if (isShowingZoom) { destroyZoomPreview(); return; } // Close card info display if showing if (isShowingCardInfo) { destroyCardInfoDisplay(); } // Close class feature display if showing if (isShowingClassFeature) { destroyClassFeatureDisplay(); return; } // Check if a synergy class icon was clicked var classNames = ["Tank", "Mage", "Rogue", "Warrior"]; var synergyStartY = 800; var synergySpacing = 200; for (var i = 0; i < classNames.length; i++) { var className = classNames[i]; var yPos = synergyStartY + i * synergySpacing; var iconBounds = { left: 50, right: 150, top: yPos - 40, bottom: yPos + 40 }; if (x >= iconBounds.left && x <= iconBounds.right && y >= iconBounds.top && y <= iconBounds.bottom) { createClassFeatureDisplay(className); return; } } // Check if end turn button was clicked if (x >= 1700 && x <= 1900 && y >= 1910 && y <= 1990) { endTurn(); return; } // Check if main menu button was clicked if (x >= 1480 && x <= 1720 && y >= 110 && y <= 190) { // Button press effect tween(mainMenuBtn, { scaleX: 0.55, scaleY: 0.55, tint: 0x2980b9 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(mainMenuBtn, { scaleX: 0.6, scaleY: 0.6, tint: 0x3498db }, { duration: 100, easing: tween.easeOut }); } }); // Return to main menu and reset game LK.setTimeout(function () { resetGame(); }, 200); return; } // Check if a spell was clicked for (var i = 0; i < humanPlayer.spells.length; i++) { var spell = humanPlayer.spells[i]; var spellBounds = { left: spell.x - 60, right: spell.x + 60, top: spell.y - 60, bottom: spell.y + 60 }; if (x >= spellBounds.left && x <= spellBounds.right && y >= spellBounds.top && y <= spellBounds.bottom) { if (spell.isUsable) { // Start dragging spell instead of auto-casting draggedCard = spell; selectedCard = spell; } return; } } // Check if a hand card was clicked for (var i = 0; i < humanPlayer.hand.length; i++) { var card = humanPlayer.hand[i]; // Ensure card is properly displayed in game if (!game.children.includes(card)) { continue; } var cardBounds = { left: card.x - 90, right: card.x + 90, top: card.y - 125, bottom: card.y + 125 }; if (x >= cardBounds.left && x <= cardBounds.right && y >= cardBounds.top && y <= cardBounds.bottom) { // Check for double-tap var currentTime = Date.now(); if (lastTappedCard === card && currentTime - lastTapTime < doubleTapThreshold) { // Double-tap detected - show card info createCardInfoDisplay(card); lastTappedCard = null; lastTapTime = 0; return; } // Record this tap lastTappedCard = card; lastTapTime = currentTime; if (card.isPlayable && humanPlayer.canPlayCard(card)) { selectedCard = card; draggedCard = card; // Start long press timer for zoom preview if (zoomPreviewTimeout) { LK.clearTimeout(zoomPreviewTimeout); } zoomPreviewTimeout = LK.setTimeout(function () { if (selectedCard === card && game.children.includes(card)) { createZoomPreview(card); draggedCard = null; // Cancel drag when showing zoom } }, 800); // 800ms long press } return; } } // Check battlefield cards for zoom preview and drag (human player cards only) for (var i = 0; i < humanPlayer.battlefield.length; i++) { var card = humanPlayer.battlefield[i]; // Ensure card is properly displayed in game if (!game.children.includes(card)) { continue; } var cardBounds = { left: card.x - 90, right: card.x + 90, top: card.y - 125, bottom: card.y + 125 }; if (x >= cardBounds.left && x <= cardBounds.right && y >= cardBounds.top && y <= cardBounds.bottom) { // Check for double-tap on battlefield cards var currentTime = Date.now(); if (lastTappedCard === card && currentTime - lastTapTime < doubleTapThreshold) { // Double-tap detected - show card info createCardInfoDisplay(card); lastTappedCard = null; lastTapTime = 0; return; } // Record this tap lastTappedCard = card; lastTapTime = currentTime; // Allow dragging battlefield cards if not locked in if (!cardsLockedIn && card.isOnBattlefield) { draggedCard = card; selectedCard = card; } // Start long press timer for battlefield card zoom if (zoomPreviewTimeout) { LK.clearTimeout(zoomPreviewTimeout); } zoomPreviewTimeout = LK.setTimeout(function () { if (!draggedCard && game.children.includes(card)) { // Only show zoom if not dragging createZoomPreview(card); } }, 800); return; } } // Check AI battlefield cards for zoom preview only (no dragging) for (var i = 0; i < aiPlayer.battlefield.length; i++) { var card = aiPlayer.battlefield[i]; var cardBounds = { left: card.x - 90, right: card.x + 90, top: card.y - 125, bottom: card.y + 125 }; if (x >= cardBounds.left && x <= cardBounds.right && y >= cardBounds.top && y <= cardBounds.bottom) { // Check for double-tap on AI battlefield cards var currentTime = Date.now(); if (lastTappedCard === card && currentTime - lastTapTime < doubleTapThreshold) { // Double-tap detected - show card info createCardInfoDisplay(card); lastTappedCard = null; lastTapTime = 0; return; } // Record this tap lastTappedCard = card; lastTapTime = currentTime; // Start long press timer for AI battlefield card zoom if (zoomPreviewTimeout) { LK.clearTimeout(zoomPreviewTimeout); } zoomPreviewTimeout = LK.setTimeout(function () { createZoomPreview(card); }, 800); return; } } // Battlefield cards can no longer be manually selected for attacking // Combat is now automatic at end of turn }; game.move = function (x, y, obj) { // Cancel zoom preview if user starts moving if (zoomPreviewTimeout) { LK.clearTimeout(zoomPreviewTimeout); zoomPreviewTimeout = null; } // Check if mouse is over main menu button var isOverMainMenuButton = x >= 1480 && x <= 1720 && y >= 110 && y <= 190; if (isOverMainMenuButton && !mainMenuButtonHover) { mainMenuButtonHover = true; tween(mainMenuBtn, { scaleX: 0.7, scaleY: 0.7, tint: 0x5dade2 }, { duration: 200, easing: tween.easeOut }); } else if (!isOverMainMenuButton && mainMenuButtonHover) { mainMenuButtonHover = false; tween(mainMenuBtn, { scaleX: 0.6, scaleY: 0.6, tint: 0x3498db }, { duration: 200, easing: tween.easeOut }); } // Handle card dragging if (draggedCard && game.children.includes(draggedCard)) { draggedCard.x = x; draggedCard.y = y; // If dragging a spell, highlight potential targets if (draggedCard.castSpell) { // Reset all card alphas first for (var i = 0; i < aiPlayer.battlefield.length; i++) { if (game.children.includes(aiPlayer.battlefield[i])) { aiPlayer.battlefield[i].alpha = 1.0; } } for (var i = 0; i < humanPlayer.battlefield.length; i++) { if (game.children.includes(humanPlayer.battlefield[i])) { humanPlayer.battlefield[i].alpha = 1.0; } } // Determine which cards to highlight based on spell target type var targetCards = []; if (draggedCard.spellData.target === "enemy") { targetCards = aiPlayer.battlefield; } else if (draggedCard.spellData.target === "ally") { targetCards = humanPlayer.battlefield; } // Highlight cards that are close to the spell for (var i = 0; i < targetCards.length; i++) { var card = targetCards[i]; if (game.children.includes(card)) { var distance = Math.sqrt((card.x - x) * (card.x - x) + (card.y - y) * (card.y - y)); if (distance < 150) { card.alpha = 0.7; } } } } } else { // Reset dragged card if it's not in the game anymore draggedCard = null; selectedCard = null; } }; game.up = function (x, y, obj) { // Clear zoom preview timeout if (zoomPreviewTimeout) { LK.clearTimeout(zoomPreviewTimeout); zoomPreviewTimeout = null; } // Handle spell targeting if (draggedCard && draggedCard.castSpell) { var target = null; var targetCards = []; // Determine valid targets based on spell type if (draggedCard.spellData.target === "enemy") { targetCards = aiPlayer.battlefield; } else if (draggedCard.spellData.target === "ally") { targetCards = humanPlayer.battlefield; } // Check if spell was dropped on a valid target card for (var i = 0; i < targetCards.length; i++) { var card = targetCards[i]; var cardBounds = { left: card.x - 90, right: card.x + 90, top: card.y - 125, bottom: card.y + 125 }; if (x >= cardBounds.left && x <= cardBounds.right && y >= cardBounds.top && y <= cardBounds.bottom) { target = card; break; } } // Cast spell if valid target found if (target && target.isOnBattlefield && humanPlayer.castSpell(draggedCard, target)) { updateUI(); arrangeHand(); } // Reset all card alphas after spell targeting for (var i = 0; i < aiPlayer.battlefield.length; i++) { aiPlayer.battlefield[i].alpha = 1.0; } for (var i = 0; i < humanPlayer.battlefield.length; i++) { humanPlayer.battlefield[i].alpha = 1.0; } // Return spell to original position arrangeSpells(); draggedCard = null; selectedCard = null; return; } if (draggedCard && y < 1350 && y > 700) { // Determine which lane the card was dropped in var targetLane = -1; if (x >= 380 && x < 812) targetLane = 0; // Left lane else if (x >= 812 && x < 1236) targetLane = 1; // Center lane else if (x >= 1236 && x < 1668) targetLane = 2; // Right lane // Check if lane is available and card can be played if (targetLane >= 0 && humanPlayer.battlefield.length < 3) { // Check if target lane is already occupied var laneOccupied = false; for (var i = 0; i < humanPlayer.battlefield.length; i++) { if (humanPlayer.battlefield[i].laneIndex === targetLane) { laneOccupied = true; break; } } // Check if placing Lucifer would face another Lucifer in same lane var luciferBlocked = false; if (draggedCard.cardData.name === "Lucifer") { // Check if AI has Lucifer in the target lane for (var j = 0; j < aiPlayer.battlefield.length; j++) { if (aiPlayer.battlefield[j].laneIndex === targetLane && aiPlayer.battlefield[j].cardData.name === "Lucifer") { luciferBlocked = true; break; } } } if (!laneOccupied && !luciferBlocked && humanPlayer.playCard(draggedCard)) { draggedCard.laneIndex = targetLane; draggedCard.targetLane = targetLane; draggedCard = null; selectedCard = null; updateUI(); arrangeHand(); arrangeBattlefield(); } } } // Check if card is being dragged from battlefield back to hand area (return to deck functionality) else if (draggedCard && y > 1900 && draggedCard.isOnBattlefield && !cardsLockedIn) { // Find the card on battlefield and return it to deck var battlefieldIndex = humanPlayer.battlefield.indexOf(draggedCard); if (battlefieldIndex >= 0) { // Store original card data before removing var originalCardData = { name: draggedCard.cardData.name, cost: draggedCard.cardData.cost, attack: draggedCard.cardData.attack, health: draggedCard.cardData.health, description: draggedCard.cardData.description, passive: draggedCard.cardData.passive }; // Return mana to player humanPlayer.currentMana = Math.min(humanPlayer.maxMana, humanPlayer.currentMana + draggedCard.cardData.cost); // Remove from battlefield humanPlayer.battlefield.splice(battlefieldIndex, 1); // Clear lane assignment draggedCard.laneIndex = undefined; draggedCard.isOnBattlefield = false; // Remove from game display game.removeChild(draggedCard); // Create a completely fresh new card instance with the original data var newCard = new Card(originalCardData); newCard.validateStats(); // Ensure stats are correct // Add new card instance to deck humanPlayer.deck.push(newCard); // Visual feedback for successful return var returnText = new Text2("KARTA DESTEYE DÖNDÜ!", { size: 40, fill: 0x27ae60 }); returnText.anchor.set(0.5, 0.5); returnText.x = 1024; returnText.y = 1500; returnText.alpha = 1.0; game.addChild(returnText); // Animate feedback text tween(returnText, { y: returnText.y - 80, alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(returnText); } }); draggedCard = null; selectedCard = null; updateUI(); arrangeHand(); arrangeBattlefield(); } } selectedCard = null; if (draggedCard) { arrangeHand(); draggedCard = null; } // Dead cards are now automatically removed in takeDamage function updateUI(); arrangeBattlefield(); checkGameOver(); }; // Mana regeneration timer var manaRegenTimer = 0; var manaRegenInterval = 500; // Regenerate mana every 500ms game.update = function () { if (gamePhase === "playing") { // Handle mana regeneration during active turn if (currentPlayer === 0 && !combatPhase) { // Only for human player during their turn manaRegenTimer += LK.deltaTime; if (manaRegenTimer >= manaRegenInterval) { if (humanPlayer.currentMana < humanPlayer.maxMana) { humanPlayer.currentMana = Math.min(humanPlayer.maxMana, humanPlayer.currentMana + 2); // Mana regeneration visual effect var manaOrbEffect = game.addChild(LK.getAsset('manaOrb', { anchorX: 0.5, anchorY: 0.5, x: 50, y: 2000, alpha: 0.8 })); tween(manaOrbEffect, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(manaOrbEffect); } }); } manaRegenTimer = 0; } } updateUI(); } }; function initializeGameplay() { // Initialize starting hands for (var i = 0; i < 4; i++) { humanPlayer.drawCard(); aiPlayer.drawCard(); } // Play background music LK.playMusic('Darksouls'); // Initial setup updateUI(); arrangeHand(); arrangeBattlefield(); arrangeSpells(); } function showMainMenu() { if (mainMenu) { game.removeChild(mainMenu); } mainMenu = new MainMenu(); game.addChild(mainMenu); } function showOpeningScreen() { var opening = new OpeningScreen(); game.addChild(opening); } // Initialize with opening screen if (gameState === "menu") { showOpeningScreen(); }
===================================================================
--- original.js
+++ change.js
@@ -3210,16 +3210,16 @@
/****
* Game Code
****/
-// Generic card back
-// Walter Spirit card assets
-// Lightning Bolt card assets
-// Air Wisp card assets
-// Earth Golem card assets
-// Water Spirit card assets
-// Fire Imp card assets
// Game state variables
+// Fire Imp card assets
+// Water Spirit card assets
+// Earth Golem card assets
+// Air Wisp card assets
+// Lightning Bolt card assets
+// Walter Spirit card assets
+// Generic card back
var gameState = "menu"; // "menu", "playing", "gameOver"
var gameDifficulty = "easy"; // "easy", "medium", "hard" - will be set by difficulty selection
var currentPlayer = 0; // 0 = human, 1 = AI
var gamePhase = "playing"; // "playing", "gameOver"
@@ -4172,8 +4172,54 @@
currentPlayerObj.battlefield[i].triggerPassive("end_turn", {
player: currentPlayerObj
});
}
+ // Apply Tank synergy health regeneration after 2 turns for current player
+ if (turnCounter >= 2) {
+ var tankCards = [];
+ for (var i = 0; i < currentPlayerObj.battlefield.length; i++) {
+ if (getCardClass(currentPlayerObj.battlefield[i].cardData.name) === "Tank") {
+ tankCards.push(currentPlayerObj.battlefield[i]);
+ }
+ }
+ // Tank synergy: heal 1 health if 2 or more tank cards present
+ if (tankCards.length >= 2) {
+ for (var i = 0; i < tankCards.length; i++) {
+ var tankCard = tankCards[i];
+ var oldHealth = tankCard.currentHealth;
+ tankCard.currentHealth = Math.min(tankCard.maxHealth, tankCard.currentHealth + 1);
+ // Show regeneration effect if health was actually restored
+ if (tankCard.currentHealth > oldHealth) {
+ tankCard.updateHealthDisplay();
+ // Create healing visual effect
+ var healText = new Text2("+1", {
+ size: 30,
+ fill: 0x00ff00
+ });
+ healText.anchor.set(0.5, 0.5);
+ healText.x = tankCard.x + (Math.random() - 0.5) * 40;
+ healText.y = tankCard.y - 30;
+ healText.alpha = 1.0;
+ game.addChild(healText);
+ // Animate healing number floating up and fading
+ tween(healText, {
+ y: healText.y - 60,
+ alpha: 0,
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 600,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ game.removeChild(healText);
+ }
+ });
+ // Brief green flash on card
+ LK.effects.flashObject(tankCard, 0x00ff00, 200);
+ }
+ }
+ }
+ }
// Switch to next player
turnCounter++;
currentPlayer = 1 - currentPlayer;
// Reset cards locked in flag for new turn
End turn button fark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Kart alanı dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Ateş ruhu karakteri dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Lightning spirit character Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Kocaman kayadan oluşan golem kırmızı parıldayan gözlere sahip dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Air wisp character dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Arka planı doldur sadece aynısını yap
Koridor yukarıdan bakış dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Ateş 🔥 dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Ulan yatay tarsfa doğru geniş yap yüksekliğe doğru küçük yap
Shadow drake dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Michael demiurgos dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
İnfinity Minion character dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Fireball dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Magic stand dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Play button Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Deck yaz ama düzgün bir arka planla
Büyü asası logosu Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Suikastçı bıçağı logosu Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Kalkan logosu Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Warrior logo Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Sadece freeze büyüsü yap insan olmasın Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Sadece play yerine Wiki yaz
Spell icon Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
İpuçları icon Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Synergy icon Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Game Rules dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Frost Wolf Man Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Water spirit dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Phoenix woman Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Void Stalker Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows
Crystal guardian Dark souls style 2d pixel art. In-Game asset. 2d. High contrast. No shadows