mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
Refactor Lockpicking Minigame: Update button functionality for mode switching between key and lockpicking modes. Introduce new icons for keyway, password, and pin in the inventory. Enhance interaction logic for locked objects and doors, including visual indicators. Clean up CSS styles for improved layout and user experience. Remove unused assets and streamline code for better performance.
This commit is contained in:
BIN
assets/icons/keyway.png
Normal file
BIN
assets/icons/keyway.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 418 B |
BIN
assets/icons/password.png
Normal file
BIN
assets/icons/password.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 116 B |
BIN
assets/icons/pin.png
Normal file
BIN
assets/icons/pin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 607 B |
BIN
assets/objects/pc.png
Normal file
BIN
assets/objects/pc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 830 B |
Binary file not shown.
|
Before Width: | Height: | Size: 856 B |
@@ -319,11 +319,9 @@
|
||||
gap: 10px;
|
||||
padding: 15px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||
min-height: 120px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.container-contents-grid::-webkit-scrollbar {
|
||||
|
||||
85
css/main.css
85
css/main.css
@@ -47,7 +47,6 @@ body {
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
z-index: 2000;
|
||||
pointer-events: auto;
|
||||
border: 4px solid #444;
|
||||
clip-path: polygon(
|
||||
0px calc(100% - 10px),
|
||||
2px calc(100% - 10px),
|
||||
@@ -91,48 +90,8 @@ body {
|
||||
|
||||
.laptop-frame {
|
||||
background: transparent;
|
||||
border: 2px solid #444;
|
||||
clip-path: polygon(
|
||||
0px calc(100% - 10px),
|
||||
2px calc(100% - 10px),
|
||||
2px calc(100% - 6px),
|
||||
4px calc(100% - 6px),
|
||||
4px calc(100% - 4px),
|
||||
6px calc(100% - 4px),
|
||||
6px calc(100% - 2px),
|
||||
10px calc(100% - 2px),
|
||||
10px 100%,
|
||||
calc(100% - 10px) 100%,
|
||||
calc(100% - 10px) calc(100% - 2px),
|
||||
calc(100% - 6px) calc(100% - 2px),
|
||||
calc(100% - 6px) calc(100% - 4px),
|
||||
calc(100% - 4px) calc(100% - 4px),
|
||||
calc(100% - 4px) calc(100% - 6px),
|
||||
calc(100% - 2px) calc(100% - 6px),
|
||||
calc(100% - 2px) calc(100% - 10px),
|
||||
100% calc(100% - 10px),
|
||||
100% 10px,
|
||||
calc(100% - 2px) 10px,
|
||||
calc(100% - 2px) 6px,
|
||||
calc(100% - 4px) 6px,
|
||||
calc(100% - 4px) 4px,
|
||||
calc(100% - 6px) 4px,
|
||||
calc(100% - 6px) 2px,
|
||||
calc(100% - 10px) 2px,
|
||||
calc(100% - 10px) 0px,
|
||||
10px 0px,
|
||||
10px 2px,
|
||||
6px 2px,
|
||||
6px 4px,
|
||||
4px 4px,
|
||||
4px 6px,
|
||||
2px 6px,
|
||||
2px 10px,
|
||||
0px 10px
|
||||
);
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
height: calc(100% - 40px);
|
||||
height: calc(100%);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -140,45 +99,8 @@ body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #1a1a1a;
|
||||
border: 2px solid #333;
|
||||
clip-path: polygon(
|
||||
0px calc(100% - 10px),
|
||||
2px calc(100% - 10px),
|
||||
2px calc(100% - 6px),
|
||||
4px calc(100% - 6px),
|
||||
4px calc(100% - 4px),
|
||||
6px calc(100% - 4px),
|
||||
6px calc(100% - 2px),
|
||||
10px calc(100% - 2px),
|
||||
10px 100%,
|
||||
calc(100% - 10px) 100%,
|
||||
calc(100% - 10px) calc(100% - 2px),
|
||||
calc(100% - 6px) calc(100% - 2px),
|
||||
calc(100% - 6px) calc(100% - 4px),
|
||||
calc(100% - 4px) calc(100% - 4px),
|
||||
calc(100% - 4px) calc(100% - 6px),
|
||||
calc(100% - 2px) calc(100% - 6px),
|
||||
calc(100% - 2px) calc(100% - 10px),
|
||||
100% calc(100% - 10px),
|
||||
100% 10px,
|
||||
calc(100% - 2px) 10px,
|
||||
calc(100% - 2px) 6px,
|
||||
calc(100% - 4px) 6px,
|
||||
calc(100% - 4px) 4px,
|
||||
calc(100% - 6px) 4px,
|
||||
calc(100% - 6px) 2px,
|
||||
calc(100% - 10px) 2px,
|
||||
calc(100% - 10px) 0px,
|
||||
10px 0px,
|
||||
10px 2px,
|
||||
6px 2px,
|
||||
6px 4px,
|
||||
4px 4px,
|
||||
4px 6px,
|
||||
2px 6px,
|
||||
2px 10px,
|
||||
0px 10px
|
||||
);
|
||||
/* border: 2px solid #333; */
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
@@ -194,6 +116,7 @@ body {
|
||||
border-bottom: 1px solid #444;
|
||||
font-family: 'VT323', monospace;
|
||||
font-size: 18px;
|
||||
min-height: 25px;
|
||||
}
|
||||
|
||||
.title-bar .close-btn {
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<div class="laptop-screen">
|
||||
<div class="title-bar">
|
||||
<span>Crypto Workstation</span>
|
||||
<button class="close-btn" onclick="closeLaptop()">×</button>
|
||||
<button class="minigame-close-button" onclick="closeLaptop()">×</button>
|
||||
</div>
|
||||
<div id="cyberchef-container">
|
||||
<iframe id="cyberchef-frame" src=""></iframe>
|
||||
|
||||
@@ -63,6 +63,9 @@ export function preload() {
|
||||
this.load.image('fingerprint', 'assets/objects/fingerprint_small.png');
|
||||
this.load.image('lockpick', 'assets/objects/lockpick.png');
|
||||
this.load.image('spoofing_kit', 'assets/objects/office-misc-headphones.png');
|
||||
this.load.image('keyway', 'assets/icons/keyway.png');
|
||||
this.load.image('password', 'assets/icons/password.png');
|
||||
this.load.image('pin', 'assets/icons/pin.png');
|
||||
|
||||
// Load new object sprites from Tiled map tileset
|
||||
// These are the key objects that appear in the new room_reception2.json
|
||||
|
||||
@@ -59,6 +59,13 @@ export class LockpickingMinigamePhaser extends MinigameScene {
|
||||
this.skipStartingKey = params.skipStartingKey || false; // Skip creating initial key if true
|
||||
this.keySelectionMode = false; // Track if we're in key selection mode
|
||||
|
||||
// Mode switching settings
|
||||
this.canSwitchToPickMode = params.canSwitchToPickMode || false; // Allow switching from key to pick mode
|
||||
this.inventoryKeys = params.inventoryKeys || null; // Stored for mode switching
|
||||
this.requirefKeyId = params.requiredKeyId || null; // Track required key ID
|
||||
this.canSwitchToKeyMode = params.canSwitchToKeyMode || false; // Allow switching from lockpick to key mode
|
||||
this.availableKeys = params.availableKeys || null; // Keys available for mode switching
|
||||
|
||||
// Sound effects
|
||||
this.sounds = {};
|
||||
|
||||
@@ -74,7 +81,9 @@ export class LockpickingMinigamePhaser extends MinigameScene {
|
||||
thresholdSensitivity: this.thresholdSensitivity,
|
||||
highlightBindingOrder: this.highlightBindingOrder,
|
||||
highlightPinAlignment: this.highlightPinAlignment,
|
||||
liftSpeed: this.liftSpeed
|
||||
liftSpeed: this.liftSpeed,
|
||||
canSwitchToPickMode: this.canSwitchToPickMode,
|
||||
canSwitchToKeyMode: this.canSwitchToKeyMode
|
||||
});
|
||||
|
||||
this.pins = [];
|
||||
@@ -278,6 +287,44 @@ export class LockpickingMinigamePhaser extends MinigameScene {
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add mode switch button if applicable
|
||||
if (this.canSwitchToPickMode && this.keyMode) {
|
||||
const buttonContainer = document.createElement('div');
|
||||
buttonContainer.style.cssText = `
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const switchModeBtn = document.createElement('button');
|
||||
switchModeBtn.className = 'minigame-button';
|
||||
switchModeBtn.id = 'lockpicking-switch-mode-btn';
|
||||
switchModeBtn.innerHTML = '<img src="assets/objects/lockpick.png" alt="Lockpick" class="icon-large"> Switch to Lockpicking';
|
||||
switchModeBtn.onclick = () => this.switchToPickMode();
|
||||
|
||||
buttonContainer.appendChild(switchModeBtn);
|
||||
itemDisplayDiv.appendChild(buttonContainer);
|
||||
} else if (this.canSwitchToKeyMode && !this.keyMode) {
|
||||
// Show switch to key mode button when in lockpicking mode
|
||||
const buttonContainer = document.createElement('div');
|
||||
buttonContainer.style.cssText = `
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const switchModeBtn = document.createElement('button');
|
||||
switchModeBtn.className = 'minigame-button';
|
||||
switchModeBtn.id = 'lockpicking-switch-to-keys-btn';
|
||||
switchModeBtn.innerHTML = '<img src="assets/objects/key.png" alt="Key" class="icon-large"> Switch to Key Mode';
|
||||
switchModeBtn.onclick = () => this.switchToKeyMode();
|
||||
|
||||
buttonContainer.appendChild(switchModeBtn);
|
||||
itemDisplayDiv.appendChild(buttonContainer);
|
||||
}
|
||||
|
||||
// Insert before the game container
|
||||
this.gameContainer.parentElement.insertBefore(itemDisplayDiv, this.gameContainer);
|
||||
}
|
||||
@@ -4481,4 +4528,143 @@ export class LockpickingMinigamePhaser extends MinigameScene {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
switchToPickMode() {
|
||||
// Switch from key selection mode to lockpicking mode
|
||||
console.log('Switching from key mode to lockpicking mode');
|
||||
|
||||
// Hide the mode switch button
|
||||
const switchBtn = document.getElementById('lockpicking-switch-mode-btn');
|
||||
if (switchBtn) {
|
||||
switchBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
// Exit key mode
|
||||
this.keyMode = false;
|
||||
this.keySelectionMode = false;
|
||||
|
||||
// Clean up key selection UI if visible
|
||||
if (this.keySelectionContainer) {
|
||||
this.keySelectionContainer.destroy();
|
||||
this.keySelectionContainer = null;
|
||||
}
|
||||
|
||||
// Clean up any key visuals
|
||||
if (this.keyGroup) {
|
||||
this.keyGroup.destroy();
|
||||
this.keyGroup = null;
|
||||
}
|
||||
if (this.keyClickZone) {
|
||||
this.keyClickZone.destroy();
|
||||
this.keyClickZone = null;
|
||||
}
|
||||
|
||||
// Show lockpicking tools
|
||||
if (this.tensionWrench) {
|
||||
this.tensionWrench.setVisible(true);
|
||||
}
|
||||
if (this.hookGroup) {
|
||||
this.hookGroup.setVisible(true);
|
||||
}
|
||||
if (this.wrenchText) {
|
||||
this.wrenchText.setVisible(true);
|
||||
}
|
||||
if (this.hookPickLabel) {
|
||||
this.hookPickLabel.setVisible(true);
|
||||
}
|
||||
|
||||
// Reset pins to original positions
|
||||
this.resetPinsToOriginalPositions();
|
||||
|
||||
// Update feedback
|
||||
this.updateFeedback("Lockpicking mode - Apply tension first, then lift pins in binding order");
|
||||
}
|
||||
|
||||
showLockpickingTools() {
|
||||
// Show tension wrench and hook pick in lockpicking mode
|
||||
if (this.tensionWrench) {
|
||||
this.tensionWrench.setVisible(true);
|
||||
}
|
||||
if (this.hookGroup) {
|
||||
this.hookGroup.setVisible(true);
|
||||
}
|
||||
|
||||
// Show labels
|
||||
if (this.wrenchText) {
|
||||
this.wrenchText.setVisible(true);
|
||||
}
|
||||
if (this.hookPickLabel) {
|
||||
this.hookPickLabel.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
switchToKeyMode() {
|
||||
// Switch from lockpicking mode to key selection mode
|
||||
console.log('Switching from lockpicking mode to key mode');
|
||||
|
||||
// Hide the mode switch button
|
||||
const switchBtn = document.getElementById('lockpicking-switch-to-keys-btn');
|
||||
if (switchBtn) {
|
||||
switchBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
// Enter key mode
|
||||
this.keyMode = true;
|
||||
this.keySelectionMode = true;
|
||||
|
||||
// Hide lockpicking tools
|
||||
if (this.tensionWrench) {
|
||||
this.tensionWrench.setVisible(false);
|
||||
}
|
||||
if (this.hookGroup) {
|
||||
this.hookGroup.setVisible(false);
|
||||
}
|
||||
if (this.wrenchText) {
|
||||
this.wrenchText.setVisible(false);
|
||||
}
|
||||
if (this.hookPickLabel) {
|
||||
this.hookPickLabel.setVisible(false);
|
||||
}
|
||||
|
||||
// Reset pins to original positions
|
||||
this.resetPinsToOriginalPositions();
|
||||
|
||||
// Add mode switch back button (can switch back to lockpicking if available)
|
||||
if (this.canSwitchToPickMode) {
|
||||
const itemDisplayDiv = document.querySelector('.lockpicking-item-section');
|
||||
if (itemDisplayDiv) {
|
||||
// Remove any existing button container
|
||||
const existingButtonContainer = itemDisplayDiv.querySelector('div[style*="margin-top"]');
|
||||
if (existingButtonContainer) {
|
||||
existingButtonContainer.remove();
|
||||
}
|
||||
|
||||
// Add new button container
|
||||
const buttonContainer = document.createElement('div');
|
||||
buttonContainer.style.cssText = `
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const switchModeBtn = document.createElement('button');
|
||||
switchModeBtn.className = 'minigame-button';
|
||||
switchModeBtn.id = 'lockpicking-switch-mode-btn';
|
||||
switchModeBtn.innerHTML = '<img src="assets/objects/lockpick.png" alt="Lockpick" class="icon-large"> Switch to Lockpicking';
|
||||
switchModeBtn.onclick = () => this.switchToPickMode();
|
||||
|
||||
buttonContainer.appendChild(switchModeBtn);
|
||||
itemDisplayDiv.appendChild(buttonContainer);
|
||||
}
|
||||
}
|
||||
|
||||
// Show key selection UI with available keys
|
||||
if (this.availableKeys && this.availableKeys.length > 0) {
|
||||
this.createKeySelectionUI(this.availableKeys, this.requiredKeyId);
|
||||
this.updateFeedback("Select a key to use");
|
||||
} else {
|
||||
this.updateFeedback("No keys available");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,11 @@ export function checkObjectInteractions() {
|
||||
if (obj.isHighlighted) {
|
||||
obj.isHighlighted = false;
|
||||
obj.clearTint();
|
||||
// Clean up interaction sprite if exists
|
||||
if (obj.interactionIndicator) {
|
||||
obj.interactionIndicator.destroy();
|
||||
delete obj.interactionIndicator;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -69,6 +74,11 @@ export function checkObjectInteractions() {
|
||||
if (obj.isHighlighted) {
|
||||
obj.isHighlighted = false;
|
||||
obj.clearTint();
|
||||
// Clean up interaction sprite if exists
|
||||
if (obj.interactionIndicator) {
|
||||
obj.interactionIndicator.destroy();
|
||||
delete obj.interactionIndicator;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -82,15 +92,167 @@ export function checkObjectInteractions() {
|
||||
if (!obj.isHighlighted) {
|
||||
obj.isHighlighted = true;
|
||||
obj.setTint(0x4da6ff); // Blue tint for interactable objects
|
||||
// Add interaction indicator sprite
|
||||
addInteractionIndicator(obj);
|
||||
}
|
||||
} else if (obj.isHighlighted) {
|
||||
obj.isHighlighted = false;
|
||||
obj.clearTint();
|
||||
// Clean up interaction sprite if exists
|
||||
if (obj.interactionIndicator) {
|
||||
obj.interactionIndicator.destroy();
|
||||
delete obj.interactionIndicator;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Also check door sprites
|
||||
if (room.doorSprites) {
|
||||
Object.values(room.doorSprites).forEach(door => {
|
||||
// Skip inactive or non-locked doors
|
||||
if (!door.active || !door.doorProperties || !door.doorProperties.locked) {
|
||||
// Clear highlight if door was previously highlighted
|
||||
if (door.isHighlighted) {
|
||||
door.isHighlighted = false;
|
||||
door.clearTint();
|
||||
// Clean up interaction sprite if exists
|
||||
if (door.interactionIndicator) {
|
||||
door.interactionIndicator.destroy();
|
||||
delete door.interactionIndicator;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip doors outside viewport for performance (if viewport bounds available)
|
||||
if (viewBounds && (
|
||||
door.x < viewBounds.left ||
|
||||
door.x > viewBounds.right ||
|
||||
door.y < viewBounds.top ||
|
||||
door.y > viewBounds.bottom)) {
|
||||
// Clear highlight if door is outside viewport
|
||||
if (door.isHighlighted) {
|
||||
door.isHighlighted = false;
|
||||
door.clearTint();
|
||||
// Clean up interaction sprite if exists
|
||||
if (door.interactionIndicator) {
|
||||
door.interactionIndicator.destroy();
|
||||
delete door.interactionIndicator;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Use squared distance for performance
|
||||
const dx = px - door.x;
|
||||
const dy = py - door.y;
|
||||
const distanceSq = dx * dx + dy * dy;
|
||||
|
||||
if (distanceSq <= INTERACTION_RANGE_SQ) {
|
||||
if (!door.isHighlighted) {
|
||||
door.isHighlighted = true;
|
||||
door.setTint(0x4da6ff); // Blue tint for locked doors
|
||||
// Add interaction indicator sprite for doors
|
||||
addInteractionIndicator(door);
|
||||
}
|
||||
} else if (door.isHighlighted) {
|
||||
door.isHighlighted = false;
|
||||
door.clearTint();
|
||||
// Clean up interaction sprite if exists
|
||||
if (door.interactionIndicator) {
|
||||
door.interactionIndicator.destroy();
|
||||
delete door.interactionIndicator;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getInteractionSpriteKey(obj) {
|
||||
// Determine which sprite to show based on the object's interaction type
|
||||
|
||||
// Check for doors first (they may not have scenarioData)
|
||||
if (obj.doorProperties) {
|
||||
if (obj.doorProperties.locked) {
|
||||
// Check door lock type
|
||||
const lockType = obj.doorProperties.lockType;
|
||||
if (lockType === 'password') return 'password';
|
||||
if (lockType === 'pin') return 'pin';
|
||||
return 'keyway'; // Default to keyway for key locks or unknown types
|
||||
}
|
||||
return null; // Unlocked doors don't need overlay
|
||||
}
|
||||
|
||||
if (!obj || !obj.scenarioData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = obj.scenarioData;
|
||||
|
||||
// Check for locked containers and items
|
||||
if (data.locked === true) {
|
||||
// Check specific lock type
|
||||
const lockType = data.lockType;
|
||||
if (lockType === 'password') return 'password';
|
||||
if (lockType === 'pin') return 'pin';
|
||||
if (lockType === 'biometric') return 'fingerprint';
|
||||
// Default to keyway for key locks or unknown types
|
||||
return 'keyway';
|
||||
}
|
||||
|
||||
// Check for containers with contents (even if not locked yet)
|
||||
if (data.contents) {
|
||||
return 'keyway';
|
||||
}
|
||||
|
||||
// Check for fingerprint collection
|
||||
if (data.hasFingerprint === true) {
|
||||
return 'fingerprint';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function addInteractionIndicator(obj) {
|
||||
// Only add indicator if we have a game instance and the object has a scene
|
||||
if (!gameRef || !obj.scene || !obj.scene.add) {
|
||||
return;
|
||||
}
|
||||
|
||||
const spriteKey = getInteractionSpriteKey(obj);
|
||||
if (!spriteKey) return;
|
||||
|
||||
// Create indicator sprite centered over the object
|
||||
try {
|
||||
// Get the center of the parent sprite, accounting for its origin
|
||||
const center = obj.getCenter();
|
||||
|
||||
// Position indicator above the object (accounting for parent's display height)
|
||||
const indicatorX = center.x;
|
||||
const indicatorY = center.y; // Position above with 10px offset
|
||||
|
||||
const indicator = obj.scene.add.image(indicatorX, indicatorY, spriteKey);
|
||||
indicator.setDepth(999); // High depth to appear on top
|
||||
indicator.setOrigin(0.5, 0.5); // Center the sprite
|
||||
// indicator.setScale(0.5); // Scale down to be less intrusive
|
||||
|
||||
// Add pulsing animation
|
||||
obj.scene.tweens.add({
|
||||
targets: indicator,
|
||||
alpha: { from: 1, to: 0.5 },
|
||||
duration: 800,
|
||||
yoyo: true,
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
// Store reference for cleanup
|
||||
obj.interactionIndicator = indicator;
|
||||
} catch (error) {
|
||||
console.warn('Failed to add interaction indicator:', error);
|
||||
}
|
||||
}
|
||||
|
||||
export function handleObjectInteraction(sprite) {
|
||||
console.log('OBJECT INTERACTION', {
|
||||
name: sprite.name,
|
||||
|
||||
@@ -79,6 +79,44 @@ export function startLockpickingMinigame(lockable, scene, difficulty = 'medium',
|
||||
itemImage: itemImage,
|
||||
itemObservations: itemObservations,
|
||||
cancelText: 'Close',
|
||||
canSwitchToKeyMode: window.inventory.items.some(item =>
|
||||
item && item.scenarioData &&
|
||||
item.scenarioData.type === 'key'
|
||||
),
|
||||
availableKeys: (() => {
|
||||
// Collect all available keys for mode switching
|
||||
const keys = [];
|
||||
|
||||
// Individual keys
|
||||
const individualKeys = window.inventory.items.filter(item =>
|
||||
item && item.scenarioData &&
|
||||
item.scenarioData.type === 'key'
|
||||
);
|
||||
individualKeys.forEach(key => {
|
||||
keys.push({
|
||||
id: key.scenarioData.key_id,
|
||||
name: key.scenarioData.name,
|
||||
cuts: key.scenarioData.cuts || []
|
||||
});
|
||||
});
|
||||
|
||||
// Keys from key ring
|
||||
const keyRingItem = window.inventory.items.find(item =>
|
||||
item && item.scenarioData &&
|
||||
item.scenarioData.type === 'key_ring'
|
||||
);
|
||||
if (keyRingItem && keyRingItem.scenarioData.allKeys) {
|
||||
keyRingItem.scenarioData.allKeys.forEach(keyData => {
|
||||
keys.push({
|
||||
id: keyData.key_id,
|
||||
name: keyData.name,
|
||||
cuts: keyData.cuts || []
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return keys.length > 0 ? keys : null;
|
||||
})(),
|
||||
onComplete: (success, result) => {
|
||||
if (success) {
|
||||
console.log('LOCKPICK SUCCESS');
|
||||
@@ -246,6 +284,12 @@ export function startKeySelectionMinigame(lockable, type, playerKeys, requiredKe
|
||||
itemImage: itemImage,
|
||||
itemObservations: itemObservations,
|
||||
cancelText: 'Close',
|
||||
canSwitchToPickMode: window.inventory.items.some(item =>
|
||||
item && item.scenarioData &&
|
||||
item.scenarioData.type === 'lockpick'
|
||||
),
|
||||
inventoryKeys: keysToShow,
|
||||
requiredKeyId: requiredKeyId,
|
||||
onComplete: (success, result) => {
|
||||
if (success) {
|
||||
console.log('KEY SELECTION SUCCESS');
|
||||
|
||||
@@ -82,39 +82,35 @@ export function handleUnlock(lockable, type) {
|
||||
playerKeys = playerKeys.concat(keyRingKeys);
|
||||
}
|
||||
|
||||
// Check for lockpick kit
|
||||
const hasLockpick = window.inventory.items.some(item =>
|
||||
item && item.scenarioData &&
|
||||
item.scenarioData.type === 'lockpick'
|
||||
);
|
||||
|
||||
if (playerKeys.length > 0) {
|
||||
// Show key selection interface
|
||||
// Keys take priority - go straight to key selection
|
||||
console.log('KEYS AVAILABLE - STARTING KEY SELECTION');
|
||||
startKeySelectionMinigame(lockable, type, playerKeys, requiredKey, unlockTarget);
|
||||
} else {
|
||||
// Check for lockpick kit
|
||||
const hasLockpick = window.inventory.items.some(item =>
|
||||
item && item.scenarioData &&
|
||||
item.scenarioData.type === 'lockpick'
|
||||
);
|
||||
} else if (hasLockpick) {
|
||||
// Only lockpick available - launch lockpicking minigame directly
|
||||
console.log('LOCKPICK AVAILABLE - STARTING LOCKPICKING MINIGAME');
|
||||
let difficulty = lockable.scenarioData?.difficulty || lockable.properties?.difficulty || 'medium';
|
||||
|
||||
if (hasLockpick) {
|
||||
console.log('LOCKPICK AVAILABLE');
|
||||
if (confirm("Would you like to attempt picking this lock?")) {
|
||||
let difficulty = lockable.scenarioData?.difficulty || lockable.properties?.difficulty || 'medium';
|
||||
|
||||
console.log('STARTING LOCKPICK MINIGAME', { difficulty });
|
||||
startLockpickingMinigame(lockable, window.game, difficulty, (success) => {
|
||||
if (success) {
|
||||
// Small delay to ensure minigame cleanup completes
|
||||
setTimeout(() => {
|
||||
unlockTarget(lockable, type, lockable.layer);
|
||||
window.gameAlert(`Successfully picked the lock!`, 'success', 'Lock Picked', 4000);
|
||||
}, 100);
|
||||
} else {
|
||||
console.log('LOCKPICK FAILED');
|
||||
window.gameAlert('Failed to pick the lock. Try again.', 'error', 'Pick Failed', 3000);
|
||||
}
|
||||
});
|
||||
startLockpickingMinigame(lockable, window.game, difficulty, (success) => {
|
||||
if (success) {
|
||||
setTimeout(() => {
|
||||
unlockTarget(lockable, type, lockable.layer);
|
||||
window.gameAlert(`Successfully picked the lock!`, 'success', 'Lock Picked', 4000);
|
||||
}, 100);
|
||||
} else {
|
||||
console.log('LOCKPICK FAILED');
|
||||
window.gameAlert('Failed to pick the lock. Try again.', 'error', 'Pick Failed', 3000);
|
||||
}
|
||||
} else {
|
||||
console.log('NO KEYS OR LOCKPICK AVAILABLE');
|
||||
window.gameAlert(`Requires key: ${requiredKey}`, 'error', 'Locked', 4000);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('NO KEYS OR LOCKPICK AVAILABLE');
|
||||
window.gameAlert(`Requires key: ${requiredKey}`, 'error', 'Locked', 4000);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user