Quelques petits fixes #541
| @@ -94,7 +94,7 @@ export class RdDActorSheet extends ActorSheet { | ||||
|     RdDItemArme.computeNiveauArmes(formData.combat, formData.competences); | ||||
|     RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.data.carac); | ||||
|     formData.esquives = this.actor.getCompetences("Esquive").map(i => foundry.utils.deepClone(i.data)); | ||||
|     formData.combat = RdDCombatManager.finalizeArmeList(formData.combat, formData.competences, formData.data.carac); | ||||
|     formData.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.data.carac); | ||||
|  | ||||
|     this.armesList = formData.combat; | ||||
|  | ||||
| @@ -335,8 +335,8 @@ export class RdDActorSheet extends ActorSheet { | ||||
|     html.find('.arme-initiative a').click(async event => { | ||||
|       let combatant = game.combat.data.combatants.find(c => c.actor.data._id == this.actor.data._id); | ||||
|       if (combatant) { | ||||
|         let arme = this._getEventArmeCombat(event); | ||||
|         RdDCombatManager.rollInitiativeCompetence(combatant._id, arme); | ||||
|         let action = this._getEventArmeCombat(event); | ||||
|         RdDCombatManager.rollInitiativeAction(combatant._id, action); | ||||
|       } else { | ||||
|         ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat."); | ||||
|       } | ||||
|   | ||||
| @@ -394,6 +394,9 @@ export class RdDActor extends Actor { | ||||
|   getPossession(possessionId) { | ||||
|     return this.items.find(it => it.type == 'possession' && it.data.data.possessionid == possessionId); | ||||
|   } | ||||
|   getPossessions() { | ||||
|     return this.items.filter(it => it.type == 'possession'); | ||||
|   } | ||||
|  | ||||
|   getDemiReve() { | ||||
|     return Misc.templateData(this).reve.tmrpos.coord; | ||||
| @@ -2555,7 +2558,7 @@ export class RdDActor extends Actor { | ||||
|         if (rollData.competence.data.ispossession) { | ||||
|           RdDPossession.onAttaquePossession(this, rollData.competence) | ||||
|         } else { | ||||
|           const arme = RdDItemCompetenceCreature.toArme(rollData.competence) | ||||
|           const arme = RdDItemCompetenceCreature.toActionArme(rollData.competence) | ||||
|           RdDCombat.createUsingTarget(this)?.attaque(competence, arme) | ||||
|         } | ||||
|         return | ||||
| @@ -3145,7 +3148,7 @@ export class RdDActor extends Actor { | ||||
|         return carac.chance; | ||||
|     } | ||||
|     let entry = Misc.findFirstLike(name, Object.entries(carac), { mapper: it => it[1].label, description: 'caractéristique' }); | ||||
|     return entry.length > 0 ? carac[entry[0]] : undefined; | ||||
|     return entry && entry.length > 0 ? carac[entry[0]] : undefined; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   | ||||
| @@ -30,7 +30,7 @@ export class RdDItemArme extends Item { | ||||
|     switch (armeData ? armeData.type : '') { | ||||
|       case 'arme': return armeData; | ||||
|       case 'competencecreature': | ||||
|         return RdDItemCompetenceCreature.toArme(armeData); | ||||
|         return RdDItemCompetenceCreature.toActionArme(armeData); | ||||
|     } | ||||
|     return RdDItemArme.mainsNues(); | ||||
|   } | ||||
| @@ -189,7 +189,7 @@ export class RdDItemArme extends Item { | ||||
|         categorie_parade: 'sans-armes' | ||||
|       } | ||||
|     }; | ||||
|     mergeObject(corpsACorps.data, actorData ??{}, { overwrite: false }); | ||||
|     mergeObject(corpsACorps.data, actorData ?? {}, { overwrite: false }); | ||||
|     return corpsACorps; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -212,8 +212,11 @@ export class RdDItemCompetence extends Item { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static findCompetence(list, idOrName, options = {}) { | ||||
|     if (idOrName == undefined) { | ||||
|       return undefined; | ||||
|     } | ||||
|     options = mergeObject(options, { | ||||
|       filter: it => RdDItemCompetence.isCompetence(it), | ||||
|       preFilter: it => RdDItemCompetence.isCompetence(it), | ||||
|       description: 'compétence', | ||||
|     }); | ||||
|     return list.find(it => it.id == idOrName && RdDItemCompetence.isCompetence(it)) | ||||
|   | ||||
| @@ -11,14 +11,14 @@ export class RdDItemCompetenceCreature extends Item { | ||||
|     rollData.competence.data.categorie = "creature" | ||||
|     rollData.selectedCarac =  rollData.carac.carac_creature | ||||
|     if (rollData.competence.data.iscombat) { | ||||
|       rollData.arme = RdDItemCompetenceCreature.toArme(rollData.competence); | ||||
|       rollData.arme = RdDItemCompetenceCreature.toActionArme(rollData.competence); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static toArme(item) { | ||||
|   static toActionArme(item) { | ||||
|     if (RdDItemCompetenceCreature.isCompetenceAttaque(item)) { | ||||
|       // si c'est un Item compétence: cloner pour ne pas modifier lma compétence | ||||
|       // si c'est un Item compétence: cloner pour ne pas modifier la compétence | ||||
|       let arme = Misc.data( (item instanceof Item) ? item.clone():  item); | ||||
|       mergeObject(arme.data, | ||||
|         { | ||||
| @@ -28,11 +28,12 @@ export class RdDItemCompetenceCreature extends Item { | ||||
|           dommagesReels: arme.data.dommages, | ||||
|           penetration: 0, | ||||
|           force: 0, | ||||
|           rapide: true | ||||
|           rapide: true, | ||||
|           action: 'attaque' | ||||
|         }); | ||||
|       return arme; | ||||
|     } | ||||
|     console.error("RdDItemCompetenceCreature.toArme(", item, ") : impossible de transformer l'Item en arme"); | ||||
|     console.error("RdDItemCompetenceCreature.toActionArme(", item, ") : impossible de transformer l'Item en arme"); | ||||
|     return undefined; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -192,7 +192,7 @@ export class Misc { | ||||
|     if (!single) { | ||||
|       single = subset[0]; | ||||
|       const choices = Misc.join(subset.map(it => options.mapper(it)), '<br>'); | ||||
|       options.info(`Plusieurs choix de ${options.description}s possibles:<br>${choices}<br>Le premier sera choisi: ${mapToValue(single)}`); | ||||
|       options.onMessage(`Plusieurs choix de ${options.description}s possibles:<br>${choices}<br>Le premier sera choisi: ${options.mapper(single)}`); | ||||
|     } | ||||
|     return single; | ||||
|   } | ||||
| @@ -211,7 +211,7 @@ export class Misc { | ||||
|     } | ||||
|     value = Grammar.toLowerCaseNoAccent(value); | ||||
|     const subset = elements.filter(options.preFilter) | ||||
|       .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it)).includes(value)); | ||||
|       .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value)); | ||||
|     if (subset.length == 0) { | ||||
|       options.onMessage(`Pas de ${options.description} correspondant à ${value}`); | ||||
|     } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { ChatUtility } from "./chat-utility.js"; | ||||
| import { HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { RdDItemArme } from "./item-arme.js"; | ||||
| import { RdDItemCompetence } from "./item-competence.js"; | ||||
| import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; | ||||
| @@ -26,7 +27,7 @@ const premierRoundInit = [ | ||||
|   { pattern: 'epeegnome', init: 5.35 }, | ||||
|   { pattern: 'masse', init: 5.30 }, | ||||
|   { pattern: 'gourdin', init: 5.25 }, | ||||
|   { pattern: 'fléau', init: 5.20 }, | ||||
|   { pattern: 'fleau', init: 5.20 }, | ||||
|   { pattern: 'dague', init: 5.15 }, | ||||
|   { pattern: 'autre', init: 5.10 }, | ||||
| ]; | ||||
| @@ -84,28 +85,23 @@ export class RdDCombatManager extends Combat { | ||||
|     // calculate initiative | ||||
|     for (let cId = 0; cId < ids.length; cId++) { | ||||
|       const combatant = this.combatants.get(ids[cId]); | ||||
|       //if (!c) return results; | ||||
|  | ||||
|       let rollFormula = formula; // Init per default | ||||
|       if (!rollFormula) { | ||||
|         let armeCombat, competence; | ||||
|       let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0); | ||||
|       if (!formula) { | ||||
|         if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') { | ||||
|           for (const competenceItemData of combatant.actor.data.items) { | ||||
|             if (competenceItemData.data.data.iscombat) { | ||||
|               competence = duplicate(competenceItemData); | ||||
|             } | ||||
|           const competence = combatant.actor.data.items.find(it => it.data.data.iscombat) | ||||
|           if (competence) { | ||||
|             rollFormula = RdDCombatManager.formuleInitiative(2, competence.data.carac_value, competence.data.niveau, 0); | ||||
|           } | ||||
|           rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, competence.data.carac_value) + ")/100)"; | ||||
|         } else { | ||||
|           for (const itemData of combatant.actor.data.items) { | ||||
|             if (itemData.type == "arme" && itemData.data.equipe) { | ||||
|               armeCombat = duplicate(itemData); | ||||
|             } | ||||
|           const armeCombat = combatant.actor.data.items.find(it => it.type == 'arme' && itemData.data.equipe) | ||||
|           const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence; | ||||
|           const competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, compName); | ||||
|           if (competence) { | ||||
|             const carac = combatant.actor.data.data.carac[competence.data.defaut_carac].value; | ||||
|             const niveau = competence.data.niveau; | ||||
|             const bonusEcaille = (armeCombat?.data.magique) ? armeCombat.data.ecaille_efficacite : 0; | ||||
|             rollFormula = RdDCombatManager.formuleInitiative(2,  carac, niveau, bonusEcaille); | ||||
|           } | ||||
|           let compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence; | ||||
|           competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, compName); | ||||
|           let bonusEcaille = (armeCombat && armeCombat.data.magique) ? armeCombat.data.ecaille_efficacite : 0; | ||||
|           rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, Misc.data(combatant.actor).data.carac[competence.data.defaut_carac].value, bonusEcaille) + ")/100)"; | ||||
|         } | ||||
|       } | ||||
|       //console.log("Combatat", c); | ||||
| @@ -142,6 +138,10 @@ export class RdDCombatManager extends Combat { | ||||
|     return this; | ||||
|   }; | ||||
|  | ||||
|   static formuleInitiative(rang, carac, niveau, bonusMalus) { | ||||
|     return `${rang} +( (${RdDCombatManager.calculInitiative(niveau, carac, bonusMalus)} )/100)`; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static calculInitiative(niveau, caracValue, bonusEcaille = 0) { | ||||
|     let base = niveau + Math.floor(caracValue / 2); | ||||
| @@ -150,63 +150,77 @@ export class RdDCombatManager extends Combat { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   /** Retourne une liste triée d'armes avec le split arme1 main / arme 2 main */ | ||||
|   static finalizeArmeList(armes, competences, carac) { | ||||
|   /** Retourne une liste triée d'actions d'armes avec le split arme1 main / arme 2 main */ | ||||
|   static listActionsArmes(armes, competences, carac) { | ||||
|     // Gestion des armes 1/2 mains | ||||
|     let armesEquipe = []; | ||||
|     let actionsArme = []; | ||||
|     for (const arme of armes) { | ||||
|       let armeData = duplicate(Misc.data(arme)); | ||||
|       if (armeData.data.equipe) { | ||||
|         let compData = competences.map(c => Misc.data(c)).find(c => c.name == armeData.data.competence); | ||||
|       let action = duplicate(Misc.data(arme)); | ||||
|       if (action.data.equipe) { | ||||
|         let compData = competences.map(c => Misc.data(c)).find(c => c.name == action.data.competence); | ||||
|  | ||||
|         armesEquipe.push(armeData); | ||||
|         armeData.data.dommagesReels = Number(armeData.data.dommages); | ||||
|         armeData.data.niveau = compData.data.niveau; | ||||
|         armeData.data.initiative = RdDCombatManager.calculInitiative(compData.data.niveau, carac[compData.data.defaut_carac].value); | ||||
|         actionsArme.push(action); | ||||
|         action.action = 'attaque'; | ||||
|         action.data.dommagesReels = Number(action.data.dommages); | ||||
|         action.data.niveau = compData.data.niveau; | ||||
|         action.data.initiative = RdDCombatManager.calculInitiative(compData.data.niveau, carac[compData.data.defaut_carac].value); | ||||
|         // Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence | ||||
|         if (armeData.data.unemain && !armeData.data.deuxmains) { | ||||
|           armeData.data.mainInfo = "(1m)"; | ||||
|         } else if (!armeData.data.unemain && armeData.data.deuxmains) { | ||||
|           armeData.data.mainInfo = "(2m)"; | ||||
|         } else if (armeData.data.unemain && armeData.data.deuxmains) { | ||||
|           armeData.data.mainInfo = "(1m)"; | ||||
|         if (action.data.unemain && !action.data.deuxmains) { | ||||
|           action.data.mainInfo = "(1m)"; | ||||
|         } else if (!action.data.unemain && action.data.deuxmains) { | ||||
|           action.data.mainInfo = "(2m)"; | ||||
|         } else if (action.data.unemain && action.data.deuxmains) { | ||||
|           action.data.mainInfo = "(1m)"; | ||||
|  | ||||
|           const comp2m = armeData.data.competence.replace(" 1 main", " 2 mains"); // Replace ! | ||||
|           const comp2m = action.data.competence.replace(" 1 main", " 2 mains"); // Replace ! | ||||
|           const comp = Misc.data(competences.find(c => c.name == comp2m)); | ||||
|  | ||||
|           const arme2main = duplicate(armeData); | ||||
|           const arme2main = duplicate(action); | ||||
|           arme2main.data.mainInfo = "(2m)"; | ||||
|           arme2main.data.niveau = comp.data.niveau; | ||||
|           arme2main.data.competence = comp2m; | ||||
|           arme2main.data.initiative = RdDCombatManager.calculInitiative(arme2main.data.niveau, carac[comp.data.defaut_carac].value); | ||||
|           armesEquipe.push(arme2main); | ||||
|           const containsSlash = armeData.data.dommages.includes("/"); | ||||
|           actionsArme.push(arme2main); | ||||
|           const containsSlash = action.data.dommages.includes("/"); | ||||
|           if (containsSlash) { | ||||
|             const tableauDegats = armeData.data.dommages.split("/"); | ||||
|             armeData.data.dommagesReels = Number(tableauDegats[0]); | ||||
|             const tableauDegats = action.data.dommages.split("/"); | ||||
|             action.data.dommagesReels = Number(tableauDegats[0]); | ||||
|             arme2main.data.dommagesReels = Number(tableauDegats[1]); | ||||
|           } | ||||
|           else{ | ||||
|             ui.notifications.info("Les dommages de l'arme à 1/2 mains " + armeData.name + " ne sont pas corrects (ie sous la forme X/Y)"); | ||||
|             ui.notifications.info("Les dommages de l'arme à 1/2 mains " + action.name + " ne sont pas corrects (ie sous la forme X/Y)"); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return armesEquipe.sort(Misc.ascending(armeData => armeData.name + (armeData.data.mainInfo ?? ''))); | ||||
|     return actionsArme.sort(Misc.ascending(armeData => armeData.name + (armeData.data.mainInfo ?? ''))); | ||||
|   } | ||||
|  | ||||
|   static listActionsPossessions(actor) { | ||||
|     return RdDCombatManager._indexActions(actor.getPossessions().map(p => | ||||
|       { | ||||
|         return { | ||||
|           name: p.name, | ||||
|           action: 'conjurer', | ||||
|           data: { | ||||
|             competence: p.name, | ||||
|             possessionid: p.data.data.possessionid, | ||||
|           } | ||||
|         } | ||||
|       })); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static buildListeActionsCombat(combatant) { | ||||
|     if (combatant.actor == undefined) { | ||||
|       ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) | ||||
|       return []; | ||||
|   static listActionsCombat(combatant) { | ||||
|     const actor = combatant.actor; | ||||
|     let actions = RdDCombatManager.listActionsPossessions(actor); | ||||
|     if (actions.length>0) { | ||||
|       return actions; | ||||
|     } | ||||
|     const actorData = Misc.data(combatant.actor); | ||||
|     let items = combatant.actor.data.items; | ||||
|     let actions = [] | ||||
|     if (combatant.actor.isCreature()) { | ||||
|     let items = actor.data.items; | ||||
|     if (actor.isCreature()) { | ||||
|       actions = actions.concat(items.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it)) | ||||
|         .map(competence => RdDItemCompetenceCreature.toArme(competence))); | ||||
|         .map(competence => RdDItemCompetenceCreature.toActionArme(competence))); | ||||
|     } else { | ||||
|       // Recupération des items 'arme' | ||||
|       let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it)) | ||||
| @@ -214,14 +228,17 @@ export class RdDCombatManager extends Combat { | ||||
|         .concat(RdDItemArme.mainsNues()); | ||||
|  | ||||
|       let competences = items.filter(it => it.type == 'competence'); | ||||
|       actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actorData.data.carac)); | ||||
|       actions = actions.concat(RdDCombatManager.listActionsArmes(armes, competences, actor.data.data.carac)); | ||||
|  | ||||
|       if (actorData.data.attributs.hautrevant.value) { | ||||
|         actions.push({ name: "Draconic", data: { initOnly: true, competence: "Draconic" } }); | ||||
|       if (actor.data.data.attributs.hautrevant.value) { | ||||
|         actions.push({ name: "Draconic", action: 'haut-reve', data: { initOnly: true, competence: "Draconic" } }); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     actions.push({ name: "Autre action", data: { initOnly: true, competence: "Autre action" } }); | ||||
|     return RdDCombatManager._indexActions(actions); | ||||
|   } | ||||
|  | ||||
|   static _indexActions(actions) { | ||||
|     for (let index = 0; index < actions.length; index++) { | ||||
|       actions[index].index = index; | ||||
|     } | ||||
| @@ -235,15 +252,15 @@ export class RdDCombatManager extends Combat { | ||||
|       let initMissing = game.combat.data.combatants.find(it => !it.initiative); | ||||
|       if (!initMissing) { // Premier round ! | ||||
|         for (let combatant of game.combat.data.combatants) { | ||||
|           let arme = combatant.initiativeData?.arme; | ||||
|           let action = combatant.initiativeData?.arme; | ||||
|           //console.log("Parsed !!!", combatant, initDone, game.combat.current, arme); | ||||
|           if (arme && arme.type == "arme") { | ||||
|           if (action && action.type == "arme") { | ||||
|             for (let initData of premierRoundInit) { | ||||
|               if (arme.data.initpremierround.toLowerCase().includes(initData.pattern)) { | ||||
|               if (Grammar.toLowerCaseNoAccentNoSpace(action.data.initpremierround).includes(initData.pattern)) { | ||||
|                 let msg = `<h4>L'initiative de ${combatant.actor.name} a été modifiée !</h4> | ||||
|                       <hr> | ||||
|                       <div> | ||||
|                         Etant donné son ${arme.name}, son initative pour ce premier round est désormais de ${initData.init}. | ||||
|                         Etant donné son ${action.name}, son initative pour ce premier round est désormais de ${initData.init}. | ||||
|                       </div>` | ||||
|                 ChatMessage.create({ content: msg }); | ||||
|                 game.combat.setInitiative(combatant._id, initData.init); | ||||
| @@ -281,7 +298,7 @@ export class RdDCombatManager extends Combat { | ||||
|     ].concat(options); | ||||
|   } | ||||
|   /* -------------------------------------------- */ | ||||
|   static rollInitiativeCompetence(combatantId, arme) { | ||||
|   static rollInitiativeAction(combatantId, action) { | ||||
|     const combatant = game.combat.combatants.get(combatantId); | ||||
|     if (combatant.actor == undefined) { | ||||
|       ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) | ||||
| @@ -299,34 +316,40 @@ export class RdDCombatManager extends Combat { | ||||
|     } else if (combatant.actor.getSurprise() == "demi") { | ||||
|       initOffset = 0; | ||||
|       initInfo = "Demi Surprise" | ||||
|     } else if (arme.name == "Autre action") { | ||||
|     } else if (action.action == 'conjurer') { | ||||
|       initOffset = 10; | ||||
|       caracForInit = combatant.actor.getReveActuel(); | ||||
|       initInfo = "Possession" | ||||
|     } else if (action.name == 'autre') { | ||||
|       initOffset = 2; | ||||
|       initInfo = "Autre Action" | ||||
|     } else if (arme.name == "Draconic") { | ||||
|     } else if (action.action == 'haut-reve') { | ||||
|       initOffset = 9; | ||||
|       initInfo = "Draconic" | ||||
|     } else { | ||||
|       compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence)); | ||||
|       compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, action.data.competence)); | ||||
|       compNiveau = compData.data.niveau; | ||||
|       initInfo = arme.name + " / " + arme.data.competence; | ||||
|       if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') { | ||||
|         caracForInit = compData.data.carac_value; | ||||
|         if (compData.data.categorie == "lancer") { | ||||
|           initOffset = 7; | ||||
|         } | ||||
|         else { | ||||
|           initOffset = 5; | ||||
|         } | ||||
|       } else { | ||||
|         caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value; | ||||
|         initOffset = RdDCombatManager._baseInitOffset(compData.data.categorie, arme); | ||||
|         initInfo = action.name + " / " + action.data.competence; | ||||
|           | ||||
|         if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') { | ||||
|           caracForInit = compData.data.carac_value; | ||||
|           if (compData.data.categorie == "lancer") { | ||||
|             initOffset = 7; | ||||
|           } | ||||
|           else { | ||||
|             initOffset = 5; | ||||
|           } | ||||
|         } else { | ||||
|           caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value; | ||||
|           initOffset = RdDCombatManager._baseInitOffset(compData.data.categorie, action); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     let malus = combatant.actor.getEtatGeneral(); // Prise en compte état général  | ||||
|     // Cas des créatures et entités vs personnages | ||||
|     let rollFormula = initOffset + "+ ( (" + RdDCombatManager.calculInitiative(compNiveau, caracForInit) + " + " + malus + ") /100)"; | ||||
|     let rollFormula = RdDCombatManager.formuleInitiative(initOffset, caracForInit, compNiveau, malus); | ||||
|     // Garder la trace de l'arme/compétence utilisée pour l'iniative | ||||
|     combatant.initiativeData = { arme: arme } // pour reclasser l'init au round 0 | ||||
|     combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0 | ||||
|     game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo }); | ||||
|   } | ||||
|  | ||||
| @@ -349,16 +372,21 @@ export class RdDCombatManager extends Combat { | ||||
|   static displayInitiativeMenu(html, combatantId) { | ||||
|     console.log("Combatant ; ", combatantId); | ||||
|     const combatant = game.combat.combatants.get(combatantId); | ||||
|     let armesList = RdDCombatManager.buildListeActionsCombat(combatant); | ||||
|     if (! (combatant?.actor) ) { | ||||
|       ui.notifications.warn(`Le combatant ${combatant.name ?? combatantId} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     let actions = RdDCombatManager.listActionsCombat(combatant); | ||||
|  | ||||
|     // Build the relevant submenu | ||||
|     if (armesList) { | ||||
|     if (actions) { | ||||
|       let menuItems = []; | ||||
|       for (let arme of armesList) { | ||||
|       for (let action of actions) { | ||||
|         menuItems.push({ | ||||
|           name: arme.data.competence, | ||||
|           name: action.data.competence, | ||||
|           icon: "<i class='fas fa-dice-d6'></i>", | ||||
|           callback: target => { RdDCombatManager.rollInitiativeCompetence(combatantId, arme) } | ||||
|           callback: target => { RdDCombatManager.rollInitiativeAction(combatantId, action) } | ||||
|         }); | ||||
|       } | ||||
|       new ContextMenu(html, ".directory-list", menuItems).render(); | ||||
|   | ||||
| @@ -276,9 +276,11 @@ export class RdDCommands { | ||||
|           diff = 0; | ||||
|         } | ||||
|         const caracName = params[0]; | ||||
|         const compName = length > 1 ? Misc.join(params.slice(1, length), ' ') : undefined; | ||||
|         for (let actor of actors) { | ||||
|           await actor.rollCaracCompetence(caracName, compName, diff); | ||||
|         let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : undefined; | ||||
|         if (competence) { | ||||
|           for (let actor of actors) { | ||||
|             await actor.rollCaracCompetence(caracName, competence.name, diff); | ||||
|           } | ||||
|         } | ||||
|         return; | ||||
|       } | ||||
|   | ||||
| @@ -85,15 +85,10 @@ export class RdDPossession { | ||||
|       defender: defender, | ||||
|       competence: defender.getDraconicOuPossession(), | ||||
|       selectedCarac: defender.data.data.carac.reve, | ||||
|       forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } } | ||||
|     } | ||||
|     rollData.competence.data.defaut_carac = 'reve-actuel' | ||||
|  | ||||
|     if (rollData.isECNIDefender) { | ||||
|       rollData.competence.data.defaut_carac = "reve" | ||||
|       rollData.forceCarac = { 'reve': { label: "Rêve", value: defender.data.data.carac.reve.value } } | ||||
|     } else { | ||||
|       rollData.competence.data.defaut_carac = 'reve-actuel' | ||||
|       rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } } | ||||
|     } | ||||
|  | ||||
|     const dialog = await RdDRoll.create(defender, rollData, | ||||
|       { | ||||
|   | ||||
| @@ -23,40 +23,63 @@ export class RdDTokenHud { | ||||
|     let token = canvas.tokens.get(tokenId); | ||||
|     let actor = token.actor; | ||||
|     let combatant = game.combat.combatants.find(c => Misc.data(c).tokenId == tokenId); | ||||
|     if (! (combatant?.actor) ) { | ||||
|         ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) | ||||
|         return; | ||||
|     } | ||||
|     app.hasExtension = true; | ||||
|  | ||||
|     let armesList = RdDCombatManager.buildListeActionsCombat(combatant); | ||||
|     let actionsCombat = RdDCombatManager.listActionsCombat(combatant); | ||||
|     const hudData = { | ||||
|       combatant: combatant, armes: armesList, | ||||
|       commandes: [{ name: 'Initiative +1', command: 'inc', value: 0.01 }, { name: 'Initiative -1', command: 'dec', value: -0.01 }] | ||||
|       combatant: combatant, | ||||
|       actions: actionsCombat, | ||||
|       commandes: [ | ||||
|         { name: "Autre action", command: 'autre' }, | ||||
|         { name: 'Initiative +1', command: 'inc', value: 0.01 },  | ||||
|         { name: 'Initiative -1', command: 'dec', value: -0.01 }] | ||||
|     }; | ||||
|  | ||||
|     const controlIconCombat = html.find('.control-icon[data-action=combat]'); | ||||
|     // initiative | ||||
|     await RdDTokenHud._configureSubMenu(controlIconCombat, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', hudData, | ||||
|     await RdDTokenHud._configureSubMenu(controlIconCombat, | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', | ||||
|       hudData, | ||||
|       (event) => { | ||||
|         let initCommand = event.currentTarget.attributes['data-command'].value; | ||||
|         let combatantId = event.currentTarget.attributes['data-combatant-id'].value; | ||||
|         if (!initCommand) { | ||||
|           let armeIndex = event.currentTarget.attributes['data-arme-id'].value; | ||||
|           let arme = armesList[armeIndex]; | ||||
|           RdDCombatManager.rollInitiativeCompetence(combatantId, arme); | ||||
|         } else if (initCommand == 'inc') { | ||||
|           RdDCombatManager.incDecInit(combatantId, 0.01); | ||||
|         } else if (initCommand == 'dec') { | ||||
|           RdDCombatManager.incDecInit(combatantId, -0.01); | ||||
|         } | ||||
|         let initCommand = event.currentTarget.attributes['data-command']?.value; | ||||
|         let combatantId = event.currentTarget.attributes['data-combatant-id']?.value; | ||||
|         if (initCommand) { | ||||
|           RdDTokenHud._initiativeCommand(initCommand, combatantId); | ||||
|         } else { | ||||
|           let index = event.currentTarget.attributes['data-action-index'].value; | ||||
|           let action = actionsCombat[index]; | ||||
|           RdDCombatManager.rollInitiativeAction(combatantId, action); | ||||
|         }  | ||||
|       }); | ||||
|  | ||||
|     const controlIconTarget = html.find('.control-icon[data-action=target]'); | ||||
|     // combat | ||||
|     await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData, | ||||
|       (event) => { | ||||
|         let armeIndex = event.currentTarget.attributes['data-arme-id'].value; | ||||
|         actor.rollArme(armesList[armeIndex]); | ||||
|         const actionIndex = event.currentTarget.attributes['data-action-index']?.value; | ||||
|         const action = actionsCombat[actionIndex]; | ||||
|         if (action.action == 'conjurer') { | ||||
|           actor.conjurerPossession(actor.getPossession(action.data.possessionid)); | ||||
|         } | ||||
|         else { | ||||
|           actor.rollArme(action); | ||||
|         } | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|   static _initiativeCommand(initCommand, combatantId) { | ||||
|     switch (initCommand) { | ||||
|       case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01); | ||||
|       case 'dec': return RdDCombatManager.incDecInit(combatantId, -0.01); | ||||
|       case 'autre': return RdDCombatManager.rollInitiativeAction(combatantId,  | ||||
|         { name: "Autre action", action: 'autre', data: { initOnly: true, competence: "Autre action" } }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async addTokenHudExtensions(app, html, tokenId) { | ||||
|     const controlIconCombat  = html.find('.control-icon[data-action=combat]'); | ||||
|   | ||||
| @@ -17,16 +17,22 @@ | ||||
|         <a class='defense-possession chat-card-button' | ||||
|             data-attackerId='{{attacker.id}}' | ||||
|             data-defenderId='{{defender.id}}' | ||||
|             data-possessionId='{{possession.data.possessionid}}'>Résister à la possession</a> | ||||
|             data-possessionId='{{possession.data.possessionid}}'> | ||||
|             {{#if isECNIDefender}} | ||||
|             Résister à la conjuration | ||||
|             {{else}} | ||||
|             Résister à la possession | ||||
|             {{/if}} | ||||
|         </a> | ||||
|       {{else}} | ||||
|         La Tentative de Possession a échouée ! | ||||
|         La Tentative de {{#if isECNIDefender}}conjuration{{else}}possession{{/if}} a échoué ! | ||||
|       {{/if}} | ||||
|     {{else}} | ||||
|       {{#if rolled.isSuccess}} | ||||
|         La Tentative de Possession a été conjurée ! {{defender.name}} résiste à la tentative de possession. | ||||
|       {{else}} | ||||
|         La Tentative de Possession n'a pas pu être conjurée ! | ||||
|         La tentative de {{#if isECNIDefender}}conjuration a été repoussée{{else}}possession a été conjurée{{/if}}! | ||||
|         {{defender.name}} a résisté. | ||||
|         {{else}} | ||||
|         La tentative de {{#if isECNIDefender}}conjuration a réussi{{else}}possession n'a pas pu être conjurée{{/if}}! | ||||
|       {{/if}} | ||||
|     {{/if}} | ||||
|     <br>Points de Possession: {{possession.ptsPossession}} | ||||
|   | ||||
| @@ -1,10 +1,13 @@ | ||||
| <div class="control-icon rdd-combat "> | ||||
|   <img class="rdd-hud-togglebutton" src="systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg" width="36" height="36" title="Attaque"/> | ||||
|   <div class="rdd-hud-list tokenhudext left"> | ||||
|     {{#each armes as |arme key|}} | ||||
|     {{#unless arme.data.initOnly}} | ||||
|     <div class="control-icon tokenhudicon rdd-hud-menu rdd-attaque" data-combatant-id="{{../combatant.id}}" data-arme-id="{{arme.index}}"  title="{{arme.name}}"> | ||||
|       <label>C:{{arme.name}}  {{arme.data.mainInfo}}</label> | ||||
|     {{#each actions as |action key|}} | ||||
|     {{#unless action.data.initOnly}} | ||||
|     <div class="control-icon tokenhudicon rdd-hud-menu rdd-attaque" | ||||
|         data-combatant-id="{{../combatant.id}}" | ||||
|         data-action-index="{{action.index}}" | ||||
|         title="{{action.name}}"> | ||||
|       <label>{{action.name}}  {{action.data.mainInfo}}</label> | ||||
|     </div> | ||||
|     {{/unless}} | ||||
|     {{/each}} | ||||
|   | ||||
| @@ -1,14 +1,22 @@ | ||||
| <div class="control-icon rdd-initiative "> | ||||
|   <img class="rdd-hud-togglebutton" src="icons/svg/sword.svg" width="36" height="36" title="Initiative" /> | ||||
|   <div class="rdd-hud-list tokenhudext right"> | ||||
|     {{#each armes as |arme key|}} | ||||
|     <div class="control-icon tokenhudicon rdd-hud-menu" data-command="{{arme.command}}" data-combatant-id="{{../combatant.id}}" data-arme-id="{{arme.index}}" title="{{arme.name}}"> | ||||
|       <label>I:{{arme.name}} {{arme.data.mainInfo}}</label> | ||||
|     {{#each actions as |action key|}} | ||||
|     {{log 'action-hud-init' action}} | ||||
|     <div class="control-icon tokenhudicon rdd-hud-menu" | ||||
|         data-combatant-id="{{../combatant.id}}" | ||||
|         data-action-index="{{action.index}}" | ||||
|         title="{{action.name}}"> | ||||
|       <label>init: {{action.name}} {{action.data.mainInfo}}</label> | ||||
|     </div> | ||||
|     {{/each}} | ||||
|     {{#each commandes as |commande key|}} | ||||
|     <div class="control-icon tokenhudicon rdd-hud-menu" data-command="{{commande.command}}" data-combatant-id="{{../combatant.id}}" data-arme-id="{{commande.index}}" title="{{commande.name}}"> | ||||
|       <label>I:{{commande.name}}</label> | ||||
|     <div class="control-icon tokenhudicon rdd-hud-menu" | ||||
|         data-command="{{commande.command}}"  | ||||
|         data-combatant-id="{{../combatant.id}}" | ||||
|         data-action-index="{{commande.index}}" | ||||
|         title="{{commande.name}}"> | ||||
|       <label>{{commande.name}}</label> | ||||
|     </div> | ||||
|     {{/each}}     | ||||
|   </div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user