implements basic liturgy casting dialog

pull/63/head
macniel 2025-10-30 23:06:51 +01:00
parent bf78cfde87
commit dda93eeacb
13 changed files with 549 additions and 263 deletions

View File

@ -290,6 +290,17 @@ Hooks.once("init", () => {
}, },
requiresReload: true requiresReload: true
}) })
game.settings.register('DSA_4-1', 'optional_aufstufen_von_liturgien', {
name: "Optional: Aufstufen von Liturgien",
hint: "Aktiviert die Regeln zum Aufstufen von Liturgien",
scope: "world",
config: true,
type: Boolean,
default: false,
disabled: true,
requiresReload: true
})
Handlebars.registerHelper("weight", (data) => { Handlebars.registerHelper("weight", (data) => {

View File

@ -13,7 +13,9 @@ export class LiturgyDataModel extends BaseItem {
grad: new NumberField({min: 1, max: 5}), grad: new NumberField({min: 1, max: 5}),
reichweite: new StringField(), reichweite: new StringField(),
ziel: new StringField(), ziel: new StringField(),
zielArt: new StringField(), // Person, Object
wirkungsdauer: new StringField(), wirkungsdauer: new StringField(),
zauberdauer: new StringField(),
auswirkung: new SchemaField({ auswirkung: new SchemaField({
I: new StringField(), I: new StringField(),
II: new StringField(), II: new StringField(),

View File

@ -3,8 +3,29 @@ export class LiturgyData {
static ranks = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII"] static ranks = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII"]
static #ranks = [ static #ranks = [
{index: 0, name: "O", lkp: 3, mod: 2, costKaP: 2, costKaPPermant: 0, duration: "LkP* KR", strength: "LkP*/2"}, {
{index: 1, name: "I", lkp: 3, mod: 0, costKaP: 5, costKaPPermant: 0, duration: "LkP* KR", strength: "LkP*/2"}, index: 0,
name: "O",
lkp: 3,
mod: 2,
costKaP: 2,
costKaPPermant: 0,
duration: "Augenblicklich",
castDuration: "Stoßgebet",
strength: "LkP*/2"
},
{
index: 1,
name: "I",
lkp: 3,
mod: 0,
costKaP: 5,
costKaPPermant: 0,
range: "Selbst",
castDuration: "Gebet",
duration: "LkP* KR",
strength: "LkP*/2"
},
{ {
index: 2, index: 2,
name: "II", name: "II",
@ -12,6 +33,9 @@ export class LiturgyData {
mod: -2, mod: -2,
costKaP: 10, costKaP: 10,
costKaPPermant: 0, costKaPPermant: 0,
range: "Berührung",
target: ["Geweihter"],
castDuration: "Andacht",
duration: "LkP*10 KR", duration: "LkP*10 KR",
strength: "LkP/2+5" strength: "LkP/2+5"
}, },
@ -22,7 +46,10 @@ export class LiturgyData {
mod: -4, mod: -4,
costKaP: 15, costKaP: 15,
costKaPPermant: 0, costKaPPermant: 0,
duration: "LkP* SR", range: "Sicht",
target: ["1 Person", "1 Objekt"],
castDuration: "Zeremonie",
duration: "LkP* Spielrunden",
strength: "LkP*+5" strength: "LkP*+5"
}, },
{ {
@ -32,6 +59,9 @@ export class LiturgyData {
mod: -6, mod: -6,
costKaP: 20, costKaP: 20,
costKaPPermant: 0, costKaPPermant: 0,
range: "Fern",
target: ["10 Personen", "10 Objekte"],
castDuration: "Zyklus",
duration: "LkP* Stunden", duration: "LkP* Stunden",
strength: "LkP*+10" strength: "LkP*+10"
}, },
@ -42,6 +72,7 @@ export class LiturgyData {
mod: -8, mod: -8,
costKaP: 25, costKaP: 25,
costKaPPermant: 1, costKaPPermant: 1,
target: ["100 Personen", "100 Objekte"],
duration: "LkP* Tage", duration: "LkP* Tage",
strength: "LkP*+15" strength: "LkP*+15"
}, },
@ -52,6 +83,7 @@ export class LiturgyData {
mod: -10, mod: -10,
costKaP: 30, costKaP: 30,
costKaPPermant: 3, costKaPPermant: 3,
target: ["1000 Personen", "1000 Objekte"],
duration: "LkP* Wochen", duration: "LkP* Wochen",
strength: "LkP*+20" strength: "LkP*+20"
}, },
@ -109,21 +141,45 @@ export class LiturgyData {
] ]
static getModifiedStrength(originalString, rankIncrease) { static getModifiedStrength(originalString, rankIncrease) {
return this.#ranks[this.#ranks.findIndex(p => p.strength === originalString) + rankIncrease] // TODO as "Flagge des Regenbogens" demonstrates there may be different variations of Strengths which separately needs to be adjusted
return Object.assign({}, this.#ranks[this.#ranks.findIndex(p => p.strength === originalString) + rankIncrease])
} }
static getModifiedDuration(originalString, rankIncrease) { static getModifiedDuration(originalString, rankIncrease) {
return this.#ranks[this.#ranks.findIndex(p => p.duration === originalString) + rankIncrease]
let currentDuration = 0
let durationText = ""
let adjustedDurationText = ""
let found = false
for (let {duration} of this.#ranks) {
if (originalString.indexOf(duration) !== -1) {
durationText = duration
adjustedDurationText = this.#ranks[currentDuration + rankIncrease].duration
found = true
break
}
++currentDuration
}
if (found) {
durationText = this.#ranks[currentDuration].duration
console.log({currentDuration, durationText, adjustedDurationText})
return {currentDuration, durationText, adjustedDurationText}
}
return {currentDuration: 0, durationText: originalString, adjustedDurationText: originalString}
} }
static getModifiedRank(rank) { static getModifiedRank(rank) {
return LiturgyData.#ranks[rank] return Object.assign({}, LiturgyData.#ranks[rank])
} }
static getRankOfLiturgy(liturgy, deity) { static getRankOfLiturgy(liturgy, deity) {
const lookupData = liturgy.herkunft.find(p => p.name === deity) const lookupData = liturgy.herkunft.find(p => p.name === deity)
const rank = lookupData?.grad const rank = lookupData?.grad
return LiturgyData.#ranks[rank] return Object.assign({}, LiturgyData.#ranks[rank])
} }
static lookupAlias(alias) { static lookupAlias(alias) {

View File

@ -17,6 +17,7 @@ export class Talent {
* @typedef TalentData * @typedef TalentData
* @property {String} name * @property {String} name
* @property {Number} taw * @property {Number} taw
* @property {Number} mod
* @property {TalentEigenschaften} eigenschaften * @property {TalentEigenschaften} eigenschaften
* @property {"mu","kl","in","ch","ff","ge","ko","kk"} eigenschaft1 * @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"} eigenschaft2
@ -55,6 +56,7 @@ export class Talent {
const dsaDieRollEvaluated = this._evaluateRoll(evaluated1.terms[0].results, { const dsaDieRollEvaluated = this._evaluateRoll(evaluated1.terms[0].results, {
taw: data.taw, taw: data.taw,
mod: data.mod,
werte: [data.eigenschaften[data.eigenschaft1], data.eigenschaften[data.eigenschaft2], data.eigenschaften[data.eigenschaft3]], werte: [data.eigenschaften[data.eigenschaft1], data.eigenschaften[data.eigenschaft2], data.eigenschaften[data.eigenschaft3]],
}) })
@ -66,25 +68,25 @@ export class Talent {
_evaluateRoll(rolledDice, { _evaluateRoll(rolledDice, {
taw, taw,
mod,
lowerThreshold = 1, lowerThreshold = 1,
upperThreshold = 20, upperThreshold = 20,
countToMeisterlich = 3, countToMeisterlich = 3,
countToPatzer = 3, countToPatzer = 3,
werte = [] werte = []
}) { }) {
let tap = taw;
let meisterlichCounter = 0; let meisterlichCounter = 0;
let patzerCounter = 0; let patzerCounter = 0;
let failCounter = 0; let failCounter = 0;
rolledDice.forEach((rolledDie, index) => { rolledDice.forEach((rolledDie, index) => {
if (tap < 0 && rolledDie.result > werte[index]) { if (mod < 0 && rolledDie.result > werte[index]) {
tap -= rolledDie.result - werte[index]; mod -= rolledDie.result - werte[index];
if (tap < 0) { // konnte nicht vollständig ausgeglichen werden if (mod < 0) { // konnte nicht vollständig ausgeglichen werden
failCounter++; failCounter++;
} }
} else if (rolledDie.result > werte[index]) { // taw ist bereits aufgebraucht und wert kann nicht ausgeglichen werden } else if (rolledDie.result > werte[index]) { // taw ist bereits aufgebraucht und wert kann nicht ausgeglichen werden
tap -= rolledDie.result - werte[index]; mod -= rolledDie.result - werte[index];
failCounter++; failCounter++;
} }
if (rolledDie.result <= lowerThreshold) meisterlichCounter++; if (rolledDie.result <= lowerThreshold) meisterlichCounter++;
@ -92,7 +94,7 @@ export class Talent {
}) })
return { return {
tap, tap: Math.min(taw, mod),
meisterlich: meisterlichCounter === countToMeisterlich, meisterlich: meisterlichCounter === countToMeisterlich,
patzer: patzerCounter === countToPatzer, patzer: patzerCounter === countToPatzer,
} }

View File

@ -1,4 +1,5 @@
import {LiturgyData} from "../data/miracle/liturgydata.mjs"; import {LiturgyData} from "../data/miracle/liturgydata.mjs";
import {Talent} from "../data/talent.mjs";
const {ApplicationV2, HandlebarsApplicationMixin} = foundry.applications.api const {ApplicationV2, HandlebarsApplicationMixin} = foundry.applications.api
@ -16,7 +17,7 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
title: "Liturgie wirken" title: "Liturgie wirken"
}, },
form: { form: {
submitOnChange: false, submitOnChange: true,
closeOnSubmit: false, closeOnSubmit: false,
handler: LiturgyDialog.#onSubmitForm handler: LiturgyDialog.#onSubmitForm
}, },
@ -24,6 +25,7 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
selectVariant: LiturgyDialog.#selectVariant, selectVariant: LiturgyDialog.#selectVariant,
addMod: LiturgyDialog.#addModification, addMod: LiturgyDialog.#addModification,
removeMod: LiturgyDialog.#removeModification, removeMod: LiturgyDialog.#removeModification,
castLiturgy: LiturgyDialog.#castLiturgy,
} }
} }
@ -70,11 +72,16 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
}) })
this._variation = this._variations[0] this._variation = this._variations[0]
this._mods = [] this._mods = []
this._blessing = this._actor.itemTypes["Blessing"].find(p => p.system.gottheit === this._deity)
this._initialRank = 0 this._initialRank = 0
this._circumstance = 0
} }
static async #onSubmitForm(event, form, formData) { static async #onSubmitForm(event, form, formData) {
event.preventDefault() event.preventDefault()
this._circumstance = formData.object["circumstance"]
this.render({parts: ["form"]})
} }
static #selectVariant(event, target) { static #selectVariant(event, target) {
@ -91,6 +98,7 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
static #addModification(event, target) { static #addModification(event, target) {
event.stopPropagation() event.stopPropagation()
event.preventDefault() event.preventDefault()
if (game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")) {
const value = this.element.querySelector('select[name="mod"]').value const value = this.element.querySelector('select[name="mod"]').value
if (value === '') return if (value === '') return
@ -101,18 +109,80 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
mod: value, mod: value,
}) })
this.render({parts: ["form"]}) this.render({parts: ["form"]})
}
return false return false
} }
static #removeModification(event, target) { static #removeModification(event, target) {
event.stopPropagation() event.stopPropagation()
event.preventDefault() event.preventDefault()
if (game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")) {
const {index} = target.dataset const {index} = target.dataset
this._mods.splice(index, 1) this._mods.splice(index, 1)
this.render({parts: ["form"]}) this.render({parts: ["form"]})
}
return false return false
} }
static async #castLiturgy(event, target) {
const lkp = context.lkp = this._blessing.system.wert
const resultingLiturgy = this.#getLiturgyData()
const circumstance = this._circumstance
const mod = 0 + lkp + resultingLiturgy.castPenalty - circumstance
const castingTime = this.#normalizeCastingTime(this._liturgy)
//TODO push it into the sun eeerh cooldown queue
//if (castingTime > 0) {
// this._actor.system.cooldowns.push()
//} else {
const result = await new Talent({
name: this._liturgy.name,
taw: lkp,
mod: mod,
eigenschaften: {
mu: this._actor.system.attribute.mu.aktuell,
in: this._actor.system.attribute.in.aktuell,
ch: this._actor.system.attribute.ch.aktuell,
},
eigenschaft1: "mu",
eigenschaft2: "mu",
eigenschaft3: "mu"
}).evaluate("publicroll")
result.evaluatedRoll.toMessage({
speaker: ChatMessage.getSpeaker({actor: this._actor}),
flavor: `Liturgie: ${this._liturgy.name}<br/>Zauberdauer: ${castingTime > 0 ? castingTime + " Aktionen" : resultingLiturgy.castduration}<br/>LkP*: ${result.tap}<br/>${result.meisterlich ? "Meisterlich" : ""}${result.patzer ? "Petzer" : ""}<br/>${this._variation.effect}`,
})
//}
this.close()
}
#normalizeCastingTime(liturgy) {
const castingTime = liturgy.system.zauberdauer
// direct actions
const stoßgebetRegExp = /(.*) Aktionen \(Stoßgebet\)/
const gebetRegExp = /(.*) Spielrunden? \(Gebet\)/
const invalidForCooldownRegExp = /Andacht|Zeremonie|Zyklus/
if (castingTime.match(stoßgebetRegExp)) {
const [_, actions] = castingTime.match(stoßgebetRegExp)
return actions
} else if (castingTime.match(gebetRegExp)) {
const [_, actions] = castingTime.match(stoßgebetRegExp)
return actions * 20
} else if (castingTime.match(invalidForCooldownRegExp)) {
return -1
}
return -1
}
_configureRenderOptions(options) { _configureRenderOptions(options) {
super._configureRenderOptions(options) super._configureRenderOptions(options)
@ -120,16 +190,25 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
if (this._liturgy) { if (this._liturgy) {
options.window.title = `${this._liturgy.name} wirken` options.window.title = `${this._liturgy.name} wirken`
} }
if (game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")) {
options.position.height = 800
} else {
options.position.height = 640
} }
}
return options return options
} }
#getLiturgyData() { #getLiturgyData() {
let baseline = LiturgyData.getModifiedRank(this._variation?.level ?? 0) let baseline = this._liturgy.system
baseline.name = this._liturgy.name
if (game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")) {
baseline.duration = this._liturgy.system.wirkungsdauer
let upgradeDuration = false let upgradeDuration = false
let upgradeCastDuration = false let upgradeCastDuration = false
@ -153,27 +232,44 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
} }
}) })
baseline.name = this._liturgy.name
baseline.effectiveLevel = (this._variation?.level ?? 0) + this._mods.length baseline.effectiveLevel = (this._variation?.level ?? 0) + this._mods.length
baseline.costKaP = LiturgyData.getModifiedRank(baseline.effectiveLevel).costKaP baseline.costKaP = LiturgyData.getModifiedRank(baseline.effectiveLevel).costKaP
baseline.costKaPPermanent = LiturgyData.getModifiedRank(baseline.effectiveLevel).costKaPPermanent baseline.costKaPPermanent = LiturgyData.getModifiedRank(baseline.effectiveLevel).costKaPPermanent
baseline.mod = LiturgyData.getModifiedRank(baseline.effectiveLevel).mod //baseline.mod = LiturgyData.getModifiedRank(baseline.effectiveLevel).mod
baseline.rank = LiturgyData.getModifiedRank(baseline.effectiveLevel).name baseline.rank = LiturgyData.getModifiedRank(baseline.effectiveLevel).name
// estimate duration rank
// insert mods into text // insert mods into text
baseline.text = this._variation.effect baseline.text = this._variation.effect
const strengthRegexp = /(LkP\*.*?)[ .]/g const strengthRegexp = /(LkP\*.*?)[ .]/g
baseline.text = baseline.text.replace(strengthRegexp, LiturgyData.getModifiedRank((baseline.effectiveLevel ?? 0) + upgradeStrength).strength) //baseline.text = baseline.text.replace(strengthRegexp, LiturgyData.getModifiedRank((baseline.effectiveLevel ?? 0) + upgradeStrength).strength)
const durationRegexp = /(LkP\*?.*?)(\*10 KR| Stunden| Tage| Wochen| Monate| Jahre oder permanent)/g const durationRegexp = /(LkP\*?.*?)(\*10 KR| Stunden| Tage| Wochen| Monate| Jahre oder permanent)/g
const effectiveDuration = LiturgyData.getModifiedDuration((baseline.effectiveLevel ?? 0) + upgradeDuration + upgradeStrength).duration const effectiveDuration = LiturgyData.getModifiedDuration(baseline.duration, upgradeDuration + upgradeStrength)
baseline.duration = baseline.duration.replace(durationRegexp, effectiveDuration.replace("{*}", "LkP")) baseline.duration = baseline.duration.replace(effectiveDuration.durationText, effectiveDuration.adjustedDurationText)
} else {
baseline.rank = this._variation.rank
baseline.text = this._variation.effect
baseline.target = baseline.ziel
baseline.duration = baseline.wirkungsdauer
baseline.castduration = baseline.zauberdauer
baseline.costKaP = LiturgyData.getModifiedRank(this._variation.level).costKaP
baseline.costKaPPermanent = LiturgyData.getModifiedRank(this._variation.level).costKaPPermanent
if (this._variation.level > this._liturgy.system.herkunft.find(p => p.name === this._deity).grad) {
baseline.castPenalty = LiturgyData.getModifiedRank(this._liturgy.system.herkunft.find(p => p.name === this._deity).grad).mod
} else {
baseline.castPenalty = LiturgyData.getModifiedRank(this._variation.level).mod
}
}
return baseline return baseline
} }
@ -186,11 +282,27 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
context.variation = this._variation context.variation = this._variation
context.maxmods = this._maxmods context.maxmods = this._maxmods
context.variations = this._variations context.variations = this._variations
context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice')
context.canMod = (this._maxmods - (this._variation?.level ?? 0) - this._mods.length) >= 0 context.mu = {wert: this._actor.system.attribute.mu.aktuell, name: "MU", tooltip: "Mut"}
context.in = {wert: this._actor.system.attribute.in.aktuell, name: "IN", tooltip: "Intuition"}
context.ch = {wert: this._actor.system.attribute.ch.aktuell, name: "CH", tooltip: "Charisma"}
context.moddingEnabled = game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")
context.canMod = game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien") && (this._maxmods - (this._variation?.level ?? 0) - this._mods.length) >= 0
context.addingModRank = LiturgyDialog.#romanNumerals[(context._variation?.level ?? 0) + this._mods.length + 1] context.addingModRank = LiturgyDialog.#romanNumerals[(context._variation?.level ?? 0) + this._mods.length + 1]
context.lkp = this._blessing.system.wert
context.deity = this._blessing.system.name
context.resultingLiturgy = this.#getLiturgyData() context.resultingLiturgy = this.#getLiturgyData()
context.resultingCastPenalty = 0
context.circumstance = this._circumstance
if (context.resultingLiturgy.castPenalty > 0) {
context.resultingCastPenalty = `+${context.resultingLiturgy.castPenalty}`
} else {
context.resultingCastPenalty = context.resultingLiturgy.castPenalty
}
context.modResult = 0 + context.lkp + context.resultingLiturgy.castPenalty - this._circumstance
context.displayModResult = context.modResult > 0 ? "+" + context.modResult : context.modResult
return context return context
} }

View File

@ -55,7 +55,7 @@
], ],
"reichweite": "Berührung", "reichweite": "Berührung",
"ziel": "1 Person", "ziel": "1 Person",
"zauberdauer": "1/2 Stund (Andacht)", "zauberdauer": "1/2 Stunde (Andacht)",
"wirkungsdauer": "permanent; kann nur durch eine Exkommunikation aufgehoben werden", "wirkungsdauer": "permanent; kann nur durch eine Exkommunikation aufgehoben werden",
"auswirkung": { "auswirkung": {
"II": "Zwölfjährige oder Bekehrte werden mittels dieser Liturgie in den Zwölfgötterkult eingeführt, ihren Seelen steht prinzipiell eines der zwölfgöttlichen Paradiese offen. Im Zuge der Initiation erkennen Geweihte auch, ob Kinder potenzielle Novizen darstellen." "II": "Zwölfjährige oder Bekehrte werden mittels dieser Liturgie in den Zwölfgötterkult eingeführt, ihren Seelen steht prinzipiell eines der zwölfgöttlichen Paradiese offen. Im Zuge der Initiation erkennen Geweihte auch, ob Kinder potenzielle Novizen darstellen."

View File

@ -54,7 +54,7 @@
} }
], ],
"reichweite": "selbst / Sicht (Variante des Feuerschutzes)", "reichweite": "selbst / Sicht (Variante des Feuerschutzes)",
"ziel": "Gewewihter / 1 Gegenstand (Variante des Feuerschutzes)", "ziel": "Geweihter / 1 Gegenstand (Variante des Feuerschutzes)",
"zauberdauer": "1 Spielrunde (Gebet)", "zauberdauer": "1 Spielrunde (Gebet)",
"wirkungsdauer": "bis zum Ende der Probe, maximal LkP* Tage", "wirkungsdauer": "bis zum Ende der Probe, maximal LkP* Tage",
"auswirkung": { "auswirkung": {

View File

@ -1,5 +1,5 @@
{ {
"name": "Geburtssegen", "name": "Glückssegen",
"alias": [], "alias": [],
"grad": 1, "grad": 1,
"primärHerkunft": "Phex", "primärHerkunft": "Phex",

View File

@ -0,0 +1,144 @@
@use "../atoms/colours";
@use "../atoms/numbers";
@use "../atoms/assets";
@use "sass:color";
@mixin attributes {
display: flex;
position: relative;
top: -10px;
right: -10px;
.attribute {
width: 48px;
height: 48px;
position: relative;
margin-left: 2px;
.die {
svg {
position: absolute;
path {
fill: colours.$attribute-die-color;
}
}
}
.wert {
font-weight: bold;
position: absolute;
left: -1px;
width: 48px;
top: -1px;
font-size: smaller;
line-height: 48px;
vertical-align: middle;
text-align: center;
color: colours.$attribute-die-label-color;
}
.name {
position: absolute;
left: 0;
right: 0;
bottom: -12px;
line-height: 12px;
vertical-align: middle;
text-align: center;
color: colours.$attribute-label-color;
}
}
&.colorfulDice {
&.Mut {
.die svg path {
fill: colours.$attribute-die-co-color;
}
.wert {
color: colours.$attribute-die-co-text-color;
}
}
.Klugheit {
.die svg path {
fill: colours.$attribute-die-sm-color;
}
.wert {
color: colours.$attribute-die-sm-text-color;
}
}
.Intuition {
.die svg path {
fill: colours.$attribute-die-in-color;
}
.wert {
color: colours.$attribute-die-in-text-color;
}
}
.Charisma {
.die svg path {
fill: colours.$attribute-die-ch-color;
}
.wert {
color: colours.$attribute-die-ch-text-color;
}
}
.Geschicklichkeit {
.die svg path {
fill: colours.$attribute-die-dx-color;
}
.wert {
color: colours.$attribute-die-dx-text-color;
}
}
.Fingerfertigkeit {
.die svg path {
fill: colours.$attribute-die-ag-color;
}
.wert {
color: colours.$attribute-die-ag-text-color;
}
}
.Konstitution {
.die svg path {
fill: colours.$attribute-die-bd-color;
}
.wert {
color: colours.$attribute-die-bd-text-color;
}
}
.Körperkraft {
.die svg path {
fill: colours.$attribute-die-st-color;
}
.wert {
color: colours.$attribute-die-st-text-color;
}
}
}
}

View File

@ -2,6 +2,7 @@
@use "../atoms/numbers"; @use "../atoms/numbers";
@use "../atoms/assets"; @use "../atoms/assets";
@use "sass:color"; @use "sass:color";
@use "attribute-die";
.dsa41.sheet.actor.character { .dsa41.sheet.actor.character {
@ -9,145 +10,9 @@
position: relative; position: relative;
.attributes { .attributes {
display: flex; @include attribute-die.attributes
position: relative;
top: -10px;
right: -10px;
.attribute.rollable {
width: 48px;
height: 48px;
position: relative;
margin-left: 2px;
.die {
svg {
position: absolute;
path {
fill: colours.$attribute-die-color;
}
}
}
.wert {
font-weight: bold;
position: absolute;
left: -1px;
width: 48px;
top: -1px;
font-size: smaller;
line-height: 48px;
vertical-align: middle;
text-align: center;
color: colours.$attribute-die-label-color;
}
.name {
position: absolute;
left: 0;
right: 0;
bottom: -12px;
line-height: 12px;
vertical-align: middle;
text-align: center;
color: colours.$attribute-label-color;
}
}
&.colorfulDice {
&.Mut {
.die svg path {
fill: colours.$attribute-die-co-color;
}
.wert {
color: colours.$attribute-die-co-text-color;
}
}
.Klugheit {
.die svg path {
fill: colours.$attribute-die-sm-color;
}
.wert {
color: colours.$attribute-die-sm-text-color;
}
}
.Intuition {
.die svg path {
fill: colours.$attribute-die-in-color;
}
.wert {
color: colours.$attribute-die-in-text-color;
}
}
.Charisma {
.die svg path {
fill: colours.$attribute-die-ch-color;
}
.wert {
color: colours.$attribute-die-ch-text-color;
}
}
.Geschicklichkeit {
.die svg path {
fill: colours.$attribute-die-dx-color;
}
.wert {
color: colours.$attribute-die-dx-text-color;
}
}
.Fingerfertigkeit {
.die svg path {
fill: colours.$attribute-die-ag-color;
}
.wert {
color: colours.$attribute-die-ag-text-color;
}
}
.Konstitution {
.die svg path {
fill: colours.$attribute-die-bd-color;
}
.wert {
color: colours.$attribute-die-bd-text-color;
}
}
.Körperkraft {
.die svg path {
fill: colours.$attribute-die-st-color;
}
.wert {
color: colours.$attribute-die-st-text-color;
}
} }
} }
}
}
} }

View File

@ -1,5 +1,29 @@
@use "../molecules/attribute-die";
.dsa41.dialog.liturgy { .dsa41.dialog.liturgy {
section[data-application-part] {
display: flex;
flex-direction: column;
gap: 16px;
height: 100%;
.attributes {
@include attribute-die.attributes;
top: 0;
left: 0;
justify-content: center;
hr.zier {
flex: 1;
align-self: center;
border-top: 1px inset;
}
}
table { table {
tr { tr {
th:first-child { th:first-child {
@ -8,6 +32,12 @@
} }
} }
.scroll-y {
flex: 1;
overflow: hidden;
overflow-y: auto;
}
table#mods { table#mods {
tr { tr {
@ -39,7 +69,35 @@
} }
.dialog-buttons { .malus-and-mod {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr;
gap: 0 8px;
label {
span {
text-align: center;
}
output {
height: 32px;
width: 100%;
line-height: 32px;
vertical-align: middle;
display: block;
padding: 0 8px;
border: 1px inset;
border-radius: 4px;
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
}
}
}
.actions {
align-self: center;
flex: 0; flex: 0;
} }
}
} }

View File

@ -1,10 +1,36 @@
<section> <section>
<table>
<div class="attributes {{#if this.colorfulDice}}colorfulDice{{/if}}">
<hr class="zier"/>
{{> "systems/DSA_4-1/templates/ui/partial-attribute-button.hbs" this.mu}}
{{> "systems/DSA_4-1/templates/ui/partial-attribute-button.hbs" this.in}}
{{> "systems/DSA_4-1/templates/ui/partial-attribute-button.hbs" this.ch}}
<hr class="zier"/>
</div>
<div class="result">
{{#if resultingLiturgy}}
<div><span>Liturgie:</span> {{resultingLiturgy.name}}</div>
<div><span>Grad:</span> {{resultingLiturgy.rank}}</div>
<div><span>Kosten:</span> {{resultingLiturgy.costKaP}} KaP {{#if resultingLiturgy.costKaPPermanent}}
(davon {{resultingLiturgy.costKaP}} permanent){{/if}}</div>
<div><span>Ziel:</span> {{resultingLiturgy.target}}</div>
<div><span>Wirkdauer:</span> {{resultingLiturgy.duration}}</div>
<div><span>Wirkzeit:</span> {{resultingLiturgy.castduration}}</div>
{{/if}}
</div>
<div class="scroll-y">
<table>
<tr> <tr>
<th>Grad</th> <th>Grad</th>
<th>Wirkung</th> <th>Wirkung</th>
</tr> </tr>
</th>
{{#each variations}} {{#each variations}}
<tr> <tr>
<th><label><input type="radio" data-action="selectVariant" data-rank="{{this.rank}}" {{checked <th><label><input type="radio" data-action="selectVariant" data-rank="{{this.rank}}" {{checked
@ -14,7 +40,10 @@
{{/each}} {{/each}}
</table> </table>
</div>
{{#if moddingEnabled}}
<h2>Modifizieren</h2> <h2>Modifizieren</h2>
@ -49,18 +78,26 @@
<span id="info"></span> <span id="info"></span>
</div> </div>
</div> </div>
<div class="result">
{{#if resultingLiturgy}}
<div><span>Liturgie:</span> {{resultingLiturgy.name}}</div>
<div><span>Grad:</span> {{resultingLiturgy.rank}}</div>
<div><span>Kosten:</span>{{resultingLiturgy.costKaP}} KaP {{#if resultingLiturgy.costKaPPermanent}}
(davon {{resultingLiturgy.costKaP}} permanent){{/if}}</div>
<div><span>Ziel:</span>{{resultingLiturgy.target}}</div>
<div><span>Wirkdauer:</span>{{resultingLiturgy.duration}}</div>
<div><span>Wirkzeit:</span>{{resultingLiturgy.casttime}}</div>
<div>{{resultingLiturgy.text}}</div>
{{/if}} {{/if}}
<fieldset class="modding">
<legend>Erschwernisse</legend>
<div class="malus-and-mod">
<label><span>LkP</span>
<output name="lkp" type="number">{{lkp}}</output>
</label>
<label><span>Umstände</span>
<input name="circumstance" type="number" value="{{circumstance}}">
</label>
<label><span>Modifikation</span>
<output name="penalty">{{resultingCastPenalty}}</output>
</label>
</div> </div>
<output class="modResult"></output>
</fieldset>
<button class="actions" data-action="castLiturgy"><i class="fa-solid fa-sparkles"></i> Wirken {{#if modResult}}
[{{displayModResult}}]{{/if}}</button>
</section> </section>

View File

@ -1,6 +1,5 @@
<div class="attribute rollable {{this.tooltip}}" data-name="{{this.tooltip}}" alt="{{this.tooltip}}" <div class="attribute rollable {{this.tooltip}}" data-name="{{this.tooltip}}" alt="{{this.tooltip}}"
data-value="{{this.wert}}" data-value="{{this.wert}}">
data-label="{{this.name}}" data-roll="1d20cs<=@{{this.eigenschaft}}.aktuell">
<div class="die"> <div class="die">
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }} {{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
</div> </div>