diff --git a/lang/en.json b/lang/en.json index 6a34037d..f310a01d 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2371,7 +2371,8 @@ "insufficientResources": "You have insufficient resources", "multiclassAlreadyPresent": "You already have a class and multiclass", "subclassesAlreadyPresent": "You already have a class and multiclass subclass", - "noDiceSystem": "Your selected dice {system} does not have a {faces} dice" + "noDiceSystem": "Your selected dice {system} does not have a {faces} dice", + "subclassAlreadyLinked": "{name} is already a subclass in the class {class}. Remove it from there if you want it to be a subclass to this class." }, "Tooltip": { "disableEffect": "Disable Effect", diff --git a/module/applications/characterCreation/characterCreation.mjs b/module/applications/characterCreation/characterCreation.mjs index f9f832e8..19d8e4c5 100644 --- a/module/applications/characterCreation/characterCreation.mjs +++ b/module/applications/characterCreation/characterCreation.mjs @@ -432,12 +432,16 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl } }; - if (type == 'domains') + if (type === 'domains') presets.filter = { 'level.max': { key: 'level.max', value: 1 }, 'system.domain': { key: 'system.domain', value: this.setup.class?.system.domains ?? null } }; + if (type === 'subclasses') + presets.filter = { + 'system.linkedClass': { key: 'system.linkedClass', value: this.setup.class?.uuid } + }; if (equipment.includes(type)) presets.filter = { 'system.tier': { key: 'system.tier', value: 1 }, diff --git a/module/applications/sheets/items/class.mjs b/module/applications/sheets/items/class.mjs index 01f4249a..033c63e6 100644 --- a/module/applications/sheets/items/class.mjs +++ b/module/applications/sheets/items/class.mjs @@ -119,6 +119,15 @@ export default class ClassSheet extends DHBaseItemSheet { const itemType = data.data ? data.type : item.type; const target = event.target.closest('fieldset.drop-section'); if (itemType === 'subclass') { + if (item.system.linkedClass) { + return ui.notifications.warn( + game.i18n.format('DAGGERHEART.UI.Notifications.subclassAlreadyLinked', { + name: item.name, + class: this.document.name + }) + ); + } + await item.update({ 'system.linkedClass': this.document.uuid }); await this.document.update({ 'system.subclasses': [...this.document.system.subclasses.map(x => x.uuid), item.uuid] }); @@ -181,6 +190,12 @@ export default class ClassSheet extends DHBaseItemSheet { static async #removeItemFromCollection(_event, element) { const { uuid, target } = element.dataset; const prop = foundry.utils.getProperty(this.document.system, target); + + if (target === 'subclasses') { + const subclass = await foundry.utils.fromUuid(uuid); + await subclass.update({ 'system.linkedClass': null }); + } + await this.document.update({ [`system.${target}`]: prop.filter(i => i.uuid !== uuid).map(x => x.uuid) }); } diff --git a/module/config/itemBrowserConfig.mjs b/module/config/itemBrowserConfig.mjs index 6e3c0dea..7b9a0456 100644 --- a/module/config/itemBrowserConfig.mjs +++ b/module/config/itemBrowserConfig.mjs @@ -2,404 +2,419 @@ export const typeConfig = { adversaries: { columns: [ { - key: "system.tier", - label: "Tier" + key: 'system.tier', + label: 'Tier' }, { - key: "system.type", - label: "Type" + key: 'system.type', + label: 'Type' } ], filters: [ { - key: "system.tier", - label: "Tier", + key: 'system.tier', + label: 'Tier', field: 'system.api.models.actors.DhAdversary.schema.fields.tier' }, { - key: "system.type", - label: "Type", + key: 'system.type', + label: 'Type', field: 'system.api.models.actors.DhAdversary.schema.fields.type' }, { - key: "system.difficulty", - name: "difficulty.min", - label: "Difficulty (Min)", + key: 'system.difficulty', + name: 'difficulty.min', + label: 'Difficulty (Min)', field: 'system.api.models.actors.DhAdversary.schema.fields.difficulty', - operator: "gte" + operator: 'gte' }, { - key: "system.difficulty", - name: "difficulty.max", - label: "Difficulty (Max)", + key: 'system.difficulty', + name: 'difficulty.max', + label: 'Difficulty (Max)', field: 'system.api.models.actors.DhAdversary.schema.fields.difficulty', - operator: "lte" + operator: 'lte' }, { - key: "system.resources.hitPoints.max", - name: "hp.min", - label: "Hit Points (Min)", + key: 'system.resources.hitPoints.max', + name: 'hp.min', + label: 'Hit Points (Min)', field: 'system.api.models.actors.DhAdversary.schema.fields.resources.fields.hitPoints.fields.max', - operator: "gte" + operator: 'gte' }, { - key: "system.resources.hitPoints.max", - name: "hp.max", - label: "Hit Points (Max)", + key: 'system.resources.hitPoints.max', + name: 'hp.max', + label: 'Hit Points (Max)', field: 'system.api.models.actors.DhAdversary.schema.fields.resources.fields.hitPoints.fields.max', - operator: "lte" + operator: 'lte' }, { - key: "system.resources.stress.max", - name: "stress.min", - label: "Stress (Min)", + key: 'system.resources.stress.max', + name: 'stress.min', + label: 'Stress (Min)', field: 'system.api.models.actors.DhAdversary.schema.fields.resources.fields.stress.fields.max', - operator: "gte" + operator: 'gte' }, { - key: "system.resources.stress.max", - name: "stress.max", - label: "Stress (Max)", + key: 'system.resources.stress.max', + name: 'stress.max', + label: 'Stress (Max)', field: 'system.api.models.actors.DhAdversary.schema.fields.resources.fields.stress.fields.max', - operator: "lte" - }, + operator: 'lte' + } ] }, items: { columns: [ { - key: "type", - label: "Type" + key: 'type', + label: 'Type' }, { - key: "system.secondary", - label: "Subtype", - format: (isSecondary) => isSecondary ? "secondary" : (isSecondary === false ? "primary" : '-') + key: 'system.secondary', + label: 'Subtype', + format: isSecondary => (isSecondary ? 'secondary' : isSecondary === false ? 'primary' : '-') }, { - key: "system.tier", - label: "Tier" + key: 'system.tier', + label: 'Tier' } ], filters: [ { - key: "type", - label: "Type", - choices: () => CONFIG.Item.documentClass.TYPES.filter(t => ["armor", "weapon", "consumable", "loot"].includes(t)).map(t => ({ value: t, label: t })) + key: 'type', + label: 'Type', + choices: () => + CONFIG.Item.documentClass.TYPES.filter(t => + ['armor', 'weapon', 'consumable', 'loot'].includes(t) + ).map(t => ({ value: t, label: t })) }, { - key: "system.secondary", - label: "Subtype", + key: 'system.secondary', + label: 'Subtype', choices: [ - { value: false, label: "Primary Weapon"}, - { value: true, label: "Secondary Weapon"} + { value: false, label: 'Primary Weapon' }, + { value: true, label: 'Secondary Weapon' } ] }, { - key: "system.tier", - label: "Tier", - choices: [{ value: "1", label: "1"}, { value: "2", label: "2"}, { value: "3", label: "3"}, { value: "4", label: "4"}] + key: 'system.tier', + label: 'Tier', + choices: [ + { value: '1', label: '1' }, + { value: '2', label: '2' }, + { value: '3', label: '3' }, + { value: '4', label: '4' } + ] }, { - key: "system.burden", - label: "Burden", + key: 'system.burden', + label: 'Burden', field: 'system.api.models.items.DHWeapon.schema.fields.burden' }, { - key: "system.attack.roll.trait", - label: "Trait", + key: 'system.attack.roll.trait', + label: 'Trait', field: 'system.api.models.actions.actionsTypes.attack.schema.fields.roll.fields.trait' }, { - key: "system.attack.range", - label: "Range", + key: 'system.attack.range', + label: 'Range', field: 'system.api.models.actions.actionsTypes.attack.schema.fields.range' }, { - key: "system.baseScore", - name: "armor.min", - label: "Armor Score (Min)", + key: 'system.baseScore', + name: 'armor.min', + label: 'Armor Score (Min)', field: 'system.api.models.items.DHArmor.schema.fields.baseScore', - operator: "gte" + operator: 'gte' }, { - key: "system.baseScore", - name: "armor.max", - label: "Armor Score (Max)", + key: 'system.baseScore', + name: 'armor.max', + label: 'Armor Score (Max)', field: 'system.api.models.items.DHArmor.schema.fields.baseScore', - operator: "lte" + operator: 'lte' }, { - key: "system.itemFeatures", - label: "Features", - choices: () => [...Object.entries(CONFIG.DH.ITEM.weaponFeatures), ...Object.entries(CONFIG.DH.ITEM.armorFeatures)].map(([k,v]) => ({ value: k, label: v.label})), - operator: "contains3" + key: 'system.itemFeatures', + label: 'Features', + choices: () => + [ + ...Object.entries(CONFIG.DH.ITEM.weaponFeatures), + ...Object.entries(CONFIG.DH.ITEM.armorFeatures) + ].map(([k, v]) => ({ value: k, label: v.label })), + operator: 'contains3' } ] }, features: { - columns: [ - - ], - filters: [ - - ] + columns: [], + filters: [] }, cards: { columns: [ { - key: "system.type", - label: "Type" + key: 'system.type', + label: 'Type' }, { - key: "system.domain", - label: "Domain" + key: 'system.domain', + label: 'Domain' }, { - key: "system.level", - label: "Level" + key: 'system.level', + label: 'Level' } ], filters: [ { - key: "system.type", - label: "Type", + key: 'system.type', + label: 'Type', field: 'system.api.models.items.DHDomainCard.schema.fields.type' }, { - key: "system.domain", - label: "Domain", + key: 'system.domain', + label: 'Domain', field: 'system.api.models.items.DHDomainCard.schema.fields.domain', - operator: "contains2" + operator: 'contains2' }, { - key: "system.level", - name: "level.min", - label: "Level (Min)", + key: 'system.level', + name: 'level.min', + label: 'Level (Min)', field: 'system.api.models.items.DHDomainCard.schema.fields.level', - operator: "gte" + operator: 'gte' }, { - key: "system.level", - name: "level.max", - label: "Level (Max)", + key: 'system.level', + name: 'level.max', + label: 'Level (Max)', field: 'system.api.models.items.DHDomainCard.schema.fields.level', - operator: "lte" + operator: 'lte' }, { - key: "system.recallCost", - name: "recall.min", - label: "Recall Cost (Min)", + key: 'system.recallCost', + name: 'recall.min', + label: 'Recall Cost (Min)', field: 'system.api.models.items.DHDomainCard.schema.fields.recallCost', - operator: "gte" + operator: 'gte' }, { - key: "system.recallCost", - name: "recall.max", - label: "Recall Cost (Max)", + key: 'system.recallCost', + name: 'recall.max', + label: 'Recall Cost (Max)', field: 'system.api.models.items.DHDomainCard.schema.fields.recallCost', - operator: "lte" + operator: 'lte' } ] }, classes: { columns: [ { - key: "system.evasion", - label: "Evasion" + key: 'system.evasion', + label: 'Evasion' }, { - key: "system.hitPoints", - label: "Hit Points" + key: 'system.hitPoints', + label: 'Hit Points' }, { - key: "system.domains", - label: "Domains" + key: 'system.domains', + label: 'Domains' } ], filters: [ { - key: "system.evasion", - name: "evasion.min", - label: "Evasion (Min)", + key: 'system.evasion', + name: 'evasion.min', + label: 'Evasion (Min)', field: 'system.api.models.items.DHClass.schema.fields.evasion', - operator: "gte" + operator: 'gte' }, { - key: "system.evasion", - name: "evasion.max", - label: "Evasion (Max)", + key: 'system.evasion', + name: 'evasion.max', + label: 'Evasion (Max)', field: 'system.api.models.items.DHClass.schema.fields.evasion', - operator: "lte" + operator: 'lte' }, { - key: "system.hitPoints", - name: "hp.min", - label: "Hit Points (Min)", + key: 'system.hitPoints', + name: 'hp.min', + label: 'Hit Points (Min)', field: 'system.api.models.items.DHClass.schema.fields.hitPoints', - operator: "gte" + operator: 'gte' }, { - key: "system.hitPoints", - name: "hp.max", - label: "Hit Points (Max)", + key: 'system.hitPoints', + name: 'hp.max', + label: 'Hit Points (Max)', field: 'system.api.models.items.DHClass.schema.fields.hitPoints', - operator: "lte" + operator: 'lte' }, { - key: "system.domains", - label: "Domains", - choices: () => Object.values(CONFIG.DH.DOMAIN.domains).map(d => ({ value: d.id, label: d.label})), - operator: "contains2" + key: 'system.domains', + label: 'Domains', + choices: () => Object.values(CONFIG.DH.DOMAIN.domains).map(d => ({ value: d.id, label: d.label })), + operator: 'contains2' } ] }, subclasses: { columns: [ { - key: "id", - label: "Class", - format: (id) => { - return ""; + key: 'id', + label: 'Class', + format: id => { + console.log(id); + return ''; } }, { - key: "system.spellcastingTrait", - label: "Spellcasting Trait" - } - ], - filters: [] - }, - beastforms: { - columns: [ - { - key: "system.tier", - label: "Tier" - }, - { - key: "system.mainTrait", - label: "Main Trait" + key: 'system.spellcastingTrait', + label: 'Spellcasting Trait' } ], filters: [ { - key: "system.tier", - label: "Tier", + key: 'system.linkedClass', + label: 'Class', + field: 'system.api.models.items.DHSubclass.schema.fields.linkedClass' + } + ] + }, + beastforms: { + columns: [ + { + key: 'system.tier', + label: 'Tier' + }, + { + key: 'system.mainTrait', + label: 'Main Trait' + } + ], + filters: [ + { + key: 'system.tier', + label: 'Tier', field: 'system.api.models.items.DHBeastform.schema.fields.tier' }, { - key: "system.mainTrait", - label: "Main Trait", + key: 'system.mainTrait', + label: 'Main Trait', field: 'system.api.models.items.DHBeastform.schema.fields.mainTrait' } ] } -} +}; export const compendiumConfig = { - "daggerheart": { - id: "daggerheart", - label: "DAGGERHEART", + daggerheart: { + id: 'daggerheart', + label: 'DAGGERHEART', folders: { - "adversaries": { - id: "adversaries", - keys: ["adversaries"], - label: "Adversaries", - type: ["adversary"], - listType: "adversaries" + adversaries: { + id: 'adversaries', + keys: ['adversaries'], + label: 'Adversaries', + type: ['adversary'], + listType: 'adversaries' }, - "ancestries": { - id: "ancestries", - keys: ["ancestries"], - label: "Ancestries", - type: ["ancestry"], + ancestries: { + id: 'ancestries', + keys: ['ancestries'], + label: 'Ancestries', + type: ['ancestry'], folders: { - "features": { - id: "features", - keys: ["ancestries"], - label: "Features", - type: ["feature"] + features: { + id: 'features', + keys: ['ancestries'], + label: 'Features', + type: ['feature'] } } }, - "equipments": { - id: "equipments", - keys: ["armors", "weapons", "consumables", "loot"], - label: "Equipment", - type: ["armor", "weapon", "consumable", "loot"], - listType: "items" + equipments: { + id: 'equipments', + keys: ['armors', 'weapons', 'consumables', 'loot'], + label: 'Equipment', + type: ['armor', 'weapon', 'consumable', 'loot'], + listType: 'items' }, - "classes": { - id: "classes", - keys: ["classes"], - label: "Classes", - type: ["class"], + classes: { + id: 'classes', + keys: ['classes'], + label: 'Classes', + type: ['class'], folders: { - "features": { - id: "features", - keys: ["classes"], - label: "Features", - type: ["feature"] + features: { + id: 'features', + keys: ['classes'], + label: 'Features', + type: ['feature'] }, - "items": { - id: "items", - keys: ["classes"], - label: "Items", - type: ["armor", "weapon", "consumable", "loot"], - listType: "items" + items: { + id: 'items', + keys: ['classes'], + label: 'Items', + type: ['armor', 'weapon', 'consumable', 'loot'], + listType: 'items' } }, - listType: "classes" + listType: 'classes' }, - "subclasses": { - id: "subclasses", - keys: ["subclasses"], - label: "Subclasses", - type: ["subclass"], - listType: "subclasses" + subclasses: { + id: 'subclasses', + keys: ['subclasses'], + label: 'Subclasses', + type: ['subclass'], + listType: 'subclasses' }, - "domains": { - id: "domains", - keys: ["domains"], - label: "Domain Cards", - type: ["domainCard"], - listType: "cards" + domains: { + id: 'domains', + keys: ['domains'], + label: 'Domain Cards', + type: ['domainCard'], + listType: 'cards' }, - "communities": { - id: "communities", - keys: ["communities"], - label: "Communities", - type: ["community"], + communities: { + id: 'communities', + keys: ['communities'], + label: 'Communities', + type: ['community'], folders: { - "features": { - id: "features", - keys: ["communities"], - label: "Features", - type: ["feature"] + features: { + id: 'features', + keys: ['communities'], + label: 'Features', + type: ['feature'] } } }, - "environments": { - id: "environments", - keys: ["environments"], - label: "Environments", - type: ["environment"] + environments: { + id: 'environments', + keys: ['environments'], + label: 'Environments', + type: ['environment'] }, - "beastforms": { - id: "beastforms", - keys: ["beastforms"], - label: "Beastforms", - type: ["beastform"], - listType: "beastforms", + beastforms: { + id: 'beastforms', + keys: ['beastforms'], + label: 'Beastforms', + type: ['beastform'], + listType: 'beastforms', folders: { - "features": { - id: "features", - keys: ["beastforms"], - label: "Features", - type: ["feature"] + features: { + id: 'features', + keys: ['beastforms'], + label: 'Features', + type: ['feature'] } } } } } -} \ No newline at end of file +}; diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index 46b83753..e16a15f7 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -1,3 +1,4 @@ +import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import ItemLinkFields from '../fields/itemLinkFields.mjs'; import BaseDataItem from './base.mjs'; @@ -25,7 +26,8 @@ export default class DHSubclass extends BaseDataItem { }), features: new ItemLinkFields(), featureState: new fields.NumberField({ required: true, initial: 1, min: 1 }), - isMulticlass: new fields.BooleanField({ initial: false }) + isMulticlass: new fields.BooleanField({ initial: false }), + linkedClass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true, initial: null }) }; }