mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
Enhance key and lock systems with normalization and debugging improvements
This commit is contained in:
@@ -942,6 +942,15 @@ function normalizeScenarioKeyPins(scenario) {
|
||||
return Math.round(25 + (value / 100) * 40);
|
||||
}
|
||||
|
||||
// IMPORTANT: Normalize keyPins in ALL places they appear in the scenario!
|
||||
// KeyPins must be normalized exactly once at scenario load time, BEFORE any items are dropped or used.
|
||||
// If keyPins appear in multiple places (startItemsInInventory, room objects, NPC itemsHeld, etc.),
|
||||
// they ALL need normalization or keys/locks won't match when used.
|
||||
// For example:
|
||||
// - A key in an NPC's itemsHeld must be normalized the same way as a room object key
|
||||
// - The door's room-level keyPins must be normalized the same way
|
||||
// - Otherwise when the NPC drops the key, it won't open the door!
|
||||
|
||||
// Normalize keyPins in startItemsInInventory (for starting keys)
|
||||
if (scenario.startItemsInInventory && Array.isArray(scenario.startItemsInInventory)) {
|
||||
scenario.startItemsInInventory.forEach((item, index) => {
|
||||
@@ -962,6 +971,21 @@ function normalizeScenarioKeyPins(scenario) {
|
||||
console.log(`🔄 Normalized room keyPins for ${roomId}:`, roomData.keyPins);
|
||||
}
|
||||
|
||||
// Normalize NPC itemsHeld keyPins (items NPCs start with/carry)
|
||||
// CRITICAL: This ensures keys dropped by NPCs match the door's keyPins
|
||||
if (roomData.npcs && Array.isArray(roomData.npcs)) {
|
||||
roomData.npcs.forEach((npc, npcIndex) => {
|
||||
if (npc.itemsHeld && Array.isArray(npc.itemsHeld)) {
|
||||
npc.itemsHeld.forEach((item, itemIndex) => {
|
||||
if (item.keyPins && Array.isArray(item.keyPins)) {
|
||||
item.keyPins = item.keyPins.map(convertKeyPin);
|
||||
console.log(`🔄 Normalized NPC itemsHeld keyPins for ${roomId}.npcs[${npcIndex}].itemsHeld[${itemIndex}] (${item.type}):`, item.keyPins);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Convert keyPins for all objects in the room
|
||||
if (roomData.objects && Array.isArray(roomData.objects)) {
|
||||
roomData.objects.forEach((obj, index) => {
|
||||
|
||||
@@ -1979,14 +1979,29 @@ function createNPCSpritesForRoom(roomId, roomData) {
|
||||
console.log(` npcManager: ${!!window.npcManager}`);
|
||||
console.log(` gameRef: ${!!gameRef}`);
|
||||
|
||||
// Get the current scene - use gameRef.scene (the current scene manager) or fall back to window.game
|
||||
const currentScene = gameRef.scene || window.game?.scene?.scenes?.[0];
|
||||
console.log(` currentScene: ${!!currentScene}, key: ${currentScene?.key}`);
|
||||
// Get the current scene instance - need to get it from the scene manager
|
||||
// gameRef.scene is the SceneManager, we need gameRef.scene.getScene() to get the actual scene
|
||||
let currentScene = null;
|
||||
if (gameRef && gameRef.scene && typeof gameRef.scene.getScene === 'function') {
|
||||
// Get the running scene from the scene manager
|
||||
currentScene = gameRef.scene.getScene('default') ||
|
||||
gameRef.scene.scenes?.[0];
|
||||
}
|
||||
if (!currentScene && window.game?.scene) {
|
||||
currentScene = window.game.scene.getScene('default') ||
|
||||
window.game.scene.scenes?.[0];
|
||||
}
|
||||
|
||||
if (currentScene) {
|
||||
console.log(` currentScene: ${!!currentScene}, key: ${currentScene?.key}, isScene: ${currentScene?.add ? 'yes' : 'no'}`);
|
||||
|
||||
if (currentScene && typeof currentScene.add?.graphics === 'function') {
|
||||
window.npcManager.setLOSVisualization(true, currentScene);
|
||||
} else {
|
||||
console.warn(`⚠️ Cannot get current scene for LOS visualization`);
|
||||
console.warn(`⚠️ Cannot get valid Phaser scene for LOS visualization`, {
|
||||
currentScene: !!currentScene,
|
||||
hasAddMethod: !!currentScene?.add,
|
||||
hasGraphicsMethod: typeof currentScene?.add?.graphics
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log(`👁️ No NPCs requesting LOS visualization in room ${roomId}`);
|
||||
|
||||
0
js/core/title-screen.js
Normal file
0
js/core/title-screen.js
Normal file
@@ -227,6 +227,18 @@ export function createDoorSpritesForRoom(roomId, position) {
|
||||
// Check for both keyPins (camelCase) and key_pins (snake_case) in the room data
|
||||
const keyPinsArray = connectedRoomData?.keyPins || connectedRoomData?.key_pins;
|
||||
|
||||
// DEBUG: Log what we're finding
|
||||
if (connectedRoomData?.locked) {
|
||||
console.log(`🔍 Door keyPins lookup for ${connectedRoom}:`, {
|
||||
connectedRoomData_keyPins: connectedRoomData?.keyPins,
|
||||
connectedRoomData_key_pins: connectedRoomData?.key_pins,
|
||||
finalKeyPinsArray: keyPinsArray,
|
||||
locked: connectedRoomData?.locked,
|
||||
lockType: connectedRoomData?.lockType,
|
||||
requires: connectedRoomData?.requires
|
||||
});
|
||||
}
|
||||
|
||||
// Set up door properties
|
||||
doorSprite.doorProperties = {
|
||||
roomId: roomId,
|
||||
|
||||
@@ -364,12 +364,22 @@ function addKeyToInventory(sprite) {
|
||||
};
|
||||
}
|
||||
|
||||
// DEBUG: Check properties before adding
|
||||
const keyId = sprite.scenarioData?.key_id || sprite.key_id;
|
||||
const keyPins = sprite.scenarioData?.keyPins || sprite.keyPins;
|
||||
console.log(`🔑 BEFORE adding key to ring (sprite object):`, {
|
||||
sprite_key_id: sprite.key_id,
|
||||
sprite_keyPins: sprite.keyPins,
|
||||
scenarioData_key_id: sprite.scenarioData?.key_id,
|
||||
scenarioData_keyPins: sprite.scenarioData?.keyPins,
|
||||
resolved_key_id: keyId,
|
||||
resolved_keyPins: keyPins
|
||||
});
|
||||
|
||||
// Add the key to the key ring
|
||||
window.inventory.keyRing.keys.push(sprite);
|
||||
|
||||
// Log key storage with keyPins
|
||||
const keyId = sprite.scenarioData?.key_id || sprite.key_id;
|
||||
const keyPins = sprite.scenarioData?.keyPins || sprite.keyPins;
|
||||
console.log(`✓ Key "${sprite.scenarioData?.name}" added to key ring:`, {
|
||||
key_id: keyId,
|
||||
keyPins: keyPins,
|
||||
@@ -380,6 +390,13 @@ function addKeyToInventory(sprite) {
|
||||
// Update or create the key ring display
|
||||
updateKeyRingDisplay();
|
||||
|
||||
// IMPORTANT: Reinitialize key-lock mappings now that we have a new key
|
||||
// This is critical for newly acquired keys (e.g., dropped by NPCs) to unlock doors
|
||||
if (window.initializeKeyLockMappings) {
|
||||
console.log('🔑 Reinitializing key-lock mappings after adding key to inventory');
|
||||
window.initializeKeyLockMappings();
|
||||
}
|
||||
|
||||
// Apply pulse animation to the key ring slot instead of showing notification
|
||||
const keyRingSlot = window.inventory.keyRing.slot;
|
||||
if (keyRingSlot) {
|
||||
@@ -436,12 +453,18 @@ function updateKeyRingDisplay() {
|
||||
tooltip.textContent = keyRing.keys.length === 1 ? keyRing.keys[0].scenarioData.name : 'Key Ring';
|
||||
|
||||
// Add item data - use the first key's data as the primary data
|
||||
const allKeysData = keyRing.keys.map(k => k.scenarioData);
|
||||
console.log(`🔑 Building key ring scenarioData with ${keyRing.keys.length} keys:`, {
|
||||
firstKeyScenarioData: keyRing.keys[0].scenarioData,
|
||||
allKeysData: allKeysData
|
||||
});
|
||||
|
||||
itemImg.scenarioData = {
|
||||
...keyRing.keys[0].scenarioData,
|
||||
name: keyRing.keys.length === 1 ? keyRing.keys[0].scenarioData.name : 'Key Ring',
|
||||
type: 'key_ring',
|
||||
keyCount: keyRing.keys.length,
|
||||
allKeys: keyRing.keys.map(k => k.scenarioData)
|
||||
allKeys: allKeysData
|
||||
};
|
||||
itemImg.name = 'key';
|
||||
itemImg.objectId = 'inventory_key_ring';
|
||||
|
||||
@@ -114,14 +114,36 @@ function assignKeysToLocks() {
|
||||
const key = playerKeys.find(k => k.scenarioData.key_id === keyId);
|
||||
|
||||
if (key) {
|
||||
// Get the actual scenario keyPins for this lock
|
||||
let scenarioKeyPins = null;
|
||||
if (lock.objectIndex !== undefined) {
|
||||
// Object lock - get keyPins from the object
|
||||
const obj = window.gameState?.scenario?.rooms?.[lock.roomId]?.objects?.[lock.objectIndex];
|
||||
scenarioKeyPins = obj?.keyPins || obj?.key_pins;
|
||||
} else {
|
||||
// Room lock - get keyPins from the room
|
||||
const room = window.gameState?.scenario?.rooms?.[lock.roomId];
|
||||
scenarioKeyPins = room?.keyPins || room?.key_pins;
|
||||
}
|
||||
|
||||
// Use scenario keyPins if available, otherwise generate random ones
|
||||
const pinHeights = scenarioKeyPins || generatePinHeightsForLock(lock.roomId, keyId);
|
||||
|
||||
// Create a lock configuration for this specific lock
|
||||
const lockConfig = {
|
||||
id: `${lock.roomId}_${lock.objectIndex !== undefined ? `obj_${lock.objectIndex}` : 'room'}`,
|
||||
pinCount: 4, // Default pin count
|
||||
pinHeights: generatePinHeightsForLock(lock.roomId, keyId), // Generate consistent pin heights
|
||||
pinCount: pinHeights?.length || 4, // Use actual pin count from keyPins, default 4
|
||||
pinHeights: pinHeights, // Use scenario keyPins or generated ones
|
||||
difficulty: 'medium'
|
||||
};
|
||||
|
||||
console.log(`📌 Lock mapping for key "${key.scenarioData.name}" (${keyId}):`, {
|
||||
lockLocation: `${lock.roomName}${lock.objectName ? ` - ${lock.objectName}` : ''}`,
|
||||
scenarioKeyPins: scenarioKeyPins,
|
||||
pinHeights: pinHeights,
|
||||
pinCount: lockConfig.pinCount
|
||||
});
|
||||
|
||||
// Store the mapping
|
||||
window.keyLockMappings[keyId] = {
|
||||
lockId: lockConfig.id,
|
||||
|
||||
@@ -177,6 +177,17 @@ function dropNPCItems(npcId) {
|
||||
interactable: true
|
||||
};
|
||||
|
||||
// DEBUG: Log key properties if this is a key
|
||||
if (item.type === 'key') {
|
||||
console.log(`🔑 Dropped key "${item.name}":`, {
|
||||
source: 'npc-hostile.js dropNPCItems',
|
||||
item_key_id: item.key_id,
|
||||
item_keyPins: item.keyPins,
|
||||
droppedItemData_key_id: droppedItemData.key_id,
|
||||
droppedItemData_keyPins: droppedItemData.keyPins
|
||||
});
|
||||
}
|
||||
|
||||
// Apply scenario properties to sprite
|
||||
spriteObj.scenarioData = droppedItemData;
|
||||
spriteObj.interactable = true;
|
||||
|
||||
Reference in New Issue
Block a user