From c7dfc8682d56162979adb924960efc2898a022c0 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sun, 8 Dec 2024 23:46:22 +0100 Subject: [PATCH] =?UTF-8?q?Support=20de=20personnages=20sans=20comp=C3=A9t?= =?UTF-8?q?ences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Un personnage peut maintenant n'avoir aucune compétence Exemple: les entités invoquées (Kanaillous, ..) n'ont pas besoin d'une liste de compétences sans aucune valeur. Ceci permettrait de supprimer des compétences prohibées. # Conflicts: # module/actor.js # module/actor/base-actor-reve.js --- module/actor-sheet.js | 3 +- module/actor.js | 8 ++--- module/actor/base-actor-reve.js | 53 ++++++++++++++------------------- module/actor/base-actor-sang.js | 2 +- module/item-arme.js | 7 +++-- module/item-competence.js | 30 ++++++------------- module/item.js | 7 +++-- module/item/base-items.js | 20 +++++++++++++ module/misc.js | 8 ++--- module/rdd-combat.js | 13 ++++---- 10 files changed, 78 insertions(+), 73 deletions(-) create mode 100644 module/item/base-items.js diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 3b6a5103..fe6560d7 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -22,7 +22,6 @@ import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire. /* -------------------------------------------- */ /** * Extend the basic ActorSheet with some very simple modifications - * @extends {ActorSheet} */ export class RdDActorSheet extends RdDBaseActorSangSheet { @@ -83,7 +82,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { formData.combat.push(RdDItemArme.corpsACorps(actor)); formData.combat.push(RdDItemArme.empoignade(actor)); - formData.esquives = this.actor.getCompetences("Esquive"); + formData.esquives = this.actor.getCompetencesEsquive() formData.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.system.carac); formData.empoignades = this.actor.getEmpoignades(); diff --git a/module/actor.js b/module/actor.js index bfd82ec0..24530d60 100644 --- a/module/actor.js +++ b/module/actor.js @@ -39,11 +39,12 @@ import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js"; import { RdDItemArme } from "./item-arme.js"; import { RdDCombatManager } from "./rdd-combat.js"; import { RdDItemTete } from "./item/tete.js"; -import { SystemCompendiums } from "./settings/system-compendiums.js"; import { DialogSelect } from "./dialog-select.js"; +import { PAS_DE_DRACONIC, POSSESSION_SANS_DRACONIC } from "./item/base-items.js"; export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] + /* -------------------------------------------- */ /** * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. @@ -153,10 +154,9 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ getDemiReve() { return this.system.reve.tmrpos.coord } getDraconicList() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') } - getBestDraconic() { return foundry.utils.duplicate(this.getDraconicList().sort(Misc.descending(it => it.system.niveau)).find(it => true)) } + getBestDraconic() { return foundry.utils.duplicate([...this.getDraconicList(), PAS_DE_DRACONIC].sort(Misc.descending(it => it.system.niveau)).find(it => true)) } getDraconicOuPossession() { - return [...this.getDraconicList().filter(it => it.system.niveau >= 0), - super.getDraconicOuPossession()] + return [...this.getDraconicList().filter(it => it.system.niveau >= 0), POSSESSION_SANS_DRACONIC] .sort(Misc.descending(it => it.system.niveau)) .find(it => true) } diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index 1d2f1495..01388832 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -1,34 +1,27 @@ -import { ChatUtility } from "../chat-utility.js"; -import { DialogValidationEncaissement } from "../dialog-validation-encaissement.js"; +import { ENTITE_INCARNE, SHOW_DICE, SYSTEM_RDD } from "../constants.js"; import { Grammar } from "../grammar.js"; -import { RdDItemCompetence } from "../item-competence.js"; import { Misc } from "../misc.js"; -import { RdDEmpoignade } from "../rdd-empoignade.js"; import { RdDResolutionTable } from "../rdd-resolution-table.js"; import { RdDEncaisser } from "../rdd-roll-encaisser.js"; import { RdDRoll } from "../rdd-roll.js"; import { RdDUtility } from "../rdd-utility.js"; import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; import { RdDBaseActor } from "./base-actor.js"; -import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; -import { StatusEffects } from "../settings/status-effects.js"; import { ITEM_TYPES } from "../item.js"; -import { Targets } from "../targets.js"; -import { RdDPossession } from "../rdd-possession.js"; -import { RdDCombat, RdDCombatManager } from "../rdd-combat.js"; -import { RdDConfirm } from "../rdd-confirm.js"; -import { ENTITE_INCARNE, SHOW_DICE, SYSTEM_RDD } from "../constants.js"; +import { RdDItemCompetence } from "../item-competence.js"; +import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDItemArme } from "../item-arme.js"; +import { StatusEffects } from "../settings/status-effects.js"; +import { Targets } from "../targets.js"; +import { RdDConfirm } from "../rdd-confirm.js"; import { RdDCarac } from "../rdd-carac.js"; -const POSSESSION_SANS_DRACONIC = { - img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp', - name: 'Sans draconic', - system: { - niveau: 0, - defaut_carac: "reve-actuel", - } -}; +import { ChatUtility } from "../chat-utility.js"; +import { DialogValidationEncaissement } from "../dialog-validation-encaissement.js"; +import { RdDCombat } from "../rdd-combat.js"; +import { RdDEmpoignade } from "../rdd-empoignade.js"; +import { RdDPossession } from "../rdd-possession.js"; +import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, POSSESSION_SANS_DRACONIC } from "../item/base-items.js"; /** * Classe de base pour les acteurs disposant de rêve (donc, pas des objets) @@ -163,24 +156,24 @@ export class RdDBaseActorReve extends RdDBaseActor { } return RdDItemCompetence.findCompetence(this.items, idOrName, options) } - getCompetences(name) { - return RdDItemCompetence.findCompetences(this.items, name) + + getCompetences(name, options = { onMessage: message => { } }) { + return RdDItemCompetence.findCompetences(this.items, name, options) } - getCompetenceCorpsACorps(options = {}) { - return this.getCompetence("Corps à corps", options) + + getCompetenceCorpsACorps(options = { onMessage: message => { } }) { + return this.getCompetence(BASE_CORPS_A_CORPS.name, options) ?? BASE_CORPS_A_CORPS } - getCompetencesEsquive() { - return this.getCompetences("esquive") + + getCompetencesEsquive(options = { onMessage: message => { } }) { + return this.getCompetences(BASE_ESQUIVE.name, options) ?? [BASE_ESQUIVE] } getArmeParade(armeParadeId) { - const item = armeParadeId ? this.getEmbeddedDocument('Item', armeParadeId) : undefined; - return RdDItemArme.getArme(item); + return RdDItemArme.getArme(armeParadeId ? this.getEmbeddedDocument('Item', armeParadeId) : undefined) } - getDraconicOuPossession() { - return POSSESSION_SANS_DRACONIC - } + getDraconicOuPossession() { return POSSESSION_SANS_DRACONIC } getPossession(possessionId) { return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId); diff --git a/module/actor/base-actor-sang.js b/module/actor/base-actor-sang.js index 689273d9..c7392486 100644 --- a/module/actor/base-actor-sang.js +++ b/module/actor/base-actor-sang.js @@ -1,4 +1,4 @@ -import { MAX_ENDURANCE_FATIGUE, RdDUtility } from "../rdd-utility.js"; +import { RdDUtility } from "../rdd-utility.js"; import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; import { STATUSES } from "../settings/status-effects.js"; import { ITEM_TYPES } from "../item.js"; diff --git a/module/item-arme.js b/module/item-arme.js index d4b664e7..c7343564 100644 --- a/module/item-arme.js +++ b/module/item-arme.js @@ -1,6 +1,7 @@ import { Grammar } from "./grammar.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js" import { ITEM_TYPES } from "./item.js"; +import { BASE_CORPS_A_CORPS } from "./item/base-items.js"; import { RdDCombatManager } from "./rdd-combat.js"; const nomCategorieParade = { @@ -236,13 +237,13 @@ export class RdDItemArme extends Item { } static corpsACorps(actor) { - let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } }; + let competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS let melee = actor ? actor.system.carac['melee'].value : 0 return { - _id: competence?.id, + _id: competence.id, name: 'Corps à corps', type: ITEM_TYPES.arme, - img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp', + img: competence.img, system: { initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee), equipe: true, diff --git a/module/item-competence.js b/module/item-competence.js index f09ca6a8..708efb52 100644 --- a/module/item-competence.js +++ b/module/item-competence.js @@ -1,5 +1,6 @@ import { Grammar } from "./grammar.js"; import { RdDItem } from "./item.js"; +import { SANS_COMPETENCE } from "./item/base-items.js"; import { Misc } from "./misc.js"; const competenceTroncs = [["Esquive", "Dague", "Corps à corps"], @@ -137,7 +138,7 @@ export class RdDItemCompetence extends Item { /* -------------------------------------------- */ static computeEconomieXPTronc(competences) { return competenceTroncs.map( - list => list.map(name => RdDItemCompetence.findCompetence(competences, name)) + list => list.map(name => RdDItemCompetence.findCompetence(competences, name, { onMessage: message => { } })) // calcul du coût xp jusqu'au niveau 0 maximum .map(it => RdDItemCompetence.computeDeltaXP(it?.system.base ?? -11, Math.min(it?.system.niveau ?? -11, 0))) .sort(Misc.ascending()) @@ -203,26 +204,12 @@ export class RdDItemCompetence extends Item { } /* -------------------------------------------- */ - static findCompetences(list, name) { - return Misc.findAllLike(name, list, { filter: it => it.isCompetence(), description: 'compétence' }); + static findCompetences(list, name, options = {}) { + options = foundry.utils.mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, { overwrite: false, inplace: false }); + return Misc.findAllLike(name, list, options); } - static sansCompetence() { - return { - name: "Sans compétence", - type: "competence", - img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp", - system: { - niveau: 0, - default_diffLibre: 0, - base: 0, - categorie: "Aucune", - description: "", - descriptionmj: "", - defaut_carac: "", - } - }; - } + static sansCompetence() { return SANS_COMPETENCE } static findFirstItem(list, idOrName, options) { return list.find(it => it.id == idOrName && options.preFilter(it)) @@ -272,8 +259,9 @@ export class RdDItemCompetence extends Item { /* -------------------------------------------- */ static triVisible(competences) { - return competences.filter(it => !it.system.isHidden) - .sort((a, b) => RdDItemCompetence.compare(a, b)) + return competences + ? competences.filter(it => !it.system.isHidden).sort((a, b) => RdDItemCompetence.compare(a, b)) + : [] } static $positionTri(comp) { diff --git a/module/item.js b/module/item.js index ace79129..c3fdae03 100644 --- a/module/item.js +++ b/module/item.js @@ -8,6 +8,7 @@ import { SystemCompendiums } from "./settings/system-compendiums.js"; import { RdDRaretes } from "./item/raretes.js"; import { CATEGORIES_COMPETENCES } from "./item-competence.js"; import { CATEGORIES_COMPETENCES_CREATURES } from "./item-competencecreature.js"; +import { BASE_CORPS_A_CORPS, BASE_ESQUIVE } from "./item/base-items.js"; export const ACTOR_TYPES = { personnage: 'personnage', @@ -244,13 +245,13 @@ export class RdDItem extends Item { isEsquive() { return (this.isCompetence() && this.system.categorie == 'melee' - && Grammar.includesLowerCaseNoAccent(this.name, 'Esquive')); + && Grammar.includesLowerCaseNoAccent(this.name, BASE_ESQUIVE.name)); } isCorpsACorps() { return this.isCompetence() && this.system.categorie == 'melee' - && Grammar.includesLowerCaseNoAccent(this.name, 'Corps à Corps') + && Grammar.includesLowerCaseNoAccent(this.name, BASE_CORPS_A_CORPS.name) } isCompetenceArme() { @@ -602,7 +603,7 @@ export class RdDItem extends Item { if (!other || !this.isInventaire()) { return [false, undefined]; } - if (this.isConteneur()){ + if (this.isConteneur()) { return [false, `Impossible de regrouper des conteneurs, ils ne sont pas empilables`]; } if (this.system.quantite == undefined) { diff --git a/module/item/base-items.js b/module/item/base-items.js new file mode 100644 index 00000000..fd1207e5 --- /dev/null +++ b/module/item/base-items.js @@ -0,0 +1,20 @@ +export const POSSESSION_SANS_DRACONIC = { name: 'Sans draconic', type: 'competence', system: { niveau: 0, defaut_carac: "reve-actuel", }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' } +export const PAS_DE_DRACONIC = { name: 'Pas de draconic', type: 'competence', system: { niveau: -11, defaut_carac: "reve" }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' } +export const BASE_CORPS_A_CORPS = { name: 'Corps à Corps', type: 'competence', system: { niveau: -6, defaut_carac: "melee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' } +export const BASE_ESQUIVE = { name: 'Esquive', type: 'competence', system: { niveau: -6, defaut_carac: "derobee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp' } + +export const SANS_COMPETENCE = { + name: "Sans compétence", + type: 'competence', + system: { + niveau: 0, + default_diffLibre: 0, + base: 0, + categorie: "Aucune", + description: "", + descriptionmj: "", + defaut_carac: "", + }, + img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp" +} + diff --git a/module/misc.js b/module/misc.js index 2829985a..ed0dd0b6 100644 --- a/module/misc.js +++ b/module/misc.js @@ -22,7 +22,7 @@ export class Misc { const isPositiveNumber = value != NaN && value > 0; return isPositiveNumber ? "+" + number : number } - + static modulo(n, m) { return ((n % m) + m) % m; } @@ -165,7 +165,7 @@ export class Misc { static firstConnectedGM() { if (foundry.utils.isNewerVersion(game.release.version, '12.0')) { return game.users.activeGM - } + } return game.users.find(u => u.isGM && u.active); } @@ -197,7 +197,7 @@ export class Misc { } static isFirstOwnerPlayer(document) { - if (!document.testUserPermission){ + if (!document.testUserPermission) { return false } return game.users.find(u => document.testUserPermission(u, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)) == game.user @@ -231,7 +231,7 @@ export class Misc { preFilter: it => true, description: 'valeur', onMessage: m => ui.notifications.info(m) - }, options); + }, options, { overwrite: true, inplace: false }); const subset = this.findAllLike(value, elements, options); if (subset.length == 0) { diff --git a/module/rdd-combat.js b/module/rdd-combat.js index a888f653..f02d162c 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -228,16 +228,19 @@ export class RdDCombatManager extends Combat { static $prepareAttaqueArme(infoAttaque) { const comp = infoAttaque.competences.find(it => Grammar.equalsInsensitive(it.name, infoAttaque.competence)) const arme = infoAttaque.arme; - const attaque = foundry.utils.duplicate(arme); + const attaque = foundry.utils.duplicate(arme) + + const carac = comp?.system.defaut_carac ?? (infoAttaque.infoMain == '(lancer)' ? 'lancer' : infoAttaque.infoMain == '(lancer)' ? 'tir' : 'melee') + const niveau = comp?.system.niveau ?? (infoAttaque.infoMain == '(lancer)' ? -8 : -6) attaque.action = 'attaque'; attaque.system.competence = infoAttaque.competence; attaque.system.dommagesReels = infoAttaque.dommagesReel; attaque.system.infoMain = infoAttaque.infoMain; - attaque.system.niveau = comp.system.niveau; + attaque.system.niveau = niveau - const ajustement = (arme?.parent?.getEtatGeneral() ?? 0) + (arme?.system.magique) ? arme.system.ecaille_efficacite : 0; - attaque.system.initiative = RdDCombatManager.calculInitiative(comp.system.niveau, infoAttaque.carac[comp.system.defaut_carac].value, ajustement); - return attaque; + const ajustement = (arme.parent?.getEtatGeneral() ?? 0) + (arme.system.magique) ? arme.system.ecaille_efficacite : 0 + attaque.system.initiative = RdDCombatManager.calculInitiative(niveau, infoAttaque.carac[carac].value, ajustement) + return attaque } /* -------------------------------------------- */