Avancement messages défense & oeuvres
This commit is contained in:
@@ -3049,7 +3049,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _rollArtV2(oeuvreId, callbackAction = async (actor, rd) => await actor._resultArtV2(rd)) {
|
||||
async _rollArtV2(oeuvreId, callbackAction = async (rd) => await this._resultArtV2(rd)) {
|
||||
const oeuvre = this.items.get(oeuvreId)
|
||||
const rollData = {
|
||||
title: `Interpretation de ${oeuvre.name} par ${this.name}`,
|
||||
@@ -3074,15 +3074,16 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: move vers ChatRollResult
|
||||
async _resultArtV2(artData) {
|
||||
const niveau = artData.oeuvre.system.niveau ?? 0;
|
||||
const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau);
|
||||
artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite;
|
||||
|
||||
await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`);
|
||||
const niveau = artData.oeuvre.system.niveau ?? 0
|
||||
const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau)
|
||||
artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite
|
||||
//this.$onRollCompetence(artData)
|
||||
await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`)
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollOeuvre(id) {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
return await this._rollArtV2(id)
|
||||
@@ -3168,7 +3169,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
async _resultArt(artData) {
|
||||
const niveau = artData.oeuvre.system.niveau ?? 0;
|
||||
const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau);
|
||||
artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite;
|
||||
artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite
|
||||
|
||||
await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`);
|
||||
}
|
||||
@@ -3189,7 +3190,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
async _resultRecetteCuisine(cuisine) {
|
||||
const niveauRecette = cuisine.oeuvre.system.niveau ?? 0;
|
||||
const baseQualite = (cuisine.rolled.isSuccess ? niveauRecette : cuisine.competence.system.niveau);
|
||||
cuisine.qualiteFinale = Math.min(baseQualite, niveauRecette) + cuisine.rolled.ptQualite;
|
||||
cuisine.qualiteFinale = Math.min(baseQualite, niveauRecette) + cuisine.rolled.ptQualite
|
||||
cuisine.exotismeFinal = Math.min(Math.min(cuisine.qualiteFinale, cuisine.oeuvre.system.exotisme ?? 0), 0);
|
||||
cuisine.sust = cuisine.oeuvre.system.sust * Math.min(cuisine.proportions, cuisine.proportionsMax ?? cuisine.proportions)
|
||||
const platCuisine = {
|
||||
|
@@ -17,9 +17,8 @@ import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
import { RdDInitiative } from "./initiative.mjs";
|
||||
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_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
|
||||
import { DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const premierRoundInit = [
|
||||
@@ -413,6 +412,9 @@ export class RdDCombat {
|
||||
'.appel-chance-attaque',
|
||||
'.appel-destinee-attaque',
|
||||
'.echec-total-attaque',
|
||||
'.appel-chance',
|
||||
'.chat-encaissement',
|
||||
'.resister-recul',
|
||||
]) {
|
||||
$(html).on("click", button, event => {
|
||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(
|
||||
@@ -807,8 +809,6 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _sendMessageDefense(attackerRoll, defenderRoll, essaisPrecedents = undefined) {
|
||||
console.log("RdDCombat._sendMessageDefense", attackerRoll, defenderRoll, essaisPrecedents, " / ", this.attacker, this.target, this.attackerId, attackerRoll.competence.system.categorie);
|
||||
|
||||
this.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
||||
if (essaisPrecedents) {
|
||||
foundry.utils.mergeObject(attackerRoll.essais, essaisPrecedents, { overwrite: true });
|
||||
@@ -980,18 +980,21 @@ export class RdDCombat {
|
||||
opponentId: this.attackerId,
|
||||
},
|
||||
type: { allowed: ['defense'], current: 'defense' },
|
||||
attaque: RollDialogAdapter.mapActionAttaque(attackerRoll),
|
||||
attackerRoll: RollDialogAdapter.mapActionAttaque(attackerRoll),
|
||||
passeArme: attackerRoll.passeArme,
|
||||
}
|
||||
|
||||
await RollDialog.create(rollData, {
|
||||
onRollDone: (dialog) => { dialog.close() },
|
||||
onRollDone: (dialog) => {
|
||||
// dialog.close()
|
||||
},
|
||||
customChatMessage: true,
|
||||
callbacks: [async (roll) => {
|
||||
this.removeChatMessageActionsPasseArme(roll.passeArme)
|
||||
// defense: esquive / arme de parade / competence de défense
|
||||
if (!RdDCombat.isParticuliere(roll))
|
||||
if (!RdDCombat.isParticuliere(roll)) {
|
||||
await roll.active.actor.incDecItemUse(roll.current[PART_DEFENSE].defense?.id,)
|
||||
}
|
||||
await this._onDefense(roll)
|
||||
}]
|
||||
})
|
||||
@@ -1025,57 +1028,49 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
async _onDefense(rollData) {
|
||||
console.log("RdDCombat._onDefense >>>", rollData)
|
||||
const isEsquive = rollData.current[PART_DEFENSE].isEsquive
|
||||
const isParade = !isEsquive
|
||||
if (RdDCombat.isReussite(rollData)) {
|
||||
await this._onDefenseNormale(rollData)
|
||||
if (isParade) {
|
||||
await this.computeRecul(rollData)
|
||||
await this.computeDeteriorationArme(rollData)
|
||||
}
|
||||
|
||||
if (RdDCombat.isParticuliere(rollData)) {
|
||||
await this._onDefenseParticuliere(rollData)
|
||||
await this._onDefenseParticuliere(rollData, isEsquive)
|
||||
}
|
||||
}
|
||||
else {
|
||||
await this._onDefenseEchec(dialog, rollData)
|
||||
//await this._sendMessageDefense(rollData.attackerRoll, rollData, { defense: true })
|
||||
}
|
||||
|
||||
// TODO: modify chat message
|
||||
this.removeChatMessageActionsPasseArme(rollData.passeArme)
|
||||
}
|
||||
|
||||
async _onDefenseParticuliere(rollData) {
|
||||
console.log("RdDCombat._onDefenseParticuliere >>>", rollData);
|
||||
if (/*TODO: parade?*/!rollData.attackerRoll?.isPart) {
|
||||
async _onDefenseParticuliere(rollData, isEsquive) {
|
||||
if (isEsquive) {
|
||||
ChatUtility.createChatWithRollMode(
|
||||
{ content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" },
|
||||
this.defender)
|
||||
}
|
||||
else if (/*TODO: parade?*/!rollData.attackerRoll?.particuliere) {
|
||||
// TODO: attaquant doit jouer résistance et peut être désarmé p132
|
||||
ChatUtility.createChatWithRollMode(
|
||||
{ content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` },
|
||||
this.defender)
|
||||
}
|
||||
ChatUtility.createChatWithRollMode(
|
||||
{ content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" },
|
||||
this.defender);
|
||||
}
|
||||
|
||||
async _onDefenseNormale(rollData) {
|
||||
console.log("RdDCombat._onDefenseNormale >>>", rollData);
|
||||
// console.log("RdDCombat._onEsquiveNormal >>>", rollData);
|
||||
// await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-esquive.hbs');
|
||||
// this.removeChatMessageActionsPasseArme(rollData.passeArme);
|
||||
//TODO
|
||||
await this.computeRecul(rollData);
|
||||
await this.computeDeteriorationArme(rollData);
|
||||
await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-parade.hbs');
|
||||
this.removeChatMessageActionsPasseArme(rollData.passeArme);
|
||||
}
|
||||
|
||||
async _onDefenseEchec(rollData) {
|
||||
console.log("RdDCombat._onDefenseEchec >>>", rollData);
|
||||
// console.log("RdDCombat._onEsquiveEchec >>>", rollData);
|
||||
|
||||
// await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-esquive.hbs');
|
||||
|
||||
// this.removeChatMessageActionsPasseArme(rollData.passeArme);
|
||||
// this._sendMessageDefense(rollData.attackerRoll, rollData, { defense: true })
|
||||
|
||||
await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-parade.hbs');
|
||||
|
||||
this.removeChatMessageActionsPasseArme(rollData.passeArme);
|
||||
this._sendMessageDefense(rollData.attackerRoll, rollData, { defense: true });
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1214,7 +1209,7 @@ export class RdDCombat {
|
||||
// Est-ce une parade normale?
|
||||
if (defenderRoll.arme && attackerRoll && !defenderRoll.rolled.isPart) {
|
||||
// Est-ce que l'attaque est une particulière en force ou une charge
|
||||
if (defenderRoll.needResist || this._isForceOuCharge(attackerRoll)) {
|
||||
if (defenderRoll.needResist || this._isForceOuCharge(attackerRoll, defenderRoll.v2)) {
|
||||
|
||||
defenderRoll.show = defenderRoll.show || {}
|
||||
|
||||
@@ -1262,7 +1257,7 @@ export class RdDCombat {
|
||||
finalLevel: Misc.toInt(defenderRoll.competence.system.niveau) - dmg,
|
||||
showDice: HIDE_DICE
|
||||
});
|
||||
defenderRoll.show.desarme = desarme.rolled.isEchec;
|
||||
defenderRoll.show.desarme = desarme.rolled.isEchec
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1270,39 +1265,47 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async computeRecul(defenderRoll) { // Calcul du recul (p. 132)
|
||||
const attackerRoll = defenderRoll.attackerRoll;
|
||||
if (ReglesOptionnelles.isUsing('recul') && this._isForceOuCharge(attackerRoll)) {
|
||||
const impact = this._computeImpactRecul(attackerRoll);
|
||||
const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact });
|
||||
if (rollRecul.rolled.isSuccess) {
|
||||
defenderRoll.show.recul = 'encaisse';
|
||||
} else if (rollRecul.rolled.isETotal || this._isReculCauseChute(impact)) {
|
||||
defenderRoll.show.recul = 'chute';
|
||||
await this.defender.setEffect(STATUSES.StatusProne, true);
|
||||
}
|
||||
else {
|
||||
defenderRoll.show.recul = 'recul';
|
||||
}
|
||||
if (!ReglesOptionnelles.isUsing('recul')) {
|
||||
return
|
||||
}
|
||||
const attackerRoll = defenderRoll.attackerRoll;
|
||||
if (this._isForceOuCharge(attackerRoll, defenderRoll.v2)) {
|
||||
const impact = this._computeImpactRecul(attackerRoll);
|
||||
const rollRecul = await RdDResolutionTable.roll(10, impact)
|
||||
defenderRoll.show.recul = await this.gererRecul(rollRecul, impact)
|
||||
}
|
||||
}
|
||||
|
||||
async gererRecul(rolled, impact) {
|
||||
if (rolled.isSuccess) {
|
||||
return 'encaisse'
|
||||
}
|
||||
if (rolled.isETotal || this._isReculCauseChute(impact)) {
|
||||
|
||||
await this.defender.setEffect(STATUSES.StatusProne, true)
|
||||
return 'chute'
|
||||
}
|
||||
return 'recul'
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _isReculCauseChute(impact) {
|
||||
const agilite = this.defender.getAgilite();
|
||||
const chute = await RdDResolutionTable.rollData({ caracValue: agilite, finalLevel: impact });
|
||||
return chute.rolled.isEchec;
|
||||
const agilite = this.defender.getAgilite()
|
||||
const chute = await RdDResolutionTable.rollData({ caracValue: agilite, finalLevel: impact })
|
||||
return chute.rolled.isEchec
|
||||
}
|
||||
|
||||
_isForceOuCharge(attaque, isRollV2 = false /* TODO: delete roll V1 */) {
|
||||
return attaque.particuliere == 'force' || 'charge' == (isRollV2 ? attaque.tactique?.key : attaque.tactique)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_isForceOuCharge(attaque) {
|
||||
return attaque.particuliere == 'force' || attaque.tactique == 'charge';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_computeImpactRecul(attaque) {
|
||||
const taille = this.defender.getTaille();
|
||||
const force = this.attacker.getForce();
|
||||
const dommages = attaque.arme.system.dommagesReels ?? attaque.arme.system.dommages;
|
||||
_computeImpactRecul(attackerRoll) {
|
||||
const taille = this.defender.getTaille()
|
||||
const force = this.attacker.getForce()
|
||||
const dommages = attackerRoll.dmg /* TODO: delete roll V1 */
|
||||
? attackerRoll.dmg.dmgArme
|
||||
: attackerRoll.arme.system.dommagesReels ?? attaque.arme.system.dommages;
|
||||
return taille - (force + dommages);
|
||||
}
|
||||
|
||||
|
59
module/roll/chat-roll-result.mjs
Normal file
59
module/roll/chat-roll-result.mjs
Normal file
@@ -0,0 +1,59 @@
|
||||
import { ChatUtility } from "../chat-utility.js"
|
||||
import RollDialog from "./roll-dialog.mjs"
|
||||
import { RdDCarac } from "../rdd-carac.js";
|
||||
|
||||
export class ChatRollResult {
|
||||
|
||||
static onReady() {
|
||||
foundry.applications.handlebars.loadTemplates({
|
||||
'partial-appel-chance': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appel-chance.hbs',
|
||||
'partial-encaissement': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-encaissement.hbs',
|
||||
'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs',
|
||||
'partial-info-appel-moral': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-info-appel-moral.hbs',
|
||||
})
|
||||
}
|
||||
|
||||
async display(roll) {
|
||||
roll.show = roll.show || {};
|
||||
roll.show.chance = this.isAppelChancePossible(roll)
|
||||
roll.show.encaissement = this.isShowEncaissement(roll)
|
||||
roll.show.recul = this.isShowReculChoc(roll)
|
||||
|
||||
const chatMessage = await ChatUtility.createChatWithRollMode(
|
||||
{
|
||||
content: await this.buildRollHtml(roll)
|
||||
},
|
||||
roll.active.actor,
|
||||
roll.current?.rollmode?.key
|
||||
)
|
||||
if (roll.show.chance) {
|
||||
const save = RollDialog.saveParts(roll)
|
||||
console.log("Store message roll", save)
|
||||
ChatUtility.setMessageData(chatMessage, 'rollData', save)
|
||||
}
|
||||
return chatMessage
|
||||
}
|
||||
|
||||
isAppelChancePossible(roll) {
|
||||
return roll.active.actor.isPersonnage() &&
|
||||
roll.rolled.isEchec &&
|
||||
RdDCarac.isActionPhysique(roll.current.carac?.key)
|
||||
}
|
||||
|
||||
isShowEncaissement(roll) {
|
||||
return roll.rolled.isEchec &&
|
||||
roll.attackerRoll?.dmg.mortalite != 'empoignade'
|
||||
}
|
||||
|
||||
isShowReculChoc(roll) {
|
||||
return roll.rolled.isEchec &&
|
||||
roll.attackerRoll &&
|
||||
!roll.current.defense.isEsquive &&
|
||||
(roll.attackerRoll.particuliere == 'force' || 'charge' == attackerRoll.tactique?.key)
|
||||
}
|
||||
|
||||
async buildRollHtml(roll) {
|
||||
const template = `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-${roll.type.current}.hbs`
|
||||
return await foundry.applications.handlebars.renderTemplate(template, roll)
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
@@ -6,13 +6,12 @@ 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_TYPE_ATTAQUE } from "./roll-constants.mjs";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RollDialogAdapter {
|
||||
|
||||
async rollDice(rollData, rollTitle) {
|
||||
const chances = this.computeChances({
|
||||
static async rollDice(rollData, rollTitle) {
|
||||
const chances = RollDialogAdapter.computeChances({
|
||||
carac: rollData.current.carac.value,
|
||||
diff: rollData.current.totaldiff,
|
||||
bonus: rollData.current.bonus,
|
||||
@@ -21,13 +20,13 @@ export class RollDialogAdapter {
|
||||
rollMode: rollData.current.rollmode.key
|
||||
})
|
||||
|
||||
const rolled = await this.rollChances(rollData, chances)
|
||||
this.adjustRollDataForV1(rollData, rolled, rollTitle)
|
||||
const rolled = await RollDialogAdapter.rollChances(rollData, chances)
|
||||
RollDialogAdapter.adjustRollDataForV1(rollData, rolled, rollTitle)
|
||||
|
||||
return rolled
|
||||
}
|
||||
|
||||
computeChances({ carac, diff, bonus, sign, showDice, rollMode }) {
|
||||
static computeChances({ carac, diff, bonus, sign, showDice, rollMode }) {
|
||||
const chances = foundry.utils.duplicate(RdDResolutionTable.computeChances(carac, diff))
|
||||
RdDResolutionTable._updateChancesWithBonus(chances, bonus, diff)
|
||||
RdDResolutionTable._updateChancesFactor(chances, sign)
|
||||
@@ -36,7 +35,7 @@ export class RollDialogAdapter {
|
||||
return chances
|
||||
}
|
||||
|
||||
async rollChances(rollData, chances) {
|
||||
static async rollChances(rollData, chances) {
|
||||
const rolled = await RdDResolutionTable.rollChances(chances,
|
||||
rollData.current.sign,
|
||||
rollData.current.resultat)
|
||||
@@ -47,7 +46,7 @@ export class RollDialogAdapter {
|
||||
return rolled
|
||||
}
|
||||
|
||||
adjustRollDataForV1(rollData, rolled, rollTitle) {
|
||||
static adjustRollDataForV1(rollData, rolled, rollTitle) {
|
||||
// temporaire pour être homogène roll v1
|
||||
rollData.alias = rollData.active.actor.getAlias()
|
||||
// pour experience
|
||||
|
@@ -38,7 +38,8 @@ import { RollPartDefense } from "./roll-part-defense.mjs";
|
||||
import { RollDialogAdapter } from "./roll-dialog-adapter.mjs";
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs";
|
||||
import { ROLL_TYPE_COMP } from "./roll-constants.mjs";
|
||||
import { RollChatResult } from "./roll-chat-result.mjs";
|
||||
import { ChatRollResult } from "./chat-roll-result.mjs";
|
||||
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
|
||||
const doNothing = (dialog) => { }
|
||||
@@ -48,11 +49,12 @@ const ALL_ROLL_TYPES = [
|
||||
new RollTypeTache(),
|
||||
new RollTypeAttaque(),
|
||||
new RollTypeDefense(),
|
||||
// new RollTypeResistance ??
|
||||
new RollTypeSort(),
|
||||
new RollTypeMeditation(),
|
||||
new RollTypeOeuvre(),
|
||||
new RollTypeJeu(),
|
||||
// new RollTypeResistance ??
|
||||
// new RollTypeFixedCarac ??
|
||||
]
|
||||
|
||||
const BASIC_PARTS = new RollBasicParts()
|
||||
@@ -182,6 +184,8 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
'roll-button': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-button.hbs',
|
||||
})
|
||||
|
||||
ChatRollResult.onReady()
|
||||
|
||||
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())
|
||||
@@ -246,9 +250,49 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
// rien pour l'instant
|
||||
}
|
||||
|
||||
/** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */
|
||||
static $prepareRollData(rollData) {
|
||||
rollData.current = rollData.current ?? {}
|
||||
rollData.selected = rollData.selected ?? {}
|
||||
rollData.type = rollData.type ?? {}
|
||||
rollData.type.retry = rollData.type.retry ?? false
|
||||
BASIC_PARTS.restore(rollData)
|
||||
|
||||
const potential = ALL_ROLL_TYPES.find(m => m.code == rollData.type.current)?.code
|
||||
const allowed = rollData.type.retry && potential
|
||||
? [potential]
|
||||
: (rollData.type.allowed ?? ALL_ROLL_TYPES.filter(m => m.isAllowed(rollData) && m.visible(rollData)).map(m => m.code))
|
||||
const rollType = allowed.find(c => c == rollData.type.current) ?? (allowed.length > 0 ? allowed[0].code : ROLL_TYPE_COMP);
|
||||
|
||||
rollData.type.allowed = allowed
|
||||
rollData.type.current = rollType
|
||||
ALL_ROLL_TYPES.find(m => m.code == rollType).setRollDataType(rollData)
|
||||
|
||||
rollData.refs = foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(ROLL_PARTS.map(p => [p.code, {}])));
|
||||
rollData.options = rollData.options ?? { rollMode: game.settings.get("core", "rollMode") }
|
||||
|
||||
ROLL_PARTS.forEach(p => p.initialize(rollData))
|
||||
ROLL_PARTS.forEach(p => p.restore(rollData))
|
||||
ROLL_PARTS.filter(p => p.isValid(rollData))
|
||||
.forEach(p => {
|
||||
p.loadRefs(rollData)
|
||||
p.prepareContext(rollData)
|
||||
})
|
||||
return rollData
|
||||
}
|
||||
|
||||
static saveParts(rollData) {
|
||||
const target = BASIC_PARTS.initFrom(rollData)
|
||||
ROLL_PARTS.filter(p => p.isActive(rollData))
|
||||
.forEach(p => p.storeClean(rollData, target))
|
||||
target.attackerRoll = rollData.attackerRoll
|
||||
return target
|
||||
}
|
||||
|
||||
constructor(rollData, rollOptions) {
|
||||
super()
|
||||
this.rollData = rollData
|
||||
|
||||
this.rollData = RollDialog.$prepareRollData(rollData)
|
||||
this.rollOptions = {
|
||||
callbacks: [
|
||||
async r => await r.active.actor.appliquerAjoutExperience(r),
|
||||
@@ -258,37 +302,8 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
customChatMessage: rollOptions.customChatMessage,
|
||||
onRollDone: rollOptions.onRollDone ?? doNothing
|
||||
}
|
||||
this.$loadParts()
|
||||
}
|
||||
|
||||
/** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */
|
||||
$loadParts() {
|
||||
const rollData = this.rollData;
|
||||
rollData.current = rollData.current ?? {}
|
||||
rollData.selected = rollData.selected ?? {}
|
||||
rollData.type = rollData.type ?? {}
|
||||
rollData.type.retry = rollData.type.retry ?? false
|
||||
BASIC_PARTS.restore(rollData)
|
||||
|
||||
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.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.getSelectedType().setRollDataType(rollData)
|
||||
|
||||
rollData.refs = this.$prepareRefs(rollData)
|
||||
rollData.options = rollData.options ?? { showDice: true, rollMode: game.settings.get("core", "rollMode") }
|
||||
|
||||
ROLL_PARTS.forEach(p => p.initialize(rollData))
|
||||
ROLL_PARTS.forEach(p => p.restore(rollData))
|
||||
ROLL_PARTS.filter(p => p.isValid(rollData))
|
||||
.forEach(p => {
|
||||
p.loadRefs(rollData)
|
||||
p.prepareContext(rollData)
|
||||
})
|
||||
this.selectType();
|
||||
this.chatRollResult = new ChatRollResult();
|
||||
this.selectType()
|
||||
}
|
||||
|
||||
selectType() {
|
||||
@@ -301,23 +316,21 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
ROLL_PARTS.find(it => it.code == PART_COMP).filterComps(this.rollData)
|
||||
}
|
||||
|
||||
$prepareRefs(rollData) {
|
||||
return foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(ROLL_PARTS.map(p => [p.code, {}])));
|
||||
}
|
||||
|
||||
$saveParts() {
|
||||
const target = BASIC_PARTS.initFrom(this.rollData)
|
||||
ROLL_PARTS.filter(p => p.isActive(this.rollData))
|
||||
.forEach(p => p.store(this.rollData, target))
|
||||
return target
|
||||
}
|
||||
|
||||
getActiveParts() {
|
||||
return ROLL_PARTS.filter(p => p.isActive(this.rollData))
|
||||
}
|
||||
|
||||
get title() {
|
||||
return this.rollData.title ?? `Jet de dés de ${this.rollData.active.actor.name}`
|
||||
// get title() {
|
||||
// return this.rollData.title ?? `Jet de dés de ${this.rollData.active.actor.name}`
|
||||
// }
|
||||
|
||||
rollTitle(rollData) {
|
||||
return rollData.label ?? ROLL_PARTS
|
||||
.filter(it => it.section == ROLLDIALOG_SECTION.ACTION)
|
||||
.filter(it => it.isActive(rollData))
|
||||
.map(it => it.title(rollData))
|
||||
.reduce(Misc.joining(' '))
|
||||
}
|
||||
|
||||
async _onRender(context, options) {
|
||||
@@ -344,9 +357,9 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
)
|
||||
}
|
||||
|
||||
getAjustements() {
|
||||
getAjustements(rollData = this.rollData) {
|
||||
return this.getActiveParts()
|
||||
.map(p => p.getAjustements(this.rollData))
|
||||
.map(p => p.getAjustements(rollData))
|
||||
.reduce((a, b) => a.concat(b))
|
||||
.sort((a, b) => a.diff == undefined ? 1 : b.diff == undefined ? -1 : 0)
|
||||
}
|
||||
@@ -392,10 +405,10 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
}
|
||||
}
|
||||
|
||||
calculAjustements() {
|
||||
this.rollData.ajustements = this.getAjustements()
|
||||
this.rollData.ajustements.forEach(it => it.isDiff = it.diff != undefined)
|
||||
this.rollData.current.totaldiff = this.rollData.ajustements
|
||||
calculAjustements(rollData = this.rollData) {
|
||||
rollData.ajustements = this.getAjustements(rollData)
|
||||
rollData.ajustements.forEach(it => it.isDiff = it.diff != undefined)
|
||||
rollData.current.totaldiff = rollData.ajustements
|
||||
.map(adj => adj.diff)
|
||||
.filter(d => d != undefined)
|
||||
.reduce(Misc.sum(), 0)
|
||||
@@ -406,36 +419,27 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
}
|
||||
|
||||
async roll() {
|
||||
this.calculAjustements()
|
||||
const rollData = this.rollData
|
||||
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)))
|
||||
if (!this.rollOptions.customChatMessage) {
|
||||
const rollChatResult = new RollChatResult(this.getSelectedType())
|
||||
await rollChatResult.display(this.rollData)
|
||||
rollData.active.actor.$onRollCompetence(this.rollData)
|
||||
}
|
||||
|
||||
const roll = RollDialog.saveParts(this.rollData)
|
||||
RollDialog.$prepareRollData(roll)
|
||||
this.calculAjustements(roll)
|
||||
roll.current.resultat = this.rollData.current.resultat
|
||||
roll.v2 = true
|
||||
roll.rolled = await this.$rollDice(roll)
|
||||
roll.result = this.getSelectedType(roll).getResult(roll)
|
||||
console.info('RollDialog.roll:', roll)
|
||||
await Promise.all(this.rollOptions.callbacks.map(async callback => await callback(roll)))
|
||||
await this.chatRollResult.display(roll)
|
||||
|
||||
this.rollOptions.onRollDone(this)
|
||||
}
|
||||
|
||||
|
||||
async defaultCallback(rollData, rolled) {
|
||||
await rollData.active.actor.appliquerAjoutExperience(rollData)
|
||||
await rollData.active.actor.appliquerAppelMoral(rollData)
|
||||
}
|
||||
|
||||
async $rollDice(rollData) {
|
||||
const adapter = new RollDialogAdapter(ROLL_PARTS);
|
||||
return await adapter.rollDice(rollData, this.rollTitle(rollData));
|
||||
}
|
||||
|
||||
rollTitle(rollData) {
|
||||
return ROLL_PARTS
|
||||
.filter(it => it.section == ROLLDIALOG_SECTION.ACTION)
|
||||
.filter(it => it.isActive(rollData))
|
||||
.map(it => it.title(rollData))
|
||||
.reduce(Misc.joining(' '))
|
||||
return await RollDialogAdapter.rollDice(rollData, this.rollTitle(rollData));
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,8 @@
|
||||
import { RdDBonus } from "../rdd-bonus.js"
|
||||
import { StatusEffects } from "../settings/status-effects.js"
|
||||
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"
|
||||
import { PART_SIGN } from "./roll-part-sign.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
export const PART_ATTAQUE = 'attaque'
|
||||
@@ -28,6 +26,16 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
}
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
super.store(rollData, targetData)
|
||||
this.getSaved(targetData).dmg = this.getCurrent(rollData).dmg
|
||||
}
|
||||
|
||||
restore(rollData) {
|
||||
super.restore(rollData)
|
||||
this.getCurrent(rollData).dmg = this.getSaved(rollData).dmg
|
||||
}
|
||||
|
||||
choices(refs) { return refs.attaques }
|
||||
|
||||
static $extractAttaque(attaque, actor) {
|
||||
|
@@ -43,6 +43,7 @@ export class RollPartCarac extends RollPartSelect {
|
||||
// ? refs.all.filter(it => allowed.includes(Grammar.toLowerCaseNoAccent(it.key)))
|
||||
? refs.all.filter(it => allowed.includes(it.key))
|
||||
: refs.all
|
||||
this.$selectCarac(rollData)
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
|
@@ -52,6 +52,7 @@ export class RollPartComp extends RollPartSelect {
|
||||
// ? refs.all.filter(it => allowed.includes(Grammar.toLowerCaseNoAccent(it.label)))
|
||||
? refs.all.filter(it => allowed.includes(it.label))
|
||||
: refs.all
|
||||
this.$selectComp(rollData)
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
|
@@ -27,14 +27,14 @@ export class RollPartDefense extends RollPartSelect {
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
const attaque = rollData.attaque
|
||||
const attackerRoll = rollData.attackerRoll
|
||||
const defenseur = rollData.active.actor
|
||||
refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attaque?.main)
|
||||
refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attackerRoll?.main)
|
||||
const esquives = refs.isDistance == ATTAQUE_TYPE.TIR ? [] : defenseur.getCompetencesEsquive()
|
||||
.map(it => RollPartDefense.$extractEsquive(it, defenseur))
|
||||
|
||||
const parades = defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier()))
|
||||
.map(it => RollPartDefense.$extractParade(it, attaque?.attaque.arme, defenseur))
|
||||
.map(it => RollPartDefense.$extractParade(it, attackerRoll?.attaque.arme, defenseur))
|
||||
|
||||
refs.defenses = [...esquives, ...parades].filter(it => it != undefined)
|
||||
this.$selectDefense(rollData)
|
||||
@@ -48,7 +48,8 @@ export class RollPartDefense extends RollPartSelect {
|
||||
// TODO: carac pour créatures
|
||||
carac: defenseur.isPersonnage() ? CARACS.DEROBEE : esquive.name,
|
||||
verb: "esquive",
|
||||
comp: esquive
|
||||
comp: esquive,
|
||||
isEsquive: true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +67,8 @@ export class RollPartDefense extends RollPartSelect {
|
||||
comp: comp,
|
||||
arme: armeDefense,
|
||||
forceRequise: armeDefense ? RdDItemArme.valeurMain(armeDefense.system.force ?? 0, RdDItemArme.getMainAttaque(comp)) : 0,
|
||||
typeParade: armeAttaque ? RdDItemArme.defenseArmeParade(armeDefense, armeAttaque) : 'norm'
|
||||
typeParade: armeAttaque ? RdDItemArme.defenseArmeParade(armeDefense, armeAttaque) : 'norm',
|
||||
isEsquive: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +113,7 @@ export class RollPartDefense extends RollPartSelect {
|
||||
isArmeDisparate(rollData) {
|
||||
const armeDefense = this.getCurrent(rollData).arme
|
||||
if (armeDefense) {
|
||||
const armeAttaque = rollData.attaque?.attaque.arme
|
||||
const armeAttaque = rollData.attackerRoll?.attaque.arme
|
||||
return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign'
|
||||
}
|
||||
return false
|
||||
@@ -120,12 +122,12 @@ export class RollPartDefense extends RollPartSelect {
|
||||
getDiffDefense(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
const refs = this.getRefs(rollData)
|
||||
if (refs.isDistance || !rollData.attaque) {
|
||||
if (refs.isDistance || !rollData.attackerRoll) {
|
||||
// Déterminer la difficulté de parade
|
||||
return { diff: 0, type: DIFF.LIBRE }
|
||||
}
|
||||
else {
|
||||
return { diff: rollData.attaque.diff ?? 0, type: DIFF.DEFENSE }
|
||||
return { diff: rollData.attackerRoll.diff ?? 0, type: DIFF.DEFENSE }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { Misc } from "../misc.js"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
import { ROLL_TYPE_OEUVRE } from "./roll-constants.mjs"
|
||||
@@ -59,6 +58,7 @@ export class RollPartOeuvre extends RollPartSelect {
|
||||
label: oeuvre.name,
|
||||
art: art,
|
||||
caracs: art.caracs(oeuvre),
|
||||
qualite: oeuvre.system.niveau,
|
||||
value: -oeuvre.system.niveau,
|
||||
oeuvre: oeuvre,
|
||||
comp: actor.getCompetence(art.competence(oeuvre))
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
const PART_TRICHER = "tricher"
|
||||
export const PART_TRICHER = "tricher"
|
||||
|
||||
export class RollPartTricher extends RollPart {
|
||||
|
||||
|
@@ -53,7 +53,23 @@ export class RollPart {
|
||||
}
|
||||
|
||||
restore(rollData) { }
|
||||
store(rollData, targetData) { }
|
||||
|
||||
storeClean(rollData, targetData) {
|
||||
this.store(rollData, targetData)
|
||||
if (rollData.selected[this.code]) {
|
||||
const toDelete = Object.entries(rollData.selected[this.code])
|
||||
.map(([k, v]) => v == undefined ? k : undefined)
|
||||
.filter(k => k != undefined)
|
||||
toDelete.forEach(k => delete rollData.selected[this.code][k])
|
||||
if (Object.keys(rollData.selected[this.code]).length == 0) {
|
||||
delete rollData.selected[this.code]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
this.setSaved(targetData, { key: this.getCurrent(rollData).key })
|
||||
}
|
||||
|
||||
/**
|
||||
* le texte à ajouter dans la barre de titre
|
||||
@@ -92,4 +108,14 @@ export class RollPart {
|
||||
|
||||
async _onRender(rollDialog, context, options) { }
|
||||
|
||||
addResult(rollData) {
|
||||
const result = this.getResult(rollData)
|
||||
if (result){
|
||||
rollData.result[this.code] = result
|
||||
}
|
||||
}
|
||||
|
||||
getResult(rollData){
|
||||
return undefined
|
||||
}
|
||||
}
|
@@ -15,5 +15,14 @@ export class RollTypeOeuvre extends RollType {
|
||||
onSelect(rollData) {
|
||||
this.setDiffType(rollData, DIFF.AUCUN)
|
||||
}
|
||||
|
||||
getResult(rollData){
|
||||
const current = rollData.current[PART_OEUVRE]
|
||||
const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau)
|
||||
return {
|
||||
qualite: qualite + rollData.rolled.ptQualite
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -52,4 +52,8 @@ export class RollType {
|
||||
rollData.current[PART_DIFF].type = type
|
||||
this.setRollDataType(rollData)
|
||||
}
|
||||
|
||||
getResult(rollData){
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user