diff --git a/src/module/data/spell.mjs b/src/module/data/spell.mjs index 90237d28..64651fe9 100644 --- a/src/module/data/spell.mjs +++ b/src/module/data/spell.mjs @@ -22,8 +22,8 @@ export class SpellDataModel extends BaseItem { hauszauber: new BooleanField(), technik: new StringField(), zauberdauer: new SchemaField({ - min: new NumberField(), - normal: new NumberField(), + min: new StringField(), + normal: new StringField(), additionalFormula: new StringField(), variables: new ArrayField(new StringField()), additionalFormulaTimeUnit: new StringField(), diff --git a/src/module/data/spomods/spoModData.mjs b/src/module/data/spomods/spoModData.mjs new file mode 100644 index 00000000..66c4d199 --- /dev/null +++ b/src/module/data/spomods/spoModData.mjs @@ -0,0 +1,66 @@ +const data = { + + "Veränderte Technik": { + name: "Veränderte Technik", + description: "Verändert die Technik", + mod: -7, + castTimeMod: 3, + castTimeMode: "Addition" + }, + "Veränderte Technik, zentral": { + name: "Veränderte Technik, zentral", + description: "Verändert die Technik", + mod: -12, + castTimeMod: 3, + castTimeMode: "Addition" + }, + "Halbierte Zauberdauer": { + name: "Halbierte Zauberdauer", + description: "Halbiert die Zauberdauer für eine Erschwernis von 5", + mod: -5, + castTimeMod: 0.5, + castTimeMode: "Multiply" + }, + "Verdoppelte Zauberdauer": { + name: "Verdoppelte Zauberdauer", + description: "Verdoppelt die Zauberdauer für eine Erleichterung von 3", + mod: 3, + castTimeMod: 2, + castTimeMode: "Multiply" + }, + "Erzwingen": { + name: "Erzwingen", + description: "Verringert Erschwernis um 1 je doppelten AsP Punkt", + mod: -1, + castTimeMod: 1, + castTimeMode: "Addition" + }, + "Kosten einsparen": { + name: "Kosten einsparen", + description: "Reduziert die Kosten des Zaubers um 10% für jede zusätzlich aufgewendete Aktion", + mod: 3, + castingCosts: 0.1, + castingCostsMode: "Multiply", + castTimeMod: 1, + castTimeMode: "Addition" + }, + // more to come + "Vergrößerung von Reichweite oder Wirkungsradius": { + name: "Vergrößerung von Reichweite oder Wirkungsradius", + description: "Vergrößert die Reichweite oder wenn möglich den Wirkungsradius auf kosten von Aktionen", + mod: 5, + castTimeMod: 1, + castTimeMode: "Addition" + }, + "Verkleinerung von Reichweite oder Wirkungsradius": { + name: "Verkleinerung von Reichweite oder Wirkungsradius", + description: "Verkleinert die Reichweite oder wenn möglich den Wirkungsradius auf kosten von Aktionen", + mod: 3, + castTimeMod: 1, + castTimeMode: "Addition" + }, + + +} + +export default data \ No newline at end of file diff --git a/src/module/dialog/spellDialog.mjs b/src/module/dialog/spellDialog.mjs index 3f99c2e9..5d03ffba 100644 --- a/src/module/dialog/spellDialog.mjs +++ b/src/module/dialog/spellDialog.mjs @@ -1,5 +1,6 @@ import {Talent} from "../data/talent.mjs"; import {ATTRIBUTE} from "../data/attribute.mjs"; +import SpoModData from "../data/spomods/spoModData.mjs"; const { ApplicationV2, @@ -44,23 +45,32 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { * @private */ _actor = null - _mutators = {} + _costMutators = {} + _castTimeMutators = {} _variants = {} _costModel = {} + _castTimeModel = {} displayModResult = 0 constructor(actor, spellId) { super() this._actor = actor this._spell = this._actor.itemTypes["Spell"].find(p => p._id === spellId) - this.displayModResult = Number(this._spell.system.zfw) this._circumstance = 0 this._mods = [] - this._mutators = {} + this.mod = 0 + this._costMutators = {} + this._castTimeMutators = {} this._selectedRepresentation = null this._spellDie = null this._variants = {} - this._costModel = {} + 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) + this.cost = this.normalizeCastingCost() ?? 0 } /** @@ -100,24 +110,34 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { } 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._mutators = {} - this._costModel.variables.forEach(v => this._mutators[v] = 0) + 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) } - let mutators = foundry.utils.expandObject(formData.object)["mutators"] + let costMutators = foundry.utils.expandObject(formData.object)["costMutators"] - if (mutators) { - this._mutators = mutators + if (costMutators) { + this._costMutators = costMutators } - this.displayModResult = Number(this._spell.system.zfw) + this.cost = this.normalizeCastingCost() + let castTimeMutators = foundry.utils.expandObject(formData.object)["castTimeMutators"] + + if (castTimeMutators) { + this._castTimeMutators = castTimeMutators + } + + this.mod = 0 this._activeVariants = Object.entries(this._variants) .filter(([key, truthiness]) => truthiness) .map(([key, truthiness]) => this._spell.system.varianten.find(v => v.name === key)) this._activeVariants.forEach(variant => { if (variant.mod) { - this.displayModResult += Number(variant.mod) + this.mod += Number(variant.mod) } }) @@ -129,6 +149,23 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { } + normalizeCastingCost() { + + let costFormula = this._costModel.additionalFormula + + this._costModel.variables.forEach(v => { + + costFormula = costFormula.replace(v, this._costMutators[v]) + + }) + + costFormula = Number(eval(costFormula)) + Number(this._costModel.cost) + if (costFormula <= this._costModel.min) { + costFormula = this._costModel.min + } + return costFormula + } + /** * * @param spell @@ -141,20 +178,50 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { // normal: Standard Zauberzeit eines Zaubers // additionalFormulaData: enthält die zur Normalzeit zusätzlichen Zauberdauer - const castingTime = spell.system.zauberdauer - - // direct actions - const aktionenRegExp = /(.*) Aktionen/ - const srRegExp = /(.*) SR/ - - if (castingTime.match(aktionenRegExp)) { - const [_, actions] = castingTime.match(aktionenRegExp) - return actions - } else if (castingTime.match(srRegExp)) { - const [_, actions] = castingTime.match(srRegExp) - return actions * 20 + const castingTime = spell.system.zauberdauer.normal ?? 0 + let baseCastTime = 0 + const minCastingTime = spell.system.zauberdauer.min ?? 0 + let baseMinCastTime = 0 + if (castingTime) { + baseCastTime = castingTime.replace(/(.*) Aktionen/g, (_, aktionen) => { + return aktionen + }) + baseCastTime = baseCastTime.replace(/(.*) SR/g, (_, aktionen) => { + return aktionen * 20 + }) } - return -1 + if (minCastingTime) { + baseMinCastTime = minCastingTime.replace(/(.*) Aktionen/g, (_, aktionen) => { + return aktionen + }) + baseMinCastTime = baseMinCastTime.replace(/(.*) SR/g, (_, aktionen) => { + return aktionen * 20 + }) + } + + let actualCastingTime = 0 + let formula = spell.system.zauberdauer.additionalFormula + if (formula) { + Object.entries(this._castTimeMutators).forEach(([variableName, variableValue]) => { + console.log(variableName, variableValue) + formula = formula.replaceAll(variableName, variableValue) + }) + + if (spell.system.zauberdauer.additionalFormulaTimeUnit == "Aktionen") { + actualCastingTime = (Number(baseCastTime) + Number(eval(formula)) ?? 0) + } else { + actualCastingTime = (Number(baseCastTime) + (Number(eval(formula)) * 20) ?? 0) + } + + } else { + actualCastingTime = baseCastTime + } + + if (Number(actualCastingTime) <= Number(baseMinCastTime)) { + actualCastingTime = baseMinCastTime + } + + return actualCastingTime } _configureRenderOptions(options) { @@ -180,8 +247,12 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { context.text = this._spell.system.wirkung context.dice = [] context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice') - context.modResult = this.displayModResult - context.displayModResult = (context.modResult > 0 ? "+" : "") + this.displayModResult + context.modResult = this._spell.system.zfw - this.mod + context.penalty = (this.mod > 0 ? "+" : "") + this.mod + context.displayModResult = (context.modResult > 0 ? "+" : "") + context.modResult + context.castingTime = this.#normalizeCastingTime(this._spell) + + // variable probe (should consider Achaz as they can replace one KL in a KL/KL/* spell with IN this._spell.system.probe.map(p => { if (p === "*") { @@ -214,28 +285,48 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) { } }) + // Repräsentation + context.representationOptions[""] = "" Object.entries(this._spell.system.repräsentation).forEach(([key, value]) => { context.representationOptions[key] = key }) + // Costs and Mutators + + context.castingCosts = this.cost + // set probe to current held probe variables or take from _spell - context.mutators = this._mutators + context.costMutators = this._costMutators if (this._costModel) { - context.variables = this._costModel.variables + context.costVariables = this._costModel.variables } else { - context.variables = [] + context.costVariables = [] } + // SpoMods + context.spoMods = [] + if (this._spell.system.modifikationen) { + this._spell.system.modifikationen.split(",").forEach(spoMod => { - // generate a list of variables in cost and castTime - - // generate a list of variants - - // generate a list of SpoMods + switch (spoMod.trim()) { + case "Zauberdauer": + context.spoMods.push(SpoModData["Halbierte Zauberdauer"]) + context.spoMods.push(SpoModData["Verdoppelte Zauberdauer"]) + break; + case "Kosten": + context.spoMods.push(SpoModData["Kosten einsparen"]) + break; + case "Reichweite": + context.spoMods.push(SpoModData["Verkleinerung von Reichweite oder Wirkungsradius"]) + context.spoMods.push(SpoModData["Vergrößerung von Reichweite oder Wirkungsradius"]) + break; + } + }) + } return context } diff --git a/src/templates/dialog/spell-dialog.hbs b/src/templates/dialog/spell-dialog.hbs index 12d11e40..50a3aab6 100644 --- a/src/templates/dialog/spell-dialog.hbs +++ b/src/templates/dialog/spell-dialog.hbs @@ -50,17 +50,39 @@ {{/if}} -
- Modifikationen - + {{#if this.spoMods}} +
+ Spontane Modifikation +
+ {{#each this.spoMods}} +
+
+ +
+
+ {{name}} +
+
+ {{/each}} +
+ {{/if}}
Variablen - {{#each variables}} + {{#each castTimeVariables}}
- + +
+ {{/each}} + {{#each costVariables}} +
+ +
{{/each}}
@@ -69,10 +91,10 @@
Dauer und Kosten
-