import { SYSTEM } from "../config/system.mjs" import { CATEGORY } from "../config/skill.mjs" export default class LethalFantasySkill extends foundry.abstract.TypeDataModel { static defineSchema() { const fields = foundry.data.fields const schema = {} const requiredInteger = { required: true, nullable: false, integer: true } schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.category = new fields.StringField({ required: true, initial: "layperson", choices: SYSTEM.SKILL_CATEGORY }) schema.base = new fields.StringField({ required: true, initial: "WIS" }) schema.bonus = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }) schema.cost = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }) schema.weaponClass = new fields.StringField({ required: true, initial: "shortblade", choices: SYSTEM.WEAPON_CLASS }) schema.weaponBonus = new fields.SchemaField({ attack: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }), defense: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }), damage: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }) }) return schema } /** @override */ static LOCALIZATION_PREFIXES = ["LETHALFANTASY.Skill"] get skillCategory() { return game.i18n.localize(CATEGORY[this.category].label) } validate(options) { let isError = super.validate(options) console.log(this) let bonus = this._source.weaponBonus.attack + this._source.weaponBonus.defense + this._source.weaponBonus.damage console.log(bonus, this._source.skillTotal) if (bonus > Math.floor(this._source.skillTotal / 10)) { ui.notifications.error(game.i18n.localize("LETHALFANTASY.Skill.error.weaponBonus")) isError = true } return isError } prepareDerivedData() { super.prepareDerivedData(); this.skillTotal = this.computeBase(); if (this.category === "weapon") { this.totalBonus = this.weaponBonus.attack + this.weaponBonus.defense + this.weaponBonus.damage; if (Number(this.skillTotal)) { this.availableBonus = Math.max(Math.floor(this.skillTotal / 10) - 1, 0) } else { this.availableBonus = "N/A" } } } computeBase() { let actor = this.parent?.actor; if (!actor) { return `${this.base} + ${String(this.bonus)}`; } if (this.base === "N/A" || this.base === "None") { return this.bonus } // Split the base value per stat : WIS,DEX,STR,INT,CHA (example) let base = this.base; // Fix errors in the base value base.replace("CHARISMA", "CHA"); if (base.match(/OR/)) { let baseSplit = base.split("OR"); let baseSplitLength = baseSplit.length; if (baseSplitLength > 0) { // Select the max stat value from the parent actor let maxStat = 0; for (let i = 0; i < baseSplitLength; i++) { const stat = baseSplit[i].trim(); const statValue = actor.system.characteristics[stat.toLowerCase()]?.value || 0; if (statValue > maxStat) { maxStat = statValue; } } return maxStat + this.bonus } } else { if (base.match(/\+/)) { // Split with + calculate the total let baseSplit = base.split("+"); let baseSplitLength = baseSplit.length; if (baseSplitLength > 0) { let total = 0; for (let i = 0; i < baseSplitLength; i++) { const stat = baseSplit[i].trim(); const statValue = actor.system.characteristics[stat.toLowerCase()]?.value || 0; total += statValue; } return total + this.bonus } } else { // Single stat const statValue = actor.system.characteristics[base.trim().toLowerCase()]?.value || 0; return statValue + this.bonus } } return `${this.base} + ${String(this.bonus)}`; } }