Code edit (1 edits merged)
Please save this source code
User prompt
otra cosa cuando pierdo una y sigo teniendo tres vidas igual game over aunque tenga 2 vidas mas
User prompt
quiero que la dificultad se seleccione antes de jugar, quiero que las pregunta de cada dificultad se van incrementando dependiendo del nivel y que sean dificiles
User prompt
🏅 SISTEMA DE DIFICULTAD ESCALONADA Fácil (Luz de Aprendiz): conocimiento superficial, contenido jugado comúnmente. Media (Sabio del Núcleo): requiere experiencia jugando múltiples temporadas. Difícil (Archivo Negro): exige haber leído lore, conectado eventos entre temporadas. Extrema (Oscuridad Interior): conecta frases cifradas, símbolos, detalles no explicados directamente en el juego.
User prompt
hazlo con preguntas actualizadas al 02/7/2025
User prompt
cuando quiero seleccionar una respuesta no me deja le doy click y nada
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'wordWrap')' in or related to this line: 'self.questionText.style.wordWrap = true;' Line Number: 116
Code edit (1 edits merged)
Please save this source code
User prompt
El Archivo del Guardián
Initial prompt
🎮 Nombre del juego: “El Archivo del Guardián” Tagline: "El conocimiento es la luz que vence a la Oscuridad." 🕹️ Tipo de Juego Modo de juego: Trivia en solitario. Estilo: Por rondas con niveles de dificultad. Formato: Consola (CLI), Escritorio (GUI simple) o incluso archivo ejecutable .exe. ⚙️ Mecánica de Juego 🔹 Estructura básica El jugador responde a preguntas una por una. Hay varias categorías que escalan en dificultad: Historia General Armas y Armaduras Lore Profundo Actividades y Raids Preguntas tipo acertijo Cada ronda contiene entre 5 y 10 preguntas. Cada respuesta correcta suma puntos. Si fallas, puedes perder puntos o tener penalizaciones. 🔥 Modo "Desafío del Guardián" Este es el modo difícil diseñado para jugadores hardcore: Una sola vida: Si fallas una pregunta, terminas el juego. Sin pistas, sin tiempo visible. Las preguntas son encriptadas o indirectas. Ejemplo: “Mi voz se escuchó en las profundidades de la Luna, y fui testigo de la caída de Crota. ¿Quién soy?” Respuesta: Eris Morn 🧠 Tipos de Preguntas 1. Trivia clásica Opción múltiple, 4 respuestas. 2. Identificación por texto Pregunta sin opciones. Ejemplo: “¿Qué significa el nombre 'Xûr' en la lengua de los Nueve?” 3. Cifrado simbólico (modo avanzado) Usas símbolos de la colmena o vex (representados por texto en ASCII) que debes descifrar. Ejemplo: ⚙️ Código Vex: ΔΘψΣ Traducción: "Red" (pista a Red Legion o Redrix) 4. Lore de libro Basado en grimoire, registros o textos oficiales. Ejemplo: “¿Qué palabra susurró Savathûn al final de la Temporada de los Perdidos que alteró el curso del ritual?” 5. Perk Challenge Te dicen un perk y debes decir qué arma podía tenerlo en X temporada. “¿Qué arma legendaria introducida en la Temporada 17 podía tener el perk Incandescente?” 🧩 Estructura de dificultad Fase 1: Iniciado del Archivo Preguntas simples sobre personajes, armas conocidas y actividades básicas. Fase 2: Criptarca Errante Entra el lore más profundo, misiones exóticas específicas, eventos de temporada. Fase 3: Vidente Preguntas indirectas, con citas, frases oscuras, conexiones entre personajes y eventos. Fase 4: Archivo Prohibido Preguntas imposibles para los que no han leído grimoire o no siguieron temporadas específicas. 🏅 Sistema de Logros Rangos internos (guardados localmente, sin conexión): 0–20 pts: Portador de la Luz 21–50 pts: Discípulo de Osiris 51–75 pts: Devorador de Sabiduría 76–100 pts: Leyenda del Archivo Puedes desbloquear modos especiales si alcanzas ciertos puntajes: Modo Oscuridad: todas las preguntas se invierten lógicamente (deben deducirse con pistas falsas). Modo Cronómetro: 5 segundos por pregunta, sin volver atrás.
/****
* 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(); /****
* 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();