Migration datamodels !
This commit is contained in:
334
modules/applications/yggdrasill-roll-dialog.mjs
Normal file
334
modules/applications/yggdrasill-roll-dialog.mjs
Normal file
@@ -0,0 +1,334 @@
|
||||
import { YggdrasillUtility } from "../yggdrasill-utility.js"
|
||||
|
||||
const dureeGaldrSD = { "1d5a": 3, "1d10t": 6, "1d10m": 9, "1d10h": 12, "1d5j": 15}
|
||||
const ciblesGaldrSD = { "1": 3, "2_4": 6, "5_9": 9, "10_49": 12, "50plus": 15}
|
||||
const zonesciblesGaldrSD = { "INS10cm3": 3, "INS50cm3": 6, "INS1m3": 9, "INS5m3": 12, "INS10m3": 15}
|
||||
|
||||
/**
|
||||
* Dialogue de jet de dé pour Yggdrasill - Version DialogV2
|
||||
*/
|
||||
export class YggdrasillRollDialog {
|
||||
|
||||
/**
|
||||
* Create and display the roll dialog
|
||||
* @param {YggdrasillActor} actor - The actor making the roll
|
||||
* @param {Object} rollData - Data for the roll
|
||||
* @returns {Promise}
|
||||
*/
|
||||
static async create(actor, rollData) {
|
||||
// Initialiser attackData pour les armes si nécessaire
|
||||
if ((rollData.mode === "armecc" || rollData.mode === "armetir" || rollData.mode === "armedist") && rollData.attackDef) {
|
||||
// Les données sont déjà calculées dans attackDef par getAttaqueData/getTirData
|
||||
// On les copie simplement dans attackData pour le template
|
||||
rollData.attackData = { ...rollData.attackDef }
|
||||
}
|
||||
|
||||
// Calculer srTotal pour les sorts
|
||||
if (rollData.mode === "galdr") {
|
||||
this._updateGaldrSD(rollData)
|
||||
rollData.srTotal = 14 + (rollData.sdGaldr || 0)
|
||||
} else if (rollData.mode === "sejdr") {
|
||||
rollData.srTotal = 14 + (rollData.bonusdefense || 0)
|
||||
} else if (rollData.mode === "rune") {
|
||||
this._updateRuneData(rollData, actor)
|
||||
}
|
||||
|
||||
// Préparer le contexte pour le template
|
||||
const context = {
|
||||
...rollData,
|
||||
img: actor.img,
|
||||
name: actor.name,
|
||||
config: game.system.yggdrasill.config,
|
||||
}
|
||||
|
||||
// Titre selon le mode
|
||||
let title = "Test"
|
||||
if (rollData.mode === "competence") title = "Test de Compétence"
|
||||
else if (rollData.mode === "carac") title = "Test de Caractéristique"
|
||||
else if (rollData.mode === "attribut") title = "Test d'Attribut"
|
||||
else if (rollData.mode === "armecc") title = "Attaque au Corps à Corps"
|
||||
else if (rollData.mode === "armetir" || rollData.mode === "armedist") title = "Attaque à Distance"
|
||||
else if (rollData.mode === "sejdr") title = "Sort Sejdr"
|
||||
else if (rollData.mode === "galdr") title = "Sort Galdr"
|
||||
else if (rollData.mode === "rune") title = "Rune"
|
||||
|
||||
// Rendre le template en HTML
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
"systems/fvtt-yggdrasill/templates/roll-dialog-generic-new.hbs",
|
||||
context
|
||||
)
|
||||
|
||||
// Utiliser DialogV2.wait avec le HTML rendu
|
||||
return foundry.applications.api.DialogV2.wait({
|
||||
window: {
|
||||
title: title,
|
||||
icon: "fa-solid fa-dice-d20"
|
||||
},
|
||||
classes: ["yggdrasill-roll-dialog"],
|
||||
position: { width: 600 },
|
||||
modal: false,
|
||||
content,
|
||||
buttons: [
|
||||
{
|
||||
action: "roll",
|
||||
label: "Lancer le Test",
|
||||
icon: "fa-solid fa-dice",
|
||||
default: true,
|
||||
callback: (event, button, dialog) => {
|
||||
this._updateRollDataFromForm(rollData, button.form.elements, actor)
|
||||
this._performRoll(rollData)
|
||||
}
|
||||
},
|
||||
],
|
||||
actions: {},
|
||||
render: (event, dialog) => {
|
||||
// Pour Galdr: recalculer srTotal quand durée, cibles ou zone changent
|
||||
if (rollData.mode === "galdr") {
|
||||
$("#dureeGaldr, #nbCibles, #zoneGaldr").on("change", () => {
|
||||
rollData.dureeGaldr = $("#dureeGaldr").val()
|
||||
rollData.nbCibles = $("#nbCibles").val()
|
||||
rollData.zoneGaldr = $("#zoneGaldr").val()
|
||||
this._updateGaldrSD(rollData)
|
||||
rollData.srTotal = 14 + (rollData.sdGaldr || 0)
|
||||
$("#srTotal").text(rollData.srTotal)
|
||||
})
|
||||
}
|
||||
|
||||
// Pour Sejdr: recalculer srTotal quand DM change
|
||||
if (rollData.mode === "sejdr") {
|
||||
$("#bonusdefense").on("change", () => {
|
||||
rollData.bonusdefense = parseInt($("#bonusdefense").val()) || 0
|
||||
rollData.srTotal = 14 + rollData.bonusdefense
|
||||
$("#srTotal").text(rollData.srTotal)
|
||||
})
|
||||
}
|
||||
|
||||
// Pour Rune: recalculer srTotal quand support ou puissance changent
|
||||
if (rollData.mode === "rune") {
|
||||
$("#supportRune, #puissanceRune").on("change", () => {
|
||||
rollData.supportRune = $("#supportRune").val()
|
||||
rollData.puissanceRune = parseInt($("#puissanceRune").val()) || 1
|
||||
this._updateRuneData(rollData, actor)
|
||||
$("#runeDuree").text(rollData.runeDuree)
|
||||
$("#runeDureeVie").text(rollData.runeDureeVie)
|
||||
$("#srTotal").text(rollData.srTotal)
|
||||
})
|
||||
}
|
||||
},
|
||||
rejectClose: false,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the roll based on mode
|
||||
* @param {Object} rollData - The roll data
|
||||
* @private
|
||||
*/
|
||||
static _performRoll(rollData) {
|
||||
if (rollData.mode === "attribut") {
|
||||
YggdrasillUtility.rollAttribute(rollData)
|
||||
} else {
|
||||
YggdrasillUtility.rollYggdrasill(rollData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mettre à jour rollData avec les valeurs du formulaire
|
||||
* @param {Object} rollData - L'objet rollData à mettre à jour
|
||||
* @param {HTMLFormControlsCollection} formElements - Les éléments du formulaire
|
||||
* @param {YggdrasillActor} actor - L'acteur pour récupérer les données
|
||||
* @private
|
||||
*/
|
||||
static _updateRollDataFromForm(rollData, formElements, actor) {
|
||||
// Caractéristique (pour compétences)
|
||||
if (formElements.caracName) {
|
||||
const caracKey = formElements.caracName.value
|
||||
rollData.caracName = caracKey
|
||||
rollData.selectedCarac = this._findCaracByKey(actor, caracKey)
|
||||
}
|
||||
|
||||
// Type d'attaque (pour armes)
|
||||
if (formElements.typeAttack) {
|
||||
rollData.attackDef = rollData.attackDef || {}
|
||||
rollData.attackDef.typeAttack = formElements.typeAttack.value
|
||||
this._updateAttackData(rollData, actor)
|
||||
}
|
||||
|
||||
// Bonus/Malus
|
||||
if (formElements.bonusMalus) {
|
||||
rollData.bonusMalus = parseInt(formElements.bonusMalus.value) || 0
|
||||
}
|
||||
|
||||
// Furor
|
||||
if (formElements.furorUsage) {
|
||||
rollData.furorUsage = parseInt(formElements.furorUsage.value) || 0
|
||||
}
|
||||
|
||||
// Seuil de Réussite
|
||||
if (formElements.sr) {
|
||||
rollData.sr = parseInt(formElements.sr.value) || 9
|
||||
}
|
||||
|
||||
// Galdr options
|
||||
if (formElements.dureeGaldr) {
|
||||
rollData.dureeGaldr = formElements.dureeGaldr.value
|
||||
}
|
||||
if (formElements.nbCibles) {
|
||||
rollData.nbCibles = formElements.nbCibles.value
|
||||
}
|
||||
if (formElements.zoneGaldr) {
|
||||
rollData.zoneGaldr = formElements.zoneGaldr.value
|
||||
}
|
||||
if (rollData.mode === "galdr") {
|
||||
this._updateGaldrSD(rollData)
|
||||
rollData.srTotal = 14 + (rollData.sdGaldr || 0)
|
||||
}
|
||||
|
||||
// Sejdr options
|
||||
if (formElements.bonusdefense) {
|
||||
rollData.bonusdefense = parseInt(formElements.bonusdefense.value) || 0
|
||||
}
|
||||
if (rollData.mode === "sejdr") {
|
||||
rollData.srTotal = 14 + (rollData.bonusdefense || 0)
|
||||
}
|
||||
|
||||
// Rune options
|
||||
if (formElements.runeDuree) {
|
||||
rollData.runeDuree = formElements.runeDuree.value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find characteristic by key in actor
|
||||
* @param {YggdrasillActor} actor
|
||||
* @param {String} caracKey
|
||||
* @returns {Object}
|
||||
* @private
|
||||
*/
|
||||
static _findCaracByKey(actor, caracKey) {
|
||||
for (let [categKey, categ] of Object.entries(actor.system.carac)) {
|
||||
for (let [key, carac] of Object.entries(categ.carac)) {
|
||||
if (key === caracKey) {
|
||||
return { ...carac, categName: categKey, caracName: key }
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Update attack data based on attack type
|
||||
* @param {Object} rollData
|
||||
* @param {YggdrasillActor} actor
|
||||
* @private
|
||||
*/
|
||||
static _updateAttackData(rollData, actor) {
|
||||
const config = game.system.yggdrasill.config
|
||||
const attackType = rollData.attackDef.typeAttack
|
||||
const attackMode = config.attackMode?.[attackType]
|
||||
|
||||
if (attackMode) {
|
||||
rollData.attackData = rollData.attackData || {}
|
||||
rollData.attackData.categName = attackMode.categName
|
||||
rollData.attackData.caracName = attackMode.caracName
|
||||
rollData.attackData.malus = this._computeValue(attackMode.malus, actor)
|
||||
rollData.attackData.bonusdegats = this._computeValue(attackMode.bonusdegats, actor)
|
||||
rollData.attackData.protection = this._computeValue(attackMode.protection, actor)
|
||||
rollData.attackData.label = attackMode.label
|
||||
rollData.attackData.description = attackMode.description
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute value from string formula like "puissance;3"
|
||||
* @param {String|Number} value
|
||||
* @param {YggdrasillActor} actor
|
||||
* @returns {Number}
|
||||
* @private
|
||||
*/
|
||||
static _computeValue(value, actor) {
|
||||
if (typeof value === 'number') return value
|
||||
if (!value || value === "0") return 0
|
||||
|
||||
const parts = String(value).split(';')
|
||||
if (parts.length === 2) {
|
||||
const caracName = parts[0]
|
||||
const multiplier = parseInt(parts[1]) || 1
|
||||
const caracValue = this._getCaracValue(actor, caracName)
|
||||
return caracValue * multiplier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Get characteristic value by name
|
||||
* @param {YggdrasillActor} actor
|
||||
* @param {String} caracName
|
||||
* @returns {Number}
|
||||
* @private
|
||||
*/
|
||||
static _getCaracValue(actor, caracName) {
|
||||
for (let categ of Object.values(actor.system.carac)) {
|
||||
if (categ.carac && categ.carac[caracName]) {
|
||||
return categ.carac[caracName].value || 0
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Update rune data based on support and power
|
||||
* @param {Object} rollData
|
||||
* @param {YggdrasillActor} actor
|
||||
* @private
|
||||
*/
|
||||
static _updateRuneData(rollData, actor) {
|
||||
let support = 0
|
||||
|
||||
rollData.dureeRune = 6 - (rollData.agiliteCarac?.value || 0)
|
||||
|
||||
if (rollData.supportRune === "peau") {
|
||||
support = 3
|
||||
rollData.echelleDuree = "Actions"
|
||||
rollData.echelleDureeVie = "Heures"
|
||||
} else if (rollData.supportRune === "tissu") {
|
||||
support = 6
|
||||
rollData.echelleDuree = "Tours"
|
||||
rollData.echelleDureeVie = "Jours"
|
||||
} else if (rollData.supportRune === "cuir") {
|
||||
support = 9
|
||||
rollData.echelleDuree = "Minutes"
|
||||
rollData.echelleDureeVie = "Semaines"
|
||||
} else if (rollData.supportRune === "bois") {
|
||||
support = 12
|
||||
rollData.echelleDuree = "Heures"
|
||||
rollData.echelleDureeVie = "Mois"
|
||||
} else if (rollData.supportRune === "pierremetal") {
|
||||
support = 15
|
||||
rollData.echelleDuree = "Jours"
|
||||
rollData.echelleDureeVie = "Années"
|
||||
}
|
||||
|
||||
rollData.runeDuree = `${rollData.dureeRune} ${rollData.echelleDuree}`
|
||||
rollData.runeDureeVie = `${rollData.competence?.system.niveau || 1} ${rollData.echelleDureeVie}`
|
||||
rollData.srTotal = (rollData.puissanceRune || 1) + (Number(rollData.sort?.system.niveau || 0) * 3) + support
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Galdr SD based on duration and targets
|
||||
* @param {Object} rollData
|
||||
* @private
|
||||
*/
|
||||
static _updateGaldrSD(rollData) {
|
||||
let sdDuree = Number(dureeGaldrSD[rollData.dureeGaldr]) || 0
|
||||
let sdVar = 0
|
||||
|
||||
if (rollData.sort?.system.voie === "illusion") {
|
||||
sdVar = Number(zonesciblesGaldrSD[rollData.zoneGaldr]) || 0
|
||||
} else {
|
||||
sdVar = Number(ciblesGaldrSD[rollData.nbCibles]) || 0
|
||||
}
|
||||
|
||||
rollData.sdGaldr = sdDuree + sdVar
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user