From 52484bd81812e601424a998c42ba3986eaa6a1d6 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 8 Jun 2025 22:28:10 +0200 Subject: [PATCH] Fixed datamodel and set up basic template in new style --- lang/en.json | 149 +++++---- module/applications/sheets/adversary.mjs | 313 ++---------------- module/config/actorConfig.mjs | 34 +- module/config/generalConfig.mjs | 29 +- module/data/adversary.mjs | 70 ++-- styles/daggerheart.css | 6 + styles/less/global/elements.less | 8 + system.json | 16 +- templates/sheets/actors/adversary/header.hbs | 9 + .../sheets/actors/adversary/information.hbs | 17 + templates/sheets/actors/adversary/main.hbs | 57 ++++ 11 files changed, 288 insertions(+), 420 deletions(-) create mode 100644 templates/sheets/actors/adversary/header.hbs create mode 100644 templates/sheets/actors/adversary/information.hbs create mode 100644 templates/sheets/actors/adversary/main.hbs diff --git a/lang/en.json b/lang/en.json index eb5ecd62..fc7b4864 100755 --- a/lang/en.json +++ b/lang/en.json @@ -261,46 +261,54 @@ "Description": "When an effect makes a creature Restrained, it means they cannot move until this condition is cleared.\nThey can still take actions from their current position." } }, + "Tiers": { + "tier1": "Tier 1", + "tier2": "Tier 2", + "tier3": "Tier 3", + "tier4": "Tier 4" + }, "Adversary": { - "Bruiser": { - "Name": "Bruiser", - "Description": "Tough adversaries with powerful attacks." - }, - "Horde": { - "Name": "Horde", - "Description": "A Horde represents a number of foes working in a group." - }, - "Leader": { - "Name": "Leader", - "Description": "Adversaries that command and summon other adversaries." - }, - "Minion": { - "Name": "Minion", - "Description": "Basic enemies that are easily dispatched but dangerous in numbers." - }, - "Ranged": { - "Name": "Ranged", - "Description": "Adversaries that attack from a distance." - }, - "Skulker": { - "Name": "Skulker", - "Description": "Adversaries that maneuver and exploit opportunities to ambush their opponents." - }, - "Social": { - "Name": "Social", - "Description": "Adversaries that are primarily interpersonal threats or challenges." - }, - "Solo": { - "Name": "Solo", - "Description": "Designed to present a challenge to a whole party." - }, - "Standard": { - "Name": "Standard", - "Description": "Rank and File adversaries." - }, - "Support": { - "Name": "Support", - "Description": "Enemies that enhance their allies and/or disrupt their opponents." + "Type": { + "Bruiser": { + "label": "Bruiser", + "Description": "Tough adversaries with powerful attacks." + }, + "Horde": { + "label": "Horde", + "Description": "A Horde represents a number of foes working in a group." + }, + "Leader": { + "label": "Leader", + "Description": "Adversaries that command and summon other adversaries." + }, + "Minion": { + "label": "Minion", + "Description": "Basic enemies that are easily dispatched but dangerous in numbers." + }, + "Ranged": { + "label": "Ranged", + "Description": "Adversaries that attack from a distance." + }, + "Skulk": { + "label": "Skulk", + "Description": "Adversaries that maneuver and exploit opportunities to ambush their opponents." + }, + "Social": { + "label": "Social", + "Description": "Adversaries that are primarily interpersonal threats or challenges." + }, + "Solo": { + "label": "Solo", + "Description": "Designed to present a challenge to a whole party." + }, + "Standard": { + "label": "Standard", + "Description": "Rank and File adversaries." + }, + "Support": { + "label": "Support", + "Description": "Enemies that enhance their allies and/or disrupt their opponents." + } }, "Trait": { "Relentless": { @@ -999,35 +1007,50 @@ } }, "Adversary": { - "Description": "Description", - "MotivesAndTactics": "Motives & Tactics", - "Tier": "Tier", - "Type": "Type", - "Attack": { - "Title": "Attack", - "Modifier": "Attack Modifier", - "Name": "Name", - "Range": "Range", - "Damage": { - "Title": "Damage", - "Value": "Value", - "Type": "Type" + "FIELDS": { + "tier": { "label": "Tier" }, + "type": { "label": "Type" }, + "description": { "label": "Description" }, + "motivesAndTactics": { "label": "Motives & Tactics" }, + "difficulty": { "label": "Difficulty" }, + "damageThresholds": { + "major": { "label": "Major" }, + "severe": { "label": "Severe" } + }, + "hitPoints": { + "value": { "label": "Current" }, + "max": { "label": "Max" } + }, + "stress": { + "value": { "label": "Current" }, + "max": { "label": "Max" } + }, + "experiences": { + "element": { + "name": { "label": "Name" }, + "value": { "label": "Modifier" } + } + }, + "attack": { + "name": { "label": "Name" }, + "modifier": { "label": "Modifier" }, + "range": { "label": "Range" }, + "damage": { + "value": { "label": "Damage" }, + "type": { "label": "Damage Type" } + } } }, - "Difficulty": "Difficulty", - "Reaction": "Reaction Roll", - "DamageThresholds": { - "Title": "Damage Thresholds", - "Minor": "Minor", - "Major": "Major", - "Severe": "Severe" + "Tabs": { + "Main": "Data", + "Information": "Information" }, - "HP": "HP", + "General": "General", + "DamageThresholds": "Damage Thresholds", + "HitPoints": "Hit Points", "Stress": "Stress", - "Experience": "Experience", "Experiences": "Experiences", - "Features": "Features", - "NewFeature": "New Feature" + "Attack": "Attack" }, "Environment": { "ToneAndFeel": "Tone And feel", diff --git a/module/applications/sheets/adversary.mjs b/module/applications/sheets/adversary.mjs index b9180bf3..86ee79fc 100644 --- a/module/applications/sheets/adversary.mjs +++ b/module/applications/sheets/adversary.mjs @@ -1,219 +1,12 @@ -// import DhpApplicationMixin from '../daggerheart-sheet.mjs'; - -// export class Teest extends DhpApplicationMixin(ActorSheet) { -// static documentType = "adversary"; - -// constructor(options){ -// super(options); - -// this.editMode = false; -// } - -// /** @override */ -// static get defaultOptions() { -// return foundry.utils.mergeObject(super.defaultOptions, { -// classes: ["daggerheart", "sheet", "adversary"], -// width: 600, -// height: 'auto', -// resizable: false, -// }); -// } - -// async getData() { -// const context = super.getData(); -// context.config = SYSTEM; -// context.editMode = this.editMode; -// context.title = `${this.actor.name} - ${game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.actor.system.type].name)}`; - -// context.data = { -// description: this.object.system.description, -// motivesAndTactics: this.object.system.motivesAndTactics.join(', '), -// tier: this.object.system.tier, -// type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.object.system.type].name), -// attack: { -// name: this.object.system.attack.name, -// attackModifier: this.object.system.attackModifier, -// range: this.object.system.attack.range ? game.i18n.localize(SYSTEM.GENERAL.range[this.object.system.attack.range].name) : null, -// damage: { -// value: this.object.system.attack.damage.value, -// type: this.object.system.attack.damage.type, -// typeName: this.object.system.attack.damage.type ? game.i18n.localize(SYSTEM.GENERAL.damageTypes[this.object.system.attack.damage.type].abbreviation).toLowerCase() : null, -// }, -// }, -// damageThresholds: this.object.system.damageThresholds, -// difficulty: this.object.system.difficulty, -// hp: { ...this.object.system.resources.health, lastRowIndex: Math.floor(this.object.system.resources.health.max/5)*5 }, -// stress: { ...this.object.system.resources.stress, lastRowIndex: Math.floor(this.object.system.resources.stress.max/5)*5 }, -// moves: this.object.system.moves, -// }; - -// return context; -// } - -// async _handleAction(action, event, button) { -// switch(action){ -// case 'viewMove': -// await this.viewMove(button); -// break; -// case 'addMove': -// this.addMove(); -// break; -// case 'removeMove': -// await this.removeMove(button); -// break; -// case 'toggleSlider': -// this.toggleEditMode(); -// break; -// case 'addMotive': -// await this.addMotive(); -// break; -// case 'removeMotive': -// await this.removeMotive(button); -// break; -// case 'reactionRoll': -// await this.reactionRoll(event); -// break; -// case 'attackRoll': -// await this.attackRoll(event); -// break; -// case 'addExperience': -// await this.addExperience(); -// break; -// case 'removeExperience': -// await this.removeExperience(button); -// break; -// case 'toggleHP': -// await this.toggleHP(button); -// break; -// case 'toggleStress': -// await this.toggleStress(button); -// break; -// } -// } - -// async viewMove(button){ -// const move = await fromUuid(button.dataset.move); -// move.sheet.render(true); -// } - -// async addMove(){ -// const result = await this.object.createEmbeddedDocuments("Item", [{ -// name: game.i18n.localize('DAGGERHEART.Sheets.Adversary.NewMove'), -// type: 'feature', -// }]); - -// await result[0].sheet.render(true); -// } - -// async removeMove(button){ -// await this.object.items.find(x => x.uuid === button.dataset.move).delete(); -// } - -// toggleEditMode(){ -// this.editMode = !this.editMode; -// this.render(); -// } - -// async addMotive(){ -// await this.object.update({ "system.motivesAndTactics": [...this.object.system.motivesAndTactics, ''] }); -// } - -// async removeMotive(button){ -// await this.object.update({ "system.motivesAndTactics": this.object.system.motivesAndTactics.filter((_, index) => index !== Number.parseInt(button.dataset.motive) )}); -// } - -// async reactionRoll(event){ -// const { roll, diceResults, modifiers } = await this.actor.diceRoll({ title: `${this.actor.name} - Reaction Roll`, value: 0 }, event.shiftKey); - -// const cls = getDocumentClass("ChatMessage"); -// const msg = new cls({ -// type: 'adversaryRoll', -// system: { -// roll: roll._formula, -// total: roll._total, -// modifiers: modifiers, -// diceResults: diceResults, -// }, -// content: "systems/daggerheart/templates/chat/adversary-roll.hbs", -// rolls: [roll] -// }); - -// cls.create(msg.toObject()); -// } - -// async attackRoll(event){ -// const modifier = Number.parseInt(event.currentTarget.dataset.value); - -// const { roll, diceResults, modifiers } = await this.actor.diceRoll({ title: `${this.actor.name} - Attack Roll`, value: modifier }, event.shiftKey); - -// const targets = Array.from(game.user.targets).map(x => ({ -// id: x.id, -// name: x.actor.name, -// img: x.actor.img, -// difficulty: x.actor.system.difficulty, -// evasion: x.actor.system.evasion, -// })); - -// const cls = getDocumentClass("ChatMessage"); -// const msg = new cls({ -// type: 'adversaryRoll', -// system: { -// roll: roll._formula, -// total: roll._total, -// modifiers: modifiers, -// diceResults: diceResults, -// targets: targets, -// damage: { value: event.currentTarget.dataset.damage, type: event.currentTarget.dataset.damageType }, -// }, -// content: "systems/daggerheart/templates/chat/adversary-attack-roll.hbs", -// rolls: [roll] -// }); - -// cls.create(msg.toObject()); -// } - -// async addExperience(){ -// await this.object.update({ "system.experiences": [...this.object.system.experiences, { name: 'Experience', value: 1 }] }); -// } - -// async removeExperience(button){ -// await this.object.update({ "system.experiences": this.object.system.experiences.filter((_, index) => index !== Number.parseInt(button.dataset.experience) )}); -// } - -// async toggleHP(button){ -// const index = Number.parseInt(button.dataset.index); -// const newHP = index < this.object.system.resources.health.value ? index : index+1; -// await this.object.update({ "system.resources.health.value": newHP }); -// } - -// async toggleStress(button){ -// const index = Number.parseInt(button.dataset.index); -// const newStress = index < this.object.system.resources.stress.value ? index : index+1; -// await this.object.update({ "system.resources.stress.value": newStress }); -// } -// } - import DaggerheartSheet from './daggerheart-sheet.mjs'; const { ActorSheetV2 } = foundry.applications.sheets; export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) { - constructor(options = {}) { - super(options); - - this.editMode = false; - } - static DEFAULT_OPTIONS = { tag: 'form', - classes: ['daggerheart', 'sheet', 'adversary'], - position: { width: 600 }, + classes: ['daggerheart', 'sheet', 'actor', 'dh-style', 'adversary'], + position: { width: 450, height: 1000 }, actions: { - viewMove: this.viewMove, - addMove: this.addMove, - removeMove: this.removeMove, - toggleSlider: this.toggleEditMode, - addMotive: this.addMotive, - removeMotive: this.removeMotive, reactionRoll: this.reactionRoll, attackRoll: this.attackRoll, addExperience: this.addExperience, @@ -229,54 +22,35 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) { }; static PARTS = { - form: { - id: 'feature', - template: 'systems/daggerheart/templates/sheets/adversary.hbs' + header: { template: 'systems/daggerheart/templates/sheets/actors/adversary/header.hbs' }, + tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, + main: { template: 'systems/daggerheart/templates/sheets/actors/adversary/main.hbs' }, + information: { template: 'systems/daggerheart/templates/sheets/actors/adversary/information.hbs' } + }; + + static TABS = { + main: { + active: true, + cssClass: '', + group: 'primary', + id: 'main', + icon: null, + label: 'DAGGERHEART.Sheets.Adversary.Tabs.Main' + }, + information: { + active: false, + cssClass: '', + group: 'primary', + id: 'information', + icon: null, + label: 'DAGGERHEART.Sheets.Adversary.Tabs.Information' } }; async _prepareContext(_options) { const context = await super._prepareContext(_options); context.document = this.document; - context.config = SYSTEM; - context.editMode = this.editMode; - context.title = `${this.actor.name} - ${game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.actor.system.type].name)}`; - - context.data = { - description: this.document.system.description, - motivesAndTactics: this.document.system.motivesAndTactics.join(', '), - tier: this.document.system.tier, - type: game.i18n.localize(SYSTEM.ACTOR.adversaryTypes[this.document.system.type].name), - attack: { - name: this.document.system.attack.name, - attackModifier: this.document.system.attackModifier, - range: this.document.system.attack.range - ? game.i18n.localize(SYSTEM.GENERAL.range[this.document.system.attack.range].name) - : null, - damage: { - value: this.document.system.attack.damage.value, - type: this.document.system.attack.damage.type, - typeName: this.document.system.attack.damage.type - ? game.i18n - .localize( - SYSTEM.GENERAL.damageTypes[this.document.system.attack.damage.type].abbreviation - ) - .toLowerCase() - : null - } - }, - damageThresholds: this.document.system.damageThresholds, - difficulty: this.document.system.difficulty, - hp: { - ...this.document.system.resources.health, - lastRowIndex: Math.floor(this.document.system.resources.health.max / 5) * 5 - }, - stress: { - ...this.document.system.resources.stress, - lastRowIndex: Math.floor(this.document.system.resources.stress.max / 5) * 5 - }, - moves: this.document.system.moves - }; + context.tabs = super._getTabs(this.constructor.TABS); return context; } @@ -286,43 +60,6 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) { this.render(); } - static async viewMove(_, button) { - const move = await fromUuid(button.dataset.move); - move.sheet.render(true); - } - - static async addMove() { - const result = await this.document.createEmbeddedDocuments('Item', [ - { - name: game.i18n.localize('DAGGERHEART.Sheets.Adversary.NewMove'), - type: 'feature' - } - ]); - - await result[0].sheet.render(true); - } - - static async removeMove(_, button) { - await this.document.items.find(x => x.uuid === button.dataset.move).delete(); - } - - static toggleEditMode() { - this.editMode = !this.editMode; - this.render(); - } - - static async addMotive() { - await this.document.update({ 'system.motivesAndTactics': [...this.document.system.motivesAndTactics, ''] }); - } - - static async removeMotive(button) { - await this.document.update({ - 'system.motivesAndTactics': this.document.system.motivesAndTactics.filter( - (_, index) => index !== Number.parseInt(button.dataset.motive) - ) - }); - } - static async reactionRoll(event) { const { roll, diceResults, modifiers } = await this.actor.diceRoll( { title: `${this.actor.name} - Reaction Roll`, value: 0 }, diff --git a/module/config/actorConfig.mjs b/module/config/actorConfig.mjs index 4db5ca9c..b851cee1 100644 --- a/module/config/actorConfig.mjs +++ b/module/config/actorConfig.mjs @@ -82,43 +82,53 @@ export const featureProperties = { export const adversaryTypes = { bruiser: { - name: 'DAGGERHEART.Adversary.Bruiser.Name', + id: 'bruiser', + label: 'DAGGERHEART.Adversary.Type.Bruiser.label', description: 'DAGGERHEART.Adversary.Bruiser.Description' }, horde: { - name: 'DAGGERHEART.Adversary.Horde.Name', + id: 'horde', + label: 'DAGGERHEART.Adversary.Type.Horde.label', description: 'DAGGERHEART.Adversary.Horde.Description' }, leader: { - name: 'DAGGERHEART.Adversary.Leader.Name', + id: 'leader', + label: 'DAGGERHEART.Adversary.Type.Leader.label', description: 'DAGGERHEART.Adversary.Leader.Description' }, minion: { - name: 'DAGGERHEART.Adversary.Minion.Name', + id: 'minion', + label: 'DAGGERHEART.Adversary.Type.Minion.label', description: 'DAGGERHEART.Adversary.Minion.Description' }, ranged: { - name: 'DAGGERHEART.Adversary.Ranged.Name', + id: 'ranged', + label: 'DAGGERHEART.Adversary.Type.Ranged.label', description: 'DAGGERHEART.Adversary.Ranged.Description' }, - skulker: { - name: 'DAGGERHEART.Adversary.Skulker.Name', - description: 'DAGGERHEART.Adversary.Skulker.Description' + skulk: { + id: 'skulk', + label: 'DAGGERHEART.Adversary.Type.Skulk.label', + description: 'DAGGERHEART.Adversary.Skulk.Description' }, social: { - name: 'DAGGERHEART.Adversary.Social.Name', + id: 'social', + label: 'DAGGERHEART.Adversary.Type.Social.label', description: 'DAGGERHEART.Adversary.Social.Description' }, solo: { - name: 'DAGGERHEART.Adversary.Solo.Name', + id: 'solo', + label: 'DAGGERHEART.Adversary.Type.Solo.label', description: 'DAGGERHEART.Adversary.Solo.Description' }, standard: { - name: 'DAGGERHEART.Adversary.Standard.Name', + id: 'standard', + label: 'DAGGERHEART.Adversary.Type.Standard.label', description: 'DAGGERHEART.Adversary.Standard.Description' }, support: { - name: 'DAGGERHEART.Adversary.Support.Name', + id: 'support', + label: 'DAGGERHEART.Adversary.Type.Support.label', description: 'DAGGERHEART.Adversary.Support.Description' } }; diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index fb596347..fecb939e 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -1,25 +1,30 @@ export const range = { melee: { + id: 'melee', label: 'DAGGERHEART.Range.melee.name', description: 'DAGGERHEART.Range.melee.description', distance: 1 }, veryClose: { + id: 'veryClose', label: 'DAGGERHEART.Range.veryClose.name', description: 'DAGGERHEART.Range.veryClose.description', distance: 3 }, close: { + id: 'close', label: 'DAGGERHEART.Range.close.name', description: 'DAGGERHEART.Range.close.description', distance: 10 }, far: { + id: 'far', label: 'DAGGERHEART.Range.far.name', description: 'DAGGERHEART.Range.far.description', distance: 20 }, veryFar: { + id: 'veryFar', label: 'DAGGERHEART.Range.veryFar.name', description: 'DAGGERHEART.Range.veryFar.description', distance: 30 @@ -175,25 +180,21 @@ export const deathMoves = { }; export const tiers = { - 0: { - key: 0, - id: 'tier0', - name: 'DAGGERHEART.General.Tier.0' - }, - 1: { - key: 1, + tier1: { id: 'tier1', - name: 'DAGGERHEART.General.Tier.1' + label: 'DAGGERHEART.Tiers.tier1' }, - 2: { - key: 2, + tier2: { id: 'tier2', - name: 'DAGGERHEART.General.Tier.2' + label: 'DAGGERHEART.Tiers.tier2' }, - 3: { - key: 3, + tier3: { id: 'tier3', - name: 'DAGGERHEART.General.Tier.3' + label: 'DAGGERHEART.Tiers.tier3' + }, + tier4: { + id: 'tier4', + label: 'DAGGERHEART.Tiers.tier4' } }; diff --git a/module/data/adversary.mjs b/module/data/adversary.mjs index 3e8cdaf6..d2ac36bb 100644 --- a/module/data/adversary.mjs +++ b/module/data/adversary.mjs @@ -1,52 +1,58 @@ +const resourceField = () => + new foundry.data.fields.SchemaField({ + value: new foundry.data.fields.NumberField({ initial: 0, integer: true }), + max: new foundry.data.fields.NumberField({ initial: 0, integer: true }) + }); + export default class DhpAdversary extends foundry.abstract.TypeDataModel { + static LOCALIZATION_PREFIXES = ['DAGGERHEART.Sheets.Adversary']; + static defineSchema() { const fields = foundry.data.fields; return { - resources: new fields.SchemaField({ - health: new fields.SchemaField({ - value: new fields.NumberField({ initial: 0, integer: true }), - min: new fields.NumberField({ initial: 0, integer: true }), - max: new fields.NumberField({ initial: 0, integer: true }) - }), - stress: new fields.SchemaField({ - value: new fields.NumberField({ initial: 0, integer: true }), - min: new fields.NumberField({ initial: 0, integer: true }), - max: new fields.NumberField({ initial: 0, integer: true }) - }) + tier: new fields.StringField({ + required: true, + choices: SYSTEM.GENERAL.tiers, + initial: SYSTEM.GENERAL.tiers.tier1.id }), - tier: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.tiers), integer: false }), type: new fields.StringField({ - choices: Object.keys(SYSTEM.ACTOR.adversaryTypes), - integer: false, - initial: Object.keys(SYSTEM.ACTOR.adversaryTypes).find(x => x === 'standard') + required: true, + choices: SYSTEM.ACTOR.adversaryTypes, + initial: SYSTEM.ACTOR.adversaryTypes.standard.id }), - description: new fields.StringField({}), - motivesAndTactics: new fields.ArrayField(new fields.StringField({})), - attackModifier: new fields.NumberField({ integer: true, nullabe: true, initial: null }), + description: new fields.HTMLField(), + motivesAndTactics: new fields.HTMLField(), + difficulty: new fields.NumberField({ required: true, initial: 1, integer: true }), + damageThresholds: new fields.SchemaField({ + major: new fields.NumberField({ required: true, initial: 0, integer: true }), + severe: new fields.NumberField({ required: true, initial: 0, integer: true }) + }), + hitPoints: resourceField(), + stress: resourceField(), attack: new fields.SchemaField({ name: new fields.StringField({}), - range: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.range), integer: false }), + modifier: new fields.NumberField({ required: true, integer: true, initial: 0 }), + range: new fields.StringField({ + required: true, + choices: SYSTEM.GENERAL.range, + initial: SYSTEM.GENERAL.range.melee.id + }), damage: new fields.SchemaField({ - value: new fields.StringField({}), - type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false }) + value: new fields.StringField(), + type: new fields.StringField({ + required: true, + choices: SYSTEM.GENERAL.damageTypes, + initial: SYSTEM.GENERAL.damageTypes.physical.id + }) }) }), - difficulty: new fields.NumberField({ initial: 1, integer: true }), - damageThresholds: new fields.SchemaField({ - major: new fields.NumberField({ initial: 0, integer: true }), - severe: new fields.NumberField({ initial: 0, integer: true }) - }), experiences: new fields.TypedObjectField( new fields.SchemaField({ - id: new fields.StringField({ required: true }), name: new fields.StringField(), - value: new fields.NumberField({ integer: true, nullable: true, initial: null }) + value: new fields.NumberField({ required: true, integer: true, initial: 1 }) }) ) + /* Features waiting on pseudo-document data model addition */ }; } - - get features() { - return this.parent.items.filter(x => x.type === 'feature'); - } } diff --git a/styles/daggerheart.css b/styles/daggerheart.css index 78af5ecc..3a9a227b 100755 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -3354,6 +3354,12 @@ div.daggerheart.views.multiclass { grid-template-columns: 1fr 2fr; gap: 10px; } +.application.sheet.dh-style fieldset.two-columns.even { + grid-template-columns: 1fr 1fr; +} +.application.sheet.dh-style fieldset.two-columns .full-width { + grid-column: span 2; +} .application.sheet.dh-style fieldset legend { font-family: 'Montserrat', sans-serif; font-weight: bold; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 077d2226..797b2328 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -103,6 +103,14 @@ display: grid; grid-template-columns: 1fr 2fr; gap: 10px; + + &.even { + grid-template-columns: 1fr 1fr; + } + + .full-width { + grid-column: span 2; + } } legend { diff --git a/system.json b/system.json index f90f53c8..20069250 100644 --- a/system.json +++ b/system.json @@ -163,10 +163,7 @@ "name": "Daggerheart", "sorting": "m", "color": "#08718c", - "packs": [ - "adversaries", - "environments" - ], + "packs": ["adversaries", "environments"], "folders": [ { "name": "Character Options", @@ -186,12 +183,7 @@ "name": "Items", "sorting": "m", "color": "#000000", - "packs": [ - "weapons", - "armors", - "consumables", - "general-items" - ] + "packs": ["weapons", "armors", "consumables", "general-items"] } ] } @@ -212,7 +204,9 @@ "documentTypes": { "Actor": { "pc": {}, - "adversary": {}, + "adversary": { + "htmlFields": ["description", "motivesAndTactics"] + }, "environment": {} }, "Item": { diff --git a/templates/sheets/actors/adversary/header.hbs b/templates/sheets/actors/adversary/header.hbs new file mode 100644 index 00000000..e3914c32 --- /dev/null +++ b/templates/sheets/actors/adversary/header.hbs @@ -0,0 +1,9 @@ +
+ +
+

+
+

{{localize 'TYPES.Actor.adversary'}}

+
+
+
\ No newline at end of file diff --git a/templates/sheets/actors/adversary/information.hbs b/templates/sheets/actors/adversary/information.hbs new file mode 100644 index 00000000..6d6efb21 --- /dev/null +++ b/templates/sheets/actors/adversary/information.hbs @@ -0,0 +1,17 @@ +
+
+ {{localize "DAGGERHEART.Sheets.Adversary.Description" }} + + {{formGroup systemFields.description value=source.system.description}} +
+ +
+ {{localize "DAGGERHEART.Sheets.Adversary.MotivesAndTactics" }} + + {{formGroup systemFields.motivesAndTactics value=source.system.motivesAndTactics}} +
+
diff --git a/templates/sheets/actors/adversary/main.hbs b/templates/sheets/actors/adversary/main.hbs new file mode 100644 index 00000000..e6b664d7 --- /dev/null +++ b/templates/sheets/actors/adversary/main.hbs @@ -0,0 +1,57 @@ +
+
+ {{localize "DAGGERHEART.Sheets.Adversary.General"}} + + {{formGroup systemFields.tier value=source.system.tier localize=true}} + {{formGroup systemFields.type value=source.system.type localize=true}} +
{{formGroup systemFields.difficulty value=source.system.difficulty}}
+ +
+ {{localize "DAGGERHEART.Sheets.Adversary.DamageThresholds"}} + + {{formGroup systemFields.damageThresholds.fields.major value=source.system.damageThresholds.major}} + {{formGroup systemFields.damageThresholds.fields.severe value=source.system.damageThresholds.severe}} +
+ +
+ {{localize "DAGGERHEART.Sheets.Adversary.HitPoints"}} + + {{formGroup systemFields.hitPoints.fields.value value=source.system.hitPoints.value}} + {{formGroup systemFields.hitPoints.fields.max value=source.system.hitPoints.max}} +
+ +
+ {{localize "DAGGERHEART.Sheets.Adversary.Stress"}} + + {{formGroup systemFields.stress.fields.value value=source.system.stress.value}} + {{formGroup systemFields.stress.fields.max value=source.system.stress.max}} +
+ +
+ {{localize "DAGGERHEART.Sheets.Adversary.Experiences"}} + + {{#each source.system.experiences}} +
+ {{this.name}} + + {{formGroup @root.systemFields.experiences.element.fields.name name=(concat "system.experiences." @key ".name") value=this.name }} + {{formGroup @root.systemFields.experiences.element.fields.value name=(concat "system.experiences." @key ".value") value=this.value }} +
+ {{/each}} +
+
+ +
+ {{localize "DAGGERHEART.Sheets.Adversary.Attack"}} + +
{{formGroup systemFields.attack.fields.name value=source.system.attack.name}}
+ {{formGroup systemFields.attack.fields.modifier value=source.system.attack.modifier}} + {{formGroup systemFields.attack.fields.range value=source.system.attack.range localize=true}} + {{formGroup systemFields.attack.fields.damage.fields.value value=source.system.attack.damage.value}} + {{formGroup systemFields.attack.fields.damage.fields.type value=source.system.attack.damage.type localize=true}} +
+