Nouvelle fenêtre: attaque/defense

quelques améliorations
préparation pour gérer les messages de résultats en
fonction du type de jet (attaque/compétence/...)

quelques corrections (suppression du filtre de compétences
quand on change de type de jet, astrologie, ..)
This commit is contained in:
2025-09-24 01:23:10 +02:00
parent 1f330c734e
commit d26ab59c51
65 changed files with 381 additions and 350 deletions

View File

@@ -1,18 +1,18 @@
import { Misc } from "../misc.js";
import { RollModeComp } from "./roll-mode-comp.mjs";
import { RollModeTache } from "./roll-mode-tache.mjs";
import { RollModeAttaque } from "./roll-mode-attaque.mjs";
import { RollModeDefense } from "./roll-mode-defense.mjs";
import { RollModeMeditation } from "./roll-mode-meditation.mjs";
import { RollModeSort } from "./roll-mode-sort.mjs";
import { RollModeOeuvre } from "./roll-mode-oeuvre.mjs";
import { RollModeJeu } from "./roll-mode-jeu.mjs";
import { RollTypeComp } from "./roll-type-comp.mjs";
import { RollTypeTache } from "./roll-type-tache.mjs";
import { RollTypeAttaque } from "./roll-type-attaque.mjs";
import { RollTypeDefense } from "./roll-type-defense.mjs";
import { RollTypeMeditation } from "./roll-type-meditation.mjs";
import { RollTypeSort } from "./roll-type-sort.mjs";
import { RollTypeOeuvre } from "./roll-type-oeuvre.mjs";
import { RollTypeJeu } from "./roll-type-jeu.mjs";
import { RollPartAction } from "./roll-part-action.mjs";
import { RollPartActor } from "./roll-part-actor.mjs";
import { RollPartAppelMoral } from "./roll-part-appelmoral.mjs";
import { RollPartAstrologique } from "./roll-part-astrologique.mjs";
import { RollPartCarac } from "./roll-part-carac.mjs";
import { PART_CARAC, RollPartCarac } from "./roll-part-carac.mjs";
import { RollPartCoeur } from "./roll-part-coeur.mjs";
import { PART_COMP, RollPartComp } from "./roll-part-comp.mjs";
import { RollPartConditions } from "./roll-part-conditions.mjs";
@@ -37,23 +37,22 @@ import { RollPartAttaque } from "./roll-part-attaque.mjs";
import { RollPartDefense } from "./roll-part-defense.mjs";
import { RollDialogAdapter } from "./roll-dialog-adapter.mjs";
import { ROLLDIALOG_SECTION } from "./roll-part.mjs";
import { ROLL_MODE_COMP } from "./roll-constants.mjs";
import { ROLL_TYPE_COMP } from "./roll-constants.mjs";
import { RollChatResult } from "./roll-chat-result.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
const doNothing = (dialog) => { }
const ROLL_MODE_TABS = [
new RollModeComp(),
new RollModeTache(),
new RollModeAttaque(),
new RollModeDefense(),
// new RollModeParade??
// new RollModeEsquive??
// new RollModeResistance ??
new RollModeSort(),
new RollModeMeditation(),
new RollModeOeuvre(),
new RollModeJeu(),
const ALL_ROLL_TYPES = [
new RollTypeComp(),
new RollTypeTache(),
new RollTypeAttaque(),
new RollTypeDefense(),
// new RollTypeResistance ??
new RollTypeSort(),
new RollTypeMeditation(),
new RollTypeOeuvre(),
new RollTypeJeu(),
]
const BASIC_PARTS = new RollBasicParts()
@@ -95,7 +94,7 @@ const ROLL_PARTS = [
* @extends {Dialog}
* # Principes
* - une seule fenêtre de dialogue (classe RollDialog)
* - plusieurs modes de fonctionnement (classe RollMode)
* - plusieurs "types"s de fonctionnement (classe RollType)
* - gestion uniforme des modificateurs (classe RollPart)
* - un objet rollData contient les informations liées à un jet de dés
* - un rollData doit pouvoir être "réduit" pour fournir les informations significatives
@@ -106,15 +105,15 @@ const ROLL_PARTS = [
* - TODO: une classe de base RollChatMessage gerera les messages correspondant aux résultats du dés
* - TODO: réfléchir aux messages supplémentaires gérés par RdDCombat ?
*
* ## Modes de fonctionnement - RollMode
* ## Types de fonctionnement - RollType
*
* Un mode de fonctionnement (RollMode) détermine quelles parties (RollPart) de la
* Un type de fonctionnement (RollType) détermine quelles parties (RollPart) de la
* fenêtre RollDialog sont actives, mais aussi quels sont les effets du jet.
*
* - chaque mode de fonctionnement peut impacter les RollPart utilisés, les données
* - chaque type de fonctionnement peut impacter les RollPart utilisés, les données
* attendues et ajoutées au rollData.
* - chaque mode de fonctionnement peut définir le template de ChatMessage correspondant
* - Le mode de fonctionnement détermine aussi quelles sont les effets du jet:
* - chaque type de fonctionnement peut définir le template de ChatMessage correspondant
* - Le type de fonctionnement détermine aussi quelles sont les effets du jet:
* - quelle ChatMessage afficher dans le tchat?
* - en cas d'attaque/de défense, quelles sont les suites à donner?
* - en cas de lancement de sort, réduire les points de rêve
@@ -176,14 +175,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
foundry.applications.handlebars.loadTemplates({
'roll-section': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-section.hbs',
'roll-mode': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-mode.hbs',
'roll-type': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-type.hbs',
'roll-table': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-table.hbs',
'roll-ajustements': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-ajustements.hbs',
'roll-chances': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-chances.hbs',
'roll-button': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-button.hbs',
})
foundry.applications.handlebars.loadTemplates(ROLL_MODE_TABS.map(m => m.template))
foundry.applications.handlebars.loadTemplates(ALL_ROLL_TYPES.map(m => m.template))
foundry.applications.handlebars.loadTemplates(ROLL_PARTS.map(p => p.template))
ROLL_PARTS.forEach(p => p.onReady())
@@ -252,12 +251,12 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
this.rollData = rollData
this.rollOptions = {
callbacks: [
async (actor, r) => await actor.appliquerAjoutExperience(r),
async (actor, r) => await actor.appliquerAppelMoral(r),
async r => await r.active.actor.appliquerAjoutExperience(r),
async r => await r.active.actor.appliquerAppelMoral(r),
...(rollOptions.callbacks ?? [])
],
customChatMessage: rollOptions.customChatMessage,
onRoll: rollOptions.onRoll ?? doNothing
onRollDone: rollOptions.onRollDone ?? doNothing
}
this.$loadParts()
}
@@ -267,17 +266,17 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
const rollData = this.rollData;
rollData.current = rollData.current ?? {}
rollData.selected = rollData.selected ?? {}
rollData.mode = rollData.mode ?? {}
rollData.mode.retry = rollData.mode.retry ?? false
rollData.type = rollData.type ?? {}
rollData.type.retry = rollData.type.retry ?? false
BASIC_PARTS.restore(rollData)
const loadedMode = ROLL_MODE_TABS.find(m => m.code == rollData.mode?.current)?.code
const allowedModes = ROLL_MODE_TABS.filter(m => m.isAllowed(rollData) && m.visible(rollData)).map(m => m.code)
const loadedType = ALL_ROLL_TYPES.find(m => m.code == rollData.type?.current)?.code
const allowedTypes = ALL_ROLL_TYPES.filter(m => m.isAllowed(rollData) && m.visible(rollData)).map(m => m.code)
rollData.mode.allowed = rollData.mode.retry ? [loadedMode] : rollData.mode.allowed ?? ROLL_MODE_TABS.map(m => m.code)
rollData.mode.current = allowedModes.find(m => m == rollData.mode?.current) ?? (allowedModes.length > 0 ? allowedModes[0] : ROLL_MODE_COMP)
rollData.type.allowed = rollData.type.retry ? [loadedType] : rollData.type.allowed ?? ALL_ROLL_TYPES.map(m => m.code)
rollData.type.current = allowedTypes.find(m => m == rollData.type?.current) ?? (allowedTypes.length > 0 ? allowedTypes[0] : ROLL_TYPE_COMP)
this.getSelectedMode().setRollDataMode(rollData)
this.getSelectedType().setRollDataType(rollData)
rollData.refs = this.$prepareRefs(rollData)
rollData.options = rollData.options ?? { showDice: true, rollMode: game.settings.get("core", "rollMode") }
@@ -289,13 +288,17 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
p.loadRefs(rollData)
p.prepareContext(rollData)
})
this.selectMode();
this.selectType();
}
selectMode() {
this.rollData.mode.label = this.getSelectedMode().title(this.rollData)
this.getSelectedMode().setRollDataMode(this.rollData)
this.getSelectedMode().onSelect(this.rollData);
selectType() {
const selectedType = this.getSelectedType();
this.rollData.type.label = selectedType.title(this.rollData)
selectedType.setRollDataType(this.rollData)
selectedType.onSelect(this.rollData)
ROLL_PARTS.find(it => it.code == PART_CARAC).filterCaracs(this.rollData)
ROLL_PARTS.find(it => it.code == PART_COMP).filterComps(this.rollData)
}
$prepareRefs(rollData) {
@@ -326,12 +329,12 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
this.roll()
}
)
const buttonsMode = this.element.querySelectorAll(`button[name="roll-mode"]`)
buttonsMode?.forEach(it => it.addEventListener(
const buttonsType = this.element.querySelectorAll(`button[name="roll-type"]`)
buttonsType?.forEach(it => it.addEventListener(
"click", e => {
e.preventDefault()
this.rollData.mode.current = e.currentTarget.dataset.mode
this.selectMode()
this.rollData.type.current = e.currentTarget.dataset.type
this.selectType()
this.render()
}
))
@@ -352,15 +355,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return await foundry.applications.handlebars.renderTemplate('roll-table', { carac, diff })
}
async _prepareContext() {
const rollData = this.rollData
const modes = ROLL_MODE_TABS.filter(m => m.isAllowed(rollData) && m.visible(rollData))
.map(m => m.toModeData(rollData))
BASIC_PARTS.loadSurprises(this.rollData, this.getSelectedMode().code)
this.setModeTitle()
const types = ALL_ROLL_TYPES.filter(m => m.isAllowed(rollData) && m.visible(rollData))
.map(m => m.toTypeData(rollData))
BASIC_PARTS.loadSurprises(this.rollData, this.getSelectedType().code)
this.rollData.type.label = this.getSelectedType()?.title(this.rollData)
//TOCHECK: set type.label ?
const visibleRollParts = this.getActiveParts()
visibleRollParts.forEach(p => p.applyExternalImpacts(visibleRollParts, rollData))
@@ -374,7 +376,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
const context = await super._prepareContext()
return foundry.utils.mergeObject(
{
modes: modes,
types: types,
templates: templates,
rollData: rollData,
}, context)
@@ -399,12 +401,8 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
.reduce(Misc.sum(), 0)
}
setModeTitle() {
this.rollData.mode.label = this.getSelectedMode()?.title(this.rollData)
}
getSelectedMode() {
return ROLL_MODE_TABS.find(m => m.code == this.rollData.mode.current)
getSelectedType() {
return ALL_ROLL_TYPES.find(m => m.code == this.rollData.type.current)
}
async roll() {
@@ -413,11 +411,13 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
console.info('Roll parts:', this.$saveParts())
const rolled = await this.$rollDice(rollData)
rollData.rolled = rolled
Promise.all(this.rollOptions.callbacks.map(async callback => await callback(rollData.active.actor, rollData)))
Promise.all(this.rollOptions.callbacks.map(async callback => await callback(rollData)))
if (!this.rollOptions.customChatMessage) {
const rollChatResult = new RollChatResult(this.getSelectedType())
await rollChatResult.display(this.rollData)
rollData.active.actor.$onRollCompetence(this.rollData)
}
this.rollOptions.onRoll(this)
this.rollOptions.onRollDone(this)
}