import { CORE_SKILLS_CHOICES, CORE_SKILL_BONUS, CORE_SKILLS } from "../config/skill.mjs" import { SUB_ATTRIBUTES } from "../config/character.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: "" }) // Is this the character's chosen Core Skill? schema.isCoreSkill = new fields.BooleanField({ required: true, initial: false, label: "Is Core Skill" }) // First sub-attribute for this skill schema.subAttribute1 = new fields.StringField({ required: true, initial: "prowess", label: "Sub-Attribute 1" }) // Second sub-attribute for this skill schema.subAttribute2 = new fields.StringField({ required: true, initial: "initiative", label: "Sub-Attribute 2" }) // 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() // Core Skill gives +5 proficiency bonus if (this.isCoreSkill) { this.modifier = 5 this.canAdvancedCheck = true } else { this.modifier = 0 this.canAdvancedCheck = false } } /** * Calculate skill check bonus * @param {string} subAttributeKey The sub-attribute to use (prowess, vigor, etc.) * @returns {number} Total skill check bonus */ getSkillCheckBonus(subAttributeKey) { let actor = this.parent?.actor if (!actor) return this.modifier const subAttribute = actor.system.subAttributes?.[subAttributeKey] const subAttributeMod = subAttribute?.value || 0 return subAttributeMod + this.modifier } /** * Get the available sub-attribute choices for this skill */ get subAttributeChoices() { const choices = {} if (this.subAttribute1) { choices[this.subAttribute1] = SUB_ATTRIBUTES[this.subAttribute1]?.label || this.subAttribute1 } if (this.subAttribute2) { choices[this.subAttribute2] = SUB_ATTRIBUTES[this.subAttribute2]?.label || this.subAttribute2 } return choices } }