Code edit (15 edits merged)
Please save this source code
User prompt
Agrega un asset de sonido al momento de obtener un personaje y otro al momento de obtener 10, no modifiques la estrcutura lógica
Code edit (7 edits merged)
Please save this source code
User prompt
Agrega música que suene constantemente en bucle
Code edit (1 edits merged)
Please save this source code
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
/**** * Classes ****/
var Character = Container.expand(function () {
var self = Container.call(this);
self.init = function (elementId, elementName, rarity, assetId, multiplier) {
// Mapa de colores por rareza
var rarityColorsHex = {
'Common': 0xFFFFFF,
'Uncommon': 0x00FF00,
'Rare': 0x00BFFF,
'Ultra-Rare': 0x8A2BE2,
'Special': 0xFF1493,
'Legendary': 0xFFD700,
'Unique': 0xFF0000
};
var rColor = rarityColorsHex[rarity] || 0xffffff;
// 1. El Marco (Aura de fondo)
var frame = self.attachAsset('bg_character', {
anchorX: 0.5,
anchorY: 0.55
});
frame.scale.set(0.75, 1);
frame.tint = rColor;
frame.alpha = 0.6; // Resplandor sutil
// 2. El Gráfico del Personaje
var graphic = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
graphic.scale.set(0.5, 0.5);
// 3. El Nombre
var nameText = new Text2(elementName, {
size: 50,
fill: '#ffffff'
});
nameText.anchor.set(0.5, 0);
nameText.y = 130;
self.addChild(nameText);
// 4. La Rareza (Ahora obtiene el color automáticamente)
var rarityText = new Text2('[' + rarity + ']', {
size: 45,
fill: rColor
});
rarityText.anchor.set(0.5, 0);
rarityText.y = 170;
self.addChild(rarityText);
// Guardamos referencias para modificarlas fácilmente en la galería
self.frameObj = frame;
self.graphicObj = graphic;
self.nameObj = nameText;
self.rarityObj = rarityText;
};
return self;
});
var FloatingText = Container.expand(function () {
var self = Container.call(this);
self.init = function (textValue, startX, startY, color) {
self.x = startX;
self.y = startY;
var txt = new Text2(textValue, {
size: 48,
fill: color || '#ffffff'
});
txt.anchor.set(0.5, 0.5);
self.addChild(txt);
tween(self, {
y: self.y - 150,
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
// Clases de UI: Income Level (AHORA MÁS GRANDE)
var IncomeLevel = Container.expand(function () {
var self = Container.call(this);
self.levelIndex = 0;
self.baseIncome = 0;
self.baseCost = 0;
self.currentCost = 0;
self.init = function (levelIndex, baseIncome) {
self.levelIndex = levelIndex;
self.baseIncome = baseIncome;
self.baseCost = 50 * (levelIndex + 1);
var bg = self.attachAsset('upgrade_button', {
anchorX: 0.5,
anchorY: 0.5
});
// Escala aumentada de 1.5 a 2.0
bg.scale.set(2.0, 2.0);
// Textos aumentados y reposicionados
var levelText = new Text2('', {
size: 38,
fill: '#ffffff'
});
levelText.anchor.set(0.5, 0.5);
levelText.y = -25;
self.addChild(levelText);
self.levelText = levelText;
var costText = new Text2('', {
size: 30,
fill: '#ffffff'
});
costText.anchor.set(0.5, 0.5);
costText.y = 25;
self.addChild(costText);
self.costText = costText;
};
self.updateData = function (purchases) {
self.currentCost = Math.floor(self.baseCost * Math.pow(1.5, purchases));
self.costText.setText('Cost: ' + self.currentCost);
self.levelText.setText('Lvl ' + (self.levelIndex + 1) + ' (x' + purchases + '): +' + self.baseIncome + '/t');
};
return self;
});
/****
* Initialize Game
****/
/**** * Initialize Game ****/
var game = new LK.Game({
backgroundColor: 0x6f6fdb
});
/****
* Game Code
****/
/**** * Plugins ****/
/**** * Game Code ****/
var GAME_CONFIG = {
BASE_GACHA_COST: 1000,
GACHA_COST_MULTIPLIER: 1.10,
FPS: 60,
SAVE_INTERVAL: 300,
MAX_EQUIPPED: 6,
ORBIT_RADIUS: 400,
ORBIT_SPEED: 0.008
};
var characterDatabase = [{
id: 0,
name: 'Fire',
rarity: 'Common',
asset: 'fire_common',
multiplier: 2
}, {
id: 1,
name: 'Water',
rarity: 'Common',
asset: 'water_common',
multiplier: 2
}, {
id: 2,
name: 'Earth',
rarity: 'Common',
asset: 'earth_common',
multiplier: 2
}, {
id: 3,
name: 'Wind',
rarity: 'Common',
asset: 'wind_common',
multiplier: 2
}, {
id: 4,
name: 'Lightning',
rarity: 'Uncommon',
asset: 'lightning_uncommon',
multiplier: 3
}, {
id: 5,
name: 'Ice',
rarity: 'Uncommon',
asset: 'ice_uncommon',
multiplier: 3
}, {
id: 6,
name: 'Nature',
rarity: 'Uncommon',
asset: 'nature_uncommon',
multiplier: 3
}, {
id: 7,
name: 'Metal',
rarity: 'Uncommon',
asset: 'metal_uncommon',
multiplier: 3
}, {
id: 8,
name: 'Sand',
rarity: 'Uncommon',
asset: 'sand_uncommon',
multiplier: 3
}, {
id: 9,
name: 'Steam',
rarity: 'Uncommon',
asset: 'steam_uncommon',
multiplier: 3
}, {
id: 10,
name: 'Magma',
rarity: 'Rare',
asset: 'magma_rare',
multiplier: 4
}, {
id: 11,
name: 'Frost',
rarity: 'Rare',
asset: 'frost_rare',
multiplier: 4
}, {
id: 12,
name: 'Crystal',
rarity: 'Rare',
asset: 'crystal_rare',
multiplier: 4
}, {
id: 13,
name: 'Storm',
rarity: 'Rare',
asset: 'storm_rare',
multiplier: 4
}, {
id: 14,
name: 'Coral',
rarity: 'Rare',
asset: 'coral_rare',
multiplier: 4
}, {
id: 15,
name: 'Forest',
rarity: 'Rare',
asset: 'forest_rare',
multiplier: 4
}, {
id: 16,
name: 'Shadow',
rarity: 'Rare',
asset: 'shadow_rare',
multiplier: 4
}, {
id: 17,
name: 'Plasma',
rarity: 'Ultra-Rare',
asset: 'plasma_ultra',
multiplier: 5
}, {
id: 18,
name: 'Abyss',
rarity: 'Ultra-Rare',
asset: 'abyss_ultra',
multiplier: 5
}, {
id: 19,
name: 'Aurora',
rarity: 'Ultra-Rare',
asset: 'aurora_ultra',
multiplier: 5
}, {
id: 20,
name: 'Inferno',
rarity: 'Ultra-Rare',
asset: 'inferno_ultra',
multiplier: 5
}, {
id: 21,
name: 'Glacier',
rarity: 'Ultra-Rare',
asset: 'glacier_ultra',
multiplier: 5
}, {
id: 22,
name: 'Mirage',
rarity: 'Ultra-Rare',
asset: 'mirage_ultra',
multiplier: 5
}, {
id: 23,
name: 'Celestial',
rarity: 'Legendary',
asset: 'celestial_legendary',
multiplier: 7
}, {
id: 24,
name: 'Cosmic',
rarity: 'Legendary',
asset: 'cosmic_legendary',
multiplier: 7
}, {
id: 25,
name: 'Void',
rarity: 'Legendary',
asset: 'void_legendary',
multiplier: 7
}, {
id: 26,
name: 'Radiance',
rarity: 'Legendary',
asset: 'radiance_legendary',
multiplier: 7
}, {
id: 27,
name: 'Eclipse',
rarity: 'Legendary',
asset: 'eclipse_legendary',
multiplier: 7
}, {
id: 28,
name: 'Genesis',
rarity: 'Unique',
asset: 'genesis_unique',
multiplier: 10
}, {
id: 29,
name: 'Apocalypse',
rarity: 'Unique',
asset: 'apocalypse_unique',
multiplier: 10
}, {
id: 30,
name: 'Paradox',
rarity: 'Unique',
asset: 'paradox_unique',
multiplier: 10
}, {
id: 31,
name: 'Nova',
rarity: 'Special',
asset: 'nova_special',
multiplier: 6
}, {
id: 32,
name: 'Nebula',
rarity: 'Special',
asset: 'nebula_special',
multiplier: 6
}, {
id: 33,
name: 'Titan',
rarity: 'Special',
asset: 'titan_special',
multiplier: 6
}, {
id: 34,
name: 'Phantom',
rarity: 'Special',
asset: 'phantom_special',
multiplier: 6
}, {
id: 35,
name: 'Sphinx',
rarity: 'Special',
asset: 'sphinx_special',
multiplier: 6
}, {
id: 36,
name: 'Oracle',
rarity: 'Special',
asset: 'oracle_special',
multiplier: 6
}, {
id: 37,
name: 'Dust',
rarity: 'Uncommon',
asset: 'dust_uncommon',
multiplier: 3
}, {
id: 38,
name: 'Spore',
rarity: 'Uncommon',
asset: 'spore_uncommon',
multiplier: 3
}, {
id: 39,
name: 'Tectonic',
rarity: 'Rare',
asset: 'tectonic_rare',
multiplier: 4
}, {
id: 40,
name: 'Biosphere',
rarity: 'Ultra-Rare',
asset: 'biosphere_ultra',
multiplier: 5
}, {
id: 41,
name: 'Pulsar',
rarity: 'Special',
asset: 'pulsar_special',
multiplier: 6
}, {
id: 42,
name: 'Antimatter',
rarity: 'Legendary',
asset: 'antimatter_legendary',
multiplier: 7
}, {
id: 43,
name: 'Singularity',
rarity: 'Legendary',
asset: 'singularity_legendary',
multiplier: 7
}, {
id: 44,
name: 'Entropy',
rarity: 'Unique',
asset: 'entropy_unique',
multiplier: 10
}];
var dropRates = [{
rarity: 'Common',
chance: 45,
ids: [0, 1, 2, 3]
}, {
rarity: 'Uncommon',
chance: 20,
ids: [4, 5, 6, 7, 8, 9, 37, 38]
}, {
rarity: 'Rare',
chance: 15,
ids: [10, 11, 12, 13, 14, 15, 16, 39]
}, {
rarity: 'Ultra-Rare',
chance: 10,
ids: [17, 18, 19, 20, 21, 22, 40]
}, {
rarity: 'Special',
chance: 6,
ids: [31, 32, 33, 34, 35, 36, 41]
}, {
rarity: 'Legendary',
chance: 3,
ids: [23, 24, 25, 26, 27, 42, 43]
}, {
rarity: 'Unique',
chance: 1,
ids: [28, 29, 30, 44]
}];
var galleryDisplayOrder = [0, 1, 2, 3,
// Common
4, 5, 6, 7, 8, 9, 37, 38,
// Uncommon
10, 11, 12, 13, 14, 15, 16, 39,
// Rare
17, 18, 19, 20, 21, 22, 40,
// Ultra-Rare
31, 32, 33, 34, 35, 36, 41,
// Special
23, 24, 25, 26, 27, 42, 43,
// Legendary
28, 29, 30, 44 // Unique
];
var gameState = {
credits: 0,
incomePerTick: 1,
collectedCharacters: {},
totalCharactersCollected: 0,
incomeLevels: [],
tickCounter: 0,
equippedCharacters: [],
pityCounter: 0 // Contador de Lástima
};
// Estado temporal para controlar la vista de la galería
var galleryState = {
currentPage: 0,
itemsPerPage: 9,
// Cuadrícula de 3x3
selectedElementId: 0
};
// --- Funciones Base de Estado ---
function getGachaCost() {
return Math.floor(GAME_CONFIG.BASE_GACHA_COST * Math.pow(GAME_CONFIG.GACHA_COST_MULTIPLIER, gameState.totalCharactersCollected));
}
function loadGame() {
gameState.collectedCharacters = {};
gameState.incomeLevels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
gameState.equippedCharacters = [];
if (storage.credits !== undefined) {
gameState.credits = storage.credits;
gameState.incomePerTick = storage.incomePerTick;
gameState.totalCharactersCollected = storage.totalCharactersCollected;
gameState.tickCounter = storage.tickCounter || 0;
gameState.pityCounter = storage.pityCounter || 0;
var collectedIds = (storage.collectedCharacterIds || '').split(',');
for (var i = 0; i < collectedIds.length; i++) {
if (collectedIds[i] !== '') {
gameState.collectedCharacters[parseInt(collectedIds[i])] = true;
}
}
var upgradedLevels = (storage.upgradedLevelCounts || '').split(',');
for (var j = 0; j < upgradedLevels.length; j++) {
if (upgradedLevels[j] !== '') {
gameState.incomeLevels[j] = parseInt(upgradedLevels[j]) || 0;
}
}
var equippedStr = storage.equippedCharactersIds || '';
if (equippedStr !== '') {
var eqSplit = equippedStr.split(',');
for (var k = 0; k < eqSplit.length; k++) {
if (eqSplit[k] !== '') {
gameState.equippedCharacters.push(parseInt(eqSplit[k]));
}
}
}
}
}
function saveGame() {
storage.credits = gameState.credits;
storage.incomePerTick = gameState.incomePerTick;
storage.totalCharactersCollected = gameState.totalCharactersCollected;
storage.tickCounter = gameState.tickCounter;
storage.pityCounter = gameState.pityCounter;
var collectedIds = '';
for (var charId in gameState.collectedCharacters) {
if (gameState.collectedCharacters[charId]) {
collectedIds += charId + ',';
}
}
storage.collectedCharacterIds = collectedIds;
var upgradedLevels = '';
for (var i = 0; i < gameState.incomeLevels.length; i++) {
upgradedLevels += gameState.incomeLevels[i] + ',';
}
storage.upgradedLevelCounts = upgradedLevels;
var equippedIds = '';
for (var e = 0; e < gameState.equippedCharacters.length; e++) {
equippedIds += gameState.equippedCharacters[e] + ',';
}
storage.equippedCharactersIds = equippedIds;
}
loadGame();
// --- UI Construction ---
var creditsText = new Text2('Credits: 0', {
size: 100,
fill: '#FFD700'
});
creditsText.anchor.set(0.5, 0);
creditsText.x = 1024;
creditsText.y = 50;
game.addChild(creditsText);
var incomeText = new Text2('Income: 1/tick', {
size: 80,
fill: '#00FF00'
});
incomeText.anchor.set(0.5, 0);
incomeText.x = 1024;
incomeText.y = 160;
game.addChild(incomeText);
var collectionText = new Text2('Collection: 0/41', {
size: 60,
fill: '#87CEEB'
});
collectionText.anchor.set(0.5, 0);
collectionText.x = 1024;
collectionText.y = 250;
game.addChild(collectionText);
// --- SISTEMA DE ÓRBITA (A LA DERECHA) ---
var orbitContainer = new Container();
orbitContainer.x = 1536; // 3/4 de la pantalla
orbitContainer.y = 1366; // Centro vertical
game.addChild(orbitContainer);
var orbitingSprites = [];
var orbitAngle = 0;
function updateEquippedDisplay() {
while (orbitContainer.children.length > 0) {
orbitContainer.children[0].destroy();
}
orbitingSprites = [];
for (var i = 0; i < gameState.equippedCharacters.length; i++) {
var charId = gameState.equippedCharacters[i];
var charData = characterDatabase[charId];
var sprite = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
sprite.scale.set(0.55, 0.55);
orbitContainer.addChild(sprite);
orbitingSprites.push(sprite);
}
}
updateEquippedDisplay();
// --- Manual Clicker Core (A LA DERECHA) ---
var coreGraphic = LK.getAsset('core_crystal', {
anchorX: 0.5,
anchorY: 0.5
});
var coreButton = new Container();
coreButton.addChild(coreGraphic);
coreButton.x = 1536; // 3/4 de la pantalla
coreButton.y = 1366; // Centro vertical
game.addChild(coreButton);
var coreText = new Text2('TAP', {
size: 50,
fill: '#ffffff'
});
coreText.anchor.set(0.5, 0.5);
coreButton.addChild(coreText);
// --- Botón Gacha Individual (Movido a la Izquierda) ---
var gachaBtnGraphic = LK.getAsset('gacha_button', {
anchorX: 0.5,
anchorY: 0.5
});
gachaBtnGraphic.scale.set(1.6, 1.8);
var gachaButton = new Container();
gachaButton.addChild(gachaBtnGraphic);
gachaButton.x = 600; // Antes 1024
gachaButton.y = 2500;
game.addChild(gachaButton);
var gachaText = new Text2('PULL (' + getGachaCost() + ')', {
size: 55,
fill: '#ffffff'
});
gachaText.anchor.set(0.5, 0.5);
gachaText.y = -20;
gachaButton.addChild(gachaText);
var pityText = new Text2('Pity: 0/10', {
size: 40,
fill: '#FFD700'
});
pityText.anchor.set(0.5, 0.5);
pityText.y = 30;
gachaButton.addChild(pityText);
var gachaEnabled = false;
// --- NUEVO: Botón Gacha x10 (A la Derecha) ---
var gacha10BtnGraphic = LK.getAsset('gacha_button', {
anchorX: 0.5,
anchorY: 0.5
});
gacha10BtnGraphic.scale.set(1.6, 1.8);
var gacha10Button = new Container();
gacha10Button.addChild(gacha10BtnGraphic);
gacha10Button.x = 1448;
gacha10Button.y = 2500;
game.addChild(gacha10Button);
var gacha10Text = new Text2('10x PULL', {
size: 55,
fill: '#ffffff'
});
gacha10Text.anchor.set(0.5, 0.5);
gacha10Text.y = -20;
gacha10Button.addChild(gacha10Text);
var pity10Text = new Text2('1 Guaranteed!', {
size: 40,
fill: '#00FF00'
});
pity10Text.anchor.set(0.5, 0.5);
pity10Text.y = 30;
gacha10Button.addChild(pity10Text);
var gacha10Enabled = false;
// Gallery Button
var galleryBtnGraphic = LK.getAsset('gallery_button', {
anchorX: 0.5,
anchorY: 0.5
});
galleryButton.size(2.0, 2.0);
var galleryButton = new Container();
galleryButton.addChild(galleryBtnGraphic);
galleryButton.x = 1800;
galleryButton.y = 500;
game.addChild(galleryButton);
var galleryText = new Text2('GALLERY', {
size: 50,
fill: '#ffffff'
});
galleryText.anchor.set(0.5, 0.5);
galleryButton.addChild(galleryText);
// Debug Reset Button
/*
var debugBtnGraphic = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
var debugButton = new Container();
debugButton.addChild(debugBtnGraphic);
debugButton.x = 300;
debugButton.y = 100;
game.addChild(debugButton);
var debugText = new Text2('RESET', {
size: 40,
fill: '#ff4444'
});
debugText.anchor.set(0.5, 0.5);
debugButton.addChild(debugText);*/
// Upgrade Levels Container (A LA IZQUIERDA Y MÁS GRANDES)
var levelContainers = [];
var levelStartY = 500; // Empezamos un poco más arriba
var levelSpacing = 180; // Más espacio vertical porque los botones crecieron
for (var i = 0; i < 10; i++) {
var levelContainer = new IncomeLevel();
levelContainer.init(i, [1, 2, 3, 5, 10, 20, 50, 100, 200, 300][i]);
levelContainer.updateData(gameState.incomeLevels[i]);
levelContainer.x = 512; // 1/4 de la pantalla hacia la izquierda
levelContainer.y = levelStartY + i * levelSpacing;
game.addChild(levelContainer);
levelContainers.push(levelContainer);
}
// Modal Variables
var modalOpen = false;
var modalContainer = null;
// --- Funciones Lógicas ---
function openGallery() {
if (modalOpen) {
return;
}
modalOpen = true;
galleryState.currentPage = 0;
galleryState.selectedElementId = 0;
// Buscar el primer personaje recolectado para mostrarlo por defecto al abrir
for (var s = 0; s < characterDatabase.length; s++) {
if (gameState.collectedCharacters[s]) {
galleryState.selectedElementId = s;
break;
}
}
modalContainer = new Container();
var modalBg = LK.getAsset('modal_bg', {
anchorX: 0.5,
anchorY: 0.5
});
modalContainer.addChild(modalBg);
modalContainer.x = 1024;
modalContainer.y = 1366;
var galleryTitle = new Text2('Element Gallery', {
size: 80,
fill: '#FFD700'
});
galleryTitle.anchor.set(0.5, 0);
galleryTitle.x = 0;
galleryTitle.y = -1100;
modalContainer.addChild(galleryTitle);
var closeBtnGraphic = LK.getAsset('modal_close_btn', {
anchorX: 0.5,
anchorY: 0.5
});
var closeBtn = new Container();
closeBtn.addChild(closeBtnGraphic);
closeBtn.x = 800;
closeBtn.y = -1050;
modalContainer.addChild(closeBtn);
var closeBtnText = new Text2('X', {
size: 60,
fill: '#ffffff'
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
closeBtn.down = function () {
closeModal();
LK.getSound('ui_click').play();
};
// Contenedor dinámico que se refresca
var contentContainer = new Container();
modalContainer.addChild(contentContainer);
function renderGalleryContent() {
while (contentContainer.children.length > 0) {
contentContainer.children[0].destroy();
}
var totalItems = galleryDisplayOrder.length;
var totalPages = Math.ceil(totalItems / galleryState.itemsPerPage);
var startIndex = galleryState.currentPage * galleryState.itemsPerPage;
var endIndex = Math.min(startIndex + galleryState.itemsPerPage, totalItems);
// --- PANEL IZQUIERDO: CUADRÍCULA 3x3 ---
var gridStartX = -750;
var gridStartY = -700;
var spacing = 400;
for (var i = startIndex; i < endIndex; i++) {
var localIndex = i - startIndex;
var col = localIndex % 3;
var row = Math.floor(localIndex / 3);
// AHORA BUSCAMOS EL ID BASADO EN EL NUEVO ORDEN
var actualCharId = galleryDisplayOrder[i];
var charData = characterDatabase[actualCharId];
var isCollected = gameState.collectedCharacters[actualCharId];
var displayChar = new Character();
var displayName = isCollected ? charData.name : "???";
// Siempre revelamos la rareza (Spoiler visual)
var displayRarity = charData.rarity;
displayChar.init(actualCharId, displayName, displayRarity, charData.asset, charData.multiplier);
displayChar.x = gridStartX + col * spacing;
displayChar.y = gridStartY + row * (spacing * 1.2);
// Efecto Silueta Inteligente
if (!isCollected) {
displayChar.graphicObj.tint = 0x000000; // Personaje en negro
displayChar.nameObj.fill = '#555555'; // Letras del nombre en gris
displayChar.frameObj.alpha = 0.05; // Apagamos casi todo el brillo del marco
}
// Indicador visual de elemento seleccionado
if (galleryState.selectedElementId === actualCharId) {
displayChar.scale.set(1.15, 1.15); // Ligeramente más grande al seleccionarlo
}
(function (idToSelect) {
displayChar.down = function () {
if (galleryState.selectedElementId !== idToSelect) {
galleryState.selectedElementId = idToSelect;
LK.getSound('ui_click').play();
renderGalleryContent();
}
};
})(actualCharId);
contentContainer.addChild(displayChar);
}
var pageText = new Text2('Page ' + (galleryState.currentPage + 1) + ' / ' + totalPages, {
size: 80,
fill: '#FFFFFF'
});
pageText.anchor.set(0.5, 0.5);
pageText.x = -300;
pageText.y = 800;
contentContainer.addChild(pageText);
var collectionStatus = new Text2('Collected: ' + gameState.totalCharactersCollected + '/41', {
size: 60,
fill: '#87CEEB'
});
collectionStatus.anchor.set(0.5, 0.5);
collectionStatus.x = -300;
collectionStatus.y = 900;
contentContainer.addChild(collectionStatus);
if (galleryState.currentPage > 0) {
var prevBtn = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
prevBtn.scale.set(0.6, 0.8);
prevBtn.x = -550;
prevBtn.y = 650;
var prevTxt = new Text2('< PREV', {
size: 70,
fill: '#FFF'
});
prevTxt.anchor.set(0.5, 0.5);
prevBtn.addChild(prevTxt);
prevBtn.down = function () {
galleryState.currentPage--;
LK.getSound('ui_click').play();
renderGalleryContent();
};
contentContainer.addChild(prevBtn);
}
if (galleryState.currentPage < totalPages - 1) {
var nextBtn = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
nextBtn.scale.set(0.6, 0.8);
nextBtn.x = -50;
nextBtn.y = 650;
var nextTxt = new Text2('NEXT >', {
size: 70,
fill: '#FFF'
});
nextTxt.anchor.set(0.5, 0.5);
nextBtn.addChild(nextTxt);
nextBtn.down = function () {
galleryState.currentPage++;
LK.getSound('ui_click').play();
renderGalleryContent();
};
contentContainer.addChild(nextBtn);
}
// --- PANEL DERECHO: DETALLES Y EQUIPAR ---
var rightPanelX = 550;
var detailData = characterDatabase[galleryState.selectedElementId];
var isDetailCollected = gameState.collectedCharacters[galleryState.selectedElementId];
if (detailData) {
var bigGraphic = LK.getAsset(detailData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
bigGraphic.scale.set(1.35, 1.35);
bigGraphic.x = rightPanelX;
bigGraphic.y = -250;
if (!isDetailCollected) {
bigGraphic.tint = 0x000000;
}
contentContainer.addChild(bigGraphic);
var detailNameText = isDetailCollected ? detailData.name : "???";
var detailName = new Text2(detailNameText, {
size: 80,
fill: '#FFF'
});
detailName.anchor.set(0.5, 0);
detailName.x = rightPanelX;
detailName.y = 200;
contentContainer.addChild(detailName);
// Mapa de colores String para la UI de detalles
var uiColors = {
'Common': '#FFFFFF',
'Uncommon': '#00FF00',
'Rare': '#00BFFF',
'Ultra-Rare': '#8A2BE2',
'Special': '#FF1493',
'Legendary': '#FFD700',
'Unique': '#FF0000'
};
var rarityColorHexStr = uiColors[detailData.rarity] || '#FFFFFF';
var detailRarity = new Text2('[' + detailData.rarity + ']', {
size: 60,
fill: rarityColorHexStr
});
detailRarity.anchor.set(0.5, 0);
detailRarity.x = rightPanelX;
detailRarity.y = 280;
contentContainer.addChild(detailRarity);
if (isDetailCollected) {
var incomeInfo = new Text2('Income Boost: +' + detailData.multiplier + '/tick', {
size: 55,
fill: '#00FF00'
});
incomeInfo.anchor.set(0.5, 0);
incomeInfo.x = rightPanelX;
incomeInfo.y = 350;
contentContainer.addChild(incomeInfo);
}
// LÓGICA DEL BOTÓN EQUIPAR
var orbitStatusText = new Text2('Orbiting: ' + gameState.equippedCharacters.length + ' / ' + GAME_CONFIG.MAX_EQUIPPED, {
size: 60,
fill: '#87CEEB'
});
orbitStatusText.anchor.set(0.5, 0);
orbitStatusText.x = rightPanelX;
orbitStatusText.y = 450;
contentContainer.addChild(orbitStatusText);
if (isDetailCollected) {
var isEquipped = gameState.equippedCharacters.indexOf(galleryState.selectedElementId) > -1;
var equipBtnGraphic = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
equipBtnGraphic.scale.set(1.5, 1.2);
equipBtnGraphic.tint = isEquipped ? 0xFF4444 : 0x32CD32;
var equipBtn = new Container();
equipBtn.addChild(equipBtnGraphic);
equipBtn.x = rightPanelX;
equipBtn.y = 650;
var equipBtnText = new Text2(isEquipped ? 'UNEQUIP' : 'EQUIP', {
size: 50,
fill: '#ffffff'
});
equipBtnText.anchor.set(0.5, 0.5);
equipBtn.addChild(equipBtnText);
equipBtn.down = function () {
if (isEquipped) {
var index = gameState.equippedCharacters.indexOf(galleryState.selectedElementId);
gameState.equippedCharacters.splice(index, 1);
} else {
if (gameState.equippedCharacters.length >= GAME_CONFIG.MAX_EQUIPPED) {
gameState.equippedCharacters.shift();
}
gameState.equippedCharacters.push(galleryState.selectedElementId);
}
updateEquippedDisplay();
saveGame();
LK.getSound('ui_click').play();
renderGalleryContent();
};
contentContainer.addChild(equipBtn);
} else {
var lockText = new Text2('LOCKED', {
size: 50,
fill: '#FF4444'
});
lockText.anchor.set(0.5, 0.5);
lockText.x = rightPanelX;
lockText.y = 400;
contentContainer.addChild(lockText);
}
}
}
renderGalleryContent();
game.addChild(modalContainer);
}
function closeModal() {
if (modalContainer) {
modalContainer.destroy();
modalOpen = false;
}
}
function performGachaPull() {
var currentCost = getGachaCost();
if (gameState.credits < currentCost) {
return;
}
gameState.credits -= currentCost;
gameState.pityCounter++; // Incrementamos el contador al tirar
var roll = Math.random() * 100;
var selectedRarity = null;
// VERIFICACIÓN DEL PITY SYSTEM
if (gameState.pityCounter >= 10) {
// Tirada garantizada (60% Special, 30% Legendary, 10% Unique)
var pityRoll = Math.random() * 100;
if (pityRoll <= 60) {
selectedRarity = {
rarity: 'Special',
ids: [31, 32, 33, 34, 35, 36]
};
} else if (pityRoll <= 90) {
selectedRarity = {
rarity: 'Legendary',
ids: [23, 24, 25, 26, 27]
};
} else {
selectedRarity = {
rarity: 'Unique',
ids: [28, 29, 30]
};
}
gameState.pityCounter = 0; // Reiniciamos el pity después de usarlo
} else {
// Tirada Normal
var cumulativeChance = 0;
for (var i = 0; i < dropRates.length; i++) {
cumulativeChance += dropRates[i].chance;
if (roll <= cumulativeChance) {
selectedRarity = dropRates[i];
break;
}
}
// Si en la tirada normal obtuviste una rareza alta, el pity se reinicia
if (selectedRarity.rarity === 'Special' || selectedRarity.rarity === 'Legendary' || selectedRarity.rarity === 'Unique') {
gameState.pityCounter = 0;
}
}
var characterIdArray = selectedRarity.ids;
var selectedCharacterId = characterIdArray[Math.floor(Math.random() * characterIdArray.length)];
var wasNew = false;
var charData = characterDatabase[selectedCharacterId];
if (!gameState.collectedCharacters[selectedCharacterId]) {
gameState.collectedCharacters[selectedCharacterId] = true;
gameState.totalCharactersCollected++;
wasNew = true;
gameState.incomePerTick += charData.multiplier;
}
saveGame();
LK.getSound('gacha_pull').play();
var rarityEffects = {
'Common': {
color: 0xFFFFFF,
scale: 1
},
'Uncommon': {
color: 0x00FF00,
scale: 1
},
'Rare': {
color: 0x00BFFF,
scale: 1
},
'Ultra-Rare': {
color: 0x8A2BE2,
scale: 1
},
'Legendary': {
color: 0xFFD700,
scale: 1
},
'Unique': {
color: 0xFF0000,
scale: 1.0
},
'Special': {
color: 0xFF1493,
scale: 1
}
};
var currentEffect = rarityEffects[charData.rarity] || {
color: 0xFFFFFF,
scale: 0.70
};
var resultMessage = wasNew ? 'NEW: ' + charData.name + '!' : 'Duplicate: ' + charData.name;
var resultColor = wasNew ? '#2d633b' : '#b89e14';
var resultContainer = new Container();
var resultBg = LK.getAsset('pull_bg', {
anchorX: 0.5,
anchorY: 0.5
});
resultContainer.addChild(resultBg);
resultContainer.x = 1024;
resultContainer.y = 1366;
resultContainer.scale.set(0.1, 0.1);
tween(resultContainer, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
var aura = LK.getAsset('core_crystal', {
anchorX: 0.5,
anchorY: 0.5
});
aura.tint = currentEffect.color;
var auraScaleFactor = currentEffect.scale * 2.5;
aura.scale.set(auraScaleFactor, auraScaleFactor);
aura.alpha = 0.5;
resultContainer.addChild(aura);
tween(aura, {
rotation: Math.PI * 2
}, {
duration: 2000
});
var resultGraphic = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
var scaleTarget = currentEffect.scale;
resultGraphic.scale.set(0.1, 0.1);
tween(resultGraphic, {
scaleX: scaleTarget + 0.05,
scaleY: scaleTarget + 0.05
}, {
duration: 250,
onFinish: function onFinish() {
tween(resultGraphic, {
scaleX: scaleTarget,
scaleY: scaleTarget
}, {
duration: 150
});
}
});
resultGraphic.y = 0;
resultContainer.addChild(resultGraphic);
var safePadding = 720 * scaleTarget / 2 + 80;
var resultTitle = new Text2(resultMessage, {
size: 150,
fill: resultColor
});
resultTitle.anchor.set(0.5, 0.5);
resultTitle.y = -safePadding;
resultContainer.addChild(resultTitle);
var resultRarity = new Text2('[' + charData.rarity + ']', {
size: 90,
fill: '#191919'
});
resultRarity.anchor.set(0.5, 0.5);
resultRarity.y = safePadding;
resultContainer.addChild(resultRarity);
game.addChild(resultContainer);
LK.setTimeout(function () {
tween(resultContainer, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
resultContainer.destroy();
}
});
}, 2000);
}
function performGachaPull10() {
var singleCost = getGachaCost();
var totalCost = singleCost * 10;
if (gameState.credits < totalCost) {
return;
}
gameState.credits -= totalCost;
var pullResults = [];
// 1. Las 9 tiradas normales
for (var i = 0; i < 9; i++) {
var roll = Math.random() * 100;
var selectedRarity = null;
var cumulativeChance = 0;
for (var j = 0; j < dropRates.length; j++) {
cumulativeChance += dropRates[j].chance;
if (roll <= cumulativeChance) {
selectedRarity = dropRates[j];
break;
}
}
var charIdArray = selectedRarity.ids;
var selectedCharId = charIdArray[Math.floor(Math.random() * charIdArray.length)];
pullResults.push(characterDatabase[selectedCharId]);
if (!gameState.collectedCharacters[selectedCharId]) {
gameState.collectedCharacters[selectedCharId] = true;
gameState.totalCharactersCollected++;
gameState.incomePerTick += characterDatabase[selectedCharId].multiplier;
}
}
// 2. La 10ª tirada (Lástima Garantizada)
var pityRoll = Math.random() * 100;
var pityRarity = null;
// (Asegúrate de haber añadido los IDs de tus 8 nuevos personajes en los arreglos correspondientes)
if (pityRoll <= 60) {
pityRarity = {
rarity: 'Special',
ids: [31, 32, 33, 34, 35, 36]
};
} else if (pityRoll <= 90) {
pityRarity = {
rarity: 'Legendary',
ids: [23, 24, 25, 26, 27]
};
} else {
pityRarity = {
rarity: 'Unique',
ids: [28, 29, 30]
};
}
var pityCharIdArray = pityRarity.ids;
var pityCharId = pityCharIdArray[Math.floor(Math.random() * pityCharIdArray.length)];
pullResults.push(characterDatabase[pityCharId]);
if (!gameState.collectedCharacters[pityCharId]) {
gameState.collectedCharacters[pityCharId] = true;
gameState.totalCharactersCollected++;
gameState.incomePerTick += characterDatabase[pityCharId].multiplier;
}
// Reiniciamos el pity porque acabamos de dar uno garantizado
gameState.pityCounter = 0;
saveGame();
LK.getSound('gacha_pull').play();
showMultiPullResults(pullResults);
}
function showMultiPullResults(results) {
modalOpen = true; // Bloquea la UI de fondo
var resultContainer = new Container();
var modalBg = LK.getAsset('modal_bg', {
anchorX: 0.5,
anchorY: 0.5
});
resultContainer.addChild(modalBg);
resultContainer.x = 1024;
resultContainer.y = 1366;
resultContainer.scale.set(0.1, 0.1);
tween(resultContainer, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
var titleText = new Text2('10x PULL RESULTS', {
size: 100,
fill: '#FFD700'
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -900;
resultContainer.addChild(titleText);
// Configuramos la cuadrícula (2 filas x 5 columnas)
var startX = -600;
var startY = -400;
var spacingX = 300;
var spacingY = 400;
for (var i = 0; i < results.length; i++) {
var charData = results[i];
var col = i % 5;
var row = Math.floor(i / 5);
// Si es de rareza alta, le ponemos un aura detrás
if (charData.rarity === 'Special' || charData.rarity === 'Legendary' || charData.rarity === 'Unique') {
var aura = LK.getAsset('core_crystal', {
anchorX: 0.5,
anchorY: 0.5
});
aura.x = startX + col * spacingX;
aura.y = startY + row * spacingY;
aura.scale.set(1.5, 1.5);
aura.tint = 0xFFD700;
aura.alpha = 0.5;
resultContainer.addChild(aura);
tween(aura, {
rotation: Math.PI * 2
}, {
duration: 2000
});
}
var charGraphic = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
charGraphic.x = startX + col * spacingX;
charGraphic.y = startY + row * spacingY;
charGraphic.scale.set(0.35, 0.35); // Más pequeños para que quepan
resultContainer.addChild(charGraphic);
}
// Botón para cerrar
var closeBtnGraphic = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
var closeBtn = new Container();
closeBtn.addChild(closeBtnGraphic);
closeBtn.y = 800;
resultContainer.addChild(closeBtn);
var closeText = new Text2('CONTINUE', {
size: 60,
fill: '#FFFFFF'
});
closeText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeText);
closeBtn.down = function () {
LK.getSound('ui_click').play();
tween(resultContainer, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
resultContainer.destroy();
modalOpen = false; // Liberamos la UI
}
});
};
game.addChild(resultContainer);
}
function upgradeIncomeLevel(levelIndex) {
var level = levelContainers[levelIndex];
if (gameState.credits >= level.currentCost) {
gameState.credits -= level.currentCost;
gameState.incomeLevels[levelIndex]++;
gameState.incomePerTick += level.baseIncome;
level.updateData(gameState.incomeLevels[levelIndex]);
saveGame();
LK.getSound('level_up').play();
}
}
// --- Event Handlers Directos ---
gachaButton.down = function () {
if (modalOpen) {
return;
}
if (gachaEnabled) {
performGachaPull();
LK.getSound('ui_click').play();
}
};
gacha10Button.down = function () {
if (modalOpen) {
return;
}
if (gacha10Enabled) {
performGachaPull10();
}
};
galleryButton.down = function () {
if (modalOpen) {
return;
}
openGallery();
LK.getSound('ui_click').play();
};
/*
debugButton.down = function () {
if (modalOpen) {
return;
}
gameState.credits = 0;
gameState.incomePerTick = 1;
gameState.collectedCharacters = {};
gameState.totalCharactersCollected = 0;
gameState.incomeLevels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
gameState.equippedCharacters = [];
for (var i = 0; i < levelContainers.length; i++) {
levelContainers[i].updateData(0);
}
updateEquippedDisplay();
saveGame();
LK.getSound('ui_click').play();
};
*/
coreButton.down = function () {
if (modalOpen) {
return;
}
var clickGain = 1 + Math.floor(gameState.incomePerTick * 0.2);
gameState.credits += clickGain;
// El texto flotante ahora sigue dinámicamente al nuevo centro del botón (X: 1536, Y: 1366)
var floatText = new FloatingText('+' + clickGain, coreButton.x + (Math.random() * 100 - 50), coreButton.y - 150, '#00ffff');
game.addChild(floatText);
tween(coreGraphic, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 50,
onFinish: function onFinish() {
tween(coreGraphic, {
scaleX: 1,
scaleY: 1
}, {
duration: 50
});
}
});
};
for (var i = 0; i < levelContainers.length; i++) {
(function (index) {
levelContainers[index].down = function () {
if (modalOpen) {
return;
}
upgradeIncomeLevel(index);
};
})(i);
}
// --- Variables para el Main Loop ---
var pulseTimer = 0;
var lastDisplayedCredits = -1;
var lastDisplayedIncome = -1;
var lastDisplayedCollection = -1;
var lastDisplayedGachaCost = -1;
var lastDisplayedPity = -1;
// --- Main Game Loop Optimizado ---
game.update = function () {
gameState.tickCounter++;
// LÓGICA DE ÓRBITA
var numOrbiting = orbitingSprites.length;
if (numOrbiting > 0) {
orbitAngle += GAME_CONFIG.ORBIT_SPEED;
var angleStep = Math.PI * 2 / numOrbiting;
for (var o = 0; o < numOrbiting; o++) {
var currentAngle = orbitAngle + o * angleStep;
orbitingSprites[o].x = Math.cos(currentAngle) * GAME_CONFIG.ORBIT_RADIUS;
orbitingSprites[o].y = Math.sin(currentAngle) * GAME_CONFIG.ORBIT_RADIUS;
//orbitingSprites[o].rotation += 0.01;
}
}
if (gameState.tickCounter % GAME_CONFIG.FPS === 0) {
gameState.credits += gameState.incomePerTick;
}
// --- Actualización de Costos y Textos ---
var currentCredits = Math.floor(gameState.credits);
var currentGachaCost = getGachaCost();
var currentGachaCost10 = currentGachaCost * 10;
// === INICIO DEL BLOQUE FALTANTE ===
if (currentCredits !== lastDisplayedCredits) {
creditsText.setText('Credits: ' + currentCredits);
lastDisplayedCredits = currentCredits;
}
if (gameState.incomePerTick !== lastDisplayedIncome) {
incomeText.setText('Income: ' + gameState.incomePerTick + '/tick');
lastDisplayedIncome = gameState.incomePerTick;
}
if (gameState.totalCharactersCollected !== lastDisplayedCollection) {
// Usamos characterDatabase.length para que se actualice solo si agregas más en el futuro
collectionText.setText('Collection: ' + gameState.totalCharactersCollected + '/' + characterDatabase.length);
lastDisplayedCollection = gameState.totalCharactersCollected;
}
if (currentGachaCost !== lastDisplayedGachaCost || gameState.pityCounter !== lastDisplayedPity) {
// Actualiza textos Botón x1
gachaText.setText('PULL (' + currentGachaCost + ')');
if (gameState.pityCounter >= 9) {
pityText.setText('Pity: READY!');
pityText.fill = '#00FF00';
} else {
pityText.setText('Pity: ' + gameState.pityCounter + '/10');
pityText.fill = '#FFD700';
}
// Actualiza textos Botón x10
gacha10Text.setText('10x (' + currentGachaCost10 + ')');
lastDisplayedGachaCost = currentGachaCost;
lastDisplayedPity = gameState.pityCounter;
}
// --- Control Visual de Botones Disponibles ---
gachaEnabled = gameState.credits >= currentGachaCost;
gacha10Enabled = gameState.credits >= currentGachaCost10;
// Efectos del Botón x1
if (gachaEnabled) {
gachaBtnGraphic.tint = 0xFF1493;
gachaText.tint = 0xFFFFFF;
pulseTimer += 0.05;
var scaleX = 1.6 + Math.sin(pulseTimer) * 0.05;
var scaleY = 1.8 + Math.sin(pulseTimer) * 0.05;
gachaBtnGraphic.scale.set(scaleX, scaleY);
} else {
gachaBtnGraphic.tint = 0x883366;
gachaText.tint = 0xAAAAAA;
gachaBtnGraphic.scale.set(1.6, 1.8);
}
// Efectos del Botón x10
if (gacha10Enabled) {
gacha10BtnGraphic.tint = 0xFF1493;
gacha10Text.tint = 0xFFFFFF;
var scaleX10 = 1.6 + Math.cos(pulseTimer) * 0.05; // Usamos cos para desfasar el pulso visual
var scaleY10 = 1.8 + Math.cos(pulseTimer) * 0.05;
gacha10BtnGraphic.scale.set(scaleX10, scaleY10);
} else {
gacha10BtnGraphic.tint = 0x883366;
gacha10Text.tint = 0xAAAAAA;
gacha10BtnGraphic.scale.set(1.6, 1.8);
}
for (var j = 0; j < levelContainers.length; j++) {
var level = levelContainers[j];
if (gameState.credits >= level.currentCost) {
level.children[0].tint = 0xffffff;
} else {
level.children[0].tint = 0x525252;
}
}
if (gameState.tickCounter % GAME_CONFIG.SAVE_INTERVAL === 0) {
saveGame();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
/**** * Classes ****/
var Character = Container.expand(function () {
var self = Container.call(this);
self.init = function (elementId, elementName, rarity, assetId, multiplier) {
// Mapa de colores por rareza
var rarityColorsHex = {
'Common': 0xFFFFFF,
'Uncommon': 0x00FF00,
'Rare': 0x00BFFF,
'Ultra-Rare': 0x8A2BE2,
'Special': 0xFF1493,
'Legendary': 0xFFD700,
'Unique': 0xFF0000
};
var rColor = rarityColorsHex[rarity] || 0xffffff;
// 1. El Marco (Aura de fondo)
var frame = self.attachAsset('bg_character', {
anchorX: 0.5,
anchorY: 0.55
});
frame.scale.set(0.75, 1);
frame.tint = rColor;
frame.alpha = 0.6; // Resplandor sutil
// 2. El Gráfico del Personaje
var graphic = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
graphic.scale.set(0.5, 0.5);
// 3. El Nombre
var nameText = new Text2(elementName, {
size: 50,
fill: '#ffffff'
});
nameText.anchor.set(0.5, 0);
nameText.y = 130;
self.addChild(nameText);
// 4. La Rareza (Ahora obtiene el color automáticamente)
var rarityText = new Text2('[' + rarity + ']', {
size: 45,
fill: rColor
});
rarityText.anchor.set(0.5, 0);
rarityText.y = 170;
self.addChild(rarityText);
// Guardamos referencias para modificarlas fácilmente en la galería
self.frameObj = frame;
self.graphicObj = graphic;
self.nameObj = nameText;
self.rarityObj = rarityText;
};
return self;
});
var FloatingText = Container.expand(function () {
var self = Container.call(this);
self.init = function (textValue, startX, startY, color) {
self.x = startX;
self.y = startY;
var txt = new Text2(textValue, {
size: 48,
fill: color || '#ffffff'
});
txt.anchor.set(0.5, 0.5);
self.addChild(txt);
tween(self, {
y: self.y - 150,
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
// Clases de UI: Income Level (AHORA MÁS GRANDE)
var IncomeLevel = Container.expand(function () {
var self = Container.call(this);
self.levelIndex = 0;
self.baseIncome = 0;
self.baseCost = 0;
self.currentCost = 0;
self.init = function (levelIndex, baseIncome) {
self.levelIndex = levelIndex;
self.baseIncome = baseIncome;
self.baseCost = 50 * (levelIndex + 1);
var bg = self.attachAsset('upgrade_button', {
anchorX: 0.5,
anchorY: 0.5
});
// Escala aumentada de 1.5 a 2.0
bg.scale.set(2.0, 2.0);
// Textos aumentados y reposicionados
var levelText = new Text2('', {
size: 38,
fill: '#ffffff'
});
levelText.anchor.set(0.5, 0.5);
levelText.y = -25;
self.addChild(levelText);
self.levelText = levelText;
var costText = new Text2('', {
size: 30,
fill: '#ffffff'
});
costText.anchor.set(0.5, 0.5);
costText.y = 25;
self.addChild(costText);
self.costText = costText;
};
self.updateData = function (purchases) {
self.currentCost = Math.floor(self.baseCost * Math.pow(1.5, purchases));
self.costText.setText('Cost: ' + self.currentCost);
self.levelText.setText('Lvl ' + (self.levelIndex + 1) + ' (x' + purchases + '): +' + self.baseIncome + '/t');
};
return self;
});
/****
* Initialize Game
****/
/**** * Initialize Game ****/
var game = new LK.Game({
backgroundColor: 0x6f6fdb
});
/****
* Game Code
****/
/**** * Plugins ****/
/**** * Game Code ****/
var GAME_CONFIG = {
BASE_GACHA_COST: 1000,
GACHA_COST_MULTIPLIER: 1.10,
FPS: 60,
SAVE_INTERVAL: 300,
MAX_EQUIPPED: 6,
ORBIT_RADIUS: 400,
ORBIT_SPEED: 0.008
};
var characterDatabase = [{
id: 0,
name: 'Fire',
rarity: 'Common',
asset: 'fire_common',
multiplier: 2
}, {
id: 1,
name: 'Water',
rarity: 'Common',
asset: 'water_common',
multiplier: 2
}, {
id: 2,
name: 'Earth',
rarity: 'Common',
asset: 'earth_common',
multiplier: 2
}, {
id: 3,
name: 'Wind',
rarity: 'Common',
asset: 'wind_common',
multiplier: 2
}, {
id: 4,
name: 'Lightning',
rarity: 'Uncommon',
asset: 'lightning_uncommon',
multiplier: 3
}, {
id: 5,
name: 'Ice',
rarity: 'Uncommon',
asset: 'ice_uncommon',
multiplier: 3
}, {
id: 6,
name: 'Nature',
rarity: 'Uncommon',
asset: 'nature_uncommon',
multiplier: 3
}, {
id: 7,
name: 'Metal',
rarity: 'Uncommon',
asset: 'metal_uncommon',
multiplier: 3
}, {
id: 8,
name: 'Sand',
rarity: 'Uncommon',
asset: 'sand_uncommon',
multiplier: 3
}, {
id: 9,
name: 'Steam',
rarity: 'Uncommon',
asset: 'steam_uncommon',
multiplier: 3
}, {
id: 10,
name: 'Magma',
rarity: 'Rare',
asset: 'magma_rare',
multiplier: 4
}, {
id: 11,
name: 'Frost',
rarity: 'Rare',
asset: 'frost_rare',
multiplier: 4
}, {
id: 12,
name: 'Crystal',
rarity: 'Rare',
asset: 'crystal_rare',
multiplier: 4
}, {
id: 13,
name: 'Storm',
rarity: 'Rare',
asset: 'storm_rare',
multiplier: 4
}, {
id: 14,
name: 'Coral',
rarity: 'Rare',
asset: 'coral_rare',
multiplier: 4
}, {
id: 15,
name: 'Forest',
rarity: 'Rare',
asset: 'forest_rare',
multiplier: 4
}, {
id: 16,
name: 'Shadow',
rarity: 'Rare',
asset: 'shadow_rare',
multiplier: 4
}, {
id: 17,
name: 'Plasma',
rarity: 'Ultra-Rare',
asset: 'plasma_ultra',
multiplier: 5
}, {
id: 18,
name: 'Abyss',
rarity: 'Ultra-Rare',
asset: 'abyss_ultra',
multiplier: 5
}, {
id: 19,
name: 'Aurora',
rarity: 'Ultra-Rare',
asset: 'aurora_ultra',
multiplier: 5
}, {
id: 20,
name: 'Inferno',
rarity: 'Ultra-Rare',
asset: 'inferno_ultra',
multiplier: 5
}, {
id: 21,
name: 'Glacier',
rarity: 'Ultra-Rare',
asset: 'glacier_ultra',
multiplier: 5
}, {
id: 22,
name: 'Mirage',
rarity: 'Ultra-Rare',
asset: 'mirage_ultra',
multiplier: 5
}, {
id: 23,
name: 'Celestial',
rarity: 'Legendary',
asset: 'celestial_legendary',
multiplier: 7
}, {
id: 24,
name: 'Cosmic',
rarity: 'Legendary',
asset: 'cosmic_legendary',
multiplier: 7
}, {
id: 25,
name: 'Void',
rarity: 'Legendary',
asset: 'void_legendary',
multiplier: 7
}, {
id: 26,
name: 'Radiance',
rarity: 'Legendary',
asset: 'radiance_legendary',
multiplier: 7
}, {
id: 27,
name: 'Eclipse',
rarity: 'Legendary',
asset: 'eclipse_legendary',
multiplier: 7
}, {
id: 28,
name: 'Genesis',
rarity: 'Unique',
asset: 'genesis_unique',
multiplier: 10
}, {
id: 29,
name: 'Apocalypse',
rarity: 'Unique',
asset: 'apocalypse_unique',
multiplier: 10
}, {
id: 30,
name: 'Paradox',
rarity: 'Unique',
asset: 'paradox_unique',
multiplier: 10
}, {
id: 31,
name: 'Nova',
rarity: 'Special',
asset: 'nova_special',
multiplier: 6
}, {
id: 32,
name: 'Nebula',
rarity: 'Special',
asset: 'nebula_special',
multiplier: 6
}, {
id: 33,
name: 'Titan',
rarity: 'Special',
asset: 'titan_special',
multiplier: 6
}, {
id: 34,
name: 'Phantom',
rarity: 'Special',
asset: 'phantom_special',
multiplier: 6
}, {
id: 35,
name: 'Sphinx',
rarity: 'Special',
asset: 'sphinx_special',
multiplier: 6
}, {
id: 36,
name: 'Oracle',
rarity: 'Special',
asset: 'oracle_special',
multiplier: 6
}, {
id: 37,
name: 'Dust',
rarity: 'Uncommon',
asset: 'dust_uncommon',
multiplier: 3
}, {
id: 38,
name: 'Spore',
rarity: 'Uncommon',
asset: 'spore_uncommon',
multiplier: 3
}, {
id: 39,
name: 'Tectonic',
rarity: 'Rare',
asset: 'tectonic_rare',
multiplier: 4
}, {
id: 40,
name: 'Biosphere',
rarity: 'Ultra-Rare',
asset: 'biosphere_ultra',
multiplier: 5
}, {
id: 41,
name: 'Pulsar',
rarity: 'Special',
asset: 'pulsar_special',
multiplier: 6
}, {
id: 42,
name: 'Antimatter',
rarity: 'Legendary',
asset: 'antimatter_legendary',
multiplier: 7
}, {
id: 43,
name: 'Singularity',
rarity: 'Legendary',
asset: 'singularity_legendary',
multiplier: 7
}, {
id: 44,
name: 'Entropy',
rarity: 'Unique',
asset: 'entropy_unique',
multiplier: 10
}];
var dropRates = [{
rarity: 'Common',
chance: 45,
ids: [0, 1, 2, 3]
}, {
rarity: 'Uncommon',
chance: 20,
ids: [4, 5, 6, 7, 8, 9, 37, 38]
}, {
rarity: 'Rare',
chance: 15,
ids: [10, 11, 12, 13, 14, 15, 16, 39]
}, {
rarity: 'Ultra-Rare',
chance: 10,
ids: [17, 18, 19, 20, 21, 22, 40]
}, {
rarity: 'Special',
chance: 6,
ids: [31, 32, 33, 34, 35, 36, 41]
}, {
rarity: 'Legendary',
chance: 3,
ids: [23, 24, 25, 26, 27, 42, 43]
}, {
rarity: 'Unique',
chance: 1,
ids: [28, 29, 30, 44]
}];
var galleryDisplayOrder = [0, 1, 2, 3,
// Common
4, 5, 6, 7, 8, 9, 37, 38,
// Uncommon
10, 11, 12, 13, 14, 15, 16, 39,
// Rare
17, 18, 19, 20, 21, 22, 40,
// Ultra-Rare
31, 32, 33, 34, 35, 36, 41,
// Special
23, 24, 25, 26, 27, 42, 43,
// Legendary
28, 29, 30, 44 // Unique
];
var gameState = {
credits: 0,
incomePerTick: 1,
collectedCharacters: {},
totalCharactersCollected: 0,
incomeLevels: [],
tickCounter: 0,
equippedCharacters: [],
pityCounter: 0 // Contador de Lástima
};
// Estado temporal para controlar la vista de la galería
var galleryState = {
currentPage: 0,
itemsPerPage: 9,
// Cuadrícula de 3x3
selectedElementId: 0
};
// --- Funciones Base de Estado ---
function getGachaCost() {
return Math.floor(GAME_CONFIG.BASE_GACHA_COST * Math.pow(GAME_CONFIG.GACHA_COST_MULTIPLIER, gameState.totalCharactersCollected));
}
function loadGame() {
gameState.collectedCharacters = {};
gameState.incomeLevels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
gameState.equippedCharacters = [];
if (storage.credits !== undefined) {
gameState.credits = storage.credits;
gameState.incomePerTick = storage.incomePerTick;
gameState.totalCharactersCollected = storage.totalCharactersCollected;
gameState.tickCounter = storage.tickCounter || 0;
gameState.pityCounter = storage.pityCounter || 0;
var collectedIds = (storage.collectedCharacterIds || '').split(',');
for (var i = 0; i < collectedIds.length; i++) {
if (collectedIds[i] !== '') {
gameState.collectedCharacters[parseInt(collectedIds[i])] = true;
}
}
var upgradedLevels = (storage.upgradedLevelCounts || '').split(',');
for (var j = 0; j < upgradedLevels.length; j++) {
if (upgradedLevels[j] !== '') {
gameState.incomeLevels[j] = parseInt(upgradedLevels[j]) || 0;
}
}
var equippedStr = storage.equippedCharactersIds || '';
if (equippedStr !== '') {
var eqSplit = equippedStr.split(',');
for (var k = 0; k < eqSplit.length; k++) {
if (eqSplit[k] !== '') {
gameState.equippedCharacters.push(parseInt(eqSplit[k]));
}
}
}
}
}
function saveGame() {
storage.credits = gameState.credits;
storage.incomePerTick = gameState.incomePerTick;
storage.totalCharactersCollected = gameState.totalCharactersCollected;
storage.tickCounter = gameState.tickCounter;
storage.pityCounter = gameState.pityCounter;
var collectedIds = '';
for (var charId in gameState.collectedCharacters) {
if (gameState.collectedCharacters[charId]) {
collectedIds += charId + ',';
}
}
storage.collectedCharacterIds = collectedIds;
var upgradedLevels = '';
for (var i = 0; i < gameState.incomeLevels.length; i++) {
upgradedLevels += gameState.incomeLevels[i] + ',';
}
storage.upgradedLevelCounts = upgradedLevels;
var equippedIds = '';
for (var e = 0; e < gameState.equippedCharacters.length; e++) {
equippedIds += gameState.equippedCharacters[e] + ',';
}
storage.equippedCharactersIds = equippedIds;
}
loadGame();
// --- UI Construction ---
var creditsText = new Text2('Credits: 0', {
size: 100,
fill: '#FFD700'
});
creditsText.anchor.set(0.5, 0);
creditsText.x = 1024;
creditsText.y = 50;
game.addChild(creditsText);
var incomeText = new Text2('Income: 1/tick', {
size: 80,
fill: '#00FF00'
});
incomeText.anchor.set(0.5, 0);
incomeText.x = 1024;
incomeText.y = 160;
game.addChild(incomeText);
var collectionText = new Text2('Collection: 0/41', {
size: 60,
fill: '#87CEEB'
});
collectionText.anchor.set(0.5, 0);
collectionText.x = 1024;
collectionText.y = 250;
game.addChild(collectionText);
// --- SISTEMA DE ÓRBITA (A LA DERECHA) ---
var orbitContainer = new Container();
orbitContainer.x = 1536; // 3/4 de la pantalla
orbitContainer.y = 1366; // Centro vertical
game.addChild(orbitContainer);
var orbitingSprites = [];
var orbitAngle = 0;
function updateEquippedDisplay() {
while (orbitContainer.children.length > 0) {
orbitContainer.children[0].destroy();
}
orbitingSprites = [];
for (var i = 0; i < gameState.equippedCharacters.length; i++) {
var charId = gameState.equippedCharacters[i];
var charData = characterDatabase[charId];
var sprite = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
sprite.scale.set(0.55, 0.55);
orbitContainer.addChild(sprite);
orbitingSprites.push(sprite);
}
}
updateEquippedDisplay();
// --- Manual Clicker Core (A LA DERECHA) ---
var coreGraphic = LK.getAsset('core_crystal', {
anchorX: 0.5,
anchorY: 0.5
});
var coreButton = new Container();
coreButton.addChild(coreGraphic);
coreButton.x = 1536; // 3/4 de la pantalla
coreButton.y = 1366; // Centro vertical
game.addChild(coreButton);
var coreText = new Text2('TAP', {
size: 50,
fill: '#ffffff'
});
coreText.anchor.set(0.5, 0.5);
coreButton.addChild(coreText);
// --- Botón Gacha Individual (Movido a la Izquierda) ---
var gachaBtnGraphic = LK.getAsset('gacha_button', {
anchorX: 0.5,
anchorY: 0.5
});
gachaBtnGraphic.scale.set(1.6, 1.8);
var gachaButton = new Container();
gachaButton.addChild(gachaBtnGraphic);
gachaButton.x = 600; // Antes 1024
gachaButton.y = 2500;
game.addChild(gachaButton);
var gachaText = new Text2('PULL (' + getGachaCost() + ')', {
size: 55,
fill: '#ffffff'
});
gachaText.anchor.set(0.5, 0.5);
gachaText.y = -20;
gachaButton.addChild(gachaText);
var pityText = new Text2('Pity: 0/10', {
size: 40,
fill: '#FFD700'
});
pityText.anchor.set(0.5, 0.5);
pityText.y = 30;
gachaButton.addChild(pityText);
var gachaEnabled = false;
// --- NUEVO: Botón Gacha x10 (A la Derecha) ---
var gacha10BtnGraphic = LK.getAsset('gacha_button', {
anchorX: 0.5,
anchorY: 0.5
});
gacha10BtnGraphic.scale.set(1.6, 1.8);
var gacha10Button = new Container();
gacha10Button.addChild(gacha10BtnGraphic);
gacha10Button.x = 1448;
gacha10Button.y = 2500;
game.addChild(gacha10Button);
var gacha10Text = new Text2('10x PULL', {
size: 55,
fill: '#ffffff'
});
gacha10Text.anchor.set(0.5, 0.5);
gacha10Text.y = -20;
gacha10Button.addChild(gacha10Text);
var pity10Text = new Text2('1 Guaranteed!', {
size: 40,
fill: '#00FF00'
});
pity10Text.anchor.set(0.5, 0.5);
pity10Text.y = 30;
gacha10Button.addChild(pity10Text);
var gacha10Enabled = false;
// Gallery Button
var galleryBtnGraphic = LK.getAsset('gallery_button', {
anchorX: 0.5,
anchorY: 0.5
});
galleryButton.size(2.0, 2.0);
var galleryButton = new Container();
galleryButton.addChild(galleryBtnGraphic);
galleryButton.x = 1800;
galleryButton.y = 500;
game.addChild(galleryButton);
var galleryText = new Text2('GALLERY', {
size: 50,
fill: '#ffffff'
});
galleryText.anchor.set(0.5, 0.5);
galleryButton.addChild(galleryText);
// Debug Reset Button
/*
var debugBtnGraphic = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
var debugButton = new Container();
debugButton.addChild(debugBtnGraphic);
debugButton.x = 300;
debugButton.y = 100;
game.addChild(debugButton);
var debugText = new Text2('RESET', {
size: 40,
fill: '#ff4444'
});
debugText.anchor.set(0.5, 0.5);
debugButton.addChild(debugText);*/
// Upgrade Levels Container (A LA IZQUIERDA Y MÁS GRANDES)
var levelContainers = [];
var levelStartY = 500; // Empezamos un poco más arriba
var levelSpacing = 180; // Más espacio vertical porque los botones crecieron
for (var i = 0; i < 10; i++) {
var levelContainer = new IncomeLevel();
levelContainer.init(i, [1, 2, 3, 5, 10, 20, 50, 100, 200, 300][i]);
levelContainer.updateData(gameState.incomeLevels[i]);
levelContainer.x = 512; // 1/4 de la pantalla hacia la izquierda
levelContainer.y = levelStartY + i * levelSpacing;
game.addChild(levelContainer);
levelContainers.push(levelContainer);
}
// Modal Variables
var modalOpen = false;
var modalContainer = null;
// --- Funciones Lógicas ---
function openGallery() {
if (modalOpen) {
return;
}
modalOpen = true;
galleryState.currentPage = 0;
galleryState.selectedElementId = 0;
// Buscar el primer personaje recolectado para mostrarlo por defecto al abrir
for (var s = 0; s < characterDatabase.length; s++) {
if (gameState.collectedCharacters[s]) {
galleryState.selectedElementId = s;
break;
}
}
modalContainer = new Container();
var modalBg = LK.getAsset('modal_bg', {
anchorX: 0.5,
anchorY: 0.5
});
modalContainer.addChild(modalBg);
modalContainer.x = 1024;
modalContainer.y = 1366;
var galleryTitle = new Text2('Element Gallery', {
size: 80,
fill: '#FFD700'
});
galleryTitle.anchor.set(0.5, 0);
galleryTitle.x = 0;
galleryTitle.y = -1100;
modalContainer.addChild(galleryTitle);
var closeBtnGraphic = LK.getAsset('modal_close_btn', {
anchorX: 0.5,
anchorY: 0.5
});
var closeBtn = new Container();
closeBtn.addChild(closeBtnGraphic);
closeBtn.x = 800;
closeBtn.y = -1050;
modalContainer.addChild(closeBtn);
var closeBtnText = new Text2('X', {
size: 60,
fill: '#ffffff'
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeBtnText);
closeBtn.down = function () {
closeModal();
LK.getSound('ui_click').play();
};
// Contenedor dinámico que se refresca
var contentContainer = new Container();
modalContainer.addChild(contentContainer);
function renderGalleryContent() {
while (contentContainer.children.length > 0) {
contentContainer.children[0].destroy();
}
var totalItems = galleryDisplayOrder.length;
var totalPages = Math.ceil(totalItems / galleryState.itemsPerPage);
var startIndex = galleryState.currentPage * galleryState.itemsPerPage;
var endIndex = Math.min(startIndex + galleryState.itemsPerPage, totalItems);
// --- PANEL IZQUIERDO: CUADRÍCULA 3x3 ---
var gridStartX = -750;
var gridStartY = -700;
var spacing = 400;
for (var i = startIndex; i < endIndex; i++) {
var localIndex = i - startIndex;
var col = localIndex % 3;
var row = Math.floor(localIndex / 3);
// AHORA BUSCAMOS EL ID BASADO EN EL NUEVO ORDEN
var actualCharId = galleryDisplayOrder[i];
var charData = characterDatabase[actualCharId];
var isCollected = gameState.collectedCharacters[actualCharId];
var displayChar = new Character();
var displayName = isCollected ? charData.name : "???";
// Siempre revelamos la rareza (Spoiler visual)
var displayRarity = charData.rarity;
displayChar.init(actualCharId, displayName, displayRarity, charData.asset, charData.multiplier);
displayChar.x = gridStartX + col * spacing;
displayChar.y = gridStartY + row * (spacing * 1.2);
// Efecto Silueta Inteligente
if (!isCollected) {
displayChar.graphicObj.tint = 0x000000; // Personaje en negro
displayChar.nameObj.fill = '#555555'; // Letras del nombre en gris
displayChar.frameObj.alpha = 0.05; // Apagamos casi todo el brillo del marco
}
// Indicador visual de elemento seleccionado
if (galleryState.selectedElementId === actualCharId) {
displayChar.scale.set(1.15, 1.15); // Ligeramente más grande al seleccionarlo
}
(function (idToSelect) {
displayChar.down = function () {
if (galleryState.selectedElementId !== idToSelect) {
galleryState.selectedElementId = idToSelect;
LK.getSound('ui_click').play();
renderGalleryContent();
}
};
})(actualCharId);
contentContainer.addChild(displayChar);
}
var pageText = new Text2('Page ' + (galleryState.currentPage + 1) + ' / ' + totalPages, {
size: 80,
fill: '#FFFFFF'
});
pageText.anchor.set(0.5, 0.5);
pageText.x = -300;
pageText.y = 800;
contentContainer.addChild(pageText);
var collectionStatus = new Text2('Collected: ' + gameState.totalCharactersCollected + '/41', {
size: 60,
fill: '#87CEEB'
});
collectionStatus.anchor.set(0.5, 0.5);
collectionStatus.x = -300;
collectionStatus.y = 900;
contentContainer.addChild(collectionStatus);
if (galleryState.currentPage > 0) {
var prevBtn = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
prevBtn.scale.set(0.6, 0.8);
prevBtn.x = -550;
prevBtn.y = 650;
var prevTxt = new Text2('< PREV', {
size: 70,
fill: '#FFF'
});
prevTxt.anchor.set(0.5, 0.5);
prevBtn.addChild(prevTxt);
prevBtn.down = function () {
galleryState.currentPage--;
LK.getSound('ui_click').play();
renderGalleryContent();
};
contentContainer.addChild(prevBtn);
}
if (galleryState.currentPage < totalPages - 1) {
var nextBtn = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
nextBtn.scale.set(0.6, 0.8);
nextBtn.x = -50;
nextBtn.y = 650;
var nextTxt = new Text2('NEXT >', {
size: 70,
fill: '#FFF'
});
nextTxt.anchor.set(0.5, 0.5);
nextBtn.addChild(nextTxt);
nextBtn.down = function () {
galleryState.currentPage++;
LK.getSound('ui_click').play();
renderGalleryContent();
};
contentContainer.addChild(nextBtn);
}
// --- PANEL DERECHO: DETALLES Y EQUIPAR ---
var rightPanelX = 550;
var detailData = characterDatabase[galleryState.selectedElementId];
var isDetailCollected = gameState.collectedCharacters[galleryState.selectedElementId];
if (detailData) {
var bigGraphic = LK.getAsset(detailData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
bigGraphic.scale.set(1.35, 1.35);
bigGraphic.x = rightPanelX;
bigGraphic.y = -250;
if (!isDetailCollected) {
bigGraphic.tint = 0x000000;
}
contentContainer.addChild(bigGraphic);
var detailNameText = isDetailCollected ? detailData.name : "???";
var detailName = new Text2(detailNameText, {
size: 80,
fill: '#FFF'
});
detailName.anchor.set(0.5, 0);
detailName.x = rightPanelX;
detailName.y = 200;
contentContainer.addChild(detailName);
// Mapa de colores String para la UI de detalles
var uiColors = {
'Common': '#FFFFFF',
'Uncommon': '#00FF00',
'Rare': '#00BFFF',
'Ultra-Rare': '#8A2BE2',
'Special': '#FF1493',
'Legendary': '#FFD700',
'Unique': '#FF0000'
};
var rarityColorHexStr = uiColors[detailData.rarity] || '#FFFFFF';
var detailRarity = new Text2('[' + detailData.rarity + ']', {
size: 60,
fill: rarityColorHexStr
});
detailRarity.anchor.set(0.5, 0);
detailRarity.x = rightPanelX;
detailRarity.y = 280;
contentContainer.addChild(detailRarity);
if (isDetailCollected) {
var incomeInfo = new Text2('Income Boost: +' + detailData.multiplier + '/tick', {
size: 55,
fill: '#00FF00'
});
incomeInfo.anchor.set(0.5, 0);
incomeInfo.x = rightPanelX;
incomeInfo.y = 350;
contentContainer.addChild(incomeInfo);
}
// LÓGICA DEL BOTÓN EQUIPAR
var orbitStatusText = new Text2('Orbiting: ' + gameState.equippedCharacters.length + ' / ' + GAME_CONFIG.MAX_EQUIPPED, {
size: 60,
fill: '#87CEEB'
});
orbitStatusText.anchor.set(0.5, 0);
orbitStatusText.x = rightPanelX;
orbitStatusText.y = 450;
contentContainer.addChild(orbitStatusText);
if (isDetailCollected) {
var isEquipped = gameState.equippedCharacters.indexOf(galleryState.selectedElementId) > -1;
var equipBtnGraphic = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
equipBtnGraphic.scale.set(1.5, 1.2);
equipBtnGraphic.tint = isEquipped ? 0xFF4444 : 0x32CD32;
var equipBtn = new Container();
equipBtn.addChild(equipBtnGraphic);
equipBtn.x = rightPanelX;
equipBtn.y = 650;
var equipBtnText = new Text2(isEquipped ? 'UNEQUIP' : 'EQUIP', {
size: 50,
fill: '#ffffff'
});
equipBtnText.anchor.set(0.5, 0.5);
equipBtn.addChild(equipBtnText);
equipBtn.down = function () {
if (isEquipped) {
var index = gameState.equippedCharacters.indexOf(galleryState.selectedElementId);
gameState.equippedCharacters.splice(index, 1);
} else {
if (gameState.equippedCharacters.length >= GAME_CONFIG.MAX_EQUIPPED) {
gameState.equippedCharacters.shift();
}
gameState.equippedCharacters.push(galleryState.selectedElementId);
}
updateEquippedDisplay();
saveGame();
LK.getSound('ui_click').play();
renderGalleryContent();
};
contentContainer.addChild(equipBtn);
} else {
var lockText = new Text2('LOCKED', {
size: 50,
fill: '#FF4444'
});
lockText.anchor.set(0.5, 0.5);
lockText.x = rightPanelX;
lockText.y = 400;
contentContainer.addChild(lockText);
}
}
}
renderGalleryContent();
game.addChild(modalContainer);
}
function closeModal() {
if (modalContainer) {
modalContainer.destroy();
modalOpen = false;
}
}
function performGachaPull() {
var currentCost = getGachaCost();
if (gameState.credits < currentCost) {
return;
}
gameState.credits -= currentCost;
gameState.pityCounter++; // Incrementamos el contador al tirar
var roll = Math.random() * 100;
var selectedRarity = null;
// VERIFICACIÓN DEL PITY SYSTEM
if (gameState.pityCounter >= 10) {
// Tirada garantizada (60% Special, 30% Legendary, 10% Unique)
var pityRoll = Math.random() * 100;
if (pityRoll <= 60) {
selectedRarity = {
rarity: 'Special',
ids: [31, 32, 33, 34, 35, 36]
};
} else if (pityRoll <= 90) {
selectedRarity = {
rarity: 'Legendary',
ids: [23, 24, 25, 26, 27]
};
} else {
selectedRarity = {
rarity: 'Unique',
ids: [28, 29, 30]
};
}
gameState.pityCounter = 0; // Reiniciamos el pity después de usarlo
} else {
// Tirada Normal
var cumulativeChance = 0;
for (var i = 0; i < dropRates.length; i++) {
cumulativeChance += dropRates[i].chance;
if (roll <= cumulativeChance) {
selectedRarity = dropRates[i];
break;
}
}
// Si en la tirada normal obtuviste una rareza alta, el pity se reinicia
if (selectedRarity.rarity === 'Special' || selectedRarity.rarity === 'Legendary' || selectedRarity.rarity === 'Unique') {
gameState.pityCounter = 0;
}
}
var characterIdArray = selectedRarity.ids;
var selectedCharacterId = characterIdArray[Math.floor(Math.random() * characterIdArray.length)];
var wasNew = false;
var charData = characterDatabase[selectedCharacterId];
if (!gameState.collectedCharacters[selectedCharacterId]) {
gameState.collectedCharacters[selectedCharacterId] = true;
gameState.totalCharactersCollected++;
wasNew = true;
gameState.incomePerTick += charData.multiplier;
}
saveGame();
LK.getSound('gacha_pull').play();
var rarityEffects = {
'Common': {
color: 0xFFFFFF,
scale: 1
},
'Uncommon': {
color: 0x00FF00,
scale: 1
},
'Rare': {
color: 0x00BFFF,
scale: 1
},
'Ultra-Rare': {
color: 0x8A2BE2,
scale: 1
},
'Legendary': {
color: 0xFFD700,
scale: 1
},
'Unique': {
color: 0xFF0000,
scale: 1.0
},
'Special': {
color: 0xFF1493,
scale: 1
}
};
var currentEffect = rarityEffects[charData.rarity] || {
color: 0xFFFFFF,
scale: 0.70
};
var resultMessage = wasNew ? 'NEW: ' + charData.name + '!' : 'Duplicate: ' + charData.name;
var resultColor = wasNew ? '#2d633b' : '#b89e14';
var resultContainer = new Container();
var resultBg = LK.getAsset('pull_bg', {
anchorX: 0.5,
anchorY: 0.5
});
resultContainer.addChild(resultBg);
resultContainer.x = 1024;
resultContainer.y = 1366;
resultContainer.scale.set(0.1, 0.1);
tween(resultContainer, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
var aura = LK.getAsset('core_crystal', {
anchorX: 0.5,
anchorY: 0.5
});
aura.tint = currentEffect.color;
var auraScaleFactor = currentEffect.scale * 2.5;
aura.scale.set(auraScaleFactor, auraScaleFactor);
aura.alpha = 0.5;
resultContainer.addChild(aura);
tween(aura, {
rotation: Math.PI * 2
}, {
duration: 2000
});
var resultGraphic = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
var scaleTarget = currentEffect.scale;
resultGraphic.scale.set(0.1, 0.1);
tween(resultGraphic, {
scaleX: scaleTarget + 0.05,
scaleY: scaleTarget + 0.05
}, {
duration: 250,
onFinish: function onFinish() {
tween(resultGraphic, {
scaleX: scaleTarget,
scaleY: scaleTarget
}, {
duration: 150
});
}
});
resultGraphic.y = 0;
resultContainer.addChild(resultGraphic);
var safePadding = 720 * scaleTarget / 2 + 80;
var resultTitle = new Text2(resultMessage, {
size: 150,
fill: resultColor
});
resultTitle.anchor.set(0.5, 0.5);
resultTitle.y = -safePadding;
resultContainer.addChild(resultTitle);
var resultRarity = new Text2('[' + charData.rarity + ']', {
size: 90,
fill: '#191919'
});
resultRarity.anchor.set(0.5, 0.5);
resultRarity.y = safePadding;
resultContainer.addChild(resultRarity);
game.addChild(resultContainer);
LK.setTimeout(function () {
tween(resultContainer, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
resultContainer.destroy();
}
});
}, 2000);
}
function performGachaPull10() {
var singleCost = getGachaCost();
var totalCost = singleCost * 10;
if (gameState.credits < totalCost) {
return;
}
gameState.credits -= totalCost;
var pullResults = [];
// 1. Las 9 tiradas normales
for (var i = 0; i < 9; i++) {
var roll = Math.random() * 100;
var selectedRarity = null;
var cumulativeChance = 0;
for (var j = 0; j < dropRates.length; j++) {
cumulativeChance += dropRates[j].chance;
if (roll <= cumulativeChance) {
selectedRarity = dropRates[j];
break;
}
}
var charIdArray = selectedRarity.ids;
var selectedCharId = charIdArray[Math.floor(Math.random() * charIdArray.length)];
pullResults.push(characterDatabase[selectedCharId]);
if (!gameState.collectedCharacters[selectedCharId]) {
gameState.collectedCharacters[selectedCharId] = true;
gameState.totalCharactersCollected++;
gameState.incomePerTick += characterDatabase[selectedCharId].multiplier;
}
}
// 2. La 10ª tirada (Lástima Garantizada)
var pityRoll = Math.random() * 100;
var pityRarity = null;
// (Asegúrate de haber añadido los IDs de tus 8 nuevos personajes en los arreglos correspondientes)
if (pityRoll <= 60) {
pityRarity = {
rarity: 'Special',
ids: [31, 32, 33, 34, 35, 36]
};
} else if (pityRoll <= 90) {
pityRarity = {
rarity: 'Legendary',
ids: [23, 24, 25, 26, 27]
};
} else {
pityRarity = {
rarity: 'Unique',
ids: [28, 29, 30]
};
}
var pityCharIdArray = pityRarity.ids;
var pityCharId = pityCharIdArray[Math.floor(Math.random() * pityCharIdArray.length)];
pullResults.push(characterDatabase[pityCharId]);
if (!gameState.collectedCharacters[pityCharId]) {
gameState.collectedCharacters[pityCharId] = true;
gameState.totalCharactersCollected++;
gameState.incomePerTick += characterDatabase[pityCharId].multiplier;
}
// Reiniciamos el pity porque acabamos de dar uno garantizado
gameState.pityCounter = 0;
saveGame();
LK.getSound('gacha_pull').play();
showMultiPullResults(pullResults);
}
function showMultiPullResults(results) {
modalOpen = true; // Bloquea la UI de fondo
var resultContainer = new Container();
var modalBg = LK.getAsset('modal_bg', {
anchorX: 0.5,
anchorY: 0.5
});
resultContainer.addChild(modalBg);
resultContainer.x = 1024;
resultContainer.y = 1366;
resultContainer.scale.set(0.1, 0.1);
tween(resultContainer, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
var titleText = new Text2('10x PULL RESULTS', {
size: 100,
fill: '#FFD700'
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -900;
resultContainer.addChild(titleText);
// Configuramos la cuadrícula (2 filas x 5 columnas)
var startX = -600;
var startY = -400;
var spacingX = 300;
var spacingY = 400;
for (var i = 0; i < results.length; i++) {
var charData = results[i];
var col = i % 5;
var row = Math.floor(i / 5);
// Si es de rareza alta, le ponemos un aura detrás
if (charData.rarity === 'Special' || charData.rarity === 'Legendary' || charData.rarity === 'Unique') {
var aura = LK.getAsset('core_crystal', {
anchorX: 0.5,
anchorY: 0.5
});
aura.x = startX + col * spacingX;
aura.y = startY + row * spacingY;
aura.scale.set(1.5, 1.5);
aura.tint = 0xFFD700;
aura.alpha = 0.5;
resultContainer.addChild(aura);
tween(aura, {
rotation: Math.PI * 2
}, {
duration: 2000
});
}
var charGraphic = LK.getAsset(charData.asset, {
anchorX: 0.5,
anchorY: 0.5
});
charGraphic.x = startX + col * spacingX;
charGraphic.y = startY + row * spacingY;
charGraphic.scale.set(0.35, 0.35); // Más pequeños para que quepan
resultContainer.addChild(charGraphic);
}
// Botón para cerrar
var closeBtnGraphic = LK.getAsset('button_bg', {
anchorX: 0.5,
anchorY: 0.5
});
var closeBtn = new Container();
closeBtn.addChild(closeBtnGraphic);
closeBtn.y = 800;
resultContainer.addChild(closeBtn);
var closeText = new Text2('CONTINUE', {
size: 60,
fill: '#FFFFFF'
});
closeText.anchor.set(0.5, 0.5);
closeBtn.addChild(closeText);
closeBtn.down = function () {
LK.getSound('ui_click').play();
tween(resultContainer, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
resultContainer.destroy();
modalOpen = false; // Liberamos la UI
}
});
};
game.addChild(resultContainer);
}
function upgradeIncomeLevel(levelIndex) {
var level = levelContainers[levelIndex];
if (gameState.credits >= level.currentCost) {
gameState.credits -= level.currentCost;
gameState.incomeLevels[levelIndex]++;
gameState.incomePerTick += level.baseIncome;
level.updateData(gameState.incomeLevels[levelIndex]);
saveGame();
LK.getSound('level_up').play();
}
}
// --- Event Handlers Directos ---
gachaButton.down = function () {
if (modalOpen) {
return;
}
if (gachaEnabled) {
performGachaPull();
LK.getSound('ui_click').play();
}
};
gacha10Button.down = function () {
if (modalOpen) {
return;
}
if (gacha10Enabled) {
performGachaPull10();
}
};
galleryButton.down = function () {
if (modalOpen) {
return;
}
openGallery();
LK.getSound('ui_click').play();
};
/*
debugButton.down = function () {
if (modalOpen) {
return;
}
gameState.credits = 0;
gameState.incomePerTick = 1;
gameState.collectedCharacters = {};
gameState.totalCharactersCollected = 0;
gameState.incomeLevels = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
gameState.equippedCharacters = [];
for (var i = 0; i < levelContainers.length; i++) {
levelContainers[i].updateData(0);
}
updateEquippedDisplay();
saveGame();
LK.getSound('ui_click').play();
};
*/
coreButton.down = function () {
if (modalOpen) {
return;
}
var clickGain = 1 + Math.floor(gameState.incomePerTick * 0.2);
gameState.credits += clickGain;
// El texto flotante ahora sigue dinámicamente al nuevo centro del botón (X: 1536, Y: 1366)
var floatText = new FloatingText('+' + clickGain, coreButton.x + (Math.random() * 100 - 50), coreButton.y - 150, '#00ffff');
game.addChild(floatText);
tween(coreGraphic, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 50,
onFinish: function onFinish() {
tween(coreGraphic, {
scaleX: 1,
scaleY: 1
}, {
duration: 50
});
}
});
};
for (var i = 0; i < levelContainers.length; i++) {
(function (index) {
levelContainers[index].down = function () {
if (modalOpen) {
return;
}
upgradeIncomeLevel(index);
};
})(i);
}
// --- Variables para el Main Loop ---
var pulseTimer = 0;
var lastDisplayedCredits = -1;
var lastDisplayedIncome = -1;
var lastDisplayedCollection = -1;
var lastDisplayedGachaCost = -1;
var lastDisplayedPity = -1;
// --- Main Game Loop Optimizado ---
game.update = function () {
gameState.tickCounter++;
// LÓGICA DE ÓRBITA
var numOrbiting = orbitingSprites.length;
if (numOrbiting > 0) {
orbitAngle += GAME_CONFIG.ORBIT_SPEED;
var angleStep = Math.PI * 2 / numOrbiting;
for (var o = 0; o < numOrbiting; o++) {
var currentAngle = orbitAngle + o * angleStep;
orbitingSprites[o].x = Math.cos(currentAngle) * GAME_CONFIG.ORBIT_RADIUS;
orbitingSprites[o].y = Math.sin(currentAngle) * GAME_CONFIG.ORBIT_RADIUS;
//orbitingSprites[o].rotation += 0.01;
}
}
if (gameState.tickCounter % GAME_CONFIG.FPS === 0) {
gameState.credits += gameState.incomePerTick;
}
// --- Actualización de Costos y Textos ---
var currentCredits = Math.floor(gameState.credits);
var currentGachaCost = getGachaCost();
var currentGachaCost10 = currentGachaCost * 10;
// === INICIO DEL BLOQUE FALTANTE ===
if (currentCredits !== lastDisplayedCredits) {
creditsText.setText('Credits: ' + currentCredits);
lastDisplayedCredits = currentCredits;
}
if (gameState.incomePerTick !== lastDisplayedIncome) {
incomeText.setText('Income: ' + gameState.incomePerTick + '/tick');
lastDisplayedIncome = gameState.incomePerTick;
}
if (gameState.totalCharactersCollected !== lastDisplayedCollection) {
// Usamos characterDatabase.length para que se actualice solo si agregas más en el futuro
collectionText.setText('Collection: ' + gameState.totalCharactersCollected + '/' + characterDatabase.length);
lastDisplayedCollection = gameState.totalCharactersCollected;
}
if (currentGachaCost !== lastDisplayedGachaCost || gameState.pityCounter !== lastDisplayedPity) {
// Actualiza textos Botón x1
gachaText.setText('PULL (' + currentGachaCost + ')');
if (gameState.pityCounter >= 9) {
pityText.setText('Pity: READY!');
pityText.fill = '#00FF00';
} else {
pityText.setText('Pity: ' + gameState.pityCounter + '/10');
pityText.fill = '#FFD700';
}
// Actualiza textos Botón x10
gacha10Text.setText('10x (' + currentGachaCost10 + ')');
lastDisplayedGachaCost = currentGachaCost;
lastDisplayedPity = gameState.pityCounter;
}
// --- Control Visual de Botones Disponibles ---
gachaEnabled = gameState.credits >= currentGachaCost;
gacha10Enabled = gameState.credits >= currentGachaCost10;
// Efectos del Botón x1
if (gachaEnabled) {
gachaBtnGraphic.tint = 0xFF1493;
gachaText.tint = 0xFFFFFF;
pulseTimer += 0.05;
var scaleX = 1.6 + Math.sin(pulseTimer) * 0.05;
var scaleY = 1.8 + Math.sin(pulseTimer) * 0.05;
gachaBtnGraphic.scale.set(scaleX, scaleY);
} else {
gachaBtnGraphic.tint = 0x883366;
gachaText.tint = 0xAAAAAA;
gachaBtnGraphic.scale.set(1.6, 1.8);
}
// Efectos del Botón x10
if (gacha10Enabled) {
gacha10BtnGraphic.tint = 0xFF1493;
gacha10Text.tint = 0xFFFFFF;
var scaleX10 = 1.6 + Math.cos(pulseTimer) * 0.05; // Usamos cos para desfasar el pulso visual
var scaleY10 = 1.8 + Math.cos(pulseTimer) * 0.05;
gacha10BtnGraphic.scale.set(scaleX10, scaleY10);
} else {
gacha10BtnGraphic.tint = 0x883366;
gacha10Text.tint = 0xAAAAAA;
gacha10BtnGraphic.scale.set(1.6, 1.8);
}
for (var j = 0; j < levelContainers.length; j++) {
var level = levelContainers[j];
if (gameState.credits >= level.currentCost) {
level.children[0].tint = 0xffffff;
} else {
level.children[0].tint = 0x525252;
}
}
if (gameState.tickCounter % GAME_CONFIG.SAVE_INTERVAL === 0) {
saveGame();
}
};
Crea un rectángulo para asset de botón. Debe ser: color amarillo, rojo, verde, azul, gris, rosa dispuestos en forma diagonal irregular por el rectángulo. Los colores deben ser planos, y los bordes redondeados. In-Game asset. 2d. High contrast. No shadows. anime. simple
Crea un rectángulo para asset de botón. Debe ser: color rojo escarlata con borde en forma de rectángulo. Los colores deben ser planos, y los bordes redondeados. In-Game asset. 2d. High contrast. No shadows. anime. simple
Crea un rectángulo para asset de botón. Debe ser: color verde esmeralda con borde en forma de rectángulo. Los colores deben ser planos, y los bordes redondeados. In-Game asset. 2d. High contrast. No shadows. anime. simple
Crea un fondo de textura verde tipo anime. In-Game asset. 2d. High contrast. No shadows. Background. anime