implements roll mechanic for battle dice
parent
b50e4d3090
commit
196b99b52e
|
|
@ -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<EmptyObject> & {_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<EmptyObject> & {_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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import {ActionManager} from "../sheets/actions/action-manager.mjs";
|
import {ActionManager} from "../sheets/actions/action-manager.mjs";
|
||||||
|
import {Talent} from "../data/talent.mjs";
|
||||||
|
|
||||||
const {ApplicationV2, HandlebarsApplicationMixin} = foundry.applications.api
|
const {ApplicationV2, HandlebarsApplicationMixin} = foundry.applications.api
|
||||||
|
|
||||||
|
|
@ -76,19 +77,94 @@ export class BattleDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
this.render({parts: ["form"]})
|
this.render({parts: ["form"]})
|
||||||
}
|
}
|
||||||
|
|
||||||
static #doBattle(event, target) {
|
static async #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']) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO perform Dice Rolls but in secret mode so its up to the GM if they want to display the result or not
|
// 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}<br/>TaP: ${offense.tap}<br/>${offense.meisterlich ? "Meisterlich" : ""}${offense.patzer ? "Petzer" : ""}`,
|
||||||
|
})
|
||||||
|
defense.evaluatedRoll.toMessage({
|
||||||
|
speaker: ChatMessage.getSpeaker({actor: this._defenseActor}),
|
||||||
|
flavor: `Talent: ${defenseTalent.name}<br/>TaP: ${defense.tap}<br/>${defense.meisterlich ? "Meisterlich" : ""}${defense.patzer ? "Petzer" : ""}`,
|
||||||
|
})
|
||||||
|
|
||||||
this.close()
|
this.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
<div class="presets">
|
<div class="presets">
|
||||||
<label><span>Voreinstellungen</span>
|
<label><span>Voreinstellungen</span>
|
||||||
|
{{!-- TODO implement logic --}}
|
||||||
<select name="battle-presets">
|
<select name="battle-presets">
|
||||||
<option value="" selected></option>
|
<option value="" selected></option>
|
||||||
<option value="zechen-v-zechen">Vergleichend: Zechen</option>
|
<option value="zechen-v-zechen">Vergleichend: Zechen</option>
|
||||||
|
|
@ -136,7 +137,7 @@
|
||||||
|
|
||||||
<div class="attribut">
|
<div class="attribut">
|
||||||
<label><span>KO</span>
|
<label><span>KO</span>
|
||||||
<output name="defenseAttributes.mu">{{offenseAttributes.ko}}</output>
|
<output name="offenseAttributes.mu">{{offenseAttributes.ko}}</output>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue