User prompt
Please fix the bug: 'Timeout.tick error: Cannot read properties of null (reading 'setProgress')' in or related to this line: 'progressDisplay.setProgress(currentQuestion, questionsPerRound);' Line Number: 1318
User prompt
esta todo bug
User prompt
🎮 TÍTULO DEL MODO: Forja de Leyendas Un viaje interactivo por el universo de Destiny 2 donde los conocimientos se convierten en armas, y las decisiones marcan el destino de tu Guardián. 🧱 VISIÓN GENERAL "Forja de Leyendas" es una campaña por niveles dividida en sectores narrativos. Cada nivel es un enfrentamiento táctico que combina: Preguntas de trivia tematizadas (lore, armas, personajes, eventos) Mecánicas RPG ligeras (clase, vida, energía) Decisiones estratégicas (elegir ruta, gastar energía, usar habilidades) Tu progreso se guarda, y puedes repetir niveles para subir puntuación, mejorar tu Guardian, o desbloquear rutas alternativas. 🌌 ESTRUCTURA PRINCIPAL ➤ 5 SECTORES — CAMPAÑA PRINCIPAL Cada sector es una zona narrativa inspirada en el universo de Destiny, con ambientación, enemigos y trivia única. Sector Tema central Enemigos Trivia 1. ZME (Zona Muerta) Primer contacto Caídos Básicos de Destiny 2 2. Marte Rojo Dominio militar Cabal NPCs, armas, historia bélica 3. Mundo Trono Corrupción y engaño Hive Savathûn, colmena, lore oscuro 4. Red Vex Simulación y paradoja Vex Misiones, lógica, fractales 5. Apoteosis Luz vs Oscuridad final Combinados Filosofía, Unveiling, Final Shape Cada sector tiene 5 niveles, con progresión creciente. 🧠 ESTRUCTURA DE NIVEL ▶ Nivel tipo: Nombre del nivel Narración introductoria (puede ser texto o voz) Enemigo con mecánicas especiales 5 preguntas (de dificultad progresiva) Resultado basado en respuestas (ataque, defensa, energía, etc.) ▶ Mecánicas ✅ Aciertas → Atacas o activas habilidad ❌ Fallas → Recibes daño o efectos negativos ⚡ Energía: se acumula con respuestas buenas, se gasta en habilidades especiales ❤️ Vidas: pierdes una con cada error; a 0 = reinicio del nivel ⚔️ EJEMPLO DETALLADO DE UN NIVEL 🌑 Sector 3: Mundo Trono Nivel 2 - "El Eco de Savathûn" Historia breve: Te adentras en los secretos del trono de Savathûn. Las ilusiones son fuertes. Solo el conocimiento puede atravesarlas. Enemigo: Acolyte Fantasma HP: 3 Habilidad: si fallas dos preguntas, se regenera 1 vida Preguntas: ¿Qué le ofreció la Luz a Savathûn? ¿Quién es Immaru? ¿Qué arma exótica se relaciona con su historia? ¿Qué hizo Mara Sov para traerla de vuelta? ¿Qué dijo la colmena sobre la Verdad oculta? Resultados: Si aciertas 4+, pasas y desbloqueas la siguiente misión. Si aciertas todas, desbloqueas una entrada del grimorio secreto. Si fallas 3+, reinicias el nivel y pierdes un intento. 🧬 EVOLUCIÓN DEL GUARDIÁN El jugador tiene un perfil de Guardián con: ⭐ Nivel (sube con EXP por nivel) 💠 Clase (Titan, Hunter, Warlock — elige una al principio) ⚙️ Habilidades desbloqueables (ej: "Curarse al acertar 3 seguidas") 📚 Recompensas cosméticas (avatares, emblemas) 🔄 RUTAS RAMIFICADAS Al terminar ciertos niveles, puedes: Elegir entre dos caminos (difícil/fácil) Desbloquear un atajo si respondiste rápido Iniciar niveles de evento raro (preguntas trampa, narrativa oculta, lore profundo) 🧩 MODO DESAFÍO: “Realidad Fracturada” Se desbloquea tras completar los 5 sectores: Todos los enemigos combinados Preguntas sin opciones (escribes la respuesta) Límite de tiempo para cada turno Solo una vida Recompensa final: “Leyenda Eterna” 💡 VENTAJAS DE ESTE SISTEMA Mantiene el núcleo de trivia, pero lo hace emocionante y significativo. Introduce progresión, historia y conexión emocional con Destiny. Tiene espacio para rejugabilidad, desbloqueos, decisiones. Perfecto para contenido episódico o expansiones. es para el rpg esta idea ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
User prompt
cuando me hace daño no me baja la vida y cuando acierto tampoco le bajo la vida
User prompt
agregue un sonido llamado damage y quiero que este en el modo rpg que cuando de una incorrecta como recibe dano de oponentes cuando le baja vida que suene ese sonido
User prompt
IDEA NUEVA: “Forja de Leyendas” – Trivia con mecánicas de rol táctico Concepto general Un juego que mezcla preguntas de trivia con combate táctico por turnos, donde las respuestas correctas “atacan” o “defienden” a tu Guardián en batallas contra enemigos icónicos de Destiny 2. No es solo responder, sino usar la trivia para ganar ventaja en peleas estratégicas. Mecánicas centrales 1. Batallas por turnos basadas en trivia En cada turno, para atacar o defender debes responder una pregunta. Respuesta correcta = ataque exitoso o defensa reforzada. Respuesta incorrecta = enemigo ataca o tu defensa se debilita. 2. Clases y habilidades del Guardián Elige entre Titan, Hunter o Warlock. Cada clase tiene habilidades especiales que puedes activar respondiendo preguntas “de habilidad” (por ejemplo, preguntas de dificultad extra o retos). Habilidades: Titan: escudo extra que absorbe daño. Hunter: doble ataque si responde dos preguntas seguidas bien. Warlock: cura o daño en área. 3. Enemigos con patrones y debilidades Cada enemigo tiene un patrón de ataque y puntos débiles que se revelan parcialmente con las preguntas. Preguntas temáticas según enemigo (Ejemplo: Cabal, Hive, Vex). Responder preguntas correctas explota debilidades, aumentando el daño. 4. Sistema de energía y recursos Responder bien genera energía para activar habilidades especiales o combos. Responder mal consume energía o hace que pierdas vida. 5. Modo campaña progresivo Avanzas por diferentes misiones con enemigos y preguntas específicas. Cada misión con dificultad creciente y enemigos más fuertes. Dinámica de juego Inicias con tu Guardián y enfrentas un enemigo. Turno 1: te hacen una pregunta, respondes. Si aciertas, atacas y haces daño. Si fallas, el enemigo ataca y te quita vida. Al ganar, recibes puntos y mejoras (mejor equipo, habilidades). Puedes elegir mejorar estadísticas o habilidades según las respuestas que des. ¿Qué hace único a este juego? Combina trivia con estrategia y RPG táctico, no es solo preguntas y respuestas. La trivia afecta directamente la batalla y estrategia. Las clases ofrecen estilos de juego diferentes. Preguntas adaptadas a enemigos y situaciones, enriqueciendo la experiencia. Desafíos tácticos: decidir cuándo usar habilidades, cuándo arriesgarse con preguntas difíciles. Ejemplo de una ronda Entras a combate contra un Cabal Coloso. Pregunta: “¿Cuál es la principal fortaleza del Cabal?” Opciones. Respondes correctamente. Tu Titan activa escudo y ataca. El Coloso pierde vida. Enemigo contraataca. Turno siguiente, te preguntan sobre armas exóticas para Hunter. Si fallas, recibes daño extra. Si aciertas, tu Hunter lanza doble ataque. quiero que hagas una seccion que dice. que quieres jugar? trivia o Forja de Leyendas” – Trivia con mecánicas de rol táctico
User prompt
Nivel 1 (Rodri) ¿Qué vendedor maneja Trials of Osiris? Opciones: Lord Shaxx, Saint-14, Osiris, The Drifter Correcta marcada: Saint-14 Corrección: El vendedor correcto es Osiris. ¿Qué moneda reemplazó Legendary Shards? Opciones: Enhancement Cores, Glimmer only, Bright Dust, Strange Coins Correcta marcada: Bright Dust Corrección: Legendary Shards no fue reemplazado por Bright Dust; Legendary Shards sigue vigente para mejoras. Esta pregunta es confusa o incorrecta. Nivel 2 (Diego) ¿Cómo se llama el pollo de Cayde-6? Opciones: Ace, Colonel, General, Captain Correcta marcada: Colonel Corrección: El pollo se llama Ace. ¿Quién fue el dueño original de Whisper of the Worm? Opciones: Oryx, Xol, Nokris, Savathûn Correcta marcada: Xol Corrección: Mejor respuesta sería Oryx (el arma está relacionada con él en la historia). ¿Qué conecta el Jardín Negro con la red Vex? Opciones: The Black Heart, Sol Divisive, Quria, The Undying Mind Correcta marcada: Sol Divisive Corrección: "Sol Divisive" no es término canon; conexiones conocidas son Quria o The Undying Mind.
Code edit (1 edits merged)
Please save this source code
User prompt
quiero que pongas timer para responder cada pregunta de 60s y que pongas cuando falta
User prompt
pon 60s de time para responder cada pregunta quiero que pongas cuando tiempo falta
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'setOption')' in or related to this line: 'optionButtons[i].setOption(questionData.options[originalIndex], originalIndex, originalIndex === questionData.correct);' Line Number: 655
User prompt
podrias mejorar el codigo y mirar todo eso que te dije
User prompt
en dificultad diego 8/10 son abajo a la izquierda del cuadrado en todas las dificultades hazlo random
User prompt
porque muchas respuestas son de abajo a la izquierda de ese cuadrado quiero que sea random y no este fijo porque de 6/10 ahi esta
User prompt
quiero clickear una y hace otra y siempre es la correcta mira todos los bugs y analiza
User prompt
al aparecer de 8/10 la respuesta es la de abajo a la derecha quiero que sea al azar donde aparezca arriba derecha izquierda pero no donde mismo y es asi en todas las dificultsddes
User prompt
quiero que cambies los nombrs de las dificultades, el primero que se llame Javi segundo Rodri, tercero Diego y ultimo que se llame Nadie la sabe
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var MenuButton = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('optionButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.buttonText = new Text2('', {
size: 48,
fill: 0xFFFFFF
});
self.buttonText.anchor.set(0.5, 0.5);
self.addChild(self.buttonText);
self.difficulty = 0;
self.setButton = function (text, difficulty) {
self.buttonText.setText(text);
self.difficulty = difficulty;
};
self.down = function (x, y, obj) {
if (inMenu) {
startGameWithDifficulty(self.difficulty);
}
};
return self;
});
var OptionButton = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('optionButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.optionText = new Text2('', {
size: 36,
fill: 0xFFFFFF
});
self.optionText.anchor.set(0.5, 0.5);
self.addChild(self.optionText);
self.correctIndicator = null;
self.wrongIndicator = null;
self.isCorrect = false;
self.index = 0;
self.buttonPosition = 0;
self.setOption = function (text, index, isCorrect) {
self.optionText.setText(text);
self.index = index;
self.isCorrect = isCorrect;
};
self.showResult = function (correct) {
if (correct) {
self.correctIndicator = self.attachAsset('correctIndicator', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
} else {
self.wrongIndicator = self.attachAsset('wrongIndicator', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
}
};
self.down = function (x, y, obj) {
if (!canAnswer) {
return;
}
checkAnswer(self.buttonPosition);
};
return self;
});
var ProgressDisplay = Container.expand(function () {
var self = Container.call(this);
var barBg = self.attachAsset('progressBar', {
anchorX: 0,
anchorY: 0.5
});
self.progressFill = self.attachAsset('progressFill', {
anchorX: 0,
anchorY: 0.5,
scaleX: 0
});
self.progressText = new Text2('Question 1/10', {
size: 32,
fill: 0xFFFFFF
});
self.progressText.anchor.set(0.5, 0.5);
self.progressText.x = 800;
self.progressText.y = -40;
self.addChild(self.progressText);
self.setProgress = function (current, total) {
self.progressText.setText('Question ' + current + '/' + total);
var progress = current / total;
tween(self.progressFill, {
scaleX: progress
}, {
duration: 500,
easing: tween.easeOut
});
};
return self;
});
var QuestionDisplay = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('questionBg', {
anchorX: 0.5,
anchorY: 0.5
});
self.questionText = new Text2('', {
size: 48,
fill: 0xFFFFFF
});
self.questionText.anchor.set(0.5, 0.5);
self.addChild(self.questionText);
self.setQuestion = function (text) {
self.questionText.setText(text);
// Word wrap for long questions
self.questionText.wordWrap = true;
self.questionText.wordWrapWidth = 1600;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0a0f
});
/****
* Game Code
****/
// Constants
var ANIMATION_DURATION = {
SHORT: 500,
MEDIUM: 1000,
LONG: 1500,
EXTRA_LONG: 2000,
GAME_OVER_DELAY: 3000
};
var SCORE_BASE = [5, 10, 20, 40];
var UNLOCK_THRESHOLDS = {
GUARDIAN: 30,
DARKNESS: 50,
TIMER: 70,
WIN: 100
};
var TIMER_BASE = 3600; // 60 seconds in frames (60 FPS)
var TIMER_REDUCTION_PER_DIFFICULTY = 0; // No reduction per difficulty for 60s timer
var DIFFICULTY_COLORS = [0x5EB3FF, 0xFFD700, 0xFF6B6B, 0x9B59B6];
var timerDisplay = null; // Timer display text for all modes
// Game state variables
var currentPhase = 0; // 0: Javi, 1: Rodri, 2: Diego, 3: Nadie la sabe
var currentQuestion = 0;
var score = 0;
var lives = 3;
var questionsPerRound = 10;
var canAnswer = true;
var guardianMode = false;
var darknessMode = false;
var timerMode = false;
var timerCount = 0;
var timerStartTime = 0; // For real-time timer sync
var usedQuestions = []; // Track used questions to avoid repetition
var availableQuestionsPool = []; // Pool of available questions for current difficulty
var inMenu = true; // Track if we're in the menu
var selectedDifficulty = 0; // Selected starting difficulty
var questionDifficulty = 0; // Current question difficulty within phase
// UI Elements
var questionDisplay = null;
var optionButtons = [];
var progressDisplay = null;
var scoreText = null;
var phaseText = null;
var livesText = null;
var modeIndicator = null;
// Question Database - Updated for 02/07/2025 with progressive difficulty
var questions = {
0: [
// Javi - Basic knowledge, commonly played content
// Easy questions (0-3)
{
q: "What is the primary currency in Destiny 2?",
options: ["Glimmer", "Bright Dust", "Legendary Shards", "Silver"],
correct: 0,
difficulty: 0
}, {
q: "How many character classes exist in the game?",
options: ["2", "3", "4", "5"],
correct: 1,
difficulty: 0
}, {
q: "What element type is Solar associated with?",
options: ["Ice", "Lightning", "Fire", "Void"],
correct: 2,
difficulty: 0
}, {
q: "Which NPC serves as the Titan Vanguard?",
options: ["Ikora Rey", "Commander Zavala", "Lord Shaxx", "Saint-14"],
correct: 1,
difficulty: 1
}, {
q: "Where do Guardians primarily operate from?",
options: ["The Farm", "The Tower", "The Reef", "Europa"],
correct: 1,
difficulty: 1
}, {
q: "What is the name of your Ghost?",
options: ["Sundance", "Sagira", "Ghost", "Pulled Pork"],
correct: 2,
difficulty: 1
},
// Medium questions (4-7)
{
q: "Which activity rewards Pinnacle gear?",
options: ["Public Events", "Patrols", "Nightfalls", "Lost Sectors"],
correct: 2,
difficulty: 2
}, {
q: "What currency is used in Eververse?",
options: ["Glimmer", "Silver", "Legendary Shards", "Enhancement Cores"],
correct: 1,
difficulty: 2
}, {
q: "How many subclasses can each class use?",
options: ["3", "4", "5", "6"],
correct: 2,
difficulty: 2
},
// Harder questions (8-10)
{
q: "What is the weekly reset day?",
options: ["Monday", "Tuesday", "Wednesday", "Thursday"],
correct: 1,
difficulty: 3
}, {
q: "What power level is the soft cap?",
options: ["1750", "1800", "1810", "1830"],
correct: 2,
difficulty: 3
}, {
q: "Which raid was the first in Destiny 2?",
options: ["Leviathan", "Last Wish", "Garden of Salvation", "Deep Stone Crypt"],
correct: 0,
difficulty: 3
}],
1: [
// Rodri - Requires playing multiple seasons
{
q: "Which exotic hand cannon returned in Episode: Revenant?",
options: ["Hawkmoon", "Thorn", "The Last Word", "Eriana's Vow"],
correct: 1,
difficulty: 0
}, {
q: "What is the name of the Witness's ship seen in The Final Shape?",
options: ["The Monolith", "The Pyramid", "The Veil", "The Radial Mast"],
correct: 0,
difficulty: 1
}, {
q: "Which character became the new Hunter Vanguard?",
options: ["Crow", "Ana Bray", "Shiro-4", "No one yet"],
correct: 3,
difficulty: 1
}, {
q: "What exotic was craftable in Season of the Wish?",
options: ["Wish-Ender", "Dragon's Breath", "Whisper of the Worm", "Outbreak Perfected"],
correct: 1,
difficulty: 2
}, {
q: "Which vendor handles Trials of Osiris?",
options: ["Lord Shaxx", "Saint-14", "Osiris", "The Drifter"],
correct: 2,
difficulty: 0
}, {
q: "What is the main currency for weapon upgrades?",
options: ["Enhancement Cores", "Legendary Shards", "Bright Dust", "Strange Coins"],
correct: 1,
difficulty: 2
}, {
q: "Which raid features Nezarec as the final boss?",
options: ["Root of Nightmares", "King's Fall", "Vow of the Disciple", "Deep Stone Crypt"],
correct: 0,
difficulty: 3
}, {
q: "What is the max stat tier for abilities?",
options: ["10", "100", "12", "120"],
correct: 1,
difficulty: 3
}, {
q: "Which season introduced the Lightfall expansion?",
options: ["Season of Defiance", "Season of the Deep", "Season of the Witch", "Season of the Wish"],
correct: 0,
difficulty: 2
}, {
q: "What is the name of Strand's Titan super?",
options: ["Bladefury", "Needlestorm", "Silkstrike", "Threadrunner"],
correct: 0,
difficulty: 3
}],
2: [
// Diego - Deep lore, connections between seasons
{
q: "According to lore, who gave Savathûn her memories back?",
options: ["The Witness", "Immaru", "The Traveler", "Mara Sov"],
correct: 2,
difficulty: 0
}, {
q: "What is the name of Cayde-6's chicken?",
options: ["Ace", "Colonel", "General", "Captain"],
correct: 0,
difficulty: 0
}, {
q: "Which Disciple of the Witness created the Hive?",
options: ["Nezarec", "Rhulk", "Calus", "The Witness itself"],
correct: 1,
difficulty: 1
}, {
q: "What are the three queens Mara Sov refers to in her throne world?",
options: ["Past Present Future", "Light Dark Gray", "Savathûn Xivu Mara", "Birth Life Death"],
correct: 2,
difficulty: 1
}, {
q: "Which Hive Worm God is connected to the Whisper of the Worm?",
options: ["Oryx", "Xol", "Nokris", "Savathûn"],
correct: 1,
difficulty: 2
}, {
q: "What did the Witness seek within the Traveler?",
options: ["Power", "The Final Shape", "Salvation", "The Light"],
correct: 1,
difficulty: 2
}, {
q: "Which character's real name is Uldren Sov?",
options: ["The Drifter", "Crow", "Spider", "Variks"],
correct: 1,
difficulty: 3
}, {
q: "What connects the Black Garden to the Vex network?",
options: ["The Black Heart", "Sol Divisive", "Quria", "The Undying Mind"],
correct: 1,
difficulty: 3
}],
3: [
// Nadie la sabe - Cryptic connections, unexplained details
{
q: "Complete the prophecy: 'The line between Light and Dark is so very...'",
options: ["Blurred", "Thin", "Fragile", "Clear"],
correct: 1,
difficulty: 0
}, {
q: "What pattern appears in the symbols of the Nine?",
options: ["Circles within circles", "Triangular fractals", "Spiral convergence", "Unknown geometry"],
correct: 0,
difficulty: 0
}, {
q: "In the Books of Sorrow, what is the Sword Logic's ultimate goal?",
options: ["Survival", "The Final Shape", "Perfect existence", "Eternal war"],
correct: 1,
difficulty: 1
}, {
q: "What whispered truth did Savathûn hide in her throne world?",
options: ["The Witness lied", "The Traveler chose her", "Light needs Dark", "All of the above"],
correct: 3,
difficulty: 1
}, {
q: "According to Unveiling, what existed before Light and Dark?",
options: ["The Garden", "Nothing", "The Pattern", "Potential"],
correct: 0,
difficulty: 2
}, {
q: "What is the significance of 'O champion mine'?",
options: ["Ahamkara wish magic", "Vex simulation", "Hive curse", "Awoken blessing"],
correct: 0,
difficulty: 2
}, {
q: "What truth about the Collapse did Rasputin hide?",
options: ["He attacked the Traveler", "He made a deal", "He knew it would happen", "All records were destroyed"],
correct: 0,
difficulty: 3
}, {
q: "In Cayde's final message, what does Ace represent?",
options: ["His gun", "His son", "A memory", "All meanings"],
correct: 3,
difficulty: 3
}]
};
var phaseNames = ["Javi", "Rodri", "Diego", "Nadie la sabe"];
var rankNames = ["Light Bearer", "Disciple of Osiris", "Wisdom Devourer", "Archive Legend"];
// Campaign mode variables
var campaignMode = false;
var currentSector = 0;
var currentLevel = 0;
var guardianClass = 0; // 0: Titan, 1: Hunter, 2: Warlock
var guardianHealth = 100;
var guardianMaxHealth = 100;
var guardianEnergy = 3;
var guardianMaxEnergy = 3;
var guardianLevel = 1;
var guardianExp = 0;
var enemyHealth = 80;
var enemyMaxHealth = 80;
var currentEnemy = 0;
var battleTurn = 0; // 0: player turn, 1: enemy turn
var consecutiveCorrect = 0;
var shieldActive = false;
var hunterDoubleAttack = false;
// Campaign data structure
var sectors = [{
name: "Zona Muerta Europea",
theme: "Primer contacto",
enemyType: "Caídos",
color: 0x5EB3FF,
description: "Tu primer encuentro con las fuerzas de la Oscuridad",
levels: [{
name: "Despertar del Guardián",
narrative: "Despiertas en las ruinas congeladas de la Zona Muerta. Tu Ghost te guía hacia tu destino.",
enemy: {
name: "Dregs Menores",
health: 40,
damage: 10,
pattern: ["attack", "attack", "defend"]
},
questions: 3
}, {
name: "Primeros Pasos",
narrative: "Los Caídos patrullan estas tierras. Debes demostrar tu valía como Guardián.",
enemy: {
name: "Vandal Explorador",
health: 60,
damage: 15,
pattern: ["attack", "defend", "attack"]
},
questions: 4
}, {
name: "El Eco de la Luz",
narrative: "Una señal extraña resuena desde las profundidades. La Luz te llama.",
enemy: {
name: "Capitán Caído",
health: 80,
damage: 20,
pattern: ["defend", "attack", "special"]
},
questions: 5
}, {
name: "Senderos Helados",
narrative: "El frío de Europa no es solo clima. Algo más oscuro acecha entre las sombras.",
enemy: {
name: "Servitor Corrupto",
health: 90,
damage: 18,
pattern: ["special", "attack", "defend"]
},
questions: 5
}, {
name: "Guardián Forjado",
narrative: "Has demostrado tu valía. La Zona Muerta ya no te intimida.",
enemy: {
name: "Archonte Menor",
health: 120,
damage: 25,
pattern: ["attack", "special", "special"]
},
questions: 5
}]
}, {
name: "Marte Rojo",
theme: "Dominio militar",
enemyType: "Cabal",
color: 0xFF6B6B,
description: "El imperio Cabal y sus máquinas de guerra te esperan",
levels: [{
name: "Tierras Rojas",
narrative: "Marte se extiende ante ti, dominado por la maquinaria de guerra Cabal.",
enemy: {
name: "Legionario Cabal",
health: 100,
damage: 22,
pattern: ["attack", "attack", "defend"]
},
questions: 4
}, {
name: "Fortaleza Imperial",
narrative: "Las estructuras Cabal se alzan imponentes. Su disciplina militar es legendaria.",
enemy: {
name: "Centurión de Guerra",
health: 130,
damage: 28,
pattern: ["defend", "attack", "special"]
},
questions: 5
}, {
name: "El Dominio Rojo",
narrative: "En el corazón del territorio Cabal, enfrentas su verdadero poder.",
enemy: {
name: "Gladiador Imperial",
health: 150,
damage: 30,
pattern: ["special", "attack", "attack"]
},
questions: 5
}, {
name: "Máquinas de Guerra",
narrative: "La tecnología Cabal pone a prueba incluso a los Guardianes más experimentados.",
enemy: {
name: "Coloso de Asalto",
health: 180,
damage: 35,
pattern: ["attack", "special", "defend"]
},
questions: 5
}, {
name: "Emperador Caído",
narrative: "Enfrentas los últimos vestigios del poder imperial Cabal en Marte.",
enemy: {
name: "Comandante Supremo",
health: 200,
damage: 40,
pattern: ["special", "special", "attack"]
},
questions: 5
}]
}, {
name: "Mundo Trono",
theme: "Corrupción y engaño",
enemyType: "Colmena",
color: 0x9B59B6,
description: "Los secretos de Savathûn y el poder de la Colmena",
levels: [{
name: "Puertas del Engaño",
narrative: "El Mundo Trono de Savathûn se abre ante ti. Nada es lo que parece.",
enemy: {
name: "Acolito Susurrante",
health: 80,
damage: 25,
pattern: ["attack", "defend", "special"]
},
questions: 4
}, {
name: "El Eco de Savathûn",
narrative: "Los ecos de la Reina Bruja resuenan en cada rincón de su dominio.",
enemy: {
name: "Caballero del Engaño",
health: 140,
damage: 32,
pattern: ["special", "attack", "defend"]
},
questions: 5
}, {
name: "Secretos Susurrados",
narrative: "Las verdades ocultas de la Colmena se revelan en sussurros de poder.",
enemy: {
name: "Bruja de las Mentiras",
health: 160,
damage: 35,
pattern: ["defend", "special", "special"]
},
questions: 5
}, {
name: "La Verdad Final",
narrative: "En el corazón del engaño, la verdad más pura espera ser descubierta.",
enemy: {
name: "Ogro del Trono",
health: 220,
damage: 42,
pattern: ["attack", "attack", "special"]
},
questions: 5
}, {
name: "Reina de Mentiras",
narrative: "Enfrentas la esencia misma del engaño en su forma más pura.",
enemy: {
name: "Eco de Savathûn",
health: 280,
damage: 50,
pattern: ["special", "defend", "special"]
},
questions: 5
}]
}, {
name: "Red Vex",
theme: "Simulación y paradoja",
enemyType: "Vex",
color: 0xFFD700,
description: "Las máquinas del tiempo y sus simulaciones infinitas",
levels: [{
name: "Entrada a la Red",
narrative: "La Red Vex se extiende a través del tiempo y el espacio. Cada paso es calculado.",
enemy: {
name: "Goblin Vex",
health: 90,
damage: 20,
pattern: ["attack", "defend", "attack"]
},
questions: 4
}, {
name: "Simulaciones Fractales",
narrative: "La realidad se pliega sobre sí misma en patrones infinitos de posibilidad.",
enemy: {
name: "Hobgoblin Táctico",
health: 120,
damage: 30,
pattern: ["defend", "special", "attack"]
},
questions: 5
}, {
name: "El Nexo Temporal",
narrative: "En el corazón de la Red, el tiempo mismo es una herramienta de guerra.",
enemy: {
name: "Minotauro Guardián",
health: 180,
damage: 38,
pattern: ["attack", "defend", "special"]
},
questions: 5
}, {
name: "Paradoja Convergente",
narrative: "Las líneas temporales convergen en un solo punto de infinita complejidad.",
enemy: {
name: "Hydra de Simulación",
health: 250,
damage: 45,
pattern: ["special", "attack", "special"]
},
questions: 5
}, {
name: "Mente Colectiva",
narrative: "Te enfrentas a la consciencia unificada de toda la Red Vex.",
enemy: {
name: "Mente del Nexo",
health: 320,
damage: 55,
pattern: ["defend", "special", "special"]
},
questions: 5
}]
}, {
name: "Apoteosis",
theme: "Luz vs Oscuridad final",
enemyType: "Testigo",
color: 0x000000,
description: "El enfrentamiento final entre Luz y Oscuridad",
levels: [{
name: "El Umbral Final",
narrative: "Has llegado al final de todo. Aquí, Luz y Oscuridad chocan en su forma más pura.",
enemy: {
name: "Discípulo Perdido",
health: 200,
damage: 40,
pattern: ["attack", "special", "defend"]
},
questions: 5
}, {
name: "Ecos del Testigo",
narrative: "Los restos del Testigo aún pulsan con poder primordial.",
enemy: {
name: "Fragmento del Testigo",
health: 280,
damage: 50,
pattern: ["special", "attack", "special"]
},
questions: 5
}, {
name: "La Forma Final",
narrative: "El concepto mismo de la Forma Final se materializa ante ti.",
enemy: {
name: "Manifestación Final",
health: 350,
damage: 60,
pattern: ["defend", "special", "attack"]
},
questions: 5
}, {
name: "Más Allá de la Luz",
narrative: "Trasciende los límites de Luz y Oscuridad. Forja tu propio destino.",
enemy: {
name: "Avatar del Equilibrio",
health: 400,
damage: 65,
pattern: ["special", "special", "special"]
},
questions: 5
}, {
name: "Leyenda Eterna",
narrative: "Te conviertes en leyenda. Tu nombre resonará a través de toda la eternidad.",
enemy: {
name: "El Destino Mismo",
health: 500,
damage: 70,
pattern: ["attack", "defend", "special"]
},
questions: 5
}]
}];
var enemies = [{
name: "Cabal Legionary",
health: 60,
damage: 15,
pattern: ["attack", "attack", "defend"],
weakness: "Cabal"
}, {
name: "Hive Knight",
health: 80,
damage: 20,
pattern: ["attack", "special", "attack"],
weakness: "Hive"
}, {
name: "Vex Minotaur",
health: 100,
damage: 25,
pattern: ["defend", "attack", "special"],
weakness: "Vex"
}, {
name: "Fallen Captain",
health: 70,
damage: 18,
pattern: ["attack", "attack", "special"],
weakness: "Fallen"
}];
var classNames = ["Titan", "Hunter", "Warlock"];
var classColors = [0xFF6B6B, 0x5EB3FF, 0x9B59B6];
var classAbilities = ["Fortaleza: Escudo que absorbe daño", "Precisión: Ataques consecutivos potenciados", "Sabiduría: Curación y potenciación arcana"];
// Tactical UI elements
var guardianHealthBar = null;
var energyBar = null;
var enemyHealthBar = null;
var enemyInfo = null;
var battleStatus = null;
function initializeGame() {
// Show game mode selection first
showGameModeMenu();
LK.playMusic('ambient');
}
function showGameModeMenu() {
inMenu = true;
// Title
var titleText = new Text2('Destiny 2', {
size: 96,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
game.addChild(titleText);
// Subtitle
var subtitleText = new Text2('¿Qué quieres jugar?', {
size: 56,
fill: 0xFFFFFF
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 600;
game.addChild(subtitleText);
// Trivia mode button
var triviaButton = game.addChild(new MenuButton());
triviaButton.x = 1024;
triviaButton.y = 900;
triviaButton.setButton('Trivia Clásico', 0);
triviaButton.buttonText.tint = 0x5EB3FF;
var triviaDesc = new Text2('El juego de trivia tradicional', {
size: 32,
fill: 0xAAAAAA
});
triviaDesc.anchor.set(0.5, 0.5);
triviaDesc.x = 1024;
triviaDesc.y = 950;
game.addChild(triviaDesc);
// Tactical RPG mode button
var rpgButton = game.addChild(new MenuButton());
rpgButton.x = 1024;
rpgButton.y = 1200;
rpgButton.setButton('Forja de Leyendas', 1);
rpgButton.buttonText.tint = 0xFF6B6B;
var rpgDesc = new Text2('Trivia con mecánicas de combate táctico', {
size: 32,
fill: 0xAAAAAA
});
rpgDesc.anchor.set(0.5, 0.5);
rpgDesc.x = 1024;
rpgDesc.y = 1250;
game.addChild(rpgDesc);
// Override button actions
triviaButton.down = function (x, y, obj) {
if (inMenu) {
// Clear menu
while (game.children.length > 0) {
game.children[0].destroy();
}
showDifficultyMenu();
}
};
rpgButton.down = function (x, y, obj) {
if (inMenu) {
// Clear menu
while (game.children.length > 0) {
game.children[0].destroy();
}
showCampaignMenu();
}
};
}
function showDifficultyMenu() {
inMenu = true;
// Title
var titleText = new Text2('Destiny 2', {
size: 96,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
game.addChild(titleText);
// Subtitle
var subtitleText = new Text2('Selecciona tu nivel de dificultad', {
size: 48,
fill: 0xFFFFFF
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 600;
game.addChild(subtitleText);
// Difficulty buttons
var difficulties = [{
name: 'Javi',
color: 0x5EB3FF,
desc: 'Conocimiento básico'
}, {
name: 'Rodri',
color: 0xFFD700,
desc: 'Experiencia intermedia'
}, {
name: 'Diego',
color: 0xFF6B6B,
desc: 'Dominio del lore'
}, {
name: 'Nadie la sabe',
color: 0x9B59B6,
desc: 'Desafío extremo'
}];
for (var i = 0; i < 4; i++) {
var menuBtn = game.addChild(new MenuButton());
menuBtn.x = 1024;
menuBtn.y = 900 + i * 200;
menuBtn.setButton(difficulties[i].name, i);
menuBtn.buttonText.tint = difficulties[i].color;
var descText = new Text2(difficulties[i].desc, {
size: 32,
fill: 0xAAAAAA
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 950 + i * 200;
game.addChild(descText);
}
// Show unlocked modes
if (guardianMode || darknessMode || timerMode) {
var modesText = new Text2('Modos desbloqueados:', {
size: 36,
fill: 0xFFD700
});
modesText.anchor.set(0.5, 0.5);
modesText.x = 1024;
modesText.y = 2000;
game.addChild(modesText);
var unlocked = [];
if (guardianMode) {
unlocked.push('Guardian');
}
if (darknessMode) {
unlocked.push('Oscuridad');
}
if (timerMode) {
unlocked.push('Cronómetro');
}
var unlockedText = new Text2(unlocked.join(' • '), {
size: 32,
fill: 0x5EB3FF
});
unlockedText.anchor.set(0.5, 0.5);
unlockedText.x = 1024;
unlockedText.y = 2050;
game.addChild(unlockedText);
}
}
function showCampaignMenu() {
inMenu = true;
// Load saved progress
var savedSector = storage.currentSector || 0;
var savedLevel = storage.currentLevel || 0;
var savedClass = storage.guardianClass || 0;
var savedExp = storage.guardianExp || 0;
var savedGuardianLevel = storage.guardianLevel || 1;
// Title
var titleText = new Text2('FORJA DE LEYENDAS', {
size: 80,
fill: 0xFF6B6B
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
game.addChild(titleText);
// Subtitle
var subtitleText = new Text2('Un viaje interactivo por el universo de Destiny 2', {
size: 36,
fill: 0xAAAAAA
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 360;
game.addChild(subtitleText);
// Show saved progress if exists
if (savedSector > 0 || savedLevel > 0) {
var progressText = new Text2('Progreso Guardado: Sector ' + (savedSector + 1) + ' - Nivel ' + (savedLevel + 1), {
size: 32,
fill: 0x5EB3FF
});
progressText.anchor.set(0.5, 0.5);
progressText.x = 1024;
progressText.y = 420;
game.addChild(progressText);
var continueBtn = game.addChild(new MenuButton());
continueBtn.x = 1024;
continueBtn.y = 500;
continueBtn.setButton('Continuar Campaña', -1);
continueBtn.buttonText.tint = 0x00FF00;
continueBtn.down = function (x, y, obj) {
if (inMenu) {
while (game.children.length > 0) {
game.children[0].destroy();
}
currentSector = savedSector;
currentLevel = savedLevel;
guardianClass = savedClass;
guardianExp = savedExp;
guardianLevel = savedGuardianLevel;
startCampaignLevel();
}
};
}
// New campaign button
var newBtn = game.addChild(new MenuButton());
newBtn.x = 1024;
newBtn.y = 650;
newBtn.setButton('Nueva Campaña', -2);
newBtn.buttonText.tint = 0xFFD700;
newBtn.down = function (x, y, obj) {
if (inMenu) {
while (game.children.length > 0) {
game.children[0].destroy();
}
showClassSelectionMenu();
}
};
// Sector selection (show unlocked sectors)
var unlockedSectors = storage.unlockedSectors || 1;
if (unlockedSectors > 1) {
var sectorText = new Text2('Sectores Desbloqueados:', {
size: 40,
fill: 0xFFD700
});
sectorText.anchor.set(0.5, 0.5);
sectorText.x = 1024;
sectorText.y = 800;
game.addChild(sectorText);
for (var i = 0; i < Math.min(unlockedSectors, sectors.length); i++) {
(function (sectorIndex) {
var sectorBtn = game.addChild(new MenuButton());
sectorBtn.x = 300 + sectorIndex % 3 * 450;
sectorBtn.y = 900 + Math.floor(sectorIndex / 3) * 150;
sectorBtn.setButton(sectors[sectorIndex].name, sectorIndex);
sectorBtn.buttonText.tint = sectors[sectorIndex].color;
sectorBtn.down = function (x, y, obj) {
if (inMenu) {
while (game.children.length > 0) {
game.children[0].destroy();
}
currentSector = sectorIndex;
currentLevel = 0;
guardianClass = savedClass;
startCampaignLevel();
}
};
})(i);
}
}
}
function showClassSelectionMenu() {
inMenu = true;
// Title
var titleText = new Text2('Elige tu Guardián', {
size: 96,
fill: 0xFF6B6B
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
game.addChild(titleText);
// Subtitle
var subtitleText = new Text2('Cada clase tiene habilidades únicas en combate', {
size: 48,
fill: 0xFFFFFF
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 500;
game.addChild(subtitleText);
// Class selection
for (var i = 0; i < 3; i++) {
var classBtn = game.addChild(new MenuButton());
classBtn.x = 1024;
classBtn.y = 700 + i * 200;
classBtn.setButton(classNames[i], i);
classBtn.buttonText.tint = classColors[i];
var descText = new Text2(classAbilities[i], {
size: 32,
fill: 0xAAAAAA
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 750 + i * 200;
game.addChild(descText);
// Set up class selection
(function (classIndex) {
classBtn.down = function (x, y, obj) {
if (inMenu) {
while (game.children.length > 0) {
game.children[0].destroy();
}
guardianClass = classIndex;
currentSector = 0;
currentLevel = 0;
guardianLevel = 1;
guardianExp = 0;
storage.guardianClass = guardianClass;
storage.currentSector = 0;
storage.currentLevel = 0;
storage.guardianLevel = 1;
storage.guardianExp = 0;
startCampaignLevel();
}
};
})(i);
}
}
function startGameWithDifficulty(difficulty) {
if (!inMenu) {
return;
}
inMenu = false;
selectedDifficulty = difficulty;
currentPhase = difficulty;
// Clear menu
while (game.children.length > 0) {
game.children[0].destroy();
}
// Initialize game elements
// Question display
questionDisplay = game.addChild(new QuestionDisplay());
questionDisplay.x = 1024;
questionDisplay.y = 600;
// Option buttons
optionButtons = []; // Reset the array before populating
for (var i = 0; i < 4; i++) {
var button = game.addChild(new OptionButton());
button.x = 520 + i % 2 * 1000;
button.y = 1200 + Math.floor(i / 2) * 200;
optionButtons.push(button);
}
// Progress display
progressDisplay = game.addChild(new ProgressDisplay());
progressDisplay.x = 224;
progressDisplay.y = 2400;
// Score text
scoreText = new Text2('Score: 0', {
size: 64,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Phase text
phaseText = new Text2(phaseNames[currentPhase], {
size: 48,
fill: 0x5EB3FF
});
phaseText.anchor.set(0.5, 0);
phaseText.y = 100;
LK.gui.top.addChild(phaseText);
// Lives text
livesText = new Text2('Lives: ❤❤❤', {
size: 40,
fill: 0xFF6B6B
});
livesText.anchor.set(0, 0);
livesText.x = 120;
LK.gui.topLeft.addChild(livesText);
// Timer display for all modes
timerDisplay = new Text2('Time: 60s', {
size: 40,
fill: 0xFFD700
});
timerDisplay.anchor.set(0.5, 0);
timerDisplay.y = 180;
LK.gui.top.addChild(timerDisplay);
// Mode indicator for timer mode
if (timerMode) {
modeIndicator = new Text2('TIMER MODE ACTIVE', {
size: 36,
fill: 0xFF6B6B
});
modeIndicator.anchor.set(0.5, 0);
modeIndicator.y = 230;
LK.gui.top.addChild(modeIndicator);
}
// Load saved progress
guardianMode = storage.guardianUnlocked || false;
darknessMode = storage.darknessUnlocked || false;
timerMode = storage.timerUnlocked || false;
// Reset game state
score = 0;
lives = 3;
currentQuestion = 0;
questionDifficulty = 0;
usedQuestions = [];
availableQuestionsPool = [];
timerStartTime = 0;
// Start game
loadQuestion();
}
function startCampaignLevel() {
if (!inMenu) return;
inMenu = false;
campaignMode = true;
// Get current sector and level data
var sector = sectors[currentSector];
var level = sector.levels[currentLevel];
// Reset battle state
guardianHealth = guardianMaxHealth;
guardianEnergy = guardianMaxEnergy;
battleTurn = 0;
consecutiveCorrect = 0;
shieldActive = false;
hunterDoubleAttack = false;
// Setup enemy from level data
var enemy = level.enemy;
enemyHealth = enemy.health;
enemyMaxHealth = enemy.health;
currentEnemy = 0; // Reset enemy reference
// Initialize campaign UI
setupCampaignUI(sector, level);
showLevelNarrative(level);
}
function setupCampaignUI(sector, level) {
// Sector and level info
var sectorText = new Text2(sector.name, {
size: 64,
fill: sector.color
});
sectorText.anchor.set(0.5, 0);
sectorText.x = 1024;
sectorText.y = 50;
game.addChild(sectorText);
var levelText = new Text2('Nivel ' + (currentLevel + 1) + ': ' + level.name, {
size: 48,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.x = 1024;
levelText.y = 120;
game.addChild(levelText);
// Question display
questionDisplay = game.addChild(new QuestionDisplay());
questionDisplay.x = 1024;
questionDisplay.y = 900;
// Option buttons
optionButtons = [];
for (var i = 0; i < 4; i++) {
var button = game.addChild(new OptionButton());
button.x = 520 + i % 2 * 1000;
button.y = 1500 + Math.floor(i / 2) * 200;
optionButtons.push(button);
}
// Progress display for campaign questions
progressDisplay = game.addChild(new ProgressDisplay());
progressDisplay.x = 224;
progressDisplay.y = 2100;
// Guardian info panel
var guardianPanel = new Text2(classNames[guardianClass] + ' Guardian (Nivel ' + guardianLevel + ')', {
size: 40,
fill: classColors[guardianClass]
});
guardianPanel.anchor.set(0, 0);
guardianPanel.x = 50;
guardianPanel.y = 200;
game.addChild(guardianPanel);
// Health and energy bars
guardianHealthBar = new Text2('Salud: ' + guardianHealth + '/' + guardianMaxHealth, {
size: 32,
fill: 0x00FF00
});
guardianHealthBar.anchor.set(0, 0);
guardianHealthBar.x = 50;
guardianHealthBar.y = 250;
game.addChild(guardianHealthBar);
energyBar = new Text2('Energía: ' + guardianEnergy + '/' + guardianMaxEnergy, {
size: 32,
fill: 0x5EB3FF
});
energyBar.anchor.set(0, 0);
energyBar.x = 50;
energyBar.y = 290;
game.addChild(energyBar);
// Experience bar
var expBar = new Text2('EXP: ' + guardianExp + '/100', {
size: 28,
fill: 0xFFD700
});
expBar.anchor.set(0, 0);
expBar.x = 50;
expBar.y = 330;
game.addChild(expBar);
// Enemy info
var enemy = level.enemy;
enemyInfo = new Text2(enemy.name, {
size: 40,
fill: 0xFF6B6B
});
enemyInfo.anchor.set(1, 0);
enemyInfo.x = 1998;
enemyInfo.y = 200;
game.addChild(enemyInfo);
enemyHealthBar = new Text2('Salud: ' + enemyHealth + '/' + enemyMaxHealth, {
size: 32,
fill: 0xFF6B6B
});
enemyHealthBar.anchor.set(1, 0);
enemyHealthBar.x = 1998;
enemyHealthBar.y = 250;
game.addChild(enemyHealthBar);
// Battle status
battleStatus = new Text2('Tu Turno - ¡Responde para Atacar!', {
size: 36,
fill: 0xFFD700
});
battleStatus.anchor.set(0.5, 0);
battleStatus.x = 1024;
battleStatus.y = 400;
game.addChild(battleStatus);
}
function showLevelNarrative(level) {
// Show narrative text
var narrativeText = new Text2(level.narrative, {
size: 32,
fill: 0xAAAAAA
});
narrativeText.anchor.set(0.5, 0.5);
narrativeText.x = 1024;
narrativeText.y = 600;
narrativeText.wordWrap = true;
narrativeText.wordWrapWidth = 1600;
narrativeText.alpha = 0;
game.addChild(narrativeText);
// Fade in narrative
tween(narrativeText, {
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(narrativeText, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
narrativeText.destroy();
loadCampaignQuestion();
}
});
}, 3000);
}
});
}
function loadQuestion() {
canAnswer = true;
currentQuestion++;
// Calculate question difficulty based on progress
questionDifficulty = Math.floor((currentQuestion - 1) / 3);
if (questionDifficulty > 3) {
questionDifficulty = 3;
}
if (currentQuestion > questionsPerRound) {
// Phase complete - stay in selected difficulty
checkAchievements();
return;
}
if (progressDisplay) {
progressDisplay.setProgress(currentQuestion, questionsPerRound);
}
// Update difficulty visual indicator
phaseText.tint = DIFFICULTY_COLORS[currentPhase];
// Add difficulty indicator
var difficultyText = ' - Nivel ' + (questionDifficulty + 1);
phaseText.setText(phaseNames[currentPhase] + difficultyText);
// Get questions from current phase
var phaseQuestions = questions[currentPhase];
// Initialize question pool if empty or at start
if (availableQuestionsPool.length === 0 || currentQuestion === 1) {
availableQuestionsPool = [];
for (var i = 0; i < phaseQuestions.length; i++) {
availableQuestionsPool.push({
question: phaseQuestions[i],
index: i
});
}
}
// Filter questions by difficulty from the pool
var availableQuestions = [];
for (var i = 0; i < availableQuestionsPool.length; i++) {
var qData = availableQuestionsPool[i];
var q = qData.question;
// Select questions matching current difficulty or close to it
if (Math.abs(q.difficulty - questionDifficulty) <= 1) {
availableQuestions.push(qData);
}
}
// If no questions available for this difficulty, expand search
if (availableQuestions.length === 0) {
// Use all remaining questions in pool
availableQuestions = availableQuestionsPool.slice();
}
// Select random question from available
var selectedIndex = Math.floor(Math.random() * availableQuestions.length);
var selected = availableQuestions[selectedIndex];
var questionData = selected.question;
// Remove selected question from pool
for (var i = 0; i < availableQuestionsPool.length; i++) {
if (availableQuestionsPool[i].index === selected.index) {
availableQuestionsPool.splice(i, 1);
break;
}
}
// Apply darkness mode with better visual feedback
if (darknessMode) {
questionDisplay.setQuestion("\n" + questionData.q + "\n");
questionDisplay.questionText.tint = 0x9B59B6;
} else {
questionDisplay.setQuestion(questionData.q);
questionDisplay.questionText.tint = 0xFFFFFF;
}
// Create a shuffled array of indices using only Fisher-Yates
var indices = [0, 1, 2, 3];
var shuffledIndices = [];
// Use proper Fisher-Yates shuffle
var tempIndices = indices.slice(); // Create a copy
while (tempIndices.length > 0) {
var randomIndex = Math.floor(Math.random() * tempIndices.length);
shuffledIndices.push(tempIndices[randomIndex]);
tempIndices.splice(randomIndex, 1);
}
// Set options with shuffled positions
for (var i = 0; i < 4; i++) {
var originalIndex = shuffledIndices[i];
optionButtons[i].setOption(questionData.options[originalIndex], originalIndex, originalIndex === questionData.correct);
// Store button position for click handling
optionButtons[i].buttonPosition = i;
}
// Initialize 60-second timer for all questions
timerCount = TIMER_BASE; // Always 60 seconds
timerStartTime = Date.now();
}
function loadCampaignQuestion() {
if (!campaignMode) return;
canAnswer = true;
currentQuestion++;
// Get current level data
var sector = sectors[currentSector];
var level = sector.levels[currentLevel];
// Check if level is complete
if (currentQuestion > level.questions) {
completeCampaignLevel();
return;
}
// Select questions based on sector theme and current difficulty
var questionPool = [];
var sectorQuestions = questions[currentSector] || questions[0]; // Fallback to basic questions
// Add variety by mixing difficulties
for (var i = 0; i < sectorQuestions.length; i++) {
questionPool.push(sectorQuestions[i]);
}
// Add some cross-sector questions for variety
if (currentSector > 0) {
var extraQuestions = questions[Math.max(0, currentSector - 1)];
for (var i = 0; i < Math.min(3, extraQuestions.length); i++) {
questionPool.push(extraQuestions[i]);
}
}
// Randomly select a question
var selectedQuestion = questionPool[Math.floor(Math.random() * questionPool.length)];
questionDisplay.setQuestion(selectedQuestion.q);
// Shuffle options
var indices = [0, 1, 2, 3];
var shuffledIndices = [];
var tempIndices = indices.slice();
while (tempIndices.length > 0) {
var randomIndex = Math.floor(Math.random() * tempIndices.length);
shuffledIndices.push(tempIndices[randomIndex]);
tempIndices.splice(randomIndex, 1);
}
// Set options
for (var i = 0; i < 4; i++) {
var originalIndex = shuffledIndices[i];
optionButtons[i].setOption(selectedQuestion.options[originalIndex], originalIndex, originalIndex === selectedQuestion.correct);
optionButtons[i].buttonPosition = i;
}
// Initialize timer
timerCount = TIMER_BASE;
timerStartTime = Date.now();
}
function completeCampaignLevel() {
// Award experience
guardianExp += 20 + currentLevel * 5;
// Level up check
if (guardianExp >= 100) {
guardianLevel++;
guardianExp -= 100;
guardianMaxHealth += 20;
guardianHealth = guardianMaxHealth;
guardianMaxEnergy++;
guardianEnergy = guardianMaxEnergy;
showBattleMessage("¡Guardián subió de nivel! Nivel " + guardianLevel);
}
// Save progress
storage.currentSector = currentSector;
storage.currentLevel = currentLevel + 1;
storage.guardianLevel = guardianLevel;
storage.guardianExp = guardianExp;
// Check if sector is complete
if (currentLevel + 1 >= sectors[currentSector].levels.length) {
// Sector complete
currentSector++;
currentLevel = 0;
if (currentSector >= sectors.length) {
// Campaign complete!
showBattleMessage("¡Campaña Completada! ¡Eres una Leyenda Eterna!");
LK.setTimeout(function () {
LK.showYouWin();
}, 3000);
return;
} else {
// Unlock next sector
storage.unlockedSectors = Math.max(storage.unlockedSectors || 1, currentSector + 1);
storage.currentSector = currentSector;
storage.currentLevel = 0;
showBattleMessage("¡Sector " + sectors[currentSector - 1].name + " completado!");
}
} else {
currentLevel++;
}
// Show completion message and continue
LK.setTimeout(function () {
// Clear current UI
while (game.children.length > 0) {
game.children[0].destroy();
}
if (currentSector < sectors.length) {
startCampaignLevel();
}
}, 2000);
}
function checkAnswer(selectedIndex) {
if (!canAnswer) {
return;
}
canAnswer = false;
timerStartTime = 0; // Stop timer when answer is selected
if (campaignMode) {
checkCampaignAnswer(selectedIndex);
return;
}
var correct = optionButtons[selectedIndex].isCorrect;
// Darkness mode inverts correct answers
if (darknessMode) {
correct = !correct;
}
if (correct) {
LK.getSound('correct').play();
optionButtons[selectedIndex].showResult(true);
// Progressive scoring based on phase and question difficulty
var difficultyMultiplier = 1 + questionDifficulty * 0.5; // 1x, 1.5x, 2x, 2.5x
var pointsEarned = Math.floor(SCORE_BASE[currentPhase] * difficultyMultiplier);
score += pointsEarned;
scoreText.setText('Score: ' + score);
LK.setScore(score);
// Show points earned
var pointsText = new Text2('+' + pointsEarned, {
size: 48,
fill: 0x00FF00
});
pointsText.anchor.set(0.5, 0.5);
pointsText.x = optionButtons[selectedIndex].x;
pointsText.y = optionButtons[selectedIndex].y - 100;
game.addChild(pointsText);
tween(pointsText, {
y: pointsText.y - 50,
alpha: 0
}, {
duration: ANIMATION_DURATION.MEDIUM,
onFinish: function onFinish() {
pointsText.destroy();
}
});
// Check for unlocks
if (score >= UNLOCK_THRESHOLDS.GUARDIAN && !guardianMode) {
guardianMode = true;
storage.guardianUnlocked = true;
LK.getSound('unlock').play();
showUnlockMessage("Guardian's Challenge Unlocked!");
}
if (score >= UNLOCK_THRESHOLDS.DARKNESS && !darknessMode) {
darknessMode = true;
storage.darknessUnlocked = true;
LK.getSound('unlock').play();
showUnlockMessage("Darkness Mode Unlocked!");
}
if (score >= UNLOCK_THRESHOLDS.TIMER && !timerMode) {
timerMode = true;
storage.timerUnlocked = true;
LK.getSound('unlock').play();
showUnlockMessage("Timer Mode Unlocked!");
}
} else {
LK.getSound('wrong').play();
optionButtons[selectedIndex].showResult(false);
lives--;
updateLives();
if (lives <= 0) {
LK.showGameOver();
return;
}
}
// Save high score
if (score > (storage.highScore || 0)) {
storage.highScore = score;
}
// Next question after delay
LK.setTimeout(function () {
// Clear indicators
for (var i = 0; i < 4; i++) {
if (optionButtons[i].correctIndicator) {
optionButtons[i].correctIndicator.destroy();
optionButtons[i].correctIndicator = null;
}
if (optionButtons[i].wrongIndicator) {
optionButtons[i].wrongIndicator.destroy();
optionButtons[i].wrongIndicator = null;
}
}
loadQuestion();
}, ANIMATION_DURATION.LONG);
}
function checkCampaignAnswer(selectedIndex) {
var correct = optionButtons[selectedIndex].isCorrect;
if (correct) {
LK.getSound('correct').play();
optionButtons[selectedIndex].showResult(true);
consecutiveCorrect++;
// Guardian attacks enemy
var damage = 30 + guardianLevel * 5;
// Class-specific abilities
if (guardianClass === 0 && guardianEnergy >= 2) {
// Titan shield
shieldActive = true;
guardianEnergy -= 2;
showBattleMessage("¡Escudo Titán Activado!");
} else if (guardianClass === 1 && consecutiveCorrect >= 2) {
// Hunter double attack
damage *= 2;
consecutiveCorrect = 0;
showBattleMessage("¡Golpe Doble del Cazador!");
} else if (guardianClass === 2 && guardianEnergy >= 1) {
// Warlock heal and enhance damage
guardianHealth = Math.min(guardianMaxHealth, guardianHealth + 20);
guardianEnergy -= 1;
damage += 15;
showBattleMessage("¡Curación y Poder Arcano del Hechicero!");
}
enemyHealth -= damage;
guardianEnergy = Math.min(guardianMaxEnergy, guardianEnergy + 1);
guardianExp += 5;
score += 15;
if (enemyHealth <= 0) {
// Enemy defeated, level complete
showBattleMessage("¡Enemigo derrotado! Nivel completado.");
LK.setTimeout(function () {
completeCampaignLevel();
}, 2000);
return;
}
} else {
LK.getSound('wrong').play();
optionButtons[selectedIndex].showResult(false);
consecutiveCorrect = 0;
guardianEnergy = Math.max(0, guardianEnergy - 1);
}
updateCampaignUI();
// Enemy turn after delay
LK.setTimeout(function () {
if (enemyHealth > 0) {
campaignEnemyTurn();
}
LK.setTimeout(function () {
clearBattleIndicators();
loadCampaignQuestion();
}, ANIMATION_DURATION.MEDIUM);
}, ANIMATION_DURATION.LONG);
}
function updateTacticalUI() {
// This function is not used in campaign mode, left empty
}
function enemyTurn() {
var enemy = enemies[currentEnemy];
var turnIndex = battleTurn % enemy.pattern.length;
var action = enemy.pattern[turnIndex];
battleTurn++;
if (action === "attack") {
var damage = enemy.damage;
if (shieldActive && guardianClass === 0) {
damage = Math.floor(damage * 0.5);
shieldActive = false;
showBattleMessage("Shield absorbed damage!");
} else {
showBattleMessage(enemy.name + " attacks for " + damage + " damage!");
}
guardianHealth -= damage;
LK.getSound('damage').play();
} else if (action === "special") {
var damage = Math.floor(enemy.damage * 1.5);
showBattleMessage(enemy.name + " uses special attack!");
guardianHealth -= damage;
LK.getSound('damage').play();
} else if (action === "defend") {
showBattleMessage(enemy.name + " defends and recovers!");
enemyHealth = Math.min(enemyMaxHealth, enemyHealth + 10);
}
if (guardianHealth <= 0) {
showBattleMessage("Guardian defeated!");
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
}
updateTacticalUI();
}
function campaignEnemyTurn() {
var sector = sectors[currentSector];
var level = sector.levels[currentLevel];
var enemy = level.enemy;
var turnIndex = battleTurn % enemy.pattern.length;
var action = enemy.pattern[turnIndex];
battleTurn++;
if (action === "attack") {
var damage = enemy.damage - guardianLevel * 2; // Level reduces incoming damage
damage = Math.max(5, damage); // Minimum damage
if (shieldActive && guardianClass === 0) {
damage = Math.floor(damage * 0.4);
shieldActive = false;
showBattleMessage("¡El escudo absorbió el daño!");
} else {
showBattleMessage(enemy.name + " ataca por " + damage + " de daño!");
}
guardianHealth -= damage;
LK.getSound('damage').play();
} else if (action === "special") {
var damage = Math.floor(enemy.damage * 1.3) - guardianLevel;
damage = Math.max(8, damage);
showBattleMessage("¡" + enemy.name + " usa ataque especial!");
guardianHealth -= damage;
LK.getSound('damage').play();
} else if (action === "defend") {
showBattleMessage(enemy.name + " se defiende y se regenera!");
enemyHealth = Math.min(enemyMaxHealth, enemyHealth + 15);
}
if (guardianHealth <= 0) {
showBattleMessage("¡Guardián derrotado! Regresando al inicio del nivel...");
LK.setTimeout(function () {
// Reset level but keep progress
guardianHealth = guardianMaxHealth;
guardianEnergy = guardianMaxEnergy;
currentQuestion = 0;
enemyHealth = enemy.health;
enemyMaxHealth = enemy.health;
updateCampaignUI();
showBattleMessage("¡Inténtalo de nuevo!");
}, 2000);
}
updateCampaignUI();
}
function updateCampaignUI() {
// Update all UI elements with current stats
if (guardianHealthBar) {
guardianHealthBar.setText('Salud: ' + guardianHealth + '/' + guardianMaxHealth);
// Change color based on health percentage
var healthPercent = guardianHealth / guardianMaxHealth;
if (healthPercent > 0.6) {
guardianHealthBar.tint = 0x00FF00; // Green
} else if (healthPercent > 0.3) {
guardianHealthBar.tint = 0xFFD700; // Yellow
} else {
guardianHealthBar.tint = 0xFF6B6B; // Red
}
}
if (energyBar) {
energyBar.setText('Energía: ' + guardianEnergy + '/' + guardianMaxEnergy);
}
if (enemyHealthBar) {
enemyHealthBar.setText('Salud: ' + enemyHealth + '/' + enemyMaxHealth);
}
if (battleStatus) {
if (battleTurn % 2 === 0) {
battleStatus.setText('Tu Turno - ¡Responde para Atacar!');
battleStatus.tint = 0xFFD700;
} else {
battleStatus.setText('Turno del Enemigo - ¡Prepárate!');
battleStatus.tint = 0xFF6B6B;
}
}
}
function showBattleMessage(message) {
var battleText = new Text2(message, {
size: 36,
fill: 0xFFD700
});
battleText.anchor.set(0.5, 0.5);
battleText.x = 1024;
battleText.y = 500;
battleText.alpha = 0;
game.addChild(battleText);
tween(battleText, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(battleText, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
battleText.destroy();
}
});
}, 1500);
}
});
}
function clearBattleIndicators() {
for (var i = 0; i < 4; i++) {
if (optionButtons[i].correctIndicator) {
optionButtons[i].correctIndicator.destroy();
optionButtons[i].correctIndicator = null;
}
if (optionButtons[i].wrongIndicator) {
optionButtons[i].wrongIndicator.destroy();
optionButtons[i].wrongIndicator = null;
}
}
}
function updateLives() {
var hearts = '';
for (var i = 0; i < lives; i++) {
hearts += '❤';
}
livesText.setText('Lives: ' + hearts);
}
function showUnlockMessage(message) {
var unlockText = new Text2(message, {
size: 72,
fill: 0xFFD700
});
unlockText.anchor.set(0.5, 0.5);
unlockText.x = 1024;
unlockText.y = 1366;
unlockText.alpha = 0;
game.addChild(unlockText);
tween(unlockText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: ANIMATION_DURATION.SHORT,
easing: tween.easeOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(unlockText, {
alpha: 0
}, {
duration: ANIMATION_DURATION.SHORT,
onFinish: function onFinish() {
unlockText.destroy();
}
});
}, ANIMATION_DURATION.EXTRA_LONG);
}
});
}
function checkAchievements() {
var rank = 0;
if (score >= 21) {
rank = 1;
}
if (score >= 51) {
rank = 2;
}
if (score >= 76) {
rank = 3;
}
var achievementText = new Text2('Rank: ' + rankNames[rank], {
size: 96,
fill: 0xFFD700
});
achievementText.anchor.set(0.5, 0.5);
achievementText.x = 1024;
achievementText.y = 1366;
game.addChild(achievementText);
if (score >= UNLOCK_THRESHOLDS.WIN) {
LK.showYouWin();
} else {
LK.setTimeout(function () {
LK.showGameOver();
}, ANIMATION_DURATION.GAME_OVER_DELAY);
}
}
game.update = function () {
// Update timer for all modes when answering is allowed
if (canAnswer && timerStartTime > 0) {
// Calculate elapsed time in milliseconds
var elapsedTime = Date.now() - timerStartTime;
var elapsedFrames = Math.floor(elapsedTime / (1000 / 60)); // Convert to frames (60 FPS)
var remainingFrames = timerCount - elapsedFrames;
// Update timer display
if (timerDisplay) {
var remainingSeconds = Math.max(0, Math.ceil(remainingFrames / 60));
timerDisplay.setText('Time: ' + remainingSeconds + 's');
// Change color when time is running low
if (remainingSeconds <= 10) {
timerDisplay.tint = 0xFF6B6B; // Red when low
} else if (remainingSeconds <= 20) {
timerDisplay.tint = 0xFFD700; // Yellow when moderate
} else {
timerDisplay.tint = 0x5EB3FF; // Blue when plenty
}
}
if (remainingFrames <= 0) {
// Time's up
canAnswer = false;
timerStartTime = 0;
// In timer mode, losing a life. In other modes, just move to next question
if (timerMode) {
lives--;
updateLives();
LK.getSound('wrong').play();
if (lives <= 0) {
LK.showGameOver();
return;
}
} else {
// In non-timer modes, just show a visual indication and move on
LK.getSound('wrong').play();
}
LK.setTimeout(function () {
loadQuestion();
}, ANIMATION_DURATION.MEDIUM);
}
}
};
// Initialize the game
initializeGame(); ===================================================================
--- original.js
+++ change.js
@@ -1187,8 +1187,12 @@
button.x = 520 + i % 2 * 1000;
button.y = 1500 + Math.floor(i / 2) * 200;
optionButtons.push(button);
}
+ // Progress display for campaign questions
+ progressDisplay = game.addChild(new ProgressDisplay());
+ progressDisplay.x = 224;
+ progressDisplay.y = 2100;
// Guardian info panel
var guardianPanel = new Text2(classNames[guardianClass] + ' Guardian (Nivel ' + guardianLevel + ')', {
size: 40,
fill: classColors[guardianClass]
@@ -1296,9 +1300,11 @@
// Phase complete - stay in selected difficulty
checkAchievements();
return;
}
- progressDisplay.setProgress(currentQuestion, questionsPerRound);
+ if (progressDisplay) {
+ progressDisplay.setProgress(currentQuestion, questionsPerRound);
+ }
// Update difficulty visual indicator
phaseText.tint = DIFFICULTY_COLORS[currentPhase];
// Add difficulty indicator
var difficultyText = ' - Nivel ' + (questionDifficulty + 1);