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 {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}<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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<div class="presets">
|
||||
<label><span>Voreinstellungen</span>
|
||||
{{!-- TODO implement logic --}}
|
||||
<select name="battle-presets">
|
||||
<option value="" selected></option>
|
||||
<option value="zechen-v-zechen">Vergleichend: Zechen</option>
|
||||
|
|
@ -136,7 +137,7 @@
|
|||
|
||||
<div class="attribut">
|
||||
<label><span>KO</span>
|
||||
<output name="defenseAttributes.mu">{{offenseAttributes.ko}}</output>
|
||||
<output name="offenseAttributes.mu">{{offenseAttributes.ko}}</output>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue