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

@@ -424,7 +424,7 @@ select,
.system-foundryvtt-reve-de-dragon .roll-dialog {
font-family: CaslonAntique;
display: grid;
grid-template-areas: "header header header header header header header" "action action action action action action action" "mode separation separation separation separation separation separation" "mode carac carac carac comp comp resume" "mode choix choix choix choix choix modifiers" "mode resolution resolution resolution resolution resolution modifiers" "mode chances chances chances chances chances buttons" "footer footer footer footer footer footer footer";
grid-template-areas: "header header header header header header header" "action action action action action action action" "type separation separation separation separation separation separation" "type carac carac carac comp comp resume" "type choix choix choix choix choix modifiers" "type resolution resolution resolution resolution resolution modifiers" "type chances chances chances chances chances buttons" "footer footer footer footer footer footer footer";
grid-template-columns: 2rem 1rem 1fr 1fr 2fr 2fr 3fr;
gap: 0.2rem;
}
@@ -461,26 +461,26 @@ select,
.system-foundryvtt-reve-de-dragon .roll-dialog roll-buttons {
grid-area: buttons;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode {
grid-area: mode;
.system-foundryvtt-reve-de-dragon .roll-dialog roll-type {
grid-area: type;
display: flex;
flex-direction: column;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button[data-checked="true"],
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button[data-checked="true"] {
.system-foundryvtt-reve-de-dragon .roll-dialog roll-type button[data-checked="true"] {
background-color: var(--color-text-selection-bg);
color: var(--color-controls);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button[data-checked="true"] i,
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button[data-checked="true"] i {
.system-foundryvtt-reve-de-dragon .roll-dialog roll-type button[data-checked="true"] i {
filter: invert(0.8);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button[data-checked="true"] img,
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button[data-checked="true"] img {
.system-foundryvtt-reve-de-dragon .roll-dialog roll-type button[data-checked="true"] img {
filter: invert(0.2);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button,
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button {
.system-foundryvtt-reve-de-dragon .roll-dialog roll-type button {
height: 1.8rem;
width: 1.8rem;
gap: 0.5rem;
@@ -489,11 +489,11 @@ select,
color: var(--color-controls);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button i,
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button i {
.system-foundryvtt-reve-de-dragon .roll-dialog roll-type button i {
filter: invert(0.2);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button img,
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button img {
.system-foundryvtt-reve-de-dragon .roll-dialog roll-type button img {
filter: invert(0.8);
}
.system-foundryvtt-reve-de-dragon .roll-dialog :is(roll-carac, roll-comp) {

View File

@@ -4,11 +4,11 @@
grid-template-areas:
"header header header header header header header"
"action action action action action action action"
"mode separation separation separation separation separation separation"
"mode carac carac carac comp comp resume"
"mode choix choix choix choix choix modifiers"
"mode resolution resolution resolution resolution resolution modifiers"
"mode chances chances chances chances chances buttons"
"type separation separation separation separation separation separation"
"type carac carac carac comp comp resume"
"type choix choix choix choix choix modifiers"
"type resolution resolution resolution resolution resolution modifiers"
"type chances chances chances chances chances buttons"
"footer footer footer footer footer footer footer";
grid-template-columns: 2rem 1rem 1fr 1fr 2fr 2fr 3fr;
gap: 0.2rem;
@@ -27,13 +27,13 @@
roll-resume { grid-area: resume; }
roll-buttons { grid-area: buttons; }
roll-mode {
grid-area: mode;
roll-type {
grid-area: type;
display: flex;
flex-direction: column;
}
roll-conditions roll-section[name="rollmode"],
roll-mode {
roll-type {
button[data-checked="true"] {
background-color: var(--color-text-selection-bg);
color: var(--color-controls);

View File

@@ -3053,11 +3053,11 @@ export class RdDActor extends RdDBaseActorSang {
const oeuvre = this.items.get(oeuvreId)
const rollData = {
title: `Interpretation de ${oeuvre.name} par ${this.name}`,
mode: {
allowed: ["oeuvre"]
type: {
allowed: ["oeuvre"],
current: "oeuvre",
},
selected: {
mode: "oeuvre",
oeuvre: { key: oeuvre.id },
},
ids: {
@@ -3065,9 +3065,9 @@ export class RdDActor extends RdDBaseActorSang {
}
}
await RollDialog.create(rollData, {
onRoll: (dialog) => {
this._onCloseRollDialog(),
dialog.close()
onRollDone: (dialog) => {
this._onCloseRollDialog()
dialog.close()
},
customChatMessage: true,
callbacks: [callbackAction]

View File

@@ -19,7 +19,7 @@ import RollDialog from "./roll/roll-dialog.mjs";
import { PART_DEFENSE } from "./roll/roll-part-defense.mjs";
import { PART_ATTAQUE } from "./roll/roll-part-attaque.mjs";
import { RollDialogAdapter } from "./roll/roll-dialog-adapter.mjs";
import { ROLL_MODE_ATTAQUE, ROLL_MODE_DEFENSE } from "./roll/roll-constants.mjs";
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
/* -------------------------------------------- */
const premierRoundInit = [
@@ -565,7 +565,7 @@ export class RdDCombat {
// TODO: en cas de demi-surprise en défense, pas de changement à la règle de base
return rollData.rolled.isETotal
}
if (rollData.mode == ROLL_MODE_ATTAQUE && rollData.surprise == 'demi'){
if (rollData.mode == ROLL_TYPE_ATTAQUE && rollData.surprise == 'demi') {
// échec normal à l'attaque en demi surprise
return rollData.rolled.isEchec && rollData.rolled.code != 'notSign'
}
@@ -702,7 +702,7 @@ export class RdDCombat {
/* -------------------------------------------- */
_prepareAttaque(competence, arme) {
let rollData = {
mode: ROLL_MODE_ATTAQUE,
mode: ROLL_TYPE_ATTAQUE,
alias: this.attacker?.getAlias(),
passeArme: foundry.utils.randomID(16),
mortalite: arme?.system.mortalite,
@@ -979,25 +979,20 @@ export class RdDCombat {
opponentTokenId: this.attackerTokenId,
opponentId: this.attackerId,
},
mode: {
allowed: ['defense'],
current: 'defense'
},
type: { allowed: ['defense'], current: 'defense' },
attaque: RollDialogAdapter.mapActionAttaque(attackerRoll),
passeArme: attackerRoll.passeArme,
}
await RollDialog.create(rollData, {
onRoll: (dialog) => {
dialog.close()
},
onRollDone: (dialog) => { dialog.close() },
customChatMessage: true,
callbacks: [async (actor, rd) => {
this.removeChatMessageActionsPasseArme(rd.passeArme)
callbacks: [async (roll) => {
this.removeChatMessageActionsPasseArme(roll.passeArme)
// defense: esquive / arme de parade / competence de défense
if (!RdDCombat.isParticuliere(rd))
await rd.active.actor.incDecItemUse(rd.current[PART_DEFENSE].defense?.id,)
await this._onDefense(rd)
if (!RdDCombat.isParticuliere(roll))
await roll.active.actor.incDecItemUse(roll.current[PART_DEFENSE].defense?.id,)
await this._onDefense(roll)
}]
})
}
@@ -1006,7 +1001,7 @@ export class RdDCombat {
/* -------------------------------------------- */
_prepareParade(attackerRoll, armeParade, competenceParade) {
let defenderRoll = {
mode: ROLL_MODE_DEFENSE,
mode: ROLL_TYPE_DEFENSE,
alias: this.defender?.getAlias(),
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
@@ -1037,7 +1032,7 @@ export class RdDCombat {
}
}
else {
await this._onDefenseEchec(rollData)
await this._onDefenseEchec(dialog, rollData)
}
}
@@ -1155,7 +1150,7 @@ export class RdDCombat {
/* -------------------------------------------- */
_prepareEsquive(attackerRoll, competence) {
let rollData = {
mode: ROLL_MODE_DEFENSE,
mode: ROLL_TYPE_DEFENSE,
alias: this.defender.getAlias(),
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,

View File

@@ -1,6 +1,6 @@
import { ActorToken } from "../actor-token.mjs"
import { StatusEffects } from "../settings/status-effects.js"
import { ROLL_MODE_ATTAQUE, ROLL_MODE_DEFENSE } from "./roll-constants.mjs"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { PART_DEFENSE } from "./roll-part-defense.mjs"
@@ -10,14 +10,14 @@ export class RollBasicParts {
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
rollData.active = RollBasicParts.$getActor(rollData)
rollData.opponent = RollBasicParts.$getOpponent(rollData)
if (rollData.mode.opposed == undefined) {
rollData.mode.opposed = rollData.opponent != null
if (rollData.type.opposed == undefined) {
rollData.type.opposed = rollData.opponent != null
}
}
loadSurprises(rollData, mode) {
if (!rollData.mode.passif) {
this.loadSurprise(rollData.active, this.getForceRequiseActiveActor(rollData, mode))
loadSurprises(rollData, type) {
if (!rollData.type.passif) {
this.loadSurprise(rollData.active, this.getForceRequiseActiveActor(rollData, type))
this.loadSurprise(rollData.opponent, 0)
}
}
@@ -30,10 +30,10 @@ export class RollBasicParts {
}
}
getForceRequiseActiveActor(rollData, mode) {
switch (mode) {
case ROLL_MODE_ATTAQUE: return rollData.current[PART_ATTAQUE].attaque.forceRequise
case ROLL_MODE_DEFENSE: return rollData.current[PART_DEFENSE].forceRequise
getForceRequiseActiveActor(rollData, type) {
switch (type) {
case ROLL_TYPE_ATTAQUE: return rollData.current[PART_ATTAQUE].attaque.forceRequise
case ROLL_TYPE_DEFENSE: return rollData.current[PART_DEFENSE].forceRequise
default: return 0
}
}
@@ -41,15 +41,15 @@ export class RollBasicParts {
initFrom(rollData) {
return {
selected: {},
mode: {
current: rollData.mode.current
type: {
current: rollData.type.current
},
ids: {
sceneId: rollData.ids.sceneId,
actorId: rollData.active.id,
actorTokenId: rollData.active.tokenId,
opponentId: rollData.mode.opposed ? rollData.opponent.id : undefined,
opponentTokenId: rollData.mode.opposed ? rollData.opponent.tokenId : undefined,
opponentId: rollData.type.opposed ? rollData.opponent.id : undefined,
opponentTokenId: rollData.type.opposed ? rollData.opponent.tokenId : undefined,
}
}
}

View File

@@ -0,0 +1,15 @@
export class RollChatResult {
constructor(rollType) {
this.rollType = rollType
}
async display(rollData) {
const template = this.rollType.chatResultTemplate()
const chatContent = await renderTemplate(template, rollData)
ChatMessage.create({
whisper: ChatUtility.getOwners(this),
content: chatContent
})
}
}

View File

@@ -1,14 +1,14 @@
export const ROLL_MODE_ATTAQUE = 'attaque'
export const ROLL_MODE_COMP = 'comp'
export const ROLL_MODE_DEFENSE = 'defense'
export const ROLL_MODE_JEU = 'jeu'
export const ROLL_MODE_MEDITATION = 'meditation'
export const ROLL_MODE_OEUVRE = 'oeuvre'
export const ROLL_MODE_SORT = 'sort'
export const ROLL_MODE_TACHE = 'tache'
export const ROLL_TYPE_ATTAQUE = 'attaque'
export const ROLL_TYPE_COMP = 'comp'
export const ROLL_TYPE_DEFENSE = 'defense'
export const ROLL_TYPE_JEU = 'jeu'
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 DIFF_MODE = {
export const DIFF = {
LIBRE: 'libre',
ATTAQUE: 'attaque',
IMPOSEE: 'imposee',
@@ -17,12 +17,12 @@ export const DIFF_MODE = {
AUCUN: 'aucun'
}
export const DIFF_MODES = {
[DIFF_MODE.LIBRE]: { key: DIFF_MODE.LIBRE, label: "Difficulté libre", libre: true, visible: true, max: 0 },
[DIFF_MODE.ATTAQUE]: { key: DIFF_MODE.ATTAQUE, label: "Difficulté d'attaque", libre: true, visible: true, max: 0 },
[DIFF_MODE.IMPOSEE]: { key: DIFF_MODE.IMPOSEE, label: "Diffficulté imposée", libre: false, visible: true, max: 0 },
[DIFF_MODE.DEFENSE]: { key: DIFF_MODE.DEFENSE, label: "Diffficulté défense", libre: false, visible: true, max: 0 },
[DIFF_MODE.DEFAUT]: { key: DIFF_MODE.DEFAUT, label: "Difficulté", libre: true, visible: true, max: 5 },
[DIFF_MODE.AUCUN]: { key: DIFF_MODE.AUCUN, label: "", libre: false, visible: false, max: 0 },
export const DIFFS = {
[DIFF.LIBRE]: { key: DIFF.LIBRE, label: "Difficulté libre", libre: true, visible: true, max: 0 },
[DIFF.ATTAQUE]: { key: DIFF.ATTAQUE, label: "Difficulté d'attaque", libre: true, visible: true, max: 0 },
[DIFF.IMPOSEE]: { key: DIFF.IMPOSEE, label: "Diffficulté imposée", libre: false, visible: true, max: 0 },
[DIFF.DEFENSE]: { key: DIFF.DEFENSE, label: "Diffficulté défense", libre: false, visible: true, max: 0 },
[DIFF.DEFAUT]: { key: DIFF.DEFAUT, label: "Difficulté", libre: true, visible: true, max: 5 },
[DIFF.AUCUN]: { key: DIFF.AUCUN, label: "", libre: false, visible: false, max: 0 },
}

View File

@@ -6,7 +6,7 @@ import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
import { PART_OEUVRE } from "./roll-part-oeuvre.mjs";
import { RdDItemArme } from "../item/arme.js";
import { RdDBonus } from "../rdd-bonus.js";
import { ROLL_MODE_ATTAQUE } from "./roll-constants.mjs";
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs";
/* -------------------------------------------- */
export class RollDialogAdapter {
@@ -62,7 +62,7 @@ export class RollDialogAdapter {
const compKey = rollData.current.comp?.key
if (compKey) {
rollData.competence = rollData.refs[PART_COMP].all.find(it => it.key == compKey)?.comp
rollData.jetResistance = rollData.mode.jetResistance
rollData.jetResistance = rollData.type.jetResistance
}
const oeuvreKey = rollData.current.oeuvre?.key
if (oeuvreKey) {

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)
}

View File

@@ -1,13 +0,0 @@
import { DIFF_MODE, ROLL_MODE_ATTAQUE } from "./roll-constants.mjs"
import { RollMode } from "./roll-mode.mjs"
export class RollModeAttaque extends RollMode {
get code() { return ROLL_MODE_ATTAQUE }
get name() { return `Attaquer` }
title(rollData) { return `attaque` }
onSelect(rollData) {
this.setDiffMode(rollData, DIFF_MODE.ATTAQUE)
}
}

View File

@@ -1,9 +0,0 @@
import { ROLL_MODE_COMP } from "./roll-constants.mjs"
import { RollMode } from "./roll-mode.mjs"
export class RollModeComp extends RollMode {
get code() { return ROLL_MODE_COMP }
get name() { return `Jet de caractéristique / compétence` }
title(rollData) { return `fait un jet ${rollData.mode.opposed ? ' contre ' : ''}` }
}

View File

@@ -1,17 +0,0 @@
import { DIFF_MODE, ROLL_MODE_DEFENSE } from "./roll-constants.mjs"
import { RollMode } from "./roll-mode.mjs"
export class RollModeDefense extends RollMode {
get code() { return ROLL_MODE_DEFENSE }
get name() { return `Se défendre` }
title(rollData) { return `se défend${rollData.opponent ? ' de' : ''}` }
getOpponent(rollData) {
return rollData.attacker
}
onSelect(rollData) {
this.setDiffMode(rollData, DIFF_MODE.DEFENSE)
}
}

View File

@@ -1,15 +0,0 @@
import { DIFF_MODE, ROLL_MODE_SORT } from "./roll-constants.mjs"
import { RollMode } from "./roll-mode.mjs"
import { PART_SORT } from "./roll-part-sort.mjs"
export class RollModeSort extends RollMode {
get code() { return ROLL_MODE_SORT }
get name() { return `lancer un sort` }
visible(rollData) { return rollData.active.actor.isHautRevant() }
title(rollData) { return `lance le sort:` }
onSelect(rollData) {
this.setDiffMode(rollData, DIFF_MODE.AUCUN)
}
}

View File

@@ -1,54 +0,0 @@
import { DIFF_MODE } from "./roll-constants.mjs"
import { PART_DIFF } from "./roll-part-diff.mjs"
const DEFAULT_DIFF_MODES = [DIFF_MODE.LIBRE, DIFF_MODE.IMPOSEE, DIFF_MODE.DEFAUT]
export class RollMode {
onReady() { }
get code() { throw new Error(`Pas de code défini pour ${this}`) }
get name() { return this.code }
get icon() { return `systems/foundryvtt-reve-de-dragon/assets/actions/${this.code}.svg` }
toModeData(rollData) {
return { code: this.code, name: this.name, icon: this.icon, section: 'mode', template: this.template, selected: this.isSelected(rollData) }
}
isAllowed(rollData) { return rollData.mode.allowed == undefined || rollData.mode.allowed.includes(this.code) }
visible(rollData) { return true }
title(rollData) { return this.code }
isSelected(rollData) { return rollData.mode.current == this.code }
setRollDataMode(rollData) {
rollData.mode.opposed = rollData.opponent != undefined
rollData.mode.resistance = false /** TODO */
}
onSelect(rollData) {
const mode = [
rollData.current[PART_DIFF].mode,
this.modeFromOpponents(rollData),
rollData.selected[PART_DIFF].mode].find(m => DEFAULT_DIFF_MODES.includes(m))
this.setDiffMode(rollData, mode ??
DIFF_MODE.DEFAUT)
}
modeFromOpponents(rollData) {
if (rollData.mode.opposed) {
if (rollData.mode.resistance) {
return DIFF_MODE.IMPOSEE
}
return DIFF_MODE.LIBRE
}
return undefined
}
setDiffMode(rollData, mode) {
rollData.current[PART_DIFF].mode = mode
this.setRollDataMode(rollData)
}
}

View File

@@ -8,12 +8,12 @@ export class RollPartAction extends RollPart {
get section() { return ROLLDIALOG_SECTION.ACTION }
title(rollData) {
return rollData.mode.label
return rollData.type.label
}
prepareContext(rollData) {
const current = this.getCurrent(rollData)
current.verb = rollData.mode.label
current.verb = rollData.type.label
}
}

View File

@@ -10,10 +10,8 @@ export class RollPartAstrologique extends RollPartCheckbox {
get useCheckboxTemplate() { return false }
visible(rollData) {
return this.$isUsingAstrologie() && (
this.isJetChance(rollData)
|| this.isLancementRituel(rollData)
)
return this.$isUsingAstrologie()
&& (this.isJetChance(rollData) || this.isLancementRituel(rollData))
}
isLancementRituel(rollData) {

View File

@@ -1,6 +1,6 @@
import { RdDBonus } from "../rdd-bonus.js"
import { StatusEffects } from "../settings/status-effects.js"
import { ROLL_MODE_ATTAQUE } from "./roll-constants.mjs"
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
@@ -16,7 +16,7 @@ export class RollPartAttaque extends RollPartSelect {
get code() { return PART_ATTAQUE }
get section() { return ROLLDIALOG_SECTION.CHOIX }
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_ATTAQUE) }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_ATTAQUE) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -92,7 +92,6 @@ export class RollPartAttaque extends RollPartSelect {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectAttaque(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.setModeTitle()
rollDialog.render()
})

View File

@@ -36,7 +36,7 @@ export class RollPartCarac extends RollPartSelect {
}
}
filterCaracs(rollData, allowed) {
filterCaracs(rollData, allowed = []) {
allowed = allowed.filter(it => it != undefined)
const refs = this.getRefs(rollData)
refs.caracs = allowed.length > 0

View File

@@ -45,7 +45,7 @@ export class RollPartComp extends RollPartSelect {
}
}
filterComps(rollData, allowed) {
filterComps(rollData, allowed = []) {
allowed = allowed.filter(it => it != undefined)
const refs = this.getRefs(rollData)
refs.comps = allowed.length > 0

View File

@@ -4,7 +4,7 @@ import { ATTAQUE_TYPE, RdDItemArme } from "../item/arme.js"
import { RdDBonus } from "../rdd-bonus.js"
import { CARACS } from "../rdd-carac.js"
import { StatusEffects } from "../settings/status-effects.js"
import { DIFF_MODE, ROLL_MODE_DEFENSE } from "./roll-constants.mjs"
import { DIFF, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { PART_DIFF } from "./roll-part-diff.mjs"
@@ -18,7 +18,7 @@ export class RollPartDefense extends RollPartSelect {
get code() { return PART_DEFENSE }
get section() { return ROLLDIALOG_SECTION.CHOIX }
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_DEFENSE) }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) }
static getDiffAttaque(attackerRoll) {
// TODO: rollDataV2?
@@ -91,7 +91,6 @@ export class RollPartDefense extends RollPartSelect {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectDefense(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.setModeTitle()
rollDialog.render()
})
}
@@ -121,12 +120,12 @@ export class RollPartDefense extends RollPartSelect {
getDiffDefense(rollData) {
const current = this.getCurrent(rollData)
const refs = this.getRefs(rollData)
if (refs.isDistance) {
if (refs.isDistance || !rollData.attaque) {
// Déterminer la difficulté de parade
return { diff: 0, mode: DIFF_MODE.LIBRE }
return { diff: 0, type: DIFF.LIBRE }
}
else {
return { diff: rollData.attaque.diff, mode: DIFF_MODE.DEFENSE }
return { diff: rollData.attaque.diff ?? 0, type: DIFF.DEFENSE }
}
}
}

View File

@@ -1,9 +1,9 @@
import { DIFF_MODE, DIFF_MODES, ROLL_MODE_MEDITATION, ROLL_MODE_OEUVRE, ROLL_MODE_SORT, ROLL_MODE_TACHE } from "./roll-constants.mjs";
import { DIFF, DIFFS, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_SORT, ROLL_TYPE_TACHE } from "./roll-constants.mjs";
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs";
export const PART_DIFF = "diff"
const EXCLUDED_ROLL_MODES = [ROLL_MODE_TACHE, ROLL_MODE_MEDITATION, ROLL_MODE_SORT, ROLL_MODE_OEUVRE]
const EXCLUDED_ROLL_TYPES = [ROLL_TYPE_TACHE, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT, ROLL_TYPE_OEUVRE]
export class RollPartDiff extends RollPart {
@@ -14,37 +14,37 @@ export class RollPartDiff extends RollPart {
const current = this.getCurrent(rollData)
const saved = this.getSaved(rollData)
current.value = saved?.value ?? current.value ?? 0
current.mode = saved?.mode ?? current.mode
current.type = saved?.type ?? current.type
}
store(rollData, targetData) {
const current = this.getCurrent(rollData)
this.setSaved(targetData, {
value: current.value,
mode: current.mode
type: current.type
})
}
visible(rollData) {
if (EXCLUDED_ROLL_MODES.includes(rollData.mode.current)) {
if (EXCLUDED_ROLL_TYPES.includes(rollData.type.current)) {
return false
}
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_MODE).includes(current.mode)
return Object.values(DIFF).includes(current.type)
}
prepareContext(rollData) {
const current = this.getCurrent(rollData)
const diffMode = DIFF_MODES[current.mode] ?? DIFF_MODES[DIFF_MODE.AUCUN]
const diffType = DIFFS[current.type] ?? DIFFS[DIFF.AUCUN]
foundry.utils.mergeObject(current,
{
mode: diffMode.key,
label: diffMode?.label ?? '',
type: diffType.key,
label: diffType?.label ?? '',
value: current.value ?? 0,
disabled: !diffMode.libre,
disabled: !diffType.libre,
min: -10,
max: diffMode.max
max: diffType.max
},
{ inplace: true }
)
@@ -53,7 +53,7 @@ export class RollPartDiff extends RollPart {
setDiff(rollData, diffDefense) {
const current = this.getCurrent(rollData)
current.value = diffDefense.diff
current.mode = diffDefense.mode
current.type = diffDefense.type
}
getAjustements(rollData) {

View File

@@ -1,7 +1,7 @@
import { Grammar } from "../grammar.js"
import { ITEM_TYPES } from "../constants.js"
import { CARACS } from "../rdd-carac.js"
import { ROLL_MODE_JEU } from "./roll-constants.mjs"
import { ROLL_TYPE_JEU } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
@@ -17,7 +17,7 @@ export class RollPartJeu extends RollPartSelect {
get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_JEU) }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_JEU) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -68,8 +68,8 @@ export class RollPartJeu extends RollPartSelect {
prepareContext(rollData) {
const current = this.getCurrent(rollData)
if (rollData.mode.current == ROLL_MODE_JEU && current) {
rollData.mode.opposed = true
if (rollData.type.current == ROLL_TYPE_JEU && current) {
rollData.type.opposed = true
}
}
@@ -86,7 +86,6 @@ export class RollPartJeu extends RollPartSelect {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectJeu(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.setModeTitle()
rollDialog.render()
})
}

View File

@@ -3,7 +3,7 @@ import { Grammar } from "../grammar.js"
import { CARACS, RdDCarac } from "../rdd-carac.js"
import { RdDTimestamp } from "../time/rdd-timestamp.js"
import { TMRUtility } from "../tmr-utility.js"
import { ROLL_MODE_MEDITATION } from "./roll-constants.mjs"
import { ROLL_TYPE_MEDITATION } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
@@ -17,7 +17,7 @@ export class RollPartMeditation extends RollPartSelect {
get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_MEDITATION) }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_MEDITATION) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -86,7 +86,6 @@ export class RollPartMeditation extends RollPartSelect {
const index = selectOptions.selectedIndex
this.$selectMeditation(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.render()
rollDialog.setModeTitle()
})
this.setupListenerCondition(rollDialog, 'isComportement')

View File

@@ -2,7 +2,7 @@ import { ITEM_TYPES } from "../constants.js"
import { Grammar } from "../grammar.js"
import { Misc } from "../misc.js"
import { CARACS } from "../rdd-carac.js"
import { ROLL_MODE_OEUVRE } from "./roll-constants.mjs"
import { ROLL_TYPE_OEUVRE } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
@@ -38,7 +38,7 @@ export class RollPartOeuvre extends RollPartSelect {
get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_OEUVRE) }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_OEUVRE) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -80,7 +80,6 @@ export class RollPartOeuvre extends RollPartSelect {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectOeuvre(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.setModeTitle()
rollDialog.render()
})
}

View File

@@ -7,6 +7,6 @@ export class RollPartOpponent extends RollPart {
get code() { return OPPONENT }
get section() { return ROLLDIALOG_SECTION.ACTION }
visible(rollData) { return rollData.mode.opposed }
visible(rollData) { return rollData.type.opposed }
title(rollData) { return rollData.opponent?.name ?? '' }
}

View File

@@ -1,7 +1,7 @@
import { Misc } from "../misc.js"
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { StatusEffects } from "../settings/status-effects.js"
import { ROLL_MODE_ATTAQUE, ROLL_MODE_DEFENSE } from "./roll-constants.mjs"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_SIGN = "sign"
@@ -24,7 +24,7 @@ export class RollPartSign extends RollPart {
}
isCombat(rollData) {
return [ROLL_MODE_ATTAQUE, ROLL_MODE_DEFENSE].includes(rollData.mode.current) || rollData.mode.isCombat
return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE].includes(rollData.type.current) || rollData.type.isCombat
}
prepareContext(rollData) {
@@ -32,7 +32,7 @@ export class RollPartSign extends RollPart {
}
setFromState(rollData) {
if (rollData.mode.retry) {
if (rollData.type.retry) {
return
}
const actor = rollData.active.actor;
@@ -65,7 +65,7 @@ export class RollPartSign extends RollPart {
}
isAttaqueFinesse(rollData) {
return ROLL_MODE_DEFENSE == rollData.mode.current && rollData.attaque.particuliere == 'finesse'
return ROLL_TYPE_DEFENSE == rollData.type.current && rollData.attaque?.particuliere == 'finesse'
}
isParadeArmeDisparate(current) {

View File

@@ -1,5 +1,5 @@
import { ITEM_TYPES } from "../constants.js"
import { ROLL_MODE_SORT } from "./roll-constants.mjs"
import { ROLL_TYPE_SORT } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
@@ -18,7 +18,7 @@ export class RollPartSort extends RollPartSelect {
get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_SORT) }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_SORT) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -98,7 +98,6 @@ export class RollPartSort extends RollPartSelect {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectSort(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.setModeTitle()
rollDialog.render()
})

View File

@@ -1,6 +1,6 @@
import { ITEM_TYPES } from "../constants.js"
import { Grammar } from "../grammar.js"
import { ROLL_MODE_TACHE } from "./roll-constants.mjs"
import { ROLL_TYPE_TACHE } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
@@ -14,7 +14,7 @@ export class RollPartTache extends RollPartSelect {
get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_TACHE) }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_TACHE) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -48,7 +48,6 @@ export class RollPartTache extends RollPartSelect {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectTache(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.setModeTitle()
rollDialog.render()
})
}

View File

@@ -60,7 +60,7 @@ export class RollPart {
* @returns une chaîne vide si rien ne doit être affiché
*/
title() { return '' }
isRollMode(rollData, mode) { return rollData.mode.current == mode }
isRollType(rollData, type) { return rollData.type.current == type }
isActive(rollData) { return this.isValid(rollData) && this.visible(rollData) }
isValid(rollData) { return true }

View File

@@ -0,0 +1,13 @@
import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs"
export class RollTypeAttaque extends RollType {
get code() { return ROLL_TYPE_ATTAQUE }
get name() { return `Attaquer` }
title(rollData) { return `attaque` }
onSelect(rollData) {
this.setDiffType(rollData, DIFF.ATTAQUE)
}
}

View File

@@ -0,0 +1,10 @@
import { ROLL_TYPE_COMP } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs"
export class RollTypeComp extends RollType {
get code() { return ROLL_TYPE_COMP }
get name() { return `Jet de caractéristique / compétence` }
title(rollData) { return `fait un jet ${rollData.type.opposed ? ' contre ' : ''}` }
}

View File

@@ -0,0 +1,17 @@
import { DIFF, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs"
export class RollTypeDefense extends RollType {
get code() { return ROLL_TYPE_DEFENSE }
get name() { return `Se défendre` }
title(rollData) { return `se défend${rollData.opponent ? ' de' : ''}` }
getOpponent(rollData) {
return rollData.attacker
}
onSelect(rollData) {
this.setDiffType(rollData, DIFF.DEFENSE)
}
}

View File

@@ -1,9 +1,9 @@
import { PART_JEU } from "./roll-part-jeu.mjs"
import { RollMode } from "./roll-mode.mjs"
import { ROLL_MODE_JEU } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs"
import { ROLL_TYPE_JEU } from "./roll-constants.mjs"
export class RollModeJeu extends RollMode {
get code() { return ROLL_MODE_JEU }
export class RollTypeJeu extends RollType {
get code() { return ROLL_TYPE_JEU }
get name() { return `Jouer` }
visible(rollData) { return rollData.active.actor.isPersonnage() }

View File

@@ -1,9 +1,9 @@
import { DIFF_MODE, ROLL_MODE_MEDITATION } from "./roll-constants.mjs"
import { DIFF, ROLL_TYPE_MEDITATION } from "./roll-constants.mjs"
import { PART_MEDITATION } from "./roll-part-meditation.mjs"
import { RollMode } from "./roll-mode.mjs"
import { RollType } from "./roll-type.mjs"
export class RollModeMeditation extends RollMode {
get code() { return ROLL_MODE_MEDITATION }
export class RollTypeMeditation extends RollType {
get code() { return ROLL_TYPE_MEDITATION }
get name() { return `Méditation draconique` }
visible(rollData) { return rollData.active.actor.isHautRevant() }
@@ -14,6 +14,6 @@ export class RollModeMeditation extends RollMode {
}
onSelect(rollData) {
this.setDiffMode(rollData, DIFF_MODE.AUCUN)
this.setDiffType(rollData, DIFF.AUCUN)
}
}

View File

@@ -1,9 +1,9 @@
import { DIFF_MODE, ROLL_MODE_OEUVRE } from "./roll-constants.mjs"
import { DIFF, ROLL_TYPE_OEUVRE } from "./roll-constants.mjs"
import { PART_OEUVRE } from "./roll-part-oeuvre.mjs"
import { RollMode } from "./roll-mode.mjs"
import { RollType } from "./roll-type.mjs"
export class RollModeOeuvre extends RollMode {
get code() { return ROLL_MODE_OEUVRE }
export class RollTypeOeuvre extends RollType {
get code() { return ROLL_TYPE_OEUVRE }
get name() { return `Interpréter une oeuvre` }
visible(rollData) { return rollData.active.actor.isPersonnage() }
@@ -13,7 +13,7 @@ export class RollModeOeuvre extends RollMode {
}
onSelect(rollData) {
this.setDiffMode(rollData, DIFF_MODE.AUCUN)
this.setDiffType(rollData, DIFF.AUCUN)
}
}

View File

@@ -0,0 +1,14 @@
import { DIFF, ROLL_TYPE_SORT } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs"
export class RollTypeSort extends RollType {
get code() { return ROLL_TYPE_SORT }
get name() { return `lancer un sort` }
visible(rollData) { return rollData.active.actor.isHautRevant() }
title(rollData) { return `lance le sort:` }
onSelect(rollData) {
this.setDiffType(rollData, DIFF.AUCUN)
}
}

View File

@@ -1,9 +1,9 @@
import { DIFF_MODE, ROLL_MODE_TACHE } from "./roll-constants.mjs"
import { DIFF, ROLL_TYPE_TACHE } from "./roll-constants.mjs"
import { PART_TACHE } from "./roll-part-tache.mjs"
import { RollMode } from "./roll-mode.mjs"
import { RollType } from "./roll-type.mjs"
export class RollModeTache extends RollMode {
get code() { return ROLL_MODE_TACHE }
export class RollTypeTache extends RollType {
get code() { return ROLL_TYPE_TACHE }
get name() { return `Travailler à une tâche` }
visible(rollData) { return rollData.active.actor.isPersonnage() }
@@ -14,6 +14,6 @@ export class RollModeTache extends RollMode {
}
onSelect(rollData) {
this.setDiffMode(rollData, DIFF_MODE.AUCUN)
this.setDiffType(rollData, DIFF.AUCUN)
}
}

55
module/roll/roll-type.mjs Normal file
View File

@@ -0,0 +1,55 @@
import { DIFF } from "./roll-constants.mjs"
import { PART_DIFF } from "./roll-part-diff.mjs"
const DEFAULT_DIFF_TYPES = [DIFF.LIBRE, DIFF.IMPOSEE, DIFF.DEFAUT]
export class RollType {
onReady() { }
get code() { throw new Error(`Pas de code défini pour ${this}`) }
get name() { return this.code }
get icon() { return `systems/foundryvtt-reve-de-dragon/assets/actions/${this.code}.svg` }
get chatResultTemplate() { return `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-${this.code}.hbs` }
toTypeData(rollData) {
return { code: this.code, name: this.name, icon: this.icon, section: 'type', template: this.template, selected: this.isSelected(rollData) }
}
isAllowed(rollData) { return rollData.type.allowed == undefined || rollData.type.allowed.includes(this.code) }
visible(rollData) { return true }
title(rollData) { return this.code }
isSelected(rollData) { return rollData.type.current == this.code }
setRollDataType(rollData) {
rollData.type.opposed = rollData.opponent != undefined
rollData.type.resistance = false /** TODO */
}
onSelect(rollData) {
const possibleTypes = [
rollData.current[PART_DIFF].type,
this.typeFromOpponents(rollData),
rollData.selected[PART_DIFF].type
]
const type = possibleTypes.find(m => DEFAULT_DIFF_TYPES.includes(m)) ??DIFF.DEFAUT
this.setDiffType(rollData, type)
}
typeFromOpponents(rollData) {
if (rollData.type.opposed) {
if (rollData.type.resistance) {
return DIFF.IMPOSEE
}
return DIFF.LIBRE
}
return undefined
}
setDiffType(rollData, type) {
rollData.current[PART_DIFF].type = type
this.setRollDataType(rollData)
}
}

View File

@@ -1,9 +1,9 @@
<div data-passearme="{{passeArme}}">
<h4 class="rdd-roll-etotal">Maladresse à l'attaque
<h4 class="rdd-roll-etotal">Maladresse à l'attaque:<br>échec
{{#if rolled.isETotal}}
(échec total)
total
{{else}}
(échec en demi-surprise)
en demi-surprise
{{/if}}
</h4>
<br>

View File

View File

@@ -0,0 +1,31 @@
<h4>
{{log this}}
<img class="chat-icon" src="{{competence.img}}" data-tooltip="{{competence.name}}" />
{{alias}} esquive une attaque à {{diffLibre}}</h4>
<p>{{selectedCarac.label}}{{#unless (eq selectedCarac.label competence.name)}} / {{competence.name}}{{/unless}}</p>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.hbs"}}
<hr>
<p>
{{#if rolled.isSuccess}}
<span>Attaque esquivée!</span>
{{#if rolled.isPart}}
<!-- TODO: cas de parade à mains nues, texte à modifier -->
<span><strong>{{alias}} peut faire une deuxième esquive!</strong></span>
{{/if}}
{{else}}
<span>L'esquive de {{alias}} a échoué!</span>
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.hbs"}}
</p>
{{#if attackerRoll.tactique}}
<p>
{{#if (eq attackerRoll.tactique 'charge')}}
<img class="chat-icon" src="icons/svg/thrust.svg" data-tooltip="charge" height="32" width="32" />
C'était une charge, les parades de l'adversaire de {{alias}} auront un -4 et il ne pourra pas esquiver!
{{ else if (eq attackerRoll.tactique 'feinte')}}
<img class="chat-icon" src="systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg" data-tooltip="feinte" height="32" width="32" />
C'était une feinte!
{{/if}}
</p>
{{/if}}

View File

View File

View File

View File

View File

@@ -1,4 +1,4 @@
{{#if (or rollData.mode.passif (ne rollData.active.surprise.key 'totale'))}}
{{#if (or rollData.type.passif (ne rollData.active.surprise.key 'totale'))}}
<button name="roll-dialog-button">Lancer
{{rollData.current.carac.value}} à {{plusMoins rollData.current.totaldiff}}
{{#if rollData.current.significative.used}}

View File

@@ -1,10 +1,6 @@
<form class="roll-dialog">
<roll-header></roll-header>
<roll-mode>
{{#each modes as |mode|}}
{{> 'roll-mode' mode}}
{{/each}}
</roll-mode>
<roll-type>{{> 'roll-type' types=types}}</roll-type>
<roll-action>{{#each templates as |template|}}{{> 'roll-section' rollData=@root.rollData currentsection='action'}}{{/each}}</roll-action>
<roll-carac>{{#each templates as |template|}}{{> 'roll-section' rollData=@root.rollData currentsection='carac'}}{{/each}}</roll-carac>
<roll-comp>{{#each templates as |template|}}{{> 'roll-section' rollData=@root.rollData currentsection='comp'}}{{/each}}</roll-comp>

View File

@@ -1,3 +0,0 @@
<button name="roll-mode" data-tooltip="{{name}}" data-mode="{{code}}" data-checked="{{selected}}">
<img src="{{icon}}">
</button>

View File

@@ -1,2 +1,2 @@
<input name="{{code}}" type="checkbox" {{#if current.checked}}checked{{/if}}/>
<label for="{{code}}">{{current.label}}</label>
<label for="{{code}}">{{refs.label}}</label>

View File

@@ -1,5 +1,5 @@
<subline>
<select name="select-attaque" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="select-attaque" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.attaques selected=current.key valueAttr="key" labelAttr="label"}}
</select>
</subline>
@@ -11,7 +11,7 @@
<roll-part-detail>
<subline>
<label for="select-tactique">Tactique:</label>
<select name="select-tactique" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="select-tactique" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.tactiques selected=current.tactique.key valueAttr="key" labelAttr="label"}}
</select>
</subline>

View File

@@ -1,4 +1,4 @@
<select name="select-carac" {{#if (or rollData.mode.retry (eq refs.caracs.length 1))}}disabled{{/if}}>
<select name="select-carac" {{#if (or rollData.type.retry (eq refs.caracs.length 1))}}disabled{{/if}}>
{{selectOptions refs.caracs selected=current.key valueAttr="key" labelAttr="label"}}
</select>
<selected-numeric-value>{{current.value}}</selected-numeric-value>

View File

@@ -1,5 +1,5 @@
<label for="{{code}}">Coeur</label>
<select name="{{code}}" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="{{code}}" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.amoureux selected=current.key valueAttr="key" labelAttr="label"}}
</select>
{{#if current.amour}}

View File

@@ -1,4 +1,4 @@
<select name="select-comp" {{#if (or rollData.mode.retry (eq refs.comps.length 1))}}disabled{{/if}}>
<select name="select-comp" {{#if (or rollData.type.retry (eq refs.comps.length 1))}}disabled{{/if}}>
{{selectOptions refs.comps selected=current.key valueAttr="key" labelAttr="label"}}
</select>
<selected-numeric-value>{{plusMoins current.value}}</selected-numeric-value>

View File

@@ -4,5 +4,5 @@
step=1
min=current.min
max=current.max
disabled=rollData.mode.retry
disabled=rollData.type.retry
}}

View File

@@ -3,7 +3,7 @@
</roll-part-img>
<roll-part-detail>
<subline>
<select name="select-defense" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="select-defense" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.defenses selected=current.key valueAttr="key" labelAttr="label"}}
</select>
</subline>

View File

@@ -5,6 +5,6 @@
step=1
min=current.min
max=current.max
disabled=(or rollData.mode.retry current.disabled)
disabled=(or rollData.type.retry current.disabled)
}}
</subline>

View File

@@ -9,5 +9,5 @@
step=1
min=-30
max=0
disabled=rollData.mode.retry
disabled=rollData.type.retry
}}

View File

@@ -3,7 +3,7 @@
</roll-part-img>
<roll-part-detail>
<subline>
<select name="select-jeu" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="select-jeu" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.jeux selected=current.key valueAttr="key" labelAttr="label"}}
</select>
<selected-numeric-value>{{plusMoins current.value}}</selected-numeric-value>

View File

@@ -6,7 +6,7 @@
Rêve actuel: {{rollData.active.actor.system.reve.reve.value}}
</subline>
<subline>
<select name="select-meditation" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="select-meditation" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.meditations selected=current.key valueAttr="key" labelAttr="label"}}
</select>
{{#if current.meditation.system.malus}}
@@ -28,14 +28,14 @@
<subline>Durée:&nbsp;60 minutes</subline>
<hr>
<subline>
<input class="conditionMeditation" type="checkbox" name="isComportement" {{#if current.isComportement}}checked{{/if}} {{#if rollData.mode.retry}}disabled{{/if}}/>
<input class="conditionMeditation" type="checkbox" name="isComportement" {{#if current.isComportement}}checked{{/if}} {{#if rollData.type.retry}}disabled{{/if}}/>
<label for="isComportement">Comportement:&nbsp;
<span name="comportement">{{current.meditation.system.comportement}}</span>
</label>
</subline>
<subline>
<input class="conditionMeditation" type="checkbox" name="isHeure" {{#if current.isHeure}}checked{{/if}} {{#if rollData.mode.retry}}disabled{{/if}}/>
<input class="conditionMeditation" type="checkbox" name="isHeure" {{#if current.isHeure}}checked{{/if}} {{#if rollData.type.retry}}disabled{{/if}}/>
<label for="isHeure">Heure:&nbsp;
{{#with current.meditation.system.heure as |heure|}}
<span name="heure">{{timestamp-label heure}}</span>
@@ -45,13 +45,13 @@
</subline>
<subline>
<input class="conditionMeditation" type="checkbox" name="isPurification" {{#if current.isPurification}}checked{{/if}} {{#if rollData.mode.retry}}disabled{{/if}}/>
<input class="conditionMeditation" type="checkbox" name="isPurification" {{#if current.isPurification}}checked{{/if}} {{#if rollData.type.retry}}disabled{{/if}}/>
<label for="isPurification">Purification:&nbsp;
<span name="purification">{{current.meditation.system.purification}}</span></label>
</subline>
<subline>
<input class="conditionMeditation" type="checkbox" name="isVeture" {{#if current.isVeture}}checked{{/if}} {{#if rollData.mode.retry}}disabled{{/if}}/>
<input class="conditionMeditation" type="checkbox" name="isVeture" {{#if current.isVeture}}checked{{/if}} {{#if rollData.type.retry}}disabled{{/if}}/>
<label for="isVeture">Vêture:&nbsp;
<span name="veture">{{current.meditation.system.veture}}</span>
</label>

View File

@@ -3,7 +3,7 @@
</roll-part-img>
<roll-part-detail>
<subline>
<select name="select-oeuvre" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="select-oeuvre" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.oeuvres selected=current.key valueAttr="key" labelAttr="label"}}
</select>
{{#if current.oeuvre}}

View File

@@ -4,7 +4,7 @@
<roll-part-detail>
<subline>TMR actuelle: {{caseTmr-label rollData.active.actor.system.reve.tmrpos.coord}} {{rollData.active.actor.system.reve.tmrpos.coord}}</subline>
<subline>
<select name="select-sort" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="select-sort" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.sorts selected=current.key valueAttr="key" labelAttr="label"}}
</select>
{{#if current.isDiffVariable}}
@@ -13,7 +13,7 @@
step=1
min=-20
max=-1
disabled=rollData.mode.retry
disabled=rollData.type.retry
}}
{{else}}
<selected-numeric-value>{{plusMoins current.value}}</selected-numeric-value>
@@ -28,7 +28,7 @@
step=1
min=1
max=30
disabled=rollData.mode.retry
disabled=rollData.type.retry
}}
{{/if}}
<span>&nbsp;(actuel: {{rollData.active.actor.system.reve.reve.value}})</span>
@@ -37,7 +37,7 @@
{{#if current.sort.system.isrituel}}
<i class="fa-solid fa-book-sparkles"></i>&nbsp; Rituel
{{else}}
<input type="checkbox" name="reserve" {{#if current.isReserve}}checked{{/if}} {{#if rollData.mode.retry}}disabled{{/if}}/>
<input type="checkbox" name="reserve" {{#if current.isReserve}}checked{{/if}} {{#if rollData.type.retry}}disabled{{/if}}/>
<label for="reserve"><i class="fa-solid fa-sparkles"></i>&nbsp; Mettre en réserve</label>
{{/if}}
</subline>

View File

@@ -3,7 +3,7 @@
</roll-part-img>
<roll-part-detail>
<subline>
<select name="select-tache" {{#if rollData.mode.retry}}disabled{{/if}}>
<select name="select-tache" {{#if rollData.type.retry}}disabled{{/if}}>
{{selectOptions refs.taches selected=current.key valueAttr="key" labelAttr="label"}}
</select>
<selected-numeric-value>{{plusMoins current.value}}</selected-numeric-value>

View File

@@ -0,0 +1,5 @@
{{#each types as |type|}}
<button name="roll-type" data-tooltip="{{name}}" data-type="{{code}}" data-checked="{{selected}}">
<img src="{{icon}}">
</button>
{{/each}}