From 02f0ecc9dd5b6e3763d71d6db91abb5fdad31c40 Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 16 Nov 2025 16:56:54 +0100 Subject: [PATCH] implements last standalone tab --- .../sheets/character-standalone/health.mjs | 111 ++++++++++++++ src/module/sheets/characterSheet.mjs | 2 + .../organisms/character-tabs/_health.scss | 141 ++++++++++++++++++ .../actor/character/standalone/health.hbs | 138 +++++++++++++++++ 4 files changed, 392 insertions(+) create mode 100644 src/module/sheets/character-standalone/health.mjs create mode 100644 src/templates/actor/character/standalone/health.hbs diff --git a/src/module/sheets/character-standalone/health.mjs b/src/module/sheets/character-standalone/health.mjs new file mode 100644 index 00000000..6d4157df --- /dev/null +++ b/src/module/sheets/character-standalone/health.mjs @@ -0,0 +1,111 @@ +const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api +const {ActorSheetV2} = foundry.applications.sheets + +export class StandaloneHealth extends HandlebarsApplicationMixin(ActorSheetV2) { + + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + position: {width: 520, height: 716}, + classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'health'], + tag: 'form', + actions: { + openEmbeddedDocument: StandaloneHealth.#openEmbeddedDocument, + setWounds: StandaloneHealth.#setWounds, + + } + } + + /** @inheritDoc */ + static PARTS = { + form: { + template: `systems/DSA_4-1/templates/actor/character/standalone/health.hbs` + } + } + + _actor = null + + constructor(actor) { + super(actor) + this._actor = actor + this.render(true) + } + + static async #openEmbeddedDocument(event, target) { + this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target) + } + + static async #setWounds(event, target) { + this._actor?.sheet.options.actions.setWounds.bind(this)(event, target) + } + + _configureRenderOptions(options) { + super._configureRenderOptions(options) + + options.window.title = `${this.document.name}: Gesundheit` + + return options + } + + async _prepareContext(context, options, object) { + const actorData = this.document + context.system = actorData.system + context.flags = actorData.flags + context.derived = this.document.system + context.originalName = actorData.name + context.name = context.derived.name ?? actorData.name + context.effects = actorData.effects ?? [] + + const findEquipmentOnSlot = (slot, setNumber, object) => { + return object.items.get(object.system.heldenausruestung[setNumber]?.[slot]) + } + + context.inidice = actorData.system.ini.wuerfel + context.inivalue = actorData.system.ini.aktuell + context.inimod = actorData.system.ini.mod + + context.zonenruestung = game.settings.get("DSA_4-1", "optional_ruestungzonen") + context.trefferzonen = game.settings.get("DSA_4-1", "optional_trefferzonen") + context.ausdauer = game.settings.get("DSA_4-1", "optional_ausdauer") + context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice') + + context.aupper = Math.min((actorData.system.aup.aktuell / actorData.system.aup.max) * 100, 100) + context.lepper = Math.min((actorData.system.lep.aktuell / actorData.system.lep.max) * 100, 100) + context.keper = Math.min((actorData.system.kap.aktuell / actorData.system.kap.max) * 100, 100) + context.aspper = Math.min((actorData.system.asp.aktuell / actorData.system.asp.max) * 100, 100) + + context.lepcurrent = actorData.system.lep.aktuell ?? 0 + context.aupcurrent = actorData.system.aup.aktuell ?? 0 + context.aspcurrent = actorData.system.asp.aktuell ?? 0 + context.kapcurrent = actorData.system.kap.aktuell ?? 0 + + context.maxWounds = actorData.system.wunden.max ?? 3 + context.wounds = actorData.system.wunden.aktuell ?? 0 + context.woundsFilled = [] + for (let i = 1; i <= context.maxWounds; i++) { + context.woundsFilled[i] = i <= context.wounds + } + + context.withErschoepfung = game.settings.get("DSA_4-1", "optional_erschoepfung") + context.ueberanstrengung = actorData.system.ueberanstrengung + context.erschoepfung = actorData.system.erschoepfung.aktuell + context.maxErschoepfung = actorData.system.erschoepfung.max + + context.erschoepfungFilled = [] + for (let i = 1; i <= context.maxErschoepfung; i++) { + context.erschoepfungFilled[i] = i <= context.erschoepfung + } + + + context.effects = [] + for (let i = 0; i < actorData.appliedEffects.length; i++) { + const item = actorData.appliedEffects[i] + context.effects.push(item.name) + } + + return context + + } + + _onRender(context, options) { + } +} \ No newline at end of file diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 73e94338..46331c88 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -21,6 +21,7 @@ import {StandaloneSkills} from "./character-standalone/skills.mjs"; import {Bagpack} from "./character-standalone/bagpack.mjs"; import {StandaloneSpells} from "./character-standalone/spells.mjs"; import {StandaloneLiturgies} from "./character-standalone/liturgies.mjs"; +import {StandaloneHealth} from "./character-standalone/health.mjs"; const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api const {ActorSheetV2} = foundry.applications.sheets @@ -67,6 +68,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) { openBagpack: CharacterSheet.#openBagpack, openStandaloneSpells: CharacterSheet.#openStandaloneSpells, openStandaloneLiturgies: CharacterSheet.#openStandaloneLiturgies, + openStandaloneHealth: CharacterSheet.#openStandaloneHealth, setWounds: CharacterSheet.#setWounds, } diff --git a/src/style/organisms/character-tabs/_health.scss b/src/style/organisms/character-tabs/_health.scss index a8fb173d..52769dbe 100644 --- a/src/style/organisms/character-tabs/_health.scss +++ b/src/style/organisms/character-tabs/_health.scss @@ -254,4 +254,145 @@ } +} + +.mini-health { + @include tab; + + display: flex; + flex-direction: column; + padding: 0; + + input { + height: 26px !important; + text-align: center !important; + padding: 0 !important; + margin: 0 !important; + width: 28px !important; + } + + .side-by-side { + display: flex; + + > * { + flex: 1; + } + } + + .paperdoll { + + div { + position: relative; + + .wound { + position: absolute; + width: 32px; + height: 32px; + border-radius: 16px; + border: 1px solid black; + background-color: rgba(0, 0, 0, 0.5); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); + line-height: 32px; + vertical-align: middle; + text-align: center; + color: red; + + + &.armlinks { + top: 146px; + left: 210px; + } + + &.armrechts { + top: 146px; + left: 60px; + } + + &.beinlinks { + top: 346px; + left: 210px; + } + + &.beinrechts { + top: 346px; + left: 60px; + } + + &.bauch { + top: 166px; + left: 136px; + } + + &.kopf { + top: 6px; + left: 136px + } + + &.brust { + top: 86px; + left: 110px; + } + + &.ruecken { + top: 86px; + left: 160px; + } + + } + + .armor { + position: absolute; + width: 32px; + height: 32px; + border-radius: 0 0 16px 16px; + line-height: 32px; + vertical-align: middle; + text-align: center; + border: 1px solid silver; + background-color: rgba(0, 0, 0, 0.5); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); + color: silver; + + &.armlinks { + top: 180px; + left: 210px; + } + + &.armrechts { + top: 180px; + left: 60px; + } + + &.beinlinks { + top: 380px; + left: 210px; + } + + &.beinrechts { + top: 380px; + left: 60px; + } + + &.bauch { + top: 200px; + left: 136px; + } + + &.kopf { + top: 40px; + left: 136px + } + + &.ruecken { + top: 120px; + left: 160px; + } + + &.brust { + top: 120px; + left: 110px; + } + } + } + } } \ No newline at end of file diff --git a/src/templates/actor/character/standalone/health.hbs b/src/templates/actor/character/standalone/health.hbs new file mode 100644 index 00000000..e259fc5f --- /dev/null +++ b/src/templates/actor/character/standalone/health.hbs @@ -0,0 +1,138 @@ +
+
+ +
+ + + w6 + +
+
+ + + von + +
+ {{#if ausdauer}} +
+ + + von + +
+ {{/if}} + {{#if (not zonenruestung)}} +
+ + {{derived.rs}} +
+ {{/if}} +
+ + {{derived.be}} +
+
+ + {{derived.gs.aktuell}} +
+ + +
+ {{#if (not trefferzonen)}} +
+ + {{#each this.woundsFilled}} + {{#if this}} +
{{@index}}
+ {{else}} +
{{@index}}
+ {{/if}} + {{/each}} +
+ {{/if}} + + {{#if withErschoepfung}} +
+ + {{#each this.erschoepfungFilled}} + {{#if this}} +
{{@index}}
+ {{else}} +
{{@index}}
+ {{/if}} + {{/each}} + + {{#if (gt this.ueberanstrengung 0)}} +
{{system.erschoepfung.aktuell}}
+ {{else}} +
+ {{/if}} +
+ {{/if}} + + {{#if (or trefferzonen zonenruestung)}} +
+ {{/if}} + +
+ +
    + {{#each effects}} +
  • {{this}}
  • + {{/each}} +
+
+ + {{#if (or trefferzonen zonenruestung)}} +
+

{{#if (and trefferzonen zonenruestung)}}Trefferzonen{{/if}}{{#if + (and trefferzonen (not zonenruestung))}}Wunden{{/if}}{{#if + (and (not trefferzonen) zonenruestung)}}Rüstung{{/if}}

+
+ + + + {{#if trefferzonen}} + {{derived.wunden.kopf}} + {{derived.wunden.brust}} + {{derived.wunden.armlinks}} + {{derived.wunden.armrechts}} + {{derived.wunden.ruecken}} + {{derived.wunden.bauch}} + {{derived.wunden.beinlinks}} + {{derived.wunden.beinrechts}} + {{/if}} + {{#if zonenruestung}} + {{derived.rs.kopf}} + {{derived.rs.brust}} + {{derived.rs.armlinks}} + {{derived.rs.armrechts}} + {{derived.rs.ruecken}} + {{derived.rs.bauch}} + {{derived.rs.beinlinks}} + {{derived.rs.beinrechts}} + {{/if}} +
+
+ {{/if}} + + {{#if (or trefferzonen zonenruestung)}} +
+ {{/if}} +