/* Common useful functions shared between objects */ import { RdDRollTables } from "./rdd-rolltables.js"; import { ChatUtility } from "./chat-utility.js"; import { RdDItemCompetence } from "./item-competence.js"; import { RdDCombat } from "./rdd-combat.js"; import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js"; import { RdDItem } from "./item.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemArme } from "./item-arme.js"; /* -------------------------------------------- */ const level_category = { "generale": "-4", "particuliere": "-8", "specialisee": "-11", "connaissance": "-11", "draconic": "-11", "melee": "-6", "tir": "-8", "lancer": "-8" } /* -------------------------------------------- */ const label_category = { "generale": "Générales", "particuliere": "Particulières", "specialisee": "Spécialisées", "connaissance": "Connaissances", "draconic": "Draconics", "melee": "Mêlée", "tir": "Tir", "lancer": "Lancer" } /* -------------------------------------------- */ const competenceTroncs = [ ["Esquive", "Dague", "Corps à corps"], ["Epée à 1 main", "Epée à 2 mains", "Hache à 1 main", "Hache à 2 mains", "Lance", "Masse à 1 main", "Masse à 2 mains"] ]; const competence_xp = { "-11" : [ 5, 10, 15, 25, 35, 45, 55, 70, 85, 100, 115, 135, 155, 175 ], "-8" : [ 10, 20, 30, 40, 55, 70, 85, 100, 120, 140,160], "-6" : [ 10, 20, 35, 50, 65, 80, 100, 120, 140], "-4" : [ 15, 30, 45, 60, 80, 100, 120] } /* -------------------------------------------- */ // This table starts at 0 -> niveau -10 const competence_xp_par_niveau = [ 5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20, 30, 30, 40, 40, 60, 60, 100, 100, 100, 100, 100, 100, 100, 100, 100]; const carac_array = [ "taille", "apparence", "constitution", "force", "agilite", "dexterite", "vue", "ouie", "odoratgout", "volonte", "intellect", "empathie", "reve", "chance", "melee", "tir", "lancer", "derobee"]; const difficultesLibres = [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]; const ajustementsConditions = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10]; const ajustementsEncaissement = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10, +11, +12, +13, +14, +15, +16, +17, +18, +19, +20, +21, +22, +23, +24, +25]; const carac_xp_par_valeur = [6, 6, 7, 7, 8, 8, 9, 9, 10, 20, 30, 40, 50, 60, 70]; const XP_CARAC_OFFSET = 7; /* -------------------------------------------- */ function _buildAllSegmentsFatigue(max) { const cycle = [5, 2, 4, 1, 3, 0]; let fatigue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; for (let i = 0; i <= max; i++) { const ligneFatigue= duplicate(fatigue[i]); const caseIncrementee = cycle[i % 6]; ligneFatigue[caseIncrementee]++; ligneFatigue[caseIncrementee + 6]++; ligneFatigue.fatigueMax = 2 * (i + 1); fatigue[i + 1] = ligneFatigue ; } return fatigue; } /* -------------------------------------------- */ function _cumulSegmentsFatigue(matrix) { let cumulMatrix = []; for (let line of matrix) { let cumul = duplicate(line); for (let i = 1; i < 12; i++) { cumul[i] += cumul[i - 1]; } cumulMatrix.push(cumul); } return cumulMatrix; } /* -------------------------------------------- */ const fatigueMatrix = _buildAllSegmentsFatigue(60); const cumulFatigueMatrix = _cumulSegmentsFatigue(fatigueMatrix); const fatigueMalus = [ 0, 0, 0, -1, -1, -1, -2, -3, -4, -5, -6, -7 ]; // Provides the malus for each segment of fatigue const fatigueLineSize = [ 3, 6, 7, 8, 9, 10, 11, 12]; const fatigueLineMalus = [ 0, -1, -2, -3, -4, -5, -6, -7 ]; const fatigueMarche = { "aise": { "4":1, "6":2, "8":3, "10":4, "12":6 }, "malaise": { "4":2, "6":3, "8":4, "10":6 }, "difficile": { "4":3, "6":4, "8":6 }, "tresdifficile": { "4":4, "6":6 } } /* -------------------------------------------- */ /* Static tables for commands /table */ const table2func = { "rdd": { descr: "rdd: Ouvre la table de résolution", func: RdDRollResolutionTable.open }, "queues": { descr: "queues: Tire une queue de Dragon", func: RdDRollTables.getQueue}, "ombre": { descr: "ombre: Tire une Ombre de Dragon", func: RdDRollTables.getOmbre }, "tetehr": { descr: "tetehr: Tire une Tête de Dragon pour Hauts Revants", fund: RdDRollTables.getTeteHR}, "tete" : { descr: "tete: Tire une Tête de Dragon", func: RdDRollTables.getTete}, "souffle": { descr: "souffle: Tire un Souffle de Dragon", func: RdDRollTables.getSouffle}, "tarot" : { descr: "tarot: Tire une carte de Tarot Dracnique", func: RdDRollTables.getTarot} }; /* -------------------------------------------- */ const definitionsBlessures = [ { type: "legere", facteur: 2 }, { type: "grave", facteur : 4 }, { type: "critique", facteur : 6 } ] /* -------------------------------------------- */ const nomEthylisme = [ "Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"]; /* -------------------------------------------- */ const definitionsEncaissement = { "mortel": [ { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 1, graves: 0, critiques: 0 }, { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", legeres: 0, graves: 1, critiques: 0 }, { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", legeres: 0, graves: 0, critiques: 1 }, ], "non-mortel": [ { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", legeres: 1, graves: 0, critiques: 0 }, { minimum: 20, maximum: undefined, endurance: "100", vie: "1", legeres: 1, graves: 0, critiques: 0 }, ], "cauchemar": [ { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", legeres: 0, graves: 0, critiques: 0 }, ] }; /* -------------------------------------------- */ export class RdDUtility { /* -------------------------------------------- */ static async preloadHandlebarsTemplates( ) { const templatePaths = [ //Character Sheets 'systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-humanoide-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html', //Items 'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-arme-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-armure-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-objet-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-conteneur-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-sort-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-herbe-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-ingredient-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-rencontresTMR-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-souffle-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-tarot-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-tete-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-ombre-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-monnaie-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-meditation-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/competence-categorie.html', 'systems/foundryvtt-reve-de-dragon/templates/competence-carac-defaut.html', 'systems/foundryvtt-reve-de-dragon/templates/competence-base.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categorie.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categorie_parade.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html', 'systems/foundryvtt-reve-de-dragon/templates/arme-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/sort-draconic.html', 'systems/foundryvtt-reve-de-dragon/templates/sort-tmr.html', 'systems/foundryvtt-reve-de-dragon/templates/niveau-ethylisme.html', 'systems/foundryvtt-reve-de-dragon/templates/casetmr-specific-list.html', // Dialogs 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-surenc.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-enctotal.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', // Calendrier 'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html', 'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', 'systems/foundryvtt-reve-de-dragon/templates/heures-select-option.html', // Conteneur/item in Actor sheet 'systems/foundryvtt-reve-de-dragon/templates/actor-inventaire-conteneur.html', 'systems/foundryvtt-reve-de-dragon/templates/editor-notes-mj.html', // HUD 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', // messages tchat 'systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-appelchance.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-attaque.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-parade.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-esquive.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-general.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-tache.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-sort.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html' ]; return loadTemplates(templatePaths); } /* -------------------------------------------- */ static checkNull(items) { if (items && items.length) { return items; } return []; } /* -------------------------------------------- */ static getNomEthylisme( niveauEthylisme ) { let index = -niveauEthylisme; return index <0 ? 'Aucun' : nomEthylisme[index]; } /* -------------------------------------------- */ static initAfficheContenu( actorId ) { // persistent handling of conteneur show/hide if ( !this.afficheContenu ) this.afficheContenu = {}; } /* -------------------------------------------- */ static toggleAfficheContenu( conteneurId) { this.afficheContenu[conteneurId] = !this.afficheContenu[conteneurId]; } /* -------------------------------------------- */ static getAfficheContenu( conteneurId) { return this.afficheContenu[conteneurId]; } /* -------------------------------------------- */ static filterItemsPerTypeForSheet( data ) { data.data.materiel = this.checkNull(data.itemsByType['objet']); data.data.conteneurs = this.checkNull(data.itemsByType['conteneur']); data.data.armes = this.checkNull(data.itemsByType['arme']); data.data.armures = this.checkNull(data.itemsByType['armure']); data.data.livres = this.checkNull(data.itemsByType['livre']); data.data.potions = this.checkNull(data.itemsByType['potion']); data.data.ingredients = this.checkNull(data.itemsByType['ingredient']); data.data.munitions = this.checkNull(data.itemsByType['munition']); data.data.herbes = this.checkNull(data.itemsByType['herbe']); data.data.sorts = this.checkNull(data.itemsByType['sort']); data.data.queues = this.checkNull(data.itemsByType['queue']); data.data.souffles = this.checkNull(data.itemsByType['souffle']); data.data.ombres = this.checkNull(data.itemsByType['ombre']); data.data.tetes = this.checkNull(data.itemsByType['tete']); data.data.taches = this.checkNull(data.itemsByType['tache']); data.data.monnaie = this.checkNull(data.itemsByType['monnaie']); data.data.meditations = this.checkNull(data.itemsByType['meditation']); data.data.objets = data.data.conteneurs.concat(data.data.materiel).concat(data.data.armes).concat(data.data.armures).concat(data.data.munitions).concat(data.data.livres).concat(data.data.potions).concat(data.data.herbes).concat(data.data.ingredients); } /* -------------------------------------------- */ static async processItemDropEvent( actorSheet, event) { let dragData = JSON.parse(event.dataTransfer.getData("text/plain")); let dropID = $(event.target).parents(".item").attr("data-item-id"); // Only relevant if container drop if ( dropID ) { // Dropped over an item !!! let objetId = dragData.id || dragData.data._id; if ( actorSheet.objetVersConteneur[objetId] != dropID ) { if ( actorSheet.actor.testConteneurCapacite(objetId, dropID) ) { await actorSheet.actor.enleverDeConteneur(objetId, actorSheet.objetVersConteneur[objetId]); await actorSheet.actor.ajouterAConteneur(objetId, dropID); } else { ui.notifications.info("Capacité d'encombrement insuffisante dans le conteneur !"); } } } actorSheet.actor.computeEncombrementTotalEtMalusArmure(); } /* -------------------------------------------- */ static buildArbreDeConteneur( actorSheet, data ) { actorSheet.objetVersConteneur = {}; // Table de hash locale pour recupération rapide du conteneur parent (si existant) // Attribution des objets aux conteneurs for (let conteneur of data.data.conteneurs) { conteneur.subItems = []; if (!conteneur.data.encTotal) conteneur.data.encTotal = 0; //conteneur.data.encTotal = ; Deja calculé if (conteneur.data.contenu) { for (let id of conteneur.data.contenu) { let objet = data.data.objets.find( objet => (id == objet._id) ); if (objet) { if (!objet.data.encombrement) objet.data.encombrement = 0; // Auto-fix objet.estContenu = true; // Permet de filtrer ce qifui est porté dans le template actorSheet.objetVersConteneur[id] = conteneur._id; conteneur.data.encTotal += Number(objet.data.encombrement) * Number(((objet.data.quantite)?objet.data.quantite:1)); conteneur.subItems.push( objet ); } } } } // Construit la liste des conteneurs de niveau 1 (c'est à dire non contenu eux-même dans un conteneur) let newConteneurs = data.data.conteneurs.filter(function(conteneur, index, arr) { return !conteneur.estContenu } ); data.data.conteneurs = newConteneurs; } /* -------------------------------------------- */ /** Construit la structure récursive des conteneurs, avec imbrication potentielle * */ static buildConteneur( objet, niveau ) { if (!niveau) niveau = 1; objet.niveau = niveau; //console.log("OBJ:", objet); let str = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor-inventaire-conteneur.html']( { item: objet} ); if (objet.type == 'conteneur') { //console.log("ITEM DISPLAYED", this.getAfficheContenu(objet._id) ); if ( this.getAfficheContenu(objet._id) ) { str = str + "