implements partial (display) support for SpoMods
parent
5f85631679
commit
959f47f348
|
|
@ -22,8 +22,8 @@ export class SpellDataModel extends BaseItem {
|
||||||
hauszauber: new BooleanField(),
|
hauszauber: new BooleanField(),
|
||||||
technik: new StringField(),
|
technik: new StringField(),
|
||||||
zauberdauer: new SchemaField({
|
zauberdauer: new SchemaField({
|
||||||
min: new NumberField(),
|
min: new StringField(),
|
||||||
normal: new NumberField(),
|
normal: new StringField(),
|
||||||
additionalFormula: new StringField(),
|
additionalFormula: new StringField(),
|
||||||
variables: new ArrayField(new StringField()),
|
variables: new ArrayField(new StringField()),
|
||||||
additionalFormulaTimeUnit: new StringField(),
|
additionalFormulaTimeUnit: new StringField(),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import {Talent} from "../data/talent.mjs";
|
import {Talent} from "../data/talent.mjs";
|
||||||
import {ATTRIBUTE} from "../data/attribute.mjs";
|
import {ATTRIBUTE} from "../data/attribute.mjs";
|
||||||
|
import SpoModData from "../data/spomods/spoModData.mjs";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ApplicationV2,
|
ApplicationV2,
|
||||||
|
|
@ -44,23 +45,32 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_actor = null
|
_actor = null
|
||||||
_mutators = {}
|
_costMutators = {}
|
||||||
|
_castTimeMutators = {}
|
||||||
_variants = {}
|
_variants = {}
|
||||||
_costModel = {}
|
_costModel = {}
|
||||||
|
_castTimeModel = {}
|
||||||
displayModResult = 0
|
displayModResult = 0
|
||||||
|
|
||||||
constructor(actor, spellId) {
|
constructor(actor, spellId) {
|
||||||
super()
|
super()
|
||||||
this._actor = actor
|
this._actor = actor
|
||||||
this._spell = this._actor.itemTypes["Spell"].find(p => p._id === spellId)
|
this._spell = this._actor.itemTypes["Spell"].find(p => p._id === spellId)
|
||||||
this.displayModResult = Number(this._spell.system.zfw)
|
|
||||||
this._circumstance = 0
|
this._circumstance = 0
|
||||||
this._mods = []
|
this._mods = []
|
||||||
this._mutators = {}
|
this.mod = 0
|
||||||
|
this._costMutators = {}
|
||||||
|
this._castTimeMutators = {}
|
||||||
this._selectedRepresentation = null
|
this._selectedRepresentation = null
|
||||||
this._spellDie = null
|
this._spellDie = null
|
||||||
this._variants = {}
|
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) {
|
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._costModel = this._spell.system.kosten.find(c => c.repräsentation === context.selectedRepresentation) ?? this._spell.system.kosten.find(c => c.repräsentation === "")
|
||||||
this._mutators = {}
|
this._castTimeModel = this._spell.system.zauberdauer
|
||||||
this._costModel.variables.forEach(v => this._mutators[v] = 0)
|
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) {
|
if (costMutators) {
|
||||||
this._mutators = mutators
|
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)
|
this._activeVariants = Object.entries(this._variants)
|
||||||
.filter(([key, truthiness]) => truthiness)
|
.filter(([key, truthiness]) => truthiness)
|
||||||
.map(([key, truthiness]) => this._spell.system.varianten.find(v => v.name === key))
|
.map(([key, truthiness]) => this._spell.system.varianten.find(v => v.name === key))
|
||||||
this._activeVariants.forEach(variant => {
|
this._activeVariants.forEach(variant => {
|
||||||
|
|
||||||
if (variant.mod) {
|
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
|
* @param spell
|
||||||
|
|
@ -141,20 +178,50 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
// normal: Standard Zauberzeit eines Zaubers
|
// normal: Standard Zauberzeit eines Zaubers
|
||||||
// additionalFormulaData: enthält die zur Normalzeit zusätzlichen Zauberdauer
|
// additionalFormulaData: enthält die zur Normalzeit zusätzlichen Zauberdauer
|
||||||
|
|
||||||
const castingTime = spell.system.zauberdauer
|
const castingTime = spell.system.zauberdauer.normal ?? 0
|
||||||
|
let baseCastTime = 0
|
||||||
// direct actions
|
const minCastingTime = spell.system.zauberdauer.min ?? 0
|
||||||
const aktionenRegExp = /(.*) Aktionen/
|
let baseMinCastTime = 0
|
||||||
const srRegExp = /(.*) SR/
|
if (castingTime) {
|
||||||
|
baseCastTime = castingTime.replace(/(.*) Aktionen/g, (_, aktionen) => {
|
||||||
if (castingTime.match(aktionenRegExp)) {
|
return aktionen
|
||||||
const [_, actions] = castingTime.match(aktionenRegExp)
|
})
|
||||||
return actions
|
baseCastTime = baseCastTime.replace(/(.*) SR/g, (_, aktionen) => {
|
||||||
} else if (castingTime.match(srRegExp)) {
|
return aktionen * 20
|
||||||
const [_, actions] = castingTime.match(srRegExp)
|
})
|
||||||
return actions * 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) {
|
_configureRenderOptions(options) {
|
||||||
|
|
@ -180,8 +247,12 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
context.text = this._spell.system.wirkung
|
context.text = this._spell.system.wirkung
|
||||||
context.dice = []
|
context.dice = []
|
||||||
context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice')
|
context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice')
|
||||||
context.modResult = this.displayModResult
|
context.modResult = this._spell.system.zfw - this.mod
|
||||||
context.displayModResult = (context.modResult > 0 ? "+" : "") + this.displayModResult
|
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 => {
|
this._spell.system.probe.map(p => {
|
||||||
if (p === "*") {
|
if (p === "*") {
|
||||||
|
|
@ -214,28 +285,48 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Repräsentation
|
||||||
|
|
||||||
context.representationOptions[""] = ""
|
context.representationOptions[""] = ""
|
||||||
Object.entries(this._spell.system.repräsentation).forEach(([key, value]) => {
|
Object.entries(this._spell.system.repräsentation).forEach(([key, value]) => {
|
||||||
context.representationOptions[key] = key
|
context.representationOptions[key] = key
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Costs and Mutators
|
||||||
|
|
||||||
|
context.castingCosts = this.cost
|
||||||
|
|
||||||
|
|
||||||
// set probe to current held probe variables or take from _spell
|
// set probe to current held probe variables or take from _spell
|
||||||
context.mutators = this._mutators
|
context.costMutators = this._costMutators
|
||||||
|
|
||||||
|
|
||||||
if (this._costModel) {
|
if (this._costModel) {
|
||||||
context.variables = this._costModel.variables
|
context.costVariables = this._costModel.variables
|
||||||
} else {
|
} 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
|
switch (spoMod.trim()) {
|
||||||
|
case "Zauberdauer":
|
||||||
// generate a list of variants
|
context.spoMods.push(SpoModData["Halbierte Zauberdauer"])
|
||||||
|
context.spoMods.push(SpoModData["Verdoppelte Zauberdauer"])
|
||||||
// generate a list of SpoMods
|
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
|
return context
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,17 +50,39 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<fieldset>
|
{{#if this.spoMods}}
|
||||||
<legend>Modifikationen</legend>
|
<fieldset class="scroll-y">
|
||||||
|
<legend>Spontane Modifikation</legend>
|
||||||
|
<div class="variantList">
|
||||||
|
{{#each this.spoMods}}
|
||||||
|
<div class="variant" data-tooltip="{{{description}}}">
|
||||||
|
<div class="selection">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="spoMods.{{name}}" {{checked variantChecked}}>
|
||||||
|
{{#if (gte mod 0)}}+{{/if}}{{mod}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="variantText">
|
||||||
|
<em>{{name}}</em>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Variablen</legend>
|
<legend>Variablen</legend>
|
||||||
{{#each variables}}
|
{{#each castTimeVariables}}
|
||||||
<div>
|
<div>
|
||||||
<label for="{{this}}">{{this}}: </label>
|
<label for="{{this}}">{{this}}: </label>
|
||||||
<input type="number" name="mutators.{{this}}" value="{{lookup ../mutators this}}"/>
|
<input type="number" name="castTimeMutators.{{this}}" value="{{lookup ../castTimeMutators this}}"/>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
{{#each costVariables}}
|
||||||
|
<div>
|
||||||
|
<label for="{{this}}">{{this}}: </label>
|
||||||
|
<input type="number" name="costMutators.{{this}}" value="{{lookup ../costMutators this}}"/>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
@ -69,10 +91,10 @@
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Dauer und Kosten</legend>
|
<legend>Dauer und Kosten</legend>
|
||||||
<div class="malus-and-mod">
|
<div class="malus-and-mod">
|
||||||
<label><span>Zauberdauer</span>
|
<label><span>Zauberdauer (A)</span>
|
||||||
<output name="castingTime">{{castingTime}}</output>
|
<output name="castingTime">{{castingTime}}</output>
|
||||||
</label>
|
</label>
|
||||||
<label><span>Kosten</span>
|
<label><span>Kosten (AsP)</span>
|
||||||
<output name="costs">{{castingCosts}}</output>
|
<output name="costs">{{castingCosts}}</output>
|
||||||
</label>
|
</label>
|
||||||
<label><span>Erschwernis</span>
|
<label><span>Erschwernis</span>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue