mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-21 11:18:08 +00:00
Update Room and Scenario Files: Rename an object in the reception room JSON files to "phone" for clarity. Modify the scenario brief in the CEO exfiltration scenario for improved narrative engagement. Enhance CSS styles across various minigames, including adjustments to layout, font sizes, and new sections for item displays in lockpicking and password minigames, improving overall user experience.
This commit is contained in:
@@ -145,7 +145,7 @@
|
||||
"gid":230,
|
||||
"height":17,
|
||||
"id":47,
|
||||
"name":"",
|
||||
"name":"phone",
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
"gid":230,
|
||||
"height":17,
|
||||
"id":47,
|
||||
"name":"",
|
||||
"name":"phone",
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"scenario_brief": "Hi, You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.",
|
||||
"scenario_brief": "old version. You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.",
|
||||
"startRoom": "reception",
|
||||
"rooms": {
|
||||
"reception": {
|
||||
|
||||
@@ -225,7 +225,6 @@
|
||||
|
||||
.desktop-taskbar {
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border-top: 2px solid #333;
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -271,9 +270,6 @@
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.container-image {
|
||||
@@ -374,10 +370,11 @@
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: crisp-edges;
|
||||
transition: transform 0.2s ease;
|
||||
transform: scale(2);
|
||||
}
|
||||
|
||||
.container-content-item:hover {
|
||||
transform: scale(1.1);
|
||||
transform: scale(2.2);
|
||||
}
|
||||
|
||||
.container-content-tooltip {
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
color: white;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
font-size: 18px;
|
||||
white-space: nowrap;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
|
||||
@@ -27,3 +27,73 @@
|
||||
.lockpick-feedback:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Lockpicking item section styling */
|
||||
.lockpicking-item-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.lockpicking-item-image {
|
||||
min-width: 80px;
|
||||
min-height: 80px;
|
||||
object-fit: contain;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: crisp-edges;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.lockpicking-item-info h4 {
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 20px;
|
||||
margin: 0 0 10px 0;
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
.lockpicking-item-info p {
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
color: #ecf0f1;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.lockpicking-item-section {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.lockpicking-item-image {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.lockpicking-item-info h4 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.lockpicking-item-info p {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Phaser game container styling - prevent margin/padding shifts */
|
||||
#phaser-game-container {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#phaser-game-container canvas {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,38 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.password-image-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.password-image {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
object-fit: contain;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: crisp-edges;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.password-info h4 {
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 20px;
|
||||
margin: 0 0 10px 0;
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
.password-info p {
|
||||
font-size: 20px;
|
||||
margin: 0;
|
||||
color: #ecf0f1;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.password-input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -529,4 +561,16 @@
|
||||
padding: 10px 20px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.password-image-section {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.password-image {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,38 @@
|
||||
/* Phone Messages Minigame Styles */
|
||||
|
||||
.phone-image-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.phone-image {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
object-fit: contain;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: crisp-edges;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.phone-info h4 {
|
||||
font-family: 'Press Start 2P', monospace;
|
||||
font-size: 20px;
|
||||
margin: 0 0 10px 0;
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
.phone-info p {
|
||||
font-size: 20px;
|
||||
margin: 0;
|
||||
color: #ecf0f1;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.phone-messages-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -7,7 +41,6 @@
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
background: #a0a0ad;
|
||||
border: 4px solid #333;
|
||||
clip-path: polygon(
|
||||
0px calc(100% - 10px),
|
||||
2px calc(100% - 10px),
|
||||
@@ -469,3 +502,4 @@
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,6 @@ export class ContainerMinigame extends MinigameScene {
|
||||
|
||||
<div class="container-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>
|
||||
`;
|
||||
@@ -100,6 +99,15 @@ export class ContainerMinigame extends MinigameScene {
|
||||
|
||||
createDesktopUI() {
|
||||
this.gameContainer.innerHTML = `
|
||||
<div class="container-image-section">
|
||||
<img src="assets/objects/${this.containerItem.name}.png"
|
||||
alt="${this.containerItem.scenarioData.name}"
|
||||
class="container-image">
|
||||
<div class="container-info">
|
||||
<h4>${this.containerItem.scenarioData.name}</h4>
|
||||
<p>${this.containerItem.scenarioData.observations || ''}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-minigame desktop-mode">
|
||||
<div class="container-monitor-bezel">
|
||||
<div class="desktop-background">
|
||||
@@ -115,13 +123,8 @@ export class ContainerMinigame extends MinigameScene {
|
||||
` : ''}
|
||||
|
||||
<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>
|
||||
|
||||
@@ -251,9 +251,37 @@ export class LockpickingMinigamePhaser extends MinigameScene {
|
||||
<p>Apply tension and hold click on pins to lift them to the shear line</p>
|
||||
`;
|
||||
|
||||
// Create the lockable item display section if item info is provided
|
||||
this.createLockableItemDisplay();
|
||||
|
||||
this.setupPhaserGame();
|
||||
}
|
||||
|
||||
createLockableItemDisplay() {
|
||||
// Create display for the locked item (door, chest, etc.)
|
||||
const itemName = this.params?.itemName || this.lockable || 'Locked Item';
|
||||
const itemImage = this.params?.itemImage || null;
|
||||
const itemObservations = this.params?.itemObservations || '';
|
||||
|
||||
if (!itemImage) return; // Only create if image is provided
|
||||
|
||||
// Create container for the item display
|
||||
const itemDisplayDiv = document.createElement('div');
|
||||
itemDisplayDiv.className = 'lockpicking-item-section';
|
||||
itemDisplayDiv.innerHTML = `
|
||||
<img src="${itemImage}"
|
||||
alt="${itemName}"
|
||||
class="lockpicking-item-image">
|
||||
<div class="lockpicking-item-info">
|
||||
<h4>${itemName}</h4>
|
||||
<p>${itemObservations}</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Insert before the game container
|
||||
this.gameContainer.parentElement.insertBefore(itemDisplayDiv, this.gameContainer);
|
||||
}
|
||||
|
||||
setupPhaserGame() {
|
||||
// Create a container for the Phaser game
|
||||
this.gameContainer.innerHTML = `
|
||||
@@ -3108,6 +3136,7 @@ export class LockpickingMinigamePhaser extends MinigameScene {
|
||||
|
||||
if (!this.lockState.tensionApplied) {
|
||||
this.updateFeedback("Apply tension first before picking pins");
|
||||
this.flashWrenchRed();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3231,6 +3260,7 @@ export class LockpickingMinigamePhaser extends MinigameScene {
|
||||
|
||||
if (!this.lockState.tensionApplied) {
|
||||
this.updateFeedback("Apply tension first before picking pins");
|
||||
this.flashWrenchRed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4418,4 +4448,37 @@ export class LockpickingMinigamePhaser extends MinigameScene {
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
flashWrenchRed() {
|
||||
// Flash the tension wrench red to indicate tension is needed
|
||||
if (!this.wrenchGraphics) return;
|
||||
|
||||
const originalFillStyle = this.lockState.tensionApplied ? 0x00ff00 : 0x888888;
|
||||
|
||||
// Store original state
|
||||
const originalClear = this.wrenchGraphics.clear.bind(this.wrenchGraphics);
|
||||
|
||||
// Flash red 3 times
|
||||
for (let i = 0; i < 3; i++) {
|
||||
this.scene.time.delayedCall(i * 150, () => {
|
||||
this.wrenchGraphics.clear();
|
||||
this.wrenchGraphics.fillStyle(0xff0000); // Red
|
||||
|
||||
// Long vertical arm
|
||||
this.wrenchGraphics.fillRect(0, -120, 10, 170);
|
||||
// Short horizontal arm
|
||||
this.wrenchGraphics.fillRect(0, 40, 37.5, 10);
|
||||
});
|
||||
|
||||
this.scene.time.delayedCall(i * 150 + 75, () => {
|
||||
this.wrenchGraphics.clear();
|
||||
this.wrenchGraphics.fillStyle(originalFillStyle); // Back to original color
|
||||
|
||||
// Long vertical arm
|
||||
this.wrenchGraphics.fillRect(0, -120, 10, 170);
|
||||
// Short horizontal arm
|
||||
this.wrenchGraphics.fillRect(0, 40, 37.5, 10);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,8 +51,43 @@ export class PasswordMinigame extends MinigameScene {
|
||||
|
||||
setupPasswordInterface() {
|
||||
// Create the password entry interface
|
||||
// Check if we can get the device image from sprite or params
|
||||
const getImageData = () => {
|
||||
// Try to get sprite data from params (from lockable object passed through minigame framework)
|
||||
const sprite = this.params.sprite || this.params.lockable;
|
||||
if (sprite && sprite.name && sprite.scenarioData) {
|
||||
return {
|
||||
imageFile: sprite.name,
|
||||
deviceName: sprite.scenarioData.name || sprite.name,
|
||||
observations: sprite.scenarioData.observations || ''
|
||||
};
|
||||
}
|
||||
// Fallback to explicit params if provided
|
||||
if (this.params.deviceImage) {
|
||||
return {
|
||||
imageFile: this.params.deviceImage,
|
||||
deviceName: this.params.deviceName || this.params.title || 'Device',
|
||||
observations: this.params.observations || ''
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const imageData = getImageData();
|
||||
|
||||
this.gameContainer.innerHTML = `
|
||||
<div class="password-minigame-area">
|
||||
${imageData ? `
|
||||
<div class="password-image-section">
|
||||
<img src="assets/objects/${imageData.imageFile}.png"
|
||||
alt="${imageData.deviceName}"
|
||||
class="password-image">
|
||||
<div class="password-info">
|
||||
<h4>${imageData.deviceName}</h4>
|
||||
<p>${imageData.observations}</p>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
<div class="monitor-bezel">
|
||||
<div class="monitor-screen">
|
||||
<div class="password-input-container">
|
||||
|
||||
@@ -328,7 +328,8 @@ export class PhoneMessagesMinigame extends MinigameScene {
|
||||
const notebookBtn = document.createElement('button');
|
||||
notebookBtn.className = 'minigame-button';
|
||||
notebookBtn.id = 'minigame-notebook';
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notebook.png" alt="Notebook" class="icon"> Add to Notebook';
|
||||
notebookBtn.innerHTML = '<img src="assets/icons/notes-sm.png" alt="Notebook" class="icon-small"> Add to Notebook';
|
||||
|
||||
this.controlsElement.appendChild(notebookBtn);
|
||||
|
||||
// Change cancel button text to "Close"
|
||||
@@ -347,7 +348,42 @@ export class PhoneMessagesMinigame extends MinigameScene {
|
||||
|
||||
setupPhoneInterface() {
|
||||
// Create the phone interface
|
||||
// Check if we can get the device image from sprite or params
|
||||
const getImageData = () => {
|
||||
// Try to get sprite data from params (from lockable object passed through minigame framework)
|
||||
const sprite = this.params.sprite || this.params.lockable;
|
||||
if (sprite && sprite.name && sprite.scenarioData) {
|
||||
return {
|
||||
imageFile: sprite.name,
|
||||
deviceName: sprite.scenarioData.name || sprite.name,
|
||||
observations: sprite.scenarioData.observations || ''
|
||||
};
|
||||
}
|
||||
// Fallback to explicit params if provided
|
||||
if (this.params.deviceImage) {
|
||||
return {
|
||||
imageFile: this.params.deviceImage,
|
||||
deviceName: this.params.deviceName || this.params.title || 'Device',
|
||||
observations: this.params.observations || ''
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const imageData = getImageData();
|
||||
|
||||
this.gameContainer.innerHTML = `
|
||||
${imageData ? `
|
||||
<div class="phone-image-section">
|
||||
<img src="assets/objects/${imageData.imageFile}.png"
|
||||
alt="${imageData.deviceName}"
|
||||
class="phone-image">
|
||||
<div class="phone-info">
|
||||
<h4>${imageData.deviceName}</h4>
|
||||
<p>${imageData.observations}</p>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
<div class="phone-messages-container">
|
||||
<div class="phone-screen">
|
||||
<div class="phone-header">
|
||||
@@ -393,10 +429,7 @@ export class PhoneMessagesMinigame extends MinigameScene {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="phone-observations" id="phone-observations">
|
||||
<!-- Observations will be populated here -->
|
||||
</div>
|
||||
|
||||
`;
|
||||
|
||||
// Get references to important elements
|
||||
@@ -406,7 +439,6 @@ export class PhoneMessagesMinigame extends MinigameScene {
|
||||
this.messageTime = document.getElementById('message-time');
|
||||
this.messageContent = document.getElementById('message-content');
|
||||
this.messageActions = document.getElementById('message-actions');
|
||||
this.phoneObservations = document.getElementById('phone-observations');
|
||||
|
||||
// Control buttons
|
||||
this.prevBtn = document.getElementById('prev-btn');
|
||||
@@ -422,9 +454,7 @@ export class PhoneMessagesMinigame extends MinigameScene {
|
||||
|
||||
// Populate messages
|
||||
this.populateMessages();
|
||||
|
||||
// Populate observations
|
||||
this.populateObservations();
|
||||
|
||||
}
|
||||
|
||||
populateMessages() {
|
||||
@@ -444,13 +474,11 @@ export class PhoneMessagesMinigame extends MinigameScene {
|
||||
messageElement.className = `message-item ${message.type || 'text'}`;
|
||||
messageElement.dataset.index = index;
|
||||
|
||||
const icon = message.type === 'voice' ? '🎤' : '💬';
|
||||
const preview = message.type === 'voice'
|
||||
? (message.text ? message.text.substring(0, 50) + '...' : 'Voice message')
|
||||
: (message.text || 'No text content');
|
||||
|
||||
messageElement.innerHTML = `
|
||||
<div class="message-icon">${icon}</div>
|
||||
<div class="message-preview">
|
||||
<div class="message-sender">${message.sender || 'Unknown'}</div>
|
||||
<div class="message-text">${preview}</div>
|
||||
@@ -463,22 +491,7 @@ export class PhoneMessagesMinigame extends MinigameScene {
|
||||
});
|
||||
}
|
||||
|
||||
populateObservations() {
|
||||
// Get observations from the original object data
|
||||
const observations = this.params?.observations || this.phoneData?.observations;
|
||||
|
||||
if (observations) {
|
||||
this.phoneObservations.innerHTML = `
|
||||
<div class="observations-content">
|
||||
<h4>Observations:</h4>
|
||||
<p>${observations}</p>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
this.phoneObservations.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setupEventListeners() {
|
||||
// Message list clicks
|
||||
this.addEventListener(this.messagesList, 'click', (event) => {
|
||||
@@ -788,7 +801,7 @@ export class PhoneMessagesMinigame extends MinigameScene {
|
||||
|
||||
if (message.type === 'voice') {
|
||||
// For voice messages, show audio icon and transcript
|
||||
content += `🎵 [Audio Message]\n`;
|
||||
content += `[Audio Message]\n`;
|
||||
content += `Transcript: ${message.voice || message.text || 'No transcript available'}\n\n`;
|
||||
} else {
|
||||
// For text messages, show the content
|
||||
|
||||
@@ -292,6 +292,7 @@ export function handleObjectInteraction(sprite) {
|
||||
title: data.name || 'Phone Messages',
|
||||
messages: messages,
|
||||
observations: data.observations,
|
||||
lockable: sprite,
|
||||
onComplete: (success, result) => {
|
||||
console.log('Phone messages minigame completed:', success, result);
|
||||
}
|
||||
@@ -318,6 +319,7 @@ export function handleObjectInteraction(sprite) {
|
||||
fileContent: data.text,
|
||||
fileType: data.fileType || 'text',
|
||||
observations: data.observations,
|
||||
lockable: sprite,
|
||||
source: data.source || 'Unknown Source',
|
||||
onComplete: (success, result) => {
|
||||
console.log('Text file minigame completed:', success, result);
|
||||
|
||||
@@ -35,10 +35,49 @@ export function startLockpickingMinigame(lockable, scene, difficulty = 'medium',
|
||||
window.MinigameFramework.init(scene);
|
||||
}
|
||||
|
||||
// Extract item information from lockable object (handles both items and doors)
|
||||
let itemName, itemImage, itemObservations;
|
||||
|
||||
// Check if this is a door (has doorProperties) or an item
|
||||
if (lockable?.doorProperties) {
|
||||
// This is a door - get the connected room name
|
||||
const connectedRoomId = lockable.doorProperties.connectedRoom;
|
||||
const currentRoomId = lockable.doorProperties.roomId;
|
||||
const gameScenario = window.gameScenario;
|
||||
const connectedRoom = gameScenario?.rooms?.[connectedRoomId];
|
||||
const currentRoom = gameScenario?.rooms?.[currentRoomId];
|
||||
const isLocked = lockable.doorProperties.locked;
|
||||
|
||||
// Use door_sign if available (player-visible sign on the door)
|
||||
const doorSignOrName = connectedRoom?.door_sign || connectedRoom?.name;
|
||||
|
||||
// Format item name with locked status
|
||||
if (doorSignOrName) {
|
||||
// Has door_sign or room name - show it
|
||||
itemName = isLocked ? `Locked ${doorSignOrName}` : doorSignOrName;
|
||||
itemObservations = `Door to ${doorSignOrName}`;
|
||||
} else {
|
||||
// No door_sign and undiscovered room - use generic names
|
||||
itemName = 'Locked door';
|
||||
const currentRoomName = currentRoom?.name || currentRoomId;
|
||||
itemObservations = `A door leading out of ${currentRoomName}`;
|
||||
}
|
||||
|
||||
itemImage = 'assets/tiles/door.png'; // Use default door image
|
||||
} else {
|
||||
// This is a regular item - use scenarioData
|
||||
itemName = lockable?.scenarioData?.name || lockable?.name || 'Locked Item';
|
||||
itemImage = lockable?.name ? `assets/objects/${lockable.name}.png` : null;
|
||||
itemObservations = lockable?.scenarioData?.observations || '';
|
||||
}
|
||||
|
||||
// Start the lockpicking minigame (Phaser version)
|
||||
window.MinigameFramework.startMinigame('lockpicking', null, {
|
||||
lockable: lockable,
|
||||
difficulty: difficulty,
|
||||
itemName: itemName,
|
||||
itemImage: itemImage,
|
||||
itemObservations: itemObservations,
|
||||
cancelText: 'Close',
|
||||
onComplete: (success, result) => {
|
||||
if (success) {
|
||||
@@ -158,6 +197,42 @@ export function startKeySelectionMinigame(lockable, type, playerKeys, requiredKe
|
||||
console.log(`Using default lock configuration for ${lockId}:`, lockConfig);
|
||||
}
|
||||
|
||||
// Extract item information from lockable object (handles both items and doors)
|
||||
let itemName, itemImage, itemObservations;
|
||||
|
||||
// Check if this is a door (has doorProperties) or an item
|
||||
if (lockable?.doorProperties) {
|
||||
// This is a door - get the connected room name
|
||||
const connectedRoomId = lockable.doorProperties.connectedRoom;
|
||||
const currentRoomId = lockable.doorProperties.roomId;
|
||||
const gameScenario = window.gameScenario;
|
||||
const connectedRoom = gameScenario?.rooms?.[connectedRoomId];
|
||||
const currentRoom = gameScenario?.rooms?.[currentRoomId];
|
||||
const isLocked = lockable.doorProperties.locked;
|
||||
|
||||
// Use door_sign if available (player-visible sign on the door)
|
||||
const doorSignOrName = connectedRoom?.door_sign || connectedRoom?.name;
|
||||
|
||||
// Format item name with locked status
|
||||
if (doorSignOrName) {
|
||||
// Has door_sign or room name - show it
|
||||
itemName = isLocked ? `${doorSignOrName}` : doorSignOrName;
|
||||
itemObservations = `Door to ${doorSignOrName}`;
|
||||
} else {
|
||||
// No door_sign and undiscovered room - use generic names
|
||||
itemName = 'Locked door';
|
||||
const currentRoomName = currentRoom?.name || currentRoomId;
|
||||
itemObservations = `A door leading out of ${currentRoomName}`;
|
||||
}
|
||||
|
||||
itemImage = 'assets/tiles/door.png'; // Use default door image
|
||||
} else {
|
||||
// This is a regular item - use scenarioData
|
||||
itemName = lockable?.scenarioData?.name || lockable?.name || 'Locked Item';
|
||||
itemImage = lockable?.name ? `assets/objects/${lockable.name}.png` : null;
|
||||
itemObservations = lockable?.scenarioData?.observations || '';
|
||||
}
|
||||
|
||||
// Start the key selection minigame
|
||||
window.MinigameFramework.startMinigame('lockpicking', null, {
|
||||
keyMode: true,
|
||||
@@ -167,6 +242,9 @@ export function startKeySelectionMinigame(lockable, type, playerKeys, requiredKe
|
||||
pinCount: lockConfig.pinCount,
|
||||
predefinedPinHeights: lockConfig.pinHeights, // Pass the predefined pin heights
|
||||
difficulty: lockConfig.difficulty,
|
||||
itemName: itemName,
|
||||
itemImage: itemImage,
|
||||
itemObservations: itemObservations,
|
||||
cancelText: 'Close',
|
||||
onComplete: (success, result) => {
|
||||
if (success) {
|
||||
@@ -299,6 +377,7 @@ export function startPasswordMinigame(lockable, type, correctPassword, callback,
|
||||
maxAttempts: options.maxAttempts || 3,
|
||||
postitNote: options.postitNote || '',
|
||||
showPostit: options.showPostit || false,
|
||||
lockable: lockable,
|
||||
onComplete: (success, result) => {
|
||||
if (success) {
|
||||
console.log('PASSWORD MINIGAME SUCCESS');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"scenario_brief": "You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.",
|
||||
"scenario_brief": "Hi! You are a cyber investigator tasked with uncovering evidence of corporate espionage. Anonymous tips suggest the CEO has been selling company secrets, but you need proof.",
|
||||
"startRoom": "reception",
|
||||
"rooms": {
|
||||
"reception": {
|
||||
@@ -95,6 +95,7 @@
|
||||
"lockType": "key",
|
||||
"requires": "office1_key:40,35,38,32,10",
|
||||
"difficulty": "easy",
|
||||
"door_sign": "4A Hot Desks",
|
||||
|
||||
"connections": {
|
||||
"north": ["office2", "office3"],
|
||||
|
||||
Reference in New Issue
Block a user