feat(rfid): Complete system integration

Integrated RFID minigame into all game systems:

Chat System Integration:
- Added clone_keycard tag handler to chat-helpers.js
- Format: # clone_keycard:Card Name|HEX_ID
- Uses proven window.pendingConversationReturn pattern
- Automatically returns to conversation after cloning

Inventory Integration:
- Added keycard click handler in interactions.js
- Click keycard with cloner → starts clone mode
- Shows alert if no cloner available

Interaction Indicator:
- Added RFID icon support to getInteractionSpriteKey()
- RFID-locked doors/items show rfid-icon overlay
- Works for both door and item lock types

HTML Integration:
- Added rfid-minigame.css link to index.html
- Loaded alongside other minigame styles

Phaser Asset Integration:
- Added keycard sprites (base + 3 variants)
- Added rfid_cloner sprite
- Added rfid-icon and nfc-waves icons
- Loaded in js/core/game.js preload

All integration follows existing patterns from other minigames.
Ready for testing and asset creation.
This commit is contained in:
Z. Cliffe Schreuders
2025-11-15 23:48:15 +00:00
parent c153b44e34
commit f8b20c2db0
4 changed files with 92 additions and 2 deletions

View File

@@ -41,6 +41,7 @@
<link rel="stylesheet" href="css/container-minigame.css">
<link rel="stylesheet" href="css/phone-chat-minigame.css">
<link rel="stylesheet" href="css/person-chat-minigame.css">
<link rel="stylesheet" href="css/rfid-minigame.css">
<link rel="stylesheet" href="css/npc-interactions.css">
<link rel="stylesheet" href="css/pin.css">
<link rel="stylesheet" href="css/minigames-framework.css">

View File

@@ -82,6 +82,15 @@ export function preload() {
this.load.image('pin', 'assets/icons/pin.png');
this.load.image('talk', 'assets/icons/talk.png');
// Load RFID keycard and cloner assets
this.load.image('keycard', 'assets/objects/keycard.png');
this.load.image('keycard-ceo', 'assets/objects/keycard-ceo.png');
this.load.image('keycard-security', 'assets/objects/keycard-security.png');
this.load.image('keycard-maintenance', 'assets/objects/keycard-maintenance.png');
this.load.image('rfid_cloner', 'assets/objects/rfid_cloner.png');
this.load.image('rfid-icon', 'assets/icons/rfid-icon.png');
this.load.image('nfc-waves', 'assets/icons/nfc-waves.png');
// Load new object sprites from Tiled map tileset
// These are the key objects that appear in the new room_reception2.json
this.load.image('fingerprint_kit', 'assets/objects/fingerprint_kit.png');

View File

@@ -236,6 +236,57 @@ export function processGameActionTags(tags, ui) {
if (window.eventDispatcher) {
window.eventDispatcher.emit('npc_became_hostile', { npcId });
}
case 'clone_keycard':
if (param) {
const [cardName, cardHex] = param.split('|').map(s => s.trim());
// Check if player has RFID cloner
const hasCloner = window.inventory.items.some(item =>
item && item.scenarioData &&
item.scenarioData.type === 'rfid_cloner'
);
if (!hasCloner) {
result.message = '⚠️ You need an RFID cloner to clone cards';
if (ui) ui.showNotification(result.message, 'warning');
break;
}
// Generate card data
const cardData = {
name: cardName,
rfid_hex: cardHex,
rfid_facility: parseInt(cardHex.substring(0, 2), 16),
rfid_card_number: parseInt(cardHex.substring(2, 6), 16),
rfid_protocol: 'EM4100',
type: 'keycard',
key_id: `cloned_${cardName.toLowerCase().replace(/\s+/g, '_')}`
};
// Set pending conversation return (MINIMAL CONTEXT!)
// Conversation state automatically managed by npcConversationStateManager
window.pendingConversationReturn = {
npcId: window.currentConversationNPCId,
type: window.currentConversationMinigameType || 'person-chat'
};
// Start RFID minigame in clone mode
if (window.startRFIDMinigame) {
window.startRFIDMinigame(null, null, {
mode: 'clone',
cardToClone: cardData
});
result.success = true;
result.message = `📡 Starting card clone: ${cardName}`;
console.log('🔐 Started RFID clone minigame for:', cardName);
} else {
result.message = '⚠️ RFID minigame not available';
console.warn('startRFIDMinigame not found');
}
} else {
result.message = '⚠️ clone_keycard tag missing parameters (name|hex)';
console.warn(result.message);
}
break;

View File

@@ -352,6 +352,7 @@ function getInteractionSpriteKey(obj) {
const lockType = obj.doorProperties.lockType;
if (lockType === 'password') return 'password';
if (lockType === 'pin') return 'pin';
if (lockType === 'rfid') return 'rfid-icon';
return 'keyway'; // Default to keyway for key locks or unknown types
}
return null; // Unlocked doors don't need overlay
@@ -370,6 +371,7 @@ function getInteractionSpriteKey(obj) {
if (lockType === 'password') return 'password';
if (lockType === 'pin') return 'pin';
if (lockType === 'biometric') return 'fingerprint';
if (lockType === 'rfid') return 'rfid-icon';
// Default to keyway for key locks or unknown types
return 'keyway';
}
@@ -501,12 +503,39 @@ export function handleObjectInteraction(sprite) {
}
return;
}
if (!sprite.scenarioData) {
console.warn('Invalid sprite or missing scenario data');
return;
}
// Handle keycard cloning (when clicked from inventory)
if (sprite.scenarioData.type === 'keycard') {
console.log('KEYCARD INTERACTION - checking for cloner');
// Check if player has RFID cloner
const hasCloner = window.inventory.items.some(item =>
item && item.scenarioData &&
item.scenarioData.type === 'rfid_cloner'
);
if (hasCloner) {
// Start RFID minigame in clone mode
console.log('Starting RFID clone for keycard:', sprite.scenarioData.name);
if (window.startRFIDMinigame) {
window.startRFIDMinigame(null, null, {
mode: 'clone',
cardToClone: sprite.scenarioData
});
} else {
window.gameAlert('RFID minigame not available', 'error', 'Error', 3000);
}
} else {
window.gameAlert('You need an RFID cloner to clone this card', 'info', 'No Cloner', 3000);
}
return; // Early return
}
// Handle the Crypto Workstation - pick it up if takeable, or use it if in inventory
if (sprite.scenarioData.type === "workstation") {
// If it's in inventory (marked as non-takeable), open it