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