mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-23 04:08:03 +00:00
Add Password Minigame: Introduce a new minigame for password entry, featuring customizable hints, keyboard input, and attempt tracking. Implement CSS styles for the minigame interface and integrate it into the existing framework. Update index.html to include the new CSS file and register the minigame in the minigame manager. Add test page for functionality and ensure compatibility with existing game mechanics.
This commit is contained in:
BIN
assets/mini-games/desktop-wallpaper.png
Normal file
BIN
assets/mini-games/desktop-wallpaper.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -8,6 +8,141 @@
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* Desktop Mode Styles */
|
||||
.container-minigame.desktop-mode {
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.desktop-background {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
background: #000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.desktop-wallpaper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image: url('../assets/mini-games/desktop-wallpaper.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: crisp-edges;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.desktop-wallpaper::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.desktop-icons {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.desktop-icon {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.desktop-icon:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.desktop-icon-image {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
object-fit: contain;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: crisp-edges;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 8px;
|
||||
padding: 4px;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.desktop-icon:hover .desktop-icon-image {
|
||||
border-color: #00ff00;
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
}
|
||||
|
||||
.desktop-icon-label {
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 8px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
margin-top: 4px;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
|
||||
word-wrap: break-word;
|
||||
max-width: 80px;
|
||||
}
|
||||
|
||||
.desktop-taskbar {
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border-top: 2px solid #333;
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.desktop-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.desktop-title {
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 10px;
|
||||
color: #00ff00;
|
||||
}
|
||||
|
||||
.desktop-subtitle {
|
||||
font-family: 'VT323', monospace;
|
||||
font-size: 14px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.desktop-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.empty-desktop {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container-image-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -190,3 +190,385 @@
|
||||
transition: width 0.3s ease;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* Password Minigame Specific Styles */
|
||||
.password-minigame-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
gap: 15px;
|
||||
background: #1a1a1a;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.password-input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.monitor-bezel {
|
||||
background: #2a2a2a;
|
||||
border: 8px solid #1a1a1a;
|
||||
border-radius: 15px;
|
||||
padding: 20px;
|
||||
box-shadow:
|
||||
inset 0 0 20px rgba(0, 0, 0, 0.5),
|
||||
0 0 30px rgba(0, 0, 0, 0.8);
|
||||
position: relative;
|
||||
background-image: url('../assets/mini-games/desktop-wallpaper.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
|
||||
.monitor-bezel::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
left: -4px;
|
||||
right: -4px;
|
||||
bottom: -4px;
|
||||
background: linear-gradient(45deg, #444, #666, #444);
|
||||
border-radius: 19px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.monitor-bezel::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
border-radius: 7px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.monitor-screen {
|
||||
border: 2px solid #333;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
min-height: 120px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.monitor-screen::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(0, 255, 0, 0.1), rgba(0, 255, 255, 0.1));
|
||||
border-radius: 6px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.monitor-screen > * {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.password-input-container label {
|
||||
font-size: 12px;
|
||||
color: #00ff00;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.password-field-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.password-field {
|
||||
width: 100%;
|
||||
padding: 12px 45px 12px 12px;
|
||||
background: #1a1a1a;
|
||||
border: 2px solid #00ff00;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 10px;
|
||||
outline: none;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.password-field:focus {
|
||||
border-color: #00ffff;
|
||||
box-shadow: 0 0 10px rgba(0, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.password-field::placeholder {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.toggle-password-btn {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
color: #00ff00;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.toggle-password-btn:hover {
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
}
|
||||
|
||||
.password-hint-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.hint-btn {
|
||||
background: #f39c12;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 8px;
|
||||
transition: background 0.3s ease;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.hint-btn:hover {
|
||||
background: #e67e22;
|
||||
}
|
||||
|
||||
.password-hint {
|
||||
background: rgba(243, 156, 18, 0.1);
|
||||
border: 1px solid #f39c12;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
font-size: 10px;
|
||||
color: #f39c12;
|
||||
}
|
||||
|
||||
.postit-note {
|
||||
background: #ffff88;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3);
|
||||
position: relative;
|
||||
transform: rotate(-2deg);
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 8px;
|
||||
color: #333;
|
||||
max-width: 200px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.postit-note::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
right: -1px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 15px solid transparent;
|
||||
border-top: 15px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.postit-note::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #ff6b6b;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 1px #fff, 0 0 0 2px #ff6b6b;
|
||||
}
|
||||
|
||||
.onscreen-keyboard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
background: #2a2a2a;
|
||||
border: 2px solid #444;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.keyboard-row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 3px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.key {
|
||||
background: #444;
|
||||
color: white;
|
||||
border: 1px solid #666;
|
||||
border-radius: 4px;
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 8px;
|
||||
min-width: 35px;
|
||||
text-align: center;
|
||||
transition: all 0.2s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.key:hover {
|
||||
background: #555;
|
||||
border-color: #00ff00;
|
||||
}
|
||||
|
||||
.key:active {
|
||||
background: #00ff00;
|
||||
color: black;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.key-backspace {
|
||||
background: #e74c3c;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.key-backspace:hover {
|
||||
background: #c0392b;
|
||||
}
|
||||
|
||||
.key-space {
|
||||
background: #3498db;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.key-space:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
.key-special {
|
||||
background: #9b59b6;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.key-special:hover {
|
||||
background: #8e44ad;
|
||||
}
|
||||
|
||||
.password-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
background: #2ecc71;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 10px;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.submit-btn:hover {
|
||||
background: #27ae60;
|
||||
}
|
||||
|
||||
.submit-btn:active {
|
||||
background: #229954;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background: #e74c3c;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 10px;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.cancel-btn:hover {
|
||||
background: #c0392b;
|
||||
}
|
||||
|
||||
.cancel-btn:active {
|
||||
background: #a93226;
|
||||
}
|
||||
|
||||
.attempts-counter {
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
color: #f39c12;
|
||||
background: rgba(243, 156, 18, 0.1);
|
||||
border: 1px solid #f39c12;
|
||||
border-radius: 5px;
|
||||
padding: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.attempts-counter span {
|
||||
color: #e74c3c;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Responsive design for smaller screens */
|
||||
@media (max-width: 768px) {
|
||||
.onscreen-keyboard {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.key {
|
||||
padding: 6px 8px;
|
||||
font-size: 7px;
|
||||
min-width: 30px;
|
||||
}
|
||||
|
||||
.key-backspace {
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
.key-space {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.key-special {
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.password-field {
|
||||
font-size: 9px;
|
||||
padding: 10px 40px 10px 10px;
|
||||
}
|
||||
|
||||
.submit-btn, .cancel-btn {
|
||||
padding: 10px 20px;
|
||||
font-size: 9px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
<link rel="stylesheet" href="css/container-minigame.css">
|
||||
<link rel="stylesheet" href="css/phone.css">
|
||||
<link rel="stylesheet" href="css/pin.css">
|
||||
<link rel="stylesheet" href="css/minigames.css">
|
||||
|
||||
<!-- External JavaScript libraries -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.min.js"></script>
|
||||
|
||||
@@ -8,6 +8,27 @@ export class ContainerMinigame extends MinigameScene {
|
||||
this.containerItem = params.containerItem;
|
||||
this.contents = params.contents || [];
|
||||
this.isTakeable = params.isTakeable || false;
|
||||
|
||||
// Auto-detect desktop mode for PC/tablet containers
|
||||
this.desktopMode = params.desktopMode || this.shouldUseDesktopMode();
|
||||
}
|
||||
|
||||
shouldUseDesktopMode() {
|
||||
// Check if the container is a PC, tablet, or computer-related device
|
||||
const containerName = this.containerItem?.scenarioData?.name?.toLowerCase() || '';
|
||||
const containerType = this.containerItem?.scenarioData?.type?.toLowerCase() || '';
|
||||
const containerImage = this.containerItem?.name?.toLowerCase() || '';
|
||||
|
||||
// Keywords that indicate desktop/computer devices
|
||||
const desktopKeywords = [
|
||||
'computer', 'pc', 'laptop', 'desktop', 'terminal', 'workstation',
|
||||
'tablet', 'ipad', 'surface', 'monitor', 'screen', 'display',
|
||||
'server', 'mainframe', 'console', 'kiosk', 'smartboard'
|
||||
];
|
||||
|
||||
// Check if any keyword matches
|
||||
const allText = `${containerName} ${containerType} ${containerImage}`.toLowerCase();
|
||||
return desktopKeywords.some(keyword => allText.includes(keyword));
|
||||
}
|
||||
|
||||
init() {
|
||||
@@ -27,6 +48,20 @@ export class ContainerMinigame extends MinigameScene {
|
||||
}
|
||||
|
||||
createContainerUI() {
|
||||
if (this.desktopMode) {
|
||||
this.createDesktopUI();
|
||||
} else {
|
||||
this.createStandardUI();
|
||||
}
|
||||
|
||||
// Populate contents
|
||||
this.populateContents();
|
||||
|
||||
// Set up event listeners
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
createStandardUI() {
|
||||
this.gameContainer.innerHTML = `
|
||||
<div class="container-minigame">
|
||||
<div class="container-image-section">
|
||||
@@ -52,15 +87,41 @@ export class ContainerMinigame extends MinigameScene {
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Populate contents
|
||||
this.populateContents();
|
||||
|
||||
// Set up event listeners
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
createDesktopUI() {
|
||||
this.gameContainer.innerHTML = `
|
||||
<div class="container-minigame desktop-mode">
|
||||
<div class="desktop-background">
|
||||
<div class="desktop-wallpaper"></div>
|
||||
<div class="desktop-icons" id="desktop-icons">
|
||||
<!-- Desktop icons will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-taskbar">
|
||||
<div class="desktop-info">
|
||||
<span class="desktop-title">${this.containerItem.scenarioData.name}</span>
|
||||
<span class="desktop-subtitle">${this.containerItem.scenarioData.observations || ''}</span>
|
||||
</div>
|
||||
<div class="desktop-actions">
|
||||
${this.isTakeable ? '<button class="minigame-button" id="take-container-btn">Take Container</button>' : ''}
|
||||
<button class="minigame-button" id="close-container-btn">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
populateContents() {
|
||||
if (this.desktopMode) {
|
||||
this.populateDesktopIcons();
|
||||
} else {
|
||||
this.populateStandardContents();
|
||||
}
|
||||
}
|
||||
|
||||
populateStandardContents() {
|
||||
const contentsGrid = document.getElementById('container-contents-grid');
|
||||
if (!contentsGrid) return;
|
||||
|
||||
@@ -107,6 +168,57 @@ export class ContainerMinigame extends MinigameScene {
|
||||
});
|
||||
}
|
||||
|
||||
populateDesktopIcons() {
|
||||
const desktopIcons = document.getElementById('desktop-icons');
|
||||
if (!desktopIcons) return;
|
||||
|
||||
if (this.contents.length === 0) {
|
||||
desktopIcons.innerHTML = '<div class="empty-desktop">Desktop is empty</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
this.contents.forEach((item, index) => {
|
||||
const icon = document.createElement('div');
|
||||
icon.className = 'desktop-icon';
|
||||
|
||||
const iconImg = document.createElement('img');
|
||||
iconImg.className = 'desktop-icon-image';
|
||||
iconImg.src = `assets/objects/${item.type}.png`;
|
||||
iconImg.alt = item.name;
|
||||
|
||||
const iconLabel = document.createElement('div');
|
||||
iconLabel.className = 'desktop-icon-label';
|
||||
iconLabel.textContent = item.name;
|
||||
|
||||
// Add item data
|
||||
iconImg.scenarioData = item;
|
||||
iconImg.name = item.type;
|
||||
iconImg.objectId = `desktop_${index}`;
|
||||
|
||||
// Add click handler for taking items
|
||||
if (item.takeable) {
|
||||
icon.style.cursor = 'pointer';
|
||||
|
||||
// Special handling for notes - trigger notes minigame instead of taking
|
||||
if (item.type === 'notes' && item.readable && item.text) {
|
||||
icon.addEventListener('click', () => this.handleNotesItem(item, iconImg));
|
||||
} else {
|
||||
icon.addEventListener('click', () => this.takeItem(item, iconImg));
|
||||
}
|
||||
}
|
||||
|
||||
// Position icon randomly on desktop
|
||||
const x = Math.random() * 70 + 10; // 10% to 80% of width
|
||||
const y = Math.random() * 60 + 10; // 10% to 70% of height
|
||||
icon.style.left = `${x}%`;
|
||||
icon.style.top = `${y}%`;
|
||||
|
||||
icon.appendChild(iconImg);
|
||||
icon.appendChild(iconLabel);
|
||||
desktopIcons.appendChild(icon);
|
||||
});
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Take container button
|
||||
const takeContainerBtn = document.getElementById('take-container-btn');
|
||||
@@ -254,8 +366,13 @@ export class ContainerMinigame extends MinigameScene {
|
||||
}
|
||||
|
||||
// Function to start the container minigame
|
||||
export function startContainerMinigame(containerItem, contents, isTakeable = false) {
|
||||
console.log('Starting container minigame', { containerItem, contents, isTakeable });
|
||||
export function startContainerMinigame(containerItem, contents, isTakeable = false, desktopMode = null) {
|
||||
// Auto-detect desktop mode if not explicitly set
|
||||
if (desktopMode === null) {
|
||||
desktopMode = shouldUseDesktopModeForContainer(containerItem);
|
||||
}
|
||||
|
||||
console.log('Starting container minigame', { containerItem, contents, isTakeable, desktopMode });
|
||||
|
||||
// Initialize the minigame framework if not already done
|
||||
if (!window.MinigameFramework) {
|
||||
@@ -273,6 +390,7 @@ export function startContainerMinigame(containerItem, contents, isTakeable = fal
|
||||
containerItem: containerItem,
|
||||
contents: contents,
|
||||
isTakeable: isTakeable,
|
||||
desktopMode: desktopMode,
|
||||
cancelText: 'Close',
|
||||
showCancel: true,
|
||||
onComplete: (success, result) => {
|
||||
@@ -281,6 +399,25 @@ export function startContainerMinigame(containerItem, contents, isTakeable = fal
|
||||
});
|
||||
}
|
||||
|
||||
// Helper function to determine if a container should use desktop mode
|
||||
function shouldUseDesktopModeForContainer(containerItem) {
|
||||
// Check if the container is a PC, tablet, or computer-related device
|
||||
const containerName = containerItem?.scenarioData?.name?.toLowerCase() || '';
|
||||
const containerType = containerItem?.scenarioData?.type?.toLowerCase() || '';
|
||||
const containerImage = containerItem?.name?.toLowerCase() || '';
|
||||
|
||||
// Keywords that indicate desktop/computer devices
|
||||
const desktopKeywords = [
|
||||
'computer', 'pc', 'laptop', 'desktop', 'terminal', 'workstation',
|
||||
'tablet', 'ipad', 'surface', 'monitor', 'screen', 'display',
|
||||
'server', 'mainframe', 'console', 'kiosk', 'smartboard'
|
||||
];
|
||||
|
||||
// Check if any keyword matches
|
||||
const allText = `${containerName} ${containerType} ${containerImage}`.toLowerCase();
|
||||
return desktopKeywords.some(keyword => allText.includes(keyword));
|
||||
}
|
||||
|
||||
// Function to return to container after notes minigame
|
||||
export function returnToContainerAfterNotes() {
|
||||
console.log('Returning to container after notes minigame');
|
||||
|
||||
@@ -12,6 +12,7 @@ export { LockpickSetMinigame, startLockpickSetMinigame } from './lockpick/lockpi
|
||||
export { ContainerMinigame, startContainerMinigame, returnToContainerAfterNotes } from './container/container-minigame.js';
|
||||
export { PhoneMessagesMinigame, returnToPhoneAfterNotes } from './phone/phone-messages-minigame.js';
|
||||
export { PinMinigame, startPinMinigame } from './pin/pin-minigame.js';
|
||||
export { PasswordMinigame } from './password/password-minigame.js';
|
||||
|
||||
// Initialize the global minigame framework for backward compatibility
|
||||
import { MinigameFramework } from './framework/minigame-manager.js';
|
||||
@@ -61,6 +62,9 @@ import { PhoneMessagesMinigame, returnToPhoneAfterNotes } from './phone/phone-me
|
||||
// Import the PIN minigame
|
||||
import { PinMinigame, startPinMinigame } from './pin/pin-minigame.js';
|
||||
|
||||
// Import the password minigame
|
||||
import { PasswordMinigame } from './password/password-minigame.js';
|
||||
|
||||
// Register minigames
|
||||
MinigameFramework.registerScene('lockpicking', LockpickingMinigamePhaser); // Use Phaser version as default
|
||||
MinigameFramework.registerScene('lockpicking-phaser', LockpickingMinigamePhaser); // Keep explicit phaser name
|
||||
@@ -72,6 +76,7 @@ MinigameFramework.registerScene('lockpick-set', LockpickSetMinigame);
|
||||
MinigameFramework.registerScene('container', ContainerMinigame);
|
||||
MinigameFramework.registerScene('phone-messages', PhoneMessagesMinigame);
|
||||
MinigameFramework.registerScene('pin', PinMinigame);
|
||||
MinigameFramework.registerScene('password', PasswordMinigame);
|
||||
|
||||
// Make minigame functions available globally
|
||||
window.startNotesMinigame = startNotesMinigame;
|
||||
|
||||
357
js/minigames/password/password-minigame.js
Normal file
357
js/minigames/password/password-minigame.js
Normal file
@@ -0,0 +1,357 @@
|
||||
import { MinigameScene } from '../framework/base-minigame.js';
|
||||
|
||||
export class PasswordMinigame extends MinigameScene {
|
||||
constructor(container, params) {
|
||||
super(container, params);
|
||||
|
||||
// Initialize password-specific state
|
||||
this.gameData = {
|
||||
password: params.password || '',
|
||||
passwordHint: params.passwordHint || '',
|
||||
showHint: params.showHint || false,
|
||||
showKeyboard: params.showKeyboard || false,
|
||||
maxAttempts: params.maxAttempts || 3,
|
||||
attempts: 0,
|
||||
showPassword: false,
|
||||
postitNote: params.postitNote || '',
|
||||
showPostit: params.showPostit || false
|
||||
};
|
||||
|
||||
// Store the correct password for validation
|
||||
this.correctPassword = params.password || '';
|
||||
}
|
||||
|
||||
init() {
|
||||
// Call parent init to set up basic UI structure
|
||||
super.init();
|
||||
|
||||
// Customize the header
|
||||
this.headerElement.innerHTML = `
|
||||
<h3>${this.params.title || 'Password Entry'}</h3>
|
||||
<p>Enter the correct password to proceed</p>
|
||||
`;
|
||||
|
||||
// Set up the password interface
|
||||
this.setupPasswordInterface();
|
||||
|
||||
// Set up event listeners
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
setupPasswordInterface() {
|
||||
// Create the password entry interface
|
||||
this.gameContainer.innerHTML = `
|
||||
<div class="password-minigame-area">
|
||||
${this.gameData.showPostit && this.gameData.postitNote ? `
|
||||
<div class="postit-note">
|
||||
${this.gameData.postitNote}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div class="monitor-bezel">
|
||||
<div class="monitor-screen">
|
||||
<div class="password-input-container">
|
||||
<label for="password-field">Password:</label>
|
||||
<div class="password-field-wrapper">
|
||||
<input type="${this.gameData.showPassword ? 'text' : 'password'}"
|
||||
id="password-field"
|
||||
class="password-field"
|
||||
placeholder="Enter password..."
|
||||
maxlength="50">
|
||||
<button type="button" class="toggle-password-btn" id="toggle-password">
|
||||
${this.gameData.showPassword ? '👁️' : '👁️🗨️'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${this.gameData.showHint ? `
|
||||
<div class="password-hint-container">
|
||||
<button type="button" class="hint-btn" id="show-hint">Show Hint</button>
|
||||
<div class="password-hint" id="password-hint" style="display: none;">
|
||||
<strong>Hint:</strong> ${this.gameData.passwordHint}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${this.gameData.showKeyboard ? `
|
||||
<div class="onscreen-keyboard" id="onscreen-keyboard">
|
||||
<div class="keyboard-row">
|
||||
<button class="key" data-key="1">1</button>
|
||||
<button class="key" data-key="2">2</button>
|
||||
<button class="key" data-key="3">3</button>
|
||||
<button class="key" data-key="4">4</button>
|
||||
<button class="key" data-key="5">5</button>
|
||||
<button class="key" data-key="6">6</button>
|
||||
<button class="key" data-key="7">7</button>
|
||||
<button class="key" data-key="8">8</button>
|
||||
<button class="key" data-key="9">9</button>
|
||||
<button class="key" data-key="0">0</button>
|
||||
<button class="key key-backspace" data-key="Backspace">⌫</button>
|
||||
</div>
|
||||
<div class="keyboard-row">
|
||||
<button class="key" data-key="q">Q</button>
|
||||
<button class="key" data-key="w">W</button>
|
||||
<button class="key" data-key="e">E</button>
|
||||
<button class="key" data-key="r">R</button>
|
||||
<button class="key" data-key="t">T</button>
|
||||
<button class="key" data-key="y">Y</button>
|
||||
<button class="key" data-key="u">U</button>
|
||||
<button class="key" data-key="i">I</button>
|
||||
<button class="key" data-key="o">O</button>
|
||||
<button class="key" data-key="p">P</button>
|
||||
</div>
|
||||
<div class="keyboard-row">
|
||||
<button class="key" data-key="a">A</button>
|
||||
<button class="key" data-key="s">S</button>
|
||||
<button class="key" data-key="d">D</button>
|
||||
<button class="key" data-key="f">F</button>
|
||||
<button class="key" data-key="g">G</button>
|
||||
<button class="key" data-key="h">H</button>
|
||||
<button class="key" data-key="j">J</button>
|
||||
<button class="key" data-key="k">K</button>
|
||||
<button class="key" data-key="l">L</button>
|
||||
</div>
|
||||
<div class="keyboard-row">
|
||||
<button class="key" data-key="z">Z</button>
|
||||
<button class="key" data-key="x">X</button>
|
||||
<button class="key" data-key="c">C</button>
|
||||
<button class="key" data-key="v">V</button>
|
||||
<button class="key" data-key="b">B</button>
|
||||
<button class="key" data-key="n">N</button>
|
||||
<button class="key" data-key="m">M</button>
|
||||
<button class="key key-space" data-key=" ">Space</button>
|
||||
</div>
|
||||
<div class="keyboard-row">
|
||||
<button class="key key-special" data-key="Enter">Enter</button>
|
||||
<button class="key key-special" data-key="Escape">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div class="password-actions">
|
||||
<button type="button" class="submit-btn" id="submit-password">Submit</button>
|
||||
<button type="button" class="cancel-btn" id="cancel-password">Cancel</button>
|
||||
</div>
|
||||
|
||||
<div class="attempts-counter">
|
||||
Attempts: <span id="attempts-display">${this.gameData.attempts}</span>/${this.gameData.maxAttempts}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Get references to important elements
|
||||
this.passwordField = document.getElementById('password-field');
|
||||
this.togglePasswordBtn = document.getElementById('toggle-password');
|
||||
this.submitBtn = document.getElementById('submit-password');
|
||||
this.cancelBtn = document.getElementById('cancel-password');
|
||||
this.attemptsDisplay = document.getElementById('attempts-display');
|
||||
|
||||
// Focus the password field
|
||||
if (this.passwordField) {
|
||||
this.passwordField.focus();
|
||||
}
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Password field events
|
||||
if (this.passwordField) {
|
||||
this.addEventListener(this.passwordField, 'keydown', (event) => {
|
||||
this.handleKeyPress(event);
|
||||
});
|
||||
|
||||
this.addEventListener(this.passwordField, 'input', (event) => {
|
||||
this.handlePasswordInput(event);
|
||||
});
|
||||
}
|
||||
|
||||
// Toggle password visibility
|
||||
if (this.togglePasswordBtn) {
|
||||
this.addEventListener(this.togglePasswordBtn, 'click', () => {
|
||||
this.togglePasswordVisibility();
|
||||
});
|
||||
}
|
||||
|
||||
// Submit button
|
||||
if (this.submitBtn) {
|
||||
this.addEventListener(this.submitBtn, 'click', () => {
|
||||
this.submitPassword();
|
||||
});
|
||||
}
|
||||
|
||||
// Cancel button
|
||||
if (this.cancelBtn) {
|
||||
this.addEventListener(this.cancelBtn, 'click', () => {
|
||||
this.cancelPassword();
|
||||
});
|
||||
}
|
||||
|
||||
// Hint button
|
||||
const hintBtn = document.getElementById('show-hint');
|
||||
if (hintBtn) {
|
||||
this.addEventListener(hintBtn, 'click', () => {
|
||||
this.toggleHint();
|
||||
});
|
||||
}
|
||||
|
||||
// Onscreen keyboard
|
||||
const keyboard = document.getElementById('onscreen-keyboard');
|
||||
if (keyboard) {
|
||||
this.addEventListener(keyboard, 'click', (event) => {
|
||||
this.handleKeyboardClick(event);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
// Call parent start
|
||||
super.start();
|
||||
|
||||
console.log("Password minigame started");
|
||||
}
|
||||
|
||||
handleKeyPress(event) {
|
||||
if (!this.gameState.isActive) return;
|
||||
|
||||
switch(event.key) {
|
||||
case 'Enter':
|
||||
event.preventDefault();
|
||||
this.submitPassword();
|
||||
break;
|
||||
case 'Escape':
|
||||
event.preventDefault();
|
||||
this.cancelPassword();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handlePasswordInput(event) {
|
||||
// Update the internal password state
|
||||
this.gameData.password = event.target.value;
|
||||
}
|
||||
|
||||
togglePasswordVisibility() {
|
||||
this.gameData.showPassword = !this.gameData.showPassword;
|
||||
|
||||
// Update input type
|
||||
this.passwordField.type = this.gameData.showPassword ? 'text' : 'password';
|
||||
|
||||
// Update button icon
|
||||
this.togglePasswordBtn.textContent = this.gameData.showPassword ? '👁️' : '👁️🗨️';
|
||||
}
|
||||
|
||||
toggleHint() {
|
||||
const hintElement = document.getElementById('password-hint');
|
||||
const hintBtn = document.getElementById('show-hint');
|
||||
|
||||
if (hintElement && hintBtn) {
|
||||
if (hintElement.style.display === 'none') {
|
||||
hintElement.style.display = 'block';
|
||||
hintBtn.textContent = 'Hide Hint';
|
||||
} else {
|
||||
hintElement.style.display = 'none';
|
||||
hintBtn.textContent = 'Show Hint';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyboardClick(event) {
|
||||
if (!this.gameState.isActive) return;
|
||||
|
||||
const key = event.target;
|
||||
if (!key.classList.contains('key')) return;
|
||||
|
||||
const keyValue = key.dataset.key;
|
||||
|
||||
if (keyValue === 'Enter') {
|
||||
this.submitPassword();
|
||||
} else if (keyValue === 'Escape') {
|
||||
this.cancelPassword();
|
||||
} else if (keyValue === 'Backspace') {
|
||||
this.passwordField.value = this.passwordField.value.slice(0, -1);
|
||||
this.gameData.password = this.passwordField.value;
|
||||
} else if (keyValue === ' ') {
|
||||
this.passwordField.value += ' ';
|
||||
this.gameData.password = this.passwordField.value;
|
||||
} else if (keyValue && keyValue.length === 1) {
|
||||
this.passwordField.value += keyValue;
|
||||
this.gameData.password = this.passwordField.value;
|
||||
}
|
||||
|
||||
// Keep focus on password field
|
||||
this.passwordField.focus();
|
||||
}
|
||||
|
||||
submitPassword() {
|
||||
if (!this.gameState.isActive) return;
|
||||
|
||||
const enteredPassword = this.passwordField.value.trim();
|
||||
|
||||
if (!enteredPassword) {
|
||||
this.showFailure("Please enter a password", false, 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
this.gameData.attempts++;
|
||||
this.attemptsDisplay.textContent = this.gameData.attempts;
|
||||
|
||||
if (enteredPassword === this.correctPassword) {
|
||||
this.passwordCorrect();
|
||||
} else {
|
||||
this.passwordIncorrect();
|
||||
}
|
||||
}
|
||||
|
||||
passwordCorrect() {
|
||||
this.cleanup();
|
||||
this.showSuccess("Password accepted! Access granted.", true, 3000);
|
||||
|
||||
// Set game result for the callback
|
||||
this.gameResult = {
|
||||
success: true,
|
||||
password: this.gameData.password,
|
||||
attempts: this.gameData.attempts
|
||||
};
|
||||
}
|
||||
|
||||
passwordIncorrect() {
|
||||
if (this.gameData.attempts >= this.gameData.maxAttempts) {
|
||||
this.passwordFailed();
|
||||
} else {
|
||||
this.showFailure(`Incorrect password. ${this.gameData.maxAttempts - this.gameData.attempts} attempts remaining.`, false, 3000);
|
||||
|
||||
// Clear the password field
|
||||
this.passwordField.value = '';
|
||||
this.gameData.password = '';
|
||||
this.passwordField.focus();
|
||||
}
|
||||
}
|
||||
|
||||
passwordFailed() {
|
||||
this.cleanup();
|
||||
this.showFailure("Maximum attempts exceeded. Access denied.", true, 3000);
|
||||
|
||||
this.gameResult = {
|
||||
success: false,
|
||||
reason: 'max_attempts_exceeded',
|
||||
attempts: this.gameData.attempts
|
||||
};
|
||||
}
|
||||
|
||||
cancelPassword() {
|
||||
this.cleanup();
|
||||
this.showFailure("Password entry cancelled.", true, 2000);
|
||||
|
||||
this.gameResult = {
|
||||
success: false,
|
||||
reason: 'cancelled',
|
||||
attempts: this.gameData.attempts
|
||||
};
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
// Call parent cleanup (handles event listeners)
|
||||
super.cleanup();
|
||||
}
|
||||
}
|
||||
@@ -264,8 +264,58 @@ export function startPinMinigame(lockable, type, correctPin, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
export function startPasswordMinigame(lockable, type, correctPassword, callback, options = {}) {
|
||||
console.log('Starting password minigame for', type, 'with password:', correctPassword);
|
||||
|
||||
// Initialize the minigame framework if not already done
|
||||
if (!window.MinigameFramework) {
|
||||
console.error('MinigameFramework not available');
|
||||
// Fallback to simple prompt
|
||||
const passwordInput = prompt(`Enter password:`);
|
||||
if (passwordInput === correctPassword) {
|
||||
console.log('PASSWORD SUCCESS (fallback)');
|
||||
window.gameAlert(`Correct password! The ${type} is now unlocked.`, 'success', 'Password Accepted', 4000);
|
||||
callback(true);
|
||||
} else if (passwordInput !== null) {
|
||||
console.log('PASSWORD FAIL (fallback)');
|
||||
window.gameAlert("Incorrect password.", 'error', 'Password Rejected', 3000);
|
||||
callback(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the advanced minigame framework
|
||||
if (!window.MinigameFramework.mainGameScene) {
|
||||
window.MinigameFramework.init(window.game);
|
||||
}
|
||||
|
||||
// Start the password minigame
|
||||
window.MinigameFramework.startMinigame('password', null, {
|
||||
title: `Enter password for ${type}`,
|
||||
password: correctPassword,
|
||||
passwordHint: options.passwordHint || '',
|
||||
showHint: options.showHint || false,
|
||||
showKeyboard: options.showKeyboard || false,
|
||||
maxAttempts: options.maxAttempts || 3,
|
||||
postitNote: options.postitNote || '',
|
||||
showPostit: options.showPostit || false,
|
||||
onComplete: (success, result) => {
|
||||
if (success) {
|
||||
console.log('PASSWORD MINIGAME SUCCESS');
|
||||
window.gameAlert(`Correct password! The ${type} is now unlocked.`, 'success', 'Password Accepted', 4000);
|
||||
callback(true);
|
||||
} else {
|
||||
console.log('PASSWORD MINIGAME FAILED');
|
||||
window.gameAlert("Failed to enter correct password.", 'error', 'Password Rejected', 3000);
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Export for global access
|
||||
window.startLockpickingMinigame = startLockpickingMinigame;
|
||||
window.startKeySelectionMinigame = startKeySelectionMinigame;
|
||||
window.startPinMinigame = startPinMinigame;
|
||||
window.startPasswordMinigame = startPasswordMinigame;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import { DOOR_ALIGN_OVERLAP } from '../utils/constants.js';
|
||||
import { rooms } from '../core/rooms.js';
|
||||
import { unlockDoor } from './doors.js';
|
||||
import { startLockpickingMinigame, startKeySelectionMinigame, startPinMinigame } from './minigame-starters.js';
|
||||
import { startLockpickingMinigame, startKeySelectionMinigame, startPinMinigame, startPasswordMinigame } from './minigame-starters.js';
|
||||
|
||||
// Helper function to check if two rectangles overlap
|
||||
function boundsOverlap(rect1, rect2) {
|
||||
@@ -106,29 +106,22 @@ export function handleUnlock(lockable, type) {
|
||||
|
||||
case 'password':
|
||||
console.log('PASSWORD REQUESTED');
|
||||
if (window.showPasswordModal) {
|
||||
window.showPasswordModal(function(passwordInput) {
|
||||
if (passwordInput === lockRequirements.requires) {
|
||||
unlockTarget(lockable, type, lockable.layer);
|
||||
console.log('PASSWORD SUCCESS');
|
||||
window.gameAlert(`Correct password! The ${type} is now unlocked.`, 'success', 'Password Accepted', 4000);
|
||||
} else if (passwordInput !== null) {
|
||||
console.log('PASSWORD FAIL');
|
||||
window.gameAlert("Incorrect password.", 'error', 'Password Rejected', 3000);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Fallback to prompt
|
||||
const passwordInput = prompt(`Enter password:`);
|
||||
if (passwordInput === lockRequirements.requires) {
|
||||
|
||||
// Get password options from the lockable object
|
||||
const passwordOptions = {
|
||||
passwordHint: lockable.passwordHint || lockable.scenarioData?.passwordHint || '',
|
||||
showHint: lockable.showHint || lockable.scenarioData?.showHint || false,
|
||||
showKeyboard: lockable.showKeyboard || lockable.scenarioData?.showKeyboard || false,
|
||||
maxAttempts: lockable.maxAttempts || lockable.scenarioData?.maxAttempts || 3,
|
||||
postitNote: lockable.postitNote || lockable.scenarioData?.postitNote || '',
|
||||
showPostit: lockable.showPostit || lockable.scenarioData?.showPostit || false
|
||||
};
|
||||
|
||||
startPasswordMinigame(lockable, type, lockRequirements.requires, (success) => {
|
||||
if (success) {
|
||||
unlockTarget(lockable, type, lockable.layer);
|
||||
console.log('PASSWORD SUCCESS');
|
||||
window.gameAlert(`Correct password! The ${type} is now unlocked.`, 'success', 'Password Accepted', 4000);
|
||||
} else if (passwordInput !== null) {
|
||||
console.log('PASSWORD FAIL');
|
||||
window.gameAlert("Incorrect password.", 'error', 'Password Rejected', 3000);
|
||||
}
|
||||
}
|
||||
}, passwordOptions);
|
||||
break;
|
||||
|
||||
case 'biometric':
|
||||
|
||||
157
password-minigame-example.json
Normal file
157
password-minigame-example.json
Normal file
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"name": "Password Minigame Example",
|
||||
"description": "Example scenario showing how to use the password minigame",
|
||||
"rooms": {
|
||||
"office": {
|
||||
"id": "office",
|
||||
"name": "Office",
|
||||
"image": "room_office.png",
|
||||
"map": "room_office.json",
|
||||
"position": { "x": 0, "y": 0 },
|
||||
"connections": []
|
||||
}
|
||||
},
|
||||
"objects": [
|
||||
{
|
||||
"id": "secure_door",
|
||||
"name": "Secure Door",
|
||||
"type": "door",
|
||||
"room": "office",
|
||||
"x": 400,
|
||||
"y": 300,
|
||||
"image": "door.png",
|
||||
"lockType": "password",
|
||||
"requires": "admin123",
|
||||
"passwordHint": "The default administrator password",
|
||||
"showHint": true,
|
||||
"showKeyboard": false,
|
||||
"maxAttempts": 3,
|
||||
"locked": true,
|
||||
"observations": "A secure door with a password keypad."
|
||||
},
|
||||
{
|
||||
"id": "computer_terminal",
|
||||
"name": "Computer Terminal",
|
||||
"type": "computer",
|
||||
"room": "office",
|
||||
"x": 200,
|
||||
"y": 200,
|
||||
"image": "computer.png",
|
||||
"lockType": "password",
|
||||
"requires": "cyber2024",
|
||||
"passwordHint": "Current year with cyber prefix",
|
||||
"showHint": true,
|
||||
"showKeyboard": true,
|
||||
"maxAttempts": 5,
|
||||
"postitNote": "Password: cyber2024",
|
||||
"showPostit": true,
|
||||
"locked": true,
|
||||
"observations": "A computer terminal requiring password access."
|
||||
},
|
||||
{
|
||||
"id": "safe_box",
|
||||
"name": "Safe Box",
|
||||
"type": "container",
|
||||
"room": "office",
|
||||
"x": 600,
|
||||
"y": 400,
|
||||
"image": "safe.png",
|
||||
"lockType": "password",
|
||||
"requires": "treasure",
|
||||
"showHint": false,
|
||||
"showKeyboard": true,
|
||||
"maxAttempts": 2,
|
||||
"locked": true,
|
||||
"contents": [
|
||||
{
|
||||
"id": "secret_document",
|
||||
"name": "Secret Document",
|
||||
"type": "document",
|
||||
"image": "document.png",
|
||||
"takeable": true,
|
||||
"observations": "A classified document containing sensitive information."
|
||||
}
|
||||
],
|
||||
"observations": "A heavy safe box with a digital keypad."
|
||||
},
|
||||
{
|
||||
"id": "office_computer",
|
||||
"name": "Office Computer",
|
||||
"type": "container",
|
||||
"room": "office",
|
||||
"x": 300,
|
||||
"y": 300,
|
||||
"image": "computer.png",
|
||||
"lockType": "password",
|
||||
"requires": "desktop123",
|
||||
"showHint": false,
|
||||
"showKeyboard": false,
|
||||
"maxAttempts": 3,
|
||||
"locked": true,
|
||||
"contents": [
|
||||
{
|
||||
"id": "project_files",
|
||||
"name": "Project Files",
|
||||
"type": "document",
|
||||
"takeable": true,
|
||||
"observations": "Important project documentation."
|
||||
},
|
||||
{
|
||||
"id": "meeting_notes",
|
||||
"name": "Meeting Notes",
|
||||
"type": "notes",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "Meeting notes about the upcoming project deadline..."
|
||||
},
|
||||
{
|
||||
"id": "encryption_key",
|
||||
"name": "Encryption Key",
|
||||
"type": "key",
|
||||
"takeable": true,
|
||||
"observations": "A digital encryption key file."
|
||||
}
|
||||
],
|
||||
"observations": "An office computer with desktop access. Desktop mode will be automatically enabled."
|
||||
},
|
||||
{
|
||||
"id": "tablet_device",
|
||||
"name": "Executive Tablet",
|
||||
"type": "container",
|
||||
"room": "office",
|
||||
"x": 500,
|
||||
"y": 200,
|
||||
"image": "tablet.png",
|
||||
"lockType": "password",
|
||||
"requires": "tablet2024",
|
||||
"showHint": false,
|
||||
"showKeyboard": true,
|
||||
"maxAttempts": 3,
|
||||
"locked": true,
|
||||
"contents": [
|
||||
{
|
||||
"id": "executive_notes",
|
||||
"name": "Executive Notes",
|
||||
"type": "notes",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "Confidential executive meeting notes..."
|
||||
},
|
||||
{
|
||||
"id": "financial_data",
|
||||
"name": "Financial Data",
|
||||
"type": "document",
|
||||
"takeable": true,
|
||||
"observations": "Sensitive financial information."
|
||||
}
|
||||
],
|
||||
"observations": "An executive tablet device. Desktop mode will be automatically enabled."
|
||||
}
|
||||
],
|
||||
"victoryConditions": [
|
||||
{
|
||||
"type": "collect_item",
|
||||
"itemId": "secret_document"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -30,8 +30,31 @@
|
||||
"type": "pc",
|
||||
"name": "Reception Computer",
|
||||
"takeable": false,
|
||||
"lockType": "password",
|
||||
"passwordHint": "Optional hint text",
|
||||
"showHint": true,
|
||||
"showKeyboard": true,
|
||||
"maxAttempts": 3,
|
||||
"locked": true,
|
||||
"requires": "password",
|
||||
"observations": "The reception's computer, currently locked"
|
||||
"observations": "The reception's computer, currently locked",
|
||||
"contents": [
|
||||
{
|
||||
"type": "notes",
|
||||
"name": "Private Note",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "Closet keypad code: 7391 - Must move evidence to safe before audit",
|
||||
"observations": "A hastily written note on expensive paper"
|
||||
},
|
||||
{
|
||||
"type": "key",
|
||||
"name": "Safe Key",
|
||||
"takeable": true,
|
||||
"key_id": "safe_key:52,29,44,37",
|
||||
"observations": "A heavy-duty safe key hidden behind server equipment"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "tablet",
|
||||
|
||||
383
test-auto-desktop.html
Normal file
383
test-auto-desktop.html
Normal file
@@ -0,0 +1,383 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Auto Desktop Mode Test</title>
|
||||
|
||||
<!-- Include the game's CSS -->
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/minigames.css">
|
||||
<link rel="stylesheet" href="css/container-minigame.css">
|
||||
<link rel="stylesheet" href="css/notifications.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.test-container {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border: 2px solid #444;
|
||||
border-radius: 10px;
|
||||
background: #2a2a2a;
|
||||
}
|
||||
|
||||
.test-button {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 10px;
|
||||
margin: 5px;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.test-button:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
.test-button.success {
|
||||
background: #2ecc71;
|
||||
}
|
||||
|
||||
.test-button.success:hover {
|
||||
background: #27ae60;
|
||||
}
|
||||
|
||||
.test-description {
|
||||
font-size: 8px;
|
||||
color: #ccc;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.test-results {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
background: #1a1a1a;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
|
||||
.test-results h3 {
|
||||
color: #00ff00;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.test-results pre {
|
||||
background: #0a0a0a;
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
overflow-x: auto;
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
.detection-info {
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
border: 1px solid #00ff00;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
font-size: 8px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="test-container">
|
||||
<h1>Auto Desktop Mode Detection Test</h1>
|
||||
<p>Test automatic desktop mode detection for PC, tablet, and computer containers.</p>
|
||||
|
||||
<div class="detection-info">
|
||||
<strong>Auto-Detection Keywords:</strong> computer, pc, laptop, desktop, terminal, workstation, tablet, ipad, surface, monitor, screen, display, server, mainframe, console, kiosk, smartboard
|
||||
</div>
|
||||
|
||||
<!-- Computer Container Test -->
|
||||
<div class="test-section">
|
||||
<h2>Computer Container (Auto Desktop)</h2>
|
||||
<div class="test-description">
|
||||
Test container with "computer" in the name - should automatically enable desktop mode.
|
||||
</div>
|
||||
<button class="test-button success" onclick="testComputerContainer()">Test Computer Container</button>
|
||||
</div>
|
||||
|
||||
<!-- Tablet Container Test -->
|
||||
<div class="test-section">
|
||||
<h2>Tablet Container (Auto Desktop)</h2>
|
||||
<div class="test-description">
|
||||
Test container with "tablet" in the name - should automatically enable desktop mode.
|
||||
</div>
|
||||
<button class="test-button success" onclick="testTabletContainer()">Test Tablet Container</button>
|
||||
</div>
|
||||
|
||||
<!-- PC Container Test -->
|
||||
<div class="test-section">
|
||||
<h2>PC Container (Auto Desktop)</h2>
|
||||
<div class="test-description">
|
||||
Test container with "pc" in the name - should automatically enable desktop mode.
|
||||
</div>
|
||||
<button class="test-button success" onclick="testPCContainer()">Test PC Container</button>
|
||||
</div>
|
||||
|
||||
<!-- Regular Container Test -->
|
||||
<div class="test-section">
|
||||
<h2>Regular Container (No Auto Desktop)</h2>
|
||||
<div class="test-description">
|
||||
Test container with "safe" in the name - should NOT automatically enable desktop mode.
|
||||
</div>
|
||||
<button class="test-button" onclick="testRegularContainer()">Test Regular Container</button>
|
||||
</div>
|
||||
|
||||
<!-- Manual Override Test -->
|
||||
<div class="test-section">
|
||||
<h2>Manual Override Test</h2>
|
||||
<div class="test-description">
|
||||
Test container with "safe" but manually force desktop mode - should enable desktop mode.
|
||||
</div>
|
||||
<button class="test-button" onclick="testManualOverride()">Test Manual Override</button>
|
||||
</div>
|
||||
|
||||
<!-- Test Results -->
|
||||
<div class="test-results">
|
||||
<h3>Test Results</h3>
|
||||
<pre id="test-results">Click a test button to see results here...</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Include Phaser first -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.min.js"></script>
|
||||
|
||||
<!-- Include the minigame framework -->
|
||||
<script type="module">
|
||||
// Import the minigame framework and container minigame
|
||||
import { MinigameFramework } from './js/minigames/framework/minigame-manager.js';
|
||||
import { ContainerMinigame } from './js/minigames/container/container-minigame.js';
|
||||
|
||||
// Initialize the framework
|
||||
window.MinigameFramework = MinigameFramework;
|
||||
MinigameFramework.registerScene('container', ContainerMinigame);
|
||||
|
||||
// Mock game object
|
||||
window.game = {
|
||||
sound: {
|
||||
play: function(soundName) {
|
||||
console.log('Playing sound:', soundName);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Mock game alert function
|
||||
window.gameAlert = function(message, type, title, duration) {
|
||||
console.log(`[${type.toUpperCase()}] ${title}: ${message}`);
|
||||
updateTestResults(`[${type.toUpperCase()}] ${title}: ${message}`);
|
||||
};
|
||||
|
||||
// Mock inventory functions
|
||||
window.addToInventory = function(item) {
|
||||
console.log('Added to inventory:', item);
|
||||
updateTestResults(`Added to inventory: ${item.name}`);
|
||||
};
|
||||
|
||||
window.removeFromInventory = function(item) {
|
||||
console.log('Removed from inventory:', item);
|
||||
updateTestResults(`Removed from inventory: ${item.name}`);
|
||||
};
|
||||
|
||||
// Test functions
|
||||
function testComputerContainer() {
|
||||
updateTestResults("Testing computer container (should auto-enable desktop mode)...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Office Computer",
|
||||
type: "container",
|
||||
observations: "A computer that should auto-enable desktop mode"
|
||||
},
|
||||
name: "computer"
|
||||
};
|
||||
|
||||
const contents = [
|
||||
{
|
||||
id: "file1",
|
||||
name: "Document",
|
||||
type: "document",
|
||||
takeable: true
|
||||
}
|
||||
];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'Computer Container Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: null, // Let it auto-detect
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Computer container test completed. Success: ${success}, Desktop mode should be enabled automatically.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testTabletContainer() {
|
||||
updateTestResults("Testing tablet container (should auto-enable desktop mode)...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Executive Tablet",
|
||||
type: "container",
|
||||
observations: "A tablet that should auto-enable desktop mode"
|
||||
},
|
||||
name: "tablet"
|
||||
};
|
||||
|
||||
const contents = [
|
||||
{
|
||||
id: "note1",
|
||||
name: "Notes",
|
||||
type: "notes",
|
||||
takeable: true
|
||||
}
|
||||
];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'Tablet Container Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: null, // Let it auto-detect
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Tablet container test completed. Success: ${success}, Desktop mode should be enabled automatically.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testPCContainer() {
|
||||
updateTestResults("Testing PC container (should auto-enable desktop mode)...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Gaming PC",
|
||||
type: "container",
|
||||
observations: "A PC that should auto-enable desktop mode"
|
||||
},
|
||||
name: "pc"
|
||||
};
|
||||
|
||||
const contents = [
|
||||
{
|
||||
id: "game1",
|
||||
name: "Game Files",
|
||||
type: "document",
|
||||
takeable: true
|
||||
}
|
||||
];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'PC Container Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: null, // Let it auto-detect
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`PC container test completed. Success: ${success}, Desktop mode should be enabled automatically.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testRegularContainer() {
|
||||
updateTestResults("Testing regular container (should NOT auto-enable desktop mode)...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Safe Box",
|
||||
type: "container",
|
||||
observations: "A safe that should NOT auto-enable desktop mode"
|
||||
},
|
||||
name: "safe"
|
||||
};
|
||||
|
||||
const contents = [
|
||||
{
|
||||
id: "item1",
|
||||
name: "Valuable Item",
|
||||
type: "key",
|
||||
takeable: true
|
||||
}
|
||||
];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'Regular Container Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: null, // Let it auto-detect
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Regular container test completed. Success: ${success}, Desktop mode should NOT be enabled automatically.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testManualOverride() {
|
||||
updateTestResults("Testing manual override (force desktop mode on safe)...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Safe Box",
|
||||
type: "container",
|
||||
observations: "A safe with manually forced desktop mode"
|
||||
},
|
||||
name: "safe"
|
||||
};
|
||||
|
||||
const contents = [
|
||||
{
|
||||
id: "item1",
|
||||
name: "Valuable Item",
|
||||
type: "key",
|
||||
takeable: true
|
||||
}
|
||||
];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'Manual Override Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: true, // Manually force desktop mode
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Manual override test completed. Success: ${success}, Desktop mode should be enabled manually.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateTestResults(message) {
|
||||
const resultsElement = document.getElementById('test-results');
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
resultsElement.textContent += `[${timestamp}] ${message}\n`;
|
||||
resultsElement.scrollTop = resultsElement.scrollHeight;
|
||||
}
|
||||
|
||||
// Make functions globally available
|
||||
window.testComputerContainer = testComputerContainer;
|
||||
window.testTabletContainer = testTabletContainer;
|
||||
window.testPCContainer = testPCContainer;
|
||||
window.testRegularContainer = testRegularContainer;
|
||||
window.testManualOverride = testManualOverride;
|
||||
|
||||
// Initialize test results
|
||||
updateTestResults("Auto desktop mode detection test suite loaded and ready.");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
348
test-container-desktop.html
Normal file
348
test-container-desktop.html
Normal file
@@ -0,0 +1,348 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Container Desktop Mode Test</title>
|
||||
|
||||
<!-- Include the game's CSS -->
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/minigames.css">
|
||||
<link rel="stylesheet" href="css/container-minigame.css">
|
||||
<link rel="stylesheet" href="css/notifications.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.test-container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border: 2px solid #444;
|
||||
border-radius: 10px;
|
||||
background: #2a2a2a;
|
||||
}
|
||||
|
||||
.test-button {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 10px;
|
||||
margin: 5px;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.test-button:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
.test-button.success {
|
||||
background: #2ecc71;
|
||||
}
|
||||
|
||||
.test-button.success:hover {
|
||||
background: #27ae60;
|
||||
}
|
||||
|
||||
.test-description {
|
||||
font-size: 8px;
|
||||
color: #ccc;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.test-results {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
background: #1a1a1a;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
|
||||
.test-results h3 {
|
||||
color: #00ff00;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.test-results pre {
|
||||
background: #0a0a0a;
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
overflow-x: auto;
|
||||
font-size: 8px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="test-container">
|
||||
<h1>Container Desktop Mode Test Suite</h1>
|
||||
<p>Test the container minigame in desktop mode with desktop wallpaper and icons.</p>
|
||||
|
||||
<!-- Standard Container Test -->
|
||||
<div class="test-section">
|
||||
<h2>Standard Container Test</h2>
|
||||
<div class="test-description">
|
||||
Test the standard container minigame (non-desktop mode) with various items.
|
||||
</div>
|
||||
<button class="test-button" onclick="testStandardContainer()">Test Standard Container</button>
|
||||
</div>
|
||||
|
||||
<!-- Desktop Container Test -->
|
||||
<div class="test-section">
|
||||
<h2>Desktop Container Test</h2>
|
||||
<div class="test-description">
|
||||
Test the container minigame in desktop mode with desktop wallpaper and scattered icons.
|
||||
</div>
|
||||
<button class="test-button success" onclick="testDesktopContainer()">Test Desktop Container</button>
|
||||
</div>
|
||||
|
||||
<!-- Desktop with Notes Test -->
|
||||
<div class="test-section">
|
||||
<h2>Desktop with Notes Test</h2>
|
||||
<div class="test-description">
|
||||
Test desktop mode with notes that should trigger the notes minigame when clicked.
|
||||
</div>
|
||||
<button class="test-button" onclick="testDesktopWithNotes()">Test Desktop with Notes</button>
|
||||
</div>
|
||||
|
||||
<!-- Empty Desktop Test -->
|
||||
<div class="test-section">
|
||||
<h2>Empty Desktop Test</h2>
|
||||
<div class="test-description">
|
||||
Test desktop mode with no items to see the empty desktop message.
|
||||
</div>
|
||||
<button class="test-button" onclick="testEmptyDesktop()">Test Empty Desktop</button>
|
||||
</div>
|
||||
|
||||
<!-- Test Results -->
|
||||
<div class="test-results">
|
||||
<h3>Test Results</h3>
|
||||
<pre id="test-results">Click a test button to see results here...</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Include Phaser first -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.min.js"></script>
|
||||
|
||||
<!-- Include the minigame framework -->
|
||||
<script type="module">
|
||||
// Import the minigame framework and container minigame
|
||||
import { MinigameFramework } from './js/minigames/framework/minigame-manager.js';
|
||||
import { ContainerMinigame } from './js/minigames/container/container-minigame.js';
|
||||
|
||||
// Initialize the framework
|
||||
window.MinigameFramework = MinigameFramework;
|
||||
MinigameFramework.registerScene('container', ContainerMinigame);
|
||||
|
||||
// Mock game object
|
||||
window.game = {
|
||||
sound: {
|
||||
play: function(soundName) {
|
||||
console.log('Playing sound:', soundName);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Mock game alert function
|
||||
window.gameAlert = function(message, type, title, duration) {
|
||||
console.log(`[${type.toUpperCase()}] ${title}: ${message}`);
|
||||
updateTestResults(`[${type.toUpperCase()}] ${title}: ${message}`);
|
||||
};
|
||||
|
||||
// Mock inventory functions
|
||||
window.addToInventory = function(item) {
|
||||
console.log('Added to inventory:', item);
|
||||
updateTestResults(`Added to inventory: ${item.name}`);
|
||||
};
|
||||
|
||||
window.removeFromInventory = function(item) {
|
||||
console.log('Removed from inventory:', item);
|
||||
updateTestResults(`Removed from inventory: ${item.name}`);
|
||||
};
|
||||
|
||||
// Test functions - define them globally
|
||||
function testStandardContainer() {
|
||||
updateTestResults("Starting standard container test...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Test Container",
|
||||
observations: "A standard container for testing"
|
||||
},
|
||||
name: "container"
|
||||
};
|
||||
|
||||
const contents = [
|
||||
{
|
||||
id: "item1",
|
||||
name: "Test Item 1",
|
||||
type: "key",
|
||||
takeable: true
|
||||
},
|
||||
{
|
||||
id: "item2",
|
||||
name: "Test Item 2",
|
||||
type: "document",
|
||||
takeable: true
|
||||
}
|
||||
];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'Standard Container Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: false,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Standard container test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function testDesktopContainer() {
|
||||
updateTestResults("Starting desktop container test...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Computer Desktop",
|
||||
observations: "A computer desktop with scattered files and applications"
|
||||
},
|
||||
name: "computer"
|
||||
};
|
||||
|
||||
const contents = [
|
||||
{
|
||||
id: "file1",
|
||||
name: "Secret Document",
|
||||
type: "document",
|
||||
takeable: true
|
||||
},
|
||||
{
|
||||
id: "file2",
|
||||
name: "Encryption Key",
|
||||
type: "key",
|
||||
takeable: true
|
||||
},
|
||||
{
|
||||
id: "file3",
|
||||
name: "Password List",
|
||||
type: "notes",
|
||||
takeable: true
|
||||
},
|
||||
{
|
||||
id: "file4",
|
||||
name: "Backup Files",
|
||||
type: "folder",
|
||||
takeable: true
|
||||
}
|
||||
];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'Desktop Container Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: true,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Desktop container test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function testDesktopWithNotes() {
|
||||
updateTestResults("Starting desktop with notes test...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Office Computer",
|
||||
observations: "An office computer with important documents"
|
||||
},
|
||||
name: "computer"
|
||||
};
|
||||
|
||||
const contents = [
|
||||
{
|
||||
id: "notes1",
|
||||
name: "Meeting Notes",
|
||||
type: "notes",
|
||||
takeable: true,
|
||||
readable: true,
|
||||
text: "Important meeting notes about the project..."
|
||||
},
|
||||
{
|
||||
id: "file1",
|
||||
name: "Project Files",
|
||||
type: "document",
|
||||
takeable: true
|
||||
}
|
||||
];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'Desktop with Notes Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: true,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Desktop with notes test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function testEmptyDesktop() {
|
||||
updateTestResults("Starting empty desktop test...");
|
||||
|
||||
const mockContainer = {
|
||||
scenarioData: {
|
||||
name: "Empty Desktop",
|
||||
observations: "A clean desktop with no files"
|
||||
},
|
||||
name: "computer"
|
||||
};
|
||||
|
||||
const contents = [];
|
||||
|
||||
MinigameFramework.startMinigame('container', null, {
|
||||
title: 'Empty Desktop Test',
|
||||
containerItem: mockContainer,
|
||||
contents: contents,
|
||||
isTakeable: false,
|
||||
desktopMode: true,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Empty desktop test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function updateTestResults(message) {
|
||||
const resultsElement = document.getElementById('test-results');
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
resultsElement.textContent += `[${timestamp}] ${message}\n`;
|
||||
resultsElement.scrollTop = resultsElement.scrollHeight;
|
||||
}
|
||||
|
||||
// Make functions globally available
|
||||
window.testStandardContainer = testStandardContainer;
|
||||
window.testDesktopContainer = testDesktopContainer;
|
||||
window.testDesktopWithNotes = testDesktopWithNotes;
|
||||
window.testEmptyDesktop = testEmptyDesktop;
|
||||
|
||||
// Initialize test results
|
||||
updateTestResults("Container desktop mode test suite loaded and ready.");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
189
test-container-simple.html
Normal file
189
test-container-simple.html
Normal file
@@ -0,0 +1,189 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Simple Container Desktop Test</title>
|
||||
|
||||
<!-- Include the game's CSS -->
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/minigames.css">
|
||||
<link rel="stylesheet" href="css/container-minigame.css">
|
||||
<link rel="stylesheet" href="css/notifications.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.test-container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border: 2px solid #444;
|
||||
border-radius: 10px;
|
||||
background: #2a2a2a;
|
||||
}
|
||||
|
||||
.test-button {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 10px;
|
||||
margin: 5px;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.test-button:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
.test-button.success {
|
||||
background: #2ecc71;
|
||||
}
|
||||
|
||||
.test-button.success:hover {
|
||||
background: #27ae60;
|
||||
}
|
||||
|
||||
.test-description {
|
||||
font-size: 8px;
|
||||
color: #ccc;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.demo-area {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border: 2px solid #00ff00;
|
||||
border-radius: 10px;
|
||||
background: #1a1a1a;
|
||||
min-height: 400px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="test-container">
|
||||
<h1>Simple Container Desktop Mode Test</h1>
|
||||
<p>Test the container desktop mode CSS and layout without the full framework.</p>
|
||||
|
||||
<!-- Standard Container Demo -->
|
||||
<div class="test-section">
|
||||
<h2>Standard Container Layout</h2>
|
||||
<div class="test-description">
|
||||
Standard container minigame layout (non-desktop mode).
|
||||
</div>
|
||||
<div class="demo-area">
|
||||
<div class="container-minigame">
|
||||
<div class="container-image-section">
|
||||
<img src="assets/objects/container.png" alt="Container" class="container-image">
|
||||
<div class="container-info">
|
||||
<h4>Test Container</h4>
|
||||
<p>A standard container for testing</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-contents-section">
|
||||
<h4>Contents</h4>
|
||||
<div class="container-contents-grid">
|
||||
<div class="container-content-slot">
|
||||
<img src="assets/objects/key.png" alt="Key" class="container-content-item">
|
||||
<div class="container-content-tooltip">Test Key</div>
|
||||
</div>
|
||||
<div class="container-content-slot">
|
||||
<img src="assets/objects/document.png" alt="Document" class="container-content-item">
|
||||
<div class="container-content-tooltip">Test Document</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Desktop Container Demo -->
|
||||
<div class="test-section">
|
||||
<h2>Desktop Container Layout</h2>
|
||||
<div class="test-description">
|
||||
Container minigame in desktop mode with desktop wallpaper and scattered icons.
|
||||
</div>
|
||||
<div class="demo-area">
|
||||
<div class="container-minigame desktop-mode">
|
||||
<div class="desktop-background">
|
||||
<div class="desktop-wallpaper"></div>
|
||||
<div class="desktop-icons">
|
||||
<div class="desktop-icon" style="left: 20%; top: 15%;">
|
||||
<img src="assets/objects/document.png" alt="Document" class="desktop-icon-image">
|
||||
<div class="desktop-icon-label">Secret Files</div>
|
||||
</div>
|
||||
<div class="desktop-icon" style="left: 60%; top: 25%;">
|
||||
<img src="assets/objects/key.png" alt="Key" class="desktop-icon-image">
|
||||
<div class="desktop-icon-label">Encryption Key</div>
|
||||
</div>
|
||||
<div class="desktop-icon" style="left: 40%; top: 45%;">
|
||||
<img src="assets/objects/notes.png" alt="Notes" class="desktop-icon-image">
|
||||
<div class="desktop-icon-label">Meeting Notes</div>
|
||||
</div>
|
||||
<div class="desktop-icon" style="left: 70%; top: 50%;">
|
||||
<img src="assets/objects/folder.png" alt="Folder" class="desktop-icon-image">
|
||||
<div class="desktop-icon-label">Backup Files</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-taskbar">
|
||||
<div class="desktop-info">
|
||||
<span class="desktop-title">Office Computer</span>
|
||||
<span class="desktop-subtitle">Desktop with scattered files</span>
|
||||
</div>
|
||||
<div class="desktop-actions">
|
||||
<button class="minigame-button">Take Container</button>
|
||||
<button class="minigame-button">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Empty Desktop Demo -->
|
||||
<div class="test-section">
|
||||
<h2>Empty Desktop Layout</h2>
|
||||
<div class="test-description">
|
||||
Desktop mode with no items to show the empty desktop message.
|
||||
</div>
|
||||
<div class="demo-area">
|
||||
<div class="container-minigame desktop-mode">
|
||||
<div class="desktop-background">
|
||||
<div class="desktop-wallpaper"></div>
|
||||
<div class="desktop-icons">
|
||||
<div class="empty-desktop">Desktop is empty</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-taskbar">
|
||||
<div class="desktop-info">
|
||||
<span class="desktop-title">Empty Desktop</span>
|
||||
<span class="desktop-subtitle">No files found</span>
|
||||
</div>
|
||||
<div class="desktop-actions">
|
||||
<button class="minigame-button">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
290
test-password-minigame.html
Normal file
290
test-password-minigame.html
Normal file
@@ -0,0 +1,290 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Password Minigame Test</title>
|
||||
|
||||
<!-- Include the game's CSS -->
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/minigames.css">
|
||||
<link rel="stylesheet" href="css/notifications.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.test-container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border: 2px solid #444;
|
||||
border-radius: 10px;
|
||||
background: #2a2a2a;
|
||||
}
|
||||
|
||||
.test-button {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 10px;
|
||||
margin: 5px;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.test-button:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
.test-button.success {
|
||||
background: #2ecc71;
|
||||
}
|
||||
|
||||
.test-button.success:hover {
|
||||
background: #27ae60;
|
||||
}
|
||||
|
||||
.test-button.warning {
|
||||
background: #f39c12;
|
||||
}
|
||||
|
||||
.test-button.warning:hover {
|
||||
background: #e67e22;
|
||||
}
|
||||
|
||||
.test-button.danger {
|
||||
background: #e74c3c;
|
||||
}
|
||||
|
||||
.test-button.danger:hover {
|
||||
background: #c0392b;
|
||||
}
|
||||
|
||||
.test-description {
|
||||
font-size: 8px;
|
||||
color: #ccc;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.test-results {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
background: #1a1a1a;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
|
||||
.test-results h3 {
|
||||
color: #00ff00;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.test-results pre {
|
||||
background: #0a0a0a;
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
overflow-x: auto;
|
||||
font-size: 8px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="test-container">
|
||||
<h1>Password Minigame Test Suite</h1>
|
||||
<p>Test the new password minigame with various configurations and options.</p>
|
||||
|
||||
<!-- Basic Password Test -->
|
||||
<div class="test-section">
|
||||
<h2>Basic Password Test</h2>
|
||||
<div class="test-description">
|
||||
Test basic password entry with show/hide functionality. Password: "secret123"
|
||||
</div>
|
||||
<button class="test-button success" onclick="testBasicPassword()">Test Basic Password</button>
|
||||
</div>
|
||||
|
||||
<!-- Password with Hint -->
|
||||
<div class="test-section">
|
||||
<h2>Password with Hint (Desktop Background)</h2>
|
||||
<div class="test-description">
|
||||
Test password entry with hint button inside monitor bezel with desktop wallpaper. Password: "admin"<br>
|
||||
Hint: "The default administrator password"
|
||||
</div>
|
||||
<button class="test-button warning" onclick="testPasswordWithHint()">Test Password with Hint</button>
|
||||
</div>
|
||||
|
||||
<!-- Password with Onscreen Keyboard -->
|
||||
<div class="test-section">
|
||||
<h2>Password with Onscreen Keyboard</h2>
|
||||
<div class="test-description">
|
||||
Test password entry with onscreen QWERTY keyboard. Password: "keyboard"
|
||||
</div>
|
||||
<button class="test-button" onclick="testPasswordWithKeyboard()">Test Password with Keyboard</button>
|
||||
</div>
|
||||
|
||||
<!-- Full Featured Password -->
|
||||
<div class="test-section">
|
||||
<h2>Full Featured Password</h2>
|
||||
<div class="test-description">
|
||||
Test password with all features: hint, keyboard, and custom attempts. Password: "fulltest"<br>
|
||||
Hint: "A complete test of all features"
|
||||
</div>
|
||||
<button class="test-button" onclick="testFullFeaturedPassword()">Test Full Featured Password</button>
|
||||
</div>
|
||||
|
||||
<!-- Password with Post-it Note -->
|
||||
<div class="test-section">
|
||||
<h2>Password with Post-it Note</h2>
|
||||
<div class="test-description">
|
||||
Test password with post-it note on desktop. Password: "postit"<br>
|
||||
Post-it: "Password is written on the sticky note!"
|
||||
</div>
|
||||
<button class="test-button" onclick="testPasswordWithPostit()">Test Password with Post-it</button>
|
||||
</div>
|
||||
|
||||
<!-- Wrong Password Test -->
|
||||
<div class="test-section">
|
||||
<h2>Wrong Password Test</h2>
|
||||
<div class="test-description">
|
||||
Test entering wrong passwords to trigger failure scenarios. Try: "wrong", "incorrect", "fail"
|
||||
</div>
|
||||
<button class="test-button danger" onclick="testWrongPassword()">Test Wrong Password</button>
|
||||
</div>
|
||||
|
||||
<!-- Test Results -->
|
||||
<div class="test-results">
|
||||
<h3>Test Results</h3>
|
||||
<pre id="test-results">Click a test button to see results here...</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Include the minigame framework -->
|
||||
<script type="module">
|
||||
// Import the minigame framework and password minigame
|
||||
import { MinigameFramework } from './js/minigames/framework/minigame-manager.js';
|
||||
import { PasswordMinigame } from './js/minigames/password/password-minigame.js';
|
||||
|
||||
// Initialize the framework
|
||||
window.MinigameFramework = MinigameFramework;
|
||||
MinigameFramework.registerScene('password', PasswordMinigame);
|
||||
|
||||
// Mock game alert function
|
||||
window.gameAlert = function(message, type, title, duration) {
|
||||
console.log(`[${type.toUpperCase()}] ${title}: ${message}`);
|
||||
updateTestResults(`[${type.toUpperCase()}] ${title}: ${message}`);
|
||||
};
|
||||
|
||||
// Test functions
|
||||
window.testBasicPassword = function() {
|
||||
updateTestResults("Starting basic password test...");
|
||||
MinigameFramework.startMinigame('password', null, {
|
||||
title: 'Basic Password Test',
|
||||
password: 'secret123',
|
||||
showHint: false,
|
||||
showKeyboard: false,
|
||||
maxAttempts: 3,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Basic password test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.testPasswordWithHint = function() {
|
||||
updateTestResults("Starting password with hint test...");
|
||||
MinigameFramework.startMinigame('password', null, {
|
||||
title: 'Password with Hint Test',
|
||||
password: 'admin',
|
||||
passwordHint: 'The default administrator password',
|
||||
showHint: true,
|
||||
showKeyboard: false,
|
||||
maxAttempts: 3,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Password with hint test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.testPasswordWithKeyboard = function() {
|
||||
updateTestResults("Starting password with keyboard test...");
|
||||
MinigameFramework.startMinigame('password', null, {
|
||||
title: 'Password with Keyboard Test',
|
||||
password: 'keyboard',
|
||||
showHint: false,
|
||||
showKeyboard: true,
|
||||
maxAttempts: 3,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Password with keyboard test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.testFullFeaturedPassword = function() {
|
||||
updateTestResults("Starting full featured password test...");
|
||||
MinigameFramework.startMinigame('password', null, {
|
||||
title: 'Full Featured Password Test',
|
||||
password: 'fulltest',
|
||||
passwordHint: 'A complete test of all features',
|
||||
showHint: true,
|
||||
showKeyboard: true,
|
||||
maxAttempts: 5,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Full featured password test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.testWrongPassword = function() {
|
||||
updateTestResults("Starting wrong password test...");
|
||||
MinigameFramework.startMinigame('password', null, {
|
||||
title: 'Wrong Password Test',
|
||||
password: 'correct',
|
||||
showHint: false,
|
||||
showKeyboard: false,
|
||||
maxAttempts: 3,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Wrong password test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.testPasswordWithPostit = function() {
|
||||
updateTestResults("Starting password with post-it test...");
|
||||
MinigameFramework.startMinigame('password', null, {
|
||||
title: 'Password with Post-it Test',
|
||||
password: 'postit',
|
||||
showHint: false,
|
||||
showKeyboard: false,
|
||||
maxAttempts: 3,
|
||||
postitNote: 'Password is written on the sticky note!',
|
||||
showPostit: true,
|
||||
onComplete: (success, result) => {
|
||||
updateTestResults(`Password with post-it test completed. Success: ${success}, Result: ${JSON.stringify(result)}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function updateTestResults(message) {
|
||||
const resultsElement = document.getElementById('test-results');
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
resultsElement.textContent += `[${timestamp}] ${message}\n`;
|
||||
resultsElement.scrollTop = resultsElement.scrollHeight;
|
||||
}
|
||||
|
||||
// Initialize test results
|
||||
updateTestResults("Password minigame test suite loaded and ready.");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
208
verify-css.html
Normal file
208
verify-css.html
Normal file
@@ -0,0 +1,208 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>CSS Verification</title>
|
||||
|
||||
<!-- Include the game's CSS -->
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/minigames.css">
|
||||
<link rel="stylesheet" href="css/notifications.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.verification-container {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.test-element {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border: 2px solid #444;
|
||||
border-radius: 10px;
|
||||
background: #2a2a2a;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
border-radius: 3px;
|
||||
font-size: 8px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.status.success {
|
||||
background: #2ecc71;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status.error {
|
||||
background: #e74c3c;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="verification-container">
|
||||
<h1>CSS Verification Test</h1>
|
||||
<p>This page verifies that the password minigame CSS is properly loaded and applied.</p>
|
||||
|
||||
<div class="test-element">
|
||||
<h2>Password Field with Monitor Bezel Test</h2>
|
||||
<div class="password-minigame-area">
|
||||
<div class="monitor-bezel">
|
||||
<div class="monitor-screen">
|
||||
<div class="password-input-container">
|
||||
<label for="test-password">Password:</label>
|
||||
<div class="password-field-wrapper">
|
||||
<input type="password" id="test-password" class="password-field" placeholder="Enter password...">
|
||||
<button type="button" class="toggle-password-btn">👁️🗨️</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="password-hint-container">
|
||||
<button type="button" class="hint-btn">Show Hint</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="password-status" class="status error">CSS NOT LOADED</div>
|
||||
</div>
|
||||
|
||||
<div class="test-element">
|
||||
<h2>Hint System Test</h2>
|
||||
<div class="password-hint-container">
|
||||
<button type="button" class="hint-btn">Show Hint</button>
|
||||
<div class="password-hint" style="display: none;">
|
||||
<strong>Hint:</strong> This is a test hint
|
||||
</div>
|
||||
</div>
|
||||
<div id="hint-status" class="status error">CSS NOT LOADED</div>
|
||||
</div>
|
||||
|
||||
<div class="test-element">
|
||||
<h2>Onscreen Keyboard Test</h2>
|
||||
<div class="onscreen-keyboard">
|
||||
<div class="keyboard-row">
|
||||
<button class="key" data-key="q">Q</button>
|
||||
<button class="key" data-key="w">W</button>
|
||||
<button class="key" data-key="e">E</button>
|
||||
<button class="key key-backspace" data-key="Backspace">⌫</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="keyboard-status" class="status error">CSS NOT LOADED</div>
|
||||
</div>
|
||||
|
||||
<div class="test-element">
|
||||
<h2>Action Buttons Test</h2>
|
||||
<div class="password-actions">
|
||||
<button type="button" class="submit-btn">Submit</button>
|
||||
<button type="button" class="cancel-btn">Cancel</button>
|
||||
</div>
|
||||
<div id="buttons-status" class="status error">CSS NOT LOADED</div>
|
||||
</div>
|
||||
|
||||
<div class="test-element">
|
||||
<h2>Attempts Counter Test</h2>
|
||||
<div class="attempts-counter">
|
||||
Attempts: <span>0</span>/3
|
||||
</div>
|
||||
<div id="counter-status" class="status error">CSS NOT LOADED</div>
|
||||
</div>
|
||||
|
||||
<div class="test-element">
|
||||
<h2>Overall Status</h2>
|
||||
<div id="overall-status" class="status error">VERIFICATION IN PROGRESS</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Check if CSS classes are properly styled
|
||||
function verifyCSS() {
|
||||
let allPassed = true;
|
||||
|
||||
// Check monitor bezel background
|
||||
const monitorBezel = document.querySelector('.monitor-bezel');
|
||||
if (monitorBezel) {
|
||||
const styles = window.getComputedStyle(monitorBezel);
|
||||
if (styles.backgroundImage && styles.backgroundImage !== 'none') {
|
||||
document.getElementById('password-status').textContent = 'CSS LOADED';
|
||||
document.getElementById('password-status').className = 'status success';
|
||||
} else {
|
||||
allPassed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check hint button
|
||||
const hintBtn = document.querySelector('.hint-btn');
|
||||
if (hintBtn) {
|
||||
const styles = window.getComputedStyle(hintBtn);
|
||||
if (styles.backgroundColor === 'rgb(243, 156, 18)' || styles.backgroundColor === '#f39c12') {
|
||||
document.getElementById('hint-status').textContent = 'CSS LOADED';
|
||||
document.getElementById('hint-status').className = 'status success';
|
||||
} else {
|
||||
allPassed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check keyboard keys
|
||||
const key = document.querySelector('.key');
|
||||
if (key) {
|
||||
const styles = window.getComputedStyle(key);
|
||||
if (styles.backgroundColor === 'rgb(68, 68, 68)' || styles.backgroundColor === '#444') {
|
||||
document.getElementById('keyboard-status').textContent = 'CSS LOADED';
|
||||
document.getElementById('keyboard-status').className = 'status success';
|
||||
} else {
|
||||
allPassed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check submit button
|
||||
const submitBtn = document.querySelector('.submit-btn');
|
||||
if (submitBtn) {
|
||||
const styles = window.getComputedStyle(submitBtn);
|
||||
if (styles.backgroundColor === 'rgb(46, 204, 113)' || styles.backgroundColor === '#2ecc71') {
|
||||
document.getElementById('buttons-status').textContent = 'CSS LOADED';
|
||||
document.getElementById('buttons-status').className = 'status success';
|
||||
} else {
|
||||
allPassed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check attempts counter
|
||||
const counter = document.querySelector('.attempts-counter');
|
||||
if (counter) {
|
||||
const styles = window.getComputedStyle(counter);
|
||||
if (styles.color === 'rgb(243, 156, 18)' || styles.color === '#f39c12') {
|
||||
document.getElementById('counter-status').textContent = 'CSS LOADED';
|
||||
document.getElementById('counter-status').className = 'status success';
|
||||
} else {
|
||||
allPassed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Overall status
|
||||
if (allPassed) {
|
||||
document.getElementById('overall-status').textContent = 'ALL CSS LOADED SUCCESSFULLY';
|
||||
document.getElementById('overall-status').className = 'status success';
|
||||
} else {
|
||||
document.getElementById('overall-status').textContent = 'SOME CSS NOT LOADED';
|
||||
document.getElementById('overall-status').className = 'status error';
|
||||
}
|
||||
}
|
||||
|
||||
// Run verification after page loads
|
||||
window.addEventListener('load', () => {
|
||||
setTimeout(verifyCSS, 100); // Small delay to ensure CSS is loaded
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user