From 350268d9e031494e3df6e3befb21d55500f260d1 Mon Sep 17 00:00:00 2001 From: Jeff Hitchcock Date: Thu, 23 Feb 2023 10:50:19 -0800 Subject: [PATCH] [#342] Add race type --- lang/en.json | 3 ++ module/applications/actor/character-sheet.mjs | 9 +++- module/data/item/_module.mjs | 3 ++ module/data/item/race.mjs | 20 +++++++++ module/documents/advancement/advancement.mjs | 2 +- module/documents/advancement/item-choice.mjs | 2 +- template.json | 7 ++- templates/actors/character-sheet.hbs | 10 ++++- templates/advancement/item-choice-config.hbs | 4 +- templates/items/race.hbs | 43 +++++++++++++++++++ 10 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 module/data/item/race.mjs create mode 100644 templates/items/race.hbs diff --git a/lang/en.json b/lang/en.json index c1bd7db910..8bdba9d8f6 100644 --- a/lang/en.json +++ b/lang/en.json @@ -32,6 +32,8 @@ "ITEM.TypeFeaturePl": "Features", "ITEM.TypeLoot": "Loot", "ITEM.TypeLootPl": "Loot", +"ITEM.TypeRace": "Race", +"ITEM.TypeRacePl": "Races", "ITEM.TypeSpell": "Spell", "ITEM.TypeSpellPl": "Spells", "ITEM.TypeSubclass": "Subclass", @@ -866,6 +868,7 @@ "DND5E.PropertyTotal": "Total", "DND5E.Quantity": "Quantity", "DND5E.Race": "Race", +"DND5E.RaceName": "Race Name", "DND5E.RacialTraits": "Racial Traits", "DND5E.Range": "Range", "DND5E.RangeDistance": "Distance", diff --git a/module/applications/actor/character-sheet.mjs b/module/applications/actor/character-sheet.mjs index 6c6a76da9f..cacba81dd8 100644 --- a/module/applications/actor/character-sheet.mjs +++ b/module/applications/actor/character-sheet.mjs @@ -55,7 +55,7 @@ export default class ActorSheet5eCharacter extends ActorSheet5e { } // Partition items by category - let {items, spells, feats, backgrounds, classes, subclasses} = context.items.reduce((obj, item) => { + let {items, spells, feats, races, backgrounds, classes, subclasses} = context.items.reduce((obj, item) => { const {quantity, uses, recharge, target} = item.system; // Item details @@ -89,12 +89,13 @@ export default class ActorSheet5eCharacter extends ActorSheet5e { // Classify items into types if ( item.type === "spell" ) obj.spells.push(item); else if ( item.type === "feat" ) obj.feats.push(item); + else if ( item.type === "race" ) obj.races.push(item); else if ( item.type === "background" ) obj.backgrounds.push(item); else if ( item.type === "class" ) obj.classes.push(item); else if ( item.type === "subclass" ) obj.subclasses.push(item); else if ( Object.keys(inventory).includes(item.type) ) obj.items.push(item); return obj; - }, { items: [], spells: [], feats: [], backgrounds: [], classes: [], subclasses: [] }); + }, { items: [], spells: [], feats: [], races: [], backgrounds: [], classes: [], subclasses: [] }); // Apply active item filters items = this._filterItems(items, this._filters.inventory); @@ -140,6 +141,9 @@ export default class ActorSheet5eCharacter extends ActorSheet5e { // Organize Features const features = { + race: { + label: "ITEM.TypeRace", items: races, + hasActions: false, dataset: {type: "race"} }, background: { label: CONFIG.Item.typeLabels.background, items: backgrounds, hasActions: false, dataset: {type: "background"} }, @@ -164,6 +168,7 @@ export default class ActorSheet5eCharacter extends ActorSheet5e { context.spellbook = spellbook; context.preparedSpells = nPrepared; context.features = Object.values(features); + context.labels.race = races[0]?.name; context.labels.background = backgrounds[0]?.name; } diff --git a/module/data/item/_module.mjs b/module/data/item/_module.mjs index 1d6f7dbce5..d84473a44e 100644 --- a/module/data/item/_module.mjs +++ b/module/data/item/_module.mjs @@ -5,6 +5,7 @@ import ContainerData from "./container.mjs"; import EquipmentData from "./equipment.mjs"; import FeatData from "./feat.mjs"; import LootData from "./loot.mjs"; +import RaceData from "./race.mjs"; import SpellData from "./spell.mjs"; import SubclassData from "./subclass.mjs"; import ToolData from "./tool.mjs"; @@ -18,6 +19,7 @@ export { EquipmentData, FeatData, LootData, + RaceData, SpellData, SubclassData, ToolData, @@ -38,6 +40,7 @@ export const config = { equipment: EquipmentData, feat: FeatData, loot: LootData, + race: RaceData, spell: SpellData, subclass: SubclassData, tool: ToolData, diff --git a/module/data/item/race.mjs b/module/data/item/race.mjs new file mode 100644 index 0000000000..77b8da78ad --- /dev/null +++ b/module/data/item/race.mjs @@ -0,0 +1,20 @@ +import SystemDataModel from "../abstract.mjs"; +import { AdvancementField, IdentifierField } from "../fields.mjs"; +import ItemDescriptionTemplate from "./templates/item-description.mjs"; + +/** + * Data definition for Race items. + * @mixes ItemDescriptionTemplate + * + * @property {string} identifier Identifier slug for this race. + * @property {object[]} advancement Advancement objects for this race. + */ +export default class RaceData extends SystemDataModel.mixin(ItemDescriptionTemplate) { + /** @inheritdoc */ + static defineSchema() { + return this.mergeSchema(super.defineSchema(), { + identifier: new IdentifierField({required: true, label: "DND5E.Identifier"}), + advancement: new foundry.data.fields.ArrayField(new AdvancementField(), {label: "DND5E.AdvancementTitle"}) + }); + } +} diff --git a/module/documents/advancement/advancement.mjs b/module/documents/advancement/advancement.mjs index 44a304aea2..843b91cf62 100644 --- a/module/documents/advancement/advancement.mjs +++ b/module/documents/advancement/advancement.mjs @@ -81,7 +81,7 @@ export default class Advancement extends BaseAdvancement { title: game.i18n.localize("DND5E.AdvancementTitle"), hint: "", multiLevel: false, - validItemTypes: new Set(["background", "class", "subclass"]), + validItemTypes: new Set(["background", "class", "race", "subclass"]), apps: { config: AdvancementConfig, flow: AdvancementFlow diff --git a/module/documents/advancement/item-choice.mjs b/module/documents/advancement/item-choice.mjs index 5d0755462f..01514bd354 100644 --- a/module/documents/advancement/item-choice.mjs +++ b/module/documents/advancement/item-choice.mjs @@ -33,7 +33,7 @@ export default class ItemChoiceAdvancement extends ItemGrantAdvancement { /** @inheritdoc */ get levels() { - return Array.from(Object.keys(this.configuration.choices)); + return Array.from(Object.keys(this.configuration.choices).map(l => Number(l))); } /* -------------------------------------------- */ diff --git a/template.json b/template.json index 12117d6059..bc3663be75 100644 --- a/template.json +++ b/template.json @@ -502,7 +502,7 @@ } }, "Item": { - "types": ["weapon", "equipment", "consumable", "tool", "loot", "background", "class", "subclass", "spell", "feat", "backpack"], + "types": ["weapon", "equipment", "consumable", "tool", "loot", "race", "background", "class", "subclass", "spell", "feat", "backpack"], "templates": { "itemDescription": { "description": { @@ -676,6 +676,11 @@ "proficient": null, "bonus": "" }, + "race": { + "templates": ["itemDescription"], + "identifier": "", + "advancement": [] + }, "spell": { "templates": ["itemDescription", "activatedEffect", "action"], "level": 1, diff --git a/templates/actors/character-sheet.hbs b/templates/actors/character-sheet.hbs index 6748753a81..0a787494c3 100644 --- a/templates/actors/character-sheet.hbs +++ b/templates/actors/character-sheet.hbs @@ -32,13 +32,19 @@ {{!-- Character Summary --}}