From 24753bfc2940afc748a7180c15b5ce5c5712ec08 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Tue, 5 May 2026 22:19:12 +0200 Subject: [PATCH] Appel chance RollDialogV2 --- changelog.md | 1 + module/actor.js | 36 ++++++++--------- module/actor/base-actor-reve.js | 15 ++++--- module/moral/apprecier.mjs | 5 +-- module/rdd-combat.js | 2 +- module/roll/chat-roll-result.mjs | 1 + module/roll/roll-constants.mjs | 1 + module/roll/roll-dialog.mjs | 3 +- module/roll/roll-part-comp.mjs | 2 +- module/roll/roll-part-conditions.mjs | 6 +++ module/roll/roll-part-diff.mjs | 2 +- module/roll/roll-type-appel-chance.mjs | 44 +++++++++++++++++++++ module/roll/roll-type.mjs | 2 +- templates/roll/result/chat-appel-chance.hbs | 22 +++++++++++ 14 files changed, 108 insertions(+), 34 deletions(-) create mode 100644 module/roll/roll-type-appel-chance.mjs create mode 100644 templates/roll/result/chat-appel-chance.hbs diff --git a/changelog.md b/changelog.md index 4676bb10..5ab8255a 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ - les dés customisés Dice-So-Nice (heure, rencontres, dé draconique) fonctionnent - Le Haut-rêve est de nouveau proposé dans les options d'initiative - Nouvelle règle optionnelle: choisir si seules les armes équipées sont proposées en combat +- L'appel à la chance utilise la nouvelle fenêtre de jet de dés ## 13.0.37 - Le bonheur des zyglutes d'Illisys diff --git a/module/actor.js b/module/actor.js index 0ce6dca2..18915a20 100644 --- a/module/actor.js +++ b/module/actor.js @@ -47,11 +47,7 @@ import { RdDRollResult } from "./rdd-roll-result.js"; import { RdDInitiative } from "./initiative.mjs"; import RollDialog from "./roll/roll-dialog.mjs"; import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js"; -import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT } from "./roll/roll-constants.mjs"; -import { PART_TACHE } from "./roll/roll-part-tache.mjs"; -import { PART_COMP } from "./roll/roll-part-comp.mjs"; -import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs"; -import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs"; +import { ROLL_TYPE_COMP, ROLL_TYPE_CUISINE, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_SORT, ROLL_TYPE_APPEL_CHANCE, ROLL_TYPE_TACHE } from "./roll/roll-constants.mjs"; import { RdDPossessionV2 } from "./rdd-possession-v2.mjs"; import { Apprecier, MORAL, SITUATION_MORAL } from "./moral/apprecier.mjs"; import { Distance } from "./combat/distance.mjs"; @@ -1877,7 +1873,7 @@ export class RdDActor extends RdDBaseActorSang { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { const rollData = { ids: { actorId: this.id }, - type: { allowed: [PART_COMP], current: PART_COMP }, + type: { allowed: [ROLL_TYPE_COMP], current: ROLL_TYPE_COMP }, selected: { carac: { key: caracName }, comp: { key: compName, forced: options.forced }, @@ -1916,7 +1912,7 @@ export class RdDActor extends RdDBaseActorSang { const rollData = { ids: { actorId: this.id }, selected: { tache: { key: tache.id, forced: options.forced } }, - type: { allowed: [PART_TACHE], current: PART_TACHE } + type: { allowed: [ROLL_TYPE_TACHE], current: ROLL_TYPE_TACHE } } return await RollDialog.create(rollData, options) } @@ -2129,18 +2125,22 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async rollAppelChance(onSuccess = () => { }, onEchec = () => { }) { - await this.openRollDialog({ - name: 'appelChance', - label: 'Appel à la chance', - template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.hbs', - rollData: { selectedCarac: this.getCaracByName('chance-actuelle'), surprise: '' }, - callbacks: [{ action: r => this.$appelChanceResult(r, onSuccess, onEchec) }] - }); + + return await RollDialog.create( + { + ids: { actorId: this.id }, + type: { allowed: [ROLL_TYPE_APPEL_CHANCE], current: ROLL_TYPE_APPEL_CHANCE }, + }, + { + onRollDone: (dialog, roll) => RollDialog.onRollDoneClose(dialog, roll), + callbacks: [ + async roll => await this.$appelChanceResult(roll, onSuccess, onEchec) + ] + }) } /* -------------------------------------------- */ async $appelChanceResult(rollData, onSuccess, onEchec) { - await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-appelchance.hbs') if (rollData.rolled.isSuccess) { await this.setFlag(SYSTEM_RDD, 'utilisationChance', true); await this.chanceActuelleIncDec(-1); @@ -3015,7 +3015,7 @@ export class RdDActor extends RdDBaseActorSang { const rollData = { ids: { actorId: this.id }, selected: { oeuvre: { key: oeuvre.id } }, - type: { allowed: [PART_OEUVRE], current: PART_OEUVRE, }, + type: { allowed: [ROLL_TYPE_OEUVRE], current: ROLL_TYPE_OEUVRE, }, } return await RollDialog.create(rollData) } @@ -3117,7 +3117,7 @@ export class RdDActor extends RdDBaseActorSang { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { const rollData = { ids: { actorId: this.id }, - type: { allowed: [PART_CUISINE], current: PART_CUISINE }, + type: { allowed: [ROLL_TYPE_CUISINE], current: ROLL_TYPE_CUISINE }, selected: { cuisine: { key: recette.id } } @@ -3167,7 +3167,7 @@ export class RdDActor extends RdDBaseActorSang { if (item.getUtilisationCuisine() == 'brut' && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { const rollData = { ids: { actorId: this.id }, - type: { allowed: [PART_CUISINE], current: PART_CUISINE }, + type: { allowed: [ROLL_TYPE_CUISINE], current: ROLL_TYPE_CUISINE }, selected: { cuisine: { key: item.id } } diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index 2f369cea..73644566 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -26,9 +26,8 @@ import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES } fr import { RollDataAjustements } from "../rolldata-ajustements-v1.js"; import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs"; import RollDialog from "../roll/roll-dialog.mjs"; -import { DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE } from "../roll/roll-constants.mjs"; +import { DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP } from "../roll/roll-constants.mjs"; import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js"; -import { PART_COMP } from "../roll/roll-part-comp.mjs"; import { RdDInitiative } from "../initiative.mjs"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"; @@ -317,7 +316,7 @@ export class RdDBaseActorReve extends RdDBaseActor { const competence = this.getCompetence(compName); const rollData = { ids: { actorId: this.id }, - type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP }, + type: { allowed: DEFAULT_ROLL_TYPES, current: ROLL_TYPE_COMP }, selected: { carac: { key: caracName }, comp: { key: competence.name }, @@ -384,7 +383,7 @@ export class RdDBaseActorReve extends RdDBaseActor { ids: { actorId: this.id }, type: { allowed: DEFAULT_ROLL_TYPES, - current: PART_COMP, + current: ROLL_TYPE_COMP, }, selected: { diff: { type: DIFF.DEFAUT } @@ -417,8 +416,8 @@ export class RdDBaseActorReve extends RdDBaseActor { const rollData = { ids: { actorId: this.id }, type: { - allowed: [PART_COMP], - current: PART_COMP, + allowed: [ROLL_TYPE_COMP], + current: ROLL_TYPE_COMP, resistance: resistance }, selected: { @@ -440,8 +439,8 @@ export class RdDBaseActorReve extends RdDBaseActor { const rollData = { ids: { actorId: this.id }, type: { - allowed: options.resistance ? [PART_COMP] : DEFAULT_ROLL_TYPES, - current: PART_COMP, + allowed: options.resistance ? [ROLL_TYPE_COMP] : DEFAULT_ROLL_TYPES, + current: options.resistance ? ROLL_TYPE_COMP : ROLL_TYPE_COMP, resistance: options.resistance }, selected: { diff --git a/module/moral/apprecier.mjs b/module/moral/apprecier.mjs index fa1f0ace..f230a263 100644 --- a/module/moral/apprecier.mjs +++ b/module/moral/apprecier.mjs @@ -4,9 +4,8 @@ import { SANS_COMPETENCE } from "../item/base-items.js" import { Misc } from "../misc.js" import { CARACS } from "../rdd-carac.js" import { RdDUtility } from "../rdd-utility.js" -import { DIFF } from "../roll/roll-constants.mjs" +import { DIFF, ROLL_TYPE_COMP } from "../roll/roll-constants.mjs" import RollDialog from "../roll/roll-dialog.mjs" -import { PART_COMP } from "../roll/roll-part-comp.mjs" export const MORAL = { MALHEUREUX: "malheureux", @@ -134,7 +133,7 @@ export class Apprecier { const competence = (this.appreciation.jetComp && this.appreciation.competence) ? this.appreciation.competence : "" const rollData = { ids: { actorId: this.actor.id }, - type: { allowed: [PART_COMP], current: PART_COMP, appreciation: true }, + type: { allowed: [ROLL_TYPE_COMP], current: ROLL_TYPE_COMP, appreciation: true }, selected: { carac: { key: this.appreciation.carac, forced: true }, comp: { key: competence, forced: true }, diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 5fdbe502..00f3184e 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -644,7 +644,7 @@ export class RdDCombat { opponentId: this.defender.id, opponentTokenId: this.defenderTokenId, }, - type: { allowed: ['attaque'], current: 'attaque' }, + type: { allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE }, selected: {}, passeArme: foundry.utils.randomID(16), } diff --git a/module/roll/chat-roll-result.mjs b/module/roll/chat-roll-result.mjs index a048b5d5..0c2e6bfc 100644 --- a/module/roll/chat-roll-result.mjs +++ b/module/roll/chat-roll-result.mjs @@ -200,6 +200,7 @@ export default class ChatRollResult { const chatMessage = ChatUtility.getChatMessage(event) const savedRoll = this.loadChatMessageRoll(chatMessage) const actor = this.getActiveActor(savedRoll) + Misc.doIfOwner(actor, it => it.rollAppelChance( () => this.onAppelChanceSuccess(savedRoll, chatMessage), () => this.onAppelChanceEchec(savedRoll, chatMessage)) diff --git a/module/roll/roll-constants.mjs b/module/roll/roll-constants.mjs index ac77d16f..686470bf 100644 --- a/module/roll/roll-constants.mjs +++ b/module/roll/roll-constants.mjs @@ -9,6 +9,7 @@ export const ROLL_TYPE_MEDITATION = 'meditation' export const ROLL_TYPE_OEUVRE = 'oeuvre' export const ROLL_TYPE_SORT = 'sort' export const ROLL_TYPE_TACHE = 'tache' +export const ROLL_TYPE_APPEL_CHANCE = 'appel-chance' export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE] export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE] diff --git a/module/roll/roll-dialog.mjs b/module/roll/roll-dialog.mjs index 1253c545..92057480 100644 --- a/module/roll/roll-dialog.mjs +++ b/module/roll/roll-dialog.mjs @@ -50,6 +50,7 @@ import { RollPartResistance } from "./roll-part-resistance.mjs"; import { RollTypePossession } from "./roll-type-possession.mjs"; import { RollPartPossession } from "./roll-part-possession.mjs"; import { RollPartApprecier } from "./roll-part-apprecier.mjs"; +import { RollTypeAppelChance } from "./roll-type-appel-chance.mjs"; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api @@ -65,6 +66,7 @@ export const ALL_ROLL_TYPES = [ new RollTypeCuisine(), new RollTypeOeuvre(), new RollTypeJeu(), + new RollTypeAppelChance(), // new RollTypeResistance ?? // new RollTypeFixedCarac ?? ] @@ -290,7 +292,6 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2 return rollData.type?.allowed ? ROLL_PARTS.filter(p => RollDialog.$isIntersecting(rollData.type.allowed, p.rollTypes)) : ROLL_PARTS - } /** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */ diff --git a/module/roll/roll-part-comp.mjs b/module/roll/roll-part-comp.mjs index 36f2b512..e8c21cc5 100644 --- a/module/roll/roll-part-comp.mjs +++ b/module/roll/roll-part-comp.mjs @@ -27,7 +27,7 @@ export class RollPartComp extends RollPartSelect { const selected = this.getSelected(rollData) const all = this.$getActorComps(rollData) const selectedComp = selected.key - if (selected.forced && selectedComp) { + if (selected.forced && selectedComp!= undefined ) { refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selectedComp)) if (refs.all.length == 0) { if (selected.key && selected.key.length > 0) { diff --git a/module/roll/roll-part-conditions.mjs b/module/roll/roll-part-conditions.mjs index fa0e2df3..0fef733e 100644 --- a/module/roll/roll-part-conditions.mjs +++ b/module/roll/roll-part-conditions.mjs @@ -10,6 +10,11 @@ export class RollPartConditions extends RollPart { settingMin() { return RollPart.settingKey(this, 'min') } settingMax() { return RollPart.settingKey(this, 'max') } + visible(rollData) { + const current = this.getCurrent(rollData) + return !current.hide + } + onReady(rollParts) { game.settings.register(SYSTEM_RDD, this.settingMin(), { @@ -36,6 +41,7 @@ export class RollPartConditions extends RollPart { restore(rollData) { const current = this.getCurrent(rollData) current.value = this.getSaved(rollData)?.value ?? current.value ?? 0 + current.hide = this.getSaved(rollData)?.hide } diff --git a/module/roll/roll-part-diff.mjs b/module/roll/roll-part-diff.mjs index 14689dfb..064d9841 100644 --- a/module/roll/roll-part-diff.mjs +++ b/module/roll/roll-part-diff.mjs @@ -37,7 +37,7 @@ export class RollPartDiff extends RollPart { } const current = this.getCurrent(rollData) /* TODO: affiner les cas où afficher ou non. devrait s'afficher pour les jets basiques (même si pas d'opposant sélectionné)*/ - return Object.values(DIFF).includes(current.type) + return (DIFF.AUCUN !=current.type) && Object.values(DIFF).includes(current.type) } prepareContext(rollData) { diff --git a/module/roll/roll-type-appel-chance.mjs b/module/roll/roll-type-appel-chance.mjs new file mode 100644 index 00000000..20d39fde --- /dev/null +++ b/module/roll/roll-type-appel-chance.mjs @@ -0,0 +1,44 @@ +import { CARACS } from "../rdd-carac.js" +import { DIFF, ROLL_TYPE_APPEL_CHANCE } from "./roll-constants.mjs" +import { RollType } from "./roll-type.mjs" + +const SPECIAL_ROLL_TYPES_DETAILS = { + label: "fait appel à la chance", + icon: `systems/foundryvtt-reve-de-dragon/assets/ui/chance.svg`, + rollData: { + selected: { + carac: { key: CARACS.CHANCE_ACTUELLE, forced: true }, + diff: { value: 0, type: '' }, + comp: { key: '', forced: true }, + conditions: { hide: true } + } + } +} + +export class RollTypeAppelChance extends RollType { + get code() { return ROLL_TYPE_APPEL_CHANCE } + get name() { return `fait appel à la chance` } + get icon() { return `systems/foundryvtt-reve-de-dragon/assets/ui/chance.svg` } + get chatResultTemplate() { return `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-appel-chance.hbs` } + + title(rollData) { + return this.name + } + + setRollDataType(rollData) { + foundry.utils.mergeObject(rollData, { + selected: { + carac: { key: CARACS.CHANCE_ACTUELLE, forced: true }, + diff: { value: 0, type: '' }, + comp: { key: '', forced: true }, + conditions: { hide: true } + } + }) + super.setRollDataType(rollData) + } + + onSelect(rollData) { + this.setDiffType(rollData, DIFF.AUCUN) + } + +} \ No newline at end of file diff --git a/module/roll/roll-type.mjs b/module/roll/roll-type.mjs index ccbd61c3..5d4a6364 100644 --- a/module/roll/roll-type.mjs +++ b/module/roll/roll-type.mjs @@ -14,7 +14,7 @@ export class RollType { return { code: this.code, name: this.name, icon: this.icon, section: 'type', template: this.template, selected: this.isSelected(rollData) } } - prepare(rollData){} + prepare(rollData) {} isAllowed(rollData) { return rollData.type.allowed == undefined || rollData.type.allowed.includes(this.code) } visible(rollData) { return true } title(rollData) { return this.code } diff --git a/templates/roll/result/chat-appel-chance.hbs b/templates/roll/result/chat-appel-chance.hbs new file mode 100644 index 00000000..3dae0c49 --- /dev/null +++ b/templates/roll/result/chat-appel-chance.hbs @@ -0,0 +1,22 @@ +
+
+ + +
+
+ {{active.name}} fait appel à la chance +
+ +
+ {{> 'partial-infojet'}} +
+ +
+ {{#if rolled.isSuccess}} +

Un point de chance a été dépensé, le jet peut être retenté

+ {{else}} +

Pas de dépense de chance

+ {{/if}} +
+ +