diff --git a/css/fvtt-oath-hammer.css b/css/fvtt-oath-hammer.css index 991892a..bbd0e60 100644 --- a/css/fvtt-oath-hammer.css +++ b/css/fvtt-oath-hammer.css @@ -238,12 +238,71 @@ width: 4rem; text-align: center; } +.oathhammer .identity-lineage-class { + gap: 8px; + margin-bottom: 8px; +} +.oathhammer .identity-lineage-class .item-slot { + flex: 1; + display: flex; + align-items: center; + gap: 6px; + padding: 6px 8px; + border: 2px solid #c8a84b; + border-radius: 4px; + background: rgba(212, 160, 23, 0.08); + min-height: 40px; +} +.oathhammer .identity-lineage-class .item-slot.empty { + border-style: dashed; + opacity: 0.7; + cursor: default; +} +.oathhammer .identity-lineage-class .item-slot.empty .slot-icon { + font-size: 1.2rem; + color: #c8a84b; +} +.oathhammer .identity-lineage-class .item-slot.empty .slot-placeholder { + font-family: "Calibri", "Segoe UI", sans-serif; + font-style: italic; + color: #c8a84b; + font-size: 0.9rem; +} +.oathhammer .identity-lineage-class .item-slot .item-img { + width: 32px; + height: 32px; + -o-object-fit: contain; + object-fit: contain; + border: none; + flex-shrink: 0; +} +.oathhammer .identity-lineage-class .item-slot .item-name { + flex: 1; + font-family: "Sherwood", "Palatino Linotype", serif; + font-size: 1rem; + color: #2a1a0a; +} +.oathhammer .identity-lineage-class .item-slot a[data-action] { + color: #c8a84b; +} +.oathhammer .identity-lineage-class .item-slot a[data-action]:hover { + color: #084a74; +} .oathhammer .biodata-col { flex: 1; display: flex; flex-direction: column; gap: 2px; } +.oathhammer .character-arcane-stress .flexrow { + align-items: center; + gap: 4px; +} +.oathhammer .character-arcane-stress input { + min-width: 3rem; + max-width: 3rem; + text-align: center; +} .oathhammer .defense-display { min-width: 3rem; max-width: 3rem; diff --git a/lang/en.json b/lang/en.json index 9cb5d3b..5a44233 100644 --- a/lang/en.json +++ b/lang/en.json @@ -12,7 +12,9 @@ "MagicItem": "Oath Hammer Magic Item Sheet", "Ability": "Oath Hammer Ability Sheet", "Oath": "Oath Hammer Oath Sheet", - "Condition": "Oath Hammer Condition Sheet" + "Condition": "Oath Hammer Condition Sheet", + "Lineage": "Oath Hammer Lineage Sheet", + "Class": "Oath Hammer Class Sheet" }, "Tab": { "Identity": "Identity", @@ -64,7 +66,21 @@ "Halfling": "Halfling", "HighElf": "High Elf", "Human": "Human", - "WoodElf": "Wood Elf" + "WoodElf": "Wood Elf", + "FIELDS": { + "description": { + "label": "Description" + }, + "traits": { + "label": "Traits" + }, + "movement": { + "label": "Movement (ft)" + }, + "gritModifier": { + "label": "Grit Modifier" + } + } }, "Class": { "Berserker": "Berserker", @@ -76,7 +92,21 @@ "Scout": "Scout", "Soldier": "Soldier", "Spellblade": "Spellblade", - "Troubadour": "Troubadour" + "Troubadour": "Troubadour", + "FIELDS": { + "description": { + "label": "Description" + }, + "features": { + "label": "Features" + }, + "armorProficiency": { + "label": "Armor Proficiency" + }, + "weaponProficiency": { + "label": "Weapon Proficiency" + } + } }, "Tradition": { "Elemental": "Elemental", @@ -212,7 +242,11 @@ "Bane": "Bane", "Skill": "Skill", "SkillRank": "Rank", - "TotalDice": "Total Dice" + "TotalDice": "Total Dice", + "DropLineage": "Drop Lineage Here", + "DropClass": "Drop Class Here", + "Traits": "Traits", + "Features": "Features" }, "NewItem": { "Weapon": "New Weapon", @@ -232,8 +266,12 @@ "luck": { "label": "Luck", "fields": { - "value": { "label": "Luck" }, - "max": { "label": "Luck Max" } + "value": { + "label": "Luck" + }, + "max": { + "label": "Luck Max" + } } }, "arcaneStress": { @@ -250,32 +288,34 @@ }, "biodata": { "label": "Background", - "lineage": { - "label": "Lineage" - }, - "class": { - "label": "Class" - }, - "age": { - "label": "Age" - }, - "gender": { - "label": "Gender" - }, - "height": { - "label": "Height" - }, - "weight": { - "label": "Weight" - }, - "eyes": { - "label": "Eye Color" - }, - "hair": { - "label": "Hair Color" - }, - "alignment": { - "label": "Alignment" + "fields": { + "lineage": { + "label": "Lineage" + }, + "class": { + "label": "Class" + }, + "age": { + "label": "Age" + }, + "gender": { + "label": "Gender" + }, + "height": { + "label": "Height" + }, + "weight": { + "label": "Weight" + }, + "eyes": { + "label": "Eye Color" + }, + "hair": { + "label": "Hair Color" + }, + "alignment": { + "label": "Alignment" + } } }, "currency": { @@ -717,7 +757,9 @@ "magic_item": "Magic Item", "magic-item": "Magic Item", "ability": "Ability", - "oath": "Oath" + "oath": "Oath", + "lineage": "Lineage", + "class": "Class" }, "Actor": { "character": "Character", diff --git a/less/actor-sheet.less b/less/actor-sheet.less index 5fcbe4d..a9e1212 100644 --- a/less/actor-sheet.less +++ b/less/actor-sheet.less @@ -123,6 +123,61 @@ } } + // Lineage / Class item slots in Identity tab + .identity-lineage-class { + gap: 8px; + margin-bottom: 8px; + + .item-slot { + flex: 1; + display: flex; + align-items: center; + gap: 6px; + padding: 6px 8px; + border: 2px solid @color-gold; + border-radius: 4px; + background: rgba(212, 160, 23, 0.08); + min-height: 40px; + + &.empty { + border-style: dashed; + opacity: 0.7; + cursor: default; + + .slot-icon { + font-size: 1.2rem; + color: @color-gold; + } + .slot-placeholder { + font-family: @font-body; + font-style: italic; + color: @color-gold; + font-size: 0.9rem; + } + } + + .item-img { + width: 32px; + height: 32px; + object-fit: contain; + border: none; + flex-shrink: 0; + } + + .item-name { + flex: 1; + font-family: @font-primary; + font-size: 1rem; + color: @color-dark; + } + + a[data-action] { + color: @color-gold; + &:hover { color: @color-blue; } + } + } + } + // Biodata .biodata-col { flex: 1; @@ -131,6 +186,19 @@ gap: 2px; } + // Arcane Stress narrow inputs + .character-arcane-stress { + .flexrow { + align-items: center; + gap: 4px; + } + input { + min-width: 3rem; + max-width: 3rem; + text-align: center; + } + } + // Defense display .defense-display { min-width: 3rem; diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs index b3d44c4..cf89d84 100644 --- a/module/applications/_module.mjs +++ b/module/applications/_module.mjs @@ -9,3 +9,5 @@ export { default as OathHammerMiracleSheet } from "./sheets/miracle-sheet.mjs" export { default as OathHammerMagicItemSheet } from "./sheets/magic-item-sheet.mjs" export { default as OathHammerAbilitySheet } from "./sheets/ability-sheet.mjs" export { default as OathHammerOathSheet } from "./sheets/oath-sheet.mjs" +export { default as OathHammerLineageSheet } from "./sheets/lineage-sheet.mjs" +export { default as OathHammerClassSheet } from "./sheets/class-sheet.mjs" diff --git a/module/applications/sheets/base-actor-sheet.mjs b/module/applications/sheets/base-actor-sheet.mjs index 6146980..d5187e6 100644 --- a/module/applications/sheets/base-actor-sheet.mjs +++ b/module/applications/sheets/base-actor-sheet.mjs @@ -95,6 +95,13 @@ export default class OathHammerActorSheet extends HandlebarsApplicationMixin(fou async _onDropItem(item) { const itemData = item.toObject() + // Lineage and class are unique: replace any existing item of the same type + if (item.type === "lineage" || item.type === "class") { + const existing = this.document.itemTypes[item.type] + if (existing.length > 0) { + await this.document.deleteEmbeddedDocuments("Item", existing.map(i => i.id)) + } + } await this.document.createEmbeddedDocuments("Item", [itemData], { renderSheet: false }) } diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs index 287fa5b..1ca3c47 100644 --- a/module/applications/sheets/character-sheet.mjs +++ b/module/applications/sheets/character-sheet.mjs @@ -68,6 +68,8 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet { break case "identity": context.tab = context.tabs.identity + context.lineage = doc.itemTypes.lineage?.[0] ?? null + context.characterClass = doc.itemTypes["class"]?.[0] ?? null context.abilities = doc.itemTypes.ability context.oaths = doc.itemTypes.oath break @@ -124,7 +126,7 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet { } async _onDrop(event) { - if (!this.isEditable || !this.isEditMode) return + if (!this.isEditable) return const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event) if (data.type === "Item") { const item = await fromUuid(data.uuid) diff --git a/module/applications/sheets/class-sheet.mjs b/module/applications/sheets/class-sheet.mjs new file mode 100644 index 0000000..3f9ffd2 --- /dev/null +++ b/module/applications/sheets/class-sheet.mjs @@ -0,0 +1,30 @@ +import OathHammerItemSheet from "./base-item-sheet.mjs" + +export default class OathHammerClassSheet extends OathHammerItemSheet { + /** @override */ + static DEFAULT_OPTIONS = { + classes: ["class"], + position: { + width: 640, + }, + window: { + contentClasses: ["class-content"], + }, + } + + /** @override */ + static PARTS = { + main: { + template: "systems/fvtt-oath-hammer/templates/item/class-sheet.hbs", + }, + } + + /** @override */ + async _prepareContext() { + const context = await super._prepareContext() + context.enrichedFeatures = await foundry.applications.ux.TextEditor.implementation.enrichHTML( + this.document.system.features ?? "", { async: true } + ) + return context + } +} diff --git a/module/applications/sheets/lineage-sheet.mjs b/module/applications/sheets/lineage-sheet.mjs new file mode 100644 index 0000000..a17043c --- /dev/null +++ b/module/applications/sheets/lineage-sheet.mjs @@ -0,0 +1,30 @@ +import OathHammerItemSheet from "./base-item-sheet.mjs" + +export default class OathHammerLineageSheet extends OathHammerItemSheet { + /** @override */ + static DEFAULT_OPTIONS = { + classes: ["lineage"], + position: { + width: 640, + }, + window: { + contentClasses: ["lineage-content"], + }, + } + + /** @override */ + static PARTS = { + main: { + template: "systems/fvtt-oath-hammer/templates/item/lineage-sheet.hbs", + }, + } + + /** @override */ + async _prepareContext() { + const context = await super._prepareContext() + context.enrichedTraits = await foundry.applications.ux.TextEditor.implementation.enrichHTML( + this.document.system.traits ?? "", { async: true } + ) + return context + } +} diff --git a/module/models/_module.mjs b/module/models/_module.mjs index f18dab7..500bb88 100644 --- a/module/models/_module.mjs +++ b/module/models/_module.mjs @@ -9,3 +9,5 @@ export { default as OathHammerMiracle } from "./miracle.mjs" export { default as OathHammerMagicItem } from "./magic-item.mjs" export { default as OathHammerAbility } from "./ability.mjs" export { default as OathHammerOath } from "./oath.mjs" +export { default as OathHammerLineage } from "./lineage.mjs" +export { default as OathHammerClass } from "./class.mjs" diff --git a/module/models/character.mjs b/module/models/character.mjs index de1bc75..aa79368 100644 --- a/module/models/character.mjs +++ b/module/models/character.mjs @@ -1,4 +1,3 @@ -import { SYSTEM } from "../config/system.mjs" export default class OathHammerCharacter extends foundry.abstract.TypeDataModel { static defineSchema() { @@ -88,8 +87,6 @@ export default class OathHammerCharacter extends foundry.abstract.TypeDataModel }) schema.biodata = new fields.SchemaField({ - lineage: new fields.StringField({ required: true, initial: "dwarf", choices: SYSTEM.LINEAGE_CHOICES }), - class: new fields.StringField({ required: true, initial: "soldier", choices: SYSTEM.CLASS_CHOICES }), age: new fields.StringField({ required: true, nullable: false, initial: "" }), gender: new fields.StringField({ required: true, nullable: false, initial: "" }), height: new fields.StringField({ required: true, nullable: false, initial: "" }), diff --git a/module/models/class.mjs b/module/models/class.mjs new file mode 100644 index 0000000..e7a16e2 --- /dev/null +++ b/module/models/class.mjs @@ -0,0 +1,21 @@ +export default class OathHammerClass extends foundry.abstract.TypeDataModel { + static defineSchema() { + const fields = foundry.data.fields + const schema = {} + + schema.description = new fields.HTMLField({ required: true, textSearch: true }) + + // Class features, starting abilities, advancement options (rich text) + schema.features = new fields.HTMLField({ required: true, textSearch: true }) + + // Armor proficiencies (e.g. "Light, Medium, Heavy") + schema.armorProficiency = new fields.StringField({ required: true, nullable: false, initial: "" }) + + // Weapon proficiencies (e.g. "Common, Dueling, Heavy, Throwing") + schema.weaponProficiency = new fields.StringField({ required: true, nullable: false, initial: "" }) + + return schema + } + + static LOCALIZATION_PREFIXES = ["OATHHAMMER.Class"] +} diff --git a/module/models/lineage.mjs b/module/models/lineage.mjs new file mode 100644 index 0000000..ecc5002 --- /dev/null +++ b/module/models/lineage.mjs @@ -0,0 +1,21 @@ +export default class OathHammerLineage extends foundry.abstract.TypeDataModel { + static defineSchema() { + const fields = foundry.data.fields + const schema = {} + + schema.description = new fields.HTMLField({ required: true, textSearch: true }) + + // Racial traits and special abilities (rich text) + schema.traits = new fields.HTMLField({ required: true, textSearch: true }) + + // Base movement speed in feet + schema.movement = new fields.NumberField({ required: true, nullable: false, integer: true, initial: 30, min: 0 }) + + // Modifier to max Grit Points (e.g. -1 for High Elf, Wood Elf) + schema.gritModifier = new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0 }) + + return schema + } + + static LOCALIZATION_PREFIXES = ["OATHHAMMER.Lineage"] +} diff --git a/oath-hammer.mjs b/oath-hammer.mjs index b16ae4d..74a235b 100644 --- a/oath-hammer.mjs +++ b/oath-hammer.mjs @@ -31,7 +31,9 @@ Hooks.once("init", function () { miracle: models.OathHammerMiracle, "magic-item": models.OathHammerMagicItem, ability: models.OathHammerAbility, - oath: models.OathHammerOath + oath: models.OathHammerOath, + lineage: models.OathHammerLineage, + "class": models.OathHammerClass } foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet) @@ -56,6 +58,8 @@ Hooks.once("init", function () { foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerMagicItemSheet, { types: ["magic-item"], makeDefault: true, label: "OATHHAMMER.Sheet.MagicItem" }) foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerAbilitySheet, { types: ["ability"], makeDefault: true, label: "OATHHAMMER.Sheet.Ability" }) foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerOathSheet, { types: ["oath"], makeDefault: true, label: "OATHHAMMER.Sheet.Oath" }) + foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerLineageSheet, { types: ["lineage"], makeDefault: true, label: "OATHHAMMER.Sheet.Lineage" }) + foundry.documents.collections.Items.registerSheet("fvtt-oath-hammer", applications.OathHammerClassSheet, { types: ["class"], makeDefault: true, label: "OATHHAMMER.Sheet.Class" }) CONFIG.statusEffects = STATUS_EFFECTS diff --git a/system.json b/system.json index 9e7cbbc..495d693 100644 --- a/system.json +++ b/system.json @@ -3,35 +3,122 @@ "title": "Oath Hammer RPG", "description": "Oath Hammer RPG System for FoundryVTT", "version": "13.0.0", - "compatibility": { "minimum": "13", "verified": "13" }, - "esmodules": ["oath-hammer.mjs"], - "styles": ["css/fvtt-oath-hammer.css"], - "languages": [{ "lang": "en", "name": "English", "path": "lang/en.json" }], + "compatibility": { + "minimum": "13", + "verified": "13" + }, + "esmodules": [ + "oath-hammer.mjs" + ], + "styles": [ + "css/fvtt-oath-hammer.css" + ], + "languages": [ + { + "lang": "en", + "name": "English", + "path": "lang/en.json" + } + ], "documentTypes": { "Actor": { - "character": { "htmlFields": ["description", "notes"] }, - "npc": { "htmlFields": ["description", "notes"] } + "character": { + "htmlFields": [ + "description", + "notes" + ] + }, + "npc": { + "htmlFields": [ + "description", + "notes" + ] + } }, "Item": { - "weapon": { "htmlFields": ["description", "magicEffect"] }, - "armor": { "htmlFields": ["description", "magicEffect"] }, - "ammunition": { "htmlFields": ["description"] }, - "equipment": { "htmlFields": ["description"] }, - "spell": { "htmlFields": ["effect"] }, - "miracle": { "htmlFields": ["effect"] }, - "magic-item": { "htmlFields": ["effect"] }, - "ability": { "htmlFields": ["description"] }, - "oath": { "htmlFields": ["tenet", "boon", "bane"] } + "weapon": { + "htmlFields": [ + "description", + "magicEffect" + ] + }, + "armor": { + "htmlFields": [ + "description", + "magicEffect" + ] + }, + "ammunition": { + "htmlFields": [ + "description" + ] + }, + "equipment": { + "htmlFields": [ + "description" + ] + }, + "spell": { + "htmlFields": [ + "effect" + ] + }, + "miracle": { + "htmlFields": [ + "effect" + ] + }, + "magic-item": { + "htmlFields": [ + "effect" + ] + }, + "ability": { + "htmlFields": [ + "description" + ] + }, + "oath": { + "htmlFields": [ + "tenet", + "boon", + "bane" + ] + }, + "lineage": { + "htmlFields": [ + "description", + "traits" + ] + }, + "class": { + "htmlFields": [ + "description", + "features" + ] + } } }, - "grid": { "distance": 5, "units": "ft" }, + "grid": { + "distance": 5, + "units": "ft" + }, "primaryTokenAttribute": "grit", "socket": true, "background": "systems/fvtt-oath-hammer/assets/ui/oath_hammer_paper.webp", "flags": { "hotReload": { - "extensions": ["css", "hbs", "json"], - "paths": ["css/", "lang/", "assets/", "templates/"] + "extensions": [ + "css", + "hbs", + "json" + ], + "paths": [ + "css/", + "lang/", + "assets/", + "templates/" + ] } } -} +} \ No newline at end of file diff --git a/templates/actor/character-combat.hbs b/templates/actor/character-combat.hbs index 8b1d674..8cd8ed6 100644 --- a/templates/actor/character-combat.hbs +++ b/templates/actor/character-combat.hbs @@ -1,4 +1,4 @@ -
+
{{localize "OATHHAMMER.Label.Defense"}}
diff --git a/templates/actor/character-equipment.hbs b/templates/actor/character-equipment.hbs index 0d96421..0d45e3d 100644 --- a/templates/actor/character-equipment.hbs +++ b/templates/actor/character-equipment.hbs @@ -1,4 +1,4 @@ -
+
{{localize "OATHHAMMER.Label.Equipment"}} {{#unless isPlayMode}}{{/unless}} diff --git a/templates/actor/character-identity.hbs b/templates/actor/character-identity.hbs index 58ce2e7..31284bc 100644 --- a/templates/actor/character-identity.hbs +++ b/templates/actor/character-identity.hbs @@ -1,10 +1,36 @@ -
+
+
+
+ {{#if lineage}} + + {{lineage.name}} + {{#unless ../isPlayMode}} + + + {{/unless}} + {{else}} + + {{localize "OATHHAMMER.Label.DropLineage"}} + {{/if}} +
+
+ {{#if characterClass}} + + {{characterClass.name}} + {{#unless ../isPlayMode}} + + + {{/unless}} + {{else}} + + {{localize "OATHHAMMER.Label.DropClass"}} + {{/if}} +
+
{{localize "OATHHAMMER.Label.Biodata"}}
- {{formField systemFields.biodata.fields.lineage value=system.biodata.lineage name="system.biodata.lineage" localize=true disabled=isPlayMode}} - {{formField systemFields.biodata.fields.class value=system.biodata.class name="system.biodata.class" localize=true disabled=isPlayMode}} {{formField systemFields.biodata.fields.alignment value=system.biodata.alignment name="system.biodata.alignment" disabled=isPlayMode}} {{formField systemFields.biodata.fields.age value=system.biodata.age name="system.biodata.age" disabled=isPlayMode}} {{formField systemFields.biodata.fields.gender value=system.biodata.gender name="system.biodata.gender" disabled=isPlayMode}} diff --git a/templates/actor/character-magic.hbs b/templates/actor/character-magic.hbs index 1727f53..f37751a 100644 --- a/templates/actor/character-magic.hbs +++ b/templates/actor/character-magic.hbs @@ -1,11 +1,9 @@ -
+
{{localize "OATHHAMMER.Label.ArcaneStress"}}
- {{formInput systemFields.arcaneStress.fields.value value=system.arcaneStress.value name="system.arcaneStress.value" disabled=isPlayMode}} - / - {{formInput systemFields.arcaneStress.fields.threshold value=system.arcaneStress.threshold name="system.arcaneStress.threshold" disabled=isPlayMode}} + {{system.arcaneStress.value}} / {{system.arcaneStress.threshold}}
diff --git a/templates/actor/character-notes.hbs b/templates/actor/character-notes.hbs index f792826..ad18886 100644 --- a/templates/actor/character-notes.hbs +++ b/templates/actor/character-notes.hbs @@ -1,4 +1,4 @@ -
+
{{localize "OATHHAMMER.Label.Description"}} {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}} diff --git a/templates/actor/character-skills.hbs b/templates/actor/character-skills.hbs index aad1c88..2c9ae2e 100644 --- a/templates/actor/character-skills.hbs +++ b/templates/actor/character-skills.hbs @@ -1,4 +1,4 @@ -
+
{{#each skillGroups as |group|}}
diff --git a/templates/item/class-sheet.hbs b/templates/item/class-sheet.hbs new file mode 100644 index 0000000..f029f1a --- /dev/null +++ b/templates/item/class-sheet.hbs @@ -0,0 +1,22 @@ +
+
+ + {{formInput fields.name value=source.name}} +
+
+
+ {{formField systemFields.armorProficiency value=system.armorProficiency name="system.armorProficiency"}} +
+
+ {{formField systemFields.weaponProficiency value=system.weaponProficiency name="system.weaponProficiency"}} +
+
+
+ {{localize "OATHHAMMER.Label.Description"}} + {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}} +
+
+ {{localize "OATHHAMMER.Label.Features"}} + {{formInput systemFields.features enriched=enrichedFeatures value=system.features name="system.features" toggled=true}} +
+
diff --git a/templates/item/lineage-sheet.hbs b/templates/item/lineage-sheet.hbs new file mode 100644 index 0000000..6c4b451 --- /dev/null +++ b/templates/item/lineage-sheet.hbs @@ -0,0 +1,22 @@ +
+
+ + {{formInput fields.name value=source.name}} +
+
+
+ {{formField systemFields.movement value=system.movement name="system.movement"}} +
+
+ {{formField systemFields.gritModifier value=system.gritModifier name="system.gritModifier"}} +
+
+
+ {{localize "OATHHAMMER.Label.Description"}} + {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}} +
+
+ {{localize "OATHHAMMER.Label.Traits"}} + {{formInput systemFields.traits enriched=enrichedTraits value=system.traits name="system.traits" toggled=true}} +
+