diff --git a/module/actor-sheet.js b/module/actor-sheet.js
index 9080d850..9281bb0f 100644
--- a/module/actor-sheet.js
+++ b/module/actor-sheet.js
@@ -11,7 +11,6 @@ import { RdDBonus } from "./rdd-bonus.js";
import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js";
import { RdDCarac } from "./rdd-carac.js";
-import { RdDItem } from "./item.js";
import { DialogSplitItem } from "./dialog-split-item.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { DialogRepos } from "./dialog-repos.js";
@@ -93,7 +92,7 @@ export class RdDActorSheet extends ActorSheet {
formData.combat = duplicate(formData.armes ?? []);
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.data.carac);
- formData.esquive = RdDItemCompetence.getEsquive(formData.competences);
+ formData.esquives = this.actor.getCompetences("Esquive").map(i => foundry.utils.deepClone(i.data));
formData.combat = RdDCombatManager.finalizeArmeList(formData.combat, formData.competences, formData.data.carac);
this.armesList = formData.combat;
@@ -345,24 +344,16 @@ export class RdDActorSheet extends ActorSheet {
// Roll Weapon1
html.find('.arme-label a').click(async event => {
- let armeName = event.currentTarget.text;
- let compName = event.currentTarget.attributes['data-competence-name'].value;
- let arme = this.actor.data.items.find(it =>
- it.name == armeName &&
- RdDItemArme.isArme(it) &&
- ((compName || it.data.data.competence) == it.data.data.competence)
- );
- if (!arme) {
- arme = { name: armeName, data: { competence: compName } };
- }
+ const li = $(event.currentTarget).parents(".item");
+ let arme = this._getArmeCombat(li);
this.actor.rollArme( duplicate(arme) );
});
// Initiative pour l'arme
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 armeName = event.currentTarget.attributes['data-arme-name'].value;
- let arme = this.armesList.find(a => a.name == armeName);
+ const li = $(event.currentTarget).parents(".item");
+ let arme = this._getArmeCombat(li);
RdDCombatManager.rollInitiativeCompetence(combatant._id, arme);
} else {
ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat.");
@@ -544,6 +535,16 @@ export class RdDActorSheet extends ActorSheet {
}
+ _getArmeCombat(li) {
+ let armeName = li.data("arme-name");
+ let compName = li.data('competence-name');
+ const arme = this.armesList.find(a => a.name == armeName && a.data.competence == compName);
+ if (!arme) {
+ return { name: armeName, data: { competence: compName } };
+ }
+ return arme;
+ }
+
/* -------------------------------------------- */
/** @override */
setPosition(options = {}) {
diff --git a/module/actor.js b/module/actor.js
index 7ec70482..faf7aaf4 100644
--- a/module/actor.js
+++ b/module/actor.js
@@ -313,13 +313,19 @@ export class RdDActor extends Actor {
return Misc.templateData(this).compteurs.surenc?.value ?? 0;
}
/* -------------------------------------------- */
- getCompetence(name) {
- return RdDItemCompetence.findCompetence(this.data.items, name);
+ getCompetence(idOrName, options={}) {
+ return RdDItemCompetence.findCompetence(this.data.items, idOrName, options);
}
+
+ getCompetences(name) {
+ return RdDItemCompetence.findCompetences(this.data.items, name);
+ }
+
/* -------------------------------------------- */
getObjet(id) {
return id ? this.data.items.find(it => it.id == id) : undefined;
}
+
listItemsData(type) {
return this.filterItemsData(it => it.type == type);
}
@@ -329,16 +335,12 @@ export class RdDActor extends Actor {
filterItems(filter) {
return this.data.items.filter(it => filter(Misc.data(it)));
}
- getItemOfType(id, type) {
- if (id && type) {
- let itemById = this.data.items.find(it => it.id == id);
- const itemData = Misc.data(itemById);
- if (itemData.type == type) {
- return itemById;
- }
- }
- return undefined;
+
+ getItemOfType(idOrName, type) {
+ return this.data.items.find(it => it.id == idOrName && it.type == type)
+ ?? Misc.findFirstLike(idOrName, this.data.items,{filter: it => it.type == type, description: type});
}
+
getMonnaie(id) {
return this.getItemOfType(id, 'monnaie');
}
@@ -3077,7 +3079,7 @@ export class RdDActor extends Actor {
case 'chance-actuelle': case 'chance actuelle':
return carac.chance;
}
- let entry = Misc.findFirstLike(name, Object.entries(carac), it => it[1].label, 'caractéristiques');
+ let entry = Misc.findFirstLike(name, Object.entries(carac), {mapper:it => it[1].label, description: 'caractéristique'});
return entry.length>0 ? carac[entry[0]] : undefined;
}
diff --git a/module/item-arme.js b/module/item-arme.js
index f18bb712..b1f1aafa 100644
--- a/module/item-arme.js
+++ b/module/item-arme.js
@@ -171,12 +171,13 @@ export class RdDItemArme extends Item {
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { data: { niveau: -6 } };
let init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, carac['melee'].value);
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: init }));
- armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.data.niveau, initiative: init }));
+ //armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.data.niveau, initiative: init }));
}
static corpsACorps(actorData) {
const corpsACorps = {
name: 'Corps à corps',
+ img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
data: {
equipe: true,
rapide: true,
diff --git a/module/item-competence.js b/module/item-competence.js
index c2355ab1..4a7c246c 100644
--- a/module/item-competence.js
+++ b/module/item-competence.js
@@ -79,18 +79,12 @@ export class RdDItemCompetence extends Item {
return Misc.data(competence)?.data.categorie;
}
static isDraconic(competence) {
- return Misc.data(competence).data.categorie == 'draconic';
+ return Misc.data(competence)?.data.categorie == 'draconic';
}
/* -------------------------------------------- */
static getVoieDraconic(competences, voie) {
- voie = Grammar.toLowerCaseNoAccent(voie);
- return competences.find(it => RdDItemCompetence.isDraconic(it) && Grammar.toLowerCaseNoAccent(Misc.data(it).name).includes(voie));
- }
-
- /* -------------------------------------------- */
- static getEsquive(competences) {
- return { name: 'Esquive', niveau: RdDItemCompetence.findCompetence(competences, 'Esquive')?.data.niveau ?? -6 };
+ return RdDItemCompetence.findCompetence(competences.filter(it => RdDItemCompetence.isDraconic(it) ), voie);
}
/* -------------------------------------------- */
@@ -208,8 +202,22 @@ export class RdDItemCompetence extends Item {
}
/* -------------------------------------------- */
- static findCompetence(list, name) {
- return Misc.findFirstLike(name, list, it => it.name, 'compétences');
+ static findCompetence(list, idOrName, options = {}) {
+ options = mergeObject(options, {
+ filter: it => RdDItemCompetence.isCompetence(it),
+ description: 'compétence',
+ });
+ return list.find(it => it.id == idOrName && RdDItemCompetence.isCompetence(it))
+ ?? Misc.findFirstLike(idOrName, list, options);
+ }
+
+ /* -------------------------------------------- */
+ static findCompetences(list, name) {
+ return Misc.findAllLike(name, list, { filter: it => RdDItemCompetence.isCompetence(it), description: 'compétence' });
+ }
+
+ static isCompetence(item) {
+ return item.type == 'competence' || item.type == 'competencecreature';
}
/* -------------------------------------------- */
diff --git a/module/misc.js b/module/misc.js
index 2f4b106d..f6e0c7f1 100644
--- a/module/misc.js
+++ b/module/misc.js
@@ -134,33 +134,57 @@ export class Misc {
/* -------------------------------------------- */
static findPlayer(name) {
- return Misc.findFirstLike(name, game.users, it=>it.name,'joueurs');
+ return Misc.findFirstLike(name, game.users, { description: 'joueur' });
}
/* -------------------------------------------- */
- static findActor(name, actors = game.actors, description= 'acteurs') {
- return Misc.findFirstLike(name, actors, it=>it.name, description);
+ static findActor(name, actors = game.actors) {
+ return Misc.findFirstLike(name, actors, { description: 'acteur' });
}
/* -------------------------------------------- */
- static findFirstLike(value, elements, mapper = it=>it.name, description = 'valeurs') {
- if (!value) {
- return undefined;
- }
- value = Grammar.toLowerCaseNoAccent(value);
- const subset = elements.filter(it => Grammar.toLowerCaseNoAccent(mapper(it)).includes(value));
+ static findFirstLike(value, elements, options = {}) {
+ options = mergeObject({
+ mapper: it => it.name,
+ preFilter: it => true,
+ description: 'valeur',
+ onMessage: m => ui.notifications.info(m)
+ }, options);
+
+ const subset = this.findAllLike(value, elements, options);
if (subset.length == 0) {
- ui.notifications.info(`Pas de ${description} correspondant à ${value}`);
- return undefined;
+ return undefined
}
- let single = subset.find(it => Grammar.toLowerCaseNoAccent(mapper(it)) == value);
+ if (subset.length == 1) {
+ return subset[0]
+ }
+ let single = subset.find(it => Grammar.toLowerCaseNoAccent(options.mapper(it)) == Grammar.toLowerCaseNoAccent(value));
if (!single) {
single = subset[0];
- if (subset.length > 1) {
- const choices = subset.map(it => mapper(it)).reduce((a, b) => `${a}
${b}`);
- ui.notifications.info(`Plusieurs choix de ${description} possibles:
${choices}
Le premier sera choisi: ${mapper(single)}`);
- }
+ const choices = subset.map(it => options.mapper(it)).reduce((a, b) => `${a}
${b}`);
+ options.info(`Plusieurs choix de ${options.description}s possibles:
${choices}
Le premier sera choisi: ${mapToValue(single)}`);
}
return single;
}
+
+ static findAllLike(value, elements, options = {}) {
+ options = mergeObject({
+ mapper: it => it.name,
+ preFilter: it => true,
+ description: 'valeur',
+ onMessage: m => ui.notifications.info(m)
+ }, options);
+
+ if (!value) {
+ options.onMessage(`Pas de ${options.description} correspondant à une valeur vide`);
+ return [];
+ }
+ value = Grammar.toLowerCaseNoAccent(value);
+ const subset = elements.filter(options.preFilter)
+ .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it)).includes(value));
+ if (subset.length == 0) {
+ options.onMessage(`Pas de ${options.description} correspondant à ${value}`);
+ }
+ return subset;
+ }
}
\ No newline at end of file
diff --git a/module/rdd-combat.js b/module/rdd-combat.js
index facb5b39..4fb9e504 100644
--- a/module/rdd-combat.js
+++ b/module/rdd-combat.js
@@ -151,11 +151,12 @@ export class RdDCombatManager extends Combat {
// Gestion des armes 1/2 mains
let armesEquipe = [];
for (const arme of armes) {
- let armeData = Misc.data(arme);
+ 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);
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);
// Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence
@@ -165,14 +166,25 @@ export class RdDCombatManager extends Combat {
armeData.data.mainInfo = "(2m)";
} else if (armeData.data.unemain && armeData.data.deuxmains) {
armeData.data.mainInfo = "(1m)";
- let arme2main = duplicate(armeData);
+
+ const comp2m = armeData.data.competence.replace(" 1 main", " 2 mains"); // Replace !
+ const comp = Misc.data(competences.find(c => c.name == comp2m));
+
+ const arme2main = duplicate(armeData);
arme2main.data.mainInfo = "(2m)";
- arme2main.data.dommages = arme2main.data.dommages.split("/")[1]; // Existence temporaire uniquement dans la liste des armes, donc OK
- arme2main.data.competence = arme2main.data.competence.replace(" 1 main", " 2 mains"); // Replace !
- let comp = Misc.data(competences.find(c => c.name == arme2main.data.competence));
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("/");
+ if (containsSlash) {
+ const tableauDegats = armeData.data.dommages.split("/");
+ armeData.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)");
+ }
}
}
}
@@ -194,8 +206,8 @@ export class RdDCombatManager extends Combat {
} else {
// Recupération des items 'arme'
let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it))
- .concat(RdDItemArme.mainsNues())
- .concat(RdDItemArme.empoignade());
+ //.concat(RdDItemArme.empoignade())
+ .concat(RdDItemArme.mainsNues());
let competences = items.filter(it => it.type == 'competence');
actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actorData.data.carac));
@@ -614,11 +626,13 @@ export class RdDCombat {
const defenderTokenId = event.currentTarget.attributes['data-defenderTokenId']?.value;
const armeParadeId = event.currentTarget.attributes['data-armeid']?.value;
+ const competence = event.currentTarget.attributes['data-competence']?.value;
+ const compId = event.currentTarget.attributes['data-compid']?.value;
switch (button) {
case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value);
- case '#parer-button': return this.parade(attackerRoll, armeParadeId);
- case '#esquiver-button': return this.esquive(attackerRoll);
+ case '#parer-button': return this.parade(attackerRoll, armeParadeId, competence);
+ case '#esquiver-button': return this.esquive(attackerRoll, compId, competence);
case '#encaisser-button': return this.encaisser(attackerRoll, defenderTokenId);
case '#echec-total-attaque': return this._onEchecTotal(attackerRoll);
@@ -860,7 +874,7 @@ export class RdDCombat {
await this._sendMessageDefense(attackerRoll, defenderRoll);
}
}
-
+
/* -------------------------------------------- */
isPossession( attackerRoll) {
return attackerRoll.selectedCarac.label.toLowerCase() == 'possession';
@@ -876,18 +890,18 @@ export class RdDCombat {
}
// # utilisation esquive
- const esquive = Misc.data(this.defender.getCompetence("esquive"));
- const corpsACorps = Misc.data(this.defender.getCompetence("Corps à corps"));
- const esquiveUsage = esquive ? this.defender.getItemUse(esquive._id) : 0;
+ const corpsACorps = Misc.data(this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) }));
+ const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) }).map(c => Misc.data(c)));
+ esquives.forEach(e => e.usages = e?.id ? this.defender.getItemUse(e.id) : 0);
const paramChatDefense = {
passeArme: attackerRoll.passeArme,
essais: attackerRoll.essais,
- isPossession: this.isPossession( attackerRoll),
+ isPossession: this.isPossession(attackerRoll),
defender: Misc.data(this.defender),
attacker: Misc.data(this.attacker),
attackerId: this.attackerId,
- esquiveUsage: esquiveUsage,
+ esquives: esquives,
defenderTokenId: this.defenderTokenId,
mainsNues: attackerRoll.dmg.mortalite != 'mortel' && corpsACorps,
armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme),
@@ -1002,12 +1016,12 @@ export class RdDCombat {
}
/* -------------------------------------------- */
- async parade(attackerRoll, armeParadeId) {
+ async parade(attackerRoll, armeParadeId, competence) {
let arme = this.defender.getArmeParade(armeParadeId);
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
- let rollData = this._prepareParade(attackerRoll, arme);
+ let rollData = this._prepareParade(attackerRoll, arme, competence);
const dialog = await RdDRoll.create(this.defender, rollData,
{
@@ -1030,20 +1044,16 @@ export class RdDCombat {
}
/* -------------------------------------------- */
- _prepareParade(attackerRoll, armeParade) {
- const compName = armeParade.data.competence;
- const armeAttaque = attackerRoll.arme;
- const parade = Misc.data(this.defender.getCompetence(compName));
-
+ _prepareParade(attackerRoll, armeParade, competenceParade) {
let defenderRoll = {
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
- competence: parade,
+ competence: Misc.data(this.defender.getCompetence(competenceParade)),
arme: armeParade,
surprise: this.defender.getSurprise(true),
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(armeAttaque, armeParade),
- needResist: RdDItemArme.needArmeResist(armeAttaque, armeParade),
+ needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
carac: Misc.templateData(this.defender).carac,
show: {}
};
@@ -1089,10 +1099,10 @@ export class RdDCombat {
}
/* -------------------------------------------- */
- async esquive(attackerRoll) {
- const esquive = Misc.data(this.defender.getCompetence("esquive"));
+ async esquive(attackerRoll, compId, compName) {
+ const esquive = Misc.data(this.defender.getCompetence(compId) ?? this.defender.getCompetence(compName));
if (esquive == undefined) {
- ui.notifications.error(this.defender.name + " n'a pas de compétence 'esquive'");
+ ui.notifications.error(this.defender.name + " n'a pas de compétence " + compName);
return;
}
console.log("RdDCombat.esquive >>>", attackerRoll, esquive);
diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html
index cc3d4777..fc36ed3b 100644
--- a/templates/actor-sheet.html
+++ b/templates/actor-sheet.html
@@ -274,21 +274,38 @@
+dom
{{#each combat as |arme key|}}
-