Appel chance RollDialogV2

This commit is contained in:
2026-05-05 23:51:04 +02:00
parent e7acb0c4f2
commit 24753bfc29
14 changed files with 108 additions and 34 deletions
+1
View File
@@ -7,6 +7,7 @@
- les dés customisés Dice-So-Nice (heure, rencontres, dé draconique) fonctionnent - 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 - 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 - 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 ## 13.0.37 - Le bonheur des zyglutes d'Illisys
+18 -18
View File
@@ -47,11 +47,7 @@ import { RdDRollResult } from "./rdd-roll-result.js";
import { RdDInitiative } from "./initiative.mjs"; import { RdDInitiative } from "./initiative.mjs";
import RollDialog from "./roll/roll-dialog.mjs"; import RollDialog from "./roll/roll-dialog.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js"; 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 { 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 { 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 { RdDPossessionV2 } from "./rdd-possession-v2.mjs"; import { RdDPossessionV2 } from "./rdd-possession-v2.mjs";
import { Apprecier, MORAL, SITUATION_MORAL } from "./moral/apprecier.mjs"; import { Apprecier, MORAL, SITUATION_MORAL } from "./moral/apprecier.mjs";
import { Distance } from "./combat/distance.mjs"; import { Distance } from "./combat/distance.mjs";
@@ -1877,7 +1873,7 @@ export class RdDActor extends RdDBaseActorSang {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: [PART_COMP], current: PART_COMP }, type: { allowed: [ROLL_TYPE_COMP], current: ROLL_TYPE_COMP },
selected: { selected: {
carac: { key: caracName }, carac: { key: caracName },
comp: { key: compName, forced: options.forced }, comp: { key: compName, forced: options.forced },
@@ -1916,7 +1912,7 @@ export class RdDActor extends RdDBaseActorSang {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
selected: { tache: { key: tache.id, forced: options.forced } }, 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) return await RollDialog.create(rollData, options)
} }
@@ -2129,18 +2125,22 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollAppelChance(onSuccess = () => { }, onEchec = () => { }) { async rollAppelChance(onSuccess = () => { }, onEchec = () => { }) {
await this.openRollDialog({
name: 'appelChance', return await RollDialog.create(
label: 'Appel à la chance', {
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.hbs', ids: { actorId: this.id },
rollData: { selectedCarac: this.getCaracByName('chance-actuelle'), surprise: '' }, type: { allowed: [ROLL_TYPE_APPEL_CHANCE], current: ROLL_TYPE_APPEL_CHANCE },
callbacks: [{ action: r => this.$appelChanceResult(r, onSuccess, onEchec) }] },
}); {
onRollDone: (dialog, roll) => RollDialog.onRollDoneClose(dialog, roll),
callbacks: [
async roll => await this.$appelChanceResult(roll, onSuccess, onEchec)
]
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async $appelChanceResult(rollData, onSuccess, onEchec) { async $appelChanceResult(rollData, onSuccess, onEchec) {
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-appelchance.hbs')
if (rollData.rolled.isSuccess) { if (rollData.rolled.isSuccess) {
await this.setFlag(SYSTEM_RDD, 'utilisationChance', true); await this.setFlag(SYSTEM_RDD, 'utilisationChance', true);
await this.chanceActuelleIncDec(-1); await this.chanceActuelleIncDec(-1);
@@ -3015,7 +3015,7 @@ export class RdDActor extends RdDBaseActorSang {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
selected: { oeuvre: { key: oeuvre.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) return await RollDialog.create(rollData)
} }
@@ -3117,7 +3117,7 @@ export class RdDActor extends RdDBaseActorSang {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: [PART_CUISINE], current: PART_CUISINE }, type: { allowed: [ROLL_TYPE_CUISINE], current: ROLL_TYPE_CUISINE },
selected: { selected: {
cuisine: { key: recette.id } cuisine: { key: recette.id }
} }
@@ -3167,7 +3167,7 @@ export class RdDActor extends RdDBaseActorSang {
if (item.getUtilisationCuisine() == 'brut' && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (item.getUtilisationCuisine() == 'brut' && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: [PART_CUISINE], current: PART_CUISINE }, type: { allowed: [ROLL_TYPE_CUISINE], current: ROLL_TYPE_CUISINE },
selected: { selected: {
cuisine: { key: item.id } cuisine: { key: item.id }
} }
+7 -8
View File
@@ -26,9 +26,8 @@ import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES } fr
import { RollDataAjustements } from "../rolldata-ajustements-v1.js"; import { RollDataAjustements } from "../rolldata-ajustements-v1.js";
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs"; import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
import RollDialog from "../roll/roll-dialog.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 { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
import { PART_COMP } from "../roll/roll-part-comp.mjs";
import { RdDInitiative } from "../initiative.mjs"; import { RdDInitiative } from "../initiative.mjs";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"; import { RdDPossessionV2 } from "../rdd-possession-v2.mjs";
@@ -317,7 +316,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
const competence = this.getCompetence(compName); const competence = this.getCompetence(compName);
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP }, type: { allowed: DEFAULT_ROLL_TYPES, current: ROLL_TYPE_COMP },
selected: { selected: {
carac: { key: caracName }, carac: { key: caracName },
comp: { key: competence.name }, comp: { key: competence.name },
@@ -384,7 +383,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { type: {
allowed: DEFAULT_ROLL_TYPES, allowed: DEFAULT_ROLL_TYPES,
current: PART_COMP, current: ROLL_TYPE_COMP,
}, },
selected: { selected: {
diff: { type: DIFF.DEFAUT } diff: { type: DIFF.DEFAUT }
@@ -417,8 +416,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { type: {
allowed: [PART_COMP], allowed: [ROLL_TYPE_COMP],
current: PART_COMP, current: ROLL_TYPE_COMP,
resistance: resistance resistance: resistance
}, },
selected: { selected: {
@@ -440,8 +439,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { type: {
allowed: options.resistance ? [PART_COMP] : DEFAULT_ROLL_TYPES, allowed: options.resistance ? [ROLL_TYPE_COMP] : DEFAULT_ROLL_TYPES,
current: PART_COMP, current: options.resistance ? ROLL_TYPE_COMP : ROLL_TYPE_COMP,
resistance: options.resistance resistance: options.resistance
}, },
selected: { selected: {
+2 -3
View File
@@ -4,9 +4,8 @@ import { SANS_COMPETENCE } from "../item/base-items.js"
import { Misc } from "../misc.js" import { Misc } from "../misc.js"
import { CARACS } from "../rdd-carac.js" import { CARACS } from "../rdd-carac.js"
import { RdDUtility } from "../rdd-utility.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 RollDialog from "../roll/roll-dialog.mjs"
import { PART_COMP } from "../roll/roll-part-comp.mjs"
export const MORAL = { export const MORAL = {
MALHEUREUX: "malheureux", MALHEUREUX: "malheureux",
@@ -134,7 +133,7 @@ export class Apprecier {
const competence = (this.appreciation.jetComp && this.appreciation.competence) ? this.appreciation.competence : "" const competence = (this.appreciation.jetComp && this.appreciation.competence) ? this.appreciation.competence : ""
const rollData = { const rollData = {
ids: { actorId: this.actor.id }, 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: { selected: {
carac: { key: this.appreciation.carac, forced: true }, carac: { key: this.appreciation.carac, forced: true },
comp: { key: competence, forced: true }, comp: { key: competence, forced: true },
+1 -1
View File
@@ -644,7 +644,7 @@ export class RdDCombat {
opponentId: this.defender.id, opponentId: this.defender.id,
opponentTokenId: this.defenderTokenId, opponentTokenId: this.defenderTokenId,
}, },
type: { allowed: ['attaque'], current: 'attaque' }, type: { allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE },
selected: {}, selected: {},
passeArme: foundry.utils.randomID(16), passeArme: foundry.utils.randomID(16),
} }
+1
View File
@@ -200,6 +200,7 @@ export default class ChatRollResult {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = this.getActiveActor(savedRoll) const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => it.rollAppelChance( Misc.doIfOwner(actor, it => it.rollAppelChance(
() => this.onAppelChanceSuccess(savedRoll, chatMessage), () => this.onAppelChanceSuccess(savedRoll, chatMessage),
() => this.onAppelChanceEchec(savedRoll, chatMessage)) () => this.onAppelChanceEchec(savedRoll, chatMessage))
+1
View File
@@ -9,6 +9,7 @@ export const ROLL_TYPE_MEDITATION = 'meditation'
export const ROLL_TYPE_OEUVRE = 'oeuvre' export const ROLL_TYPE_OEUVRE = 'oeuvre'
export const ROLL_TYPE_SORT = 'sort' export const ROLL_TYPE_SORT = 'sort'
export const ROLL_TYPE_TACHE = 'tache' export const ROLL_TYPE_TACHE = 'tache'
export const ROLL_TYPE_APPEL_CHANCE = 'appel-chance'
export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE] export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE]
export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE] export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE]
+2 -1
View File
@@ -50,6 +50,7 @@ import { RollPartResistance } from "./roll-part-resistance.mjs";
import { RollTypePossession } from "./roll-type-possession.mjs"; import { RollTypePossession } from "./roll-type-possession.mjs";
import { RollPartPossession } from "./roll-part-possession.mjs"; import { RollPartPossession } from "./roll-part-possession.mjs";
import { RollPartApprecier } from "./roll-part-apprecier.mjs"; import { RollPartApprecier } from "./roll-part-apprecier.mjs";
import { RollTypeAppelChance } from "./roll-type-appel-chance.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
@@ -65,6 +66,7 @@ export const ALL_ROLL_TYPES = [
new RollTypeCuisine(), new RollTypeCuisine(),
new RollTypeOeuvre(), new RollTypeOeuvre(),
new RollTypeJeu(), new RollTypeJeu(),
new RollTypeAppelChance(),
// new RollTypeResistance ?? // new RollTypeResistance ??
// new RollTypeFixedCarac ?? // new RollTypeFixedCarac ??
] ]
@@ -290,7 +292,6 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return rollData.type?.allowed return rollData.type?.allowed
? ROLL_PARTS.filter(p => RollDialog.$isIntersecting(rollData.type.allowed, p.rollTypes)) ? ROLL_PARTS.filter(p => RollDialog.$isIntersecting(rollData.type.allowed, p.rollTypes))
: ROLL_PARTS : 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 */ /** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */
+1 -1
View File
@@ -27,7 +27,7 @@ export class RollPartComp extends RollPartSelect {
const selected = this.getSelected(rollData) const selected = this.getSelected(rollData)
const all = this.$getActorComps(rollData) const all = this.$getActorComps(rollData)
const selectedComp = selected.key const selectedComp = selected.key
if (selected.forced && selectedComp) { if (selected.forced && selectedComp!= undefined ) {
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selectedComp)) refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selectedComp))
if (refs.all.length == 0) { if (refs.all.length == 0) {
if (selected.key && selected.key.length > 0) { if (selected.key && selected.key.length > 0) {
+6
View File
@@ -10,6 +10,11 @@ export class RollPartConditions extends RollPart {
settingMin() { return RollPart.settingKey(this, 'min') } settingMin() { return RollPart.settingKey(this, 'min') }
settingMax() { return RollPart.settingKey(this, 'max') } settingMax() { return RollPart.settingKey(this, 'max') }
visible(rollData) {
const current = this.getCurrent(rollData)
return !current.hide
}
onReady(rollParts) { onReady(rollParts) {
game.settings.register(SYSTEM_RDD, this.settingMin(), game.settings.register(SYSTEM_RDD, this.settingMin(),
{ {
@@ -36,6 +41,7 @@ export class RollPartConditions extends RollPart {
restore(rollData) { restore(rollData) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
current.value = this.getSaved(rollData)?.value ?? current.value ?? 0 current.value = this.getSaved(rollData)?.value ?? current.value ?? 0
current.hide = this.getSaved(rollData)?.hide
} }
+1 -1
View File
@@ -37,7 +37,7 @@ export class RollPartDiff extends RollPart {
} }
const current = this.getCurrent(rollData) 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é)*/ /* 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) { prepareContext(rollData) {
+44
View File
@@ -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)
}
}
+1 -1
View File
@@ -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) } 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) } isAllowed(rollData) { return rollData.type.allowed == undefined || rollData.type.allowed.includes(this.code) }
visible(rollData) { return true } visible(rollData) { return true }
title(rollData) { return this.code } title(rollData) { return this.code }
@@ -0,0 +1,22 @@
<div class="roll-chat">
<div class="chat-img">
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
<img src="{{current.comp.comp.img}}" data-tooltip="{{current.comp.label}}" />
</div>
<div class="chat-header">
{{active.name}} fait appel à la chance
</div>
<div class="chat-resume">
{{> 'partial-infojet'}}
</div>
<div class="chat-details">
{{#if rolled.isSuccess}}
<p>Un point de chance a été dépensé, le jet peut être retenté</p>
{{else}}
<p>Pas de dépense de chance</p>
{{/if}}
</div>
</div>