diff --git a/README.md b/README.md index a5c7fe48..5e2bbcec 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,15 @@ Now you should be able to build the app using `npm start` ## Contributing Looking to contribute to the project? Look no further, check out our [contributing guide](contributing.md), and keep the [Code of Conduct](coc.md) in mind when working on things. + +## Disclaimer: + +**Daggerheart System** +Daggerheart is a trademark of Darrington Press LLC. All original content, mechanics, and intellectual property related to the Daggerheart roleplaying game are © Darrington Press LLC. + +This project is intended for personal or non-commercial use. All rights to Daggerheart’s original materials remain with their respective owners. + +**Free Icons** +Some Icons used in this project are provided by https://game-icons.net and are licensed under the Creative Commons Attribution 3.0 Unported (CC BY 3.0). + +This project is an unofficial fan creation and is not affiliated with or endorsed by Darrington Press or Critical Role. diff --git a/assets/icons/documents/actors/capybara.svg b/assets/icons/documents/actors/capybara.svg new file mode 100644 index 00000000..90deb64a --- /dev/null +++ b/assets/icons/documents/actors/capybara.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/actors/dragon-head.svg b/assets/icons/documents/actors/dragon-head.svg new file mode 100644 index 00000000..d9e008f5 --- /dev/null +++ b/assets/icons/documents/actors/dragon-head.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/actors/forest.svg b/assets/icons/documents/actors/forest.svg new file mode 100644 index 00000000..8f7117e8 --- /dev/null +++ b/assets/icons/documents/actors/forest.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/battered-axe.svg b/assets/icons/documents/items/battered-axe.svg new file mode 100644 index 00000000..5d7be27d --- /dev/null +++ b/assets/icons/documents/items/battered-axe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/card-play.svg b/assets/icons/documents/items/card-play.svg new file mode 100644 index 00000000..587cb1c1 --- /dev/null +++ b/assets/icons/documents/items/card-play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/chest-armor.svg b/assets/icons/documents/items/chest-armor.svg new file mode 100644 index 00000000..2cef80a6 --- /dev/null +++ b/assets/icons/documents/items/chest-armor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/family-tree.svg b/assets/icons/documents/items/family-tree.svg new file mode 100644 index 00000000..d95c935d --- /dev/null +++ b/assets/icons/documents/items/family-tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/laurel-crown.svg b/assets/icons/documents/items/laurel-crown.svg new file mode 100644 index 00000000..34a54d2a --- /dev/null +++ b/assets/icons/documents/items/laurel-crown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/laurels.svg b/assets/icons/documents/items/laurels.svg new file mode 100644 index 00000000..2c3cdf63 --- /dev/null +++ b/assets/icons/documents/items/laurels.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/open-treasure-chest.svg b/assets/icons/documents/items/open-treasure-chest.svg new file mode 100644 index 00000000..172a8003 --- /dev/null +++ b/assets/icons/documents/items/open-treasure-chest.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/round-potion.svg b/assets/icons/documents/items/round-potion.svg new file mode 100644 index 00000000..7f981914 --- /dev/null +++ b/assets/icons/documents/items/round-potion.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/stars-stack.svg b/assets/icons/documents/items/stars-stack.svg new file mode 100644 index 00000000..19c197f6 --- /dev/null +++ b/assets/icons/documents/items/stars-stack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/village.svg b/assets/icons/documents/items/village.svg new file mode 100644 index 00000000..c28d742b --- /dev/null +++ b/assets/icons/documents/items/village.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/documents/items/wolf-head.svg b/assets/icons/documents/items/wolf-head.svg new file mode 100644 index 00000000..2be500c1 --- /dev/null +++ b/assets/icons/documents/items/wolf-head.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index c0cecb59..e64c64f3 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -105,6 +105,13 @@ export default class DhpAdversary extends BaseDataActor { }; } + /* -------------------------------------------- */ + + /**@inheritdoc */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/actors/dragon-head.svg'; + + /* -------------------------------------------- */ + get attackBonus() { return this.attack.roll.bonus; } diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index f0db33e9..386b9695 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -69,6 +69,16 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { return schema; } + /* -------------------------------------------- */ + + /** + * The default icon used for newly created Actors documents + * @type {string} + */ + static DEFAULT_ICON = null; + + /* -------------------------------------------- */ + /** * Obtain a data object used to evaluate any dice rolls associated with this Item Type * @param {object} [options] - Options which modify the getRollData method. diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 7cb51d33..8e665265 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -7,8 +7,10 @@ import { ActionField } from '../fields/actionField.mjs'; import DHCharacterSettings from '../../applications/sheets-configs/character-settings.mjs'; export default class DhCharacter extends BaseDataActor { + /**@override */ static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Character']; + /**@inheritdoc */ static get metadata() { return foundry.utils.mergeObject(super.metadata, { label: 'TYPES.Actor.character', @@ -18,6 +20,7 @@ export default class DhCharacter extends BaseDataActor { }); } + /**@inheritdoc */ static defineSchema() { const fields = foundry.data.fields; @@ -303,6 +306,8 @@ export default class DhCharacter extends BaseDataActor { }; } + /* -------------------------------------------- */ + get tier() { const currentLevel = this.levelData.level.current; return currentLevel === 1 diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs index 3d00661f..7a11f1d1 100644 --- a/module/data/actor/companion.mjs +++ b/module/data/actor/companion.mjs @@ -9,6 +9,7 @@ import { resourceField, bonusField } from '../fields/actorField.mjs'; export default class DhCompanion extends BaseDataActor { static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Companion']; + /**@inheritdoc */ static get metadata() { return foundry.utils.mergeObject(super.metadata, { label: 'TYPES.Actor.companion', @@ -18,6 +19,7 @@ export default class DhCompanion extends BaseDataActor { }); } + /**@inheritdoc */ static defineSchema() { const fields = foundry.data.fields; @@ -87,6 +89,13 @@ export default class DhCompanion extends BaseDataActor { }; } + /* -------------------------------------------- */ + + /**@inheritdoc */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/actors/capybara.svg'; + + /* -------------------------------------------- */ + get proficiency() { return this.partner?.system?.proficiency ?? 1; } diff --git a/module/data/actor/environment.mjs b/module/data/actor/environment.mjs index e9a484b3..adb7dabc 100644 --- a/module/data/actor/environment.mjs +++ b/module/data/actor/environment.mjs @@ -3,8 +3,10 @@ import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayFie import DHEnvironmentSettings from '../../applications/sheets-configs/environment-settings.mjs'; export default class DhEnvironment extends BaseDataActor { + /**@override */ static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Environment']; + /**@inheritdoc */ static get metadata() { return foundry.utils.mergeObject(super.metadata, { label: 'TYPES.Actor.environment', @@ -14,6 +16,7 @@ export default class DhEnvironment extends BaseDataActor { }); } + /**@inheritdoc */ static defineSchema() { const fields = foundry.data.fields; return { @@ -37,6 +40,13 @@ export default class DhEnvironment extends BaseDataActor { }; } + /* -------------------------------------------- */ + + /**@inheritdoc */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/actors/forest.svg'; + + /* -------------------------------------------- */ + get features() { return this.parent.items.filter(x => x.type === 'feature'); } diff --git a/module/data/item/ancestry.mjs b/module/data/item/ancestry.mjs index ecffcb1b..6abdd334 100644 --- a/module/data/item/ancestry.mjs +++ b/module/data/item/ancestry.mjs @@ -19,10 +19,26 @@ export default class DHAncestry extends BaseDataItem { }; } + + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/family-tree.svg'; + + /* -------------------------------------------- */ + + /** + * Gets the primary feature. + * @type {foundry.documents.Item|null} Returns the item of the first feature with type "primary" or null if none is found. + */ get primaryFeature() { return this.features.find(x => x.type === CONFIG.DH.ITEM.featureSubTypes.primary)?.item; } + /** + * Gets the secondary feature. + * @type {foundry.documents.Item|null} Returns the item of the first feature with type "secondary" or null if none is found. + */ get secondaryFeature() { return this.features.find(x => x.type === CONFIG.DH.ITEM.featureSubTypes.secondary)?.item; } diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs index e8a6e35b..3aefc86f 100644 --- a/module/data/item/armor.mjs +++ b/module/data/item/armor.mjs @@ -42,12 +42,20 @@ export default class DHArmor extends AttachableItem { }; } + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/chest-armor.svg'; + + /* -------------------------------------------- */ + get customActions() { return this.actions.filter( action => !this.armorFeatures.some(feature => feature.actionIds.includes(action.id)) ); } + /**@inheritdoc */ async _preUpdate(changes, options, user) { const allowed = await super._preUpdate(changes, options, user); if (allowed === false) return false; @@ -68,7 +76,7 @@ export default class DHArmor extends AttachableItem { return acc; }, {}); - for (var feature of added) { + for (const feature of added) { const featureData = armorFeatures[feature.value]; if (featureData.effects?.length > 0) { const embeddedItems = await this.parent.createEmbeddedDocuments( diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index 1f55e878..4203f5cc 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -79,6 +79,16 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { return schema; } + /* -------------------------------------------- */ + + /** + * The default icon used for newly created Item documents + * @type {string} + */ + static DEFAULT_ICON = null; + + /* -------------------------------------------- */ + /** * Convenient access to the item's actor, if it exists. * @returns {foundry.documents.Actor | null} diff --git a/module/data/item/beastform.mjs b/module/data/item/beastform.mjs index d17fbf82..4ebcfade 100644 --- a/module/data/item/beastform.mjs +++ b/module/data/item/beastform.mjs @@ -81,6 +81,13 @@ export default class DHBeastform extends BaseDataItem { }; } + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/wolf-head.svg'; + + /* -------------------------------------------- */ + async _preCreate() { if (!this.actor) return; diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs index 72f58b8b..45e8b4ab 100644 --- a/module/data/item/class.mjs +++ b/module/data/item/class.mjs @@ -53,6 +53,13 @@ export default class DHClass extends BaseDataItem { }; } + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/laurel-crown.svg'; + + /* -------------------------------------------- */ + get hopeFeatures() { return this.features.filter(x => x.type === CONFIG.DH.ITEM.featureSubTypes.hope).map(x => x.item); } diff --git a/module/data/item/community.mjs b/module/data/item/community.mjs index b2827242..a8000144 100644 --- a/module/data/item/community.mjs +++ b/module/data/item/community.mjs @@ -13,10 +13,15 @@ export default class DHCommunity extends BaseDataItem { /** @inheritDoc */ static defineSchema() { - const fields = foundry.data.fields; return { ...super.defineSchema(), features: new ForeignDocumentUUIDArrayField({ type: 'Item' }) }; } + + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/village.svg'; + } diff --git a/module/data/item/consumable.mjs b/module/data/item/consumable.mjs index cd192dfe..dad6a95c 100644 --- a/module/data/item/consumable.mjs +++ b/module/data/item/consumable.mjs @@ -22,4 +22,10 @@ export default class DHConsumable extends BaseDataItem { consumeOnUse: new fields.BooleanField({ initial: false }) }; } + + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/round-potion.svg'; + } diff --git a/module/data/item/domainCard.mjs b/module/data/item/domainCard.mjs index 1dd89023..8d050158 100644 --- a/module/data/item/domainCard.mjs +++ b/module/data/item/domainCard.mjs @@ -33,6 +33,13 @@ export default class DHDomainCard extends BaseDataItem { }; } + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/card-play.svg'; + + /* -------------------------------------------- */ + /**@inheritdoc */ async _preCreate(data, options, user) { const allowed = await super._preCreate(data, options, user); diff --git a/module/data/item/feature.mjs b/module/data/item/feature.mjs index 53e4d2d6..1ca32660 100644 --- a/module/data/item/feature.mjs +++ b/module/data/item/feature.mjs @@ -13,6 +13,13 @@ export default class DHFeature extends BaseDataItem { }); } + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/stars-stack.svg'; + + /* -------------------------------------------- */ + /** @inheritDoc */ static defineSchema() { const fields = foundry.data.fields; diff --git a/module/data/item/loot.mjs b/module/data/item/loot.mjs index 2a23d338..cdb0855e 100644 --- a/module/data/item/loot.mjs +++ b/module/data/item/loot.mjs @@ -19,4 +19,11 @@ export default class DHLoot extends BaseDataItem { ...super.defineSchema() }; } + + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/open-treasure-chest.svg'; + + /* -------------------------------------------- */ } diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index 0a6685ab..735adb27 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -28,6 +28,13 @@ export default class DHSubclass extends BaseDataItem { }; } + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/laurels.svg'; + + /* -------------------------------------------- */ + get foundationFeatures() { return this.features.filter(x => x.type === CONFIG.DH.ITEM.featureSubTypes.foundation).map(x => x.item); } diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index aab5a895..c0d88c2c 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -80,6 +80,13 @@ export default class DHWeapon extends AttachableItem { }; } + /* -------------------------------------------- */ + + /**@override */ + static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/items/battered-axe.svg'; + + /* -------------------------------------------- */ + get actionsList() { return [this.attack, ...this.actions]; } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 156e9f31..ce9ffc89 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -22,6 +22,23 @@ export default class DhpActor extends Actor { return this.system.metadata.isNPC; } + /* -------------------------------------------- */ + + /**@inheritdoc */ + static getDefaultArtwork(actorData) { + const { type } = actorData; + const Model = CONFIG.Actor.dataModels[type]; + const img = Model.DEFAULT_ICON ?? this.DEFAULT_ICON; + return { + img, + texture: { + src: img + } + }; + } + + /* -------------------------------------------- */ + /** @inheritDoc */ getEmbeddedDocument(embeddedName, id, options) { let doc; @@ -39,6 +56,7 @@ export default class DhpActor extends Actor { return doc; } + /**@inheritdoc */ async _preCreate(data, options, user) { if ((await super._preCreate(data, options, user)) === false) return false; @@ -455,6 +473,7 @@ export default class DhpActor extends Actor { return ActiveEffect.implementation.create(effect, { parent: this, keepId: true }); } + /**@inheritdoc */ getRollData() { const rollData = super.getRollData(); rollData.system = this.system.getRollData(); @@ -540,8 +559,8 @@ export default class DhpActor extends Actor { updates.forEach( u => - (u.value = - u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false ? u.value * -1 : u.value) + (u.value = + u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false ? u.value * -1 : u.value) ); await this.modifyResource(updates); @@ -587,9 +606,9 @@ export default class DhpActor extends Actor { updates.forEach( u => - (u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) - ? u.value * -1 - : u.value) + (u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false) + ? u.value * -1 + : u.value) ); await this.modifyResource(updates); diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 5c7f7dfc..96d4596b 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -74,8 +74,8 @@ export default class DHItem extends foundry.documents.Item { isInventoryItem === true ? 'Inventory Items' //TODO localize : isInventoryItem === false - ? 'Character Items' //TODO localize - : 'Other'; //TODO localize + ? 'Character Items' //TODO localize + : 'Other'; //TODO localize return { value: type, label, group }; } @@ -118,6 +118,19 @@ export default class DHItem extends foundry.documents.Item { return labels; } + /* -------------------------------------------- */ + + /**@inheritdoc */ + static getDefaultArtwork(itemData) { + const { type } = itemData; + const Model = CONFIG.Item.dataModels[type]; + const img = Model.DEFAULT_ICON ?? this.DEFAULT_ICON; + return { img }; + } + + /* -------------------------------------------- */ + + async use(event) { const actions = new Set(this.system.actionsList); if (actions?.size) { @@ -139,10 +152,10 @@ export default class DHItem extends foundry.documents.Item { this.type === 'ancestry' ? game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.ancestryTitle') : this.type === 'community' - ? game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.communityTitle') - : this.type === 'feature' - ? game.i18n.localize('TYPES.Item.feature') - : game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.subclassFeatureTitle'), + ? game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.communityTitle') + : this.type === 'feature' + ? game.i18n.localize('TYPES.Item.feature') + : game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.subclassFeatureTitle'), origin: origin, img: this.img, item: {