diff --git a/index.html b/index.html index acc1117..93820bb 100644 --- a/index.html +++ b/index.html @@ -31,10 +31,9 @@ #notification-container { position: fixed; top: 20px; - left: 50%; - transform: translateX(-50%); - width: 80%; - max-width: 600px; + right: 20px; + width: 300px; + max-width: 80%; z-index: 2000; font-family: Arial, sans-serif; pointer-events: none; @@ -114,22 +113,23 @@ position: fixed; bottom: 80px; right: 20px; - width: 300px; - max-height: 400px; - background-color: rgba(0, 0, 0, 0.8); + width: 350px; + max-height: 500px; + background-color: rgba(0, 0, 0, 0.9); color: white; border-radius: 5px; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); + box-shadow: 0 2px 15px rgba(0, 0, 0, 0.5); z-index: 1999; font-family: Arial, sans-serif; display: none; overflow: hidden; transition: all 0.3s ease; + border: 1px solid #444; } #notes-header { background-color: #222; - padding: 10px 15px; + padding: 12px 15px; display: flex; justify-content: space-between; align-items: center; @@ -138,18 +138,66 @@ #notes-title { font-weight: bold; - font-size: 16px; + font-size: 18px; + color: #3498db; } #notes-close { cursor: pointer; - font-size: 16px; + font-size: 18px; color: #aaa; + transition: color 0.2s; } #notes-close:hover { color: white; } + + #notes-search-container { + padding: 10px 15px; + background-color: #333; + border-bottom: 1px solid #444; + } + + #notes-search { + width: 100%; + padding: 8px 10px; + border: none; + border-radius: 3px; + background-color: #222; + color: white; + font-size: 14px; + } + + #notes-search:focus { + outline: none; + box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.5); + } + + #notes-categories { + display: flex; + padding: 5px 15px; + background-color: #2c2c2c; + border-bottom: 1px solid #444; + } + + .notes-category { + padding: 5px 10px; + margin-right: 5px; + cursor: pointer; + border-radius: 3px; + font-size: 12px; + transition: all 0.2s; + } + + .notes-category.active { + background-color: #3498db; + color: white; + } + + .notes-category:hover:not(.active) { + background-color: #444; + } #notes-content { padding: 15px; @@ -161,6 +209,14 @@ margin-bottom: 15px; padding-bottom: 15px; border-bottom: 1px solid #444; + cursor: pointer; + transition: background-color 0.2s; + padding: 10px; + border-radius: 3px; + } + + .note-item:hover { + background-color: #333; } .note-item:last-child { @@ -174,20 +230,47 @@ margin-bottom: 5px; font-size: 14px; color: #3498db; + display: flex; + justify-content: space-between; + align-items: center; + } + + .note-icons { + display: flex; + gap: 5px; + } + + .note-icon { + font-size: 12px; + color: #aaa; } .note-text { font-size: 13px; line-height: 1.4; white-space: pre-wrap; + max-height: 80px; + overflow: hidden; + transition: max-height 0.3s; + } + + .note-item.expanded .note-text { + max-height: 1000px; + } + + .note-timestamp { + font-size: 11px; + color: #888; + margin-top: 5px; + text-align: right; } #notes-toggle { position: fixed; bottom: 20px; right: 20px; - width: 50px; - height: 50px; + width: 60px; + height: 60px; background-color: #3498db; color: white; border-radius: 50%; @@ -197,7 +280,7 @@ cursor: pointer; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); z-index: 1998; - font-size: 24px; + font-size: 28px; transition: all 0.3s ease; } @@ -213,9 +296,9 @@ background-color: #e74c3c; color: white; border-radius: 50%; - width: 20px; - height: 20px; - font-size: 12px; + width: 24px; + height: 24px; + font-size: 14px; display: flex; justify-content: center; align-items: center; @@ -322,9 +405,17 @@
-
Notes
+
Notes & Information
×
+
+ +
+
+
All
+
Important
+
Unread
+
@@ -371,6 +462,7 @@ // Debug system variables - moved to the top let debugMode = false; + let debugLevel = 1; // 1 = basic, 2 = detailed, 3 = verbose let visualDebugMode = false; let fpsCounter = null; @@ -447,6 +539,15 @@ // Add a note to the notes panel function addNote(title, text, important = false) { + // Check if a note with the same title and text already exists + const noteExists = gameNotes.some(note => note.title === title && note.text === text); + + // If the note already exists, don't add it again + if (noteExists) { + debugLog(`Note "${title}" already exists, not adding duplicate`, 2); + return null; + } + const note = { id: Date.now(), title: title, @@ -469,9 +570,31 @@ // Update the notes panel with current notes function updateNotesPanel() { const notesContent = document.getElementById('notes-content'); + const searchTerm = document.getElementById('notes-search')?.value?.toLowerCase() || ''; + + // Get active category + const activeCategory = document.querySelector('.notes-category.active')?.dataset.category || 'all'; + + // Filter notes based on search and category + let filteredNotes = [...gameNotes]; + + // Apply category filter + if (activeCategory === 'important') { + filteredNotes = filteredNotes.filter(note => note.important); + } else if (activeCategory === 'unread') { + filteredNotes = filteredNotes.filter(note => !note.read); + } + + // Apply search filter + if (searchTerm) { + filteredNotes = filteredNotes.filter(note => + note.title.toLowerCase().includes(searchTerm) || + note.text.toLowerCase().includes(searchTerm) + ); + } // Sort notes with important ones first, then by timestamp (newest first) - const sortedNotes = [...gameNotes].sort((a, b) => { + filteredNotes.sort((a, b) => { if (a.important !== b.important) { return a.important ? -1 : 1; } @@ -482,29 +605,48 @@ notesContent.innerHTML = ''; // Add notes - if (sortedNotes.length === 0) { - notesContent.innerHTML = '
No notes yet.
'; + if (filteredNotes.length === 0) { + if (searchTerm) { + notesContent.innerHTML = '
No notes match your search.
'; + } else if (activeCategory !== 'all') { + notesContent.innerHTML = `
No ${activeCategory} notes found.
`; + } else { + notesContent.innerHTML = '
No notes yet.
'; + } } else { - sortedNotes.forEach(note => { + filteredNotes.forEach(note => { const noteElement = document.createElement('div'); noteElement.className = 'note-item'; noteElement.dataset.id = note.id; - let noteContent = `
`; + // Format the timestamp + const timestamp = new Date(note.timestamp); + const formattedDate = timestamp.toLocaleDateString(); + const formattedTime = timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + + let noteContent = `
+ ${note.title} +
`; + if (note.important) { - noteContent += `⭐ `; + noteContent += ``; } if (!note.read) { - noteContent += `📌 `; + noteContent += `📌`; } - noteContent += `${note.title}
`; + + noteContent += `
`; noteContent += `
${note.text}
`; + noteContent += `
${formattedDate} ${formattedTime}
`; noteElement.innerHTML = noteContent; - // Mark as read when clicked + // Toggle expanded state when clicked noteElement.addEventListener('click', () => { - if (!note.read) { + noteElement.classList.toggle('expanded'); + + // Mark as read when expanded + if (!note.read && noteElement.classList.contains('expanded')) { note.read = true; updateNotesCount(); updateNotesPanel(); @@ -531,15 +673,6 @@ const isVisible = notesPanel.style.display === 'block'; notesPanel.style.display = isVisible ? 'none' : 'block'; - - // Mark all as read when panel is opened - if (!isVisible) { - gameNotes.forEach(note => { - note.read = true; - }); - updateNotesCount(); - updateNotesPanel(); - } } // Replace alert with our custom notification system @@ -548,42 +681,51 @@ } // Debug logging function that only logs when debug mode is active - function debugLog(...args) { - if (debugMode) { - // Check if the first argument is a string - if (typeof args[0] === 'string') { - // Create the formatted debug message - const message = args[0]; - const formattedMessage = `[DEBUG] === ${message} ===`; - - // Determine color based on message content - let color = '#0077FF'; // Default blue for general info - let fontWeight = 'bold'; - - // Success messages - green - if (message.includes('SUCCESS') || - message.includes('UNLOCKED') || - message.includes('NOT LOCKED')) { - color = '#00AA00'; // Green - } - // Error/failure messages - red - else if (message.includes('FAIL') || - message.includes('ERROR') || - message.includes('NO LOCK REQUIREMENTS FOUND')) { - color = '#DD0000'; // Red - } - // Sensitive information - purple - else if (message.includes('PIN') || - message.includes('PASSWORD') || - message.includes('KEY') || - message.includes('LOCK REQUIREMENTS')) { - color = '#AA00AA'; // Purple - } - - // Replace the first argument with the formatted message and add CSS styling - args.splice(0, 1, '%c' + formattedMessage, `color: ${color}; font-weight: ${fontWeight};`); + function debugLog(message, data = null, level = 1) { + if (!debugMode || debugLevel < level) return; + + // Check if the first argument is a string + if (typeof message === 'string') { + // Create the formatted debug message + const formattedMessage = `[DEBUG] === ${message} ===`; + + // Determine color based on message content + let color = '#0077FF'; // Default blue for general info + let fontWeight = 'bold'; + + // Success messages - green + if (message.includes('SUCCESS') || + message.includes('UNLOCKED') || + message.includes('NOT LOCKED')) { + color = '#00AA00'; // Green } - console.log(...args); + // Error/failure messages - red + else if (message.includes('FAIL') || + message.includes('ERROR') || + message.includes('NO LOCK REQUIREMENTS FOUND')) { + color = '#DD0000'; // Red + } + // Sensitive information - purple + else if (message.includes('PIN') || + message.includes('PASSWORD') || + message.includes('KEY') || + message.includes('LOCK REQUIREMENTS')) { + color = '#AA00AA'; // Purple + } + + // Add level indicator to the message + const levelIndicator = level > 1 ? ` [L${level}]` : ''; + const finalMessage = formattedMessage + levelIndicator; + + // Log with formatting + if (data) { + console.log(`%c${finalMessage}`, `color: ${color}; font-weight: ${fontWeight};`, data); + } else { + console.log(`%c${finalMessage}`, `color: ${color}; font-weight: ${fontWeight};`); + } + } else { + // If not a string, just log as is + console.log(message, data); } } @@ -592,7 +734,7 @@ if (!debugMode) return; // Skip all calculations if debug mode is off // Your existing debug code here - debugLog("Tension debug information:"); + debugLog("Tension debug information:", null, 2); // Add other debug information as needed } @@ -613,6 +755,13 @@ scene.physics.world.drawDebug = debugMode && visualDebugMode; } } + } else if (event.ctrlKey) { + // Cycle through debug levels with Ctrl+backtick + if (debugMode) { + debugLevel = (debugLevel % 3) + 1; // Cycle through 1, 2, 3 + console.log(`%c[DEBUG] === DEBUG LEVEL ${debugLevel} ===`, + `color: #0077FF; font-weight: bold;`); + } } else { // Regular debug mode toggle debugMode = !debugMode; @@ -640,6 +789,23 @@ const notesClose = document.getElementById('notes-close'); notesClose.addEventListener('click', toggleNotesPanel); + // Set up search functionality + const notesSearch = document.getElementById('notes-search'); + notesSearch.addEventListener('input', updateNotesPanel); + + // Set up category filters + const categories = document.querySelectorAll('.notes-category'); + categories.forEach(category => { + category.addEventListener('click', () => { + // Remove active class from all categories + categories.forEach(c => c.classList.remove('active')); + // Add active class to clicked category + category.classList.add('active'); + // Update notes panel + updateNotesPanel(); + }); + }); + // Initialize notes count updateNotesCount(); }); @@ -969,14 +1135,14 @@ }); if (clickedItem) { - console.log('Inventory item clicked:', clickedItem.name); + debugLog('INVENTORY ITEM CLICKED', { name: clickedItem.name }, 2); handleObjectInteraction(clickedItem); return; } } // if not clicking inventory, handle as movement - console.log('Click detected at:', pointer.worldX, pointer.worldY); + debugLog('CLICK DETECTED', { x: pointer.worldX, y: pointer.worldY }, 3); movePlayerToPoint.call(this, pointer.worldX, pointer.worldY); }); @@ -1022,7 +1188,7 @@ initializeSamplesUI(); // Log initial debug status - console.log("%cPress ` (backtick) to toggle debug mode", "color: #888; font-style: italic;"); + console.log("%cPress ` (backtick) to toggle debug mode, Ctrl+` to cycle debug levels (1-3), Shift+` for visual debug", "color: #888; font-style: italic;"); } function update() { @@ -1109,7 +1275,7 @@ width: width * 48, // tile width is 48 height: height * 48 // tile height is 48 }; - console.log(`Room ${roomId} dimensions:`, roomDimensions[roomId]); + debugLog('ROOM DIMENSIONS', { roomId, dimensions: roomDimensions[roomId] }, 3); } else { console.error(`Could not find tilemap data for room ${roomId}`); // Fallback to default dimensions if needed @@ -1189,7 +1355,7 @@ } } else { if (processed.has(connected)) { - console.log(`Room ${connected} already processed, skipping`); + debugLog('ROOM ALREADY PROCESSED', { roomId: connected }, 3); return; } @@ -1385,10 +1551,10 @@ // Add click handler for all objects sprite.on('pointerdown', () => { if (isActiveObject) { - console.log(`Clicked active object ${obj.name}`); + debugLog('OBJECT CLICKED', { name: obj.name }, 2); handleObjectInteraction(sprite); } else { - alert("Nothing of note here"); + gameAlert("Nothing of note here", 'info', '', 2000); } }); }); @@ -1554,7 +1720,7 @@ } // Otherwise, handle as movement click - console.log('Click detected at:', worldPoint.x, worldPoint.y); + debugLog('CLICK DETECTED', { x: worldPoint.x, y: worldPoint.y }, 3); movePlayerToPoint.call(this, worldPoint.x, worldPoint.y); }); } @@ -1965,10 +2131,14 @@ // handles interactions with objects // displays the object's data in an alert function handleObjectInteraction(sprite) { - console.log('CyberChef: handleObjectInteraction called for:', sprite.name, 'Has open workstation:', !!sprite.openCryptoWorkstation); + // Only log detailed object interactions at debug level 2+ + debugLog('OBJECT INTERACTION', { + name: sprite.name, + hasWorkstation: !!sprite.openCryptoWorkstation + }, 2); if (sprite.openCryptoWorkstation && sprite.openCryptoWorkstation()) { - console.log('CyberChef: Crypto workstation opened'); + debugLog('WORKSTATION OPENED', null, 1); return; } @@ -1987,7 +2157,7 @@ if (distanceSq > INTERACTION_RANGE_SQ) { // Show notification instead of alert - gameAlert("Too far away to interact with this object.", 'warning', '', 2000); + //gameAlert("Too far away to interact with this object.", 'warning', '', 2000); return; } } @@ -2045,7 +2215,7 @@ // Check if item is locked if (data.locked === true) { - console.log('Item is locked:', data); + debugLog('ITEM LOCKED', data, 2); handleUnlock(sprite, 'item'); return; } @@ -2058,32 +2228,71 @@ // Add readable text as a note if (data.text.trim().length > 0) { - addNote(data.name, data.text); + const addedNote = addNote(data.name, data.text, data.important || false); + + // Only show notification if a new note was actually added (not a duplicate) + if (addedNote) { + gameAlert(`Added "${data.name}" to your notes.`, 'info', 'Note Added', 3000); + + // If this is a note in the inventory, remove it after adding to notes list + if (isInventoryItem && data.type === 'notes') { + // Remove from inventory after a short delay to allow the player to see the message + setTimeout(() => { + if (removeFromInventory(sprite)) { + gameAlert(`Removed "${data.name}" from inventory after recording in notes.`, 'success', 'Inventory Updated', 3000); + } + }, 1000); + } + } } } if (data.takeable) { - message += `This item can be taken\n\n`; + // If it's a note type item that's already been read and added to notes, + // don't add it to inventory unless it has a special purpose + const isJustInformationalNote = + data.type === 'notes' && + data.readable && + data.text && + !data.hasSpecialPurpose; // Add this flag to notes that need to be in inventory - if (!inventory || !Array.isArray(inventory.items)) { - console.error('Inventory not properly initialized'); - return; - } - - const isInRoom = currentRoom && - rooms[currentRoom] && - rooms[currentRoom].objects && - rooms[currentRoom].objects[sprite.name]; + if (!isJustInformationalNote) { + message += `This item can be taken\n\n`; + + if (!inventory || !Array.isArray(inventory.items)) { + console.error('Inventory not properly initialized'); + return; + } + + const isInRoom = currentRoom && + rooms[currentRoom] && + rooms[currentRoom].objects && + rooms[currentRoom].objects[sprite.name]; + + const itemIdentifier = createItemIdentifier(sprite.scenarioData); + + const isInInventory = inventory.items.some(item => + item && createItemIdentifier(item.scenarioData) === itemIdentifier + ); + + if (isInRoom && !isInInventory) { + debugLog('INVENTORY ITEM ADDED', { item: itemIdentifier }, 2); + addToInventory(sprite); + } + } else { + // For informational notes, just remove them from the room after reading + if (currentRoom && + rooms[currentRoom] && + rooms[currentRoom].objects && + rooms[currentRoom].objects[sprite.name]) { - const itemIdentifier = createItemIdentifier(sprite.scenarioData); + const roomObj = rooms[currentRoom].objects[sprite.name]; + roomObj.setVisible(false); + roomObj.active = false; - const isInInventory = inventory.items.some(item => - item && createItemIdentifier(item.scenarioData) === itemIdentifier - ); - - if (isInRoom && !isInInventory) { - console.log('Adding item to inventory:', itemIdentifier); - addToInventory(sprite); + // Show notification about adding to notes instead of inventory + gameAlert(`Information recorded in your notes.`, 'success', 'Note Recorded', 3000); + } } } @@ -2154,10 +2363,11 @@ inventory.container.add(inventorySprite); inventory.items.push(inventorySprite); - console.log('Item added to inventory:', { + // Use debugLog with level 3 (verbose) for detailed inventory tracking + debugLog('INVENTORY ITEM DETAILS', { name: sprite.name, totalItems: inventory.items.length - }); + }, 3); } catch (error) { console.error('Error adding item to inventory:', error); } @@ -2193,7 +2403,7 @@ .setScrollFactor(0) .setDepth(2001); - console.log('Inventory initialized:', inventory); // Debug log + debugLog('INVENTORY INITIALIZED', inventory, 2); // Debug log at level 2 } // runs after rooms are fully set up @@ -2341,14 +2551,14 @@ if (distance <= DOOR_INTERACTION_RANGE) { if (doorTile.properties?.locked) { - console.log('Door is locked, attempting unlock'); + debugLog('DOOR LOCKED - ATTEMPTING UNLOCK', null, 2); colorDoorTiles(doorTile, room); handleDoorUnlock(doorTile, room); } else { - console.log('Door is not locked'); + debugLog('DOOR NOT LOCKED', null, 2); } } else { - console.log("Too far from door to interact"); + debugLog('DOOR TOO FAR TO INTERACT', null, 2); } }); @@ -2378,13 +2588,13 @@ } function handleDoorUnlock(doorTile, room) { - debugLog('DOOR UNLOCK ATTEMPT'); + // No need to log here since handleUnlock will log 'UNLOCK ATTEMPT' doorTile.layer = room.doorsLayer; // Ensure layer reference is set handleUnlock(doorTile, 'door'); } function handleUnlock(lockable, type) { - debugLog('UNLOCK ATTEMPT'); + debugLog('UNLOCK ATTEMPT', null, 2); // Check locked state in scenarioData for items const isLocked = type === 'door' ? @@ -2392,7 +2602,7 @@ lockable.scenarioData?.locked; if (!isLocked) { - debugLog('OBJECT NOT LOCKED'); + debugLog('OBJECT NOT LOCKED', null, 2); return; } @@ -2401,17 +2611,17 @@ ? getLockRequirementsForDoor(lockable) : getLockRequirementsForItem(lockable); - debugLog('LOCK REQUIREMENTS', lockRequirements); + // Don't log lock requirements here since it's already logged in the getter functions if (!lockRequirements) { - debugLog('NO LOCK REQUIREMENTS FOUND'); + // Don't log here since it's already logged in the getter functions if applicable return; } switch(lockRequirements.lockType) { case 'key': const requiredKey = lockRequirements.requires; - debugLog('KEY REQUIRED', requiredKey); + debugLog('KEY REQUIRED', requiredKey, 2); const hasKey = inventory.items.some(item => item && item.scenarioData && item.scenarioData.key_id === requiredKey @@ -2425,7 +2635,7 @@ const keyName = keyItem?.scenarioData?.name || 'key'; const keyLocation = keyItem?.scenarioData?.foundIn || 'your inventory'; - debugLog('KEY UNLOCK SUCCESS'); + debugLog('KEY UNLOCK SUCCESS', null, 1); unlockTarget(lockable, type, lockable.layer); gameAlert(`You used the ${keyName} that you found in ${keyLocation} to unlock the ${type}.`, 'success', 'Unlock Successful', 5000); } else { @@ -2436,7 +2646,7 @@ ); if (hasLockpick) { - debugLog('LOCKPICK AVAILABLE'); + debugLog('LOCKPICK AVAILABLE', null, 2); if (confirm("Would you like to attempt picking this lock?")) { let difficulty; @@ -2452,38 +2662,38 @@ // If not found, try object-level difficulty difficulty = difficulty || lockable.scenarioData?.difficulty || lockable.properties?.difficulty; - debugLog('STARTING LOCKPICK MINIGAME', { difficulty }); + debugLog('STARTING LOCKPICK MINIGAME', { difficulty }, 2); startLockpickingMinigame(lockable, game.scene.scenes[0], difficulty); } } else { - debugLog('KEY NOT FOUND - FAIL'); + debugLog('KEY NOT FOUND - FAIL', null, 2); gameAlert(`Requires key: ${requiredKey}`, 'error', 'Locked', 4000); } } break; case 'pin': - debugLog('PIN CODE REQUESTED'); + debugLog('PIN CODE REQUESTED', null, 2); const pinInput = prompt(`Enter PIN code:`); if (pinInput === lockRequirements.requires) { unlockTarget(lockable, type, lockable.layer); // Pass the layer here - debugLog('PIN CODE SUCCESS'); + debugLog('PIN CODE SUCCESS', null, 1); gameAlert(`Correct PIN! The ${type} is now unlocked.`, 'success', 'PIN Accepted', 4000); } else if (pinInput !== null) { - debugLog('PIN CODE FAIL'); + debugLog('PIN CODE FAIL', null, 2); gameAlert("Incorrect PIN code.", 'error', 'PIN Rejected', 3000); } break; case 'password': - debugLog('PASSWORD REQUESTED'); + debugLog('PASSWORD REQUESTED', null, 2); const passwordInput = prompt(`Enter password:`); if (passwordInput === lockRequirements.requires) { unlockTarget(lockable, type, lockable.layer); // Pass the layer here - debugLog('PASSWORD SUCCESS'); + debugLog('PASSWORD SUCCESS', null, 1); gameAlert(`Correct password! The ${type} is now unlocked.`, 'success', 'Password Accepted', 4000); } else if (passwordInput !== null) { - debugLog('PASSWORD FAIL'); + debugLog('PASSWORD FAIL', null, 2); gameAlert("Incorrect password.", 'error', 'Password Rejected', 3000); } break; @@ -2508,7 +2718,7 @@ lockable.x, lockable.y ); - debugLog('BLUETOOTH DISTANCE', distance); + debugLog('BLUETOOTH DISTANCE', distance, 3); // Check if player is within range (using BLUETOOTH_SCAN_RANGE) if (distance <= BLUETOOTH_SCAN_RANGE) { @@ -2517,7 +2727,7 @@ itemMac: lockable.scenarioData?.mac, distance: Math.round(distance), range: BLUETOOTH_SCAN_RANGE - }); + }, 1); unlockTarget(lockable, type, lockable.layer); gameAlert("Bluetooth connection established. Device unlocked.", 'success', 'Connection Successful', 4000); return; @@ -2656,7 +2866,7 @@ } function getLockRequirementsForDoor(doorTile) { - debugLog('CHECKING DOOR REQUIREMENTS'); + debugLog('CHECKING DOOR REQUIREMENTS', null, 3); if (!doorTile.layer) { console.error('Door tile missing layer reference'); @@ -2666,7 +2876,7 @@ const doorWorldX = doorTile.layer.x + (doorTile.x * TILE_SIZE); const doorWorldY = doorTile.layer.y + (doorTile.y * TILE_SIZE); - debugLog('DOOR COORDINATES', { doorWorldX, doorWorldY }); + debugLog('DOOR COORDINATES', { doorWorldX, doorWorldY }, 3); const overlappingRooms = []; Object.entries(rooms).forEach(([roomId, otherRoom]) => { @@ -2685,7 +2895,7 @@ }; if (boundsOverlap(doorCheckArea, roomBounds)) { - debugLog(`ROOM ${roomId} OVERLAPS WITH DOOR`); + debugLog(`ROOM ${roomId} OVERLAPS WITH DOOR`, null, 3); const roomCenterX = roomBounds.x + (roomBounds.width / 2); const roomCenterY = roomBounds.y + (roomBounds.height / 2); const distanceToPlayer = Phaser.Math.Distance.Between( @@ -2704,13 +2914,13 @@ } }); - debugLog('OVERLAPPING ROOMS', overlappingRooms); + debugLog('OVERLAPPING ROOMS', overlappingRooms, 3); const lockedRooms = overlappingRooms .filter(r => r.locked) .sort((a, b) => b.distance - a.distance); - debugLog('LOCKED ROOMS', lockedRooms); + debugLog('LOCKED ROOMS', lockedRooms, 3); if (lockedRooms.length > 0) { const targetRoom = lockedRooms[0]; @@ -2718,11 +2928,11 @@ lockType: targetRoom.lockType, requires: targetRoom.requires }; - debugLog('LOCK REQUIREMENTS', requirements); + debugLog('LOCK REQUIREMENTS', requirements, 2); return requirements; } - debugLog('NO LOCK REQUIREMENTS FOUND'); + debugLog('NO LOCK REQUIREMENTS FOUND', null, 2); return null; } @@ -2773,11 +2983,11 @@ debugLog('BLUETOOTH DEVICE DETECTED', { distance: Math.round(distance), range: BLUETOOTH_SCAN_RANGE - }); + }, 2); // Unlock the tablet obj.scenarioData.locked = false; - debugLog('BLUETOOTH UNLOCK SUCCESS'); + debugLog('BLUETOOTH UNLOCK SUCCESS', null, 1); } } }); @@ -2811,7 +3021,7 @@ } if (!scanner.scenarioData?.biometricType === 'fingerprint') { - debugLog('SCANNER TYPE ERROR - FAIL', scanner.scenarioData); + debugLog('SCANNER TYPE ERROR - FAIL', scanner.scenarioData, 2); gameAlert('Invalid scanner type', 'error', 'Scanner Error', 3000); return false; } @@ -4278,6 +4488,12 @@ else if (lockable && lockable.scenarioData) { console.log('Unlocking container:', lockable.scenarioData); lockable.scenarioData.locked = false; + + // Set the flag to indicate the container is unlocked but contents not collected + if (lockable.scenarioData.contents && lockable.scenarioData.contents.length > 0) { + lockable.scenarioData.isUnlockedButNotCollected = true; + debugLog('Container unlocked and ready for collection', lockable.scenarioData, 1); + } } // Remove the minigame @@ -4355,6 +4571,52 @@ } } + // removes an item from the inventory + function removeFromInventory(sprite) { + if (!sprite || !inventory.items) { + return false; + } + + try { + // Find the index of the sprite in the inventory + const index = inventory.items.indexOf(sprite); + + if (index === -1) { + return false; // Item not found in inventory + } + + // Remove from container + inventory.container.remove(sprite); + + // Remove from items array + inventory.items.splice(index, 1); + + // Destroy the sprite + sprite.destroy(); + + // Rearrange remaining items + rearrangeInventoryItems(); + + // Log the removal + debugLog('INVENTORY ITEM REMOVED', { + name: sprite.name, + totalItems: inventory.items.length + }, 2); + + return true; + } catch (error) { + console.error('Error removing item from inventory:', error); + return false; + } + } + + // Rearrange inventory items after removal + function rearrangeInventoryItems() { + inventory.items.forEach((item, index) => { + item.x = index * 60 + 100; + }); + } + \ No newline at end of file