From c51e2815302ce109bed6c84792b9b01b78f32b1d Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 30 Nov 2025 11:21:26 +0100 Subject: [PATCH] adjust dialog flow to match spell casting in 4.1 --- src/lang/de.json | 3 +- src/module/dialog/spellDialog.mjs | 81 ++++++++++++++++++++++++--- src/module/xml-import/xml-import.mjs | 5 +- src/templates/dialog/spell-dialog.hbs | 35 ++++++++++-- 4 files changed, 108 insertions(+), 16 deletions(-) diff --git a/src/lang/de.json b/src/lang/de.json index 66de97ee..17787b0d 100644 --- a/src/lang/de.json +++ b/src/lang/de.json @@ -48,7 +48,8 @@ "notReadyReason": { "title": "Zauber kann aus folgenden Gründen nicht gewirkt werden:", "noRepresentation": "Keine Repräsentation gewählt", - "tooManySpoMods": "Zu viele Spontane Modifikationen ausgewählt" + "tooManySpoMods": "Zu viele Spontane Modifikationen ausgewählt", + "noZFPDataAvailable": "Noch keine Zauberprobe gewürfelt" } }, "ITEM_BROWSER": { diff --git a/src/module/dialog/spellDialog.mjs b/src/module/dialog/spellDialog.mjs index f4ac417d..a5a9563b 100644 --- a/src/module/dialog/spellDialog.mjs +++ b/src/module/dialog/spellDialog.mjs @@ -1,6 +1,7 @@ import {ATTRIBUTE} from "../data/attribute.mjs"; import {spoModData, leadingAttribute} from "../data/spellData/spellData.mjs"; +import {evaluateRoll} from "../globals/DSARoll.mjs"; const { ApplicationV2, @@ -27,6 +28,7 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { }, actions: { cast: SpellDialog.#cast, + diceRoll: SpellDialog.#diceRoll } } @@ -50,7 +52,7 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { _variants = {} _costModel = {} _castTimeModel = {} - _spomods = {} + _spoMods = {} displayModResult = 0 constructor(actor, spellId) { @@ -62,7 +64,7 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { this.mod = 0 this._costMutators = {} this._castTimeMutators = {} - this._selectedRepresentation = null + this._selectedRepresentation = this._spell.getFlag("DSA_4-1", "representation") this._spellDie = null this._variants = {} this._costModel = this._spell.system.kosten.find(c => c.repräsentation === context.selectedRepresentation) ?? this._spell.system.kosten.find(c => c.repräsentation === "") @@ -73,6 +75,15 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { this._castTimeModel.variables.forEach(v => this._castTimeMutators[v] = 0) this.cost = this.normalizeCastingCost() ?? 0 this.castingTime = this.#normalizeCastingTime(this._spell) + this.zfp = null + if (this._selectedRepresentation) { + this._costModel = this._spell.system.kosten.find(c => c.repräsentation === context.selectedRepresentation) ?? this._spell.system.kosten.find(c => c.repräsentation === "") + this._castTimeModel = this._spell.system.zauberdauer + this._castTimeMutators = {} + this._costMutators = {} + this._costModel.variables.forEach(v => this._costMutators[v] = 0) + this._castTimeModel.variables.forEach(v => this._castTimeMutators[v] = 0) + } } /** @@ -87,8 +98,8 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { event.preventDefault() console.log(formData.object) // handle changes in variable Inputs - this._selectedRepresentation = formData.object.representation - this._variants = foundry.utils.expandObject(formData.object)["variants"] + this._selectedRepresentation = formData.object.representation ?? this._selectedRepresentation + this._variants = foundry.utils.expandObject(formData.object)["variants"] ?? {} if (this._spell.system.probe.includes("*")) { // ATTRIBUTO if (this._variants["Mut"]) { this._spellDie = "MU" @@ -145,15 +156,22 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { this.castingTime = this.#normalizeCastingTime(this._spell, this._castTimeMutators) - this._spomods = foundry.utils.expandObject(formData.object)["spoMods"] + // eval probeMod + + if (formData.object["checkMod"]) { + this.mod -= formData.object["checkMod"] + this._checkModValue = formData.object["checkMod"] + } // eval spomods + this._spoMods = foundry.utils.expandObject(formData.object)["spoMods"] ?? {} + let totalMod = this.mod let totalCost = this.cost let totalCastingTime = Number(this.castingTime) - Object.entries(this._spomods).forEach(([modName, times]) => { + Object.entries(this._spoMods).forEach(([modName, times]) => { const actualMod = spoModData[modName] @@ -181,6 +199,29 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { } + static async #diceRoll(event, target) { + const result = await evaluateRoll( + "3d20", + { + value: this._spell.system.zfw + this.mod, + owner: this._actor + } + ) + if (result.tap >= 0) { // erfolg + result.evaluated.toMessage({ + speaker: ChatMessage.getSpeaker({actor: this._actor}), + flavor: ` ${result.meisterlich ? 'Meisterlich geschafft' : 'Geschafft'} mit ${result.tap} Punkten übrig`, + }) + } else { // misserfolg + result.evaluated.toMessage({ + speaker: ChatMessage.getSpeaker({actor: this._actor}), + flavor: ` ${result.meisterlich ? 'Gepatzt' : ''} mit ${Math.abs(result.tap)} Punkten daneben`, + }) + } + this.zfp = result.tap + this.render({parts: ["form"]}) + } + normalizeCastingCost() { let costFormula = this._costModel.additionalFormula if (costFormula) { @@ -346,9 +387,16 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { context.costVariables = [] } + // probeMod + + if (this._spell.system.probeMod) { + context.checkModTest = this._spell.system.probeMod + context.checkModValue = this._checkModValue + } + // SpoMods - context.spoModCount = Object.values(this._spomods).reduce((previousValue, currentValue) => previousValue + currentValue, 0) + context.spoModCount = Object.values(this._spoMods).reduce((previousValue, currentValue) => previousValue + currentValue, 0) context.maxSpoModCount = 0 if (this._selectedRepresentation) { @@ -367,7 +415,7 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { const mapper = (spoModName) => { let data = spoModData[spoModName] - let value = this._spomods[data.name] ?? 0 + let value = this._spoMods[data.name] ?? 0 let totalModValue = data.mod * value return { ...data, @@ -397,10 +445,24 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { }) } - if (!context.ready) { + + // if this.zfp is null then we are in the first step pre dice roll + if (this.zfp == null) { + context.ready = false + context.diceRoll = true + } else { + context.zfp = this.zfp + context.spellName = this._spell.system.name + context.variant = context.variants.filter(v => v.variantChecked).map(v => v.variantText).join("

") + } + + if (!context.ready) { // rules have changed, it cant be cast when zfp - selected mutators is below 0 context.notReadyReasons = `${game.i18n.format("SPELL_DIALOG.notReadyReason.title")}" } + return context } diff --git a/src/module/xml-import/xml-import.mjs b/src/module/xml-import/xml-import.mjs index 1fdaa9b3..8401a4ef 100644 --- a/src/module/xml-import/xml-import.mjs +++ b/src/module/xml-import/xml-import.mjs @@ -383,7 +383,7 @@ export class XmlImport { } async #addSpellsFromCompendiumByNameToActor(spellName, zfw, representation, hauszauber, actor) { - const compendiumOfSpells = game.packs.get('DSA_4-1.Spells'); + const compendiumOfSpells = game.packs.get('DSA_4-1.Spells') const SCREAMING_NAME = spellName.toUpperCase() const spellId = compendiumOfSpells.index.find(spell => spell.name === SCREAMING_NAME) if (spellId) { @@ -392,7 +392,8 @@ export class XmlImport { try { const embeddedDocument = (await actor.createEmbeddedDocuments('Item', [spell]))[0] - embeddedDocument.update({system: {zfw: zfw, hauszauber: hauszauber, repräsentation: representation}}); + embeddedDocument.update({system: {zfw: zfw, hauszauber: hauszauber}}) + embeddedDocument.setFlag("DSA_4-1", "representation", representation) } catch (error) { console.error(`${spell} not found in items`, error) } diff --git a/src/templates/dialog/spell-dialog.hbs b/src/templates/dialog/spell-dialog.hbs index 917f595b..0fc7d77b 100644 --- a/src/templates/dialog/spell-dialog.hbs +++ b/src/templates/dialog/spell-dialog.hbs @@ -1,5 +1,7 @@
+ {{#unless zfp}} +

@@ -50,7 +52,33 @@ {{/if}} - {{#if this.spoMods}} + {{#if checkModTest}} +
+ Erschwernisse +
+ +
+
+ {{/if}} + + + + {{else}} + +
+ {{spellName}} + {{{this.text}}} + {{#if variant}} +
+ {{{variantText}}} + {{/if}} +
+ + {{#if this.spoMods}}
Spontane Modifikation {{#if this.spoModCount}}{{#if this.maxSpoModCount}} [{{this.spoModCount}}/{{this.maxSpoModCount}}]{{/if}}{{/if}} @@ -98,9 +126,6 @@ -
@@ -110,4 +135,6 @@ wirken {{#if modResult}} [{{displayModResult}}]{{/if}} + {{/unless}} +
\ No newline at end of file