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