188 lines
7.6 KiB
JavaScript
188 lines
7.6 KiB
JavaScript
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}
|
|
}
|
|
}
|