Add Key Ring Functionality: Introduce a new key ring system to manage keys in inventory, including visual representation and interaction logic. Update CSS for key ring styling and enhance inventory management to support key grouping and display. Modify key-lock and unlock systems to recognize keys from the key ring, improving gameplay dynamics.

This commit is contained in:
Z. Cliffe Schreuders
2025-10-14 23:56:31 +01:00
parent c2c60cc515
commit 9c718e6239
5 changed files with 213 additions and 5 deletions

BIN
assets/objects/key-ring.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

View File

@@ -70,3 +70,32 @@
.inventory-item:hover + .inventory-tooltip {
opacity: 1;
}
/* Key ring specific styling */
.inventory-item[data-type="key_ring"] {
position: relative;
}
.inventory-item[data-type="key_ring"]::after {
content: attr(data-key-count);
position: absolute;
top: -5px;
right: -5px;
background: #ff6b6b;
color: white;
border-radius: 50%;
width: 18px;
height: 18px;
font-size: 10px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
border: 2px solid #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
/* Hide count badge for single keys */
.inventory-item[data-type="key_ring"][data-key-count="1"]::after {
display: none;
}

View File

@@ -123,6 +123,11 @@ export function addToInventory(sprite) {
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) {
@@ -212,6 +217,134 @@ export function addToInventory(sprite) {
}
}
// 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
};
}
// Add the key to the key ring
window.inventory.keyRing.keys.push(sprite);
// Update or create the key ring display
updateKeyRingDisplay();
// Show notification
if (window.gameAlert) {
window.gameAlert(`Added ${sprite.scenarioData.name} to key ring`, 'success', 'Key Collected', 3000);
}
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
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)
};
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
@@ -311,3 +444,4 @@ window.addToInventory = addToInventory;
window.removeFromInventory = removeFromInventory;
window.addNotepadToInventory = addNotepadToInventory;
window.createItemIdentifier = createItemIdentifier;
window.handleKeyRingInteraction = handleKeyRingInteraction;

View File

@@ -44,11 +44,33 @@ const PREDEFINED_LOCK_CONFIGS = {
function assignKeysToLocks() {
console.log('Assigning keys to locks based on scenario definitions...');
// Get all keys from inventory
const playerKeys = window.inventory?.items?.filter(item =>
// Get all keys from inventory (including key ring)
let playerKeys = [];
// Check for individual keys
const individualKeys = window.inventory?.items?.filter(item =>
item && item.scenarioData &&
item.scenarioData.type === 'key'
) || [];
playerKeys = playerKeys.concat(individualKeys);
// Check for key ring
const keyRingItem = window.inventory?.items?.find(item =>
item && item.scenarioData &&
item.scenarioData.type === 'key_ring'
);
if (keyRingItem && keyRingItem.scenarioData.allKeys) {
// Convert key ring keys to the format expected by the system
const keyRingKeys = keyRingItem.scenarioData.allKeys.map(keyData => {
return {
scenarioData: keyData,
name: 'key',
objectId: `key_ring_${keyData.key_id || keyData.name}`
};
});
playerKeys = playerKeys.concat(keyRingKeys);
}
console.log(`Found ${playerKeys.length} keys in inventory`);

View File

@@ -53,11 +53,34 @@ export function handleUnlock(lockable, type) {
const requiredKey = lockRequirements.requires;
console.log('KEY REQUIRED', requiredKey);
// Get all keys from player's inventory
const playerKeys = window.inventory.items.filter(item =>
// Get all keys from player's inventory (including key ring)
let playerKeys = [];
// Check for individual keys
const individualKeys = window.inventory.items.filter(item =>
item && item.scenarioData &&
item.scenarioData.type === 'key'
);
playerKeys = playerKeys.concat(individualKeys);
// Check for key ring
const keyRingItem = window.inventory.items.find(item =>
item && item.scenarioData &&
item.scenarioData.type === 'key_ring'
);
if (keyRingItem && keyRingItem.scenarioData.allKeys) {
// Convert key ring keys to the format expected by the minigame
const keyRingKeys = keyRingItem.scenarioData.allKeys.map(keyData => {
// Create a mock inventory item for each key in the ring
return {
scenarioData: keyData,
name: 'key',
objectId: `key_ring_${keyData.key_id || keyData.name}`
};
});
playerKeys = playerKeys.concat(keyRingKeys);
}
if (playerKeys.length > 0) {
// Show key selection interface