import BaseItem from "./base-item.mjs"; const { BooleanField, NumberField, SchemaField, ArrayField, StringField, HTMLField, } = foundry.data.fields; export class SpecialAbilityDataModel extends BaseItem { static defineSchema() { return { name: new StringField(), value: new StringField(), 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(), }) ), mod: new ArrayField(new SchemaField({ name: new StringField(), value: new NumberField(), })) }), ), gruppe: new StringField(), seite: new NumberField(), aktionsText: new HTMLField(), text: new HTMLField(), 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}), }) ), waffenLimit: new ArrayField( new SchemaField({ waffe: new StringField(), gruppe: new StringField(), mod: new NumberField(), }) ), mod: new ArrayField(new SchemaField({ name: new StringField(), value: new NumberField(), })), mehrereAktionen: new BooleanField(), } } #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} } }