DataModels + Appv2 migration : OK

This commit is contained in:
2026-03-01 01:12:00 +01:00
parent 1ffb8b08fc
commit 6c70dc147c
130 changed files with 2998 additions and 741 deletions

View File

@@ -5,11 +5,6 @@ const _apt2attr = { init: "mind", melee: "agility", ranged: "agility", def: "vig
/* -------------------------------------------- */
export class BoLRoll {
/* -------------------------------------------- */
static options() {
return { classes: ["bol", "dialog"], width: 480, height: 'fit-content' };
}
/* -------------------------------------------- */
static getDefaultAttribute(key) {
return _apt2attr[key]
@@ -129,7 +124,7 @@ export class BoLRoll {
rangeMsg = "BOL.chat.range6"
}
ChatMessage.create({
content: await renderTemplate('systems/bol/templates/chat/chat-info-range.hbs', {
content: await foundry.applications.handlebars.renderTemplate('systems/bol/templates/chat/chat-info-range.hbs', {
weapon: weapon,
attackerName: _token.actor.name,
defenderName: target.actor.name,
@@ -308,26 +303,31 @@ export class BoLRoll {
// Final number of dices
this.rollData.nbDice = 2 + Math.abs(this.rollData.bmDice)
// Bonus or Malus ?
if (this.rollData.bmDice == 0) {
$('#roll-nbdice').val("2")
} else {
let letter = (this.rollData.bmDice > 0) ? "B" : "M"
$('#roll-nbdice').val("2 + " + String(Math.abs(this.rollData.bmDice)) + letter)
const nbDiceEl = document.querySelector('#roll-nbdice')
if (nbDiceEl) {
if (this.rollData.bmDice == 0) {
nbDiceEl.value = "2"
} else {
let letter = (this.rollData.bmDice > 0) ? "B" : "M"
nbDiceEl.value = "2 + " + String(Math.abs(this.rollData.bmDice)) + letter
}
}
let rollbase = this.rollData.attrValue + "+" + this.rollData.aptValue
if (this.rollData.weapon && this.rollData.weapon.system.properties.onlymodifier) {
rollbase = ""
}
$('#roll-modifier').val(rollbase + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" +
const modifierEl = document.querySelector('#roll-modifier')
if (modifierEl) modifierEl.value = rollbase + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" +
this.rollData.modRanged + "+" + this.rollData.weaponModifier + "-" + this.rollData.defence + "-" + this.rollData.modArmorMalus + "-" +
this.rollData.shieldMalus + "+" + this.rollData.attackModifier + "+" + this.rollData.appliedArmorMalus + "+" + effectModifier)
this.rollData.shieldMalus + "+" + this.rollData.attackModifier + "+" + this.rollData.appliedArmorMalus + "+" + effectModifier
// Rebuild lits of applicable effects
// Rebuild list of applicable effects
let selectEffects = ""
for (let effect of this.rollData.bolApplicableEffects) {
selectEffects += `<option value="${effect.id}" selected>${effect.name}</option>`
}
$('#applicable-effects').html(selectEffects)
const effectsEl = document.querySelector('#applicable-effects')
if (effectsEl) effectsEl.innerHTML = selectEffects
}
/* -------------------------------------------- */
@@ -360,46 +360,48 @@ export class BoLRoll {
/* -------------------------------------------- */
static updateArmorMalus(rollData) {
rollData.appliedArmorMalus = 0
const agiEl = document.querySelector('#armor-agi-malus')
if (rollData.attribute.key == "agility") {
$("#armor-agi-malus").show()
if (agiEl) agiEl.style.display = ''
rollData.appliedArmorMalus += rollData.armorAgiMalus
} else {
$("#armor-agi-malus").hide()
if (agiEl) agiEl.style.display = 'none'
}
const initEl = document.querySelector('#armor-init-malus')
if (rollData.aptitude && rollData.aptitude.key == "init") {
$("#armor-init-malus").show()
if (initEl) initEl.style.display = ''
rollData.appliedArmorMalus += rollData.armorInitMalus
} else {
$("#armor-init-malus").hide()
if (initEl) initEl.style.display = 'none'
}
}
/* ------------------------------ -------------- */
static updatePPCost(rollData) {
$('#ppcost').html(rollData.ppCost + " + Armor(" + rollData.ppCostArmor + ")=" + Number(rollData.ppCost + rollData.ppCostArmor))
const el = document.querySelector('#ppcost')
if (el) el.innerHTML = rollData.ppCost + " + Armor(" + rollData.ppCostArmor + ")=" + Number(rollData.ppCost + rollData.ppCostArmor)
}
/* ------------------------------ -------------- */
static rollDialogListener(html) {
this.updateTotalDice()
html.find('#optcond').change((event) => { // Dynamic change of PP cost of spell
html.querySelector('#optcond')?.addEventListener('change', (event) => {
let pp = BoLUtility.computeSpellCost(this.rollData.spell, event.currentTarget.selectedOptions.length)
this.rollData.ppCost = pp
this.updatePPCost(this.rollData)
})
html.find('#mod').change((event) => {
html.querySelector('#mod')?.addEventListener('change', (event) => {
this.rollData.mod = Number(event.currentTarget.value)
this.updateTotalDice()
})
html.find('#modRanged').change((event) => {
html.querySelector('#modRanged')?.addEventListener('change', (event) => {
this.rollData.modRanged = Number(event.currentTarget.value)
this.updateTotalDice()
})
html.find('#attr').change((event) => {
html.querySelector('#attr')?.addEventListener('change', (event) => {
let attrKey = event.currentTarget.value
let actor = BoLUtility.getActorFromRollData(this.rollData)
this.rollData.attribute = foundry.utils.duplicate(actor.system.attributes[attrKey])
@@ -407,7 +409,7 @@ export class BoLRoll {
this.rollData.bolApplicableEffects = this.updateApplicableEffects(this.rollData)
this.updateTotalDice()
})
html.find('#apt').change((event) => {
html.querySelector('#apt')?.addEventListener('change', (event) => {
let aptKey = event.currentTarget.value
let actor = BoLUtility.getActorFromRollData(this.rollData)
this.rollData.aptitude = foundry.utils.duplicate(actor.system.aptitudes[aptKey])
@@ -416,65 +418,58 @@ export class BoLRoll {
this.updateTotalDice()
})
html.find('#applyShieldMalus').click((event) => {
if (event.currentTarget.checked) {
this.rollData.shieldMalus = this.rollData.shieldAttackMalus
} else {
this.rollData.shieldMalus = 0
}
html.querySelector('#applyShieldMalus')?.addEventListener('click', (event) => {
this.rollData.shieldMalus = event.currentTarget.checked ? this.rollData.shieldAttackMalus : 0
this.updateTotalDice()
})
html.find('#career').change((event) => {
let careers = $('#career').val()
html.querySelector('#career')?.addEventListener('change', (event) => {
let careers = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
this.rollData.careerBonus = (!careers || careers.length == 0) ? 0 : Math.max(...careers.map(i => parseInt(i)))
this.updateTotalDice()
})
html.find('#boon').change((event) => {
let boons = $('#boon').val()
html.querySelector('#boon')?.addEventListener('change', (event) => {
let boons = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
this.rollData.nbBoons = (!boons || boons.length == 0) ? 0 : boons.length
this.updateTotalDice()
})
html.find('#flaw').change((event) => {
let flaws = $('#flaw').val()
html.querySelector('#flaw')?.addEventListener('change', (event) => {
let flaws = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
this.rollData.nbFlaws = (!flaws || flaws.length == 0) ? 0 : flaws.length
this.updateTotalDice()
})
html.find('.bdice').click((event) => {
html.querySelectorAll('.bdice').forEach(el => el.addEventListener('click', (event) => {
this.rollData.mDice = 0
this.rollData.bDice = Number(event.currentTarget.value)
this.updateTotalDice()
})
html.find('.mdice').click((event) => {
}))
html.querySelectorAll('.mdice').forEach(el => el.addEventListener('click', (event) => {
this.rollData.bDice = 0
this.rollData.mDice = Number(event.currentTarget.value)
this.updateTotalDice()
})
html.find('#horoscope-bonus-applied').change((event) => {
}))
html.querySelector('#horoscope-bonus-applied')?.addEventListener('change', (event) => {
this.rollData.selectedHoroscope = []
for (let option of event.currentTarget.selectedOptions) {
this.rollData.selectedHoroscope.push(foundry.utils.duplicate(this.rollData.horoscopeBonusList[Number(option.index)]))
}
let horoscopes = $('#horoscope-bonus-applied').val()
let horoscopes = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
this.rollData.horoscopeBonus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
this.updateTotalDice()
})
html.find('#horoscope-malus-applied').change((event) => {
html.querySelector('#horoscope-malus-applied')?.addEventListener('change', (event) => {
this.rollData.selectedHoroscope = []
for (let option of event.currentTarget.selectedOptions) {
this.rollData.selectedHoroscope.push(foundry.utils.duplicate(this.rollData.horoscopeBonusList[Number(option.index)]))
}
let horoscopes = $('#horoscope-malus-applied').val()
let horoscopes = Array.from(event.currentTarget.selectedOptions).map(o => o.value)
this.rollData.horoscopeMalus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
this.updateTotalDice()
})
html.find('#horoscope-group-applied').change((event) => {
html.querySelector('#horoscope-group-applied')?.addEventListener('change', (event) => {
this.rollData.selectedGroupHoroscopeIndex = event.currentTarget.value
this.updateTotalDice()
})
}
/* -------------------------------------------- */
@@ -552,41 +547,47 @@ export class BoLRoll {
} else {
rollData.shieldMalus = 0
}
// Save
// Save & pre-initialize computed fields
this.rollData = rollData
this.updateTotalDice()
console.log("ROLLDATA", rollData)
// Then display+process the dialog
const rollOptionContent = await foundry.applications.handlebars.renderTemplate(rollOptionTpl, rollData);
let d = new Dialog({
title: rollData.label,
// Use Hooks to reliably get the rendered HTMLElement (renderDialogV2 receives (app, element, context))
Hooks.once('renderDialogV2', (app, element) => {
element.classList.add('bol');
this.rollDialogListener(element);
});
return foundry.applications.api.DialogV2.wait({
window: { title: rollData.label },
content: rollOptionContent,
rollData: rollData,
render: html => this.rollDialogListener(html),
buttons: {
cancel: {
icon: '<i class="fas fa-times"></i>',
rejectClose: false,
buttons: [
{
type: 'button',
label: game.i18n.localize("BOL.ui.cancel"),
callback: () => {
}
icon: 'fas fa-times',
action: 'cancel'
},
submit: {
icon: '<i class="fas fa-check"></i>',
{
type: 'submit',
label: game.i18n.localize("BOL.ui.submit"),
callback: (html) => {
icon: 'fas fa-check',
action: 'submit',
callback: (event, button, dialog) => {
console.log("Submit Roll!!!!");
if (rollData.mode == 'spell' && rollData.ppCurrent < rollData.ppCost) { // Check PP available
if (rollData.mode == 'spell' && rollData.ppCurrent < rollData.ppCost) {
ui.notifications.warn("Pas assez de Points de Pouvoir !")
return
return false
}
rollData.registerInit = (rollData.aptitude && rollData.aptitude.key == 'init') ? $('#register-init').is(":checked") : false;
rollData.registerInit = (rollData.aptitude && rollData.aptitude.key == 'init') ?
(dialog.element.querySelector('#register-init')?.checked ?? false) : false;
const isMalus = (rollData.bmDice < 0)
let rollbase = rollData.attrValue + rollData.aptValue
if (rollData.weapon?.system.properties.onlymodifier) {
rollbase = 0
}
if (rollData.weapon?.system.properties.onlymodifier) rollbase = 0
let diceData = BoLUtility.getDiceData()
let malusInit = rollData.combatData?.malusInit || 0
const modifiers = rollbase + rollData.careerBonus + rollData.mod + rollData.weaponModifier - rollData.defence - rollData.modArmorMalus + rollData.shieldMalus + rollData.attackModifier + rollData.appliedArmorMalus + rollData.effectModifier - malusInit
@@ -599,12 +600,8 @@ export class BoLRoll {
r.roll();
}
}
},
default: onEnter,
close: () => { }
}, this.options());
return d.render(true);
]
}, { classes: ['bol', 'dialog'], width: 480 });
}
}
@@ -698,18 +695,15 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */
async sendChatMessage() {
let actor = BoLUtility.getActorFromRollData(this.rollData)
this._buildChatMessage(this.rollData).then(async msgFlavor => {
//console.log("MSG", msgFlavor )
let msg = await this.rollData.roll.toMessage({
user: game.user.id,
rollMode: game.settings.get("core", "rollMode"),
flavor: msgFlavor,
speaker: ChatMessage.getSpeaker({ actor: actor }),
})
this.rollData.roll = foundry.utils.duplicate(this.rollData.roll) // Remove object, keep data (v111 ready)
msg.setFlag("world", "bol-roll-data", this.rollData)
})
const actor = BoLUtility.getActorFromRollData(this.rollData)
const rollMode = game.settings.get("core", "rollMode")
const msgFlavor = await this._buildChatMessage(this.rollData)
const msg = await this.rollData.roll.toMessage({
flavor: msgFlavor,
speaker: ChatMessage.getSpeaker({ actor: actor }),
}, { rollMode })
this.rollData.roll = foundry.utils.duplicate(this.rollData.roll)
if (msg) await msg.setFlag("world", "bol-roll-data", this.rollData)
}
/* -------------------------------------------- */