import { NpcDialog } from './NpcDialog.js'; import { syncNpcRollTables } from './npcRollTableSync.js'; import './mgt2eMigration.js'; const MODULE_ID = 'mgt2-compendium-amiral-denisov'; const ChatLogV2 = foundry.applications.sidebar.tabs.ChatLog; function openNpcDialog(initialTab, options = {}) { new NpcDialog({ initialTab, ...options }).render({ force: true }); } function registerNpcCommand(commandName, initialTab) { if (!ChatLogV2?.CHAT_COMMANDS) { console.warn(`${MODULE_ID} | ChatLog.CHAT_COMMANDS indisponible, commande /${commandName} non enregistrée`); return; } ChatLogV2.CHAT_COMMANDS[commandName] = { rgx: new RegExp(`^\\/${commandName}(?:\\s+(.*))?$`, 'i'), fn: () => { openNpcDialog(initialTab); return false; }, }; console.log(`${MODULE_ID} | Commande /${commandName} enregistrée via ChatLog.CHAT_COMMANDS`); } Hooks.once('init', () => { console.log(`${MODULE_ID} | Outils PNJ initialisés`); // Pré-charge les templates Handlebars // Compatibilité v13 et v14 const loadTemplatesFn = foundry.applications?.handlebars?.loadTemplates || loadTemplates; if (loadTemplatesFn) { loadTemplatesFn([ `modules/${MODULE_ID}/templates/npc-dialog.hbs`, `modules/${MODULE_ID}/templates/npc-result.hbs`, ]); } registerNpcCommand('pnj', 'npc'); registerNpcCommand('rencontre', 'encounter'); registerNpcCommand('mission', 'mission'); }); Hooks.once('ready', async () => { await syncNpcRollTables(); console.log(`${MODULE_ID} | Outils PNJ prêts – tapez /pnj, /rencontre ou /mission dans le chat`); }); /** * Solution pour Foundry v14 : Intercepte les commandes AVANT la validation * Utilise renderChatInput pour modifier le comportement de l'input * Compatible v13 (jQuery) et v14 (DOM element) */ Hooks.on('renderChatInput', (app, html, data) => { // Foundry v14 passe un objet avec element, v13 passe jQuery let input; // Vérifie si html est un objet avec element (v14) if (html?.element) { input = $(html.element).find('textarea[name="content"]'); } else if (html?.find) { // v13 ou déjà jQuery input = html.find('textarea[name="content"]'); } else { // Dernier recours : suppose que html est l'élément input = $(html).find('textarea[name="content"]'); } // Évite les doublons d'écouteurs if (input.data('mgt2-npc-listener')) return; input.data('mgt2-npc-listener', true); input.on('keydown', (event) => { // Intercepte Entrée (13) et vérifie si c'est une de nos commandes if (event.key === 'Enter' && !event.shiftKey) { const content = input.val()?.trim(); if (content?.startsWith('/pnj')) { event.preventDefault(); event.stopImmediatePropagation(); openNpcDialog('npc'); input.val(''); } else if (content?.startsWith('/rencontre')) { event.preventDefault(); event.stopImmediatePropagation(); openNpcDialog('encounter'); input.val(''); } else if (content?.startsWith('/mission')) { event.preventDefault(); event.stopImmediatePropagation(); openNpcDialog('mission'); input.val(''); } } }); }); /** * Intercepte les messages de chat pour /pnj, /rencontre, /mission * Utilise preCreateChatMessage pour Foundry v14+ (avant que le message ne soit validé) * Compatible avec Foundry v13 et v14 */ Hooks.on('preCreateChatMessage', (message, data, options) => { const content = message.content?.trim()?.toLowerCase(); if (content === '/pnj' || content?.startsWith('/pnj ')) { openNpcDialog('npc'); return false; // Empêche la création du message } if (content === '/rencontre' || content?.startsWith('/rencontre ')) { openNpcDialog('encounter'); return false; // Empêche la création du message } if (content === '/mission' || content?.startsWith('/mission ')) { openNpcDialog('mission'); return false; // Empêche la création du message } }); // Gardé pour compatibilité v13 Hooks.on('chatMessage', (...args) => { // Foundry v14 passe un objet ChatMessage en premier paramètre // Foundry v13 passe (chatLog, message, chatData) let message; if (args[0]?.content !== undefined) { // v14: premier argument est ChatMessage message = args[0].content; } else if (typeof args[1] === 'string') { // v13: deuxième argument est la string message message = args[1]; } else { return; } const trimmed = message?.trim()?.toLowerCase(); if (trimmed === '/pnj' || trimmed?.startsWith('/pnj ')) { openNpcDialog('npc'); return false; } if (trimmed === '/rencontre' || trimmed?.startsWith('/rencontre ')) { openNpcDialog('encounter'); return false; } if (trimmed === '/mission' || trimmed?.startsWith('/mission ')) { openNpcDialog('mission'); return false; } });