/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var AICharacter = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('crewmate', { anchorX: 0.5, anchorY: 0.5 }); self.isImpostor = false; self.isDead = false; self.killCooldown = 0; self.moveTimer = 0; self.targetX = 0; self.targetY = 0; self.username = ''; self.speed = 2; self.update = function () { if (self.isDead) return; if (self.killCooldown > 0) { self.killCooldown--; } self.moveTimer--; if (self.moveTimer <= 0) { self.targetX = Math.random() * 1800 + 100; self.targetY = Math.random() * 1500 + 200; self.moveTimer = Math.random() * 300 + 120; } var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } if (self.isImpostor && self.killCooldown <= 0) { for (var i = 0; i < aiCharacters.length; i++) { var target = aiCharacters[i]; if (!target.isImpostor && !target.isDead && target !== self) { var killDistance = Math.sqrt((target.x - self.x) * (target.x - self.x) + (target.y - self.y) * (target.y - self.y)); if (killDistance < 100) { target.isDead = true; target.visible = false; var deadBody = new DeadBody(); deadBody.x = target.x; deadBody.y = target.y; deadBodies.push(deadBody); game.addChild(deadBody); self.killCooldown = 900; LK.getSound('kill').play(); break; } } } } }; return self; }); var DeadBody = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('body', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var EmergencyButton = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('emergencyButton', { anchorX: 0.5, anchorY: 0.5 }); self.down = function (x, y, obj) { if (!votingPhase && !gameEnded) { startVotingPhase(); } }; return self; }); var Mission = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('mission', { anchorX: 0.5, anchorY: 0.5 }); self.completed = false; self.missionType = ''; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.isImpostor = false; self.isDead = false; self.killCooldown = 0; self.speed = 3; self.completedMissions = 0; self.update = function () { if (self.killCooldown > 0) { self.killCooldown--; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x111111 }); /**** * Game Code ****/ var gameState = 'menu'; // menu, waiting, loading, playing, voting, ended var gameTimer = 0; var votingPhase = false; var votingTimer = 0; var gameEnded = false; var player; var aiCharacters = []; var missions = []; var deadBodies = []; var emergencyButton; var chatMessages = []; var votingResults = {}; var totalMissions = 8; var aiNames = ['Mroxito', 'Donpollo123', 'newplayerXD', 'Luzbelito', 'Sr_Bigotes', 'Anonymus', 'Fabi_gamer', 'xX_ProKiller_Xx', 'Lupita_la_mejor', 'el_pana_misterio', 'Elver_Galarga', 'Pato_Ganso', 'Kevinoo', 'CheemsXD']; var missionTypes = ['Limpiar cocina', 'Sumar 2+2', 'Reciclar basura', 'Cargar propulsores', 'Ajustar antena', 'Calibrar motor', 'Inspeccionar muestras', 'Reparar cables']; var chatPhrases = ['Hola!', 'Donde?', 'q paso', 'busco novia', 'hubieron muertos?', 'donde fue', 'hola xd', 'espera todos somos inteligencias artificiales?', 'MUSTAAAARD', 'alguien juega roba un brainrot?', 'presto server priv de roba un brainrot', 'Skibidi Brrr', 'dejense de bromas, saben quien fue?', 'donde?', 'dnd?', 'XD', 'te acuerdas de mi?', 'amogus', 'sus', 'no era yo', 'es el, lo vi', 'voten por mi, no fui yo', 'hola xd', 'donde estabas', 'voten por el rojo', 'era el amarillo', 'estaba en la sala de las tareas', 'vote por ti xd', 'que paso?', 'saben quien es?', 'que se siente ser el impostor?', 'creo que es el impostor', 'era el de verde, lo vi', 'siganme', 'voten', 'era yo... mentira xd', 'no fui yo', 'no se, estaba en la nave', 'hola :v', 'Me gusta el pan', 'Quiero mi pizza', 'Creo que fue el amarillo', 'No sé quién es, no lo vi', '¿Alguien me ayuda con las tareas?', '¡Qué aburrido es esto!', '¿Cuándo termina?', 'Voté por el negro', 'Él estaba en la sala de cámaras', '¿Quién era?', 'Creo que me persiguen', 'El impostor está entre nosotros', 'Era el de azul']; var impostorChatPhrase = 'soy nuevo, y nose como pero me meti en la alcantarilla, porque?'; var mapLocations = ['cocina', 'motores', 'electricidad', 'navegación', 'comunicaciones', 'almacén', 'armería', 'escudos', 'oxígeno', 'reactor']; var statusText; var missionText; var timerText; var chatContainer; var voteContainer; function showMainMenu() { game.setBackgroundColor(0x111111); var background = game.attachAsset('mapBackground', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); var playButton = new Container(); var buttonBg = LK.getAsset('emergencyButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); var buttonText = new Text2('Jugar', { size: 80, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); playButton.addChild(buttonBg); playButton.addChild(buttonText); playButton.x = 1024; playButton.y = 1366; game.addChild(playButton); playButton.down = function (x, y, obj) { if (gameState === 'menu') { gameState = 'waiting'; game.removeChild(playButton); showWaitingRoom(); } }; } function showWaitingRoom() { statusText = new Text2('Sala de espera...', { size: 60, fill: 0xFFFFFF }); statusText.anchor.set(0.5, 0.5); statusText.x = 0; statusText.y = -100; LK.gui.center.addChild(statusText); // Create 14 AI characters in waiting room for (var i = 0; i < 14; i++) { var ai = game.addChild(new AICharacter()); ai.x = 200 + i % 7 * 200; ai.y = 500 + Math.floor(i / 7) * 150; ai.username = aiNames[i]; aiCharacters.push(ai); } // Create player in waiting room player = game.addChild(new Player()); player.x = 1024; player.y = 800; gameTimer = 0; } function showLoadingScreen() { game.removeChildren(); statusText.setText('Cargando...'); statusText.anchor.set(0.5, 0.5); statusText.x = 0; statusText.y = 0; LK.gui.center.removeChildren(); LK.gui.center.addChild(statusText); } function initGame() { game.removeChildren(); LK.gui.center.removeChildren(); LK.gui.topLeft.removeChildren(); LK.gui.topRight.removeChildren(); LK.gui.left.removeChildren(); game.setBackgroundColor(0x111111); var background = game.attachAsset('mapBackground', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); statusText = new Text2('Esperando...', { size: 60, fill: 0xFFFFFF }); statusText.anchor.set(0.5, 0); LK.gui.top.addChild(statusText); statusText.y = 100; missionText = new Text2('Misiones: 0/' + totalMissions, { size: 50, fill: 0xFFFF00 }); missionText.anchor.set(0, 0); LK.gui.topLeft.addChild(missionText); missionText.x = 150; missionText.y = 50; timerText = new Text2('', { size: 45, fill: 0xFF6666 }); timerText.anchor.set(1, 0); LK.gui.topRight.addChild(timerText); timerText.x = -50; timerText.y = 50; chatContainer = new Container(); LK.gui.left.addChild(chatContainer); chatContainer.x = 50; chatContainer.y = -200; voteContainer = new Container(); LK.gui.center.addChild(voteContainer); // Create map button var mapButton = new Container(); var mapBg = LK.getAsset('mission', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); var mapText = new Text2('MAPA', { size: 30, fill: 0x000000 }); mapText.anchor.set(0.5, 0.5); mapButton.addChild(mapBg); mapButton.addChild(mapText); LK.gui.bottomLeft.addChild(mapButton); mapButton.x = 100; mapButton.y = -100; mapButton.down = function (x, y, obj) { if (gameState === 'playing' && !votingPhase && !gameEnded && !player.isDead) { showMap(); } }; emergencyButton = game.addChild(new EmergencyButton()); emergencyButton.x = 1024; emergencyButton.y = 400; // Reset AI characters and assign roles aiCharacters = []; // Create player first player = game.addChild(new Player()); player.x = 1024; player.y = 1366; player.isImpostor = Math.random() < 0.3; // Shuffle AI names array var shuffledNames = aiNames.slice(); for (var i = shuffledNames.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = shuffledNames[i]; shuffledNames[i] = shuffledNames[j]; shuffledNames[j] = temp; } for (var i = 0; i < 14; i++) { var ai = game.addChild(new AICharacter()); ai.x = Math.random() * 1800 + 100; ai.y = Math.random() * 1500 + 200; ai.username = shuffledNames[i]; ai.isImpostor = i < 2; if (ai.isImpostor) { var impostorGraphics = ai.attachAsset('impostor', { anchorX: 0.5, anchorY: 0.5 }); ai.removeChild(ai.children[0]); ai.addChild(impostorGraphics); } aiCharacters.push(ai); } createMissions(); if (player.isImpostor) { statusText.setText('Impostor, mata a los demás para ganar'); statusText.tint = 0xff0000; missionText.setText('Cooldown: 15s'); } else { statusText.setText('Eres un tripulante, cumple tus misiones para ganar el juego'); statusText.tint = 0x00ff00; } gameState = 'playing'; } function createMissions() { for (var i = 0; i < totalMissions; i++) { var mission = game.addChild(new Mission()); mission.x = Math.random() * 1600 + 200; mission.y = Math.random() * 1400 + 300; mission.missionType = missionTypes[i % missionTypes.length]; missions.push(mission); } } function startVotingPhase() { if (votingPhase || gameEnded) return; votingPhase = true; votingTimer = 1800; chatContainer.removeChildren(); chatMessages = []; votingResults = {}; LK.getSound('emergency').play(); statusText.setText('REUNIÓN DE EMERGENCIA'); statusText.tint = 0xffff00; timerText.setText('30s'); for (var i = 0; i < aiCharacters.length; i++) { if (!aiCharacters[i].isDead) { votingResults[aiCharacters[i].username] = 0; } } votingResults['Player'] = 0; votingResults['skip'] = 0; showVotingUI(); } function showVotingUI() { voteContainer.removeChildren(); var voteBackground = LK.getAsset('mapBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.6, alpha: 0.9 }); voteContainer.addChild(voteBackground); var voteTitle = new Text2('VOTAR PARA EXPULSAR', { size: 50, fill: 0xFFFFFF }); voteTitle.anchor.set(0.5, 0.5); voteTitle.x = 0; voteTitle.y = -200; voteContainer.addChild(voteTitle); var yPos = -100; var aliveCharacters = []; if (!player.isDead) { aliveCharacters.push({ name: 'Player', isPlayer: true }); } for (var i = 0; i < aiCharacters.length; i++) { if (!aiCharacters[i].isDead) { aliveCharacters.push({ name: aiCharacters[i].username, isPlayer: false }); } } for (var j = 0; j < aliveCharacters.length; j++) { var character = aliveCharacters[j]; var voteButton = new Container(); var buttonBg = LK.getAsset('crewmate', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var buttonText = new Text2(character.name, { size: 35, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.y = 60; voteButton.addChild(buttonBg); voteButton.addChild(buttonText); voteButton.x = (j % 4 - 1.5) * 200; voteButton.y = yPos + Math.floor(j / 4) * 120; voteButton.targetName = character.name; voteButton.down = function (x, y, obj) { if (votingPhase && votingTimer > 900) { castVote(obj.targetName); } }; voteContainer.addChild(voteButton); } var skipButton = new Container(); var skipBg = LK.getAsset('mission', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); var skipText = new Text2('SALTAR', { size: 35, fill: 0x000000 }); skipText.anchor.set(0.5, 0.5); skipButton.addChild(skipBg); skipButton.addChild(skipText); skipButton.x = 0; skipButton.y = yPos + Math.floor(aliveCharacters.length / 4 + 1) * 120; skipButton.down = function (x, y, obj) { if (votingPhase && votingTimer > 900) { castVote('skip'); } }; voteContainer.addChild(skipButton); } function castVote(target) { LK.getSound('vote').play(); votingResults[target]++; votingTimer = 900; } function processAIChat() { if (!votingPhase || votingTimer < 900) return; var aliveAI = []; for (var i = 0; i < aiCharacters.length; i++) { if (!aiCharacters[i].isDead) { aliveAI.push(aiCharacters[i]); } } if (aliveAI.length === 0) return; var randomAI = aliveAI[Math.floor(Math.random() * aliveAI.length)]; var phrase; // 5% chance for impostor AI to send special message if (randomAI.isImpostor && Math.random() < 0.05) { phrase = impostorChatPhrase; } else { phrase = chatPhrases[Math.floor(Math.random() * chatPhrases.length)]; } addChatMessage(randomAI.username + ': ' + phrase); } function addChatMessage(message) { // Create background for better visibility var chatBg = LK.getAsset('mapBackground', { anchorX: 0, anchorY: 0, scaleX: 0.4, scaleY: 0.06, alpha: 1.0 }); chatBg.y = chatMessages.length * 40; chatContainer.addChild(chatBg); var chatText = new Text2(message, { size: 32, fill: 0xFFFFFF }); chatText.anchor.set(0, 0); chatText.y = chatMessages.length * 40 + 5; chatText.x = 10; chatText.alpha = 1.0; chatContainer.addChild(chatText); chatMessages.push({ text: chatText, bg: chatBg }); if (chatMessages.length > 8) { chatContainer.removeChild(chatMessages[0].text); chatContainer.removeChild(chatMessages[0].bg); chatMessages.shift(); for (var i = 0; i < chatMessages.length; i++) { chatMessages[i].text.y = i * 40 + 5; chatMessages[i].bg.y = i * 40; } } } function endVotingPhase() { votingPhase = false; voteContainer.removeChildren(); chatContainer.removeChildren(); chatMessages = []; var maxVotes = 0; var votedOut = ''; var tied = false; for (var name in votingResults) { if (votingResults[name] > maxVotes) { maxVotes = votingResults[name]; votedOut = name; tied = false; } else if (votingResults[name] === maxVotes && maxVotes > 0) { tied = true; } } if (tied || votedOut === 'skip' || maxVotes === 0) { statusText.setText('Nadie fue expulsado'); statusText.tint = 0xffffff; } else { if (votedOut === 'Player') { player.isDead = true; player.visible = false; statusText.setText('Fuiste expulsado!'); statusText.tint = 0xff0000; } else { for (var i = 0; i < aiCharacters.length; i++) { if (aiCharacters[i].username === votedOut) { aiCharacters[i].isDead = true; aiCharacters[i].visible = false; var wasImpostor = aiCharacters[i].isImpostor ? ' (IMPOSTOR)' : ' (TRIPULANTE)'; statusText.setText(votedOut + ' fue expulsado' + wasImpostor); statusText.tint = 0xff6666; break; } } } } LK.setTimeout(function () { if (player.isImpostor) { statusText.setText('Eres IMPOSTOR - Elimina a los tripulantes'); statusText.tint = 0xff0000; } else { statusText.setText('Eres TRIPULANTE - Completa las misiones'); statusText.tint = 0x00ff00; } checkGameEnd(); }, 3000); } function showMap() { // Create map overlay var mapOverlay = new Container(); var mapBg = LK.getAsset('mapBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.9, scaleY: 0.7, alpha: 0.95 }); mapOverlay.addChild(mapBg); var mapTitle = new Text2('MAPA - MISIONES', { size: 50, fill: 0xFFFFFF }); mapTitle.anchor.set(0.5, 0.5); mapTitle.x = 0; mapTitle.y = -250; mapOverlay.addChild(mapTitle); // Show remaining missions on map for (var i = 0; i < missions.length; i++) { if (!missions[i].completed) { var missionDot = LK.getAsset('mission', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); missionDot.x = (missions[i].x - 1024) * 0.7; missionDot.y = (missions[i].y - 1366) * 0.5; mapOverlay.addChild(missionDot); } } var closeButton = new Container(); var closeBg = LK.getAsset('emergencyButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var closeText = new Text2('CERRAR', { size: 35, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeButton.addChild(closeBg); closeButton.addChild(closeText); closeButton.x = 0; closeButton.y = 280; closeButton.down = function (x, y, obj) { LK.gui.center.removeChild(mapOverlay); }; mapOverlay.addChild(closeButton); LK.gui.center.addChild(mapOverlay); } function checkGameEnd() { if (gameEnded) return; var aliveCrewmates = 0; var aliveImpostors = 0; if (!player.isDead) { if (player.isImpostor) { aliveImpostors++; } else { aliveCrewmates++; } } for (var i = 0; i < aiCharacters.length; i++) { if (!aiCharacters[i].isDead) { if (aiCharacters[i].isImpostor) { aliveImpostors++; } else { aliveCrewmates++; } } } if (aliveImpostors >= aliveCrewmates && aliveImpostors > 0) { gameEnded = true; statusText.setText('LOS IMPOSTORES GANAN!'); statusText.tint = 0xff0000; if (player.isImpostor && !player.isDead) { LK.showYouWin(); } else { LK.showGameOver(); } return; } if (aliveImpostors === 0) { gameEnded = true; statusText.setText('LOS TRIPULANTES GANAN!'); statusText.tint = 0x00ff00; if (!player.isImpostor && !player.isDead) { LK.showYouWin(); } else { LK.showGameOver(); } return; } if (!player.isImpostor && player.completedMissions >= totalMissions) { gameEnded = true; statusText.setText('TODAS LAS MISIONES COMPLETADAS!'); statusText.tint = 0x00ff00; LK.showYouWin(); return; } } game.move = function (x, y, obj) { if (gameState !== 'playing' || votingPhase || gameEnded || player.isDead) return; var dx = x - player.x; var dy = y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > player.speed) { player.x += dx / distance * player.speed; player.y += dy / distance * player.speed; } else { player.x = x; player.y = y; } player.x = Math.max(50, Math.min(1998, player.x)); player.y = Math.max(150, Math.min(2682, player.y)); if (!player.isImpostor) { for (var i = 0; i < missions.length; i++) { var mission = missions[i]; if (!mission.completed && player.intersects(mission)) { mission.completed = true; mission.visible = false; player.completedMissions++; LK.getSound('missionComplete').play(); missionText.setText('Misiones: ' + player.completedMissions + '/' + totalMissions); break; } } } if (player.isImpostor && player.killCooldown <= 0) { for (var j = 0; j < aiCharacters.length; j++) { var target = aiCharacters[j]; if (!target.isImpostor && !target.isDead) { var killDistance = Math.sqrt((target.x - player.x) * (target.x - player.x) + (target.y - player.y) * (target.y - player.y)); if (killDistance < 120) { target.isDead = true; target.visible = false; var deadBody = new DeadBody(); deadBody.x = target.x; deadBody.y = target.y; deadBodies.push(deadBody); game.addChild(deadBody); player.killCooldown = 900; LK.getSound('kill').play(); break; } } } } }; game.update = function () { if (gameState === 'menu') { return; } if (gameState === 'waiting') { gameTimer++; if (gameTimer >= 600) { // 10 seconds at 60fps gameState = 'loading'; showLoadingScreen(); gameTimer = 0; } return; } if (gameState === 'loading') { gameTimer++; if (gameTimer >= 180) { // 3 seconds at 60fps initGame(); } return; } if (gameState !== 'playing') return; if (votingPhase) { votingTimer--; timerText.setText(Math.ceil(votingTimer / 60) + 's'); if (votingTimer > 900 && votingTimer % 120 === 0) { processAIChat(); } if (votingTimer === 900) { for (var i = 0; i < aiCharacters.length; i++) { if (!aiCharacters[i].isDead) { var voteOptions = []; if (!player.isDead) voteOptions.push('Player'); for (var j = 0; j < aiCharacters.length; j++) { if (!aiCharacters[j].isDead && i !== j) { voteOptions.push(aiCharacters[j].username); } } voteOptions.push('skip'); var aiVote = voteOptions[Math.floor(Math.random() * voteOptions.length)]; votingResults[aiVote]++; } } } if (votingTimer <= 0) { endVotingPhase(); } } else { if (player.isImpostor && player.killCooldown > 0) { missionText.setText('Cooldown: ' + Math.ceil(player.killCooldown / 60) + 's'); } else if (player.isImpostor) { missionText.setText('Cooldown: Listo'); } checkGameEnd(); } }; showMainMenu();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var AICharacter = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('crewmate', {
anchorX: 0.5,
anchorY: 0.5
});
self.isImpostor = false;
self.isDead = false;
self.killCooldown = 0;
self.moveTimer = 0;
self.targetX = 0;
self.targetY = 0;
self.username = '';
self.speed = 2;
self.update = function () {
if (self.isDead) return;
if (self.killCooldown > 0) {
self.killCooldown--;
}
self.moveTimer--;
if (self.moveTimer <= 0) {
self.targetX = Math.random() * 1800 + 100;
self.targetY = Math.random() * 1500 + 200;
self.moveTimer = Math.random() * 300 + 120;
}
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
if (self.isImpostor && self.killCooldown <= 0) {
for (var i = 0; i < aiCharacters.length; i++) {
var target = aiCharacters[i];
if (!target.isImpostor && !target.isDead && target !== self) {
var killDistance = Math.sqrt((target.x - self.x) * (target.x - self.x) + (target.y - self.y) * (target.y - self.y));
if (killDistance < 100) {
target.isDead = true;
target.visible = false;
var deadBody = new DeadBody();
deadBody.x = target.x;
deadBody.y = target.y;
deadBodies.push(deadBody);
game.addChild(deadBody);
self.killCooldown = 900;
LK.getSound('kill').play();
break;
}
}
}
}
};
return self;
});
var DeadBody = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('body', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var EmergencyButton = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('emergencyButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function (x, y, obj) {
if (!votingPhase && !gameEnded) {
startVotingPhase();
}
};
return self;
});
var Mission = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('mission', {
anchorX: 0.5,
anchorY: 0.5
});
self.completed = false;
self.missionType = '';
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.isImpostor = false;
self.isDead = false;
self.killCooldown = 0;
self.speed = 3;
self.completedMissions = 0;
self.update = function () {
if (self.killCooldown > 0) {
self.killCooldown--;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x111111
});
/****
* Game Code
****/
var gameState = 'menu'; // menu, waiting, loading, playing, voting, ended
var gameTimer = 0;
var votingPhase = false;
var votingTimer = 0;
var gameEnded = false;
var player;
var aiCharacters = [];
var missions = [];
var deadBodies = [];
var emergencyButton;
var chatMessages = [];
var votingResults = {};
var totalMissions = 8;
var aiNames = ['Mroxito', 'Donpollo123', 'newplayerXD', 'Luzbelito', 'Sr_Bigotes', 'Anonymus', 'Fabi_gamer', 'xX_ProKiller_Xx', 'Lupita_la_mejor', 'el_pana_misterio', 'Elver_Galarga', 'Pato_Ganso', 'Kevinoo', 'CheemsXD'];
var missionTypes = ['Limpiar cocina', 'Sumar 2+2', 'Reciclar basura', 'Cargar propulsores', 'Ajustar antena', 'Calibrar motor', 'Inspeccionar muestras', 'Reparar cables'];
var chatPhrases = ['Hola!', 'Donde?', 'q paso', 'busco novia', 'hubieron muertos?', 'donde fue', 'hola xd', 'espera todos somos inteligencias artificiales?', 'MUSTAAAARD', 'alguien juega roba un brainrot?', 'presto server priv de roba un brainrot', 'Skibidi Brrr', 'dejense de bromas, saben quien fue?', 'donde?', 'dnd?', 'XD', 'te acuerdas de mi?', 'amogus', 'sus', 'no era yo', 'es el, lo vi', 'voten por mi, no fui yo', 'hola xd', 'donde estabas', 'voten por el rojo', 'era el amarillo', 'estaba en la sala de las tareas', 'vote por ti xd', 'que paso?', 'saben quien es?', 'que se siente ser el impostor?', 'creo que es el impostor', 'era el de verde, lo vi', 'siganme', 'voten', 'era yo... mentira xd', 'no fui yo', 'no se, estaba en la nave', 'hola :v', 'Me gusta el pan', 'Quiero mi pizza', 'Creo que fue el amarillo', 'No sé quién es, no lo vi', '¿Alguien me ayuda con las tareas?', '¡Qué aburrido es esto!', '¿Cuándo termina?', 'Voté por el negro', 'Él estaba en la sala de cámaras', '¿Quién era?', 'Creo que me persiguen', 'El impostor está entre nosotros', 'Era el de azul'];
var impostorChatPhrase = 'soy nuevo, y nose como pero me meti en la alcantarilla, porque?';
var mapLocations = ['cocina', 'motores', 'electricidad', 'navegación', 'comunicaciones', 'almacén', 'armería', 'escudos', 'oxígeno', 'reactor'];
var statusText;
var missionText;
var timerText;
var chatContainer;
var voteContainer;
function showMainMenu() {
game.setBackgroundColor(0x111111);
var background = game.attachAsset('mapBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
var playButton = new Container();
var buttonBg = LK.getAsset('emergencyButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
var buttonText = new Text2('Jugar', {
size: 80,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
playButton.addChild(buttonBg);
playButton.addChild(buttonText);
playButton.x = 1024;
playButton.y = 1366;
game.addChild(playButton);
playButton.down = function (x, y, obj) {
if (gameState === 'menu') {
gameState = 'waiting';
game.removeChild(playButton);
showWaitingRoom();
}
};
}
function showWaitingRoom() {
statusText = new Text2('Sala de espera...', {
size: 60,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0.5);
statusText.x = 0;
statusText.y = -100;
LK.gui.center.addChild(statusText);
// Create 14 AI characters in waiting room
for (var i = 0; i < 14; i++) {
var ai = game.addChild(new AICharacter());
ai.x = 200 + i % 7 * 200;
ai.y = 500 + Math.floor(i / 7) * 150;
ai.username = aiNames[i];
aiCharacters.push(ai);
}
// Create player in waiting room
player = game.addChild(new Player());
player.x = 1024;
player.y = 800;
gameTimer = 0;
}
function showLoadingScreen() {
game.removeChildren();
statusText.setText('Cargando...');
statusText.anchor.set(0.5, 0.5);
statusText.x = 0;
statusText.y = 0;
LK.gui.center.removeChildren();
LK.gui.center.addChild(statusText);
}
function initGame() {
game.removeChildren();
LK.gui.center.removeChildren();
LK.gui.topLeft.removeChildren();
LK.gui.topRight.removeChildren();
LK.gui.left.removeChildren();
game.setBackgroundColor(0x111111);
var background = game.attachAsset('mapBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
statusText = new Text2('Esperando...', {
size: 60,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0);
LK.gui.top.addChild(statusText);
statusText.y = 100;
missionText = new Text2('Misiones: 0/' + totalMissions, {
size: 50,
fill: 0xFFFF00
});
missionText.anchor.set(0, 0);
LK.gui.topLeft.addChild(missionText);
missionText.x = 150;
missionText.y = 50;
timerText = new Text2('', {
size: 45,
fill: 0xFF6666
});
timerText.anchor.set(1, 0);
LK.gui.topRight.addChild(timerText);
timerText.x = -50;
timerText.y = 50;
chatContainer = new Container();
LK.gui.left.addChild(chatContainer);
chatContainer.x = 50;
chatContainer.y = -200;
voteContainer = new Container();
LK.gui.center.addChild(voteContainer);
// Create map button
var mapButton = new Container();
var mapBg = LK.getAsset('mission', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
var mapText = new Text2('MAPA', {
size: 30,
fill: 0x000000
});
mapText.anchor.set(0.5, 0.5);
mapButton.addChild(mapBg);
mapButton.addChild(mapText);
LK.gui.bottomLeft.addChild(mapButton);
mapButton.x = 100;
mapButton.y = -100;
mapButton.down = function (x, y, obj) {
if (gameState === 'playing' && !votingPhase && !gameEnded && !player.isDead) {
showMap();
}
};
emergencyButton = game.addChild(new EmergencyButton());
emergencyButton.x = 1024;
emergencyButton.y = 400;
// Reset AI characters and assign roles
aiCharacters = [];
// Create player first
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
player.isImpostor = Math.random() < 0.3;
// Shuffle AI names array
var shuffledNames = aiNames.slice();
for (var i = shuffledNames.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = shuffledNames[i];
shuffledNames[i] = shuffledNames[j];
shuffledNames[j] = temp;
}
for (var i = 0; i < 14; i++) {
var ai = game.addChild(new AICharacter());
ai.x = Math.random() * 1800 + 100;
ai.y = Math.random() * 1500 + 200;
ai.username = shuffledNames[i];
ai.isImpostor = i < 2;
if (ai.isImpostor) {
var impostorGraphics = ai.attachAsset('impostor', {
anchorX: 0.5,
anchorY: 0.5
});
ai.removeChild(ai.children[0]);
ai.addChild(impostorGraphics);
}
aiCharacters.push(ai);
}
createMissions();
if (player.isImpostor) {
statusText.setText('Impostor, mata a los demás para ganar');
statusText.tint = 0xff0000;
missionText.setText('Cooldown: 15s');
} else {
statusText.setText('Eres un tripulante, cumple tus misiones para ganar el juego');
statusText.tint = 0x00ff00;
}
gameState = 'playing';
}
function createMissions() {
for (var i = 0; i < totalMissions; i++) {
var mission = game.addChild(new Mission());
mission.x = Math.random() * 1600 + 200;
mission.y = Math.random() * 1400 + 300;
mission.missionType = missionTypes[i % missionTypes.length];
missions.push(mission);
}
}
function startVotingPhase() {
if (votingPhase || gameEnded) return;
votingPhase = true;
votingTimer = 1800;
chatContainer.removeChildren();
chatMessages = [];
votingResults = {};
LK.getSound('emergency').play();
statusText.setText('REUNIÓN DE EMERGENCIA');
statusText.tint = 0xffff00;
timerText.setText('30s');
for (var i = 0; i < aiCharacters.length; i++) {
if (!aiCharacters[i].isDead) {
votingResults[aiCharacters[i].username] = 0;
}
}
votingResults['Player'] = 0;
votingResults['skip'] = 0;
showVotingUI();
}
function showVotingUI() {
voteContainer.removeChildren();
var voteBackground = LK.getAsset('mapBackground', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.6,
alpha: 0.9
});
voteContainer.addChild(voteBackground);
var voteTitle = new Text2('VOTAR PARA EXPULSAR', {
size: 50,
fill: 0xFFFFFF
});
voteTitle.anchor.set(0.5, 0.5);
voteTitle.x = 0;
voteTitle.y = -200;
voteContainer.addChild(voteTitle);
var yPos = -100;
var aliveCharacters = [];
if (!player.isDead) {
aliveCharacters.push({
name: 'Player',
isPlayer: true
});
}
for (var i = 0; i < aiCharacters.length; i++) {
if (!aiCharacters[i].isDead) {
aliveCharacters.push({
name: aiCharacters[i].username,
isPlayer: false
});
}
}
for (var j = 0; j < aliveCharacters.length; j++) {
var character = aliveCharacters[j];
var voteButton = new Container();
var buttonBg = LK.getAsset('crewmate', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
var buttonText = new Text2(character.name, {
size: 35,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 60;
voteButton.addChild(buttonBg);
voteButton.addChild(buttonText);
voteButton.x = (j % 4 - 1.5) * 200;
voteButton.y = yPos + Math.floor(j / 4) * 120;
voteButton.targetName = character.name;
voteButton.down = function (x, y, obj) {
if (votingPhase && votingTimer > 900) {
castVote(obj.targetName);
}
};
voteContainer.addChild(voteButton);
}
var skipButton = new Container();
var skipBg = LK.getAsset('mission', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
var skipText = new Text2('SALTAR', {
size: 35,
fill: 0x000000
});
skipText.anchor.set(0.5, 0.5);
skipButton.addChild(skipBg);
skipButton.addChild(skipText);
skipButton.x = 0;
skipButton.y = yPos + Math.floor(aliveCharacters.length / 4 + 1) * 120;
skipButton.down = function (x, y, obj) {
if (votingPhase && votingTimer > 900) {
castVote('skip');
}
};
voteContainer.addChild(skipButton);
}
function castVote(target) {
LK.getSound('vote').play();
votingResults[target]++;
votingTimer = 900;
}
function processAIChat() {
if (!votingPhase || votingTimer < 900) return;
var aliveAI = [];
for (var i = 0; i < aiCharacters.length; i++) {
if (!aiCharacters[i].isDead) {
aliveAI.push(aiCharacters[i]);
}
}
if (aliveAI.length === 0) return;
var randomAI = aliveAI[Math.floor(Math.random() * aliveAI.length)];
var phrase;
// 5% chance for impostor AI to send special message
if (randomAI.isImpostor && Math.random() < 0.05) {
phrase = impostorChatPhrase;
} else {
phrase = chatPhrases[Math.floor(Math.random() * chatPhrases.length)];
}
addChatMessage(randomAI.username + ': ' + phrase);
}
function addChatMessage(message) {
// Create background for better visibility
var chatBg = LK.getAsset('mapBackground', {
anchorX: 0,
anchorY: 0,
scaleX: 0.4,
scaleY: 0.06,
alpha: 1.0
});
chatBg.y = chatMessages.length * 40;
chatContainer.addChild(chatBg);
var chatText = new Text2(message, {
size: 32,
fill: 0xFFFFFF
});
chatText.anchor.set(0, 0);
chatText.y = chatMessages.length * 40 + 5;
chatText.x = 10;
chatText.alpha = 1.0;
chatContainer.addChild(chatText);
chatMessages.push({
text: chatText,
bg: chatBg
});
if (chatMessages.length > 8) {
chatContainer.removeChild(chatMessages[0].text);
chatContainer.removeChild(chatMessages[0].bg);
chatMessages.shift();
for (var i = 0; i < chatMessages.length; i++) {
chatMessages[i].text.y = i * 40 + 5;
chatMessages[i].bg.y = i * 40;
}
}
}
function endVotingPhase() {
votingPhase = false;
voteContainer.removeChildren();
chatContainer.removeChildren();
chatMessages = [];
var maxVotes = 0;
var votedOut = '';
var tied = false;
for (var name in votingResults) {
if (votingResults[name] > maxVotes) {
maxVotes = votingResults[name];
votedOut = name;
tied = false;
} else if (votingResults[name] === maxVotes && maxVotes > 0) {
tied = true;
}
}
if (tied || votedOut === 'skip' || maxVotes === 0) {
statusText.setText('Nadie fue expulsado');
statusText.tint = 0xffffff;
} else {
if (votedOut === 'Player') {
player.isDead = true;
player.visible = false;
statusText.setText('Fuiste expulsado!');
statusText.tint = 0xff0000;
} else {
for (var i = 0; i < aiCharacters.length; i++) {
if (aiCharacters[i].username === votedOut) {
aiCharacters[i].isDead = true;
aiCharacters[i].visible = false;
var wasImpostor = aiCharacters[i].isImpostor ? ' (IMPOSTOR)' : ' (TRIPULANTE)';
statusText.setText(votedOut + ' fue expulsado' + wasImpostor);
statusText.tint = 0xff6666;
break;
}
}
}
}
LK.setTimeout(function () {
if (player.isImpostor) {
statusText.setText('Eres IMPOSTOR - Elimina a los tripulantes');
statusText.tint = 0xff0000;
} else {
statusText.setText('Eres TRIPULANTE - Completa las misiones');
statusText.tint = 0x00ff00;
}
checkGameEnd();
}, 3000);
}
function showMap() {
// Create map overlay
var mapOverlay = new Container();
var mapBg = LK.getAsset('mapBackground', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.7,
alpha: 0.95
});
mapOverlay.addChild(mapBg);
var mapTitle = new Text2('MAPA - MISIONES', {
size: 50,
fill: 0xFFFFFF
});
mapTitle.anchor.set(0.5, 0.5);
mapTitle.x = 0;
mapTitle.y = -250;
mapOverlay.addChild(mapTitle);
// Show remaining missions on map
for (var i = 0; i < missions.length; i++) {
if (!missions[i].completed) {
var missionDot = LK.getAsset('mission', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
missionDot.x = (missions[i].x - 1024) * 0.7;
missionDot.y = (missions[i].y - 1366) * 0.5;
mapOverlay.addChild(missionDot);
}
}
var closeButton = new Container();
var closeBg = LK.getAsset('emergencyButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
var closeText = new Text2('CERRAR', {
size: 35,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeButton.addChild(closeBg);
closeButton.addChild(closeText);
closeButton.x = 0;
closeButton.y = 280;
closeButton.down = function (x, y, obj) {
LK.gui.center.removeChild(mapOverlay);
};
mapOverlay.addChild(closeButton);
LK.gui.center.addChild(mapOverlay);
}
function checkGameEnd() {
if (gameEnded) return;
var aliveCrewmates = 0;
var aliveImpostors = 0;
if (!player.isDead) {
if (player.isImpostor) {
aliveImpostors++;
} else {
aliveCrewmates++;
}
}
for (var i = 0; i < aiCharacters.length; i++) {
if (!aiCharacters[i].isDead) {
if (aiCharacters[i].isImpostor) {
aliveImpostors++;
} else {
aliveCrewmates++;
}
}
}
if (aliveImpostors >= aliveCrewmates && aliveImpostors > 0) {
gameEnded = true;
statusText.setText('LOS IMPOSTORES GANAN!');
statusText.tint = 0xff0000;
if (player.isImpostor && !player.isDead) {
LK.showYouWin();
} else {
LK.showGameOver();
}
return;
}
if (aliveImpostors === 0) {
gameEnded = true;
statusText.setText('LOS TRIPULANTES GANAN!');
statusText.tint = 0x00ff00;
if (!player.isImpostor && !player.isDead) {
LK.showYouWin();
} else {
LK.showGameOver();
}
return;
}
if (!player.isImpostor && player.completedMissions >= totalMissions) {
gameEnded = true;
statusText.setText('TODAS LAS MISIONES COMPLETADAS!');
statusText.tint = 0x00ff00;
LK.showYouWin();
return;
}
}
game.move = function (x, y, obj) {
if (gameState !== 'playing' || votingPhase || gameEnded || player.isDead) return;
var dx = x - player.x;
var dy = y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > player.speed) {
player.x += dx / distance * player.speed;
player.y += dy / distance * player.speed;
} else {
player.x = x;
player.y = y;
}
player.x = Math.max(50, Math.min(1998, player.x));
player.y = Math.max(150, Math.min(2682, player.y));
if (!player.isImpostor) {
for (var i = 0; i < missions.length; i++) {
var mission = missions[i];
if (!mission.completed && player.intersects(mission)) {
mission.completed = true;
mission.visible = false;
player.completedMissions++;
LK.getSound('missionComplete').play();
missionText.setText('Misiones: ' + player.completedMissions + '/' + totalMissions);
break;
}
}
}
if (player.isImpostor && player.killCooldown <= 0) {
for (var j = 0; j < aiCharacters.length; j++) {
var target = aiCharacters[j];
if (!target.isImpostor && !target.isDead) {
var killDistance = Math.sqrt((target.x - player.x) * (target.x - player.x) + (target.y - player.y) * (target.y - player.y));
if (killDistance < 120) {
target.isDead = true;
target.visible = false;
var deadBody = new DeadBody();
deadBody.x = target.x;
deadBody.y = target.y;
deadBodies.push(deadBody);
game.addChild(deadBody);
player.killCooldown = 900;
LK.getSound('kill').play();
break;
}
}
}
}
};
game.update = function () {
if (gameState === 'menu') {
return;
}
if (gameState === 'waiting') {
gameTimer++;
if (gameTimer >= 600) {
// 10 seconds at 60fps
gameState = 'loading';
showLoadingScreen();
gameTimer = 0;
}
return;
}
if (gameState === 'loading') {
gameTimer++;
if (gameTimer >= 180) {
// 3 seconds at 60fps
initGame();
}
return;
}
if (gameState !== 'playing') return;
if (votingPhase) {
votingTimer--;
timerText.setText(Math.ceil(votingTimer / 60) + 's');
if (votingTimer > 900 && votingTimer % 120 === 0) {
processAIChat();
}
if (votingTimer === 900) {
for (var i = 0; i < aiCharacters.length; i++) {
if (!aiCharacters[i].isDead) {
var voteOptions = [];
if (!player.isDead) voteOptions.push('Player');
for (var j = 0; j < aiCharacters.length; j++) {
if (!aiCharacters[j].isDead && i !== j) {
voteOptions.push(aiCharacters[j].username);
}
}
voteOptions.push('skip');
var aiVote = voteOptions[Math.floor(Math.random() * voteOptions.length)];
votingResults[aiVote]++;
}
}
}
if (votingTimer <= 0) {
endVotingPhase();
}
} else {
if (player.isImpostor && player.killCooldown > 0) {
missionText.setText('Cooldown: ' + Math.ceil(player.killCooldown / 60) + 's');
} else if (player.isImpostor) {
missionText.setText('Cooldown: Listo');
}
checkGameEnd();
}
};
showMainMenu();