mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-21 11:18:08 +00:00
Merge pull request #29 from cliffe/19-copy-paste-from-notes----load-notes-etc-onto-the-page-rather-than-using-js-alert-pop-ups
19 copy paste from notes load notes etc onto the page rather than using js alert pop ups
This commit is contained in:
538
index.html
538
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 Panel -->
|
||||
<div id="notes-panel">
|
||||
<div id="notes-header">
|
||||
<div id="notes-title">Notes</div>
|
||||
<div id="notes-title">Notes & Information</div>
|
||||
<div id="notes-close">×</div>
|
||||
</div>
|
||||
<div id="notes-search-container">
|
||||
<input type="text" id="notes-search" placeholder="Search notes...">
|
||||
</div>
|
||||
<div id="notes-categories">
|
||||
<div class="notes-category active" data-category="all">All</div>
|
||||
<div class="notes-category" data-category="important">Important</div>
|
||||
<div class="notes-category" data-category="unread">Unread</div>
|
||||
</div>
|
||||
<div id="notes-content"></div>
|
||||
</div>
|
||||
<div id="notes-toggle">
|
||||
@@ -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 = '<div class="note-item">No notes yet.</div>';
|
||||
if (filteredNotes.length === 0) {
|
||||
if (searchTerm) {
|
||||
notesContent.innerHTML = '<div class="note-item">No notes match your search.</div>';
|
||||
} else if (activeCategory !== 'all') {
|
||||
notesContent.innerHTML = `<div class="note-item">No ${activeCategory} notes found.</div>`;
|
||||
} else {
|
||||
notesContent.innerHTML = '<div class="note-item">No notes yet.</div>';
|
||||
}
|
||||
} else {
|
||||
sortedNotes.forEach(note => {
|
||||
filteredNotes.forEach(note => {
|
||||
const noteElement = document.createElement('div');
|
||||
noteElement.className = 'note-item';
|
||||
noteElement.dataset.id = note.id;
|
||||
|
||||
let noteContent = `<div class="note-title">`;
|
||||
// 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 = `<div class="note-title">
|
||||
<span>${note.title}</span>
|
||||
<div class="note-icons">`;
|
||||
|
||||
if (note.important) {
|
||||
noteContent += `⭐ `;
|
||||
noteContent += `<span class="note-icon">⭐</span>`;
|
||||
}
|
||||
if (!note.read) {
|
||||
noteContent += `📌 `;
|
||||
noteContent += `<span class="note-icon">📌</span>`;
|
||||
}
|
||||
noteContent += `${note.title}</div>`;
|
||||
|
||||
noteContent += `</div></div>`;
|
||||
noteContent += `<div class="note-text">${note.text}</div>`;
|
||||
noteContent += `<div class="note-timestamp">${formattedDate} ${formattedTime}</div>`;
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user