mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
657 lines
25 KiB
JavaScript
657 lines
25 KiB
JavaScript
// Inventory System
|
|
// Handles inventory management and display
|
|
|
|
import { rooms } from '../core/rooms.js';
|
|
import InkEngine from './ink/ink-engine.js?v=1';
|
|
|
|
// Helper function to create a unique identifier for an item
|
|
export function createItemIdentifier(scenarioData) {
|
|
if (!scenarioData) return 'unknown';
|
|
return `${scenarioData.type}_${scenarioData.name || 'unnamed'}`;
|
|
}
|
|
|
|
// Initialize the inventory system
|
|
export function initializeInventory() {
|
|
console.log('Inventory system initialized');
|
|
|
|
// Initialize inventory state
|
|
window.inventory = {
|
|
items: [],
|
|
container: null
|
|
};
|
|
|
|
// Get the HTML inventory container
|
|
const inventoryContainer = document.getElementById('inventory-container');
|
|
if (!inventoryContainer) {
|
|
console.error('Inventory container not found');
|
|
return;
|
|
}
|
|
|
|
inventoryContainer.innerHTML = '';
|
|
|
|
// Store reference to container
|
|
window.inventory.container = inventoryContainer;
|
|
|
|
// Add notepad to inventory
|
|
addNotepadToInventory();
|
|
|
|
console.log('INVENTORY INITIALIZED', window.inventory);
|
|
}
|
|
|
|
// Helper function to preload intro messages for a phone
|
|
async function preloadPhoneIntroMessages(phoneId, allowedNpcIds = null) {
|
|
console.log(`📱 preloadPhoneIntroMessages called for ${phoneId}`, { allowedNpcIds });
|
|
|
|
if (!window.npcManager) {
|
|
console.warn('❌ npcManager not available');
|
|
return;
|
|
}
|
|
|
|
// Import PhoneChatConversation class (default export)
|
|
const PhoneChatConversation = (await import('../minigames/phone-chat/phone-chat-conversation.js')).default;
|
|
|
|
// Create a temporary ink engine for preloading
|
|
const tempEngine = new InkEngine();
|
|
|
|
let npcs = window.npcManager.getNPCsByPhone(phoneId);
|
|
|
|
// Filter to only allowed NPCs if specified
|
|
if (allowedNpcIds && allowedNpcIds.length > 0) {
|
|
console.log(`🔍 Filtering NPCs: allowed = ${allowedNpcIds.join(', ')}`);
|
|
npcs = npcs.filter(npc => allowedNpcIds.includes(npc.id));
|
|
}
|
|
|
|
console.log(`📱 Found ${npcs.length} NPCs on phone ${phoneId}:`, npcs.map(n => n.id));
|
|
|
|
for (const npc of npcs) {
|
|
const history = window.npcManager.getConversationHistory(npc.id);
|
|
console.log(`📱 NPC ${npc.id}: history length = ${history.length}, has story = ${!!(npc.storyPath || npc.storyJSON)}`);
|
|
|
|
// Only preload if no history exists and NPC has a story
|
|
if (history.length === 0 && (npc.storyPath || npc.storyJSON)) {
|
|
try {
|
|
console.log(`📱 Preloading intro for ${npc.id}...`);
|
|
const tempConversation = new PhoneChatConversation(npc.id, window.npcManager, tempEngine);
|
|
const storySource = npc.storyJSON || npc.storyPath;
|
|
const loaded = await tempConversation.loadStory(storySource);
|
|
|
|
if (loaded) {
|
|
const startKnot = npc.currentKnot || 'start';
|
|
tempConversation.goToKnot(startKnot);
|
|
const result = tempConversation.continue();
|
|
|
|
if (result.text && result.text.trim()) {
|
|
const messages = result.text.trim().split('\n').filter(line => line.trim());
|
|
console.log(`📱 Adding ${messages.length} preloaded messages for ${npc.id}`);
|
|
messages.forEach(message => {
|
|
if (message.trim()) {
|
|
window.npcManager.addMessage(npc.id, 'npc', message.trim(), {
|
|
preloaded: true,
|
|
timestamp: Date.now() - 3600000 // 1 hour ago
|
|
});
|
|
}
|
|
});
|
|
|
|
npc.storyState = tempConversation.saveState();
|
|
console.log(`✅ Preloaded intro for ${npc.id}`);
|
|
} else {
|
|
console.log(`⚠️ No intro text for ${npc.id}`);
|
|
}
|
|
} else {
|
|
console.log(`⚠️ Failed to load story for ${npc.id}`);
|
|
}
|
|
} catch (error) {
|
|
console.error(`❌ Error preloading intro for ${npc.id}:`, error);
|
|
}
|
|
} else {
|
|
console.log(`⏭️ Skipping ${npc.id} - history=${history.length}, story=${!!(npc.storyPath || npc.storyJSON)}`);
|
|
}
|
|
}
|
|
console.log(`📱 Finished preloading for phone ${phoneId}`);
|
|
}
|
|
|
|
// Process initial inventory items
|
|
export function processInitialInventoryItems() {
|
|
console.log('Processing initial inventory items');
|
|
|
|
if (!window.gameScenario) {
|
|
console.error('Game scenario not loaded');
|
|
return;
|
|
}
|
|
|
|
// Check for startItemsInInventory array in scenario
|
|
if (window.gameScenario.startItemsInInventory && Array.isArray(window.gameScenario.startItemsInInventory)) {
|
|
console.log(`Processing ${window.gameScenario.startItemsInInventory.length} starting inventory items`);
|
|
|
|
window.gameScenario.startItemsInInventory.forEach(itemData => {
|
|
console.log(`Adding ${itemData.name} to inventory from startItemsInInventory`);
|
|
|
|
// Create inventory sprite for this object
|
|
const inventoryItem = createInventorySprite(itemData);
|
|
if (inventoryItem) {
|
|
addToInventory(inventoryItem);
|
|
}
|
|
});
|
|
} else {
|
|
console.log('No startItemsInInventory defined in scenario');
|
|
}
|
|
}
|
|
|
|
function createInventorySprite(itemData) {
|
|
try {
|
|
// Create a pseudo-sprite object that can be used in inventory
|
|
const sprite = {
|
|
name: itemData.type,
|
|
objectId: `inventory_${itemData.type}_${Date.now()}`,
|
|
scenarioData: itemData,
|
|
texture: {
|
|
key: itemData.type // Use the type as the texture key for image lookup
|
|
},
|
|
// Copy critical properties for easy access
|
|
keyPins: itemData.keyPins, // Preserve keyPins for keys
|
|
key_id: itemData.key_id, // Preserve key_id for keys
|
|
locked: itemData.locked,
|
|
lockType: itemData.lockType,
|
|
requires: itemData.requires,
|
|
difficulty: itemData.difficulty,
|
|
setVisible: function(visible) {
|
|
// For inventory items, visibility is handled by DOM
|
|
return this;
|
|
}
|
|
};
|
|
|
|
console.log('Created inventory sprite:', {
|
|
name: sprite.name,
|
|
key_id: sprite.key_id,
|
|
keyPins: sprite.keyPins,
|
|
locked: sprite.locked,
|
|
lockType: sprite.lockType
|
|
});
|
|
|
|
// Log if this is a key with keyPins
|
|
if (sprite.keyPins) {
|
|
console.log(`✓ Inventory key "${sprite.name}" has keyPins: [${sprite.keyPins.join(', ')}]`);
|
|
}
|
|
|
|
return sprite;
|
|
} catch (error) {
|
|
console.error('Error creating inventory sprite:', error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function addToInventory(sprite) {
|
|
if (!sprite || !sprite.scenarioData) {
|
|
console.warn('Invalid sprite for inventory');
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
console.log("Adding to inventory:", {
|
|
objectId: sprite.objectId,
|
|
name: sprite.name,
|
|
type: sprite.scenarioData?.type,
|
|
currentRoom: window.currentPlayerRoom
|
|
});
|
|
|
|
// Check if the item is already in the inventory
|
|
const itemIdentifier = createItemIdentifier(sprite.scenarioData);
|
|
const isAlreadyInInventory = window.inventory.items.some(item =>
|
|
item && createItemIdentifier(item.scenarioData) === itemIdentifier
|
|
);
|
|
|
|
if (isAlreadyInInventory) {
|
|
console.log(`Item ${itemIdentifier} is already in inventory`);
|
|
return false;
|
|
}
|
|
|
|
// Remove from room if it exists
|
|
if (window.currentPlayerRoom && rooms[window.currentPlayerRoom] && rooms[window.currentPlayerRoom].objects) {
|
|
if (rooms[window.currentPlayerRoom].objects[sprite.objectId]) {
|
|
const roomObj = rooms[window.currentPlayerRoom].objects[sprite.objectId];
|
|
if (roomObj.setVisible) {
|
|
roomObj.setVisible(false);
|
|
}
|
|
roomObj.active = false;
|
|
console.log(`Removed object ${sprite.objectId} from room`);
|
|
}
|
|
}
|
|
|
|
// Only call setVisible if it's a Phaser sprite with that method
|
|
if (sprite.setVisible && typeof sprite.setVisible === 'function') {
|
|
sprite.setVisible(false);
|
|
}
|
|
|
|
// Special handling for keys - group them together
|
|
if (sprite.scenarioData.type === 'key') {
|
|
return addKeyToInventory(sprite);
|
|
}
|
|
|
|
// Create a new slot for this item
|
|
const inventoryContainer = document.getElementById('inventory-container');
|
|
if (!inventoryContainer) {
|
|
console.error('Inventory container not found');
|
|
return false;
|
|
}
|
|
|
|
// Create a new slot
|
|
const slot = document.createElement('div');
|
|
slot.className = 'inventory-slot';
|
|
inventoryContainer.appendChild(slot);
|
|
|
|
// Create inventory item
|
|
const itemImg = document.createElement('img');
|
|
itemImg.className = 'inventory-item';
|
|
itemImg.src = `assets/objects/${sprite.texture?.key || sprite.name || sprite.scenarioData?.type}.png`;
|
|
itemImg.alt = sprite.scenarioData.name;
|
|
|
|
// Create tooltip
|
|
const tooltip = document.createElement('div');
|
|
tooltip.className = 'inventory-tooltip';
|
|
tooltip.textContent = sprite.scenarioData.name;
|
|
|
|
// Add item data
|
|
itemImg.scenarioData = sprite.scenarioData;
|
|
itemImg.name = sprite.name;
|
|
itemImg.objectId = 'inventory_' + sprite.objectId;
|
|
|
|
// Explicitly preserve critical lock-related properties
|
|
itemImg.keyPins = sprite.keyPins || sprite.scenarioData?.keyPins;
|
|
itemImg.key_id = sprite.key_id || sprite.scenarioData?.key_id;
|
|
itemImg.lockType = sprite.scenarioData?.lockType;
|
|
itemImg.locked = sprite.scenarioData?.locked;
|
|
itemImg.requires = sprite.scenarioData?.requires;
|
|
itemImg.difficulty = sprite.scenarioData?.difficulty;
|
|
|
|
// Add data-type attribute for CSS styling
|
|
itemImg.setAttribute('data-type', sprite.scenarioData?.type);
|
|
|
|
// For phones, add unread message count and badge
|
|
if (sprite.scenarioData?.type === 'phone' && sprite.scenarioData?.phoneId) {
|
|
const phoneId = sprite.scenarioData.phoneId;
|
|
const npcIds = sprite.scenarioData.npcIds || null; // Get allowed NPCs for this phone
|
|
itemImg.setAttribute('data-phone-id', phoneId);
|
|
|
|
if (window.npcManager) {
|
|
// Preload intro messages for all NPCs on this phone
|
|
preloadPhoneIntroMessages(phoneId, npcIds).then(() => {
|
|
const unreadCount = window.npcManager.getTotalUnreadCount(phoneId, npcIds);
|
|
console.log(`📱 Phone ${phoneId} added to inventory, unread count: ${unreadCount}`, { npcIds });
|
|
itemImg.setAttribute('data-unread-count', unreadCount);
|
|
|
|
// Create badge element if there are unread messages
|
|
if (unreadCount > 0) {
|
|
console.log(`✅ Creating badge for phone ${phoneId}`);
|
|
const badge = document.createElement('span');
|
|
badge.className = 'phone-badge';
|
|
badge.textContent = unreadCount;
|
|
itemImg.parentElement.appendChild(badge);
|
|
} else {
|
|
console.log(`❌ Not creating badge, count is ${unreadCount}`);
|
|
}
|
|
});
|
|
} else {
|
|
console.log('❌ npcManager not available when adding phone');
|
|
}
|
|
}
|
|
|
|
// Mark as non-takeable once in inventory (so it won't try to be picked up again)
|
|
itemImg.scenarioData.takeable = false;
|
|
|
|
// Add click handler
|
|
itemImg.addEventListener('click', function() {
|
|
if (window.handleObjectInteraction) {
|
|
window.handleObjectInteraction(this);
|
|
}
|
|
});
|
|
|
|
// Add to slot
|
|
slot.appendChild(itemImg);
|
|
slot.appendChild(tooltip);
|
|
|
|
// Add to inventory array
|
|
window.inventory.items.push(itemImg);
|
|
|
|
// Emit NPC event for item pickup
|
|
if (window.eventDispatcher) {
|
|
window.eventDispatcher.emit(`item_picked_up:${sprite.scenarioData.type}`, {
|
|
itemType: sprite.scenarioData.type,
|
|
itemName: sprite.scenarioData.name,
|
|
roomId: window.currentPlayerRoom
|
|
});
|
|
}
|
|
|
|
// Apply pulse animation to the slot instead of showing notification
|
|
slot.classList.add('pulse');
|
|
// Remove the pulse class after the animation completes
|
|
setTimeout(() => {
|
|
slot.classList.remove('pulse');
|
|
}, 600);
|
|
|
|
// If this is the Bluetooth scanner, automatically open the minigame after adding to inventory
|
|
if (sprite.scenarioData.type === "bluetooth_scanner" && window.startBluetoothScannerMinigame) {
|
|
// Small delay to ensure the item is fully added to inventory
|
|
setTimeout(() => {
|
|
console.log('Auto-opening bluetooth scanner minigame after adding to inventory');
|
|
window.startBluetoothScannerMinigame(itemImg);
|
|
}, 500);
|
|
}
|
|
|
|
|
|
// Fingerprint kit is now handled as a minigame when clicked from inventory
|
|
|
|
// Handle crypto workstation - use the proper modal implementation from helpers.js
|
|
if (sprite.scenarioData.type === "workstation") {
|
|
// Don't override the openCryptoWorkstation function - it's already properly defined in helpers.js
|
|
console.log('Crypto workstation added to inventory - modal function available');
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Error adding to inventory:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Key management functions
|
|
function addKeyToInventory(sprite) {
|
|
// Initialize key ring if it doesn't exist
|
|
if (!window.inventory.keyRing) {
|
|
window.inventory.keyRing = {
|
|
keys: [],
|
|
slot: null,
|
|
itemImg: null
|
|
};
|
|
}
|
|
|
|
// 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
|
|
console.log(`✓ Key "${sprite.scenarioData?.name}" added to key ring:`, {
|
|
key_id: keyId,
|
|
keyPins: keyPins,
|
|
locked: sprite.scenarioData?.locked,
|
|
lockType: sprite.scenarioData?.lockType
|
|
});
|
|
|
|
// 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) {
|
|
keyRingSlot.classList.add('pulse');
|
|
setTimeout(() => {
|
|
keyRingSlot.classList.remove('pulse');
|
|
}, 600);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function updateKeyRingDisplay() {
|
|
const keyRing = window.inventory.keyRing;
|
|
if (!keyRing || keyRing.keys.length === 0) {
|
|
// Remove key ring display if no keys
|
|
if (keyRing && keyRing.slot) {
|
|
keyRing.slot.remove();
|
|
keyRing.slot = null;
|
|
keyRing.itemImg = null;
|
|
}
|
|
return;
|
|
}
|
|
|
|
const inventoryContainer = document.getElementById('inventory-container');
|
|
if (!inventoryContainer) {
|
|
console.error('Inventory container not found');
|
|
return;
|
|
}
|
|
|
|
// Remove existing key ring slot if it exists
|
|
if (keyRing.slot) {
|
|
keyRing.slot.remove();
|
|
}
|
|
|
|
// Create new slot for key ring
|
|
const slot = document.createElement('div');
|
|
slot.className = 'inventory-slot';
|
|
inventoryContainer.appendChild(slot);
|
|
|
|
// Create key ring item
|
|
const itemImg = document.createElement('img');
|
|
itemImg.className = 'inventory-item';
|
|
itemImg.src = keyRing.keys.length === 1 ? `assets/objects/key.png` : `assets/objects/key-ring.png`;
|
|
itemImg.alt = keyRing.keys.length === 1 ? keyRing.keys[0].scenarioData.name : 'Key Ring';
|
|
|
|
// Add data attributes for styling
|
|
itemImg.setAttribute('data-type', 'key_ring');
|
|
itemImg.setAttribute('data-key-count', keyRing.keys.length);
|
|
|
|
// Create tooltip
|
|
const tooltip = document.createElement('div');
|
|
tooltip.className = 'inventory-tooltip';
|
|
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: allKeysData
|
|
};
|
|
itemImg.name = 'key';
|
|
itemImg.objectId = 'inventory_key_ring';
|
|
|
|
// Add click handler for key ring
|
|
itemImg.addEventListener('click', function() {
|
|
if (window.handleKeyRingInteraction) {
|
|
window.handleKeyRingInteraction(this);
|
|
}
|
|
});
|
|
|
|
// Add to slot
|
|
slot.appendChild(itemImg);
|
|
slot.appendChild(tooltip);
|
|
|
|
// Store references
|
|
keyRing.slot = slot;
|
|
keyRing.itemImg = itemImg;
|
|
|
|
// Add to inventory array (replace any existing key ring item)
|
|
const existingKeyRingIndex = window.inventory.items.findIndex(item =>
|
|
item && item.scenarioData && item.scenarioData.type === 'key_ring'
|
|
);
|
|
|
|
if (existingKeyRingIndex !== -1) {
|
|
window.inventory.items[existingKeyRingIndex] = itemImg;
|
|
} else {
|
|
window.inventory.items.push(itemImg);
|
|
}
|
|
}
|
|
|
|
function handleKeyRingInteraction(keyRingItem) {
|
|
const keyRing = window.inventory.keyRing;
|
|
if (!keyRing || keyRing.keys.length === 0) {
|
|
return;
|
|
}
|
|
|
|
if (keyRing.keys.length === 1) {
|
|
// Single key - handle normally
|
|
if (window.handleObjectInteraction) {
|
|
window.handleObjectInteraction(keyRingItem);
|
|
}
|
|
} else {
|
|
// Multiple keys - show list
|
|
const keyNames = keyRing.keys.map(key => key.scenarioData.name).join('\n• ');
|
|
const message = `Key Ring contains ${keyRing.keys.length} keys:\n• ${keyNames}`;
|
|
|
|
if (window.gameAlert) {
|
|
window.gameAlert(message, 'info', 'Key Ring', 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add notepad to inventory
|
|
function addNotepadToInventory() {
|
|
// Check if notepad is already in inventory
|
|
const notepadExists = window.inventory.items.some(item =>
|
|
item && item.scenarioData && item.scenarioData.type === 'notepad'
|
|
);
|
|
|
|
if (notepadExists) {
|
|
console.log('Notepad already in inventory');
|
|
return;
|
|
}
|
|
|
|
// Create notepad item data
|
|
const notepadData = {
|
|
type: 'notepad',
|
|
name: 'Notepad',
|
|
takeable: true,
|
|
readable: true,
|
|
text: 'Use this notepad to review your collected notes and observations.',
|
|
observations: 'A handy notepad for keeping track of important information.'
|
|
};
|
|
|
|
// Create a mock sprite object for the notepad
|
|
const notepadSprite = {
|
|
name: 'notes5',
|
|
objectId: 'notepad_inventory',
|
|
scenarioData: notepadData,
|
|
setVisible: function(visible) {
|
|
// For inventory items, visibility is handled by DOM
|
|
return this;
|
|
}
|
|
};
|
|
|
|
// Add to inventory
|
|
addToInventory(notepadSprite);
|
|
|
|
// Also add the notepad as a note at the beginning of the notes collection
|
|
if (window.addNote) {
|
|
const notepadText = 'Use this notepad to review your collected notes and observations.\n\nObservation: A handy notepad for keeping track of important information.';
|
|
const notepadNote = window.addNote('Notepad', notepadText, false);
|
|
if (notepadNote) {
|
|
// Move the notepad note to the beginning of the notes array
|
|
const notes = window.gameState.notes;
|
|
const notepadIndex = notes.findIndex(note => note.id === notepadNote.id);
|
|
if (notepadIndex !== -1) {
|
|
const notepadNoteItem = notes.splice(notepadIndex, 1)[0];
|
|
notes.unshift(notepadNoteItem); // Add to beginning
|
|
console.log('Notepad note with observations added to beginning of notes collection during inventory setup');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove item from inventory
|
|
export function removeFromInventory(item) {
|
|
try {
|
|
// Find the item in the inventory array
|
|
const itemIndex = window.inventory.items.indexOf(item);
|
|
if (itemIndex === -1) return false;
|
|
|
|
// Remove from array
|
|
window.inventory.items.splice(itemIndex, 1);
|
|
|
|
// Remove the entire slot from DOM
|
|
const slot = item.parentElement;
|
|
if (slot && slot.classList.contains('inventory-slot')) {
|
|
slot.remove();
|
|
}
|
|
|
|
// Hide bluetooth toggle if we dropped the bluetooth scanner
|
|
if (item.scenarioData.type === "bluetooth_scanner") {
|
|
const bluetoothToggle = document.getElementById('bluetooth-toggle');
|
|
if (bluetoothToggle) {
|
|
bluetoothToggle.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// Hide biometrics toggle if we dropped the fingerprint kit
|
|
if (item.scenarioData.type === "fingerprint_kit") {
|
|
const biometricsToggle = document.getElementById('biometrics-toggle');
|
|
if (biometricsToggle) {
|
|
biometricsToggle.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Error removing from inventory:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Update phone badge with unread count
|
|
export function updatePhoneBadge(phoneId) {
|
|
if (!window.npcManager) return;
|
|
|
|
// Find phone items in inventory
|
|
const phoneItems = window.inventory.items.filter(item =>
|
|
item.scenarioData?.type === 'phone' &&
|
|
item.getAttribute('data-phone-id') === phoneId
|
|
);
|
|
|
|
// Update badge for each phone with this ID
|
|
phoneItems.forEach(phoneItem => {
|
|
const npcIds = phoneItem.scenarioData?.npcIds || null; // Get allowed NPCs for this phone
|
|
const unreadCount = window.npcManager.getTotalUnreadCount(phoneId, npcIds);
|
|
phoneItem.setAttribute('data-unread-count', unreadCount);
|
|
|
|
// Get the inventory slot (parent element)
|
|
const inventorySlot = phoneItem.parentElement;
|
|
if (!inventorySlot) return;
|
|
|
|
// Remove existing badge if present
|
|
const existingBadge = inventorySlot.querySelector('.phone-badge');
|
|
if (existingBadge) {
|
|
existingBadge.remove();
|
|
}
|
|
|
|
// Create new badge if there are unread messages
|
|
if (unreadCount > 0) {
|
|
const badge = document.createElement('span');
|
|
badge.className = 'phone-badge';
|
|
badge.textContent = unreadCount;
|
|
inventorySlot.appendChild(badge);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Export for global access
|
|
window.initializeInventory = initializeInventory;
|
|
window.processInitialInventoryItems = processInitialInventoryItems;
|
|
window.addToInventory = addToInventory;
|
|
window.removeFromInventory = removeFromInventory;
|
|
window.addNotepadToInventory = addNotepadToInventory;
|
|
window.createItemIdentifier = createItemIdentifier;
|
|
window.handleKeyRingInteraction = handleKeyRingInteraction;
|
|
window.updatePhoneBadge = updatePhoneBadge;
|