From f8b20c2db0a66a05b32dba191a40f8afb1f3d6c0 Mon Sep 17 00:00:00 2001 From: "Z. Cliffe Schreuders" Date: Sat, 15 Nov 2025 23:48:15 +0000 Subject: [PATCH] feat(rfid): Complete system integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- index.html | 1 + js/core/game.js | 9 +++++ js/minigames/helpers/chat-helpers.js | 51 ++++++++++++++++++++++++++++ js/systems/interactions.js | 33 ++++++++++++++++-- 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 8fa5d13..1c1291d 100644 --- a/index.html +++ b/index.html @@ -41,6 +41,7 @@ + diff --git a/js/core/game.js b/js/core/game.js index e5a1111..70f9015 100644 --- a/js/core/game.js +++ b/js/core/game.js @@ -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'); diff --git a/js/minigames/helpers/chat-helpers.js b/js/minigames/helpers/chat-helpers.js index e8cf005..4b5c99d 100644 --- a/js/minigames/helpers/chat-helpers.js +++ b/js/minigames/helpers/chat-helpers.js @@ -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; diff --git a/js/systems/interactions.js b/js/systems/interactions.js index 2809fb9..6626dd9 100644 --- a/js/systems/interactions.js +++ b/js/systems/interactions.js @@ -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