From 196b99b52ea4c3440bf243b5e8df70ddb0761703 Mon Sep 17 00:00:00 2001 From: macniel Date: Wed, 29 Oct 2025 15:14:22 +0100 Subject: [PATCH] implements roll mechanic for battle dice --- src/module/data/talent.mjs | 101 +++++++++++++++++++++++++ src/module/dialog/battleDialog.mjs | 96 ++++++++++++++++++++--- src/templates/dialog/battle-dialog.hbs | 3 +- 3 files changed, 189 insertions(+), 11 deletions(-) create mode 100644 src/module/data/talent.mjs diff --git a/src/module/data/talent.mjs b/src/module/data/talent.mjs new file mode 100644 index 00000000..04762cce --- /dev/null +++ b/src/module/data/talent.mjs @@ -0,0 +1,101 @@ +export class Talent { + + + /** + * @typedef TalentEigenschaften + * @property Number mu + * @property Number kl + * @property Number in + * @property Number ch + * @property Number ff + * @property Number ge + * @property Number ko + * @property Number kk + */ + + /** + * @typedef TalentData + * @property {String} name + * @property {Number} taw + * @property {TalentEigenschaften} eigenschaften + * @property {"mu","kl","in","ch","ff","ge","ko","kk"} eigenschaft1 + * @property {"mu","kl","in","ch","ff","ge","ko","kk"} eigenschaft2 + * @property {"mu","kl","in","ch","ff","ge","ko","kk"} eigenschaft3 + */ + + /** + * + * @param {TalentData} data + **/ + constructor(data) { + this.data = data + } + + /** + * @param {"publicroll", "gmroll", "privateroll"} rollMode + * @returns {Promise<{tap: any, meisterlich: boolean, patzer: boolean, evaluatedRoll: Roll & {_evaluated: true, _total: number, readonly total: number}}>} + */ + evaluate(rollMode) { + return this.#talentRoll(this.data, rollMode) + } + + + /** + * + * @param {TalentData} data + * @param {"publicroll", "gmroll", "privateroll"} rollMode + * @returns {Promise<{tap: any, meisterlich: boolean, patzer: boolean, evaluatedRoll: Roll & {_evaluated: true, _total: number, readonly total: number}}>} + */ + async #talentRoll(data, rollMode) { + + + let roll1 = new Roll("3d20"); + + let evaluated1 = (await roll1.evaluate()) + + const dsaDieRollEvaluated = this._evaluateRoll(evaluated1.terms[0].results, { + taw: data.taw, + werte: [data.eigenschaften[data.eigenschaft1], data.eigenschaften[data.eigenschaft2], data.eigenschaften[data.eigenschaft3]], + }) + + return { + ...dsaDieRollEvaluated, + evaluatedRoll: evaluated1, + } + } + + _evaluateRoll(rolledDice, { + taw, + lowerThreshold = 1, + upperThreshold = 20, + countToMeisterlich = 3, + countToPatzer = 3, + werte = [] + }) { + let tap = taw; + let meisterlichCounter = 0; + let patzerCounter = 0; + let failCounter = 0; + + rolledDice.forEach((rolledDie, index) => { + if (tap < 0 && rolledDie.result > werte[index]) { + tap -= rolledDie.result - werte[index]; + if (tap < 0) { // konnte nicht vollständig ausgeglichen werden + failCounter++; + } + } else if (rolledDie.result > werte[index]) { // taw ist bereits aufgebraucht und wert kann nicht ausgeglichen werden + tap -= rolledDie.result - werte[index]; + failCounter++; + } + if (rolledDie.result <= lowerThreshold) meisterlichCounter++; + if (rolledDie.result > upperThreshold) patzerCounter++; + }) + + return { + tap, + meisterlich: meisterlichCounter === countToMeisterlich, + patzer: patzerCounter === countToPatzer, + } + } + +} \ No newline at end of file diff --git a/src/module/dialog/battleDialog.mjs b/src/module/dialog/battleDialog.mjs index 0e68c72a..136c475d 100644 --- a/src/module/dialog/battleDialog.mjs +++ b/src/module/dialog/battleDialog.mjs @@ -1,4 +1,5 @@ import {ActionManager} from "../sheets/actions/action-manager.mjs"; +import {Talent} from "../data/talent.mjs"; const {ApplicationV2, HandlebarsApplicationMixin} = foundry.applications.api @@ -76,19 +77,94 @@ export class BattleDialog extends HandlebarsApplicationMixin(ApplicationV2) { this.render({parts: ["form"]}) } - static #doBattle(event, target) { - - // TODO get test values from talents either from the object or from the fields - - if (formData.object['saveOffenseData']) { - - } - if (formData.object['saveDefenseData']) { - - } + static async #doBattle(event, target) { // TODO perform Dice Rolls but in secret mode so its up to the GM if they want to display the result or not + let offenseTalent = {} + + if (this._offenseActor && this._offenseActor.items.get(this._offenseTalent)) { + const skill = this._offenseActor.items.get(this._offenseTalent) + offenseTalent.name = skill.name + offenseTalent.taw = skill.system.taw + offenseTalent.probe = skill.system.probe + } else { + offenseTalent.name = this.element.querySelector('input[name="offense.talent.name"]').value + offenseTalent.taw = this.element.querySelector('input[name="offense.talent.taw"]').value + offenseTalent.probe = [ + this.element.querySelector('input[name="offense.talent.probe.0.name"]').value, + this.element.querySelector('input[name="offense.talent.probe.1.name"]').value, + this.element.querySelector('input[name="offense.talent.probe.2.name"]').value + ] + } + + offenseTalent.eigenschaften = {} + + if (this._offenseActor && this._offenseActor.system.attribute) { + offenseTalent.eigenschaften = this._offenseActor.system.attribute + } else { + offenseTalent.eigenschaften = { + mu: this.element.querySelector('input[name="offenseAttributes.mu"]').value, + kl: this.element.querySelector('input[name="offenseAttributes.in"]').value, + in: this.element.querySelector('input[name="offenseAttributes.kl"]').value, + ch: this.element.querySelector('input[name="offenseAttributes.ch"]').value, + ff: this.element.querySelector('input[name="offenseAttributes.ff"]').value, + ge: this.element.querySelector('input[name="offenseAttributes.ge"]').value, + ko: this.element.querySelector('input[name="offenseAttributes.ko"]').value, + kk: this.element.querySelector('input[name="offenseAttributes.kk"]').value, + + } + } + + let defenseTalent = {} + + if (this._defenseActor && this._defenseActor.items.get(this._defenseTalent)) { + const skill = this._defenseActor.items.get(this._defenseTalent) + defenseTalent.name = skill.name + defenseTalent.taw = skill.system.taw + defenseTalent.probe = skill.system.probe + } else { + defenseTalent.name = this.element.querySelector('input[name="defense.talent.name"]').value + defenseTalent.taw = this.element.querySelector('input[name="defense.talent.taw"]').value + defenseTalent.probe = [ + this.element.querySelector('input[name="defense.talent.probe.0.name"]').value, + this.element.querySelector('input[name="defense.talent.probe.1.name"]').value, + this.element.querySelector('input[name="defense.talent.probe.2.name"]').value + ] + } + + + defenseTalent.eigenschaften = {} + + if (this._defenseActor && this._defenseActor.system.attribute) { + defenseTalent.eigenschaften = this._defenseActor.system.attribute + } else { + defenseTalent.eigenschaften = { + mu: this.element.querySelector('input[name="defenseAttributes.mu"]').value, + kl: this.element.querySelector('input[name="defenseAttributes.in"]').value, + in: this.element.querySelector('input[name="defenseAttributes.kl"]').value, + ch: this.element.querySelector('input[name="defenseAttributes.ch"]').value, + ff: this.element.querySelector('input[name="defenseAttributes.ff"]').value, + ge: this.element.querySelector('input[name="defenseAttributes.ge"]').value, + ko: this.element.querySelector('input[name="defenseAttributes.ko"]').value, + kk: this.element.querySelector('input[name="defenseAttributes.kk"]').value, + + } + } + + + const offense = await (new Talent(offenseTalent)).evaluate("gmroll") + const defense = await (new Talent(defenseTalent)).evaluate("gmroll") + + offense.evaluatedRoll.toMessage({ + speaker: ChatMessage.getSpeaker({actor: this._offenseActor}), + flavor: `Talent: ${offenseTalent.name}
TaP: ${offense.tap}
${offense.meisterlich ? "Meisterlich" : ""}${offense.patzer ? "Petzer" : ""}`, + }) + defense.evaluatedRoll.toMessage({ + speaker: ChatMessage.getSpeaker({actor: this._defenseActor}), + flavor: `Talent: ${defenseTalent.name}
TaP: ${defense.tap}
${defense.meisterlich ? "Meisterlich" : ""}${defense.patzer ? "Petzer" : ""}`, + }) + this.close() } diff --git a/src/templates/dialog/battle-dialog.hbs b/src/templates/dialog/battle-dialog.hbs index 1ddd70ad..39e620ef 100644 --- a/src/templates/dialog/battle-dialog.hbs +++ b/src/templates/dialog/battle-dialog.hbs @@ -2,6 +2,7 @@