diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index 64f48d02..f34555dd 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -25,6 +25,10 @@ export default class AdversarySheet extends DHBaseActorSheet { }; static PARTS = { + limited: { + template: 'systems/daggerheart/templates/sheets/actors/adversary/limited.hbs', + scrollable: ['.limited-container'] + }, sidebar: { template: 'systems/daggerheart/templates/sheets/actors/adversary/sidebar.hbs', scrollable: ['.shortcut-items-section'] @@ -52,6 +56,18 @@ export default class AdversarySheet extends DHBaseActorSheet { } }; + /** @inheritdoc */ + _initializeApplicationOptions(options) { + const applicationOptions = super._initializeApplicationOptions(options); + + if (applicationOptions.document.testUserPermission(game.user, 'LIMITED', { exact: true })) { + applicationOptions.position.width = 360; + applicationOptions.position.height = 'auto'; + } + + return applicationOptions; + } + /**@inheritdoc */ async _prepareContext(options) { const context = await super._prepareContext(options); @@ -65,6 +81,7 @@ export default class AdversarySheet extends DHBaseActorSheet { context = await super._preparePartContext(partId, context, options); switch (partId) { case 'header': + case 'limited': await this._prepareHeaderContext(context, options); const adversaryTypes = CONFIG.DH.ACTOR.allAdversaryTypes(); diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 82c258e1..b9859a01 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -76,6 +76,11 @@ export default class CharacterSheet extends DHBaseActorSheet { /**@override */ static PARTS = { + limited: { + id: 'limited', + scrollable: ['.limited-container'], + template: 'systems/daggerheart/templates/sheets/actors/character/limited.hbs' + }, sidebar: { id: 'sidebar', scrollable: ['.shortcut-items-section'], @@ -141,23 +146,37 @@ export default class CharacterSheet extends DHBaseActorSheet { }); } + /** @inheritdoc */ + _initializeApplicationOptions(options) { + const applicationOptions = super._initializeApplicationOptions(options); + + if (applicationOptions.document.testUserPermission(game.user, 'LIMITED', { exact: true })) { + applicationOptions.position.width = 360; + applicationOptions.position.height = 'auto'; + } + + return applicationOptions; + } + /** @inheritDoc */ async _onRender(context, options) { await super._onRender(context, options); - this.element - .querySelector('.level-value') - ?.addEventListener('change', event => this.document.updateLevel(Number(event.currentTarget.value))); + if (!this.document.testUserPermission(game.user, 'LIMITED', { exact: true })) { + this.element + .querySelector('.level-value') + ?.addEventListener('change', event => this.document.updateLevel(Number(event.currentTarget.value))); - const observer = this.document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER, { - exact: true - }); - if (observer) { - this.element.querySelector('.window-content').classList.add('viewMode'); + const observer = this.document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER, { + exact: true + }); + if (observer) { + this.element.querySelector('.window-content').classList.add('viewMode'); + } + + this._createFilterMenus(); + this._createSearchFilter(); } - - this._createFilterMenus(); - this._createSearchFilter(); } /* -------------------------------------------- */ diff --git a/module/applications/sheets/actors/companion.mjs b/module/applications/sheets/actors/companion.mjs index b353adbb..fd8cddbf 100644 --- a/module/applications/sheets/actors/companion.mjs +++ b/module/applications/sheets/actors/companion.mjs @@ -14,6 +14,10 @@ export default class DhCompanionSheet extends DHBaseActorSheet { }; static PARTS = { + limited: { + template: 'systems/daggerheart/templates/sheets/actors/companion/limited.hbs', + scrollable: ['.limited-container'] + }, header: { template: 'systems/daggerheart/templates/sheets/actors/companion/header.hbs' }, details: { template: 'systems/daggerheart/templates/sheets/actors/companion/details.hbs' }, effects: { diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index 0389d2c9..abf5dec0 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -26,6 +26,10 @@ export default class DhpEnvironment extends DHBaseActorSheet { /**@override */ static PARTS = { + limited: { + template: 'systems/daggerheart/templates/sheets/actors/environment/limited.hbs', + scrollable: ['.limited-container'] + }, header: { template: 'systems/daggerheart/templates/sheets/actors/environment/header.hbs' }, features: { template: 'systems/daggerheart/templates/sheets/actors/environment/features.hbs', @@ -47,6 +51,18 @@ export default class DhpEnvironment extends DHBaseActorSheet { } }; + /** @inheritdoc */ + _initializeApplicationOptions(options) { + const applicationOptions = super._initializeApplicationOptions(options); + + if (applicationOptions.document.testUserPermission(game.user, 'LIMITED', { exact: true })) { + applicationOptions.position.width = 360; + applicationOptions.position.height = 'auto'; + } + + return applicationOptions; + } + /**@inheritdoc */ async _preparePartContext(partId, context, options) { context = await super._preparePartContext(partId, context, options); diff --git a/module/applications/sheets/api/base-actor.mjs b/module/applications/sheets/api/base-actor.mjs index 930edf86..273a3c67 100644 --- a/module/applications/sheets/api/base-actor.mjs +++ b/module/applications/sheets/api/base-actor.mjs @@ -47,6 +47,12 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { return (this.#settingSheet ??= SheetClass ? new SheetClass({ document: this.document }) : null); } + get isVisible() { + const viewPermission = this.document.testUserPermission(game.user, this.options.viewPermission); + const limitedOnly = this.document.testUserPermission(game.user, this.options.viewPermission, { exact: true }); + return limitedOnly ? this.document.system.metadata.hasLimitedView : viewPermission; + } + /* -------------------------------------------- */ /* Prepare Context */ /* -------------------------------------------- */ @@ -72,6 +78,31 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { return context; } + _configureRenderParts(options) { + const parts = super._configureRenderParts(options); + if (!this.document.system.metadata.hasLimitedView) return parts; + + if (this.document.testUserPermission(game.user, 'LIMITED', { exact: true })) return { limited: parts.limited }; + + return Object.keys(parts).reduce((acc, key) => { + if (key !== 'limited') acc[key] = parts[key]; + + return acc; + }, {}); + } + + /** @inheritDoc */ + async _onRender(context, options) { + await super._onRender(context, options); + + if ( + this.document.system.metadata.hasLimitedView && + this.document.testUserPermission(game.user, 'LIMITED', { exact: true }) + ) { + this.element.classList = `${this.element.classList} limited`; + } + } + /**@inheritdoc */ _attachPartListeners(partId, htmlElement, options) { super._attachPartListeners(partId, htmlElement, options); diff --git a/module/data/actor/base.mjs b/module/data/actor/base.mjs index 9653cd6d..772a5af3 100644 --- a/module/data/actor/base.mjs +++ b/module/data/actor/base.mjs @@ -40,7 +40,8 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel { isNPC: true, settingSheet: null, hasResistances: true, - hasAttribution: false + hasAttribution: false, + hasLimitedView: true }; } diff --git a/styles/less/sheets/actors/actor-sheet-shared.less b/styles/less/sheets/actors/actor-sheet-shared.less index 4a7d6404..f3cf74b0 100644 --- a/styles/less/sheets/actors/actor-sheet-shared.less +++ b/styles/less/sheets/actors/actor-sheet-shared.less @@ -1,3 +1,22 @@ +@import '../../utils/fonts.less'; +@import '../../utils/colors.less'; +@import '../../utils/mixin.less'; + +.appTheme({ + .limited-container { + .domains-section img { + filter: @golden-filter; + } + } +}, { + .limited-container { + + .domains-section img { + filter: brightness(0) saturate(100%); + } + } +}); + .application.sheet.daggerheart.actor.dh-style { .portrait img, .profile { @@ -17,4 +36,192 @@ font-family: @font-body; color: light-dark(@chat-blue-bg, @beige-50); } + + &.limited { + &.character, + &.adversary, + &.environment, + &.companion { + .window-content { + display: unset; + padding-bottom: 20px; + background-image: url('../assets/parchments/dh-parchment-dark.png'); + } + + .limited-container { + width: 100%; + padding-top: var(--header-height); + display: flex; + flex-direction: column; + gap: 8px; + + header { + position: relative; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + top: -36px; + margin-bottom: -30px; + + .profile { + width: 100%; + max-height: 275px; + max-width: fit-content; + mask-image: linear-gradient(0deg, transparent 0%, black 10%); + } + + .title-name { + text-align: start; + font-size: var(--font-size-28); + color: light-dark(@dark-blue, @golden); + text-align: center; + } + } + + .character-details { + display: flex; + flex-direction: column; + gap: 5px; + + .basic-info, + .multiclass { + text-align: center; + padding: 0 10px; + } + } + + .domain-details, + .bio-details, + .partner-details { + margin-top: 10px; + + .domain-header, + .bio-header, + .partner-header { + display: flex; + align-items: center; + padding: 0 10px; + gap: 10px; + + h3 { + font-size: var(--font-size-20); + } + } + + .items-list { + padding: 0 20px; + } + + .partner-placeholder { + display: flex; + opacity: 0.6; + text-align: center; + font-style: italic; + justify-content: center; + padding: 10px 0; + } + + .domains-section { + position: relative; + display: flex; + gap: 10px; + background-color: light-dark(transparent, @dark-blue); + color: light-dark(@dark-blue, @golden); + padding: 5px 10px; + border: 1px solid light-dark(@dark-blue, @golden); + border-radius: 6px; + align-items: center; + width: fit-content; + height: 30px; + place-self: center; + margin-top: 10px; + + h4 { + font-size: var(--font-size-14); + font-weight: bold; + text-transform: uppercase; + color: light-dark(@dark-blue, @golden); + } + + .domain { + display: flex; + align-items: center; + gap: 5px; + + .label { + font-size: var(--font-size-14); + font-weight: bold; + text-transform: uppercase; + color: light-dark(@dark-blue, @golden); + } + + img { + height: 20px; + width: 20px; + } + } + } + + .bio-list { + display: flex; + gap: 20px; + flex-wrap: wrap; + justify-content: center; + margin-top: 10px; + + .bio-info { + display: flex; + flex-direction: column; + align-items: center; + padding: 10px; + border-radius: 5px; + min-width: 90px; + color: light-dark(@dark-blue, @golden); + background-color: light-dark(@dark-blue-10, @golden-40); + } + } + } + + .level-details { + align-self: center; + } + + .description { + font-style: italic; + text-align: center; + padding: 0 20px; + } + + .tags { + display: flex; + gap: 10px; + padding-bottom: 10px; + justify-content: center; + + .tag { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 3px 5px; + font-size: var(--font-size-12); + font: @font-body; + + background: light-dark(@dark-15, @beige-15); + border: 1px solid light-dark(@dark, @beige); + border-radius: 3px; + } + + .label { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + font-size: var(--font-size-12); + } + } + } + } + } } diff --git a/templates/sheets/actors/adversary/limited.hbs b/templates/sheets/actors/adversary/limited.hbs new file mode 100644 index 00000000..a9c53185 --- /dev/null +++ b/templates/sheets/actors/adversary/limited.hbs @@ -0,0 +1,23 @@ +
+
+ {{document.name}} +

{{document.name}}

+
+
+
+ + {{localize (concat 'DAGGERHEART.GENERAL.Tiers.' source.system.tier)}} + +
+
+ {{adversaryType}} +
+ {{#if (eq source.system.type 'horde')}} +
+ {{source.system.hordeHp}} + /{{localize "DAGGERHEART.GENERAL.HitPoints.short"}} +
+ {{/if}} +
+
{{{document.system.description}}}
+
\ No newline at end of file diff --git a/templates/sheets/actors/character/limited.hbs b/templates/sheets/actors/character/limited.hbs new file mode 100644 index 00000000..ecf7e7b6 --- /dev/null +++ b/templates/sheets/actors/character/limited.hbs @@ -0,0 +1,97 @@ +
+
+ {{document.name}} +

{{document.name}}

+
+
+
+ {{#if document.system.class.value}} + {{document.system.class.value.name}} + {{else}} + {{localize 'TYPES.Item.class'}} + {{/if}} + + {{#if document.system.class.subclass}} + {{document.system.class.subclass.name}} + {{else}} + {{localize 'TYPES.Item.subclass'}} + {{/if}} + + {{#if document.system.community}} + {{document.system.community.name}} + {{else}} + {{localize 'TYPES.Item.community'}} + {{/if}} + + {{#if document.system.ancestry}} + {{document.system.ancestry.name}} + {{else}} + {{localize 'TYPES.Item.ancestry'}} + {{/if}} +
+ + {{#if document.system.multiclass.value}} +
+ {{#if document.system.multiclass.value}} + {{document.system.multiclass.value.name}} + {{else}} + {{localize 'DAGGERHEART.GENERAL.multiclass'}} + {{/if}} + + {{#if document.system.multiclass.subclass}} + {{document.system.multiclass.subclass.name}} + {{else}} + {{localize 'TYPES.Item.subclass'}} + {{/if}} +
+ {{/if}} +
+

+ {{localize 'DAGGERHEART.GENERAL.level'}} + {{document.system.levelData.level.changed}} +

+
+
+ +

{{localize "DAGGERHEART.GENERAL.Domain.plural"}}

+ +
+ {{#if document.system.class.value}} +
+ {{#each document.system.domainData as |data|}} +
+ + {{data.label}} +
+ {{/each}} +
+ {{/if}} +
+
+
+ +

{{localize "DAGGERHEART.GENERAL.Tabs.biography"}}

+ +
+
+ {{#if source.system.biography.characteristics.pronouns}} +
+ {{localize 'DAGGERHEART.ACTORS.Character.pronouns'}} + {{source.system.biography.characteristics.pronouns}} +
+ {{/if}} + {{#if source.system.biography.characteristics.age}} +
+ {{localize 'DAGGERHEART.ACTORS.Character.age'}} + {{source.system.biography.characteristics.age}} +
+ {{/if}} + {{#if source.system.biography.characteristics.faith}} +
+ {{localize 'DAGGERHEART.ACTORS.Character.faith'}} + {{source.system.biography.characteristics.faith}} +
+ {{/if}} +
+
+
\ No newline at end of file diff --git a/templates/sheets/actors/companion/limited.hbs b/templates/sheets/actors/companion/limited.hbs new file mode 100644 index 00000000..363b5bd7 --- /dev/null +++ b/templates/sheets/actors/companion/limited.hbs @@ -0,0 +1,31 @@ +
+
+ {{document.name}} +

{{document.name}}

+
+

+ {{localize 'DAGGERHEART.GENERAL.level'}} + {{document.system.levelData.level.changed}} +

+
+
+ +

{{localize "DAGGERHEART.GENERAL.partner"}}

+ +
+ {{#if document.system.partner}} + + {{else}} + {{localize "DAGGERHEART.ACTORS.Companion.noPartner"}} + {{/if}} +
+
\ No newline at end of file diff --git a/templates/sheets/actors/environment/limited.hbs b/templates/sheets/actors/environment/limited.hbs new file mode 100644 index 00000000..87cc5174 --- /dev/null +++ b/templates/sheets/actors/environment/limited.hbs @@ -0,0 +1,21 @@ +
+
+ {{document.name}} +

{{document.name}}

+
+
+
+ + {{localize (concat 'DAGGERHEART.GENERAL.Tiers.' source.system.tier)}} + +
+ {{#if source.system.type}} +
+ + {{localize (concat 'DAGGERHEART.CONFIG.EnvironmentType.' source.system.type '.label')}} + +
+ {{/if}} +
+
{{{document.system.description}}}
+
\ No newline at end of file