import { SWDELUXStatBlockParser } from "./sw-statblock-parser.js"; import { ClassCounter} from "https://www.uberwald.me/fvtt_appcount/count-class-ready.js" const __compFolderTranslation = [ { compendium: 'swade-core-rules.swade-vehicles', words: [ { source: 'Vehicles', translation: 'Véhicules' }, { source: 'Aircraft', translation: 'Avions' }, { source: 'Civilian', translation: 'Civils' }, { source: 'Modern Military Aircraft', translation: 'Avions Militaires Modernes' }, { source: 'World War II Military Aircraft', translation: 'Avions Seconde Guerre Mondiale' }, ] } ] class FolderTranslate { static async translateFolders() { for (let tData of __compFolderTranslation) { let pack = game.packs.get(tData.compendium); let wasLocked = false; if (pack.locked) { await pack.configure({ locked: false }) wasLocked = true; } let folders = await game.CF.FICFolderAPI.loadFolders(tData.compendium); for (let trans of tData.words) { let folderToChange = folders.contents.find(f => f.name === trans.source); if (folderToChange) { await game.CF.FICFolderAPI.renameFolder(folderToChange, trans.translation); } } if (wasLocked) { await pack.configure({ locked: true }) } } } } /************************************************************************************/ Hooks.once('translateCompendiumFolders', () => { console.log("LOADED !!!!!!") }); /************************************************************************************/ class swadeFrTranslator { static getRank(rank) { if (rank == 'Novice') return 'Novice'; if (rank == 'Seasoned') return 'Aguerri'; if (rank == 'Veteran') return 'Vétéran'; if (rank == 'Heroic') return 'Héroïque'; if (rank == 'Legendary') return 'Légendaire'; return false } static getAttribute(attr) { console.log("Attr is", attr) if (attr == "Agility") return 'Agilité'; if (attr == "Smarts") return 'Intellect'; if (attr == "Spirit") return 'Ame'; if (attr == "Strength") return 'Force'; if (attr == "Vigor") return 'Vigueur'; return false } } /************************************************************************************/ Hooks.once('init', () => { console.log("INIT !!!!!!") if (typeof Babele !== 'undefined') { console.log("BABELE LOADED !!!"); Babele.get().register({ module: 'swade-fr-content', lang: 'fr', dir: 'compendiums' }); Babele.get().registerConverters({ "gear_skill": (skill) => { let transl = skill //console.log("Testing", skill) if (skill) { let translated = game.babele.translate("swade-core-rules.swade-skills", { name: skill.trim() }, true) transl = translated.name || skill.trim() } return transl }, "skill_swid": (swid) => { if (swid == "combat") return "fighting"; if (swid == "tir") return "shooting"; return swid }, "category_converter": (category) => { return game.i18n.localize(category) }, "edge_requirements": (req) => { let reqTab = req.split(",") let results = [] for (let item of reqTab) { let keyName = item.match(/([\w\s\(\)]+) (d[\w\+]*)/) //console.log("Keyword", item, keyName) if (keyName && keyName[2]) { // This is a skill or attribute let toTranslate = keyName[1].trim() let attr = swadeFrTranslator.getAttribute(toTranslate) if (attr) { // Test if attribute results.push(attr + " " + keyName[2].trim()) } else { // Test if skill let translated = game.babele.translate("swade-core-rules.swade-skills", { name: toTranslate }, true) if (!translated.name) { translated = game.babele.translate("deadlands-core-rules.deadlands-skills", { name: toTranslate }, true) } let transResult = translated.name || toTranslate results.push(transResult + " " + keyName[2].trim()) } } else { // Rank or edge let itemName = item.trim() let rank = swadeFrTranslator.getRank(itemName) if (rank) { results.push(rank) } else { let translated = game.babele.translate("swade-core-rules.swade-edges", { name: itemName }, true) if (!translated.name) { translated = game.babele.translate("deadlands-core-rules.deadlands-edges", { name: itemName }, true) } let transResult = translated.name || itemName results.push(transResult) } } } //console.log(">>>>>>>>>>>>>>>>>>>>>>>>> { if (range) { if (range == 'Cone Template') return 'Gabarit de cone'; } return range; }, "gear_ammo": (ammo) => { if (ammo) { if (ammo == 'Arrows/Bolts') return 'Flèches/Carreaux'; if (ammo == 'Canister Shot (Cannon)') return 'Cartouches (Canon)'; if (ammo == 'Shrapnel Shot (Cannon)') return 'Shrapnel (Canon)'; if (ammo == 'Solid Shot (Cannon)') return 'Solide (Canon)'; if (ammo == 'Bullets, Medium') return 'Balles, Moyenne'; if (ammo == 'Shotgun Shells') return 'Cartouche de Shotgun'; if (ammo == 'Laser Battery, Pistol') return 'Batterie pour laser, Pistolet'; if (ammo == 'Laser Battery, Rifle / SMG') return 'Batterie pour laser, Fusil'; } return ammo; }, "powers_duration": (duration) => { if (duration == 'One hour') return '1 heure'; if (duration == 'Instant (slot); 5 (speed)') return 'Instantanée (apathie), 5 (vitesse)'; if (duration == '(boost); Instant (lower)') return '5 (augmentation), Instantanée (diminution)'; if (duration == 'Instant') return 'Instantannée'; if (duration == 'Until the end of the victim\'s next turn') return 'Jusqu’à la fin du prochain tour de la victime'; if (duration == 'A brief conversation of about five minutes') return 'Une brève conversation d\'environ 5 minutes'; if (duration == '5 (detect), one hour (conceal)') return '5 (détection), 1 heure (dissimulation)'; if (duration == 'Instant (Sound); 5 (Silence)') return 'Instantanée (son), 5 (silence)'; return duration; }, "powers_range": (range) => { if (range == 'Smarts x5 (Sound); Smarts (Silence)') return 'Intellect ×5 (son), Intellect (silence)'; if (range == "Cone Template") return "Gabarit de cône" if (range == "Touch") return "Toucher" if (range == "Sm") return "Intellect" if (range == "Sm x 2" || range == "Sm x2") return "Intellect x2" if (range == "Self") return "Personnel" return range; }, "powers_rank": (rank) => { return swadeFrTranslator.getRank(rank) } }); } }); /* -------------------------------------------- */ export class SwadeFRContentCommands { static init() { if (!game.swadeFRContent) { const swadeFRCommands = new SwadeFRContentCommands() swadeFRCommands.registerCommand({ path: ["/montremonsecret"], func: (content, msg, params) => SwadeFRContentCommands.enableSecret(), descr: "Affiche les compendiums secrets" }); swadeFRCommands.registerCommand({ path: ["/cachemonsecret"], func: (content, msg, params) => SwadeFRContentCommands.disableSecret(), descr: "Cache les compendiums secrets" }); swadeFRCommands.registerCommand({ path: ["/statparser"], func: (content, msg, params) => SwadeFRContentCommands.statParser(), descr: "Parse SW Delux stat block" }); game.swadeFRContent = { commands: swadeFRCommands } } Hooks.on("chatMessage", (html, content, msg) => { console.log("CHAT PARSER!!!") if (content[0] == '/') { let regExp = /(\S+)/g; let commands = content.match(regExp); if (game.swadeFRContent.commands.processChatCommand(commands, content, msg)) { return false; } } return true }) } constructor() { this.commandsTable = {} } /* -------------------------------------------- */ registerCommand(command) { this._addCommand(this.commandsTable, command.path, '', command); } /* -------------------------------------------- */ _addCommand(targetTable, path, fullPath, command) { if (!this._validateCommand(targetTable, path, command)) { return; } const term = path[0]; fullPath = fullPath + term + ' ' if (path.length == 1) { command.descr = `${fullPath}: ${command.descr}`; targetTable[term] = command; } else { if (!targetTable[term]) { targetTable[term] = { subTable: {} }; } this._addCommand(targetTable[term].subTable, path.slice(1), fullPath, command) } } /* -------------------------------------------- */ _validateCommand(targetTable, path, command) { if (path.length > 0 && path[0] && command.descr && (path.length != 1 || targetTable[path[0]] == undefined)) { return true; } console.warn("Commande invalide", targetTable, path, command); return false; } /* -------------------------------------------- */ /* Manage chat commands */ processChatCommand(commandLine, content = '', msg = {}) { // Setup new message's visibility let rollMode = game.settings.get("core", "rollMode"); if (["gmroll", "blindroll"].includes(rollMode)) msg["whisper"] = ChatMessage.getWhisperRecipients("GM"); if (rollMode === "blindroll") msg["blind"] = true; msg["type"] = 0; let command = commandLine[0].toLowerCase(); let params = commandLine.slice(1); return this.process(command, params, content, msg); } /* -------------------------------------------- */ process(command, params, content, msg) { return this._processCommand(this.commandsTable, command, params, content, msg); } /* -------------------------------------------- */ static enableSecret() { game.settings.set("world", "swade-fr-content-hidden-compendiums", true) } /* -------------------------------------------- */ static disableSecret() { game.settings.set("world", "swade-fr-content-hidden-compendiums", false) } /* -------------------------------------------- */ static statParser() { let dialogue = new Dialog({ title: `Import`, content: `

Stab block:

`, buttons: { one: { icon: '', label: 'Parser !', callback: (html) => { let text = html.find('#swdelux-stat-parser').val(); let parser = new SWDELUXStatBlockParser(text); parser.parse(text); } } } }) dialogue.render(true) } /* -------------------------------------------- */ _processCommand(commandsTable, name, params, content = '', msg = {}, path = "") { console.log("===> Processing command") let command = commandsTable[name]; path = path + name + " "; if (command?.subTable) { if (params[0]) { return this._processCommand(command.subTable, params[0], params.slice(1), content, msg, path) } else { this.help(msg, command.subTable); return true; } } if (command?.func) { const result = command.func(content, msg, params); if (result == false) { BoLCommands._chatAnswer(msg, command.descr); } return true; } return false; } } /************************************************************************************/ const transFolder = { "Actor": "Acteur", "Edges": "Atouts" } const subFolder = { 'Social Edges': 'Atouts sociaux', 'Background Edges': 'Atouts de Background', 'Combat Edges': 'Atouts de combat', 'Leadership Edges': 'Atouts de commandement', 'Legendary Edges': 'Atouts légendaires', 'Power Edges': 'Atouts de pouvoir', 'Professional Edges': 'Atouts professionnels', 'Weird Edges': 'Atouts étranges', 'Edges': 'Atouts', 'Hindrances': 'Handicaps', 'Skills': 'Compétences', 'Equipment': 'Equipement', 'Ammo': 'Munitions', 'Armor': 'Armure', 'Common Gear': 'Matériel commun', 'Modern Firearms': 'Armes à feu modernes', 'Personal Weapons': 'Armes', 'Special Weapons': 'Armes spéciales', 'Bullet': 'Balles', 'Cannon': 'Canon', 'Laser Battery': 'Batterie Laser', 'Adventuring Gear': 'Matériel d\'aventure', 'Animals and Tack': 'Animaux', 'Clothing': 'Vêtements', 'Computers & Electronics': 'Ordinateurs et Electroniques', 'Firearms Accessories': 'Accessoires armes à feu', 'Food': 'Nourriture', 'Personal Defense': 'Auto-défense', 'Futuristic': 'Futuriste', 'Medieval & Ancient': 'Médiévale et Antiquité', 'Modern': 'Moderne', 'Shields': 'Boucliers', 'Laser (Futuristic)': 'Laser (Fururiste)', 'Machine Guns': 'Mitraillettes', 'Pistols': 'Pistolets', 'Rifles': 'Fusils', 'Submachine Guns': 'Semi-automatiques', 'Cannons': 'Canons', 'Catapults': 'Catapultes', 'Flamethrowers': 'Lance-flammes', 'Rocket Launchers & Torpedoes': 'Lance roquettes et torpilles', 'Vehicular Weapons': 'Armes de véhicules' } /************************************************************************************/ async function loadSecretCompendiums() { if (game.settings.get("world", "swade-fr-content-hidden-compendiums")) { console.log(">>>>> Load hidden compendiums!") /* Load rules */ let urls = ["modules/swade-fr-content/compendiums/swade-core-rules.swade-rules-secret.json"] const [translations] = await Promise.all( [Promise.all(urls.map((url) => fetch(url).then((r) => r.json()).catch(e => { })))]); let metadata = game.data.packs.find(p => p.name == "swade-rules") if (metadata) { let translation; translations.forEach(t => { if (t) { translation = t; // the last valid } }); if (translation) { let babele = Babele.get() let entry = mergeObject(translation, { collection: metadata.id }) babele.translations.push(entry) console.log(">>>>", babele.translations) babele.packs.set(metadata.id, new TranslatedCompendium(metadata, entry)) } } } } /************************************************************************************/ function processItemSwid(actor, item) { let swid = item.system.swid let newSwid = swid if (swid == "combat") newSwid = "fighting"; if (swid == "tir") newSwid = "shooting"; if (swid != newSwid) { console.log("Item to update", item.name, swid, newSwid) actor.updateEmbeddedDocuments('Item', [{ _id: item.id, "system.swid": newSwid }]) } } /************************************************************************************/ function migrateSwid() { for (let actor of game.actors) { for (let item of actor.items) { if (item.system?.swid) { processItemSwid(actor, item) } } } } /************************************************************************************/ function checkSwidSettings() { let swidFighting = game.settings.get('swade', 'parryBaseSwid') if (swidFighting != "fighting") { ui.notifications.warn("Votre compétence de parade n'est pas positionnée à 'fighting' dans les paramètres de SWADE. Nous vous recommandons de le faire pour éviter des problèmes de calcul de la parade.") //game.settings.set('swade', 'parryBaseSwid', "fighting") } } /************************************************************************************/ Hooks.once('ready', () => { console.log(">>>>>>>>>>") // add hidden register game.settings.register("world", "swade-fr-content-hidden-compendiums", { name: "Montrer les compendiums cachés", scope: "world", config: false, default: false, type: Boolean, onChange: lang => window.location.reload() }) SwadeFRContentCommands.init() migrateSwid() checkSwidSettings() //FolderTranslate.translateFolders() ClassCounter.registerUsageCount("swade-fr-content") }); /************************************************************************************/ Hooks.once('babele.ready', () => { console.log(">>>>>>>>>> BABELE READY") loadSecretCompendiums() }); console.log(">>>>>>>>>>>> LOADED")