amogos / index.html
kate-line's picture
Add 2 files
4b7f184 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Mini Among Us Enhanced</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* Reset and base styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: 'Arial', sans-serif;
background-color: #0a0a1a;
color: white;
overflow: hidden;
height: 100vh;
width: 100vw;
position: relative;
}
/* Game container */
#game-container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
/* Game map */
#game-map {
position: absolute;
width: 2500px;
height: 2500px;
background-color: #0d1b2a;
transform-origin: 0 0;
background-image:
linear-gradient(#4cc9f033 1px, transparent 1px),
linear-gradient(90deg, #4cc9f033 1px, transparent 1px);
background-size: 50px 50px;
}
/* Rooms and walls */
.room {
position: absolute;
background-color: #1b263b;
border: 4px solid #415a77;
box-shadow: 0 0 15px rgba(65, 90, 119, 0.5);
}
.room-wall {
position: absolute;
background-color: #415a77;
}
.room-door {
position: absolute;
background-color: #778da9;
z-index: 5;
}
.room-label {
position: absolute;
color: white;
font-size: 18px;
text-align: center;
width: 100%;
top: 15px;
pointer-events: none;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.8);
font-weight: bold;
}
/* Player character */
.player {
position: absolute;
width: 45px;
height: 45px;
background-color: #f72585;
border-radius: 50%;
border: 3px solid white;
z-index: 10;
transition: transform 0.15s ease;
}
.player::after {
content: '';
position: absolute;
width: 22px;
height: 17px;
background-color: white;
border-radius: 50%;
top: 9px;
left: 11px;
transform: rotate(10deg);
}
.player-shadow {
position: absolute;
width: 45px;
height: 15px;
background-color: rgba(0, 0, 0, 0.3);
border-radius: 50%;
bottom: -5px;
left: 0;
z-index: 9;
}
/* NPC characters */
.npc {
position: absolute;
width: 45px;
height: 45px;
border-radius: 50%;
border: 3px solid white;
z-index: 9;
}
.npc::after {
content: '';
position: absolute;
width: 22px;
height: 17px;
background-color: white;
border-radius: 50%;
top: 9px;
left: 11px;
transform: rotate(10deg);
}
.npc-shadow {
position: absolute;
width: 45px;
height: 15px;
background-color: rgba(0, 0, 0, 0.3);
border-radius: 50%;
bottom: -5px;
left: 0;
z-index: 8;
}
/* Tasks */
.task {
position: absolute;
width: 35px;
height: 35px;
background-color: #f8f9fa;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
font-size: 22px;
cursor: pointer;
z-index: 8;
box-shadow: 0 0 15px rgba(248, 249, 250, 0.7);
transition: transform 0.2s ease;
}
.task:hover, .task:active {
transform: scale(1.1);
}
/* Task popup */
#task-popup {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 85%;
max-width: 350px;
background-color: #1b263b;
border: 4px solid #415a77;
border-radius: 15px;
padding: 25px;
z-index: 100;
display: none;
text-align: center;
box-shadow: 0 0 30px rgba(65, 90, 119, 0.8);
}
#task-popup h3 {
margin-bottom: 20px;
color: #f72585;
font-size: 22px;
}
#task-popup p {
margin-bottom: 20px;
font-size: 16px;
line-height: 1.4;
}
#task-progress {
width: 100%;
height: 20px;
background-color: #415a77;
border-radius: 10px;
margin: 15px 0;
overflow: hidden;
}
#progress-bar {
height: 100%;
width: 0%;
background-color: #4cc9f0;
transition: width 0.3s ease;
}
#task-popup button {
background-color: #4cc9f0;
color: white;
border: none;
padding: 12px 25px;
border-radius: 8px;
margin-top: 15px;
font-size: 18px;
cursor: pointer;
transition: background-color 0.2s ease;
font-weight: bold;
}
#task-popup button:hover, #task-popup button:active {
background-color: #3aa8d8;
}
/* Controls */
#controls {
position: absolute;
bottom: 30px;
left: 30px;
width: 140px;
height: 140px;
z-index: 20;
}
.control-btn {
position: absolute;
width: 45px;
height: 45px;
background-color: rgba(255, 255, 255, 0.25);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: white;
user-select: none;
transition: background-color 0.2s ease;
}
.control-btn:active {
background-color: rgba(255, 255, 255, 0.4);
}
#up-btn { top: 0; left: 47px; }
#left-btn { top: 47px; left: 0; }
#right-btn { top: 47px; right: 0; }
#down-btn { bottom: 0; left: 47px; }
/* Task list */
#task-list {
position: absolute;
top: 25px;
right: 25px;
background-color: rgba(27, 38, 59, 0.9);
border: 3px solid #415a77;
border-radius: 12px;
padding: 15px;
max-width: 180px;
z-index: 20;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
}
#task-list h3 {
font-size: 16px;
margin-bottom: 10px;
color: #f72585;
text-align: center;
}
.task-item {
font-size: 14px;
margin-bottom: 8px;
display: flex;
align-items: center;
padding: 5px;
border-radius: 5px;
transition: background-color 0.2s ease;
}
.task-item:hover {
background-color: rgba(65, 90, 119, 0.3);
}
.task-item.completed {
text-decoration: line-through;
opacity: 0.6;
}
.task-checkbox {
width: 15px;
height: 15px;
border: 2px solid white;
border-radius: 3px;
margin-right: 8px;
display: inline-block;
}
.task-item.completed .task-checkbox {
background-color: #4cc9f0;
border-color: #4cc9f0;
}
/* Game status */
#game-status {
position: absolute;
top: 25px;
left: 25px;
background-color: rgba(27, 38, 59, 0.9);
border: 3px solid #415a77;
border-radius: 12px;
padding: 15px;
z-index: 20;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
}
#game-status h3 {
font-size: 16px;
margin-bottom: 10px;
color: #froyo85;
text-align: center;
}
#tasks-completed {
font-size: 14px;
text-align: center;
}
/* Mini map */
#mini-map {
position: absolute;
bottom: 30px;
right: 30px;
width: 120px;
height: 120px;
background-color: rgba(13, 27, 42, 0.8);
border: 3px solid #415a77;
border-radius: 10px;
z-index: 20;
overflow: hidden;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
}
#mini-map-view {
position: absolute;
width: 100%;
height: 100%;
transform-origin: 0 0;
}
.mini-map-room {
position: absolute;
background-color: rgba(65, 90, 119, 0.5);
border: 1px solid #778da9;
}
.mini-map-player {
position: absolute;
width: 6px;
height: 6px;
background-color: #f72585;
border-radius: 50%;
border: 1px solid white;
transform: translate(-3px, -3px);
z-index: 2;
}
.mini-map-npc {
position: absolute;
width: 4px;
height: 4px;
background-color: #4cc9f0;
border-radius: 50%;
border: 1px solid white;
transform: translate(-2px, -2px);
z-index: 1;
}
.mini-map-task {
position: absolute;
width: 4px;
height: 4px;
background-color: white;
border-radius: 50%;
transform: translate(-2px, -2px);
z-index: 1;
}
/* Win screen */
#win-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 200;
display: none;
}
#win-screen h2 {
font-size: 36px;
color: #f72585;
margin-bottom: 30px;
text-align: center;
text-shadow: 0 0 10px rgba(247, 37, 133, 0.7);
}
#win-screen p {
font-size: 18px;
margin-bottom: 30px;
text-align: center;
max-width: 80%;
}
#win-screen button {
background-color: #4cc9f0;
color: white;
border: none;
padding: 18px 36px;
border-radius: 10px;
font-size: 20px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: bold;
box-shadow: 0 0 20px rgba(76, 201, 240, 0.5);
}
#win-screen button:hover, #win-screen button:active {
background-color: #3aa8d8;
transform: scale(1.05);
}
/* Particles */
.particle {
position: absolute;
width: 3px;
height: 3px;
background-color: white;
border-radius: 50%;
pointer-events: none;
z-index: 7;
}
/* Emergency button */
#emergency-btn {
position: absolute;
bottom: 30px;
right: 160px;
width: 60px;
height: 60px;
background-color: #f72585;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: white;
z-index: 20;
box-shadow: 0 0 20px rgba(247, 37, 133, 0.5);
border: 3px solid white;
cursor: pointer;
transition: all 0.3s ease;
}
#emergency-btn:active {
transform: scale(0.95);
box-shadow: 0 0 10px rgba(247, 37, 133, 0.5);
}
/* Tooltip */
.tooltip {
position: absolute;
background-color: rgba(27, 38, 59, 0.9);
border: 2px solid #415a77;
border-radius: 8px;
padding: 8px 12px;
font-size: 14px;
z-index: 30;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s ease;
max-width: 200px;
text-align: center;
}
/* Loading screen */
#loading-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #0a0a1a;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 300;
}
#loading-screen h1 {
font-size: 28px;
color: #f72585;
margin-bottom: 30px;
text-shadow: 0 0 10px rgba(247, 37, 133, 0.7);
}
#loading-bar {
width: 80%;
max-width: 300px;
height: 20px;
background-color: #415a77;
border-radius: 10px;
overflow: hidden;
margin-bottom: 30px;
}
#loading-progress {
height: 100%;
width: 0%;
;
background-color: #4cc9f0;
transition: width 0.3s ease;
}
#loading-text {
font-size: 16px;
color: #778da9;
}
/* Animations */
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.floating {
animation: float 3s ease-in-out infinite;
}
/* Sabotage menu */
#sabotage-menu {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 85%;
max-width: 350px;
background-color: #1b263b;
border: 4px solid #f72585;
border-radius: 15px;
padding: 25px;
z-index: 100;
display: none;
text-align: center;
box-shadow: 0 0 30px rgba(247, 37, 133, 0.8);
}
#sabotage-menu h3 {
margin-bottom: 20px;
color: #f72585;
font-size: 22px;
}
.sabotage-option {
background-color: #415a77;
color: white;
border: none;
padding: 12px;
border-radius: 8px;
margin: 8px 0;
font-size: 16px;
cursor: pointer;
transition: all 0.2s ease;
width: 100%;
}
.sabotage-option:hover {
background-color: #4cc9f0;
transform: scale(1.02);
}
/* Countdown timer */
#countdown-timer {
position: absolute;
top: 25px;
left: 50%;
transform: translateX(-50%);
background-color: rgba(27, 38, 59, 0.9);
border: 3px solid #f72585;
border-radius: 12px;
padding: 10px 20px;
z-index: 20;
box-shadow: 0 0 20px rgba(247, 37, 133, 0.5);
font-size: 18px;
font-weight: bold;
color: white;
display: none;
}
/* Kill button */
#kill-btn {
position: absolute;
bottom: 30px;
right: 230px;
width: 60px;
height: 60px;
background-color: #f72585;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: white;
z-index: 20;
box-shadow: 0 0 20px rgba(247, 37, 133, 0.5);
border: 3px solid white;
cursor: pointer;
transition: all 0.3s ease;
display: none;
}
#kill-btn:active {
transform: scale(0.95);
box-shadow: 0 0 10px rgba(247, 37, 133, 0.5);
}
/* Vent button */
#vent-btn {
position: absolute;
bottom: 30px;
right: 300px;
width: 60px;
height: 60px;
background-color: #4cc9f0;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: white;
z-index: 20;
box-shadow: 0 0 20px rgba(76, 201, 240, 0.5);
border: 3px solid white;
cursor: pointer;
transition: all 0.3s ease;
display: none;
}
#vent-btn:active {
transform: scale(0.95);
box-shadow: 0 0 10px rgba(76, 201, 240, 0.5);
}
/* Role reveal */
#role-reveal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 85%;
max-width: 350px;
background-color: #1b263b;
border: 4px solid #f72585;
border-radius: 15px;
padding: 25px;
z-index: 100;
display: none;
text-align: center;
box-shadow: 0 0 30px rgba(247, 37, 133, 0.8);
}
#role-reveal h3 {
margin-bottom: 20px;
color: #f72585;
font-size: 22px;
}
#role-reveal p {
margin-bottom: 20px;
font-size: 16px;
line-height: 1.4;
}
#role-reveal button {
background-color: #4cc9f0;
color: white;
border: none;
padding: 12px 25px;
border-radius: 8px;
margin-top: 15px;
font-size: 18px;
cursor: pointer;
transition: background-color 0.2s ease;
font-weight: bold;
}
#role-reveal button:hover {
background-color: #3aa8d8;
}
</style>
</head>
<body>
<div id="loading-screen">
<h1>MINI AMONG US</h1>
<div id="loading-bar">
<div id="loading-progress"></div>
</div>
<div id="loading-text">Loading game assets...</div>
</div>
<div id="game-container">
<div id="game-map">
<!-- Rooms, player, NPCs, tasks will be generated by JavaScript -->
</div>
<!-- Game UI elements -->
<div id="controls">
<div id="up-btn" class="control-btn"></div>
<div id="left-btn" class="control-btn"></div>
<div id="right-btn" class="control-btn"></div>
<div id="down-btn" class="control-btn"></div>
</div>
<div id="task-list">
<h3>Tasks</h3>
<div id="tasks-container">
<!-- Task items will be added here -->
</div>
</div>
<div id="game-status">
<h3>Status</h3>
<div id="tasks-completed">0/5 tasks completed</div>
</div>
<div id="mini-map">
<div id="mini-map-view"></div>
</div>
<div id="emergency-btn">!</div>
<div id="kill-btn">⚔️</div>
<div id="vent-btn">🕳️</div>
<div id="countdown-timer">00:30</div>
<!-- Popups and menus -->
<div id="task-popup">
<h3 id="task-title">Fix Wiring</h3>
<p id="task-description">Connect the wires to match the colors</p>
<div id="task-progress">
<div id="progress-bar"></div>
</div>
<button id="task-cancel-btn">Cancel</button>
<button id="task-complete-btn">Complete</button>
</div>
<div id="sabotage-menu">
<h3>Sabotage</h3>
<button class="sabotage-option" data-sabotage="lights">Cut Lights</button>
<button class="sabotage-option" data-sabotage="oxygen">O2 Sabotage</button>
<button class="sabotage-option" data-sabotage="reactor">Reactor Meltdown</button>
<button class="sabotage-option" data-sabotage="comms">Disable Comms</button>
<button id="sabotage-close-btn">Close</button>
</div>
<div id="role-reveal">
<h3 id="role-title">Your Role</h3>
<p id="role-description">You are a Crewmate. Complete all tasks to win!</p>
<button id="role-confirm-btn">Start Game</button>
</div>
<div id="win-screen">
<h2 id="win-title">Victory!</h2>
<p id="win-message">All tasks completed!</p>
<button id="play-again-btn">Play Again</button>
</div>
<div class="tooltip"></div>
</div>
<script>
// Game state
const gameState = {
player: {
x: 0,
y: 0,
speed: 5,
isMoving: false,
direction: { x: 0, y: 0 },
isImpostor: false,
inVent: false,
killCooldown: 0
},
tasks: [],
completedTasks: 0,
totalTasks: 5,
npcs: [],
rooms: [],
walls: [],
doors: [],
scale: 1,
offsetX: 0,
offsetY: 0,
currentTask: null,
sabotageActive: false,
sabotageType: null,
sabotageTimer: 0,
gameTime: 300, // 5 minutes in seconds
gameStarted: false
};
// DOM elements
const elements = {
gameContainer: document.getElementById('game-container'),
gameMap: document.getElementById('game-map'),
miniMap: document.getElementById('mini-map'),
miniMapView: document.getElementById('mini-map-view'),
loadingScreen: document.getElementById('loading-screen'),
loadingProgress: document.getElementById('loading-progress'),
loadingText: document.getElementById('loading-text'),
taskList: document.getElementById('task-list'),
tasksContainer: document.getElementById('tasks-container'),
tasksCompleted: document.getElementById('tasks-completed'),
taskPopup: document.getElementById('task-popup'),
taskTitle: document.getElementById('task-title'),
taskDescription: document.getElementById('task-description'),
progressBar: document.getElementById('progress-bar'),
taskCancelBtn: document.getElementById('task-cancel-btn'),
taskCompleteBtn: document.getElementById('task-complete-btn'),
emergencyBtn: document.getElementById('emergency-btn'),
killBtn: document.getElementById('kill-btn'),
ventBtn: document.getElementById('vent-btn'),
sabotageMenu: document.getElementById('sabotage-menu'),
sabotageOptions: document.querySelectorAll('.sabotage-option'),
sabotageCloseBtn: document.getElementById('sabotage-close-btn'),
roleReveal: document.getElementById('role-reveal'),
roleTitle: document.getElementById('role-title'),
roleDescription: document.getElementById('role-description'),
roleConfirmBtn: document.getElementById('role-confirm-btn'),
winScreen: document.getElementById('win-screen'),
winTitle: document.getElementById('win-title'),
winMessage: document.getElementById('win-message'),
playAgainBtn: document.getElementById('play-again-btn'),
countdownTimer: document.getElementById('countdown-timer'),
upBtn: document.getElementById('up-btn'),
leftBtn: document.getElementById('left-btn'),
rightBtn: document.getElementById('right-btn'),
downBtn: document.getElementById('down-btn'),
tooltip: document.querySelector('.tooltip')
};
// Initialize the game
function initGame() {
// Simulate loading
let progress = 0;
const loadingInterval = setInterval(() => {
progress += 5;
elements.loadingProgress.style.width = `${progress}%`;
elements.loadingText.textContent =
progress < 50 ? "Loading game assets..." :
progress < 80 ? "Generating map..." :
"Almost ready...";
if (progress >= 100) {
clearInterval(loadingInterval);
setTimeout(() => {
elements.loadingScreen.style.display = 'none';
setupGame();
}, 500);
}
}, 100);
// Set up event listeners
setupEventListeners();
}
// Set up game world
function setupGame() {
// Create rooms
createRooms();
// Create player
createPlayer();
// Create NPCs
createNPCs(5);
// Create tasks
createTasks(gameState.totalTasks);
// Randomly assign roles
assignRoles();
// Start game loop
requestAnimationFrame(gameLoop);
// Start game timer
setInterval(updateGameTimer, 1000);
}
// Create game rooms
function createRooms() {
// Main rooms
const rooms = [
{ id: 'cafeteria', x: 500, y: 500, width: 400, height: 300 },
{ id: 'admin', x: 500, y: 850, width: 300, height: 300 },
{ id: 'medbay', x: 850, y: 500, width: 300, height: 300 },
{ id: 'electrical', x: 1200, y: 500, width: 300, height: 300 },
{ id: 'storage', x: 1200, y: 850, width: 300, height: 300 },
{ id: 'reactor', x: 1550, y: 850, width: 300, height: 300 },
{ id: 'security', x: 850, y: 850, width: 300, height: 300 },
{ id: 'navigation', x: 500, y: 1200, width: 300, height: 300 },
{ id: 'shields', x: 850, y: 1200, width: 300, height: 300 },
{ id: 'communications', x: 1200, y: 1200, width: 300, height: 300 }
];
// Create room elements
rooms.forEach(room => {
const roomElement = document.createElement('div');
roomElement.className = 'room';
roomElement.id = `room-${room.id}`;
roomElement.style.left = `${room.x}px`;
roomElement.style.top = `${room.y}px`;
roomElement.style.width = `${room.width}px`;
roomElement.style.height = `${room.height}px`;
const label = document.createElement('div');
label.className = 'room-label';
label.textContent = room.id.toUpperCase();
roomElement.appendChild(label);
elements.gameMap.appendChild(roomElement);
gameState.rooms.push(room);
// Create walls for each room
createWalls(room);
});
// Create doors between rooms
createDoors();
// Position player in cafeteria
gameState.player.x = 700;
gameState.player.y = 650;
// Calculate initial scale and offset to center player
updateViewport();
}
// Create walls for a room
function createWalls(room) {
// Top wall
const topWall = {
x: room.x,
y: room.y,
width: room.width,
height: 20
};
createWallElement(topWall);
// Bottom wall
const bottomWall = {
x: room.x,
y: room.y + room.height - 20,
width: room.width,
height: 20
};
createWallElement(bottomWall);
// Left wall
const leftWall = {
x: room.x,
y: room.y,
width: 20,
height: room.height
};
createWallElement(leftWall);
// Right wall
const rightWall = {
x: room.x + room.width - 20,
y: room.y,
width: 20,
height: room.height
};
createWallElement(rightWall);
// Add walls to game state
gameState.walls.push(topWall, bottomWall, leftWall, rightWall);
}
// Create a wall element
function createWallElement(wall) {
const wallElement = document.createElement('div');
wallElement.className = 'room-wall';
wallElement.style.left = `${wall.x}px`;
wallElement.style.top = `${wall.y}px`;
wallElement.style.width = `${wall.width}px`;
wallElement.style.height = `${wall.height}px`;
elements.gameMap.appendChild(wallElement);
}
// Create doors between rooms
function createDoors() {
// Cafeteria to Admin
createDoor(700, 800, 40, 20, 'horizontal');
// Cafeteria to Medbay
createDoor(900, 650, 20, 40, 'vertical');
// Medbay to Electrical
createDoor(1150, 650, 20, 40, 'vertical');
// Electrical to Storage
createDoor(1350, 800, 40, 20, 'horizontal');
// Storage to Reactor
createDoor(1500, 1000, 20, 40, 'vertical');
// Admin to Security
createDoor(800, 850, 20, 40, 'vertical');
// Security to Shields
createDoor(1000, 1150, 40, 20, 'horizontal');
// Navigation to Shields
createDoor(800, 1200, 20, 40, 'vertical');
// Shields to Communications
createDoor(1150, 1350, 40, 20, 'horizontal');
// Add doors to mini-map
updateMiniMap();
}
// Create a door element
function createDoor(x, y, width, height, orientation) {
const door = {
x, y, width, height, orientation
};
const doorElement = document.createElement('div');
doorElement.className = 'room-door';
doorElement.style.left = `${x}px`;
doorElement.style.top = `${y}px`;
doorElement.style.width = `${width}px`;
doorElement.style.height = `${height}px`;
elements.gameMap.appendChild(doorElement);
gameState.doors.push(door);
return door;
}
// Create player character
function createPlayer() {
const playerElement = document.createElement('div');
playerElement.className = 'player';
playerElement.id = 'player';
playerElement.style.left = `${gameState.player.x}px`;
playerElement.style.top = `${gameState.player.y}px`;
const shadowElement = document.createElement('div');
shadowElement.className = 'player-shadow';
playerElement.appendChild(shadowElement);
elements.gameMap.appendChild(playerElement);
}
// Create NPCs
function createNPCs(count) {
const colors = ['#4cc9f0', '#4361ee', '#3a0ca3', '#7209b7', '#f72585', '#b5179e'];
for (let i = 0; i < count; i++) {
const npc = {
id: `npc-${i}`,
x: 600 + Math.random() * 200,
y: 600 + Math.random() * 200,
color: colors[i % colors.length],
isImpostor: false,
speed: 1 + Math.random() * 2,
direction: { x: 0, y: 0 },
moveTimer: 0,
currentRoom: 'cafeteria'
};
const npcElement = document.createElement('div');
npcElement.className = 'npc';
npcElement.id = npc.id;
npcElement.style.left = `${npc.x}px`;
npcElement.style.top = `${npc.y}px`;
npcElement.style.backgroundColor = npc.color;
const shadowElement = document.createElement('div');
shadowElement.className = 'npc-shadow';
npcElement.appendChild(shadowElement);
elements.gameMap.appendChild(npcElement);
gameState.npcs.push(npc);
}
}
// Create tasks
function createTasks(count) {
const taskTypes = [
{ name: 'Fix Wiring', description: 'Connect the wires to match the colors', duration: 5, emoji: '🔌' },
{ name: 'Download Data', description: 'Download important data from the terminal', duration: 7, emoji: '💾' },
{ name: 'Align Engine', description: 'Align the engine output to the correct position', duration: 8, emoji: '⚙️' },
{ name: 'Clear Asteroids', description: 'Shoot the asteroids before they hit the ship', duration: 10, emoji: '☄️' },
{ name: 'Calibrate Distributor', description: 'Calibrate the distributor to optimal levels', duration: 6, emoji: '📊' },
{ name: 'Empty Garbage', description: 'Empty the garbage to prevent overflow', duration: 4, emoji: '🗑️' },
{ name: 'Fuel Engines', description: 'Fill the engines with the correct fuel mixture', duration: 7, emoji: '⛽' },
{ name: 'Inspect Sample', description: 'Analyze the sample in the medbay scanner', duration: 9, emoji: '🧪' },
{ name: 'Prime Shields', description: 'Prime the shields to full capacity', duration: 8, emoji: '🛡️' },
{ name: 'Stabilize Steering', description: 'Stabilize the steering system', duration: 5, emoji: '🧭' }
];
// Assign tasks to rooms
const roomTasks = {
'cafeteria': ['Empty Garbage'],
'admin': ['Download Data'],
'medbay': ['Inspect Sample'],
'electrical': ['Fix Wiring'],
'storage': ['Fuel Engines'],
'reactor': ['Align Engine'],
'security': ['Download Data'],
'navigation': ['Clear Asteroids', 'Stabilize Steering'],
'shields': ['Prime Shields'],
'communications': ['Download Data']
};
// Create task elements
let createdTasks = 0;
while (createdTasks < count) {
for (const roomId in roomTasks) {
if (createdTasks >= count) break;
const room = gameState.rooms.find(r => r.id === roomId);
if (!room) continue;
const availableTasks = roomTasks[roomId];
const taskType = availableTasks[Math.floor(Math.random() * availableTasks.length)];
const taskDef = taskTypes.find(t => t.name === taskType);
if (!taskDef) continue;
// Random position within room (but not too close to walls)
const x = room.x + 50 + Math.random() * (room.width - 100);
const y = room.y + 50 + Math.random() * (room.height - 100);
const task = {
id: `task-${createdTasks}`,
name: taskDef.name,
description: taskDef.description,
emoji: taskDef.emoji,
duration: taskDef.duration,
x,
y,
roomId,
completed: false,
progress: 0
};
const taskElement = document.createElement('div');
taskElement.className = 'task';
taskElement.id = task.id;
taskElement.style.left = `${x}px`;
taskElement.style.top = `${y}px`;
taskElement.textContent = taskDef.emoji;
taskElement.dataset.taskId = task.id;
elements.gameMap.appendChild(taskElement);
gameState.tasks.push(task);
createdTasks++;
// Add to task list
addTaskToList(task);
}
}
}
// Add task to the task list UI
function addTaskToList(task) {
const taskItem = document.createElement('div');
taskItem.className = 'task-item';
taskItem.dataset.taskId = task.id;
const checkbox = document.createElement('div');
checkbox.className = 'task-checkbox';
const taskName = document.createElement('span');
taskName.textContent = task.name;
taskItem.appendChild(checkbox);
taskItem.appendChild(taskName);
elements.tasksContainer.appendChild(taskItem);
}
// Randomly assign roles (1 impostor)
function assignRoles() {
// Randomly select one impostor from NPCs
const impostorIndex = Math.floor(Math.random() * gameState.npcs.length);
gameState.npcs[impostorIndex].isImpostor = true;
// Small chance (10%) for player to be impostor
gameState.player.isImpostor = Math.random() < 0.1;
// Show role reveal
showRoleReveal();
}
// Show role reveal popup
function showRoleReveal() {
if (gameState.player.isImpostor) {
elements.roleTitle.textContent = "IMPOSTOR";
elements.roleDescription.textContent = "Sabotage the ship and eliminate crewmates without being caught!";
elements.roleTitle.style.color = "#f72585";
// Show impostor buttons
elements.killBtn.style.display = 'flex';
elements.ventBtn.style.display = 'flex';
} else {
elements.roleTitle.textContent = "CREWMATE";
elements.roleDescription.textContent = "Complete all tasks and identify the impostor to win!";
elements.roleTitle.style.color = "#4cc9f0";
}
elements.roleReveal.style.display = 'block';
}
// Set up event listeners
function setupEventListeners() {
// Control buttons
elements.upBtn.addEventListener('touchstart', () => startMoving(0, -1));
elements.upBtn.addEventListener('touchend', () => stopMoving(0, -1));
elements.upBtn.addEventListener('mousedown', () => startMoving(0, -1));
elements.upBtn.addEventListener('mouseup', () => stopMoving(0, -1));
elements.upBtn.addEventListener('mouseleave', () => stopMoving(0, -1));
elements.leftBtn.addEventListener('touchstart', () => startMoving(-1, 0));
elements.leftBtn.addEventListener('touchend', () => stopMoving(-1, 0));
elements.leftBtn.addEventListener('mousedown', () => startMoving(-1, 0));
elements.leftBtn.addEventListener('mouseup', () => stopMoving(-1, 0));
elements.leftBtn.addEventListener('mouseleave', () => stopMoving(-1, 0));
elements.rightBtn.addEventListener('touchstart', () => startMoving(1, 0));
elements.rightBtn.addEventListener('touchend', () => stopMoving(1, 0));
elements.rightBtn.addEventListener('mousedown', () => startMoving(1, 0));
elements.rightBtn.addEventListener('mouseup', () => stopMoving(1, 0));
elements.rightBtn.addEventListener('mouseleave', () => stopMoving(1, 0));
elements.downBtn.addEventListener('touchstart', () => startMoving(0, 1));
elements.downBtn.addEventListener('touchend', () => stopMoving(0, 1));
elements.downBtn.addEventListener('mousedown', () => startMoving(0, 1));
elements.downBtn.addEventListener('mouseup', () => stopMoving(0, 1));
elements.downBtn.addEventListener('mouseleave', () => stopMoving(0, 1));
// Keyboard controls
document.addEventListener('keydown', (e) => {
if (gameState.currentTask) return;
switch(e.key) {
case 'ArrowUp':
case 'w':
case 'W':
startMoving(0, -1);
break;
case 'ArrowLeft':
case 'a':
case 'A':
startMoving(-1, 0);
break;
case 'ArrowRight':
case 'd':
case 'D':
startMoving(1, 0);
break;
case 'ArrowDown':
case 's':
case 'S':
startMoving(0, 1);
break;
}
});
document.addEventListener('keyup', (e) => {
switch(e.key) {
case 'ArrowUp':
case 'w':
case 'W':
stopMoving(0, -1);
break;
case 'ArrowLeft':
case 'a':
case 'A':
stopMoving(-1, 0);
break;
case 'ArrowRight':
case 'd':
case 'D':
stopMoving(1, 0);
break;
case 'ArrowDown':
case 's':
case 'S':
stopMoving(0, 1);
break;
}
});
// Task interaction
document.addEventListener('click', (e) => {
if (e.target.classList.contains('task') && !gameState.currentTask) {
const taskId = e.target.dataset.taskId;
startTask(taskId);
}
});
// Task popup buttons
elements.taskCancelBtn.addEventListener('click', cancelTask);
elements.taskCompleteBtn.addEventListener('click', completeTask);
// Emergency button
elements.emergencyBtn.addEventListener('click', showEmergencyMeeting);
// Sabotage menu
elements.sabotageOptions.forEach(option => {
option.addEventListener('click', () => startSabotage(option.dataset.sabotage));
});
elements.sabotageCloseBtn.addEventListener('click', () => {
elements.sabotageMenu.style.display = 'none';
});
// Role reveal
elements.roleConfirmBtn.addEventListener('click', () => {
elements.roleReveal.style.display = 'none';
gameState.gameStarted = true;
elements.countdownTimer.style.display = 'block';
});
// Win screen
elements.playAgainBtn.addEventListener('click', resetGame);
// Kill button (impostor only)
elements.killBtn.addEventListener('click', attemptKill);
// Vent button (impostor only)
elements.ventBtn.addEventListener('click', toggleVent);
}
// Start moving in a direction
function startMoving(x, y) {
if (gameState.currentTask || gameState.player.inVent) return;
gameState.player.isMoving = true;
gameState.player.direction.x += x;
gameState.player.direction.y += y;
}
// Stop moving in a direction
function stopMoving(x, y) {
gameState.player.direction.x -= x;
gameState.player.direction.y -= y;
if (gameState.player.direction.x === 0 && gameState.player.direction.y === 0) {
gameState.player.isMoving = false;
}
}
// Game loop
function gameLoop() {
// Move player
if (gameState.player.isMoving && !gameState.currentTask && !gameState.player.inVent) {
movePlayer();
}
// Move NPCs
moveNPCs();
// Update kill cooldown
if (gameState.player.killCooldown > 0) {
gameState.player.killCooldown--;
}
// Update sabotage timer
if (gameState.sabotageActive && gameState.sabotageTimer > 0) {
gameState.sabotageTimer--;
if (gameState.sabotageTimer <= 0) {
endSabotage();
}
}
// Update viewport
updateViewport();
// Update mini-map
updateMiniMap();
// Continue game loop
requestAnimationFrame(gameLoop);
}
// Move player character
function movePlayer() {
const newX = gameState.player.x + (gameState.player.direction.x * gameState.player.speed);
const newY = gameState.player.y + (gameState.player.direction.y * gameState.player.speed);
// Check wall collisions
if (!checkWallCollision(newX, newY)) {
gameState.player.x = newX;
gameState.player.y = newY;
// Update player element position
const playerElement = document.getElementById('player');
if (playerElement) {
playerElement.style.left = `${gameState.player.x}px`;
playerElement.style.top = `${gameState.player.y}px`;
}
}
// Check current room
checkCurrentRoom();
}
// Check wall collisions
function checkWallCollision(x, y) {
const playerSize = 45;
// Check walls
for (const wall of gameState.walls) {
if (x < wall.x + wall.width &&
x + playerSize > wall.x &&
y < wall.y + wall.height &&
y + playerSize > wall.y) {
return true;
}
}
return false;
}
// Check which room the player is in
function checkCurrentRoom() {
for (const room of gameState.rooms) {
if (gameState.player.x >= room.x &&
gameState.player.x <= room.x + room.width &&
gameState.player.y >= room.y &&
gameState.player.y <= room.y + room.height) {
// Highlight current room on mini-map
const miniRoom = document.querySelector(`.mini-map-room[data-room="${room.id}"]`);
if (miniRoom) {
document.querySelectorAll('.mini-map-room').forEach(r => {
r.style.backgroundColor = 'rgba(65, 90, 119, 0.5)';
});
miniRoom.style.backgroundColor = 'rgba(76, 201, 240, 0.7)';
}
return room.id;
}
}
return null;
}
// Move NPCs
function moveNPCs() {
gameState.npcs.forEach(npc => {
// Update move timer
if (npc.moveTimer <= 0) {
// Change direction randomly
npc.direction = {
x: Math.random() * 2 - 1,
y: Math.random() * 2 - 1
};
// Normalize direction
const length = Math.sqrt(npc.direction.x * npc.direction.x + npc.direction.y * npc.direction.y);
if (length > 0) {
npc.direction.x /= length;
npc.direction.y /= length;
}
npc.moveTimer = 60 + Math.random() * 120; // 1-3 seconds
} else {
npc.moveTimer--;
}
// Move NPC
const newX = npc.x + (npc.direction.x * npc.speed);
const newY = npc.y + (npc.direction.y * npc.speed);
// Simple wall collision (just reverse direction)
let collided = false;
for (const wall of gameState.walls) {
if (newX < wall.x + wall.width &&
newX + 45 > wall.x &&
newY < wall.y + wall.height &&
newY + 45 > wall.y) {
collided = true;
break;
}
}
if (!collided) {
npc.x = newX;
npc.y = newY;
} else {
npc.direction.x *= -1;
npc.direction.y *= -1;
npc.moveTimer = 0;
}
// Update NPC element position
const npcElement = document.getElementById(npc.id);
if (npcElement) {
npcElement.style.left = `${npc.x}px`;
npcElement.style.top = `${npc.y}px`;
}
});
}
// Update viewport to follow player
function updateViewport() {
const containerWidth = elements.gameContainer.clientWidth;
const containerHeight = elements.gameContainer.clientHeight;
// Calculate scale based on container size
const scaleX = containerWidth / 1000;
const scaleY = containerHeight / 1000;
gameState.scale = Math.min(scaleX, scaleY, 1);
// Calculate offset to center player
gameState.offsetX = (containerWidth / 2) - (gameState.player.x * gameState.scale);
gameState.offsetY = (containerHeight / 2) - (gameState.player.y * gameState.scale);
// Apply transform to game map
elements.gameMap.style.transform = `translate(${gameState.offsetX}px, ${gameState.offsetY}px) scale(${gameState.scale})`;
}
// Update mini-map
function updateMiniMap() {
// Clear mini-map
elements.miniMapView.innerHTML = '';
// Calculate mini-map scale
const miniMapScale = 0.04; // 2500px map -> 100px mini-map
// Add rooms to mini-map
gameState.rooms.forEach(room => {
const miniRoom = document.createElement('div');
miniRoom.className = 'mini-map-room';
miniRoom.dataset.room = room.id;
miniRoom.style.left = `${room.x * miniMapScale}px`;
miniRoom.style.top = `${room.y * miniMapScale}px`;
miniRoom.style.width = `${room.width * miniMapScale}px`;
miniRoom.style.height = `${room.height * miniMapScale}px`;
elements.miniMapView.appendChild(miniRoom);
});
// Add player to mini-map
const miniPlayer = document.createElement('div');
miniPlayer.className = 'mini-map-player';
miniPlayer.style.left = `${gameState.player.x * miniMapScale}px`;
miniPlayer.style.top = `${gameState.player.y * miniMapScale}px`;
elements.miniMapView.appendChild(miniPlayer);
// Add NPCs to mini-map
gameState.npcs.forEach(npc => {
const miniNPC = document.createElement('div');
miniNPC.className = 'mini-map-npc';
miniNPC.style.left = `${npc.x * miniMapScale}px`;
miniNPC.style.top = `${npc.y * miniMapScale}px`;
miniNPC.style.backgroundColor = npc.isImpostor ? '#f72585' : '#4cc9f0';
elements.miniMapView.appendChild(miniNPC);
});
// Add tasks to mini-map
gameState.tasks.forEach(task => {
if (!task.completed) {
const miniTask = document.createElement('div');
miniTask.className = 'mini-map-task';
miniTask.style.left = `${task.x * miniMapScale}px`;
miniTask.style.top = `${task.y * miniMapScale}px`;
elements.miniMapView.appendChild(miniTask);
}
});
// Highlight current room
const currentRoom = checkCurrentRoom();
if (currentRoom) {
const miniRoom = document.querySelector(`.mini-map-room[data-room="${currentRoom}"]`);
if (miniRoom) {
miniRoom.style.backgroundColor = 'rgba(76, 201, 240, 0.7)';
}
}
}
// Start a task
function startTask(taskId) {
const task = gameState.tasks.find(t => t.id === taskId);
if (!task || task.completed) return;
gameState.currentTask = task;
// Show task popup
elements.taskTitle.textContent = task.name;
elements.taskDescription.textContent = task.description;
elements.progressBar.style.width = '0%';
elements.taskPopup.style.display = 'block';
// Start progress
task.progress = 0;
const progressInterval = setInterval(() => {
task.progress++;
elements.progressBar.style.width = `${(task.progress / task.duration) * 100}%`;
if (task.progress >= task.duration) {
clearInterval(progressInterval);
elements.taskCompleteBtn.disabled = false;
}
}, 1000);
// Store interval ID to cancel if needed
task.progressInterval = progressInterval;
}
// Cancel current task
function cancelTask() {
if (!gameState.currentTask) return;
clearInterval(gameState.currentTask.progressInterval);
gameState.currentTask.progress = 0;
gameState.currentTask = null;
elements.taskPopup.style.display = 'none';
}
// Complete current task
function completeTask() {
if (!gameState.currentTask) return;
clearInterval(gameState.currentTask.progressInterval);
gameState.currentTask.completed = true;
gameState.completedTasks++;
// Update task list
const taskItem = document.querySelector(`.task-item[data-task-id="${gameState.currentTask.id}"]`);
if (taskItem) {
taskItem.classList.add('completed');
}
// Remove task from map
const taskElement = document.getElementById(gameState.currentTask.id);
if (taskElement) {
taskElement.style.display = 'none';
}
// Update status
elements.tasksCompleted.textContent = `${gameState.completedTasks}/${gameState.totalTasks} tasks completed`;
// Check for win condition
if (gameState.completedTasks >= gameState.totalTasks && !gameState.player.isImpostor) {
showWinScreen(true);
}
gameState.currentTask = null;
elements.taskPopup.style.display = 'none';
}
// Show emergency meeting
function showEmergencyMeeting() {
// For now just show a message
showTooltip("Emergency meeting called!", elements.emergencyBtn);
// In a full game, this would trigger a voting sequence
}
// Show sabotage menu
function showSabotageMenu() {
if (!gameState.player.isImpostor || gameState.sabotageActive) return;
elements.sabotageMenu.style.display = 'block';
}
// Start a sabotage
function startSabotage(type) {
if (!gameState.player.isImpostor || gameState.sabotageActive) return;
gameState.sabotageActive = true;
gameState.sabotageType = type;
// Set timer based on sabotage type
switch(type) {
case 'lights':
gameState.sabotageTimer = 30; // 30 seconds
darkenLights();
break;
case 'oxygen':
gameState.sabotageTimer = 45; // 45 seconds
showTooltip("O2 Sabotage! Fix it in admin!", elements.gameContainer);
break;
case 'reactor':
gameState.sabotageTimer = 60; // 60 seconds
showTooltip("Reactor Meltdown! Fix it in reactor!", elements.gameContainer);
break;
case 'comms':
gameState.sabotageTimer = 30; // 30 seconds
disableComms();
break;
}
elements.sabotageMenu.style.display = 'none';
}
// End current sabotage
function endSabotage() {
if (!gameState.sabotageActive) return;
switch(gameState.sabotageType) {
case 'lights':
restoreLights();
break;
case 'comms':
restoreComms();
break;
}
gameState.sabotageActive = false;
gameState.sabotageType = null;
}
// Darken lights (sabotage effect)
function darkenLights() {
elements.gameMap.style.filter = 'brightness(0.3)';
}
// Restore lights
function restoreLights() {
elements.gameMap.style.filter = 'brightness(1)';
}
// Disable comms (sabotage effect)
function disableComms() {
// In a full game, this would disable task list and other UI elements
elements.taskList.style.opacity = '0.5';
}
// Restore comms
function restoreComms() {
elements.taskList.style.opacity = '1';
}
// Attempt to kill a crewmate (impostor only)
function attemptKill() {
if (!gameState.player.isImpostor || gameState.player.killCooldown > 0) return;
// Check if player is near any crewmate
for (const npc of gameState.npcs) {
if (!npc.isImpostor) {
const distance = Math.sqrt(
Math.pow(gameState.player.x - npc.x, 2) +
Math.pow(gameState.player.y - npc.y, 2)
);
if (distance < 60) { // Kill range
// Kill the NPC
const npcElement = document.getElementById(npc.id);
if (npcElement) {
npcElement.style.display = 'none';
}
// Remove from NPC list
gameState.npcs = gameState.npcs.filter(n => n.id !== npc.id);
// Set kill cooldown
gameState.player.killCooldown = 120; // 2 seconds cooldown
// Check win condition (all crewmates dead)
const crewmatesLeft = gameState.npcs.filter(n => !n.isImpostor).length;
if (crewmatesLeft === 0) {
showWinScreen(false);
}
// Create blood particles
createBloodParticles(npc.x, npc.y);
break;
}
}
}
}
// Toggle vent (impostor only)
function toggleVent() {
if (!gameState.player.isImpostor) return;
gameState.player.inVent = !gameState.player.inVent;
if (gameState.player.inVent) {
// Hide player
const playerElement = document.getElementById('player');
if (playerElement) {
playerElement.style.opacity = '0.5';
}
// Increase speed
gameState.player.speed = 10;
// Can pass through walls
} else {
// Show player
const playerElement = document.getElementById('player');
if (playerElement) {
playerElement.style.opacity = '1';
}
// Reset speed
gameState.player.speed = 5;
}
}
// Create blood particles
function createBloodParticles(x, y) {
for (let i = 0; i < 20; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
particle.style.left = `${x + Math.random() * 30 - 15}px`;
particle.style.top = `${y + Math.random() * 30 - 15}px`;
particle.style.backgroundColor = '#f72585';
// Random size
const size = 2 + Math.random() * 4;
particle.style.width = `${size}px`;
particle.style.height = `${size}px`;
elements.gameMap.appendChild(particle);
// Animate particle
const angle = Math.random() * Math.PI * 2;
const speed = 1 + Math.random() * 3;
let distance = 0;
const maxDistance = 20 + Math.random() * 30;
const animate = () => {
distance += speed;
particle.style.left = `${parseFloat(particle.style.left) + Math.cos(angle) * speed}px`;
particle.style.top = `${parseFloat(particle.style.top) + Math.sin(angle) * speed}px`;
particle.style.opacity = `${1 - (distance / maxDistance)}`;
if (distance < maxDistance) {
requestAnimationFrame(animate);
} else {
particle.remove();
}
};
animate();
}
}
// Show tooltip
function showTooltip(text, element) {
elements.tooltip.textContent = text;
elements.tooltip.style.opacity = '1';
const rect = element.getBoundingClientRect();
elements.tooltip.style.left = `${rect.left + rect.width / 2}px`;
elements.tooltip.style.top = `${rect.top - 40}px`;
elements.tooltip.style.transform = 'translate(-50%, -100%)';
setTimeout(() => {
elements.tooltip.style.opacity = '0';
}, 2000);
}
// Update game timer
function updateGameTimer() {
if (!gameState.gameStarted) return;
gameState.gameTime--;
const minutes = Math.floor(gameState.gameTime / 60);
const seconds = gameState.gameTime % 60;
elements.countdownTimer.textContent =
`${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
// Flash red when time is running out
if (gameState.gameTime <= 30) {
elements.countdownTimer.style.color =
Math.floor(Date.now() / 500) % 2 === 0 ? '#f72585' : 'white';
}
// Game over when time runs out
if (gameState.gameTime <= 0) {
showWinScreen(false);
}
}
// Show win screen
function showWinScreen(crewmatesWin) {
if (crewmatesWin) {
elements.winTitle.textContent = "CREWMATES WIN!";
elements.winMessage.textContent = "All tasks completed and impostor defeated!";
elements.winTitle.style.color = "#4cc9f0";
} else {
elements.winTitle.textContent = "IMPOSTOR WINS!";
elements.winMessage.textContent = "All crewmates have been eliminated!";
elements.winTitle.style.color = "#f72585";
}
elements.winScreen.style.display = 'flex';
gameState.gameStarted = false;
}
// Reset game
function resetGame() {
// Clear game map
elements.gameMap.innerHTML = '';
// Reset game state
gameState.player = {
x: 700,
y: 650,
speed: 5,
isMoving: false,
direction: { x: 0, y: 0 },
isImpostor: false,
inVent: false,
killCooldown: 0
};
gameState.tasks = [];
gameState.completedTasks = 0;
gameState.npcs = [];
gameState.rooms = [];
gameState.walls = [];
gameState.doors = [];
gameState.currentTask = null;
gameState.sabotageActive = false;
gameState.sabotageType = null;
gameState.sabotageTimer = 0;
gameState.gameTime = 300;
gameState.gameStarted = false;
// Reset UI
elements.taskList.innerHTML = '<h3>Tasks</h3><div id="tasks-container"></div>';
elements.tasksCompleted.textContent = '0/5 tasks completed';
elements.taskPopup.style.display = 'none';
elements.sabotageMenu.style.display = 'none';
elements.winScreen.style.display = 'none';
elements.countdownTimer.style.display = 'none';
elements.killBtn.style.display = 'none';
elements.ventBtn.style.display = 'none';
elements.gameMap.style.filter = 'brightness(1)';
elements.taskList.style.opacity = '1';
// Hide role reveal if it's showing
elements.roleReveal.style.display = 'none';
// Setup game again
setupGame();
}
// Start the game
initGame();
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=kate-line/amogos" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>