/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var CraftedItem = Container.expand(function (recipe) { var self = Container.call(this); self.recipe = recipe; self.name = recipe.name; self.type = recipe.type; self.power = recipe.power || 0; self.defense = recipe.defense || 0; var itemGraphics; if (self.type === 'weapon') { itemGraphics = self.attachAsset('weapon', { anchorX: 0.5, anchorY: 0.5 }); } else { itemGraphics = self.attachAsset('armor', { anchorX: 0.5, anchorY: 0.5 }); } return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.health = 50; self.maxHealth = 50; self.damage = 15; self.speed = 1; self.lastAttackTime = 0; self.attackCooldown = 120; // 2 seconds at 60fps self.update = function () { if (player && self.health > 0) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 80) { var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; } else { // Attack player if (LK.ticks - self.lastAttackTime > self.attackCooldown) { player.takeDamage(self.damage); self.lastAttackTime = LK.ticks; LK.getSound('hit').play(); } } } }; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.dropResources(); self.destroy(); } }; self.dropResources = function () { for (var i = 0; i < 2; i++) { var resource = new Resource(); resource.x = self.x + (Math.random() - 0.5) * 60; resource.y = self.y + (Math.random() - 0.5) * 60; resources.push(resource); game.addChild(resource); } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.damage = 20; self.armor = 0; self.weapon = null; self.armorItem = null; self.speed = 3; self.targetX = self.x; self.targetY = self.y; self.isMoving = false; self.update = function () { if (self.isMoving) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { var moveX = dx / distance * self.speed; var moveY = dy / distance * self.speed; self.x += moveX; self.y += moveY; } else { self.x = self.targetX; self.y = self.targetY; self.isMoving = false; } } }; self.moveTo = function (x, y) { self.targetX = x; self.targetY = y; self.isMoving = true; }; self.takeDamage = function (amount) { var actualDamage = Math.max(1, amount - self.armor); self.health -= actualDamage; if (self.health <= 0) { self.health = 0; LK.showGameOver(); } LK.effects.flashObject(self, 0xFF0000, 300); }; self.equipWeapon = function (weapon) { self.weapon = weapon; self.damage = 20 + weapon.power; }; self.equipArmor = function (armor) { self.armorItem = armor; self.armor = armor.defense; }; return self; }); var Resource = Container.expand(function () { var self = Container.call(this); var resourceGraphics = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5 }); self.type = ['metal', 'wood', 'crystal', 'fabric'][Math.floor(Math.random() * 4)]; self.value = Math.floor(Math.random() * 5) + 1; self.down = function (x, y, obj) { LK.getSound('collect').play(); inventory.push({ type: self.type, value: self.value }); updateInventoryDisplay(); self.destroy(); var index = resources.indexOf(self); if (index > -1) { resources.splice(index, 1); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2C3E50 }); /**** * Game Code ****/ var player; var enemies = []; var resources = []; var inventory = []; var craftedItems = []; var gameState = 'combat'; // 'combat' or 'crafting' var lastEnemySpawn = 0; var enemySpawnRate = 300; // 5 seconds var selectedSlots = []; var craftingGrid = []; var playerLevel = 1; var selectedInventoryItem = null; var selectedInventorySlot = null; var playerXP = 0; var xpToNextLevel = 100; var materialProperties = { metal: { strength: 3, durability: 2, magic: 0, flexibility: 1 }, wood: { strength: 1, durability: 1, magic: 0, flexibility: 2 }, crystal: { strength: 2, durability: 1, magic: 4, flexibility: 0 }, fabric: { strength: 0, durability: 0, magic: 1, flexibility: 3 } }; // UI Elements var healthBar = new Text2('Health: 100/100', { size: 40, fill: 0xFF6B6B }); healthBar.anchor.set(0, 0); LK.gui.topLeft.addChild(healthBar); healthBar.x = 120; healthBar.y = 20; var inventoryText = new Text2('Inventory: 0 items', { size: 30, fill: 0xFFFFFF }); inventoryText.anchor.set(0.5, 0); LK.gui.top.addChild(inventoryText); inventoryText.y = 80; var levelText = new Text2('Level: 1 | XP: 0/100', { size: 28, fill: 0x00ff00 }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); levelText.y = 120; // Inventory panel variables var inventoryPanel = new Container(); var isInventoryOpen = false; var inventoryButton = LK.getAsset('equipButton', { anchorX: 0.5, anchorY: 0.5 }); LK.gui.bottomLeft.addChild(inventoryButton); inventoryButton.x = 100; inventoryButton.y = -100; var inventoryButtonText = new Text2('ITEMS', { size: 24, fill: 0xFFFFFF }); inventoryButtonText.anchor.set(0.5, 0.5); inventoryButton.addChild(inventoryButtonText); var craftButton = LK.getAsset('craftButton', { anchorX: 0.5, anchorY: 0.5 }); LK.gui.bottom.addChild(craftButton); craftButton.y = -100; var craftButtonText = new Text2('CRAFT', { size: 36, fill: 0xFFFFFF }); craftButtonText.anchor.set(0.5, 0.5); craftButton.addChild(craftButtonText); var inventorySlots = []; var craftingPanel = new Container(); var isCraftingOpen = false; // Initialize player player = game.addChild(new Player()); player.x = 1024; player.y = 1366; function updateInventoryDisplay() { inventoryText.setText('Inventory: ' + inventory.length + ' items'); levelText.setText('Level: ' + playerLevel + ' | XP: ' + playerXP + '/' + xpToNextLevel); if (isInventoryOpen) { updateInventoryPanel(); } } function openInventoryPanel() { if (isInventoryOpen) return; isInventoryOpen = true; // Create inventory panel background var panelBg = LK.getAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5, scaleX: 12, scaleY: 14 }); inventoryPanel.addChild(panelBg); // Create title var titleText = new Text2('INVENTORY', { size: 48, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -300; inventoryPanel.addChild(titleText); // Create inventory slots in a grid updateInventoryPanel(); // Create craft button in inventory panel var inventoryCraftButton = LK.getAsset('craftButton', { anchorX: 0.5, anchorY: 0.5 }); inventoryCraftButton.y = 280; var inventoryCraftText = new Text2('CRAFT', { size: 24, fill: 0xFFFFFF }); inventoryCraftText.anchor.set(0.5, 0.5); inventoryCraftButton.addChild(inventoryCraftText); inventoryCraftButton.down = function () { closeInventoryPanel(); openCraftingPanel(); }; inventoryPanel.addChild(inventoryCraftButton); // Create close button var closeButton = LK.getAsset('equipButton', { anchorX: 0.5, anchorY: 0.5 }); closeButton.y = 350; var closeText = new Text2('CLOSE', { size: 24, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeButton.addChild(closeText); closeButton.down = function () { closeInventoryPanel(); }; inventoryPanel.addChild(closeButton); game.addChild(inventoryPanel); inventoryPanel.x = 1024; inventoryPanel.y = 1366; } function updateInventoryPanel() { if (!isInventoryOpen) return; // Remove existing inventory slots (except background, title, and close button) for (var i = inventoryPanel.children.length - 1; i >= 0; i--) { var child = inventoryPanel.children[i]; if (child.isInventorySlot) { inventoryPanel.removeChild(child); } } // Create inventory slots in a 8x12 grid for bigger inventory var slotsPerRow = 8; var maxSlots = 96; var slotSize = 70; var startX = -(slotsPerRow - 1) * slotSize / 2; var startY = -200; for (var i = 0; i < Math.min(inventory.length, maxSlots); i++) { var row = Math.floor(i / slotsPerRow); var col = i % slotsPerRow; var slot = LK.getAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); slot.x = startX + col * slotSize; slot.y = startY + row * slotSize; slot.isInventorySlot = true; slot.itemData = inventory[i]; slot.slotIndex = i; // Color code by material type var itemColor = 0x34495e; switch (inventory[i].type) { case 'metal': itemColor = 0x95a5a6; break; case 'wood': itemColor = 0x8b4513; break; case 'crystal': itemColor = 0x9b59b6; break; case 'fabric': itemColor = 0x3498db; break; } slot.tint = itemColor; // Add item text var itemText = new Text2(inventory[i].type.charAt(0).toUpperCase() + '\n' + inventory[i].value, { size: 16, fill: 0xFFFFFF }); itemText.anchor.set(0.5, 0.5); slot.addChild(itemText); // Add click functionality to inventory slots slot.isSelected = false; slot.down = function (x, y, obj) { // Deselect previously selected item if (selectedInventorySlot) { selectedInventorySlot.tint = selectedInventorySlot.originalTint; selectedInventorySlot.isSelected = false; } // Select this item obj.originalTint = obj.tint; obj.tint = 0xFFFF00; // Yellow highlight for selection obj.isSelected = true; selectedInventorySlot = obj; selectedInventoryItem = obj.itemData; }; inventoryPanel.addChild(slot); } } function closeInventoryPanel() { isInventoryOpen = false; inventoryPanel.destroy(); inventoryPanel = new Container(); } function openCraftingPanel() { if (isCraftingOpen) return; isCraftingOpen = true; gameState = 'crafting'; // Create larger combined crafting and inventory panel background var panelBg = LK.getAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 20 }); craftingPanel.addChild(panelBg); // Add title for combined panel var titleText = new Text2('CRAFTING & INVENTORY', { size: 42, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -450; craftingPanel.addChild(titleText); // Create 3x3 crafting grid craftingGrid = []; for (var row = 0; row < 3; row++) { craftingGrid[row] = []; for (var col = 0; col < 3; col++) { var gridSlot = LK.getAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); gridSlot.x = col * 120 - 120; gridSlot.y = row * 120 - 200; gridSlot.row = row; gridSlot.col = col; gridSlot.isEmpty = true; gridSlot.itemData = null; gridSlot.tint = 0x2c3e50; gridSlot.down = function (x, y, obj) { // If we have a selected item from inventory, place it here if (selectedInventoryItem && obj.isEmpty) { obj.itemData = selectedInventoryItem; obj.isEmpty = false; obj.tint = 0x3498db; var gridText = new Text2(selectedInventoryItem.type.charAt(0).toUpperCase(), { size: 28, fill: 0xFFFFFF }); gridText.anchor.set(0.5, 0.5); obj.addChild(gridText); // Remove item from inventory inventory.splice(selectedInventorySlot.slotIndex, 1); // Clear selection selectedInventorySlot.tint = selectedInventorySlot.originalTint; selectedInventorySlot = null; selectedInventoryItem = null; updateInventoryDisplay(); closeCraftingPanel(); openCraftingPanel(); } // If clicking on occupied slot, remove item from grid slot else if (!obj.isEmpty) { inventory.push(obj.itemData); obj.itemData = null; obj.isEmpty = true; obj.tint = 0x2c3e50; if (obj.children && obj.children.length > 0) { obj.removeChild(obj.children[0]); } updateInventoryDisplay(); } }; craftingPanel.addChild(gridSlot); craftingGrid[row][col] = gridSlot; } } // Create expanded inventory display area in crafting panel var slotsPerRow = 8; var maxInventorySlots = 64; var slotSize = 60; var inventoryStartX = -(slotsPerRow - 1) * slotSize / 2; var inventoryStartY = 50; for (var i = 0; i < Math.min(inventory.length, maxInventorySlots); i++) { var row = Math.floor(i / slotsPerRow); var col = i % slotsPerRow; var slot = LK.getAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.9, scaleY: 0.9 }); slot.x = inventoryStartX + col * slotSize; slot.y = inventoryStartY + row * slotSize; slot.itemData = inventory[i]; slot.slotIndex = i; // Color code by material type var itemColor = 0x34495e; switch (inventory[i].type) { case 'metal': itemColor = 0x95a5a6; break; case 'wood': itemColor = 0x8b4513; break; case 'crystal': itemColor = 0x9b59b6; break; case 'fabric': itemColor = 0x3498db; break; } slot.tint = itemColor; var itemText = new Text2(inventory[i].type.charAt(0).toUpperCase() + '\n' + inventory[i].value, { size: 18, fill: 0xFFFFFF }); itemText.anchor.set(0.5, 0.5); slot.addChild(itemText); slot.isSelected = false; slot.down = function (x, y, obj) { // Deselect previously selected item if (selectedInventorySlot) { selectedInventorySlot.tint = selectedInventorySlot.originalTint; selectedInventorySlot.isSelected = false; } // Select this item obj.originalTint = obj.tint; obj.tint = 0xFFFF00; // Yellow highlight for selection obj.isSelected = true; selectedInventorySlot = obj; selectedInventoryItem = obj.itemData; }; craftingPanel.addChild(slot); inventorySlots.push(slot); } // Create equipment display area var equipmentLabel = new Text2('EQUIPPED ITEMS', { size: 24, fill: 0xFFD700 }); equipmentLabel.anchor.set(0.5, 0.5); equipmentLabel.x = -300; equipmentLabel.y = -350; craftingPanel.addChild(equipmentLabel); // Weapon slot var weaponSlot = LK.getAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); weaponSlot.x = -350; weaponSlot.y = -300; weaponSlot.tint = 0xe67e22; var weaponLabel = new Text2('WEAPON\n' + (player.weapon ? player.weapon.name : 'None'), { size: 14, fill: 0xFFFFFF }); weaponLabel.anchor.set(0.5, 0.5); weaponSlot.addChild(weaponLabel); craftingPanel.addChild(weaponSlot); // Armor slot var armorSlot = LK.getAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); armorSlot.x = -250; armorSlot.y = -300; armorSlot.tint = 0x95a5a6; var armorLabel = new Text2('ARMOR\n' + (player.armorItem ? player.armorItem.name : 'None'), { size: 14, fill: 0xFFFFFF }); armorLabel.anchor.set(0.5, 0.5); armorSlot.addChild(armorLabel); craftingPanel.addChild(armorSlot); // Create craft button var craftActionButton = LK.getAsset('craftButton', { anchorX: 0.5, anchorY: 0.5 }); craftActionButton.y = 400; var craftActionText = new Text2('CRAFT', { size: 36, fill: 0xFFFFFF }); craftActionText.anchor.set(0.5, 0.5); craftActionButton.addChild(craftActionText); craftActionButton.down = function () { craftFromGrid(); }; craftingPanel.addChild(craftActionButton); // Create close button var closeButton = LK.getAsset('equipButton', { anchorX: 0.5, anchorY: 0.5 }); closeButton.y = 420; var closeText = new Text2('CLOSE', { size: 24, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeButton.addChild(closeText); closeButton.down = function () { closeCraftingPanel(); }; craftingPanel.addChild(closeButton); game.addChild(craftingPanel); craftingPanel.x = 1024; craftingPanel.y = 1366; } function closeCraftingPanel() { isCraftingOpen = false; gameState = 'combat'; selectedSlots = []; inventorySlots = []; craftingPanel.destroy(); craftingPanel = new Container(); } function craftFromGrid() { var gridItems = []; var totalValue = 0; var materials = {}; var materialTypes = []; // Collect items from 3x3 grid for (var row = 0; row < 3; row++) { for (var col = 0; col < 3; col++) { var gridSlot = craftingGrid[row][col]; if (!gridSlot.isEmpty && gridSlot.itemData) { gridItems.push({ item: gridSlot.itemData, row: row, col: col }); var item = gridSlot.itemData; if (!materials[item.type]) { materials[item.type] = 0; materialTypes.push(item.type); } materials[item.type] += item.value; totalValue += item.value; } } } // Allow crafting even with just 1 item if (gridItems.length === 0) return; // Calculate combined properties same as before var combinedProps = { strength: 0, durability: 0, magic: 0, flexibility: 0 }; var dominantMaterial = ''; var highestAmount = 0; for (var matType in materials) { var amount = materials[matType]; var props = materialProperties[matType]; combinedProps.strength += props.strength * amount; combinedProps.durability += props.durability * amount; combinedProps.magic += props.magic * amount; combinedProps.flexibility += props.flexibility * amount; if (amount > highestAmount) { highestAmount = amount; dominantMaterial = matType; } } // Grid position bonus - center items get bonus var positionBonus = 0; for (var g = 0; g < gridItems.length; g++) { var gridItem = gridItems[g]; if (gridItem.row === 1 && gridItem.col === 1) { positionBonus += 5; // Center slot bonus } if ((gridItem.row === 0 || gridItem.row === 2) && (gridItem.col === 0 || gridItem.col === 2)) { positionBonus += 2; // Corner bonus } } // Determine item type and stats var itemType = 'tool'; var itemName = 'Grid-Forged Item'; var power = positionBonus; var defense = positionBonus; // Special handling for single item crafting if (gridItems.length === 1) { var singleItem = gridItems[0].item; var singleProps = materialProperties[singleItem.type]; // Single items create basic equipment based on material properties if (singleProps.strength >= 2) { itemType = 'weapon'; power = Math.floor(singleProps.strength * singleItem.value * 2 + positionBonus); } else if (singleProps.durability >= 2) { itemType = 'armor'; defense = Math.floor(singleProps.durability * singleItem.value * 2 + positionBonus); } else if (singleProps.magic >= 2) { itemType = 'artifact'; power = Math.floor(singleProps.magic * singleItem.value * 1.5 + positionBonus); defense = Math.floor(singleProps.magic * singleItem.value + positionBonus); } else { itemType = 'tool'; power = Math.floor(singleItem.value * 2 + positionBonus); defense = Math.floor(singleItem.value + positionBonus); } } else { // Multi-item crafting logic if (combinedProps.strength > combinedProps.durability && combinedProps.strength > combinedProps.magic) { itemType = 'weapon'; power = Math.floor(combinedProps.strength * 2 + totalValue + positionBonus); } else if (combinedProps.durability > combinedProps.magic) { itemType = 'armor'; defense = Math.floor(combinedProps.durability * 2 + totalValue + positionBonus); } else if (combinedProps.magic > 8) { itemType = 'artifact'; power = Math.floor(combinedProps.magic * 1.5 + positionBonus); defense = Math.floor(combinedProps.magic + positionBonus); } else { itemType = 'tool'; power = Math.floor(totalValue * 1.5 + positionBonus); defense = Math.floor(totalValue + positionBonus); } } // Generate name based on grid pattern if (gridItems.length === 1) { // Simple naming for single items var singleItemNames = { weapon: ['Knife', 'Blade', 'Dagger', 'Spike'], armor: ['Shield', 'Guard', 'Vest', 'Plate'], artifact: ['Charm', 'Gem', 'Stone', 'Crystal'], tool: ['Tool', 'Rod', 'Handle', 'Piece'] }; var baseName = singleItemNames[itemType][Math.floor(Math.random() * singleItemNames[itemType].length)]; itemName = 'Simple ' + dominantMaterial.charAt(0).toUpperCase() + dominantMaterial.slice(1) + ' ' + baseName; } else { // Multi-item pattern naming var patternNames = ['Cross', 'Line', 'Corner', 'Full', 'Sparse', 'Dense']; var patternName = patternNames[Math.floor(Math.random() * patternNames.length)]; itemName = patternName + ' ' + dominantMaterial.charAt(0).toUpperCase() + dominantMaterial.slice(1) + ' ' + itemType.charAt(0).toUpperCase() + itemType.slice(1); } var newItem = { name: itemName, type: itemType, power: power, defense: defense, materials: materialTypes.join('+'), rarity: gridItems.length >= 7 ? 'legendary' : gridItems.length >= 5 ? 'masterwork' : gridItems.length >= 3 ? 'rare' : gridItems.length === 1 ? 'basic' : 'common' }; craftedItems.push(newItem); // Clear grid for (var row = 0; row < 3; row++) { for (var col = 0; col < 3; col++) { var gridSlot = craftingGrid[row][col]; if (!gridSlot.isEmpty) { gridSlot.itemData = null; gridSlot.isEmpty = true; gridSlot.tint = 0x2c3e50; if (gridSlot.children.length > 0) { gridSlot.removeChild(gridSlot.children[0]); } } } } // Add XP and check for level up playerXP += gridItems.length * 10; checkLevelUp(); LK.getSound('craft').play(); closeCraftingPanel(); showCraftedItems(); } function checkLevelUp() { if (playerXP >= xpToNextLevel) { playerLevel++; playerXP -= xpToNextLevel; xpToNextLevel = Math.floor(xpToNextLevel * 1.5); // Auto collect materials on level up autoCollectMaterials(); // Show level up effect LK.effects.flashScreen(0x00ff00, 1000); } } function autoCollectMaterials() { var materialsToAdd = playerLevel * 2; var materialTypes = ['metal', 'wood', 'crystal', 'fabric']; for (var i = 0; i < materialsToAdd; i++) { var randomType = materialTypes[Math.floor(Math.random() * materialTypes.length)]; var randomValue = Math.floor(Math.random() * playerLevel) + 1; inventory.push({ type: randomType, value: randomValue }); } updateInventoryDisplay(); } function craftSelectedItems() { if (selectedSlots.length < 1) return; var materials = {}; var totalValue = 0; var materialTypes = []; // Calculate materials from selected slots for (var i = 0; i < selectedSlots.length; i++) { var item = inventory[selectedSlots[i]]; if (!materials[item.type]) { materials[item.type] = 0; materialTypes.push(item.type); } materials[item.type] += item.value; totalValue += item.value; } // Calculate combined properties var combinedProps = { strength: 0, durability: 0, magic: 0, flexibility: 0 }; var dominantMaterial = ''; var highestAmount = 0; for (var matType in materials) { var amount = materials[matType]; var props = materialProperties[matType]; // Add weighted properties combinedProps.strength += props.strength * amount; combinedProps.durability += props.durability * amount; combinedProps.magic += props.magic * amount; combinedProps.flexibility += props.flexibility * amount; // Track dominant material if (amount > highestAmount) { highestAmount = amount; dominantMaterial = matType; } } // Determine item type based on properties var itemType = 'tool'; var itemName = 'Crafted Item'; var power = 0; var defense = 0; var special = ''; if (combinedProps.strength > combinedProps.durability && combinedProps.strength > combinedProps.magic) { itemType = 'weapon'; power = Math.floor(combinedProps.strength * 2 + totalValue); if (combinedProps.magic > 5) { special = 'Magical '; power += Math.floor(combinedProps.magic); } } else if (combinedProps.durability > combinedProps.magic) { itemType = 'armor'; defense = Math.floor(combinedProps.durability * 2 + totalValue); if (combinedProps.flexibility > 5) { special = 'Flexible '; defense += Math.floor(combinedProps.flexibility / 2); } } else if (combinedProps.magic > 8) { itemType = 'artifact'; power = Math.floor(combinedProps.magic * 1.5); defense = Math.floor(combinedProps.magic); special = 'Enchanted '; } else { itemType = 'tool'; power = Math.floor(totalValue * 1.5); defense = Math.floor(totalValue); } // Generate creative name based on materials and properties var materialNames = { metal: ['Iron', 'Steel', 'Bronze'], wood: ['Oak', 'Pine', 'Willow'], crystal: ['Diamond', 'Ruby', 'Sapphire'], fabric: ['Silk', 'Cotton', 'Leather'] }; var typeNames = { weapon: ['Blade', 'Sword', 'Axe', 'Spear', 'Hammer'], armor: ['Shield', 'Plate', 'Mail', 'Guard', 'Protector'], artifact: ['Orb', 'Charm', 'Relic', 'Talisman'], tool: ['Tool', 'Device', 'Instrument', 'Implement'] }; var baseName = materialNames[dominantMaterial][Math.floor(Math.random() * materialNames[dominantMaterial].length)]; var typeName = typeNames[itemType][Math.floor(Math.random() * typeNames[itemType].length)]; // Add fusion indicator for multiple materials var fusionPrefix = ''; if (materialTypes.length > 1) { fusionPrefix = 'Fused '; } itemName = fusionPrefix + special + baseName + ' ' + typeName; // Bonus for unique combinations if (materialTypes.length >= 3) { power += 5; defense += 5; itemName = 'Masterwork ' + itemName; } if (materialTypes.length >= 4) { power += 10; defense += 10; itemName = 'Legendary ' + itemName; } var newItem = { name: itemName, type: itemType, power: power, defense: defense, materials: materialTypes.join('+'), rarity: materialTypes.length >= 4 ? 'legendary' : materialTypes.length >= 3 ? 'masterwork' : materialTypes.length > 1 ? 'fused' : 'common' }; craftedItems.push(newItem); // Remove used items from inventory selectedSlots.sort(function (a, b) { return b - a; }); for (var s = 0; s < selectedSlots.length; s++) { inventory.splice(selectedSlots[s], 1); } LK.getSound('craft').play(); updateInventoryDisplay(); closeCraftingPanel(); showCraftedItems(); } function showCraftedItems() { if (craftedItems.length === 0) return; var equipPanel = new Container(); for (var i = 0; i < craftedItems.length && i < 5; i++) { var item = craftedItems[i]; var equipButton = LK.getAsset('equipButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1.5 }); equipButton.y = i * 90 - 180; equipButton.itemData = item; equipButton.itemIndex = i; // Set button color based on rarity var buttonColor = 0x9b59b6; if (item.rarity === 'legendary') buttonColor = 0xf1c40f;else if (item.rarity === 'masterwork') buttonColor = 0xe74c3c;else if (item.rarity === 'fused') buttonColor = 0x3498db; equipButton.tint = buttonColor; var equipText = new Text2(item.name + '\n' + (item.type === 'weapon' ? 'Power: ' + item.power : item.type === 'armor' ? 'Defense: ' + item.defense : 'Power: ' + item.power + ' Defense: ' + item.defense) + '\nMaterials: ' + item.materials, { size: 16, fill: 0xFFFFFF }); equipText.anchor.set(0.5, 0.5); equipButton.addChild(equipText); equipButton.down = function (x, y, obj) { var item = obj.itemData; if (item.type === 'weapon') { player.equipWeapon(item); LK.effects.flashObject(player, 0xe67e22, 500); } else if (item.type === 'armor') { player.equipArmor(item); LK.effects.flashObject(player, 0x95a5a6, 500); } else { // Artifact or tool - can be equipped as either if (item.power > item.defense) { player.equipWeapon(item); LK.effects.flashObject(player, 0xe67e22, 500); } else { player.equipArmor(item); LK.effects.flashObject(player, 0x95a5a6, 500); } } craftedItems.splice(obj.itemIndex, 1); equipPanel.destroy(); updateInventoryDisplay(); }; equipPanel.addChild(equipButton); } game.addChild(equipPanel); equipPanel.x = 1024; equipPanel.y = 1366; LK.setTimeout(function () { if (equipPanel.parent) equipPanel.destroy(); }, 8000); } function spawnEnemy() { var enemy = new Enemy(); var side = Math.floor(Math.random() * 4); switch (side) { case 0: // top enemy.x = Math.random() * 2048; enemy.y = -50; break; case 1: // right enemy.x = 2098; enemy.y = Math.random() * 2732; break; case 2: // bottom enemy.x = Math.random() * 2048; enemy.y = 2782; break; case 3: // left enemy.x = -50; enemy.y = Math.random() * 2732; break; } enemies.push(enemy); game.addChild(enemy); } craftButton.down = function () { if (gameState === 'combat') { openCraftingPanel(); } }; inventoryButton.down = function () { if (gameState === 'combat' && !isInventoryOpen) { openInventoryPanel(); } }; game.down = function (x, y, obj) { if (gameState === 'combat') { // Check if tapping on an enemy to attack var attackedEnemy = false; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - x; var dy = enemy.y - y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 50 && enemy.health > 0) { // Direct tap on enemy - attack enemy.takeDamage(player.damage); LK.getSound('hit').play(); if (enemy.health <= 0) { LK.setScore(LK.getScore() + 10); playerXP += 15; checkLevelUp(); updateInventoryDisplay(); var index = enemies.indexOf(enemy); if (index > -1) enemies.splice(index, 1); } attackedEnemy = true; break; } } // If not attacking an enemy, move player to tapped location if (!attackedEnemy) { player.moveTo(x, y); } } }; game.move = function (x, y, obj) { // No move handling needed for click-based system }; game.up = function (x, y, obj) { // Click-based system handles item placement in grid slot down handlers // No special up handling needed }; game.update = function () { // Pause all combat activities when crafting/inventory is open if (gameState !== 'combat' || isCraftingOpen || isInventoryOpen) return; // Update health display healthBar.setText('Health: ' + player.health + '/' + player.maxHealth); // Spawn enemies if (LK.ticks - lastEnemySpawn > enemySpawnRate) { spawnEnemy(); lastEnemySpawn = LK.ticks; // Increase difficulty over time if (enemySpawnRate > 120) { enemySpawnRate -= 2; } } // Clean up resources that are too far for (var i = resources.length - 1; i >= 0; i--) { var resource = resources[i]; var dx = resource.x - player.x; var dy = resource.y - player.y; if (Math.sqrt(dx * dx + dy * dy) > 1000) { resource.destroy(); resources.splice(i, 1); } } // Win condition if (LK.getScore() >= 500) { LK.showYouWin(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var CraftedItem = Container.expand(function (recipe) {
var self = Container.call(this);
self.recipe = recipe;
self.name = recipe.name;
self.type = recipe.type;
self.power = recipe.power || 0;
self.defense = recipe.defense || 0;
var itemGraphics;
if (self.type === 'weapon') {
itemGraphics = self.attachAsset('weapon', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
itemGraphics = self.attachAsset('armor', {
anchorX: 0.5,
anchorY: 0.5
});
}
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
self.damage = 15;
self.speed = 1;
self.lastAttackTime = 0;
self.attackCooldown = 120; // 2 seconds at 60fps
self.update = function () {
if (player && self.health > 0) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 80) {
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
} else {
// Attack player
if (LK.ticks - self.lastAttackTime > self.attackCooldown) {
player.takeDamage(self.damage);
self.lastAttackTime = LK.ticks;
LK.getSound('hit').play();
}
}
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xFFFFFF, 200);
if (self.health <= 0) {
self.dropResources();
self.destroy();
}
};
self.dropResources = function () {
for (var i = 0; i < 2; i++) {
var resource = new Resource();
resource.x = self.x + (Math.random() - 0.5) * 60;
resource.y = self.y + (Math.random() - 0.5) * 60;
resources.push(resource);
game.addChild(resource);
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.damage = 20;
self.armor = 0;
self.weapon = null;
self.armorItem = null;
self.speed = 3;
self.targetX = self.x;
self.targetY = self.y;
self.isMoving = false;
self.update = function () {
if (self.isMoving) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
} else {
self.x = self.targetX;
self.y = self.targetY;
self.isMoving = false;
}
}
};
self.moveTo = function (x, y) {
self.targetX = x;
self.targetY = y;
self.isMoving = true;
};
self.takeDamage = function (amount) {
var actualDamage = Math.max(1, amount - self.armor);
self.health -= actualDamage;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
LK.effects.flashObject(self, 0xFF0000, 300);
};
self.equipWeapon = function (weapon) {
self.weapon = weapon;
self.damage = 20 + weapon.power;
};
self.equipArmor = function (armor) {
self.armorItem = armor;
self.armor = armor.defense;
};
return self;
});
var Resource = Container.expand(function () {
var self = Container.call(this);
var resourceGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = ['metal', 'wood', 'crystal', 'fabric'][Math.floor(Math.random() * 4)];
self.value = Math.floor(Math.random() * 5) + 1;
self.down = function (x, y, obj) {
LK.getSound('collect').play();
inventory.push({
type: self.type,
value: self.value
});
updateInventoryDisplay();
self.destroy();
var index = resources.indexOf(self);
if (index > -1) {
resources.splice(index, 1);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
var player;
var enemies = [];
var resources = [];
var inventory = [];
var craftedItems = [];
var gameState = 'combat'; // 'combat' or 'crafting'
var lastEnemySpawn = 0;
var enemySpawnRate = 300; // 5 seconds
var selectedSlots = [];
var craftingGrid = [];
var playerLevel = 1;
var selectedInventoryItem = null;
var selectedInventorySlot = null;
var playerXP = 0;
var xpToNextLevel = 100;
var materialProperties = {
metal: {
strength: 3,
durability: 2,
magic: 0,
flexibility: 1
},
wood: {
strength: 1,
durability: 1,
magic: 0,
flexibility: 2
},
crystal: {
strength: 2,
durability: 1,
magic: 4,
flexibility: 0
},
fabric: {
strength: 0,
durability: 0,
magic: 1,
flexibility: 3
}
};
// UI Elements
var healthBar = new Text2('Health: 100/100', {
size: 40,
fill: 0xFF6B6B
});
healthBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthBar);
healthBar.x = 120;
healthBar.y = 20;
var inventoryText = new Text2('Inventory: 0 items', {
size: 30,
fill: 0xFFFFFF
});
inventoryText.anchor.set(0.5, 0);
LK.gui.top.addChild(inventoryText);
inventoryText.y = 80;
var levelText = new Text2('Level: 1 | XP: 0/100', {
size: 28,
fill: 0x00ff00
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
levelText.y = 120;
// Inventory panel variables
var inventoryPanel = new Container();
var isInventoryOpen = false;
var inventoryButton = LK.getAsset('equipButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(inventoryButton);
inventoryButton.x = 100;
inventoryButton.y = -100;
var inventoryButtonText = new Text2('ITEMS', {
size: 24,
fill: 0xFFFFFF
});
inventoryButtonText.anchor.set(0.5, 0.5);
inventoryButton.addChild(inventoryButtonText);
var craftButton = LK.getAsset('craftButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottom.addChild(craftButton);
craftButton.y = -100;
var craftButtonText = new Text2('CRAFT', {
size: 36,
fill: 0xFFFFFF
});
craftButtonText.anchor.set(0.5, 0.5);
craftButton.addChild(craftButtonText);
var inventorySlots = [];
var craftingPanel = new Container();
var isCraftingOpen = false;
// Initialize player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
function updateInventoryDisplay() {
inventoryText.setText('Inventory: ' + inventory.length + ' items');
levelText.setText('Level: ' + playerLevel + ' | XP: ' + playerXP + '/' + xpToNextLevel);
if (isInventoryOpen) {
updateInventoryPanel();
}
}
function openInventoryPanel() {
if (isInventoryOpen) return;
isInventoryOpen = true;
// Create inventory panel background
var panelBg = LK.getAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 12,
scaleY: 14
});
inventoryPanel.addChild(panelBg);
// Create title
var titleText = new Text2('INVENTORY', {
size: 48,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -300;
inventoryPanel.addChild(titleText);
// Create inventory slots in a grid
updateInventoryPanel();
// Create craft button in inventory panel
var inventoryCraftButton = LK.getAsset('craftButton', {
anchorX: 0.5,
anchorY: 0.5
});
inventoryCraftButton.y = 280;
var inventoryCraftText = new Text2('CRAFT', {
size: 24,
fill: 0xFFFFFF
});
inventoryCraftText.anchor.set(0.5, 0.5);
inventoryCraftButton.addChild(inventoryCraftText);
inventoryCraftButton.down = function () {
closeInventoryPanel();
openCraftingPanel();
};
inventoryPanel.addChild(inventoryCraftButton);
// Create close button
var closeButton = LK.getAsset('equipButton', {
anchorX: 0.5,
anchorY: 0.5
});
closeButton.y = 350;
var closeText = new Text2('CLOSE', {
size: 24,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.down = function () {
closeInventoryPanel();
};
inventoryPanel.addChild(closeButton);
game.addChild(inventoryPanel);
inventoryPanel.x = 1024;
inventoryPanel.y = 1366;
}
function updateInventoryPanel() {
if (!isInventoryOpen) return;
// Remove existing inventory slots (except background, title, and close button)
for (var i = inventoryPanel.children.length - 1; i >= 0; i--) {
var child = inventoryPanel.children[i];
if (child.isInventorySlot) {
inventoryPanel.removeChild(child);
}
}
// Create inventory slots in a 8x12 grid for bigger inventory
var slotsPerRow = 8;
var maxSlots = 96;
var slotSize = 70;
var startX = -(slotsPerRow - 1) * slotSize / 2;
var startY = -200;
for (var i = 0; i < Math.min(inventory.length, maxSlots); i++) {
var row = Math.floor(i / slotsPerRow);
var col = i % slotsPerRow;
var slot = LK.getAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
slot.x = startX + col * slotSize;
slot.y = startY + row * slotSize;
slot.isInventorySlot = true;
slot.itemData = inventory[i];
slot.slotIndex = i;
// Color code by material type
var itemColor = 0x34495e;
switch (inventory[i].type) {
case 'metal':
itemColor = 0x95a5a6;
break;
case 'wood':
itemColor = 0x8b4513;
break;
case 'crystal':
itemColor = 0x9b59b6;
break;
case 'fabric':
itemColor = 0x3498db;
break;
}
slot.tint = itemColor;
// Add item text
var itemText = new Text2(inventory[i].type.charAt(0).toUpperCase() + '\n' + inventory[i].value, {
size: 16,
fill: 0xFFFFFF
});
itemText.anchor.set(0.5, 0.5);
slot.addChild(itemText);
// Add click functionality to inventory slots
slot.isSelected = false;
slot.down = function (x, y, obj) {
// Deselect previously selected item
if (selectedInventorySlot) {
selectedInventorySlot.tint = selectedInventorySlot.originalTint;
selectedInventorySlot.isSelected = false;
}
// Select this item
obj.originalTint = obj.tint;
obj.tint = 0xFFFF00; // Yellow highlight for selection
obj.isSelected = true;
selectedInventorySlot = obj;
selectedInventoryItem = obj.itemData;
};
inventoryPanel.addChild(slot);
}
}
function closeInventoryPanel() {
isInventoryOpen = false;
inventoryPanel.destroy();
inventoryPanel = new Container();
}
function openCraftingPanel() {
if (isCraftingOpen) return;
isCraftingOpen = true;
gameState = 'crafting';
// Create larger combined crafting and inventory panel background
var panelBg = LK.getAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 20
});
craftingPanel.addChild(panelBg);
// Add title for combined panel
var titleText = new Text2('CRAFTING & INVENTORY', {
size: 42,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -450;
craftingPanel.addChild(titleText);
// Create 3x3 crafting grid
craftingGrid = [];
for (var row = 0; row < 3; row++) {
craftingGrid[row] = [];
for (var col = 0; col < 3; col++) {
var gridSlot = LK.getAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
gridSlot.x = col * 120 - 120;
gridSlot.y = row * 120 - 200;
gridSlot.row = row;
gridSlot.col = col;
gridSlot.isEmpty = true;
gridSlot.itemData = null;
gridSlot.tint = 0x2c3e50;
gridSlot.down = function (x, y, obj) {
// If we have a selected item from inventory, place it here
if (selectedInventoryItem && obj.isEmpty) {
obj.itemData = selectedInventoryItem;
obj.isEmpty = false;
obj.tint = 0x3498db;
var gridText = new Text2(selectedInventoryItem.type.charAt(0).toUpperCase(), {
size: 28,
fill: 0xFFFFFF
});
gridText.anchor.set(0.5, 0.5);
obj.addChild(gridText);
// Remove item from inventory
inventory.splice(selectedInventorySlot.slotIndex, 1);
// Clear selection
selectedInventorySlot.tint = selectedInventorySlot.originalTint;
selectedInventorySlot = null;
selectedInventoryItem = null;
updateInventoryDisplay();
closeCraftingPanel();
openCraftingPanel();
}
// If clicking on occupied slot, remove item from grid slot
else if (!obj.isEmpty) {
inventory.push(obj.itemData);
obj.itemData = null;
obj.isEmpty = true;
obj.tint = 0x2c3e50;
if (obj.children && obj.children.length > 0) {
obj.removeChild(obj.children[0]);
}
updateInventoryDisplay();
}
};
craftingPanel.addChild(gridSlot);
craftingGrid[row][col] = gridSlot;
}
}
// Create expanded inventory display area in crafting panel
var slotsPerRow = 8;
var maxInventorySlots = 64;
var slotSize = 60;
var inventoryStartX = -(slotsPerRow - 1) * slotSize / 2;
var inventoryStartY = 50;
for (var i = 0; i < Math.min(inventory.length, maxInventorySlots); i++) {
var row = Math.floor(i / slotsPerRow);
var col = i % slotsPerRow;
var slot = LK.getAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9
});
slot.x = inventoryStartX + col * slotSize;
slot.y = inventoryStartY + row * slotSize;
slot.itemData = inventory[i];
slot.slotIndex = i;
// Color code by material type
var itemColor = 0x34495e;
switch (inventory[i].type) {
case 'metal':
itemColor = 0x95a5a6;
break;
case 'wood':
itemColor = 0x8b4513;
break;
case 'crystal':
itemColor = 0x9b59b6;
break;
case 'fabric':
itemColor = 0x3498db;
break;
}
slot.tint = itemColor;
var itemText = new Text2(inventory[i].type.charAt(0).toUpperCase() + '\n' + inventory[i].value, {
size: 18,
fill: 0xFFFFFF
});
itemText.anchor.set(0.5, 0.5);
slot.addChild(itemText);
slot.isSelected = false;
slot.down = function (x, y, obj) {
// Deselect previously selected item
if (selectedInventorySlot) {
selectedInventorySlot.tint = selectedInventorySlot.originalTint;
selectedInventorySlot.isSelected = false;
}
// Select this item
obj.originalTint = obj.tint;
obj.tint = 0xFFFF00; // Yellow highlight for selection
obj.isSelected = true;
selectedInventorySlot = obj;
selectedInventoryItem = obj.itemData;
};
craftingPanel.addChild(slot);
inventorySlots.push(slot);
}
// Create equipment display area
var equipmentLabel = new Text2('EQUIPPED ITEMS', {
size: 24,
fill: 0xFFD700
});
equipmentLabel.anchor.set(0.5, 0.5);
equipmentLabel.x = -300;
equipmentLabel.y = -350;
craftingPanel.addChild(equipmentLabel);
// Weapon slot
var weaponSlot = LK.getAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
weaponSlot.x = -350;
weaponSlot.y = -300;
weaponSlot.tint = 0xe67e22;
var weaponLabel = new Text2('WEAPON\n' + (player.weapon ? player.weapon.name : 'None'), {
size: 14,
fill: 0xFFFFFF
});
weaponLabel.anchor.set(0.5, 0.5);
weaponSlot.addChild(weaponLabel);
craftingPanel.addChild(weaponSlot);
// Armor slot
var armorSlot = LK.getAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
armorSlot.x = -250;
armorSlot.y = -300;
armorSlot.tint = 0x95a5a6;
var armorLabel = new Text2('ARMOR\n' + (player.armorItem ? player.armorItem.name : 'None'), {
size: 14,
fill: 0xFFFFFF
});
armorLabel.anchor.set(0.5, 0.5);
armorSlot.addChild(armorLabel);
craftingPanel.addChild(armorSlot);
// Create craft button
var craftActionButton = LK.getAsset('craftButton', {
anchorX: 0.5,
anchorY: 0.5
});
craftActionButton.y = 400;
var craftActionText = new Text2('CRAFT', {
size: 36,
fill: 0xFFFFFF
});
craftActionText.anchor.set(0.5, 0.5);
craftActionButton.addChild(craftActionText);
craftActionButton.down = function () {
craftFromGrid();
};
craftingPanel.addChild(craftActionButton);
// Create close button
var closeButton = LK.getAsset('equipButton', {
anchorX: 0.5,
anchorY: 0.5
});
closeButton.y = 420;
var closeText = new Text2('CLOSE', {
size: 24,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeText);
closeButton.down = function () {
closeCraftingPanel();
};
craftingPanel.addChild(closeButton);
game.addChild(craftingPanel);
craftingPanel.x = 1024;
craftingPanel.y = 1366;
}
function closeCraftingPanel() {
isCraftingOpen = false;
gameState = 'combat';
selectedSlots = [];
inventorySlots = [];
craftingPanel.destroy();
craftingPanel = new Container();
}
function craftFromGrid() {
var gridItems = [];
var totalValue = 0;
var materials = {};
var materialTypes = [];
// Collect items from 3x3 grid
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
var gridSlot = craftingGrid[row][col];
if (!gridSlot.isEmpty && gridSlot.itemData) {
gridItems.push({
item: gridSlot.itemData,
row: row,
col: col
});
var item = gridSlot.itemData;
if (!materials[item.type]) {
materials[item.type] = 0;
materialTypes.push(item.type);
}
materials[item.type] += item.value;
totalValue += item.value;
}
}
}
// Allow crafting even with just 1 item
if (gridItems.length === 0) return;
// Calculate combined properties same as before
var combinedProps = {
strength: 0,
durability: 0,
magic: 0,
flexibility: 0
};
var dominantMaterial = '';
var highestAmount = 0;
for (var matType in materials) {
var amount = materials[matType];
var props = materialProperties[matType];
combinedProps.strength += props.strength * amount;
combinedProps.durability += props.durability * amount;
combinedProps.magic += props.magic * amount;
combinedProps.flexibility += props.flexibility * amount;
if (amount > highestAmount) {
highestAmount = amount;
dominantMaterial = matType;
}
}
// Grid position bonus - center items get bonus
var positionBonus = 0;
for (var g = 0; g < gridItems.length; g++) {
var gridItem = gridItems[g];
if (gridItem.row === 1 && gridItem.col === 1) {
positionBonus += 5; // Center slot bonus
}
if ((gridItem.row === 0 || gridItem.row === 2) && (gridItem.col === 0 || gridItem.col === 2)) {
positionBonus += 2; // Corner bonus
}
}
// Determine item type and stats
var itemType = 'tool';
var itemName = 'Grid-Forged Item';
var power = positionBonus;
var defense = positionBonus;
// Special handling for single item crafting
if (gridItems.length === 1) {
var singleItem = gridItems[0].item;
var singleProps = materialProperties[singleItem.type];
// Single items create basic equipment based on material properties
if (singleProps.strength >= 2) {
itemType = 'weapon';
power = Math.floor(singleProps.strength * singleItem.value * 2 + positionBonus);
} else if (singleProps.durability >= 2) {
itemType = 'armor';
defense = Math.floor(singleProps.durability * singleItem.value * 2 + positionBonus);
} else if (singleProps.magic >= 2) {
itemType = 'artifact';
power = Math.floor(singleProps.magic * singleItem.value * 1.5 + positionBonus);
defense = Math.floor(singleProps.magic * singleItem.value + positionBonus);
} else {
itemType = 'tool';
power = Math.floor(singleItem.value * 2 + positionBonus);
defense = Math.floor(singleItem.value + positionBonus);
}
} else {
// Multi-item crafting logic
if (combinedProps.strength > combinedProps.durability && combinedProps.strength > combinedProps.magic) {
itemType = 'weapon';
power = Math.floor(combinedProps.strength * 2 + totalValue + positionBonus);
} else if (combinedProps.durability > combinedProps.magic) {
itemType = 'armor';
defense = Math.floor(combinedProps.durability * 2 + totalValue + positionBonus);
} else if (combinedProps.magic > 8) {
itemType = 'artifact';
power = Math.floor(combinedProps.magic * 1.5 + positionBonus);
defense = Math.floor(combinedProps.magic + positionBonus);
} else {
itemType = 'tool';
power = Math.floor(totalValue * 1.5 + positionBonus);
defense = Math.floor(totalValue + positionBonus);
}
}
// Generate name based on grid pattern
if (gridItems.length === 1) {
// Simple naming for single items
var singleItemNames = {
weapon: ['Knife', 'Blade', 'Dagger', 'Spike'],
armor: ['Shield', 'Guard', 'Vest', 'Plate'],
artifact: ['Charm', 'Gem', 'Stone', 'Crystal'],
tool: ['Tool', 'Rod', 'Handle', 'Piece']
};
var baseName = singleItemNames[itemType][Math.floor(Math.random() * singleItemNames[itemType].length)];
itemName = 'Simple ' + dominantMaterial.charAt(0).toUpperCase() + dominantMaterial.slice(1) + ' ' + baseName;
} else {
// Multi-item pattern naming
var patternNames = ['Cross', 'Line', 'Corner', 'Full', 'Sparse', 'Dense'];
var patternName = patternNames[Math.floor(Math.random() * patternNames.length)];
itemName = patternName + ' ' + dominantMaterial.charAt(0).toUpperCase() + dominantMaterial.slice(1) + ' ' + itemType.charAt(0).toUpperCase() + itemType.slice(1);
}
var newItem = {
name: itemName,
type: itemType,
power: power,
defense: defense,
materials: materialTypes.join('+'),
rarity: gridItems.length >= 7 ? 'legendary' : gridItems.length >= 5 ? 'masterwork' : gridItems.length >= 3 ? 'rare' : gridItems.length === 1 ? 'basic' : 'common'
};
craftedItems.push(newItem);
// Clear grid
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
var gridSlot = craftingGrid[row][col];
if (!gridSlot.isEmpty) {
gridSlot.itemData = null;
gridSlot.isEmpty = true;
gridSlot.tint = 0x2c3e50;
if (gridSlot.children.length > 0) {
gridSlot.removeChild(gridSlot.children[0]);
}
}
}
}
// Add XP and check for level up
playerXP += gridItems.length * 10;
checkLevelUp();
LK.getSound('craft').play();
closeCraftingPanel();
showCraftedItems();
}
function checkLevelUp() {
if (playerXP >= xpToNextLevel) {
playerLevel++;
playerXP -= xpToNextLevel;
xpToNextLevel = Math.floor(xpToNextLevel * 1.5);
// Auto collect materials on level up
autoCollectMaterials();
// Show level up effect
LK.effects.flashScreen(0x00ff00, 1000);
}
}
function autoCollectMaterials() {
var materialsToAdd = playerLevel * 2;
var materialTypes = ['metal', 'wood', 'crystal', 'fabric'];
for (var i = 0; i < materialsToAdd; i++) {
var randomType = materialTypes[Math.floor(Math.random() * materialTypes.length)];
var randomValue = Math.floor(Math.random() * playerLevel) + 1;
inventory.push({
type: randomType,
value: randomValue
});
}
updateInventoryDisplay();
}
function craftSelectedItems() {
if (selectedSlots.length < 1) return;
var materials = {};
var totalValue = 0;
var materialTypes = [];
// Calculate materials from selected slots
for (var i = 0; i < selectedSlots.length; i++) {
var item = inventory[selectedSlots[i]];
if (!materials[item.type]) {
materials[item.type] = 0;
materialTypes.push(item.type);
}
materials[item.type] += item.value;
totalValue += item.value;
}
// Calculate combined properties
var combinedProps = {
strength: 0,
durability: 0,
magic: 0,
flexibility: 0
};
var dominantMaterial = '';
var highestAmount = 0;
for (var matType in materials) {
var amount = materials[matType];
var props = materialProperties[matType];
// Add weighted properties
combinedProps.strength += props.strength * amount;
combinedProps.durability += props.durability * amount;
combinedProps.magic += props.magic * amount;
combinedProps.flexibility += props.flexibility * amount;
// Track dominant material
if (amount > highestAmount) {
highestAmount = amount;
dominantMaterial = matType;
}
}
// Determine item type based on properties
var itemType = 'tool';
var itemName = 'Crafted Item';
var power = 0;
var defense = 0;
var special = '';
if (combinedProps.strength > combinedProps.durability && combinedProps.strength > combinedProps.magic) {
itemType = 'weapon';
power = Math.floor(combinedProps.strength * 2 + totalValue);
if (combinedProps.magic > 5) {
special = 'Magical ';
power += Math.floor(combinedProps.magic);
}
} else if (combinedProps.durability > combinedProps.magic) {
itemType = 'armor';
defense = Math.floor(combinedProps.durability * 2 + totalValue);
if (combinedProps.flexibility > 5) {
special = 'Flexible ';
defense += Math.floor(combinedProps.flexibility / 2);
}
} else if (combinedProps.magic > 8) {
itemType = 'artifact';
power = Math.floor(combinedProps.magic * 1.5);
defense = Math.floor(combinedProps.magic);
special = 'Enchanted ';
} else {
itemType = 'tool';
power = Math.floor(totalValue * 1.5);
defense = Math.floor(totalValue);
}
// Generate creative name based on materials and properties
var materialNames = {
metal: ['Iron', 'Steel', 'Bronze'],
wood: ['Oak', 'Pine', 'Willow'],
crystal: ['Diamond', 'Ruby', 'Sapphire'],
fabric: ['Silk', 'Cotton', 'Leather']
};
var typeNames = {
weapon: ['Blade', 'Sword', 'Axe', 'Spear', 'Hammer'],
armor: ['Shield', 'Plate', 'Mail', 'Guard', 'Protector'],
artifact: ['Orb', 'Charm', 'Relic', 'Talisman'],
tool: ['Tool', 'Device', 'Instrument', 'Implement']
};
var baseName = materialNames[dominantMaterial][Math.floor(Math.random() * materialNames[dominantMaterial].length)];
var typeName = typeNames[itemType][Math.floor(Math.random() * typeNames[itemType].length)];
// Add fusion indicator for multiple materials
var fusionPrefix = '';
if (materialTypes.length > 1) {
fusionPrefix = 'Fused ';
}
itemName = fusionPrefix + special + baseName + ' ' + typeName;
// Bonus for unique combinations
if (materialTypes.length >= 3) {
power += 5;
defense += 5;
itemName = 'Masterwork ' + itemName;
}
if (materialTypes.length >= 4) {
power += 10;
defense += 10;
itemName = 'Legendary ' + itemName;
}
var newItem = {
name: itemName,
type: itemType,
power: power,
defense: defense,
materials: materialTypes.join('+'),
rarity: materialTypes.length >= 4 ? 'legendary' : materialTypes.length >= 3 ? 'masterwork' : materialTypes.length > 1 ? 'fused' : 'common'
};
craftedItems.push(newItem);
// Remove used items from inventory
selectedSlots.sort(function (a, b) {
return b - a;
});
for (var s = 0; s < selectedSlots.length; s++) {
inventory.splice(selectedSlots[s], 1);
}
LK.getSound('craft').play();
updateInventoryDisplay();
closeCraftingPanel();
showCraftedItems();
}
function showCraftedItems() {
if (craftedItems.length === 0) return;
var equipPanel = new Container();
for (var i = 0; i < craftedItems.length && i < 5; i++) {
var item = craftedItems[i];
var equipButton = LK.getAsset('equipButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1.5
});
equipButton.y = i * 90 - 180;
equipButton.itemData = item;
equipButton.itemIndex = i;
// Set button color based on rarity
var buttonColor = 0x9b59b6;
if (item.rarity === 'legendary') buttonColor = 0xf1c40f;else if (item.rarity === 'masterwork') buttonColor = 0xe74c3c;else if (item.rarity === 'fused') buttonColor = 0x3498db;
equipButton.tint = buttonColor;
var equipText = new Text2(item.name + '\n' + (item.type === 'weapon' ? 'Power: ' + item.power : item.type === 'armor' ? 'Defense: ' + item.defense : 'Power: ' + item.power + ' Defense: ' + item.defense) + '\nMaterials: ' + item.materials, {
size: 16,
fill: 0xFFFFFF
});
equipText.anchor.set(0.5, 0.5);
equipButton.addChild(equipText);
equipButton.down = function (x, y, obj) {
var item = obj.itemData;
if (item.type === 'weapon') {
player.equipWeapon(item);
LK.effects.flashObject(player, 0xe67e22, 500);
} else if (item.type === 'armor') {
player.equipArmor(item);
LK.effects.flashObject(player, 0x95a5a6, 500);
} else {
// Artifact or tool - can be equipped as either
if (item.power > item.defense) {
player.equipWeapon(item);
LK.effects.flashObject(player, 0xe67e22, 500);
} else {
player.equipArmor(item);
LK.effects.flashObject(player, 0x95a5a6, 500);
}
}
craftedItems.splice(obj.itemIndex, 1);
equipPanel.destroy();
updateInventoryDisplay();
};
equipPanel.addChild(equipButton);
}
game.addChild(equipPanel);
equipPanel.x = 1024;
equipPanel.y = 1366;
LK.setTimeout(function () {
if (equipPanel.parent) equipPanel.destroy();
}, 8000);
}
function spawnEnemy() {
var enemy = new Enemy();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// top
enemy.x = Math.random() * 2048;
enemy.y = -50;
break;
case 1:
// right
enemy.x = 2098;
enemy.y = Math.random() * 2732;
break;
case 2:
// bottom
enemy.x = Math.random() * 2048;
enemy.y = 2782;
break;
case 3:
// left
enemy.x = -50;
enemy.y = Math.random() * 2732;
break;
}
enemies.push(enemy);
game.addChild(enemy);
}
craftButton.down = function () {
if (gameState === 'combat') {
openCraftingPanel();
}
};
inventoryButton.down = function () {
if (gameState === 'combat' && !isInventoryOpen) {
openInventoryPanel();
}
};
game.down = function (x, y, obj) {
if (gameState === 'combat') {
// Check if tapping on an enemy to attack
var attackedEnemy = false;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - x;
var dy = enemy.y - y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 50 && enemy.health > 0) {
// Direct tap on enemy - attack
enemy.takeDamage(player.damage);
LK.getSound('hit').play();
if (enemy.health <= 0) {
LK.setScore(LK.getScore() + 10);
playerXP += 15;
checkLevelUp();
updateInventoryDisplay();
var index = enemies.indexOf(enemy);
if (index > -1) enemies.splice(index, 1);
}
attackedEnemy = true;
break;
}
}
// If not attacking an enemy, move player to tapped location
if (!attackedEnemy) {
player.moveTo(x, y);
}
}
};
game.move = function (x, y, obj) {
// No move handling needed for click-based system
};
game.up = function (x, y, obj) {
// Click-based system handles item placement in grid slot down handlers
// No special up handling needed
};
game.update = function () {
// Pause all combat activities when crafting/inventory is open
if (gameState !== 'combat' || isCraftingOpen || isInventoryOpen) return;
// Update health display
healthBar.setText('Health: ' + player.health + '/' + player.maxHealth);
// Spawn enemies
if (LK.ticks - lastEnemySpawn > enemySpawnRate) {
spawnEnemy();
lastEnemySpawn = LK.ticks;
// Increase difficulty over time
if (enemySpawnRate > 120) {
enemySpawnRate -= 2;
}
}
// Clean up resources that are too far
for (var i = resources.length - 1; i >= 0; i--) {
var resource = resources[i];
var dx = resource.x - player.x;
var dy = resource.y - player.y;
if (Math.sqrt(dx * dx + dy * dy) > 1000) {
resource.destroy();
resources.splice(i, 1);
}
}
// Win condition
if (LK.getScore() >= 500) {
LK.showYouWin();
}
};