188 lines
8.4 KiB
JavaScript
188 lines
8.4 KiB
JavaScript
import BaseItem from "./base-item.mjs";
|
|
|
|
const {ArrayField, SchemaField, BooleanField, NumberField, StringField, HTMLField} = foundry.data.fields;
|
|
|
|
export class VornachteileDataModel extends BaseItem {
|
|
|
|
static defineSchema() {
|
|
return {
|
|
name: new StringField({required: true}),
|
|
description: new HTMLField(),
|
|
nachteil: new BooleanField({required: true, initialValue: false}),
|
|
schlechteEigenschaft: new BooleanField({required: true, initialValue: false}),
|
|
|
|
// Optional Fields
|
|
value: new StringField({required: false, nullable: true}),
|
|
mod: new ArrayField(new SchemaField({
|
|
name: new StringField(),
|
|
talent: new StringField({required: false}),
|
|
value: new NumberField(),
|
|
}), {required: false}),
|
|
auswahl: new ArrayField(
|
|
new SchemaField({
|
|
name: new StringField(),
|
|
requirement: new ArrayField(
|
|
new SchemaField({
|
|
attribute: new StringField(),
|
|
minValue: new NumberField(),
|
|
maxValue: new NumberField(),
|
|
sonderfertigkeit: new StringField(),
|
|
talent: new StringField(),
|
|
compare: new SchemaField({
|
|
ownAttribute: new StringField(),
|
|
targetAttribute: new StringField(),
|
|
operation: new StringField(),
|
|
}, {required: false}),
|
|
})
|
|
),
|
|
mod: new ArrayField(new SchemaField({
|
|
name: new StringField(),
|
|
talent: new StringField({required: false}),
|
|
value: new NumberField(),
|
|
}))
|
|
}), {required: false}
|
|
),
|
|
}
|
|
/*
|
|
|
|
name: String, // Name of Vornachteil will be used for rendering and referencing by other Items
|
|
description: HTMLString, // only used for rendering
|
|
variant: [String]?, // variant name of Vornachteil e.g. "Mut" in the case of "Herausragende Eigenschaft"
|
|
levels: [Number]?, // available levels e.g. 1, 2 in the case of "Flink"
|
|
mods: [
|
|
{
|
|
level: Number?, // in reference to level of the Vornachteil, is null when it does not have any levels or is the only modification
|
|
field: String, // Reference to Actor Data e.g. "FF" maps to "FF.mod"
|
|
value: Number, // value of the Modification e.g. "+2" maps to 2
|
|
requirement: {
|
|
field: String // Reference to Actor Data e.g. "BE" maps "be.aktuell"
|
|
operation: String // Supported: "<=", ">"
|
|
value: Number // Target Value the referenced field has to compare against
|
|
}? // optional when the mod does not have an active requirement
|
|
}
|
|
]
|
|
|
|
*/
|
|
}
|
|
|
|
#getRequirements() {
|
|
if (this.value && this.auswahl?.find(p => p.name === this.value)) {
|
|
const auswahl = this.auswahl?.find(p => p.name === this.value)
|
|
return auswahl.requirement
|
|
} else {
|
|
return this.requirement
|
|
}
|
|
}
|
|
|
|
getActiveMod(options) {
|
|
if (this.isActive(options)) {
|
|
if (this.value && this.auswahl?.find(p => p.name === this.value)) {
|
|
const auswahl = this.auswahl?.find(p => p.name === this.value)
|
|
return auswahl.mod
|
|
} else {
|
|
return this.mod
|
|
}
|
|
} else {
|
|
return []
|
|
}
|
|
}
|
|
|
|
isActive(options) {
|
|
|
|
const requirements = this.#getRequirements()
|
|
|
|
let passes = true
|
|
let mod = 0
|
|
|
|
if (this.parent?.actor) {
|
|
const flatActor = foundry.utils.flattenObject(this.parent.actor.system)
|
|
if (requirements) for (let requirement of requirements) {
|
|
|
|
let targetField = null
|
|
|
|
if (requirement.attribute) {
|
|
targetField = flatActor?.[requirement.attribute.toLocaleLowerCase()]
|
|
}
|
|
if (requirement.talent) {
|
|
targetField = this.parent.actor.itemTypes["Skill"].find(p => p.name.toLocaleLowerCase() === requirement.talent.toLocaleLowerCase())?.taw ?? Number.NaN
|
|
}
|
|
if (requirement.minValue) {
|
|
passes = requirement.minValue <= targetField
|
|
if (!passes) console.debug(`fails requirement ${requirement.attribute ?? requirement.talent} (${requirement.minValue} <= ${targetField})`)
|
|
}
|
|
if (requirement.maxValue) {
|
|
passes = targetField <= requirement.maxValue
|
|
if (!passes) console.debug(`fails requirement ${requirement.attribute ?? requirement.talent} (${targetField} <= ${requirement.maxValue})`)
|
|
}
|
|
if (requirement.sonderfertigkeit) { // FIXME fails when it tries to self reference itself e.g. Ausweichen II has Ausweichen I as requirement
|
|
const regexp = /(\w*)\W?(\w*)?/
|
|
const [variantName, baseAbility, level] = regexp.exec(requirement.sonderfertigkeit)
|
|
|
|
passes = this.parent.actor.itemTypes["SpecialAbility"].find(p => p.name === baseAbility) !== undefined
|
|
if (!passes) console.debug(`fails requirement ${requirement.sonderfertigkeit} (not in possession)`)
|
|
}
|
|
if (requirement["compare"]) {
|
|
const {ownAttribute, operation, targetAttribute} = requirement["compare"]
|
|
if (options.target) {
|
|
const flatTarget = foundry.utils.flattenObject(options.target.system)
|
|
const foreignTargetField = flatTarget[targetAttribute]
|
|
const ourTargetField = flatActor[ownAttribute]
|
|
switch (operation) {
|
|
case "lt":
|
|
passes = ourTargetField < foreignTargetField;
|
|
break;
|
|
case "lte":
|
|
passes = ourTargetField <= foreignTargetField;
|
|
break;
|
|
case "eq":
|
|
passes = ourTargetField == foreignTargetField;
|
|
break;
|
|
case "neq":
|
|
passes = ourTargetField != foreignTargetField;
|
|
break;
|
|
case "gte":
|
|
passes = ourTargetField >= foreignTargetField;
|
|
break;
|
|
case "gt":
|
|
passes = ourTargetField > foreignTargetField;
|
|
break;
|
|
}
|
|
if (!passes) {
|
|
console.debug(`fails compare requirement ${ownAttribute} ${operation} ${targetAttribute}`)
|
|
}
|
|
} else {
|
|
console.debug(`fails compare requirement as no target has been selected`)
|
|
return false // cant pass as we dont have a target
|
|
}
|
|
}
|
|
if (!passes) {
|
|
console.debug("fails atleast 1 requirement of ", this)
|
|
break
|
|
}
|
|
}
|
|
if (passes) {
|
|
if (options?.weapon) {
|
|
for (const waff of this.waffenLimit) {
|
|
if (waff.waffe) {
|
|
passes = options?.weapon?.name === waff.waffe ?? false
|
|
if (waff.mod) mod = waff.mod
|
|
if (passes)
|
|
break
|
|
}
|
|
if (waff.gruppe) {
|
|
passes = options?.skill?.name === waff.gruppe ?? false
|
|
if (waff.mod) mod = waff.mod
|
|
if (passes)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
return {passes, mod}
|
|
}
|
|
|
|
}
|