import { CORE_SKILLS_CHOICES, CORE_SKILL_BONUS, CORE_SKILLS } from "../config/skill.mjs" /** * Core Skill data model for Prism RPG * * Core Skills are skills in which the character is particularly proficient. * - Basic skill checks: +5 modifier * - Advanced skill checks: Only accessible with Core Skill * - Core Skill Class: Gives access to a class based on archetype * - Attribute Bonus: +2 to one of 3 associated attributes */ export default class PrismRPGSkill 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, initial: "" }) // Core Skill type (from the 18 available Core Skills) schema.coreSkill = new fields.StringField({ required: true, initial: "acrobatics", choices: CORE_SKILLS_CHOICES, label: "Core Skill" }) // Is this the character's chosen Core Skill? schema.isCoreSkill = new fields.BooleanField({ required: true, initial: false, label: "Is Core Skill" }) // Primary attribute for this skill (str, dex, con, int, wis, cha) schema.primaryAttribute = new fields.StringField({ required: true, initial: "dex", label: "Primary Attribute" }) // If Core Skill, which attribute receives the +2 bonus? schema.attributeBonus = new fields.StringField({ required: true, initial: "", label: "Attribute Bonus" }) // Skill modifier (includes Core Skill bonus if applicable) schema.modifier = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, label: "Skill Modifier" }) // Can perform advanced checks schema.canAdvancedCheck = new fields.BooleanField({ required: true, initial: false, label: "Can Perform Advanced Checks" }) // Associated Core Skill Class (if any) schema.coreSkillClass = new fields.StringField({ required: true, initial: "", label: "Core Skill Class" }) // Notes/Custom description schema.notes = new fields.HTMLField({ required: true, initial: "", label: "Notes" }) return schema } /** @override */ static LOCALIZATION_PREFIXES = ["PRISMRPG.Skill"] /** * Get the Core Skill definition from SYSTEM */ get coreSkillDefinition() { return CORE_SKILLS?.[this.coreSkill] || null } /** * Get the localized Core Skill name */ get coreSkillLabel() { const definition = this.coreSkillDefinition return definition ? game.i18n.localize(definition.label) : this.coreSkill } /** * Get the available attribute choices for this Core Skill */ get attributeChoices() { const definition = this.coreSkillDefinition return definition?.attributeChoices || [] } /** * Prepare derived data */ prepareDerivedData() { super.prepareDerivedData() // D&D 5e style: Core Skill gives +2 proficiency bonus if (this.isCoreSkill) { this.modifier = 2 this.canAdvancedCheck = true } else { this.modifier = 0 this.canAdvancedCheck = false } } /** * Calculate skill check bonus * @param {string} attributeKey The attribute to use (str, dex, con, int, wis, cha) * @returns {number} Total skill check bonus */ getSkillCheckBonus(attributeKey) { let actor = this.parent?.actor if (!actor) return this.modifier const attribute = actor.system.characteristics?.[attributeKey] const attributeMod = attribute?.mod || 0 return attributeMod + this.modifier } }