User prompt
Shrink the text of collection and inventory buttons to fit inside the button
User prompt
Adjust the text of collection and inventory buttons to fit inside the button
User prompt
equalize all buttons sizes (roll, collection, inventory, craft)
User prompt
Please fix the bug: 'storage.clear is not a function' in or related to this line: 'storage.clear();' Line Number: 363
User prompt
Please fix the bug: 'storage.reset is not a function' in or related to this line: 'storage.reset();' Line Number: 363
User prompt
Please fix the bug: 'storage.clear is not a function' in or related to this line: 'storage.clear();' Line Number: 363
User prompt
Reset all player data every time the game is restarted.
User prompt
Let's keep track of permanent buffs from craft items.
User prompt
Let's add a recipe to the craft button. The recipe name will be "Fortune Leaf" and will be bound to the craft_fortuneleaf asset. To make this item, you will need "Moss + Breeze". This craft item will permanently give "3x luck multiplier".
User prompt
Let's add a recipe to the craft button. The recipe name will be "Lucky Pebble" and will be bound to the craft_luckypebble asset. To make this item, you will need "Spark + Sand". This craft item will permanently give "2x luck multiplier".
User prompt
Let's add a recipe to the craft button. The recipe will be called "Lucky Pebble" and will be bound to the craft_luckypebble asset. To make this item, you will need "Spark + Sand". This craft item will give "2x luck multiplier".
User prompt
Let's add the 2nd craft item. The recipe name will be "Beginner's Fortune" and will be bound to the item_fortune asset. "Moss + Breeze + Ember" will be used to make this item. The item will provide a "First roll of each day has +5% better odds" bonus.
User prompt
Craft items will not come out with rolls. We will only be able to get them with craft. They will give us permanent bonuses.
User prompt
Craft items will not be available in the collection tab. They are special items.
User prompt
Let's add a recipe inside the Craft button. The recipe name will be "Lucky Spark" and will be bound to the item_luckyspark asset. "Spark + Water + Sand" will be used to make this item. The item will provide a "+1% base chance increase for rolling Uncommon or higher" bonus.
User prompt
We will add recipes to the craft button. So let's make the button work
User prompt
When we press the collection and inventory button, the craft button should not appear.
User prompt
Add Craft button under Inventory button using roll_btn asset
User prompt
It's time to add a craft system. We will make new items with the items accumulated in the inventory and get permanent buffs. Let's put the crafting button under the inventory button and connect the roll_btn asset
User prompt
Add a new item. His name will be "Spark". Its rarity will be 1/28000. Link item_spark asset to Spark item.
User prompt
Let's add a 2-second cooldown to the Roll button.
User prompt
The cooldown on the roll button will decrease to 9 when we are level 2, to 8 when we are level 3, to 7 when we are level 4, to 6 when we are level 5, and to 5 for level 6 and above.
User prompt
Let's add a 10-second waiting time to the roll button.
User prompt
Add a new item. His name will be "Vine". Its rarity will be 1/24000. Link item_vine asset to Vine item.
User prompt
Add a new item. His name will be "Thunder". Its rarity will be 1/16000. Link item_thunder asset to Thunder item.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { collection: [] }); /**** * Classes ****/ // Collection item icon (for collection view) var CollectionIcon = Container.expand(function () { var self = Container.call(this); self.asset = null; self.overlayText = null; self.setItem = function (itemDef, owned) { if (self.asset) { self.removeChild(self.asset); self.asset = null; } if (self.overlayText) { self.removeChild(self.overlayText); self.overlayText = null; } self.asset = self.attachAsset(itemDef.asset, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); self.asset.alpha = 1; if (itemDef.rotation) self.asset.rotation = itemDef.rotation; if (itemDef.overlay) { self.overlayText = new Text2(itemDef.overlay, { size: 60, fill: "#222" }); self.overlayText.anchor.set(0.5, 0.5); self.addChild(self.overlayText); } // If not owned, gray out if (!owned) self.asset.alpha = 0.25;else self.asset.alpha = 1; }; return self; }); // Item display class var ItemDisplay = Container.expand(function () { var self = Container.call(this); self.asset = null; self.overlayText = null; self.setItem = function (itemDef) { // Remove previous if (self.asset) { self.removeChild(self.asset); self.asset = null; } if (self.overlayText) { self.removeChild(self.overlayText); self.overlayText = null; } // Add shape self.asset = self.attachAsset(itemDef.asset, { anchorX: 0.5, anchorY: 0.5 }); self.asset.alpha = 1; if (itemDef.rotation) self.asset.rotation = itemDef.rotation; // Overlay text if needed if (itemDef.overlay) { self.overlayText = new Text2(itemDef.overlay, { size: 120, fill: "#222" }); self.overlayText.anchor.set(0.5, 0.5); self.addChild(self.overlayText); } }; return self; }); // Roll button class var RollButton = Container.expand(function () { var self = Container.call(this); self.bg = self.attachAsset('roll_btn', { anchorX: 0.5, anchorY: 0.5 }); self.bg.alpha = 1; self.label = new Text2("ROLL", { size: 70, fill: "#fff" }); self.label.anchor.set(0.5, 0.5); self.addChild(self.label); // Simple press effect self.down = function (x, y, obj) { tween(self.bg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 80, easing: tween.cubicIn }); }; self.up = function (x, y, obj) { tween(self.bg, { scaleX: 1, scaleY: 1 }, { duration: 80, easing: tween.cubicOut }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Item definitions: id, name, rarity (1 in X), asset, extra (for shape/rotation/text) // We'll overlay text for "hex" // We'll overlay text for "star" // We'll rotate this to look like a triangle /* We will use simple shapes for items (boxes, ellipses) and a "roll" button. Each item will have a unique color and shape for visual distinction. */ // --- State --- var ITEM_DEFS = [{ id: 0, name: "Water", rarity: 2, asset: 'item_box' }, { id: 1, name: "Stone", rarity: 3, asset: 'item_ellipse' }, { id: 2, name: "Flame", rarity: 7, asset: 'item_triangle', rotation: Math.PI / 4 }, { id: 3, name: "Breeze", rarity: 20, asset: 'item_star', overlay: "★" }, { id: 4, name: "Amber", rarity: 50, asset: 'item_hex', overlay: "⬡" }, { id: 5, name: "Moss", rarity: 60, asset: 'item_moss' }, { id: 6, name: "Crystal", rarity: 128, asset: 'item_crystal' }, { id: 7, name: "Sand", rarity: 256, asset: 'item_sand' }, { id: 8, name: "Ash", rarity: 512, asset: 'item_ash' }, { id: 9, name: "Iron", rarity: 1000, asset: 'item_iron' }, { id: 10, name: "Quartz", rarity: 2000, asset: 'item_quartz' }, { id: 11, name: "Smoke", rarity: 4000, asset: 'item_smoke' }, { id: 12, name: "Frost", rarity: 8000, asset: 'item_frost' }, { id: 13, name: "Thunder", rarity: 16000, asset: 'item_thunder' }, { id: 14, name: "Vine", rarity: 24000, asset: 'item_vine' }, { id: 15, name: "Spark", rarity: 28000, asset: 'item_spark' }]; // --- Luck Event State --- var luckEventActive = false; // true if a luck event is active var luckEventMultiplier = 1; // 1 (normal), 10, or 25 var luckEventTimeout = null; // timeout id for ending event var luckEventLabel = null; // Text2 label for event var luckEventTimerBar = null; // Container for timer bar var luckEventEndTime = 0; // timestamp when event ends // --- Level State --- var level = 1; var rollsThisLevel = 0; var rollsTotal = 0; var levelBar = null; var levelBarLabel = null; var levelBarBg = null; var levelBarFg = null; var levelLuckMultiplier = 1; // Helper: Start a random luck event (10x or 25x) function startLuckEvent(multiplier) { // End any existing event endLuckEvent(); luckEventActive = true; luckEventMultiplier = multiplier; luckEventEndTime = Date.now() + 20000; // 20 seconds from now // Show label if (!luckEventLabel) { luckEventLabel = new Text2("", { size: 80, fill: 0xFFE066 }); luckEventLabel.anchor.set(0.5, 0); LK.gui.top.addChild(luckEventLabel); // Keep level bar UI in sync (in case of external changes) if (levelBarFg && levelBarLabel) { var frac = Math.min(1, rollsThisLevel / 100); levelBarFg.width = 1200 * frac; levelBarLabel.setText("Level " + level + " (" + rollsThisLevel + "/100) Luck x" + levelLuckMultiplier * luckEventMultiplier); } } ; luckEventLabel.visible = true; luckEventLabel.setText(multiplier === 25 ? "💎 ULTRA LUCK! 25x odds for 20s!" : "🍀 LUCKY! 10x odds for 20s!"); luckEventLabel.x = 180; luckEventLabel.y = 340; // Show timer bar if (!luckEventTimerBar) { luckEventTimerBar = new Container(); luckEventTimerBar.bg = LK.getAsset('item_box', { anchorX: 0, anchorY: 0 }); luckEventTimerBar.bg.width = 600; luckEventTimerBar.bg.height = 30; luckEventTimerBar.bg.alpha = 0.2; luckEventTimerBar.addChild(luckEventTimerBar.bg); luckEventTimerBar.fg = LK.getAsset('item_box', { anchorX: 0, anchorY: 0 }); luckEventTimerBar.fg.width = 600; luckEventTimerBar.fg.height = 30; luckEventTimerBar.fg.alpha = 0.7; luckEventTimerBar.fg.tint = 0xffe066; luckEventTimerBar.addChild(luckEventTimerBar.fg); LK.gui.top.addChild(luckEventTimerBar); } luckEventTimerBar.visible = true; luckEventTimerBar.x = 180; luckEventTimerBar.y = 440; // Set timeout to end event luckEventTimeout = LK.setTimeout(function () { endLuckEvent(); }, 20000); } // Helper: End the luck event function endLuckEvent() { luckEventActive = false; luckEventMultiplier = 1; if (luckEventTimeout) { LK.clearTimeout(luckEventTimeout); luckEventTimeout = null; } if (luckEventLabel) luckEventLabel.visible = false; if (luckEventTimerBar) luckEventTimerBar.visible = false; } // Helper: Schedule the next random luck event function scheduleNextLuckEvent() { // Next event in 20-40 seconds var nextIn = 20000 + Math.random() * 20000; LK.setTimeout(function () { // 50% chance for 10x, 50% for 25x var multiplier = Math.random() < 0.5 ? 10 : 25; startLuckEvent(multiplier); // Schedule next event after this one ends LK.setTimeout(scheduleNextLuckEvent, 20000); }, nextIn); } // Start the first luck event timer scheduleNextLuckEvent(); // Helper: get item by id function getItemDef(id) { for (var i = 0; i < ITEM_DEFS.length; ++i) { if (ITEM_DEFS[i].id === id) return ITEM_DEFS[i]; } return null; } var collection = storage.collection || []; // array of owned item ids var lastRollResult = null; // id of last rolled item var rolling = false; // is animation running var showCollection = false; // --- Roll Cooldown State --- var rollCooldown = false; // true if roll is on cooldown var rollCooldownTimeout = null; // timeout id for cooldown // --- UI Elements --- // Level bar UI (bottom of screen) levelBar = new Container(); levelBarBg = LK.getAsset('item_box', { anchorX: 0.5, anchorY: 0.5 }); levelBarBg.width = 1200; levelBarBg.height = 60; levelBarBg.alpha = 0.18; levelBar.addChild(levelBarBg); levelBarFg = LK.getAsset('item_box', { anchorX: 0.5, anchorY: 0.5 }); levelBarFg.width = 1200; levelBarFg.height = 60; levelBarFg.alpha = 0.7; levelBarFg.tint = 0x44e0ff; levelBar.addChild(levelBarFg); levelBarLabel = new Text2("", { size: 48, fill: "#fff" }); levelBarLabel.anchor.set(0.5, 0.5); levelBar.addChild(levelBarLabel); levelBar.x = 2048 / 2; levelBar.y = 2732 - 100; game.addChild(levelBar); // Title var titleTxt = new Text2("Loot Roll", { size: 120, fill: "#fff" }); titleTxt.anchor.set(0.5, 0); LK.gui.top.addChild(titleTxt); // Rarity info var rarityTxt = new Text2("", { size: 60, fill: "#fff" }); rarityTxt.anchor.set(0.5, 0); LK.gui.top.addChild(rarityTxt); // Main item display var itemDisplay = new ItemDisplay(); itemDisplay.x = 2048 / 2; itemDisplay.y = 900; game.addChild(itemDisplay); // Item name display (shows the rolled item's name) var itemNameTxt = new Text2("", { size: 90, fill: "#fff" }); itemNameTxt.anchor.set(0.5, 0); itemNameTxt.x = 2048 / 2; itemNameTxt.y = itemDisplay.y + 220; // Place below the item display game.addChild(itemNameTxt); // Roll button var rollBtn = new RollButton(); rollBtn.x = 2048 / 2; rollBtn.y = 1400; // moved up from 1800 game.addChild(rollBtn); // "Show Collection" button var showCollBtn = new Container(); var showCollBg = showCollBtn.attachAsset('roll_btn', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7 }); showCollBg.alpha = 1; var showCollLabel = new Text2("COLLECTION", { size: 48, fill: "#fff" }); showCollLabel.anchor.set(0.5, 0.5); showCollBtn.addChild(showCollLabel); showCollBtn.x = 2048 / 2; showCollBtn.y = 1600; // moved up from 2050 game.addChild(showCollBtn); // --- Inventory Button and State --- // inventory is now an array of objects: { id: <itemId>, count: <number> } var inventory = []; var inventoryBtn = new Container(); var inventoryBg = inventoryBtn.attachAsset('roll_btn', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7 }); inventoryBg.alpha = 1; var inventoryLabel = new Text2("INVENTORY", { size: 48, fill: "#fff" }); inventoryLabel.anchor.set(0.5, 0.5); inventoryBtn.addChild(inventoryLabel); // Place inventory button under collection button inventoryBtn.x = 2048 / 2; inventoryBtn.y = showCollBtn.y + 170; // will now be 1770, higher up game.addChild(inventoryBtn); // --- Craft Button --- var craftBtn = new Container(); var craftBg = craftBtn.attachAsset('roll_btn', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7 }); craftBg.alpha = 1; var craftLabel = new Text2("CRAFT", { size: 48, fill: "#fff" }); craftLabel.anchor.set(0.5, 0.5); craftBtn.addChild(craftLabel); // Place craft button under inventory button craftBtn.x = 2048 / 2; craftBtn.y = inventoryBtn.y + 170; game.addChild(craftBtn); // --- Crafting Recipes --- var CRAFT_RECIPES = [{ id: 0, name: "Lucky Pebble", asset: "craft_luckypebble", ingredients: [{ id: 15, count: 1 }, // Spark { id: 7, count: 1 } // Sand ], effect: "luckx2" }]; // --- Craft Overlay --- var craftOverlay = new Container(); craftOverlay.visible = false; game.addChild(craftOverlay); // Craft result display var craftResultDisplay = new ItemDisplay(); craftResultDisplay.x = 2048 / 2; craftResultDisplay.y = 900; craftOverlay.addChild(craftResultDisplay); var craftResultNameTxt = new Text2("", { size: 90, fill: "#fff" }); craftResultNameTxt.anchor.set(0.5, 0); craftResultNameTxt.x = 2048 / 2; craftResultNameTxt.y = craftResultDisplay.y + 220; craftOverlay.addChild(craftResultNameTxt); var craftDescTxt = new Text2("", { size: 60, fill: 0xFFE066 }); craftDescTxt.anchor.set(0.5, 0); craftDescTxt.x = 2048 / 2; craftDescTxt.y = craftResultNameTxt.y + 120; craftOverlay.addChild(craftDescTxt); // Craft ingredient icons var craftIngredientIcons = []; // Craft "Back" button var craftBackBtn = new Container(); var craftBackBg = craftBackBtn.attachAsset('roll_btn', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); craftBackBg.alpha = 1; var craftBackLabel = new Text2("BACK", { size: 48, fill: "#fff" }); craftBackLabel.anchor.set(0.5, 0.5); craftBackBtn.addChild(craftBackLabel); craftBackBtn.x = 2048 / 2; craftBackBtn.y = 2500; craftOverlay.addChild(craftBackBtn); // Craft "Make" button var craftMakeBtn = new Container(); var craftMakeBg = craftMakeBtn.attachAsset('roll_btn', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7 }); craftMakeBg.alpha = 1; var craftMakeLabel = new Text2("MAKE", { size: 48, fill: "#fff" }); craftMakeLabel.anchor.set(0.5, 0.5); craftMakeBtn.addChild(craftMakeLabel); craftMakeBtn.x = 2048 / 2; craftMakeBtn.y = craftBackBtn.y - 200; craftOverlay.addChild(craftMakeBtn); // Helper: update craft overlay for Lucky Pebble function updateCraftOverlay() { // Only one recipe for now var recipe = CRAFT_RECIPES[0]; // Show result craftResultDisplay.setItem({ asset: recipe.asset }); craftResultNameTxt.setText(recipe.name); craftDescTxt.setText("2x luck multiplier for rarest item (until next roll)"); // Remove old ingredient icons for (var i = 0; i < craftIngredientIcons.length; ++i) { craftOverlay.removeChild(craftIngredientIcons[i]); } craftIngredientIcons = []; // Layout: horizontally centered var spacing = 320; var startX = 2048 / 2 - (recipe.ingredients.length - 1) * spacing / 2; var y = craftResultDisplay.y + 400; for (var i = 0; i < recipe.ingredients.length; ++i) { var ing = recipe.ingredients[i]; var itemDef = getItemDef(ing.id); var icon = new CollectionIcon(); icon.setItem(itemDef, true); icon.x = startX + i * spacing; icon.y = y; // Show count var haveCount = 0; for (var j = 0; j < inventory.length; ++j) { if (inventory[j].id === ing.id) { haveCount = inventory[j].count; break; } } var countTxt = new Text2(haveCount + " / " + ing.count, { size: 40, fill: haveCount >= ing.count ? "#fff" : "#f44" }); countTxt.anchor.set(0.5, 0); countTxt.x = 0; countTxt.y = 90; icon.addChild(countTxt); craftOverlay.addChild(icon); craftIngredientIcons.push(icon); } } // Craft button handlers craftBtn.down = function (x, y, obj) { craftBg.scaleX = 0.95; craftBg.scaleY = 0.95; }; craftBtn.up = function (x, y, obj) { craftBg.scaleX = 1; craftBg.scaleY = 1; if (rolling || showCollection || inventoryOverlay.visible) return; // Show craft overlay craftOverlay.visible = true; updateCraftOverlay(); // Hide main UI elements titleTxt.visible = false; rarityTxt.visible = false; itemDisplay.visible = false; itemNameTxt.visible = false; rollBtn.visible = false; showCollBtn.visible = false; inventoryBtn.visible = false; craftBtn.visible = false; }; // Craft overlay back button craftBackBtn.down = function (x, y, obj) { craftBackBg.scaleX = 0.95; craftBackBg.scaleY = 0.95; }; craftBackBtn.up = function (x, y, obj) { craftBackBg.scaleX = 1; craftBackBg.scaleY = 1; craftOverlay.visible = false; // Restore main UI elements titleTxt.visible = true; rarityTxt.visible = true; itemDisplay.visible = true; itemNameTxt.visible = true; rollBtn.visible = true; showCollBtn.visible = true; inventoryBtn.visible = true; craftBtn.visible = true; }; // Craft "Make" button logic craftMakeBtn.down = function (x, y, obj) { craftMakeBg.scaleX = 0.95; craftMakeBg.scaleY = 0.95; }; craftMakeBtn.up = function (x, y, obj) { craftMakeBg.scaleX = 1; craftMakeBg.scaleY = 1; // Only one recipe for now var recipe = CRAFT_RECIPES[0]; // Check if player has all ingredients var canCraft = true; for (var i = 0; i < recipe.ingredients.length; ++i) { var ing = recipe.ingredients[i]; var haveCount = 0; for (var j = 0; j < inventory.length; ++j) { if (inventory[j].id === ing.id) { haveCount = inventory[j].count; break; } } if (haveCount < ing.count) { canCraft = false; break; } } if (!canCraft) { // Flash ingredients red for (var i = 0; i < craftIngredientIcons.length; ++i) { LK.effects.flashObject(craftIngredientIcons[i], 0xff4444, 400); } return; } // Remove ingredients from inventory for (var i = 0; i < recipe.ingredients.length; ++i) { var ing = recipe.ingredients[i]; for (var j = 0; j < inventory.length; ++j) { if (inventory[j].id === ing.id) { inventory[j].count -= ing.count; if (inventory[j].count <= 0) { inventory.splice(j, 1); } break; } } } // Apply effect: 2x luck multiplier for rarest item (until next roll) levelLuckMultiplier *= 2; // Flash level bar to indicate effect LK.effects.flashObject(levelBarFg, 0x44ff66, 800); // Show confirmation craftDescTxt.setText("2x luck! Next roll is boosted."); // Hide craft overlay after short delay and restore UI LK.setTimeout(function () { craftOverlay.visible = false; titleTxt.visible = true; rarityTxt.visible = true; itemDisplay.visible = true; itemNameTxt.visible = true; rollBtn.visible = true; showCollBtn.visible = true; inventoryBtn.visible = true; craftBtn.visible = true; }, 1200); updateInventoryGrid && updateInventoryGrid(); updateCraftOverlay(); }; // Collection view overlay var collectionOverlay = new Container(); collectionOverlay.visible = false; game.addChild(collectionOverlay); // "Back" button for collection var backBtn = new Container(); var backBg = backBtn.attachAsset('roll_btn', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); backBg.alpha = 1; var backLabel = new Text2("BACK", { size: 48, fill: "#fff" }); backLabel.anchor.set(0.5, 0.5); backBtn.addChild(backLabel); backBtn.x = 2048 / 2; backBtn.y = 2500; collectionOverlay.addChild(backBtn); // Collection grid var collectionIcons = []; function updateCollectionGrid() { // Remove old for (var i = 0; i < collectionIcons.length; ++i) collectionOverlay.removeChild(collectionIcons[i]); collectionIcons = []; // Layout: 3 per row, centered var perRow = 3; var spacing = 320; var startX = 2048 / 2 - spacing; var startY = 600; for (var i = 0; i < ITEM_DEFS.length; ++i) { var item = ITEM_DEFS[i]; var owned = collection.indexOf(item.id) !== -1; var icon = new CollectionIcon(); icon.setItem(item, owned); icon.x = startX + i % perRow * spacing; icon.y = startY + Math.floor(i / perRow) * spacing; // Name and rarity var nameTxt = new Text2(item.name, { size: 36, fill: "#fff" }); nameTxt.anchor.set(0.5, 0); nameTxt.x = 0; nameTxt.y = 90; icon.addChild(nameTxt); var rareTxt = new Text2("1 in " + item.rarity, { size: 28, fill: "#aaa" }); rareTxt.anchor.set(0.5, 0); rareTxt.x = 0; rareTxt.y = 130; icon.addChild(rareTxt); collectionOverlay.addChild(icon); collectionIcons.push(icon); } } // --- Functions --- function updateMainDisplay() { // Show last rolled item or first item var itemId = lastRollResult !== null ? lastRollResult : 0; var itemDef = getItemDef(itemId); itemDisplay.setItem(itemDef); // Show name and rarity rarityTxt.setText(itemDef.name + " • 1 in " + itemDef.rarity); // Show item name below the item display itemNameTxt.setText(itemDef.name); } function rollForItem() { // Weighted random roll, apply luck event and level multipliers var totalWeight = 0; for (var i = 0; i < ITEM_DEFS.length; ++i) { var rarity = ITEM_DEFS[i].rarity; // Apply multiplier: only to rarest item (lowest odds, highest rarity) var effectiveRarity = rarity; if (i === ITEM_DEFS.length - 1) { effectiveRarity = Math.max(1, Math.floor(rarity / (levelLuckMultiplier * luckEventMultiplier))); } totalWeight += 1 / effectiveRarity; } var r = Math.random() * totalWeight; var acc = 0; for (var i = 0; i < ITEM_DEFS.length; ++i) { var rarity = ITEM_DEFS[i].rarity; var effectiveRarity = rarity; if (i === ITEM_DEFS.length - 1) { effectiveRarity = Math.max(1, Math.floor(rarity / (levelLuckMultiplier * luckEventMultiplier))); } acc += 1 / effectiveRarity; if (r <= acc) return ITEM_DEFS[i].id; } return ITEM_DEFS[ITEM_DEFS.length - 1].id; } function animateRoll(resultId) { rolling = true; // Flash through random items, then land on result var flashes = 12; var flashTime = 60; var i = 0; function flashNext() { if (i < flashes) { var fakeId = Math.floor(Math.random() * ITEM_DEFS.length); itemDisplay.setItem(getItemDef(fakeId)); ++i; LK.setTimeout(flashNext, flashTime); } else { // Land on result itemDisplay.setItem(getItemDef(resultId)); // Animate scale itemDisplay.scale.set(1.2, 1.2); tween(itemDisplay, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.bounceOut }); rolling = false; updateMainDisplay(); } } flashNext(); } // --- Event Handlers --- // Roll button rollBtn.down = function (x, y, obj) { if (rolling || showCollection || rollCooldown) return; // Call the original RollButton.down (the class method), not this event handler if (typeof RollButton.prototype.down === "function") { RollButton.prototype.down.call(rollBtn, x, y, obj); } }; rollBtn.up = function (x, y, obj) { if (rolling || showCollection || rollCooldown) return; // Start cooldown rollCooldown = true; if (rollCooldownTimeout) { LK.clearTimeout(rollCooldownTimeout); } rollBtn.alpha = 0.5; rollCooldownTimeout = LK.setTimeout(function () { rollCooldown = false; rollBtn.alpha = 1; rollCooldownTimeout = null; }, 2000); // Do roll var resultId = rollForItem(); lastRollResult = resultId; // Add to collection if new if (collection.indexOf(resultId) === -1) { collection.push(resultId); storage.collection = collection; } // Add all rolled items to inventory, accumulate up to 64 per item var itemDef = getItemDef(resultId); if (itemDef) { // Find if item already exists in inventory var found = false; for (var i = 0; i < inventory.length; ++i) { if (inventory[i].id === resultId) { if (inventory[i].count < 64) { inventory[i].count += 1; } found = true; break; } } if (!found) { inventory.push({ id: resultId, count: 1 }); } } animateRoll(resultId); updateMainDisplay(); // --- Level logic --- rollsTotal += 1; rollsThisLevel += 1; var leveledUp = false; if (rollsThisLevel >= 50) { level += 1; rollsThisLevel = 0; leveledUp = true; // Increase level-based luck multiplier levelLuckMultiplier += 1; // Flash level bar to indicate level up LK.effects.flashObject(levelBarFg, 0xffe066, 800); } // Update level bar UI var frac = Math.min(1, rollsThisLevel / 50); levelBarFg.width = 1200 * frac; levelBarLabel.setText("Level " + level + " (" + rollsThisLevel + "/50) Luck x" + levelLuckMultiplier * luckEventMultiplier); // Call the original RollButton.up (the class method), not this event handler if (typeof RollButton.prototype.up === "function") { RollButton.prototype.up.call(rollBtn, x, y, obj); } }; // Show collection showCollBtn.down = function (x, y, obj) { if (rolling) return; showCollBg.scaleX = 0.95; showCollBg.scaleY = 0.95; }; showCollBtn.up = function (x, y, obj) { if (rolling) return; showCollBg.scaleX = 1; showCollBg.scaleY = 1; showCollection = true; collectionOverlay.visible = true; updateCollectionGrid(); // Hide main UI elements when collection is open titleTxt.visible = false; rarityTxt.visible = false; itemDisplay.visible = false; itemNameTxt.visible = false; rollBtn.visible = false; showCollBtn.visible = false; inventoryBtn.visible = false; craftBtn.visible = false; }; // Back from collection backBtn.down = function (x, y, obj) { backBg.scaleX = 0.95; backBg.scaleY = 0.95; }; backBtn.up = function (x, y, obj) { backBg.scaleX = 1; backBg.scaleY = 1; showCollection = false; collectionOverlay.visible = false; // Restore main UI elements when leaving collection titleTxt.visible = true; rarityTxt.visible = true; itemDisplay.visible = true; itemNameTxt.visible = true; rollBtn.visible = true; showCollBtn.visible = true; inventoryBtn.visible = true; craftBtn.visible = true; }; // --- Inventory Overlay --- var inventoryOverlay = new Container(); inventoryOverlay.visible = false; game.addChild(inventoryOverlay); // "Back" button for inventory var invBackBtn = new Container(); var invBackBg = invBackBtn.attachAsset('roll_btn', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); invBackBg.alpha = 1; var invBackLabel = new Text2("BACK", { size: 48, fill: "#fff" }); invBackLabel.anchor.set(0.5, 0.5); invBackBtn.addChild(invBackLabel); invBackBtn.x = 2048 / 2; invBackBtn.y = 2500; inventoryOverlay.addChild(invBackBtn); // Inventory grid var inventoryIcons = []; function updateInventoryGrid() { // Remove old for (var i = 0; i < inventoryIcons.length; ++i) inventoryOverlay.removeChild(inventoryIcons[i]); inventoryIcons = []; // Layout: 3 per row, centered var perRow = 3; var spacing = 320; var startX = 2048 / 2 - spacing; var startY = 600; for (var i = 0; i < inventory.length; ++i) { var invEntry = inventory[i]; var itemId = invEntry.id; var itemCount = invEntry.count; var item = getItemDef(itemId); if (!item) continue; var icon = new CollectionIcon(); icon.setItem(item, true); icon.x = startX + i % perRow * spacing; icon.y = startY + Math.floor(i / perRow) * spacing; // Name and rarity var nameTxt = new Text2(item.name, { size: 36, fill: "#fff" }); nameTxt.anchor.set(0.5, 0); nameTxt.x = 0; nameTxt.y = 90; icon.addChild(nameTxt); var rareTxt = new Text2("1 in " + item.rarity, { size: 28, fill: "#aaa" }); rareTxt.anchor.set(0.5, 0); rareTxt.x = 0; rareTxt.y = 130; icon.addChild(rareTxt); // Show count if more than 1 if (itemCount > 1) { var countTxt = new Text2("x" + itemCount, { size: 40, fill: 0xFFE066 }); countTxt.anchor.set(1, 1); countTxt.x = 90; countTxt.y = 90; icon.addChild(countTxt); } inventoryOverlay.addChild(icon); inventoryIcons.push(icon); } } // Inventory button handlers inventoryBtn.down = function (x, y, obj) { inventoryBg.scaleX = 0.95; inventoryBg.scaleY = 0.95; }; inventoryBtn.up = function (x, y, obj) { inventoryBg.scaleX = 1; inventoryBg.scaleY = 1; if (rolling) return; showCollection = false; collectionOverlay.visible = false; inventoryOverlay.visible = true; updateInventoryGrid(); // Hide main UI elements when inventory is open titleTxt.visible = false; rarityTxt.visible = false; itemDisplay.visible = false; itemNameTxt.visible = false; rollBtn.visible = false; showCollBtn.visible = false; inventoryBtn.visible = false; craftBtn.visible = false; }; // Inventory back button handlers invBackBtn.down = function (x, y, obj) { invBackBg.scaleX = 0.95; invBackBg.scaleY = 0.95; }; invBackBtn.up = function (x, y, obj) { invBackBg.scaleX = 1; invBackBg.scaleY = 1; inventoryOverlay.visible = false; // Restore main UI elements when leaving inventory titleTxt.visible = true; rarityTxt.visible = true; itemDisplay.visible = true; itemNameTxt.visible = true; rollBtn.visible = true; showCollBtn.visible = true; inventoryBtn.visible = true; craftBtn.visible = true; }; // --- Initial State --- updateMainDisplay(); collectionOverlay.visible = false; // --- Level bar initial state --- rollsThisLevel = 0; level = 1; levelLuckMultiplier = 1; levelBarFg.width = 0; levelBarLabel.setText("Level 1 (0/50) Luck x1"); // --- GUI Layout --- titleTxt.x = 2048 / 2; titleTxt.y = 40; rarityTxt.x = 2048 / 2; rarityTxt.y = 200; // --- Touch Handling (prevent drag) --- game.move = function (x, y, obj) {}; game.down = function (x, y, obj) {}; game.up = function (x, y, obj) {}; // --- Game Update --- game.update = function () { // Update luck event timer bar if active if (luckEventActive && luckEventTimerBar && luckEventTimerBar.visible) { var now = Date.now(); var total = 20000; var left = Math.max(0, luckEventEndTime - now); var frac = left / total; luckEventTimerBar.fg.width = 600 * frac; if (left <= 0) { endLuckEvent(); } } };
===================================================================
--- original.js
+++ change.js
@@ -215,47 +215,8 @@
id: 15,
name: "Spark",
rarity: 28000,
asset: 'item_spark'
-}, {
- id: 16,
- name: "Lucky Spark",
- rarity: 0,
- // Crafted only, not rollable
- asset: 'item_luckyspark',
- recipe: {
- ingredients: [{
- id: 15,
- name: "Spark"
- }, {
- id: 0,
- name: "Water"
- }, {
- id: 7,
- name: "Sand"
- }],
- bonus: "+1% base chance increase for rolling Uncommon or higher"
- }
-},
-// New craft item: Beginner's Fortune
-{
- id: 17,
- name: "Beginner's Fortune",
- rarity: 0,
- asset: 'item_fortune',
- recipe: {
- ingredients: [{
- id: 5,
- name: "Moss"
- }, {
- id: 3,
- name: "Breeze"
- }, {
- id: 2,
- name: "Flame"
- }],
- bonus: "First roll of each day has +5% better odds"
- }
}];
// --- Luck Event State ---
var luckEventActive = false; // true if a luck event is active
var luckEventMultiplier = 1; // 1 (normal), 10, or 25
@@ -487,13 +448,53 @@
// Place craft button under inventory button
craftBtn.x = 2048 / 2;
craftBtn.y = inventoryBtn.y + 170;
game.addChild(craftBtn);
-// --- Crafting Overlay ---
-var craftingOverlay = new Container();
-craftingOverlay.visible = false;
-game.addChild(craftingOverlay);
-// "Back" button for crafting
+// --- Crafting Recipes ---
+var CRAFT_RECIPES = [{
+ id: 0,
+ name: "Lucky Pebble",
+ asset: "craft_luckypebble",
+ ingredients: [{
+ id: 15,
+ count: 1
+ },
+ // Spark
+ {
+ id: 7,
+ count: 1
+ } // Sand
+ ],
+ effect: "luckx2"
+}];
+// --- Craft Overlay ---
+var craftOverlay = new Container();
+craftOverlay.visible = false;
+game.addChild(craftOverlay);
+// Craft result display
+var craftResultDisplay = new ItemDisplay();
+craftResultDisplay.x = 2048 / 2;
+craftResultDisplay.y = 900;
+craftOverlay.addChild(craftResultDisplay);
+var craftResultNameTxt = new Text2("", {
+ size: 90,
+ fill: "#fff"
+});
+craftResultNameTxt.anchor.set(0.5, 0);
+craftResultNameTxt.x = 2048 / 2;
+craftResultNameTxt.y = craftResultDisplay.y + 220;
+craftOverlay.addChild(craftResultNameTxt);
+var craftDescTxt = new Text2("", {
+ size: 60,
+ fill: 0xFFE066
+});
+craftDescTxt.anchor.set(0.5, 0);
+craftDescTxt.x = 2048 / 2;
+craftDescTxt.y = craftResultNameTxt.y + 120;
+craftOverlay.addChild(craftDescTxt);
+// Craft ingredient icons
+var craftIngredientIcons = [];
+// Craft "Back" button
var craftBackBtn = new Container();
var craftBackBg = craftBackBtn.attachAsset('roll_btn', {
anchorX: 0.5,
anchorY: 0.5,
@@ -508,121 +509,85 @@
craftBackLabel.anchor.set(0.5, 0.5);
craftBackBtn.addChild(craftBackLabel);
craftBackBtn.x = 2048 / 2;
craftBackBtn.y = 2500;
-craftingOverlay.addChild(craftBackBtn);
-// Lucky Spark recipe UI
-var luckySparkDef = getItemDef(16);
-var luckySparkIcon = new CollectionIcon();
-luckySparkIcon.setItem(luckySparkDef, true);
-luckySparkIcon.x = 2048 / 2;
-luckySparkIcon.y = 700;
-craftingOverlay.addChild(luckySparkIcon);
-var luckySparkName = new Text2("Lucky Spark", {
- size: 60,
- fill: "#fff"
-});
-luckySparkName.anchor.set(0.5, 0);
-luckySparkName.x = 2048 / 2;
-luckySparkName.y = 900;
-craftingOverlay.addChild(luckySparkName);
-var luckySparkRecipe = new Text2("Recipe: Spark + Water + Sand", {
- size: 44,
- fill: "#fff"
-});
-luckySparkRecipe.anchor.set(0.5, 0);
-luckySparkRecipe.x = 2048 / 2;
-luckySparkRecipe.y = 980;
-craftingOverlay.addChild(luckySparkRecipe);
-var luckySparkBonus = new Text2("+1% base chance for Uncommon or higher", {
- size: 40,
- fill: 0xFFE066
-});
-luckySparkBonus.anchor.set(0.5, 0);
-luckySparkBonus.x = 2048 / 2;
-luckySparkBonus.y = 1050;
-craftingOverlay.addChild(luckySparkBonus);
-// Craft button for Lucky Spark
-var luckySparkCraftBtn = new Container();
-var luckySparkCraftBg = luckySparkCraftBtn.attachAsset('roll_btn', {
+craftOverlay.addChild(craftBackBtn);
+// Craft "Make" button
+var craftMakeBtn = new Container();
+var craftMakeBg = craftMakeBtn.attachAsset('roll_btn', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 0.6,
- scaleY: 0.6
+ scaleX: 0.7,
+ scaleY: 0.7
});
-luckySparkCraftBg.alpha = 1;
-var luckySparkCraftLabel = new Text2("CRAFT", {
+craftMakeBg.alpha = 1;
+var craftMakeLabel = new Text2("MAKE", {
size: 48,
fill: "#fff"
});
-luckySparkCraftLabel.anchor.set(0.5, 0.5);
-luckySparkCraftBtn.addChild(luckySparkCraftLabel);
-luckySparkCraftBtn.x = 2048 / 2;
-luckySparkCraftBtn.y = 1200;
-craftingOverlay.addChild(luckySparkCraftBtn);
-// Beginner's Fortune recipe UI
-var fortuneDef = getItemDef(17);
-var fortuneIcon = new CollectionIcon();
-fortuneIcon.setItem(fortuneDef, true);
-fortuneIcon.x = 2048 / 2;
-fortuneIcon.y = 1400;
-craftingOverlay.addChild(fortuneIcon);
-var fortuneName = new Text2("Beginner's Fortune", {
- size: 60,
- fill: "#fff"
-});
-fortuneName.anchor.set(0.5, 0);
-fortuneName.x = 2048 / 2;
-fortuneName.y = 1600;
-craftingOverlay.addChild(fortuneName);
-var fortuneRecipe = new Text2("Recipe: Moss + Breeze + Flame", {
- size: 44,
- fill: "#fff"
-});
-fortuneRecipe.anchor.set(0.5, 0);
-fortuneRecipe.x = 2048 / 2;
-fortuneRecipe.y = 1680;
-craftingOverlay.addChild(fortuneRecipe);
-var fortuneBonus = new Text2("First roll of each day: +5% odds", {
- size: 40,
- fill: 0xFFE066
-});
-fortuneBonus.anchor.set(0.5, 0);
-fortuneBonus.x = 2048 / 2;
-fortuneBonus.y = 1750;
-craftingOverlay.addChild(fortuneBonus);
-// Craft button for Beginner's Fortune
-var fortuneCraftBtn = new Container();
-var fortuneCraftBg = fortuneCraftBtn.attachAsset('roll_btn', {
- anchorX: 0.5,
- anchorY: 0.5,
- scaleX: 0.6,
- scaleY: 0.6
-});
-fortuneCraftBg.alpha = 1;
-var fortuneCraftLabel = new Text2("CRAFT", {
- size: 48,
- fill: "#fff"
-});
-fortuneCraftLabel.anchor.set(0.5, 0.5);
-fortuneCraftBtn.addChild(fortuneCraftLabel);
-fortuneCraftBtn.x = 2048 / 2;
-fortuneCraftBtn.y = 1900;
-craftingOverlay.addChild(fortuneCraftBtn);
-// Crafting state
-var hasLuckySpark = false;
-var hasFortune = false;
+craftMakeLabel.anchor.set(0.5, 0.5);
+craftMakeBtn.addChild(craftMakeLabel);
+craftMakeBtn.x = 2048 / 2;
+craftMakeBtn.y = craftBackBtn.y - 200;
+craftOverlay.addChild(craftMakeBtn);
+// Helper: update craft overlay for Lucky Pebble
+function updateCraftOverlay() {
+ // Only one recipe for now
+ var recipe = CRAFT_RECIPES[0];
+ // Show result
+ craftResultDisplay.setItem({
+ asset: recipe.asset
+ });
+ craftResultNameTxt.setText(recipe.name);
+ craftDescTxt.setText("2x luck multiplier for rarest item (until next roll)");
+ // Remove old ingredient icons
+ for (var i = 0; i < craftIngredientIcons.length; ++i) {
+ craftOverlay.removeChild(craftIngredientIcons[i]);
+ }
+ craftIngredientIcons = [];
+ // Layout: horizontally centered
+ var spacing = 320;
+ var startX = 2048 / 2 - (recipe.ingredients.length - 1) * spacing / 2;
+ var y = craftResultDisplay.y + 400;
+ for (var i = 0; i < recipe.ingredients.length; ++i) {
+ var ing = recipe.ingredients[i];
+ var itemDef = getItemDef(ing.id);
+ var icon = new CollectionIcon();
+ icon.setItem(itemDef, true);
+ icon.x = startX + i * spacing;
+ icon.y = y;
+ // Show count
+ var haveCount = 0;
+ for (var j = 0; j < inventory.length; ++j) {
+ if (inventory[j].id === ing.id) {
+ haveCount = inventory[j].count;
+ break;
+ }
+ }
+ var countTxt = new Text2(haveCount + " / " + ing.count, {
+ size: 40,
+ fill: haveCount >= ing.count ? "#fff" : "#f44"
+ });
+ countTxt.anchor.set(0.5, 0);
+ countTxt.x = 0;
+ countTxt.y = 90;
+ icon.addChild(countTxt);
+ craftOverlay.addChild(icon);
+ craftIngredientIcons.push(icon);
+ }
+}
// Craft button handlers
craftBtn.down = function (x, y, obj) {
craftBg.scaleX = 0.95;
craftBg.scaleY = 0.95;
};
craftBtn.up = function (x, y, obj) {
craftBg.scaleX = 1;
craftBg.scaleY = 1;
- if (rolling || showCollection || craftingOverlay.visible) return;
- // Show crafting overlay
- craftingOverlay.visible = true;
+ if (rolling || showCollection || inventoryOverlay.visible) return;
+ // Show craft overlay
+ craftOverlay.visible = true;
+ updateCraftOverlay();
// Hide main UI elements
titleTxt.visible = false;
rarityTxt.visible = false;
itemDisplay.visible = false;
@@ -631,17 +596,17 @@
showCollBtn.visible = false;
inventoryBtn.visible = false;
craftBtn.visible = false;
};
-// Crafting back button handlers
+// Craft overlay back button
craftBackBtn.down = function (x, y, obj) {
craftBackBg.scaleX = 0.95;
craftBackBg.scaleY = 0.95;
};
craftBackBtn.up = function (x, y, obj) {
craftBackBg.scaleX = 1;
craftBackBg.scaleY = 1;
- craftingOverlay.visible = false;
+ craftOverlay.visible = false;
// Restore main UI elements
titleTxt.visible = true;
rarityTxt.visible = true;
itemDisplay.visible = true;
@@ -650,124 +615,75 @@
showCollBtn.visible = true;
inventoryBtn.visible = true;
craftBtn.visible = true;
};
-// Helper: check if player has enough ingredients for Lucky Spark
-function canCraftLuckySpark() {
- var needed = [15, 0, 7]; // Spark, Water, Sand
- var counts = {};
- for (var i = 0; i < needed.length; ++i) counts[needed[i]] = 0;
- for (var i = 0; i < inventory.length; ++i) {
- var id = inventory[i].id;
- if (counts.hasOwnProperty(id)) counts[id] = inventory[i].count;
- }
- return counts[15] >= 1 && counts[0] >= 1 && counts[7] >= 1;
-}
-// Helper: check if player has enough ingredients for Beginner's Fortune
-function canCraftFortune() {
- var needed = [5, 3, 2]; // Moss, Breeze, Flame
- var counts = {};
- for (var i = 0; i < needed.length; ++i) counts[needed[i]] = 0;
- for (var i = 0; i < inventory.length; ++i) {
- var id = inventory[i].id;
- if (counts.hasOwnProperty(id)) counts[id] = inventory[i].count;
- }
- return counts[5] >= 1 && counts[3] >= 1 && counts[2] >= 1;
-}
-// Craft Lucky Spark handler
-luckySparkCraftBtn.down = function (x, y, obj) {
- luckySparkCraftBg.scaleX = 0.95;
- luckySparkCraftBg.scaleY = 0.95;
+// Craft "Make" button logic
+craftMakeBtn.down = function (x, y, obj) {
+ craftMakeBg.scaleX = 0.95;
+ craftMakeBg.scaleY = 0.95;
};
-luckySparkCraftBtn.up = function (x, y, obj) {
- luckySparkCraftBg.scaleX = 1;
- luckySparkCraftBg.scaleY = 1;
- if (!canCraftLuckySpark()) return;
- // Remove 1 Spark, 1 Water, 1 Sand from inventory
- var needed = [15, 0, 7];
- for (var i = 0; i < needed.length; ++i) {
+craftMakeBtn.up = function (x, y, obj) {
+ craftMakeBg.scaleX = 1;
+ craftMakeBg.scaleY = 1;
+ // Only one recipe for now
+ var recipe = CRAFT_RECIPES[0];
+ // Check if player has all ingredients
+ var canCraft = true;
+ for (var i = 0; i < recipe.ingredients.length; ++i) {
+ var ing = recipe.ingredients[i];
+ var haveCount = 0;
for (var j = 0; j < inventory.length; ++j) {
- if (inventory[j].id === needed[i] && inventory[j].count > 0) {
- inventory[j].count -= 1;
- if (inventory[j].count === 0) {
- inventory.splice(j, 1);
- }
+ if (inventory[j].id === ing.id) {
+ haveCount = inventory[j].count;
break;
}
}
- }
- // Add Lucky Spark to inventory (if not already present, else +1)
- var found = false;
- for (var i = 0; i < inventory.length; ++i) {
- if (inventory[i].id === 16) {
- inventory[i].count += 1;
- found = true;
+ if (haveCount < ing.count) {
+ canCraft = false;
break;
}
}
- if (!found) {
- inventory.push({
- id: 16,
- count: 1
- });
+ if (!canCraft) {
+ // Flash ingredients red
+ for (var i = 0; i < craftIngredientIcons.length; ++i) {
+ LK.effects.flashObject(craftIngredientIcons[i], 0xff4444, 400);
+ }
+ return;
}
- hasLuckySpark = true;
- // Show a quick flash or feedback
- LK.effects.flashObject(luckySparkIcon, 0xffe066, 600);
- // Optionally update inventory grid if open
- if (inventoryOverlay.visible) updateInventoryGrid();
-};
-// Craft Beginner's Fortune handler
-fortuneCraftBtn.down = function (x, y, obj) {
- fortuneCraftBg.scaleX = 0.95;
- fortuneCraftBg.scaleY = 0.95;
-};
-fortuneCraftBtn.up = function (x, y, obj) {
- fortuneCraftBg.scaleX = 1;
- fortuneCraftBg.scaleY = 1;
- if (!canCraftFortune()) return;
- // Remove 1 Moss, 1 Breeze, 1 Flame from inventory
- var needed = [5, 3, 2];
- for (var i = 0; i < needed.length; ++i) {
+ // Remove ingredients from inventory
+ for (var i = 0; i < recipe.ingredients.length; ++i) {
+ var ing = recipe.ingredients[i];
for (var j = 0; j < inventory.length; ++j) {
- if (inventory[j].id === needed[i] && inventory[j].count > 0) {
- inventory[j].count -= 1;
- if (inventory[j].count === 0) {
+ if (inventory[j].id === ing.id) {
+ inventory[j].count -= ing.count;
+ if (inventory[j].count <= 0) {
inventory.splice(j, 1);
}
break;
}
}
}
- // Add Beginner's Fortune to inventory (if not already present, else +1)
- var found = false;
- for (var i = 0; i < inventory.length; ++i) {
- if (inventory[i].id === 17) {
- inventory[i].count += 1;
- found = true;
- break;
- }
- }
- if (!found) {
- inventory.push({
- id: 17,
- count: 1
- });
- }
- hasFortune = true;
- // Show a quick flash or feedback
- LK.effects.flashObject(fortuneIcon, 0xffe066, 600);
- // Optionally update inventory grid if open
- if (inventoryOverlay.visible) updateInventoryGrid();
+ // Apply effect: 2x luck multiplier for rarest item (until next roll)
+ levelLuckMultiplier *= 2;
+ // Flash level bar to indicate effect
+ LK.effects.flashObject(levelBarFg, 0x44ff66, 800);
+ // Show confirmation
+ craftDescTxt.setText("2x luck! Next roll is boosted.");
+ // Hide craft overlay after short delay and restore UI
+ LK.setTimeout(function () {
+ craftOverlay.visible = false;
+ titleTxt.visible = true;
+ rarityTxt.visible = true;
+ itemDisplay.visible = true;
+ itemNameTxt.visible = true;
+ rollBtn.visible = true;
+ showCollBtn.visible = true;
+ inventoryBtn.visible = true;
+ craftBtn.visible = true;
+ }, 1200);
+ updateInventoryGrid && updateInventoryGrid();
+ updateCraftOverlay();
};
-// --- Apply Lucky Spark bonus to rolling ---
-var luckySparkBonusActive = false;
-function hasLuckySparkInInventory() {
- for (var i = 0; i < inventory.length; ++i) {
- if (inventory[i].id === 16 && inventory[i].count > 0) return true;
- }
- return false;
-}
// Collection view overlay
var collectionOverlay = new Container();
collectionOverlay.visible = false;
game.addChild(collectionOverlay);
@@ -799,17 +715,15 @@
var perRow = 3;
var spacing = 320;
var startX = 2048 / 2 - spacing;
var startY = 600;
- for (var i = 0, shown = 0; i < ITEM_DEFS.length; ++i) {
+ for (var i = 0; i < ITEM_DEFS.length; ++i) {
var item = ITEM_DEFS[i];
- // Hide crafted items (those with a recipe property)
- if (item.recipe) continue;
var owned = collection.indexOf(item.id) !== -1;
var icon = new CollectionIcon();
icon.setItem(item, owned);
- icon.x = startX + shown % perRow * spacing;
- icon.y = startY + Math.floor(shown / perRow) * spacing;
+ icon.x = startX + i % perRow * spacing;
+ icon.y = startY + Math.floor(i / perRow) * spacing;
// Name and rarity
var nameTxt = new Text2(item.name, {
size: 36,
fill: "#fff"
@@ -827,9 +741,8 @@
rareTxt.y = 130;
icon.addChild(rareTxt);
collectionOverlay.addChild(icon);
collectionIcons.push(icon);
- shown++;
}
}
// --- Functions ---
function updateMainDisplay() {
@@ -843,85 +756,30 @@
itemNameTxt.setText(itemDef.name);
}
function rollForItem() {
// Weighted random roll, apply luck event and level multipliers
- // Apply Lucky Spark bonus: +1% base chance for Uncommon or higher (rarity >= 20)
- var luckySparkBonusActive = hasLuckySparkInInventory();
- // --- Beginner's Fortune: First roll of each day +5% odds ---
- var now = new Date();
- var todayKey = now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate();
- if (typeof rollForItem._lastRollDay === "undefined") rollForItem._lastRollDay = null;
- if (typeof rollForItem._firstRollToday === "undefined") rollForItem._firstRollToday = true;
- if (rollForItem._lastRollDay !== todayKey) {
- rollForItem._firstRollToday = true;
- rollForItem._lastRollDay = todayKey;
- }
- // Helper: do we have Beginner's Fortune in inventory?
- function hasFortuneInInventory() {
- for (var i = 0; i < inventory.length; ++i) {
- if (inventory[i].id === 17 && inventory[i].count > 0) return true;
- }
- return false;
- }
- var fortuneBonusActive = hasFortuneInInventory() && rollForItem._firstRollToday;
var totalWeight = 0;
for (var i = 0; i < ITEM_DEFS.length; ++i) {
- // Exclude craft items (those with a recipe property) from being rolled
- if (ITEM_DEFS[i].recipe) continue;
var rarity = ITEM_DEFS[i].rarity;
// Apply multiplier: only to rarest item (lowest odds, highest rarity)
var effectiveRarity = rarity;
if (i === ITEM_DEFS.length - 1) {
effectiveRarity = Math.max(1, Math.floor(rarity / (levelLuckMultiplier * luckEventMultiplier)));
}
- // Lucky Spark bonus: +1% base chance for Uncommon or higher (rarity >= 20)
- var weight = 1 / effectiveRarity;
- if (luckySparkBonusActive && rarity >= 20 && rarity > 0) {
- // Add 0.01 to the weight (1% base chance)
- weight += 0.01;
- }
- // Beginner's Fortune bonus: +5% odds for first roll of the day
- if (fortuneBonusActive) {
- weight *= 1.05;
- }
- totalWeight += weight;
+ totalWeight += 1 / effectiveRarity;
}
var r = Math.random() * totalWeight;
var acc = 0;
for (var i = 0; i < ITEM_DEFS.length; ++i) {
- // Exclude craft items (those with a recipe property) from being rolled
- if (ITEM_DEFS[i].recipe) continue;
var rarity = ITEM_DEFS[i].rarity;
var effectiveRarity = rarity;
if (i === ITEM_DEFS.length - 1) {
effectiveRarity = Math.max(1, Math.floor(rarity / (levelLuckMultiplier * luckEventMultiplier)));
}
- var weight = 1 / effectiveRarity;
- if (luckySparkBonusActive && rarity >= 20 && rarity > 0) {
- weight += 0.01;
- }
- if (fortuneBonusActive) {
- weight *= 1.05;
- }
- acc += weight;
- if (r <= acc) {
- // Mark that first roll of the day is done if using Beginner's Fortune
- if (fortuneBonusActive) {
- rollForItem._firstRollToday = false;
- }
- return ITEM_DEFS[i].id;
- }
+ acc += 1 / effectiveRarity;
+ if (r <= acc) return ITEM_DEFS[i].id;
}
- // Fallback: return the rarest non-craft item
- for (var i = ITEM_DEFS.length - 1; i >= 0; --i) {
- if (!ITEM_DEFS[i].recipe) {
- if (fortuneBonusActive) {
- rollForItem._firstRollToday = false;
- }
- return ITEM_DEFS[i].id;
- }
- }
- return ITEM_DEFS[0].id;
+ return ITEM_DEFS[ITEM_DEFS.length - 1].id;
}
function animateRoll(resultId) {
rolling = true;
// Flash through random items, then land on result
Water. In-Game asset. 2d. High contrast. No shadows
Stone. In-Game asset. 2d. High contrast. No shadows
Flame. In-Game asset. 2d. High contrast. No shadows
Breeze. In-Game asset. 2d. High contrast. No shadows
Ember. In-Game asset. 2d. High contrast. No shadows
light green moss. In-Game asset. 2d. High contrast. No shadows
Crystal. In-Game asset. 2d. High contrast. No shadows
sand. In-Game asset. 2d. High contrast. No shadows
Gray ash. In-Game asset. 2d. High contrast. No shadows
Iron bar. In-Game asset. 2d. High contrast. No shadows
Rectangular button. In-Game asset. 2d. High contrast. No shadows
Quartz. In-Game asset. 2d. High contrast. No shadows
smoke. In-Game asset. 2d. High contrast. No shadows
Frozen human. In-Game asset. 2d. High contrast. No shadows
Thunder. In-Game asset. 2d. High contrast. No shadows
Vine. In-Game asset. 2d. High contrast. No shadows
spark. In-Game asset. 2d. High contrast. No shadows
lucky pebble. In-Game asset. 2d. High contrast. No shadows
Fortune Leaf. In-Game asset. 2d. High contrast. No shadows